diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 2715d5b66..ab7c12ca1 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -110,6 +110,9 @@ LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag LIGHT_SPOT_LSHADOW = 0x4641 # Light spot shadow parameters LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot show cone flag LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle flag +LIGHT_SPOT_OVERSHOOT = 0x4652 # Light spot overshoot flag +LIGHT_SPOT_PROJECTOR = 0x4653 # Light spot projection bitmap +LIGHT_SPOT_ASPECT = 0x4657 # Light spot aspect ratio # >------ sub defines of CAMERA OBJECT_CAM_RANGES = 0x4720 # The camera range values @@ -1881,6 +1884,23 @@ def save(operator, context, filepath="", scale_factor=1.0, use_scene_unit=False, if ob.data.use_square: spot_square_chunk = _3ds_chunk(LIGHT_SPOT_RECTANGLE) spotlight_chunk.add_subchunk(spot_square_chunk) + if ob.scale.x and ob.scale.y != 0.0: + spot_aspect_chunk = _3ds_chunk(LIGHT_SPOT_ASPECT) + spot_aspect_chunk.add_variable("aspect", _3ds_float(round((ob.scale.x / ob.scale.y),4))) + spotlight_chunk.add_subchunk(spot_aspect_chunk) + if ob.data.use_nodes: + links = ob.data.node_tree.links + bptype = 'EMISSION' + bpmix = 'MIX', 'MIX_RGB', 'EMISSION' + bptex = 'TEX_IMAGE', 'TEX_ENVIRONMENT' + bpout = 'ADD_SHADER', 'MIX_SHADER', 'OUTPUT_LIGHT' + bshade = next((lk.from_node.type for lk in links if lk.from_node.type == bptype and lk.to_node.type in bpout), None) + bpnode = next((lk.from_node.type for lk in links if lk.from_node.type in bpmix and lk.to_node.type == bshade), bshade) + bitmap = next((lk.from_node.image for lk in links if lk.from_node.type in bptex and lk.to_node.type == bpnode), False) + if bitmap and bitmap is not None: + spot_projector_chunk = _3ds_chunk(LIGHT_SPOT_PROJECTOR) + spot_projector_chunk.add_variable("image", _3ds_string(sane_name(bitmap.name))) + spotlight_chunk.add_subchunk(spot_projector_chunk) obj_light_chunk.add_subchunk(spotlight_chunk) # Add light to object chunk diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 732a70eee..1d51491d6 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -1156,6 +1156,24 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI contextLamp.data.show_cone = True elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_RECTANGLE: # Square flag contextLamp.data.use_square = True + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_ASPECT: # Aspect + contextLamp.empty_display_size = read_float(new_chunk) + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_PROJECTOR: # Projection + contextLamp.data.use_nodes = True + nodes = contextLamp.data.node_tree.nodes + links = contextLamp.data.node_tree.links + gobo_name, read_str_len = read_string(file) + new_chunk.bytes_read += read_str_len + projection = nodes.new(type='ShaderNodeTexImage') + projection.label = gobo_name + projection.location = (-340, 360) + projection.image = load_image(gobo_name, dirname, place_holder=False, recursive=IMAGE_SEARCH, check_existing=True) + emitnode = next((node for node in nodes if node.type == 'EMISSION'), False) + emission = emitnode if emitnode else nodes.new(type='ShaderNodeEmission') + emission.label = "Projector" + emission.location = (0, 300) + links.new(emission.outputs['Emission'], nodes['Light Output'].inputs[0]) + links.new(projection.outputs['Color'], emission.inputs[0]) elif CreateLightObject and new_chunk.ID == OBJECT_HIERARCHY: # Hierarchy child_id = get_hierarchy(new_chunk) elif CreateLightObject and new_chunk.ID == OBJECT_PARENT: @@ -1613,6 +1631,18 @@ def load_3ds(filepath, context, CONSTRAIN=10.0, UNITS=False, IMAGE_SEARCH=True, # Select all new objects for ob in imported_objects: + if ob.type == 'LIGHT' and ob.data.type == 'SPOT': + aspect = ob.empty_display_size + fac = 1.0 + ratio = (fac / aspect) + align = fac - (ratio - aspect if ratio > fac else aspect - ratio) + shift = align + (align / 2.0) + if aspect > 1.0: + ob.scale.x = fac + align + ob.scale.y = fac - align + elif aspect < 1.0: + ob.scale.x = fac - align + ob.scale.y = fac + align ob.select_set(True) if not APPLY_MATRIX: # Reset transform bpy.ops.object.rotation_clear()