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).
This commit is contained in:
parent
b9ba1a9c8c
commit
c2dc0f78b9
|
@ -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')
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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",
|
||||
))
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue