[Bf-extensions-cvs] [c2dc0f7] master: FBX Import: add support for custom properties

Jens Ch. Restemeier noreply at git.blender.org
Thu Jul 31 22:19:47 CEST 2014


Commit: c2dc0f78b9f9e26d29c89596089b06ff0b6364ac
Author: Jens Ch. Restemeier
Date:   Thu Jul 31 22:09:04 2014 +0200
Branches: master
https://developer.blender.org/rBAc2dc0f78b9f9e26d29c89596089b06ff0b6364ac

FBX Import: add support for custom properties

Also add support for 3DVectors as custom properties in exporter.

With some minor edits by ideasman42 (Campbell Barton) and mont29 (Bastien Montagne).

===================================================================

M	io_scene_fbx/__init__.py
M	io_scene_fbx/export_fbx_bin.py
M	io_scene_fbx/fbx_utils.py
M	io_scene_fbx/import_fbx.py

===================================================================

diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index 06bad89..38843b5 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -122,6 +122,19 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
             options={'HIDDEN'}
             )
 
+    use_custom_props = BoolProperty(
+            name="Import user properties",
+            description="Import user properties as custom properties",
+            default=True,
+            options={'HIDDEN'},
+            )
+    use_custom_props_enum_as_string = BoolProperty(
+            name="Import enum properties as string",
+            description="Store enumeration values as string",
+            default=True,
+            options={'HIDDEN'},
+            )
+
     def draw(self, context):
         layout = self.layout
 
@@ -136,6 +149,11 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
         # layout.prop(self, "use_alpha_decals")
         layout.prop(self, "decal_offset")
 
+        layout.prop(self, "use_custom_props")
+        sub = layout.row()
+        sub.enabled = self.use_custom_props
+        sub.prop(self, "use_custom_props_enum_as_string")
+
     def execute(self, context):
         keywords = self.as_keywords(ignore=("filter_glob", "directory"))
         keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES')
diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index 72340ef..7904e1d 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -530,12 +530,16 @@ def fbx_data_element_custom_properties(props, bid):
     Store custom properties of blender ID bid (any mapping-like object, in fact) into FBX properties props.
     """
     for k, v in bid.items():
+        list_val = getattr(v, "to_list", lambda: None)()
+
         if isinstance(v, str):
             elem_props_set(props, "p_string", k.encode(), v, custom=True)
         elif isinstance(v, int):
             elem_props_set(props, "p_integer", k.encode(), v, custom=True)
-        if isinstance(v, float):
+        elif isinstance(v, float):
             elem_props_set(props, "p_double", k.encode(), v, custom=True)
+        elif list_val and len(list_val) == 3:
+            elem_props_set(props, "p_vector", k.encode(), list_val, custom=True)
 
 
 def fbx_data_empty_elements(root, empty, scene_data):
diff --git a/io_scene_fbx/fbx_utils.py b/io_scene_fbx/fbx_utils.py
index 7285259..7c6b064 100644
--- a/io_scene_fbx/fbx_utils.py
+++ b/io_scene_fbx/fbx_utils.py
@@ -1099,5 +1099,6 @@ FBXImportSettings = namedtuple("FBXImportSettings", (
     "report", "to_axes", "global_matrix", "global_scale",
     "use_cycles", "use_image_search",
     "use_alpha_decals", "decal_offset",
+    "use_custom_props", "use_custom_props_enum_as_string",
     "object_tdata_cache", "cycles_material_wrap_map", "image_cache",
 ))
diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index 72b387b..f9cf9f2 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -275,6 +275,63 @@ FBXTransformData = namedtuple("FBXTransformData", (
 ))
 
 
+def blen_read_custom_properties(fbx_obj, blen_obj, settings):
+    # There doesn't seem to be a way to put user properties into templates, so this only get the object properties:
+    fbx_obj_props = elem_find_first(fbx_obj, b'Properties70')
+    if fbx_obj_props:
+        for fbx_prop in fbx_obj_props.elems:
+            assert(fbx_prop.id == b'P')
+
+            if b'U' in fbx_prop.props[3]:
+                if fbx_prop.props[0] == b'UDP3DSMAX':
+                    # Special case for 3DS Max user properties:
+                    assert(fbx_prop.props[1] == b'KString')
+                    assert(fbx_prop.props_type[4] == data_types.STRING)
+                    items = fbx_prop.props[4].decode('utf-8')
+                    for item in items.split('\r\n'):
+                        if item:
+                            prop_name, prop_value = item.split('=', 1)
+                            blen_obj[prop_name.strip()] = prop_value.strip()
+                else:
+                    prop_name = fbx_prop.props[0].decode('utf-8')
+                    prop_type = fbx_prop.props[1]
+                    if prop_type in {b'Vector', b'Vector3D', b'Color', b'ColorRGB'}:
+                        assert(fbx_prop.props_type[4:7] == bytes((data_types.FLOAT64,)) * 3)
+                        blen_obj[prop_name] = fbx_prop.props[4:7]
+                    elif prop_type in {b'Vector4', b'ColorRGBA'}:
+                        assert(fbx_prop.props_type[4:8] == bytes((data_types.FLOAT64,)) * 4)
+                        blen_obj[prop_name] = fbx_prop.props[4:8]
+                    elif prop_type == b'Vector2D':
+                        assert(fbx_prop.props_type[4:6] == bytes((data_types.FLOAT64,)) * 2)
+                        blen_obj[prop_name] = fbx_prop.props[4:6]
+                    elif prop_type in {b'Integer', b'int'}:
+                        assert(fbx_prop.props_type[4] == data_types.INT32)
+                        blen_obj[prop_name] = fbx_prop.props[4]
+                    elif prop_type == b'KString':
+                        assert(fbx_prop.props_type[4] == data_types.STRING)
+                        blen_obj[prop_name] = fbx_prop.props[4].decode('utf-8')
+                    elif prop_type in {b'Number', b'double', b'Double'}:
+                        assert(fbx_prop.props_type[4] == data_types.FLOAT64)
+                        blen_obj[prop_name] = fbx_prop.props[4]
+                    elif prop_type in {b'Float', b'float'}:
+                        assert(fbx_prop.props_type[4] == data_types.FLOAT32)
+                        blen_obj[prop_name] = fbx_prop.props[4]
+                    elif prop_type in {b'Bool', b'bool'}:
+                        assert(fbx_prop.props_type[4] == data_types.INT32)
+                        blen_obj[prop_name] = fbx_prop.props[4] != 0
+                    elif prop_type in {b'Enum', b'enum'}:
+                        assert(fbx_prop.props_type[4:6] == bytes((data_types.INT32, data_types.STRING)))
+                        val = fbx_prop.props[4]
+                        if settings.use_custom_props_enum_as_string:
+                            enum_items = fbx_prop.props[5].decode('utf-8').split('~')
+                            assert(val >= 0 and val < len(enum_items))
+                            blen_obj[prop_name] = enum_items[val]
+                        else:
+                            blen_obj[prop_name] = val
+                    else:
+                        print ("WARNING: User property type '%s' is not supported" % prop_type.decode('utf-8'))
+
+
 def blen_read_object_transform_do(transform_data):
     from mathutils import Matrix, Euler
 
@@ -400,6 +457,9 @@ def blen_read_object(fbx_tmpl, fbx_obj, object_data, settings):
         object_tdata_cache[obj] = transform_data
     obj.matrix_basis = blen_read_object_transform_do(transform_data)
 
+    if settings.use_custom_props:
+        blen_read_custom_properties(fbx_obj, obj, settings)
+
     return obj
 
 
@@ -1143,6 +1203,9 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings):
         for p in mesh.polygons:
             p.use_smooth = True
 
+    if settings.use_custom_props:
+        blen_read_custom_properties(fbx_obj, mesh, settings)
+
     return mesh
 
 
@@ -1241,6 +1304,9 @@ def blen_read_material(fbx_tmpl, fbx_obj, settings):
             ma.raytrace_mirror.reflect_factor = ma_refl_factor
             ma.mirror_color = ma_refl_color
 
+    if settings.use_custom_props:
+        blen_read_custom_properties(fbx_obj, ma, settings)
+
     return ma
 
 
@@ -1276,6 +1342,9 @@ def blen_read_texture(fbx_tmpl, fbx_obj, basedir, settings):
     # name can be ../a/b/c
     image.name = os.path.basename(elem_name_utf8)
 
+    if settings.use_custom_props:
+        blen_read_custom_properties(fbx_obj, image, settings)
+
     return image
 
 
@@ -1366,7 +1435,9 @@ def load(operator, context, filepath="",
          use_cycles=True,
          use_image_search=False,
          use_alpha_decals=False,
-         decal_offset=0.0):
+         decal_offset=0.0,
+         use_custom_props=True,
+         use_custom_props_enum_as_string=True):
 
     global fbx_elem_nil
     fbx_elem_nil = FBXElem('', (), (), ())
@@ -1461,6 +1532,7 @@ def load(operator, context, filepath="",
         operator.report, (axis_up, axis_forward), global_matrix, global_scale,
         use_cycles, use_image_search,
         use_alpha_decals, decal_offset,
+        use_custom_props, use_custom_props_enum_as_string,
         object_tdata_cache, cycles_material_wrap_map, image_cache,
     )
 
@@ -2052,6 +2124,14 @@ def load(operator, context, filepath="",
                     tex.image = image
                     texture_cache[image] = tex
 
+                    # copy custom properties from image object to texture
+                    for key, value in image.items():
+                        tex[key] = value
+
+                    # delete custom properties on the image object
+                    for key in image.keys():
+                        del image[key]
+
                 mtex = material.texture_slots.add()
                 mtex.texture = tex
                 mtex.texture_coords = 'UV'



More information about the Bf-extensions-cvs mailing list