FBX exporter conversion almost done.
authorArystanbek Dyussenov <arystan.d@gmail.com>
Fri, 17 Jul 2009 10:09:07 +0000 (10:09 +0000)
committerArystanbek Dyussenov <arystan.d@gmail.com>
Fri, 17 Jul 2009 10:09:07 +0000 (10:09 +0000)
Unit tests:
- add a check that BKE_copy_images produces NULL filepath for images having type other than IMA_TYPE_IMAGE
- also expect NULL filepath for images having empty filename

Enhanced BKE_copy_images so the tests pass.

release/io/export_fbx.py
source/blender/blenkernel/intern/image.c
source/blender/makesrna/intern/rna_object_api.c
source/blender/python/intern/bpy_util.c

index d74e624610452c30e9fd4f76f76a33487988822c..c19a914d22eee085b65e401eb957dd5277c2cf6d 100644 (file)
@@ -297,6 +297,29 @@ def BPyMesh_meshWeight2List(ob):
        return groupNames, vWeightList
 
 
+def BPyMesh_meshWeight2Dict(me, ob):
+       ''' Takes a mesh and return its group names and a list of dicts, one dict per vertex.
+       using the group as a key and a float value for the weight.
+       These 2 lists can be modified and then used with dict2MeshWeight to apply the changes.
+       '''
+       
+       vWeightDict= [dict() for i in xrange(len(me.verts))] # Sync with vertlist.
+       
+       # Clear the vert group.
+       groupNames= [g.name for g in ob.vertex_groups]
+#      groupNames= me.getVertGroupNames()
+       
+       for group in groupNames:
+               for vert_index, weight in me.getVertsFromGroup(group, 1): # (i,w)  tuples.
+                       vWeightDict[vert_index][group]= weight
+       
+       # removed this because me may be copying teh vertex groups.
+       #for group in groupNames:
+       #       me.removeVertGroup(group)
+       
+       return groupNames, vWeightDict
+
+
 def meshNormalizedWeights(me):
        try: # account for old bad BPyMesh
                groupNames, vWeightList = BPyMesh_meshWeight2List(me)
@@ -1498,7 +1521,7 @@ def write(filename, batch_objects = None, \
                if my_mesh.blenTextures:        do_textures = True
                else:                                           do_textures = False     
                
-               do_uvs = len(me.uv_layers) > 0
+               do_uvs = len(me.uv_textures) > 0
 #              do_uvs = me.faceUV
                
                
@@ -2073,8 +2096,9 @@ def write(filename, batch_objects = None, \
                                origData = True
                                if tmp_ob_type != 'MESH':
 #                              if tmp_ob_type != 'Mesh':
-                                       me = bpy.data.meshes.new()
-                                       try:    me.getFromObject(ob)
+#                                      me = bpy.data.meshes.new()
+                                       try:    me = ob.create_mesh(True, 'PREVIEW')
+#                                      try:    me.getFromObject(ob)
                                        except: me = None
                                        if me:
                                                meshes_to_clear.append( me )
@@ -2084,65 +2108,70 @@ def write(filename, batch_objects = None, \
                                        # Mesh Type!
                                        if EXP_MESH_APPLY_MOD:
 #                                              me = bpy.data.meshes.new()
-                                               me = ob.create_mesh('PREVIEW')
+                                               me = ob.create_mesh(True, 'PREVIEW')
 #                                              me.getFromObject(ob)
                                                
                                                # so we keep the vert groups
-                                               if EXP_ARMATURE:
-                                                       orig_mesh = ob.data
+#                                              if EXP_ARMATURE:
 #                                                      orig_mesh = ob.getData(mesh=1)
-                                                       if len(ob.vertex_groups):
 #                                                      if orig_mesh.getVertGroupNames():
-                                                               ob.copy().link(me)
-                                                               # If new mesh has no vgroups we can try add if verts are teh same
-                                                               if not me.getVertGroupNames(): # vgroups were not kept by the modifier
-                                                                       if len(me.verts) == len(orig_mesh.verts):
-                                                                               groupNames, vWeightDict = BPyMesh.meshWeight2Dict(orig_mesh)
-                                                                               BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
+#                                                              ob.copy().link(me)
+#                                                              # If new mesh has no vgroups we can try add if verts are teh same
+#                                                              if not me.getVertGroupNames(): # vgroups were not kept by the modifier
+#                                                                      if len(me.verts) == len(orig_mesh.verts):
+#                                                                              groupNames, vWeightDict = BPyMesh.meshWeight2Dict(orig_mesh)
+#                                                                              BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
                                                
                                                # print ob, me, me.getVertGroupNames()
                                                meshes_to_clear.append( me )
                                                origData = False
                                                mats = me.materials
                                        else:
-                                               me = ob.getData(mesh=1)
+                                               me = ob.data
+#                                              me = ob.getData(mesh=1)
                                                mats = me.materials
                                                
-                                               # Support object colors
-                                               tmp_colbits = ob.colbits
-                                               if tmp_colbits:
-                                                       tmp_ob_mats = ob.getMaterials(1) # 1 so we get None's too.
-                                                       for i in xrange(16):
-                                                               if tmp_colbits & (1<<i):
-                                                                       mats[i] = tmp_ob_mats[i]
-                                                       del tmp_ob_mats
-                                               del tmp_colbits
+#                                              # Support object colors
+#                                              tmp_colbits = ob.colbits
+#                                              if tmp_colbits:
+#                                                      tmp_ob_mats = ob.getMaterials(1) # 1 so we get None's too.
+#                                                      for i in xrange(16):
+#                                                              if tmp_colbits & (1<<i):
+#                                                                      mats[i] = tmp_ob_mats[i]
+#                                                      del tmp_ob_mats
+#                                              del tmp_colbits
                                                        
                                        
                                if me:
-                                       # This WILL modify meshes in blender if EXP_MESH_APPLY_MOD is disabled.
-                                       # so strictly this is bad. but only in rare cases would it have negative results
-                                       # say with dupliverts the objects would rotate a bit differently
-                                       if EXP_MESH_HQ_NORMALS:
-                                               BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
+#                                      # This WILL modify meshes in blender if EXP_MESH_APPLY_MOD is disabled.
+#                                      # so strictly this is bad. but only in rare cases would it have negative results
+#                                      # say with dupliverts the objects would rotate a bit differently
+#                                      if EXP_MESH_HQ_NORMALS:
+#                                              BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
                                        
                                        texture_mapping_local = {}
                                        material_mapping_local = {}
-                                       if me.faceUV:
-                                               uvlayer_orig = me.activeUVLayer
-                                               for uvlayer in me.getUVLayerNames():
-                                                       me.activeUVLayer = uvlayer
-                                                       for f in me.faces:
-                                                               tex = f.image
+                                       if len(me.uv_textures) > 0:
+#                                      if me.faceUV:
+                                               uvlayer_orig = me.active_uv_texture
+#                                              uvlayer_orig = me.activeUVLayer
+                                               for uvlayer in me.uv_textures:
+#                                              for uvlayer in me.getUVLayerNames():
+#                                                      me.activeUVLayer = uvlayer
+                                                       for f, uf in zip(me.faces, uvlayer.data):
+#                                                      for f in me.faces:
+                                                               tex = uf.image
+#                                                              tex = f.image
                                                                textures[tex] = texture_mapping_local[tex] = None
                                                                
-                                                               try: mat = mats[f.mat]
+                                                               try: mat = mats[f.material_index]
+#                                                              try: mat = mats[f.mat]
                                                                except: mat = None
                                                                
                                                                materials[mat, tex] = material_mapping_local[mat, tex] = None # should use sets, wait for blender 2.5
                                                                        
                                                        
-                                                       me.activeUVLayer = uvlayer_orig
+#                                                      me.activeUVLayer = uvlayer_orig
                                        else:
                                                for mat in mats:
                                                        # 2.44 use mat.lib too for uniqueness
@@ -2155,9 +2184,12 @@ def write(filename, batch_objects = None, \
                                                blenParentBoneName = None
                                                
                                                # parent bone - special case
-                                               if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.BONE:
+                                               if (not armob) and ob.parent and ob.parent.type == 'ARMATURE' and \
+                                                               ob.parent_type == 'BONE':
+#                                              if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.BONE:
                                                        armob = ob.parent
-                                                       blenParentBoneName = ob.parentbonename
+                                                       blenParentBoneName = ob.parent_bone
+#                                                      blenParentBoneName = ob.parentbonename
                                                
                                                        
                                                if armob and armob not in ob_arms:
@@ -2181,7 +2213,11 @@ def write(filename, batch_objects = None, \
                                        my_mesh.fbxBoneParent = blenParentBoneName      # replace with my_bone instance later
                                        
                                        ob_meshes.append( my_mesh )
-       
+
+               # not forgetting to free dupli_list
+               if ob_base.dupli_list: ob_base.free_dupli_list()
+
+
        if EXP_ARMATURE:
                # now we have the meshes, restore the rest arm position
                for i, arm in enumerate(bpy.data.armatures):
@@ -2217,7 +2253,8 @@ def write(filename, batch_objects = None, \
                # fbxName, blenderObject, my_bones, blenderActions
                #ob_arms[i] = fbxArmObName, ob, arm_my_bones, (ob.action, [])
                
-               for bone in my_arm.blenData.bones.values():
+               for bone in my_arm.blenData.bones:
+#              for bone in my_arm.blenData.bones.values():
                        my_bone = my_bone_class(bone, my_arm)
                        my_arm.fbxBones.append( my_bone )
                        ob_bones.append( my_bone )
@@ -2662,7 +2699,8 @@ Connections:  {''')
        
        
        # Needed for scene footer as well as animation
-       render = sce.render
+       render = sce.render_data
+#      render = sce.render
        
        # from the FBX sdk
        #define KTIME_ONE_SECOND        KTime (K_LONGLONG(46186158000))
@@ -2671,8 +2709,10 @@ Connections:  {''')
                return int(0.5 + ((t/fps) * 46186158000))
        
        fps = float(render.fps) 
-       start = render.sFrame
-       end =   render.eFrame
+       start = sce.start_frame
+#      start = render.sFrame
+       end =   sce.end_frame
+#      end =   render.eFrame
        if end < start: start, end = end, start
        if start==end: ANIM_ENABLE = False
        
@@ -2959,8 +2999,6 @@ Takes:  {''')
                bpy.data.remove_mesh(me)
 #              me.verts = None
        
-       
-       
        # --------------------------- Footer
        if world:
                m = world.mist
@@ -3025,7 +3063,8 @@ Takes:  {''')
        if EXP_IMAGE_COPY:
                copy_images( basepath,  [ tex[1] for tex in textures if tex[1] != None ])       
        
-       print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time)
+       print 'export finished in %.4f sec.' % (bpy.sys.time() - start_time)
+#      print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time)
        return True
        
 
@@ -3338,11 +3377,14 @@ if __name__ == '__main__':
 # NOTES (all line numbers correspond to original export_fbx.py (under release/scripts)
 # - Draw.PupMenu alternative in 2.5?, temporarily replaced PupMenu with print
 # - get rid of cleanName somehow
-# - isinstance(inst, bpy.types.*) doesn't work on RNA objects: line 565
+# + fixed: isinstance(inst, bpy.types.*) doesn't work on RNA objects: line 565
 # - get rid of BPyObject_getObjectArmature, move it in RNA?
 # - BATCH_ENABLE and BATCH_GROUP options: line 327
 # - implement all BPyMesh_* used here with RNA
 # - getDerivedObjects is not fully replicated with .dupli* funcs
+# - talk to Campbell, this code won't work? lines 1867-1875
+# - don't know what those colbits are, do we need them? they're said to be deprecated in DNA_object_types.h: 1886-1893
+# - no hq normals: 1900-1901
 
 # TODO
 
index 495dd3ec523367e11dd82b6dce2f58e13da2c2f5..833d5ac1a9061af3b0c43679f92f8502a17da5c7 100644 (file)
@@ -2120,6 +2120,7 @@ void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr)
   Copy list of images to dest_dir.
 
   paths is optional, if given, image paths for each image will be written in it.
+  It will also contain NULLs for images that cannot be copied.
   If an image file doesn't exist, NULL is added in paths.
 
   Logic:
@@ -2161,6 +2162,13 @@ void BKE_copy_images(ListBase *images, char *dest_dir, ListBase *paths)
        while (link) {
                im= link->data;
 
+               LinkData *ld = MEM_callocN(sizeof(LinkData), "PathLinkData");
+               ld->data= NULL;
+               BLI_addtail(paths, ld);
+
+               if (!strcmp(im->name, "") || im->type != IMA_TYPE_IMAGE)
+                       goto next;
+
                BLI_strncpy(path, im->name, sizeof(path));
 
                /* expand "//" in filename and get absolute path */
@@ -2169,16 +2177,8 @@ void BKE_copy_images(ListBase *images, char *dest_dir, ListBase *paths)
                /* in unit tests, we don't want to modify the filesystem */
 #ifndef WITH_UNIT_TEST
                /* proceed only if image file exists */
-               if (!BLI_exists(path)) {
-
-                       if (paths) {
-                               LinkData *ld = MEM_callocN(sizeof(LinkData), "PathLinkData");
-                               ld->data= NULL;
-                               BLI_addtail(paths, ld);
-                       }
-
-                       continue;
-               }
+               if (!BLI_exists(path))
+                       goto next;
 #endif
 
                /* get the directory part */
@@ -2219,17 +2219,17 @@ void BKE_copy_images(ListBase *images, char *dest_dir, ListBase *paths)
                }
 
 #ifndef WITH_UNIT_TEST
-               BLI_copy_fileops(path, dest_path);
+               if (BLI_copy_fileops(path, dest_path) != 0)
+                       goto next;
 #endif
 
                if (paths) {
-                       LinkData *ld = MEM_callocN(sizeof(LinkData), "PathLinkData");
                        len= strlen(dest_path) + 1;
                        ld->data= MEM_callocN(len, "PathLinkData");
                        BLI_strncpy(ld->data, dest_path, len);
-                       BLI_addtail(paths, ld);
                }
 
+       next:
                link= link->next;
        }
 }
index bae651bf806b70c619a16a77df577f52953bf466..27a0ceb21c1d7e3bd71250a0d28204cc23232d33 100644 (file)
@@ -370,7 +370,7 @@ void RNA_api_object(StructRNA *srna)
        RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
        RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers.");
        RNA_def_property_flag(parm, PROP_REQUIRED);
-       parm= RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Mesh settings to apply.");
+       parm= RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply.");
        RNA_def_property_flag(parm, PROP_REQUIRED);
        parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export.");
        RNA_def_function_return(func, parm);
index 3295bdd91c0f395ff75f461c97d468f278b5ec6d..c5fd030cdd64a308617564051ca19aaf24a52b56 100644 (file)
@@ -583,9 +583,8 @@ static PyObject *bpy_util_copy_images(PyObject *self, PyObject *args)
 
        /* convert filenames */
        ret= PyList_New(0);
-       len= BLI_countlist(paths);
 
-       for(link= paths->first, i= 0; link; link++, i++) {
+       for(link= paths->first; link; link= link->next) {
                if (link->data) {
                        item= PyUnicode_FromString(link->data);
                        PyList_Append(ret, item);