io_scene_3ds: Improved import and export of background color and images #104801

Merged
Sebastian Sille merged 54 commits from :main into main 2023-07-30 16:34:21 +02:00
2 changed files with 71 additions and 45 deletions
Showing only changes of commit 2c7c68ee3b - Show all commits

View File

@ -1566,21 +1566,42 @@ def save(operator, context, filepath="", scale_factor=1.0, apply_unit=False, use
object_info.add_subchunk(ambient_chunk) object_info.add_subchunk(ambient_chunk)
if world.use_nodes: if world.use_nodes:
ntree = world.node_tree.links ntree = world.node_tree.links
background_color = _3ds_chunk(RGB) background_color_chunk = _3ds_chunk(RGB)
background_chunk = _3ds_chunk(SOLIDBACKGND) background_chunk = _3ds_chunk(SOLIDBACKGND)
background_flag = _3ds_chunk(USE_SOLIDBGND) background_flag = _3ds_chunk(USE_SOLIDBGND)
amcol, bgcol, bgtex, nworld = 'EMISSION', 'BACKGROUND', 'TEX_ENVIRONMENT', 'OUTPUT_WORLD' bgshader = 'ADD_SHADER', 'MIX_SHADER', 'OUTPUT_WORLD'
bg_color = next((lk.from_node.inputs[0].default_value[:3] for lk in ntree if lk.to_node.type == bgcol), world.color) bgtexture = 'TEX_IMAGE', 'TEX_ENVIRONMENT'
bg_image = next((lk.from_node.image.name for lk in ntree if lk.from_node.type == bgtex and lk.to_node.type in {amcol, bgcol}), False) acol, bcol = 'EMISSION', 'BACKGROUND'
background_color.add_variable("color", _3ds_float_color(bg_color)) bg_color = next((lk.from_node.inputs[0].default_value[:3] for lk in ntree if lk.from_node.type == bcol and lk.to_node.type in bgshader), world.color)
background_chunk.add_subchunk(background_color) bg_image = next((lk.from_node.image.name for lk in ntree if lk.from_node.type in bgtexture and lk.to_node.type in {acol, bcol}), False)
object_info.add_subchunk(background_chunk) background_color_chunk.add_variable("color", _3ds_float_color(bg_color))
background_chunk.add_subchunk(background_color_chunk)
if bg_image: if bg_image:
background_image = _3ds_chunk(BITMAP) background_image = _3ds_chunk(BITMAP)
background_flag = _3ds_chunk(USE_BITMAP) background_flag = _3ds_chunk(USE_BITMAP)
background_image.add_variable("image", _3ds_string(sane_name(bg_image))) background_image.add_variable("image", _3ds_string(sane_name(bg_image)))
object_info.add_subchunk(background_image) object_info.add_subchunk(background_image)
object_info.add_subchunk(background_chunk)
object_info.add_subchunk(background_flag) object_info.add_subchunk(background_flag)
fogshader = next((lk.from_socket.node for lk in ntree if lk.from_socket.identifier and lk.to_socket.identifier == 'Volume'), False)
if fogshader:
fogflag = 0
if world.mist_settings.falloff == 'QUADRATIC':
fogflag |= 0x1
if world.mist_settings.falloff == 'INVERSE_QUADRATIC':
fogflag |= 0x2
fog_chunk = _3ds_chunk(LAYER_FOG)
fog_color_chunk = _3ds_chunk(RGB)
use_fog_flag = _3ds_chunk(USE_LAYER_FOG)
fog_color_chunk.add_variable("color", _3ds_float_color(fogshader.inputs[0].default_value[:3]))
fog_chunk.add_variable("lowZ", _3ds_float(world.mist_settings.start))
fog_chunk.add_variable("highZ", _3ds_float(world.mist_settings.depth))
fog_chunk.add_variable("density", _3ds_float(fogshader.inputs[1].default_value))
fog_chunk.add_variable("flags", _3ds_uint(fogflag))
fog_chunk.add_subchunk(fog_color_chunk)
object_info.add_subchunk(fog_chunk)
if layer.use_pass_mist:
object_info.add_subchunk(use_fog_flag)
if write_keyframe and world.animation_data: if write_keyframe and world.animation_data:
kfdata.add_subchunk(make_ambient_node(world)) kfdata.add_subchunk(make_ambient_node(world))

View File

@ -701,15 +701,15 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
realname, ext = os.path.splitext(filename) realname, ext = os.path.splitext(filename)
contextWorld = bpy.data.worlds.new("Background: " + realname) contextWorld = bpy.data.worlds.new("Background: " + realname)
context.scene.world = contextWorld context.scene.world = contextWorld
contextWorld.use_nodes = True
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)
elif temp_chunk.ID == LIN_COLOR_F:
contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk)
else: else:
contextWorld.use_nodes = True skip_to_end(file, temp_chunk)
read_chunk(file, temp_chunk) new_chunk.bytes_read += temp_chunk.bytes_read
if temp_chunk.ID == COLOR_F:
contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = 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)
else: skip_to_end(file, temp_chunk)
new_chunk.bytes_read += temp_chunk.bytes_read
# If bitmap chunk # If bitmap chunk
elif CreateWorld and new_chunk.ID == BITMAP: elif CreateWorld and new_chunk.ID == BITMAP:
@ -719,45 +719,50 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
realname, ext = os.path.splitext(filename) realname, ext = os.path.splitext(filename)
contextWorld = bpy.data.worlds.new("Bitmap: " + realname) contextWorld = bpy.data.worlds.new("Bitmap: " + realname)
context.scene.world = contextWorld context.scene.world = contextWorld
else: contextWorld.use_nodes = True
contextWorld.use_nodes = True links = contextWorld.node_tree.links
links = contextWorld.node_tree.links nodes = contextWorld.node_tree.nodes
nodes = contextWorld.node_tree.nodes bitmapnode = nodes.new(type='ShaderNodeTexEnvironment')
bitmapnode = nodes.new(type='ShaderNodeTexEnvironment') bitmapnode.label = bitmap_name
bitmapnode.label = bitmap_name bitmapnode.location = (-300, 300)
bitmapnode.location = (-300, 300) bitmapnode.image = load_image(bitmap_name, dirname, place_holder=False, recursive=image_search, check_existing=True)
bitmapnode.image = load_image(bitmap_name, dirname, place_holder=False, recursive=image_search, check_existing=True) links.new(bitmapnode.outputs['Color'], nodes['Background'].inputs[0])
links.new(bitmapnode.outputs['Color'], nodes['Background'].inputs[0]) new_chunk.bytes_read += read_str_len
new_chunk.bytes_read += read_str_len
# If fog chunk # If fog chunk
elif CreateWorld and new_chunk.ID == LAYER_FOG: elif CreateWorld and new_chunk.ID == LAYER_FOG:
"""Fog options flags are bit 20 (0x100000) for background fogging,
bit 0 (0x1) for bottom falloff, and bit 1 (0x2) for top falloff."""
if contextWorld is None: if contextWorld is None:
path, filename = os.path.split(file.name) path, filename = os.path.split(file.name)
realname, ext = os.path.splitext(filename) realname, ext = os.path.splitext(filename)
contextWorld = bpy.data.worlds.new("LayerFog: " + realname) contextWorld = bpy.data.worlds.new("LayerFog: " + realname)
context.scene.world = contextWorld context.scene.world = contextWorld
contextWorld.use_nodes = True
links = contextWorld.node_tree.links
nodes = contextWorld.node_tree.nodes
layerfog = nodes.new(type='ShaderNodeVolumeScatter')
layerfog.label = "Layer Fog"
layerfog.location = (300, 100)
links.new(layerfog.outputs['Volume'], nodes['World Output'].inputs['Volume'])
context.view_layer.use_pass_mist = False
contextWorld.mist_settings.use_mist = True
contextWorld.mist_settings.start = read_float(new_chunk)
contextWorld.mist_settings.depth = read_float(new_chunk)
layerfog.inputs[1].default_value = read_float(new_chunk)
layerfog_flag = read_long(new_chunk)
if layerfog_flag & 0x1:
contextWorld.mist_settings.falloff = 'QUADRATIC'
if layerfog_flag & 0x2:
contextWorld.mist_settings.falloff = 'INVERSE_QUADRATIC'
read_chunk(file, temp_chunk)
if temp_chunk.ID == COLOR_F:
layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk)
elif temp_chunk.ID == LIN_COLOR_F:
layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk)
else: else:
contextWorld.use_nodes = True skip_to_end(file, temp_chunk)
links = contextWorld.node_tree.links new_chunk.bytes_read += temp_chunk.bytes_read
nodes = contextWorld.node_tree.nodes
context.view_layer.use_pass_mist = False
layerfog = nodes.new(type='ShaderNodeVolumeScatter')
layerfog.label = "Layer Fog"
layerfog.location = (300, 100)
links.new(layerfog.outputs['Volume'], nodes['World Output'].inputs['Volume'])
contextWorld.mist_settings.start = read_float(new_chunk)
contextWorld.mist_settings.depth = read_float(new_chunk)
layerfog.inputs[1].default_value = read_float(new_chunk)
layerfogflag = read_long(new_chunk)
read_chunk(file, temp_chunk)
if temp_chunk.ID == COLOR_F:
layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk)
elif temp_chunk.ID == LIN_COLOR_F:
layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk)
else:
skip_to_end(file, temp_chunk)
new_chunk.bytes_read += temp_chunk.bytes_read
elif CreateWorld and new_chunk.ID == USE_LAYER_FOG: elif CreateWorld and new_chunk.ID == USE_LAYER_FOG:
context.view_layer.use_pass_mist = True context.view_layer.use_pass_mist = True