io_scene_3ds: Advanced world bitmap and color keyframe import and export #104804

Merged
Sebastian Sille merged 56 commits from :main into main 2023-07-30 23:04:07 +02:00
2 changed files with 49 additions and 9 deletions

View File

@ -1455,7 +1455,34 @@ def make_ambient_node(world):
amb_node_header_chunk.add_variable("parent", _3ds_ushort(ROOT_OBJECT))
amb_node.add_subchunk(amb_node_header_chunk)
if world.animation_data.action:
if world.use_nodes and world.node_tree.animation_data.action:
action = world.node_tree.animation_data.action
ambinode = next((nd for nd in world.node_tree.nodes if nd.type in {'RGB', 'EMISSION'}), False)
if ambinode and action.fcurves:
fcurves = action.fcurves
fcurves.update()
kframes = [kf.co[0] for kf in [fc for fc in fcurves if fc is not None][0].keyframe_points]
ambipath = ('nodes[\"RGB\"].outputs[0].default_value' if ambinode.type == 'RGB' else
'nodes[\"Emission\"].inputs[0].default_value')
nkeys = len(kframes)
if not 0 in kframes:
kframes.append(0)
nkeys = nkeys + 1
kframes = sorted(set(kframes))
track_chunk.add_variable("track_flags", _3ds_ushort(0x40))
track_chunk.add_variable("frame_start", _3ds_uint(int(action.frame_start)))
track_chunk.add_variable("frame_total", _3ds_uint(int(action.frame_end)))
track_chunk.add_variable("nkeys", _3ds_uint(nkeys))
for i, frame in enumerate(kframes):
ambient = [fc.evaluate(frame) for fc in fcurves if fc is not None and fc.data_path == ambipath]
if not ambient:
ambient.append(world.color)
track_chunk.add_variable("tcb_frame", _3ds_uint(int(frame)))
track_chunk.add_variable("tcb_flags", _3ds_ushort())
track_chunk.add_variable("color", _3ds_float_color(ambient[:3]))
elif world.animation_data.action:
action = world.animation_data.action
if action.fcurves:
fcurves = action.fcurves

View File

@ -709,19 +709,26 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
# If background chunk
elif CreateWorld and new_chunk.ID == SOLIDBACKGND:
backgroundcolor = mathutils.Color((0.1, 0.1, 0.1))
if contextWorld is None:
path, filename = os.path.split(file.name)
realname, ext = os.path.splitext(filename)
contextWorld = bpy.data.worlds.new("Background: " + realname)
context.scene.world = contextWorld
contextWorld.use_nodes = True
worldnodes = contextWorld.node_tree.nodes
backgroundnode = worldnodes['Background']
read_chunk(file, temp_chunk)
if temp_chunk.ID == COLOR_F:
contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk)
backgroundcolor = read_float_array(temp_chunk)
elif temp_chunk.ID == LIN_COLOR_F:
contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk)
backgroundcolor = read_float_array(temp_chunk)
else:
skip_to_end(file, temp_chunk)
backgroundmix = next((wn for wn in worldnodes if wn.type in {'MIX', 'MIX_RGB'}), False)
backgroundnode.inputs[0].default_value[:3] = backgroundcolor
if backgroundmix:
backgroundmix.inputs[2].default_value[:3] = backgroundcolor
new_chunk.bytes_read += temp_chunk.bytes_read
# If bitmap chunk
@ -738,9 +745,9 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
bitmap_mix = nodes.new(type='ShaderNodeMixRGB')
bitmapnode = nodes.new(type='ShaderNodeTexEnvironment')
bitmap_mix.label = "Solid Color"
bitmapnode.label = bitmap_name
bitmap_mix.location = (-250, 300)
bitmapnode.location = (-300, 300)
bitmapnode.label = "Bitmap: " + bitmap_name
bitmap_mix.location = (-250, 360)
bitmapnode.location = (-600, 300)
bitmap_mix.inputs[2].default_value = nodes['Background'].inputs[0].default_value
bitmapnode.image = load_image(bitmap_name, dirname, place_holder=False, recursive=IMAGE_SEARCH, check_existing=True)
bitmap_mix.inputs[0].default_value = 0.0 if bitmapnode.image is not None else 1.0
@ -1143,13 +1150,17 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
worldout = nodes['World Output']
mixshade = nodes.new(type='ShaderNodeMixShader')
ambinode = nodes.new(type='ShaderNodeEmission')
ambilite = nodes.new(type='ShaderNodeRGB')
ambilite.label = "Ambient Color"
ambinode.inputs[0].default_value[:3] = child.color
ambinode.location = (10, 150)
worldout.location = (600, 200)
mixshade.location = (300, 300)
ambilite.location = (-250, 150)
links.new(mixshade.outputs[0], worldout.inputs['Surface'])
links.new(nodes['Background'].outputs[0], mixshade.inputs[1])
links.new(ambinode.outputs[0], mixshade.inputs[2])
links.new(ambilite.outputs[0], ambinode.inputs[0])
ambinode.label = object_name if object_name != '$AMBIENT$' else "Ambient"
elif CreateEmpty and tracking == 'OBJECT' and object_name == '$$$DUMMY':
child = bpy.data.objects.new(object_name, None) # Create an empty object
@ -1195,11 +1206,13 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
keyframe_data = {}
default_data = child.color[:]
child.color = read_track_data(new_chunk)[0]
ambinode.inputs[0].default_value[:3] = child.color
ambilite.color = child.color
ambinode.inputs[0].default_value[:3] = ambilite.color
for keydata in keyframe_data.items():
child.color = keydata[1]
child.keyframe_insert(data_path="color", frame=keydata[0])
ambinode.inputs[0].default_value[:3] = keydata[1]
child.color = ambilite.outputs[0].default_value[:3] = keydata[1]
child.keyframe_insert(data_path="color", frame=keydata[0])
nodetree.keyframe_insert(data_path="nodes[\"RGB\"].outputs[0].default_value", frame=keydata[0])
nodetree.keyframe_insert(data_path="nodes[\"Emission\"].inputs[0].default_value", frame=keydata[0])
contextTrack_flag = False