diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 0aad653ad..e04a071d2 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -55,9 +55,9 @@ class Import3DS(bpy.types.Operator, ImportHelper): soft_min=0.0, soft_max=1000.0, default=10.0, ) - convert_measure: BoolProperty( - name="Convert Measure", - description="Convert from millimeters to meters", + convert_unit: BoolProperty( + name="Convert Units", + description="Converts to scene unit length settings", default=False, ) use_image_search: BoolProperty( @@ -149,7 +149,7 @@ class MAX3DS_PT_import_transform(bpy.types.Panel): operator = sfile.active_operator layout.prop(operator, "constrain_size") - layout.prop(operator, "convert_measure") + layout.prop(operator, "convert_unit") layout.prop(operator, "use_apply_transform") layout.prop(operator, "use_world_matrix") layout.prop(operator, "axis_forward") @@ -176,6 +176,11 @@ class Export3DS(bpy.types.Operator, ExportHelper): soft_min=0.0, soft_max=100000.0, default=1.0, ) + apply_unit: BoolProperty( + name="Apply Units", + description="Take the scene unit length settings into account", + default=False, + ) use_selection: BoolProperty( name="Selection Only", description="Export selected objects only", @@ -259,6 +264,7 @@ class MAX3DS_PT_export_transform(bpy.types.Panel): operator = sfile.active_operator layout.prop(operator, "scale_factor") + layout.prop(operator, "apply_unit") layout.prop(operator, "axis_forward") layout.prop(operator, "axis_up") @@ -295,4 +301,4 @@ def unregister(): if __name__ == "__main__": - register() \ No newline at end of file + register() diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 83e947b52..0378b1afa 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -1489,10 +1489,9 @@ def make_ambient_node(world): # EXPORT # ########## -def save(operator, context, filepath="", scale_factor=1.0, use_selection=False, use_hierarchy=False, write_keyframe=False, global_matrix=None): - +def save(operator, context, filepath="", scale_factor=1.0, apply_unit=False, + use_selection=False, use_hierarchy=False, write_keyframe=False, global_matrix=None): """Save the Blender scene to a 3ds file.""" - mtx_scale = mathutils.Matrix.Scale(scale_factor, 4) # Time the export duration = time.time() @@ -1503,6 +1502,20 @@ def save(operator, context, filepath="", scale_factor=1.0, use_selection=False, depsgraph = context.evaluated_depsgraph_get() world = scene.world + unit_measure = 1.0 + if apply_unit: + unit_length = sce.unit_settings.length_unit + if unit_length == 'KILOMETERS': + unit_measure = 0.001 + elif unit_length == 'CENTIMETERS': + unit_measure = 100 + elif unit_length == 'MILLIMETERS': + unit_measure = 1000 + elif unit_length == 'MICROMETERS': + unit_measure = 1000000 + + mtx_scale = mathutils.Matrix.Scale((scale_factor * unit_measure),4) + if global_matrix is None: global_matrix = mathutils.Matrix() @@ -1525,7 +1538,7 @@ def save(operator, context, filepath="", scale_factor=1.0, use_selection=False, # Add MASTERSCALE element mscale = _3ds_chunk(MASTERSCALE) - mscale.add_variable("scale", _3ds_float(1.0)) + mscale.add_variable("scale", _3ds_float((1.0 / unit_measure))) object_info.add_subchunk(mscale) # Init main keyframe data chunk diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 4fa28e5a3..c7dc5d1d6 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -1101,8 +1101,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI for keydata in keyframe_data.items(): trackposition[keydata[0]] = keydata[1] # Keep track to position for target calculation child.location = apply_constrain(keydata[1]) if hierarchy == ROOT_OBJECT else mathutils.Vector(keydata[1]) - if MEASURE: - child.location = child.location * 0.001 + if MEASURE != 1.0: + child.location = child.location * MEASURE if hierarchy == ROOT_OBJECT: child.location.rotate(CONVERSE) if not contextTrack_flag & 0x100: # Flag 0x100 unlinks X axis @@ -1129,8 +1129,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI scale = mathutils.Vector.Fill(3, (CONSTRAIN * 0.1)) if CONSTRAIN != 0.0 else child.scale transformation = mathutils.Matrix.LocRotScale(locate, rotate, scale) child.matrix_world = transformation - if MEASURE: - child.matrix_world = mathutils.Matrix.Scale(0.001,4) @ child.matrix_world + if MEASURE != 1.0: + child.matrix_world = mathutils.Matrix.Scale(MEASURE,4) @ child.matrix_world if hierarchy == ROOT_OBJECT: child.matrix_world = CONVERSE @ child.matrix_world child.keyframe_insert(data_path="rotation_euler", index=0, frame=keydata[0]) @@ -1305,7 +1305,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI # IMPORT # ########## -def load_3ds(filepath, context, CONSTRAIN=10.0, MEASURE=False, IMAGE_SEARCH=True, +def load_3ds(filepath, context, CONSTRAIN=10.0, UNITS=False, IMAGE_SEARCH=True, WORLD_MATRIX=False, KEYFRAME=True, APPLY_MATRIX=True, CONVERSE=None): print("importing 3DS: %r..." % (filepath), end="") @@ -1313,6 +1313,7 @@ def load_3ds(filepath, context, CONSTRAIN=10.0, MEASURE=False, IMAGE_SEARCH=True if bpy.ops.object.select_all.poll(): bpy.ops.object.select_all(action='DESELECT') + MEASURE = 1.0 duration = time.time() current_chunk = Chunk() file = open(filepath, 'rb') @@ -1335,6 +1336,17 @@ def load_3ds(filepath, context, CONSTRAIN=10.0, MEASURE=False, IMAGE_SEARCH=True object_matrix.clear() scn = context.scene + if UNITS: + unit_length = sce.unit_settings.length_unit + if unit_length == 'KILOMETERS': + MEASURE = 1000.0 + elif unit_length == 'CENTIMETERS': + MEASURE = 0.01 + elif unit_length == 'MILLIMETERS': + MEASURE = 0.001 + elif unit_length == 'MICROMETERS': + MEASURE = 0.000001 + imported_objects = [] # Fill this list with objects process_next_chunk(context, file, current_chunk, imported_objects, CONSTRAIN, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME, CONVERSE, MEASURE) @@ -1348,8 +1360,8 @@ def load_3ds(filepath, context, CONSTRAIN=10.0, MEASURE=False, IMAGE_SEARCH=True if ob.type == 'MESH': ob.data.transform(ob.matrix_local.inverted()) - if MEASURE: - unit_mtx = mathutils.Matrix.Scale(0.001,4) + if UNITS: + unit_mtx = mathutils.Matrix.Scale(MEASURE,4) for ob in imported_objects: if ob.type == 'MESH': ob.data.transform(unit_mtx) @@ -1432,13 +1444,13 @@ def load_3ds(filepath, context, CONSTRAIN=10.0, MEASURE=False, IMAGE_SEARCH=True def load(operator, context, filepath="", constrain_size=0.0, - convert_measure=False, use_image_search=True, + convert_unit=False, use_image_search=True, use_world_matrix=False, read_keyframe=True, use_apply_transform=True, global_matrix=None, ): load_3ds(filepath, context, CONSTRAIN=constrain_size, - MEASURE=convert_measure, IMAGE_SEARCH=use_image_search, + UNITS=convert_unit, IMAGE_SEARCH=use_image_search, WORLD_MATRIX=use_world_matrix, KEYFRAME=read_keyframe, APPLY_MATRIX=use_apply_transform, CONVERSE=global_matrix, )