diff --git a/fast64_internal/f3d/f3d_material.py b/fast64_internal/f3d/f3d_material.py index bf1a739b6..218ee05e6 100644 --- a/fast64_internal/f3d/f3d_material.py +++ b/fast64_internal/f3d/f3d_material.py @@ -2550,8 +2550,58 @@ def createOrUpdateSceneProperties(): _nodeLight1Dir: NodeSocketVectorDirection = new_group.outputs.new("NodeSocketVectorDirection", "Light1Dir") _nodeLight1Size: NodeSocketInt = new_group.outputs.new("NodeSocketInt", "Light1Size") - # Set outputs from render settings sceneOutputs: NodeGroupOutput = new_group.nodes["Group Output"] + + if bpy.app.version >= (3, 4, 0): + # ShaderNodeAttribute.attribute_type = "VIEW_LAYER" is new in 3.4.0 + y = 0 + + def add_attribute_node(attribute_name_info, attribute_type, output_socket): + nonlocal y + if isinstance(attribute_name_info, tuple): + # the ShaderNodeAttribute can't access vector elements, + # so we target the vector instead and use a ShaderNodeSeparateXYZ to get the specific value + attribute_name, index = attribute_name_info + else: + attribute_name = attribute_name_info + index = None + attributeNode = new_group.nodes.new("ShaderNodeAttribute") + attributeNode: bpy.types.ShaderNodeAttribute + attributeNode.attribute_type = "VIEW_LAYER" + attributeNode.attribute_name = attribute_name + attributeNode.hide = True + attributeNode.location = (-500, y) + y -= 30 + if index is not None: + attribute_type = "Vector" + separateNode = new_group.nodes.new("ShaderNodeSeparateXYZ") + separateNode.hide = True + separateNode.location = (-400, y) + y -= 30 + new_group.links.new(separateNode.inputs[0], attributeNode.outputs["Vector"]) + new_group.links.new(sceneOutputs.inputs[output_socket], separateNode.outputs[index]) + else: + if attribute_type == "Fac": + # The socket name changed across Blender versions, but not the order. + # Just use the index + attribute_type = 2 + new_group.links.new(sceneOutputs.inputs[output_socket], attributeNode.outputs[attribute_type]) + + add_attribute_node("fast64.renderSettings.enableFogPreview", "Fac", "FogEnable") + add_attribute_node("fast64.renderSettings.fogPreviewColor", "Color", "FogColor") + add_attribute_node(("fast64.renderSettings.clippingPlanes", 0), "Fac", "F3D_NearClip") + add_attribute_node(("fast64.renderSettings.clippingPlanes", 1), "Fac", "F3D_FarClip") + add_attribute_node(("fast64.renderSettings.fogPreviewPosition", 0), "Fac", "FogNear") + add_attribute_node(("fast64.renderSettings.fogPreviewPosition", 1), "Fac", "FogFar") + add_attribute_node("fast64.renderSettings.ambientColor", "Color", "AmbientColor") + add_attribute_node("fast64.renderSettings.light0Color", "Color", "Light0Color") + add_attribute_node("fast64.renderSettings.light0Direction", "Vector", "Light0Dir") + add_attribute_node("fast64.renderSettings.light0SpecSize", "Fac", "Light0Size") + add_attribute_node("fast64.renderSettings.light1Color", "Color", "Light1Color") + add_attribute_node("fast64.renderSettings.light1Direction", "Vector", "Light1Dir") + add_attribute_node("fast64.renderSettings.light1SpecSize", "Fac", "Light1Size") + + # Set outputs from render settings renderSettings: "Fast64RenderSettings_Properties" = bpy.context.scene.fast64.renderSettings update_scene_props_from_render_settings(sceneOutputs, renderSettings) diff --git a/fast64_internal/render_settings.py b/fast64_internal/render_settings.py index 29e5a7385..59f8e4d99 100644 --- a/fast64_internal/render_settings.py +++ b/fast64_internal/render_settings.py @@ -11,6 +11,7 @@ def on_update_sm64_render_settings(self, context: bpy.types.Context): renderSettings.fogPreviewColor = tuple(c for c in area.area_fog_color) renderSettings.fogPreviewPosition = tuple(round(p) for p in area.area_fog_position) renderSettings.clippingPlanes = tuple(float(p) for p in area.clipPlanes) + force_shader_update_if_auto_update(renderSettings) def on_update_oot_render_settings(self, context: bpy.types.Context): @@ -90,6 +91,17 @@ def interpColors(cola, colb, fade): 10.0, la.z_far + float(lb.z_far - la.z_far) * fade, ) + force_shader_update_if_auto_update(renderSettings) + + +def force_shader_update_if_auto_update(renderSettings: "Fast64RenderSettings_Properties"): + if renderSettings.enableAutoUpdatePreview: + # Force update and redraw since setting the renderSettings props from python unfortunately doesn't + # cause the shader to pick up the values set + bpy.context.scene.update_tag() + for area in bpy.context.screen.areas: + if area.type == "VIEW_3D": + area.tag_redraw() def update_scene_props_from_rs_enableFogPreview( @@ -170,17 +182,19 @@ def update_scene_props_from_render_settings( sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties", ): - update_scene_props_from_rs_enableFogPreview(sceneOutputs, renderSettings) - update_scene_props_from_rs_fogPreviewColor(sceneOutputs, renderSettings) - update_scene_props_from_rs_clippingPlanes(sceneOutputs, renderSettings) - update_scene_props_from_rs_fogPreviewPosition(sceneOutputs, renderSettings) - update_scene_props_from_rs_ambientColor(sceneOutputs, renderSettings) - update_scene_props_from_rs_light0Color(sceneOutputs, renderSettings) - update_scene_props_from_rs_light0Direction(sceneOutputs, renderSettings) - update_scene_props_from_rs_light0SpecSize(sceneOutputs, renderSettings) - update_scene_props_from_rs_light1Color(sceneOutputs, renderSettings) - update_scene_props_from_rs_light1Direction(sceneOutputs, renderSettings) - update_scene_props_from_rs_light1SpecSize(sceneOutputs, renderSettings) + if bpy.app.version < (3, 4, 0): + update_scene_props_from_rs_enableFogPreview(sceneOutputs, renderSettings) + update_scene_props_from_rs_fogPreviewColor(sceneOutputs, renderSettings) + update_scene_props_from_rs_clippingPlanes(sceneOutputs, renderSettings) + update_scene_props_from_rs_fogPreviewPosition(sceneOutputs, renderSettings) + update_scene_props_from_rs_ambientColor(sceneOutputs, renderSettings) + update_scene_props_from_rs_light0Color(sceneOutputs, renderSettings) + update_scene_props_from_rs_light0Direction(sceneOutputs, renderSettings) + update_scene_props_from_rs_light0SpecSize(sceneOutputs, renderSettings) + update_scene_props_from_rs_light1Color(sceneOutputs, renderSettings) + update_scene_props_from_rs_light1Direction(sceneOutputs, renderSettings) + update_scene_props_from_rs_light1SpecSize(sceneOutputs, renderSettings) + update_scene_props_from_rs_useWorldSpaceLighting(renderSettings) # TODO use a callback on the scale props to set this value @@ -224,20 +238,32 @@ def on_update_rs_func(self: "Fast64RenderSettings_Properties", context): return on_update_rs_func -# These are all the callbacks that modify values in the scene properties node group -# Since modifying node values turns out to be very slow, -# we need one callback per prop in order to update the specific associated value. -on_update_rs_enableFogPreview = make_callback(update_scene_props_from_rs_enableFogPreview) -on_update_rs_fogPreviewColor = make_callback(update_scene_props_from_rs_fogPreviewColor) -on_update_rs_clippingPlanes = make_callback(update_scene_props_from_rs_clippingPlanes) -on_update_rs_fogPreviewPosition = make_callback(update_scene_props_from_rs_fogPreviewPosition) -on_update_rs_ambientColor = make_callback(update_scene_props_from_rs_ambientColor) -on_update_rs_light0Color = make_callback(update_scene_props_from_rs_light0Color) -on_update_rs_light0Direction = make_callback(update_scene_props_from_rs_light0Direction) -on_update_rs_light0SpecSize = make_callback(update_scene_props_from_rs_light0SpecSize) -on_update_rs_light1Color = make_callback(update_scene_props_from_rs_light1Color) -on_update_rs_light1Direction = make_callback(update_scene_props_from_rs_light1Direction) -on_update_rs_light1SpecSize = make_callback(update_scene_props_from_rs_light1SpecSize) +if bpy.app.version < (3, 4, 0): + # These are all the callbacks that modify values in the scene properties node group + # Since modifying node values turns out to be very slow, + # we need one callback per prop in order to update the specific associated value. + on_update_rs_fogPreviewColor = make_callback(update_scene_props_from_rs_fogPreviewColor) + on_update_rs_clippingPlanes = make_callback(update_scene_props_from_rs_clippingPlanes) + on_update_rs_fogPreviewPosition = make_callback(update_scene_props_from_rs_fogPreviewPosition) + on_update_rs_ambientColor = make_callback(update_scene_props_from_rs_ambientColor) + on_update_rs_light0Color = make_callback(update_scene_props_from_rs_light0Color) + on_update_rs_light0Direction = make_callback(update_scene_props_from_rs_light0Direction) + on_update_rs_light0SpecSize = make_callback(update_scene_props_from_rs_light0SpecSize) + on_update_rs_light1Color = make_callback(update_scene_props_from_rs_light1Color) + on_update_rs_light1Direction = make_callback(update_scene_props_from_rs_light1Direction) + on_update_rs_light1SpecSize = make_callback(update_scene_props_from_rs_light1SpecSize) +else: + on_update_rs_fogPreviewColor = None + on_update_rs_clippingPlanes = None + on_update_rs_fogPreviewPosition = None + on_update_rs_ambientColor = None + on_update_rs_light0Color = None + on_update_rs_light0Direction = None + on_update_rs_light0SpecSize = None + on_update_rs_light1Color = None + on_update_rs_light1Direction = None + on_update_rs_light1SpecSize = None + on_update_rs_useWorldSpaceLighting = make_callback(update_scene_props_from_rs_useWorldSpaceLighting) del make_callback