Skip to content

Commit

Permalink
Speed up render settings update and add toggle for doing it manually (#…
Browse files Browse the repository at this point in the history
…429)

* Speed up render settings update and add toggle for doing it manually

* make callbacks with function

* add description to autoupdate prop and op

* shorten funcs names
  • Loading branch information
Dragorn421 authored Sep 12, 2024
1 parent 84c650e commit 12681bf
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 34 deletions.
2 changes: 2 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

from .fast64_internal.render_settings import (
Fast64RenderSettings_Properties,
ManualUpdatePreviewOperator,
resync_scene_props,
on_update_render_settings,
)
Expand Down Expand Up @@ -311,6 +312,7 @@ def draw(self, context):
classes = (
Fast64Settings_Properties,
Fast64RenderSettings_Properties,
ManualUpdatePreviewOperator,
Fast64_Properties,
Fast64_BoneProperties,
Fast64_ObjectProperties,
Expand Down
20 changes: 18 additions & 2 deletions fast64_internal/f3d/f3d_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
from .f3d_gbi import get_F3D_GBI, enumTexScroll, isUcodeF3DEX1, default_draw_layers
from .f3d_material_presets import *
from ..utility import *
from ..render_settings import Fast64RenderSettings_Properties, update_scene_props_from_render_settings
from ..render_settings import (
Fast64RenderSettings_Properties,
update_scene_props_from_render_settings,
ManualUpdatePreviewOperator,
)
from .f3d_material_helpers import F3DMaterial_UpdateLock, node_tree_copy
from bpy.app.handlers import persistent
from typing import Generator, Optional, Tuple, Any, Dict, Union
Expand Down Expand Up @@ -2425,7 +2429,7 @@ def createOrUpdateSceneProperties():
sceneOutputs: NodeGroupOutput = new_group.nodes["Group Output"]
renderSettings: "Fast64RenderSettings_Properties" = bpy.context.scene.fast64.renderSettings

update_scene_props_from_render_settings(bpy.context, sceneOutputs, renderSettings)
update_scene_props_from_render_settings(sceneOutputs, renderSettings)


def createScenePropertiesForMaterial(material: Material):
Expand Down Expand Up @@ -4709,6 +4713,18 @@ def draw(self, context):
labelbox.label(text="Global Settings")
labelbox.ui_units_x = 6

# Only show the update preview UI if the render engine is EEVEE,
# as there's no point in updating the nodes otherwise.
if context.scene.render.engine in {
"BLENDER_EEVEE", # <4.2
"BLENDER_EEVEE_NEXT", # 4.2+
}:
updatePreviewRow = globalSettingsBox.row()
updatePreviewRow.prop(renderSettings, "enableAutoUpdatePreview")
if not renderSettings.enableAutoUpdatePreview:
updatePreviewRow.operator(ManualUpdatePreviewOperator.bl_idname)
globalSettingsBox.separator()

globalSettingsBox.prop(renderSettings, "enableFogPreview")
prop_split(globalSettingsBox, renderSettings, "fogPreviewColor", "Fog Color")
prop_split(globalSettingsBox, renderSettings, "fogPreviewPosition", "Fog Position")
Expand Down
211 changes: 179 additions & 32 deletions fast64_internal/render_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,45 +92,155 @@ def interpColors(cola, colb, fade):
)


def update_lighting_space(renderSettings: "Fast64RenderSettings_Properties"):
bpy.data.node_groups["GetSpecularNormal"].nodes["GeometryNormal"].node_tree = bpy.data.node_groups[
"GeometryNormal_WorldSpace" if renderSettings.useWorldSpaceLighting else "GeometryNormal_ViewSpace"
]
def update_scene_props_from_rs_enableFogPreview(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["FogEnable"].default_value = int(renderSettings.enableFogPreview)


def update_scene_props_from_render_settings(
context: bpy.types.Context,
sceneOutputs: bpy.types.NodeGroupOutput,
renderSettings: "Fast64RenderSettings_Properties",
def update_scene_props_from_rs_fogPreviewColor(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["FogEnable"].default_value = int(renderSettings.enableFogPreview)
sceneOutputs.inputs["FogColor"].default_value = s_rgb_alpha_1_tuple(renderSettings.fogPreviewColor)


def update_scene_props_from_rs_clippingPlanes(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["F3D_NearClip"].default_value = float(renderSettings.clippingPlanes[0])
sceneOutputs.inputs["F3D_FarClip"].default_value = float(renderSettings.clippingPlanes[1])
sceneOutputs.inputs["Blender_Game_Scale"].default_value = float(get_blender_to_game_scale(context))


def update_scene_props_from_rs_fogPreviewPosition(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["FogNear"].default_value = renderSettings.fogPreviewPosition[0]
sceneOutputs.inputs["FogFar"].default_value = renderSettings.fogPreviewPosition[1]


def update_scene_props_from_rs_ambientColor(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["AmbientColor"].default_value = s_rgb_alpha_1_tuple(renderSettings.ambientColor)


def update_scene_props_from_rs_light0Color(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light0Color"].default_value = s_rgb_alpha_1_tuple(renderSettings.light0Color)


def update_scene_props_from_rs_light0Direction(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light0Dir"].default_value = renderSettings.light0Direction


def update_scene_props_from_rs_light0SpecSize(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light0Size"].default_value = renderSettings.light0SpecSize


def update_scene_props_from_rs_light1Color(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light1Color"].default_value = s_rgb_alpha_1_tuple(renderSettings.light1Color)


def update_scene_props_from_rs_light1Direction(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light1Dir"].default_value = renderSettings.light1Direction


def update_scene_props_from_rs_light1SpecSize(
sceneOutputs: bpy.types.NodeGroupOutput, renderSettings: "Fast64RenderSettings_Properties"
):
sceneOutputs.inputs["Light1Size"].default_value = renderSettings.light1SpecSize

update_lighting_space(renderSettings)

def update_scene_props_from_rs_useWorldSpaceLighting(renderSettings: "Fast64RenderSettings_Properties"):
bpy.data.node_groups["GetSpecularNormal"].nodes["GeometryNormal"].node_tree = bpy.data.node_groups[
"GeometryNormal_WorldSpace" if renderSettings.useWorldSpaceLighting else "GeometryNormal_ViewSpace"
]


def on_update_render_preview_nodes(self, context: bpy.types.Context):
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)
update_scene_props_from_rs_useWorldSpaceLighting(renderSettings)

# TODO use a callback on the scale props to set this value
sceneOutputs.inputs["Blender_Game_Scale"].default_value = float(get_blender_to_game_scale(bpy.context))


def getSceneOutputs():
sceneProps = bpy.data.node_groups.get("SceneProperties")
if sceneProps == None:
print("Could not locate SceneProperties!")
return
return None

sceneOutputs: bpy.types.NodeGroupOutput = sceneProps.nodes["Group Output"]
renderSettings: "Fast64RenderSettings_Properties" = context.scene.fast64.renderSettings
update_scene_props_from_render_settings(context, sceneOutputs, renderSettings)
return sceneOutputs


class ManualUpdatePreviewOperator(bpy.types.Operator):
bl_idname = "view3d.fast64_manual_update_preview"
bl_label = "Update Preview"
bl_description = "Apply the F3D Render Settings to the view"

def execute(self, context):
sceneOutputs = getSceneOutputs()
renderSettings = bpy.context.scene.fast64.renderSettings

if sceneOutputs is None:
return {"CANCELLED"}

update_scene_props_from_render_settings(sceneOutputs, renderSettings)
return {"FINISHED"}


def make_callback(update_scene_props_from_rs_func):
def on_update_rs_func(self: "Fast64RenderSettings_Properties", context):
if not self.enableAutoUpdatePreview:
return
sceneOutputs = getSceneOutputs()
if sceneOutputs is not None:
update_scene_props_from_rs_func(sceneOutputs, self)

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)
on_update_rs_useWorldSpaceLighting = make_callback(update_scene_props_from_rs_useWorldSpaceLighting)

del make_callback


def on_update_render_settings(self, context: bpy.types.Context):
Expand All @@ -147,7 +257,9 @@ def on_update_render_settings(self, context: bpy.types.Context):
case _:
pass

on_update_render_preview_nodes(self, context)
sceneOutputs = getSceneOutputs()
if sceneOutputs is not None:
update_scene_props_from_render_settings(sceneOutputs, self)


def poll_sm64_area(self, object):
Expand All @@ -161,19 +273,35 @@ def poll_oot_scene(self, object):
def resync_scene_props():
if "GetSpecularNormal" in bpy.data.node_groups:
# Lighting space needs to be updated due to the nodes being shared and reloaded
update_lighting_space(bpy.context.scene.fast64.renderSettings)
update_scene_props_from_rs_useWorldSpaceLighting(bpy.context.scene.fast64.renderSettings)


def on_update_render_settings_enableAutoUpdatePreview(self, context):
# Update on enabling but not disabling
if self.enableAutoUpdatePreview:
on_update_render_settings(self, context)


class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
enableFogPreview: bpy.props.BoolProperty(name="Enable Fog Preview", default=True, update=on_update_render_settings)
enableAutoUpdatePreview: bpy.props.BoolProperty(
name="Auto Update Preview",
description="If enabled, the view will update automatically when changing render settings",
default=True,
update=on_update_render_settings_enableAutoUpdatePreview,
)
enableFogPreview: bpy.props.BoolProperty(
name="Enable Fog Preview",
default=True,
update=on_update_render_settings,
)
fogPreviewColor: bpy.props.FloatVectorProperty(
name="Fog Color",
subtype="COLOR",
size=4,
min=0,
max=1,
default=(1, 1, 1, 1),
update=on_update_render_preview_nodes,
update=on_update_rs_fogPreviewColor,
)
ambientColor: bpy.props.FloatVectorProperty(
name="Ambient Light",
Expand All @@ -182,7 +310,7 @@ class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
min=0,
max=1,
default=(0.5, 0.5, 0.5, 1),
update=on_update_render_preview_nodes,
update=on_update_rs_ambientColor,
)
light0Color: bpy.props.FloatVectorProperty(
name="Light 0 Color",
Expand All @@ -191,7 +319,7 @@ class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
min=0,
max=1,
default=(1, 1, 1, 1),
update=on_update_render_preview_nodes,
update=on_update_rs_light0Color,
)
light0Direction: bpy.props.FloatVectorProperty(
name="Light 0 Direction",
Expand All @@ -200,14 +328,14 @@ class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
min=-1,
max=1,
default=mathutils.Vector((1.0, -1.0, 1.0)).normalized(), # pre normalized
update=on_update_render_preview_nodes,
update=on_update_rs_light0Direction,
)
light0SpecSize: bpy.props.IntProperty(
name="Light 0 Specular Size",
min=1,
max=255,
default=3,
update=on_update_render_preview_nodes,
update=on_update_rs_light0SpecSize,
)
light1Color: bpy.props.FloatVectorProperty(
name="Light 1 Color",
Expand All @@ -216,7 +344,7 @@ class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
min=0,
max=1,
default=(0, 0, 0, 1),
update=on_update_render_preview_nodes,
update=on_update_rs_light1Color,
)
light1Direction: bpy.props.FloatVectorProperty(
name="Light 1 Direction",
Expand All @@ -225,36 +353,55 @@ class Fast64RenderSettings_Properties(bpy.types.PropertyGroup):
min=-1,
max=1,
default=mathutils.Vector((-1.0, 1.0, -1.0)).normalized(), # pre normalized
update=on_update_render_preview_nodes,
update=on_update_rs_light1Direction,
)
light1SpecSize: bpy.props.IntProperty(
name="Light 1 Specular Size",
min=1,
max=255,
default=3,
update=on_update_render_preview_nodes,
update=on_update_rs_light1SpecSize,
)
useWorldSpaceLighting: bpy.props.BoolProperty(
name="Use World Space Lighting", default=True, update=on_update_render_settings
name="Use World Space Lighting",
default=True,
update=on_update_render_settings,
)
# Fog Preview is int because values reflect F3D values
fogPreviewPosition: bpy.props.IntVectorProperty(
name="Fog Position", size=2, min=0, max=1000, default=(985, 1000), update=on_update_render_preview_nodes
name="Fog Position",
size=2,
min=0,
max=1000,
default=(985, 1000),
update=on_update_rs_fogPreviewPosition,
)
# Clipping planes are float because values reflect F3D values
clippingPlanes: bpy.props.FloatVectorProperty(
name="Clipping Planes", size=2, min=0, default=(100, 30000), update=on_update_render_preview_nodes
name="Clipping Planes",
size=2,
min=0,
default=(100, 30000),
update=on_update_rs_clippingPlanes,
)
useObjectRenderPreview: bpy.props.BoolProperty(
name="Use Object Preview", default=True, update=on_update_render_settings
name="Use Object Preview",
default=True,
update=on_update_render_settings,
)
# SM64
sm64Area: bpy.props.PointerProperty(
name="Area Object", type=bpy.types.Object, update=on_update_sm64_render_settings, poll=poll_sm64_area
name="Area Object",
type=bpy.types.Object,
update=on_update_sm64_render_settings,
poll=poll_sm64_area,
)
# OOT
ootSceneObject: bpy.props.PointerProperty(
name="Scene Object", type=bpy.types.Object, update=on_update_oot_render_settings, poll=poll_oot_scene
name="Scene Object",
type=bpy.types.Object,
update=on_update_oot_render_settings,
poll=poll_oot_scene,
)
ootSceneHeader: bpy.props.IntProperty(
name="Header/Setup",
Expand Down

0 comments on commit 12681bf

Please sign in to comment.