summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--__init__.py16
-rw-r--r--collada_superbmd_export.py10
-rw-r--r--collada_superbmd_import.py2
-rw-r--r--obj_kcl_export.py73
-rw-r--r--obj_neokclcreate_import.py87
5 files changed, 178 insertions, 10 deletions
diff --git a/__init__.py b/__init__.py
index b360c57..5f5b5fc 100644
--- a/__init__.py
+++ b/__init__.py
@@ -19,13 +19,15 @@ from bpy.app.handlers import persistent
# custom CSV animation file (for BCK) exporter/importer
@persistent
-def set_blenxy_env(dummy): # "dummy" is a variable that is somehow
- # passed to set_blenxy_env when called by
- # bpy.app.handlers.load_post.append
- from . import required_modules # install needed modules for bundled python (awful)
- from . import basic_settings # settings blenxy has
- from . import collada_superbmd_import # "custom" importer for SuperBMD collada files
- from . import collada_superbmd_export # "custom" exporter for SuperBMD collada files
+def set_blenxy_env(dummy): # "dummy" is a variable that is somehow
+ # passed to set_blenxy_env when called by
+ # bpy.app.handlers.load_post.append
+ from . import required_modules # install needed modules for bundled python (awful)
+ from . import basic_settings # settings blenxy has
+ from . import collada_superbmd_import # "custom" importer for SuperBMD collada files
+ from . import collada_superbmd_export # "custom" exporter for SuperBMD collada files
+ from . import obj_kcl_export # "custom" exporter for OBJ files (Collision)
+ from . import obj_neokclcreate_import # "custom" importer for OBJ files (Colllision, NeoKCLCreate)
# ~ from . import csv_anim_bck_export # exporter for CSV files for BCK conversion
# ~ from . import csv_anim_bck_import # importer for CSV files from BCK animation
diff --git a/collada_superbmd_export.py b/collada_superbmd_export.py
index 5d6f83f..ad1363b 100644
--- a/collada_superbmd_export.py
+++ b/collada_superbmd_export.py
@@ -26,6 +26,8 @@ def write_bmd_bdl_collada(context, filepath, triangulate):
# get armature object
armature = scene.objects.active
print("\nArmature found: \"%s\"" % (armature.name))
+ # change to object mode
+ bpy.ops.object.mode_set(mode='OBJECT')
# check if the armature contains only mesh objects inside
for obj in armature.children:
@@ -45,11 +47,15 @@ def write_bmd_bdl_collada(context, filepath, triangulate):
bpy.ops.object.modifier_add(type = 'ARMATURE')
mesh.modifiers["Armature"].object = armature
mesh.modifiers["Armature"].use_vertex_groups = True
- else: # ensure bind is to a vertex group
+ else: # ensure bind is to a vertex group and that the bind is to the actual parent armature
if (mesh.modifiers["Armature"].use_vertex_groups == False):
blender_funcs.disp_msg("\"%s\": armature modifier wasn't binded to vertex groups"
% (mesh.name))
mesh.modifiers["Armature"].use_vertex_groups = True
+ if (mesh.modifiers["Armature"].object != armature):
+ blender_funcs.disp_msg("\"%s\": armature modifier was binded to another armature object"
+ % (mesh.name))
+ mesh.modifiers["Armature"].object = armature;
# check if all the vertex groups in each mesh correspond to the name of a skeleton bone
bone_name_list = []
@@ -140,7 +146,7 @@ class export_superbmd_collada(Operator, ExportHelper):
filter_glob = StringProperty(default = "*.dae", options = {'HIDDEN'}, maxlen = 255)
triangulate = BoolProperty(name = "Triangulate meshes",
- description = "Triangulate meshes inside armatures",
+ description = "Triangulate meshes inside the armature",
default = False)
def execute(self, context):
return write_bmd_bdl_collada(context, self.filepath, self.triangulate)
diff --git a/collada_superbmd_import.py b/collada_superbmd_import.py
index 8187fb9..39e7ce6 100644
--- a/collada_superbmd_import.py
+++ b/collada_superbmd_import.py
@@ -40,7 +40,7 @@ def import_collada_superbmd(context, filepath):
root = xml.getroot()
# texture files path
- if (os.name == "posix"):
+ if (os.name == "posix" and root.find("library_images") != None):
for image in root.find("library_images"):
tmp = image.find("init_from").text
while (tmp[0] != '\\'):
diff --git a/obj_kcl_export.py b/obj_kcl_export.py
new file mode 100644
index 0000000..b106869
--- /dev/null
+++ b/obj_kcl_export.py
@@ -0,0 +1,73 @@
+import bpy, math
+from . import blender_funcs
+
+# just a simple OBJ exporter wrapper
+# it only selects all the meshes inside an armature and sets some OBJ exporter variables
+
+# write_kcl_obj function
+# function to write custom obj file for kcl conversion
+def write_kcl_obj(context, filepath):
+
+ # this thing is always needed for stuff
+ scene = bpy.context.scene
+
+ # if nothing is selected end the exporter
+ if (scene.objects.active == None or scene.objects.active.type != 'ARMATURE'):
+ if (scene.objects.active == None):
+ blender_funcs.disp_msg("No Armature selected. Select one and try again.")
+ else:
+ blender_funcs.disp_msg("No Armature selected. Currently selecting: \"%s\""
+ % (scene.objects.active.name))
+ return {'FINISHED'}
+
+ # get armature object
+ armature = scene.objects.active
+ print("\nArmature found: \"%s\"" % (armature.name))
+ # change to object mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # check if the armature contains only mesh objects inside
+ for obj in armature.children:
+ if (obj.type != 'MESH'):
+ blender_funcs.disp_msg("\"%s\": contains non-mesh object (%s)."
+ % (armature.name, obj.name))
+ return {'FINISHED'}
+
+ # select all the meshes inside the armature
+ blender_funcs.select_obj(scene, armature, True)
+
+ # export the object
+ bpy.ops.export_scene.obj(filepath = filepath, axis_up = "Y", axis_forward = "-Z",
+ use_selection = True, use_triangles = True, global_scale = 100,
+ use_materials = True, use_normals = True)
+
+ # done!
+ blender_funcs.select_obj(scene, armature, False)
+ blender_funcs.disp_msg("Meshes from \"%s\" exported!" % (armature.name))
+ return {'FINISHED'}
+
+# Stuff down is for the menu appending
+# of the exporter to work plus some setting stuff
+# comes from a Blender importer template
+from bpy_extras.io_utils import ExportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+class export_obj_kcl(Operator, ExportHelper):
+ """Export a OBJ file for KCL conversion"""
+ bl_idname = "export_scene.obj_kcl"
+ bl_label = "Export OBJ for KCL (.OBJ)"
+ filename_ext = ".obj"
+ filter_glob = StringProperty(default = "*.obj", options = {'HIDDEN'}, maxlen = 255)
+ def execute(self, context):
+ return write_kcl_obj(context, self.filepath)
+
+# Only needed if you want to add into a dynamic menu
+def menu_export_obj_kcl(self, context):
+ self.layout.operator(export_obj_kcl.bl_idname, text="OBJ for KCL (.obj)")
+
+bpy.utils.register_class(export_obj_kcl)
+bpy.types.INFO_MT_file_export.append(menu_export_obj_kcl)
+
+# test call
+bpy.ops.export_scene.obj_kcl('INVOKE_DEFAULT')
diff --git a/obj_neokclcreate_import.py b/obj_neokclcreate_import.py
new file mode 100644
index 0000000..1b63633
--- /dev/null
+++ b/obj_neokclcreate_import.py
@@ -0,0 +1,87 @@
+import bpy, re
+from . import blender_funcs
+
+# simple OBJ importer specific for NeoKCLCreate
+
+# import_obj_neokclcreate() function
+# read superbmd/blenxy collada file
+# used to import the collada file into Blender
+def import_obj_neokclcreate(context, filepath):
+
+ # scene variable is always needed for something
+ scene = bpy.context.scene
+
+ # load the OBJ file into blender
+ bpy.ops.import_scene.obj(filepath = filepath, axis_forward = '-Z', axis_up = 'Y')
+
+ # select the single OBJ mesh and reduce its size to match blenxy's coordinate system
+ obj = None
+ for o in bpy.data.objects:
+ # selection in blender api is confusing
+ if (o.select == True):
+ obj = o
+ break
+ blender_funcs.select_obj(scene, obj, False)
+ obj.scale = obj.scale / 100
+ bpy.ops.object.transform_apply(location = True, rotation = True, scale = True)
+
+ # deal with the infinite materials (merge those that are similar)
+ # slow as a turtle, but works like a charm
+ for i in range(len(obj.material_slots)):
+ # i will not be bound to len(obj.material_slots) once a material is deleted
+ if (i >= len(obj.material_slots)):
+ break
+ mat = obj.material_slots[i]
+ cur_mat_name = re.sub("^(.*?)\| ", "", mat.name)
+ # iterate over all the mesh faces
+ for face in obj.data.polygons:
+ face_mat = obj.material_slots[face.material_index]
+ face_mat_name = re.sub("^(.*?)\| ", "", face_mat.name)
+ # material with the same name found
+ if (cur_mat_name == face_mat_name and i != face.material_index):
+ bpy.data.materials.remove(face_mat.material) # remove the material data and the slot
+ obj.active_material_index = face.material_index
+ bpy.ops.object.material_slot_remove()
+ face.material_index = i # change the index to be the material of the current loop
+
+ # put the OBJ inside an armature object
+ bpy.ops.object.armature_add()
+ obj.parent = scene.objects.active
+
+ # done!
+ blender_funcs.disp_msg("NeoKCLCreate OBJ file imported!")
+ return {'FINISHED'}
+
+
+#################################################
+# Stuff down is for the menu appending
+# of the importer to work plus some setting stuff
+# comes from a Blender importer template
+
+# ExportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ExportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+class import_neokclcreate_obj(Operator, ExportHelper):
+ """Import a Collada file from SuperBMD (SuperBMD only)"""
+ bl_idname = "import_scene.neokclcreate_obj"
+ bl_label = "Import NeoKCLCreate OBJ (.OBJ)"
+
+ # ExportHelper mixin class uses this
+ filename_ext = ".obj"
+ filter_glob = StringProperty(default = "*.obj", options = {'HIDDEN'}, maxlen = 255)
+ # execute function
+ def execute(self, context):
+ return import_obj_neokclcreate(context, self.filepath)
+
+# Only needed if you want to add into a dynamic menu
+def menu_import_neokclcreate_obj(self, context):
+ self.layout.operator(import_neokclcreate_obj.bl_idname, text="NeoKCLCreate OBJ (.obj)")
+
+bpy.utils.register_class(import_neokclcreate_obj)
+bpy.types.INFO_MT_file_import.append(menu_import_neokclcreate_obj)
+
+# test call
+bpy.ops.import_scene.neokclcreate_obj('INVOKE_DEFAULT')