io_scene_3ds: Added spotlight aspect and projector #104813

Merged
Sebastian Sille merged 69 commits from :main into main 2023-08-03 00:41:35 +02:00
2 changed files with 50 additions and 0 deletions

View File

@ -110,6 +110,9 @@ LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag
LIGHT_SPOT_LSHADOW = 0x4641 # Light spot shadow parameters LIGHT_SPOT_LSHADOW = 0x4641 # Light spot shadow parameters
LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot show cone flag LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot show cone flag
LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle 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 # >------ sub defines of CAMERA
OBJECT_CAM_RANGES = 0x4720 # The camera range values 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: if ob.data.use_square:
spot_square_chunk = _3ds_chunk(LIGHT_SPOT_RECTANGLE) spot_square_chunk = _3ds_chunk(LIGHT_SPOT_RECTANGLE)
spotlight_chunk.add_subchunk(spot_square_chunk) 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) obj_light_chunk.add_subchunk(spotlight_chunk)
# Add light to object chunk # Add light to object chunk

View File

@ -1156,6 +1156,24 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
contextLamp.data.show_cone = True contextLamp.data.show_cone = True
elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_RECTANGLE: # Square flag elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_RECTANGLE: # Square flag
contextLamp.data.use_square = True 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 elif CreateLightObject and new_chunk.ID == OBJECT_HIERARCHY: # Hierarchy
child_id = get_hierarchy(new_chunk) child_id = get_hierarchy(new_chunk)
elif CreateLightObject and new_chunk.ID == OBJECT_PARENT: 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 # Select all new objects
for ob in imported_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) ob.select_set(True)
if not APPLY_MATRIX: # Reset transform if not APPLY_MATRIX: # Reset transform
bpy.ops.object.rotation_clear() bpy.ops.object.rotation_clear()