From 591821c92254b03a64113c077e258d50ff20cca5 Mon Sep 17 00:00:00 2001
From: Campbell Barton <ideasman42@gmail.com>
Date: Thu, 26 May 2011 08:45:31 +0000
Subject: [PATCH] added axis settings to 3ds import/export

---
 io_scene_3ds/__init__.py   | 67 +++++++++++++++++++++++++++++++++++---
 io_scene_3ds/export_3ds.py | 31 +++++++-----------
 io_scene_3ds/import_3ds.py | 42 ++++++++++++++++++------
 io_scene_fbx/__init__.py   |  8 ++---
 io_scene_fbx/export_fbx.py | 28 ++++++++--------
 5 files changed, 124 insertions(+), 52 deletions(-)

diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py
index 4915512a7..8ade71c19 100644
--- a/io_scene_3ds/__init__.py
+++ b/io_scene_3ds/__init__.py
@@ -42,8 +42,8 @@ if "bpy" in locals():
 
 
 import bpy
-from bpy.props import StringProperty, FloatProperty, BoolProperty
-from bpy_extras.io_utils import ImportHelper, ExportHelper
+from bpy.props import StringProperty, FloatProperty, BoolProperty, EnumProperty
+from bpy_extras.io_utils import ImportHelper, ExportHelper, axis_conversion
 
 
 class Import3DS(bpy.types.Operator, ImportHelper):
@@ -58,9 +58,39 @@ class Import3DS(bpy.types.Operator, ImportHelper):
     use_image_search = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True)
     use_apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=True)
 
+    global_axis_forward = EnumProperty(
+            name="Forward",
+            items=(('X', "X Forward", ""),
+                   ('Y', "Y Forward", ""),
+                   ('Z', "Z Forward", ""),
+                   ('-X', "-X Forward", ""),
+                   ('-Y', "-Y Forward", ""),
+                   ('-Z', "-Z Forward", ""),
+                   ),
+            default='Y',
+            )
+
+    global_axis_up = EnumProperty(
+            name="Up",
+            items=(('X', "X Up", ""),
+                   ('Y', "Y Up", ""),
+                   ('Z', "Z Up", ""),
+                   ('-X', "-X Up", ""),
+                   ('-Y', "-Y Up", ""),
+                   ('-Z', "-Z Up", ""),
+                   ),
+            default='Z',
+            )
+
     def execute(self, context):
         from . import import_3ds
-        return import_3ds.load(self, context, **self.as_keywords(ignore=("filter_glob",)))
+
+        keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "filter_glob"))
+
+        global_matrix = axis_conversion(from_forward=self.global_axis_forward, from_up=self.global_axis_up).to_4x4()
+        keywords["global_matrix"] = global_matrix
+
+        return import_3ds.load(self, context, **keywords)
 
 
 class Export3DS(bpy.types.Operator, ExportHelper):
@@ -73,9 +103,38 @@ class Export3DS(bpy.types.Operator, ExportHelper):
 
     use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default=False)
 
+    global_axis_forward = EnumProperty(
+            name="Forward",
+            items=(('X', "X Forward", ""),
+                   ('Y', "Y Forward", ""),
+                   ('Z', "Z Forward", ""),
+                   ('-X', "-X Forward", ""),
+                   ('-Y', "-Y Forward", ""),
+                   ('-Z', "-Z Forward", ""),
+                   ),
+            default='Y',
+            )
+
+    global_axis_up = EnumProperty(
+            name="Up",
+            items=(('X', "X Up", ""),
+                   ('Y', "Y Up", ""),
+                   ('Z', "Z Up", ""),
+                   ('-X', "-X Up", ""),
+                   ('-Y', "-Y Up", ""),
+                   ('-Z', "-Z Up", ""),
+                   ),
+            default='Z',
+            )
+
     def execute(self, context):
         from . import export_3ds
-        return export_3ds.save(self, context, **self.as_keywords(ignore=("check_existing", "filter_glob")))
+
+        keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "filter_glob", "check_existing"))
+        global_matrix = axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4()
+        keywords["global_matrix"] = global_matrix
+
+        return export_3ds.save(self, context, **keywords)
 
 
 # Add to a menu
diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py
index 8def27b16..b9f5d982a 100644
--- a/io_scene_3ds/export_3ds.py
+++ b/io_scene_3ds/export_3ds.py
@@ -485,11 +485,8 @@ def make_material_chunk(material, image):
 
     else:
         material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a * material.ambient for a in material.diffuse_color]))
-# 		material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a*material.amb for a in material.rgbCol] ))
         material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.diffuse_color))
-# 		material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.rgbCol))
         material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color))
-# 		material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specCol))
 
         images = get_material_images(material)  # can be None
         if image:
@@ -522,22 +519,15 @@ def extract_triangles(mesh):
     If the mesh contains quads, they will be split into triangles.'''
     tri_list = []
     do_uv = len(mesh.uv_textures)
-# 	do_uv = mesh.faceUV
-
-# 	if not do_uv:
-# 		face_uv = None
 
     img = None
     for i, face in enumerate(mesh.faces):
         f_v = face.vertices
-# 		f_v = face.v
 
         uf = mesh.uv_textures.active.data[i] if do_uv else None
 
         if do_uv:
             f_uv = uf.uv
-            # f_uv =  (uf.uv1, uf.uv2, uf.uv3, uf.uv4) if face.vertices[3] else (uf.uv1, uf.uv2, uf.uv3)
-# 			f_uv = face.uv
             img = uf.image if uf else None
             if img is not None:
                 img = img.name
@@ -545,16 +535,13 @@ def extract_triangles(mesh):
         # if f_v[3] == 0:
         if len(f_v) == 3:
             new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img)
-# 			new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img)
             if (do_uv):
                 new_tri.faceuvs = uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2])
             tri_list.append(new_tri)
 
         else:  # it's a quad
             new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img)
-# 			new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img)
             new_tri_2 = tri_wrapper((f_v[0], f_v[2], f_v[3]), face.material_index, img)
-# 			new_tri_2 = tri_wrapper((f_v[0].index, f_v[2].index, f_v[3].index), face.mat, img)
 
             if (do_uv):
                 new_tri.faceuvs = uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2])
@@ -887,11 +874,15 @@ def make_kf_obj_node(obj, name_to_id):
 """
 
 
-def save(operator, context, filepath="",
-          use_selection=True,
-          ):
+def save(operator,
+         context, filepath="",
+         use_selection=True,
+         global_matrix=None,
+         ):
 
     import bpy
+    import mathutils
+
     import time
     from bpy_extras.io_utils import create_derived_objects, free_derived_objects
 
@@ -901,6 +892,9 @@ def save(operator, context, filepath="",
     time1 = time.clock()
 #	Blender.Window.WaitCursor(1)
 
+    if global_matrix is None:
+        global_matrix = mathutils.Matrix()
+
     if bpy.ops.object.mode_set.poll():
         bpy.ops.object.mode_set(mode='OBJECT')
 
@@ -939,8 +933,6 @@ def save(operator, context, filepath="",
             continue
 
         for ob_derived, mat in derived:
-# 		for ob_derived, mat in getDerivedObjects(ob, False):
-
             if ob.type not in ('MESH', 'CURVE', 'SURFACE', 'FONT', 'META'):
                 continue
 
@@ -950,7 +942,7 @@ def save(operator, context, filepath="",
                 data = None
 
             if data:
-                data.transform(mat)
+                data.transform(global_matrix * mat)
 # 				data.transform(mat, recalc_normals=False)
                 mesh_objects.append((ob_derived, data))
                 mat_ls = data.materials
@@ -965,7 +957,6 @@ def save(operator, context, filepath="",
                     for f, uf in zip(data.faces, data.uv_textures.active.data):
                         if mat_ls:
                             mat_index = f.material_index
-# 							mat_index = f.mat
                             if mat_index >= mat_ls_len:
                                 mat_index = f.mat = 0
                             mat = mat_ls[mat_index]
diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py
index d66ace47c..f054033d6 100644
--- a/io_scene_3ds/import_3ds.py
+++ b/io_scene_3ds/import_3ds.py
@@ -339,18 +339,12 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
         ob = bpy.data.objects.new(contextObName, bmesh)
         object_dictionary[contextObName] = ob
         SCN.objects.link(ob)
-
-        '''
-        if contextMatrix_tx:
-            ob.setMatrix(contextMatrix_tx)
-        '''
+        importedObjects.append(ob)
 
         if contextMatrix_rot:
             ob.matrix_local = contextMatrix_rot
             object_matrix[ob] = contextMatrix_rot.copy()
 
-        importedObjects.append(ob)
-
     #a spare chunk
     new_chunk = chunk()
     temp_chunk = chunk()
@@ -667,6 +661,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
             if child is None:
                 child = bpy.data.objects.new(object_name, None)  # create an empty object
                 SCN.objects.link(child)
+                importedObjects.append(child)
 
             object_list.append(child)
             object_parent.append(hierarchy)
@@ -779,7 +774,12 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
             ob.data.transform(pivot_matrix)
 
 
-def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=True):
+def load_3ds(filepath,
+             context,
+             IMPORT_CONSTRAIN_BOUNDS=10.0,
+             IMAGE_SEARCH=True,
+             APPLY_MATRIX=True,
+             global_matrix=None):
     global SCN
 
     # XXX
@@ -838,6 +838,13 @@ def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
                 me = ob.data
                 me.transform(ob.matrix_local.inverted())
 
+    # print(importedObjects)
+    if global_matrix:
+        for ob in importedObjects:
+            if ob.parent is None:
+                ob.matrix_world = ob.matrix_world * global_matrix
+
+
     # Done DUMMYVERT
     """
     if IMPORT_AS_INSTANCE:
@@ -903,6 +910,21 @@ def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
     file.close()
 
 
-def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True):
-    load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform)
+def load(operator,
+         context,
+         filepath="",
+         constrain_size=0.0,
+         use_image_search=True,
+         use_apply_transform=True,
+         global_matrix=None,
+         ):
+
+    load_3ds(filepath,
+             context,
+             IMPORT_CONSTRAIN_BOUNDS=constrain_size,
+             IMAGE_SEARCH=use_image_search,
+             APPLY_MATRIX=use_apply_transform,
+             global_matrix=global_matrix,
+             )
+
     return {'FINISHED'}
diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index ff87d29bd..48391ac0a 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -138,12 +138,12 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
         if not self.filepath:
             raise Exception("filepath not set")
 
-        GLOBAL_MATRIX = Matrix()
-        GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.global_scale
-        GLOBAL_MATRIX = GLOBAL_MATRIX * axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4()
+        global_matrix = Matrix()
+        global_matrix[0][0] = global_matrix[1][1] = global_matrix[2][2] = self.global_scale
+        global_matrix = global_matrix * axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4()
 
         keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "global_scale", "check_existing", "filter_glob"))
-        keywords["GLOBAL_MATRIX"] = GLOBAL_MATRIX
+        keywords["global_matrix"] = global_matrix
 
         from . import export_fbx
         return export_fbx.save(self, context, **keywords)
diff --git a/io_scene_fbx/export_fbx.py b/io_scene_fbx/export_fbx.py
index 16789bf9a..fa0b5bfdf 100644
--- a/io_scene_fbx/export_fbx.py
+++ b/io_scene_fbx/export_fbx.py
@@ -201,7 +201,7 @@ header_comment = \
 
 # This func can be called with just the filepath
 def save_single(operator, scene, filepath="",
-        GLOBAL_MATRIX=None,
+        global_matrix=None,
         context_objects=None,
         object_types={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH'},
         mesh_apply_modifiers=True,
@@ -219,8 +219,8 @@ def save_single(operator, scene, filepath="",
     mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X')
     mtx4_z90 = Matrix.Rotation(math.pi / 2.0, 4, 'Z')
 
-    if GLOBAL_MATRIX is None:
-        GLOBAL_MATRIX = Matrix()
+    if global_matrix is None:
+        global_matrix = Matrix()
 
     # Use this for working out paths relative to the export location
     base_src = os.path.dirname(bpy.data.filepath)
@@ -348,9 +348,9 @@ def save_single(operator, scene, filepath="",
             self.fbxGroupNames = []
             self.fbxParent = None  # set later on IF the parent is in the selection.
             if matrixWorld:
-                self.matrixWorld = GLOBAL_MATRIX * matrixWorld
+                self.matrixWorld = global_matrix * matrixWorld
             else:
-                self.matrixWorld = GLOBAL_MATRIX * ob.matrix_world
+                self.matrixWorld = global_matrix * ob.matrix_world
 
             self.__anim_poselist = {}  # we should only access this
 
@@ -362,24 +362,24 @@ def save_single(operator, scene, filepath="",
 
         def setPoseFrame(self, f, fake=False):
             if fake:
-                # annoying, have to clear GLOBAL_MATRIX
-                self.__anim_poselist[f] = self.matrixWorld * GLOBAL_MATRIX.inverted()
+                # annoying, have to clear global_matrix
+                self.__anim_poselist[f] = global_matrix * self.matrixWorld
             else:
                 self.__anim_poselist[f] = self.blenObject.matrix_world.copy()
 
         def getAnimParRelMatrix(self, frame):
             if self.fbxParent:
-                #return (self.__anim_poselist[frame] * self.fbxParent.__anim_poselist[frame].inverted() ) * GLOBAL_MATRIX
-                return (GLOBAL_MATRIX * self.fbxParent.__anim_poselist[frame]).inverted() * (GLOBAL_MATRIX * self.__anim_poselist[frame])
+                #return (self.__anim_poselist[frame] * self.fbxParent.__anim_poselist[frame].inverted() ) * global_matrix
+                return (global_matrix * self.fbxParent.__anim_poselist[frame]).inverted() * (global_matrix * self.__anim_poselist[frame])
             else:
-                return GLOBAL_MATRIX * self.__anim_poselist[frame]
+                return global_matrix * self.__anim_poselist[frame]
 
         def getAnimParRelMatrixRot(self, frame):
             obj_type = self.blenObject.type
             if self.fbxParent:
-                matrix_rot = ((GLOBAL_MATRIX * self.fbxParent.__anim_poselist[frame]).inverted() * (GLOBAL_MATRIX * self.__anim_poselist[frame])).to_3x3()
+                matrix_rot = ((global_matrix * self.fbxParent.__anim_poselist[frame]).inverted() * (global_matrix * self.__anim_poselist[frame])).to_3x3()
             else:
-                matrix_rot = (GLOBAL_MATRIX * self.__anim_poselist[frame]).to_3x3()
+                matrix_rot = (global_matrix * self.__anim_poselist[frame]).to_3x3()
 
             # Lamps need to be rotated
             if obj_type == 'LAMP':
@@ -465,7 +465,7 @@ def save_single(operator, scene, filepath="",
             scale = tuple(scale)
         else:
             # This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore
-            #if ob and not matrix: matrix = ob.matrix_world * GLOBAL_MATRIX
+            #if ob and not matrix: matrix = ob.matrix_world * global_matrix
             if ob and not matrix:
                 raise Exception("error: this should never happen!")
 
@@ -937,7 +937,7 @@ def save_single(operator, scene, filepath="",
             do_light = not (light.use_only_shadow or (not light.use_diffuse and not light.use_specular))
             do_shadow = (light.shadow_method in ('RAY_SHADOW', 'BUFFER_SHADOW'))
 
-        scale = abs(GLOBAL_MATRIX.to_scale()[0])  # scale is always uniform in this case
+        scale = abs(global_matrix.to_scale()[0])  # scale is always uniform in this case
 
         file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type)
         file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1')
-- 
GitLab