Skip to content

Commit

Permalink
optimize frame_change_pre handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Theverat committed Jan 27, 2020
1 parent 7490706 commit b09403f
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 34 deletions.
40 changes: 13 additions & 27 deletions handlers/frame_change_pre.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,33 @@
from ..utils import openVDB_sequence_resolve_all
from ..utils import clamp

# Flag that saves us from having to iterate all node trees when no image sequences are used (the common case).
# Set in image node export method, reset when new .blend is loaded in load_post.
using_image_sequences = False

# Flag that saves us from having to iterate all node trees when no image sequences are used (the common case).
# Set in openVDB node export method, reset when new .blend is loaded in load_post.
using_smoke_sequences = False
RELEVANT_NODES = {"LuxCoreNodeTexImagemap", "LuxCoreNodeTexOpenVDB", "LuxCoreNodeTexTimeInfo"}

# Flags that save us from having to iterate all node trees when no related nodes are used (the common case).
# Set in relevant node export methods, reset when new .blend is loaded in load_post.
have_to_check_node_trees = False

# Important: Since this function is executed on every frame, even milliseconds of processin time in here will
# bring down the frame rate of animations considerably. Always assume the worst case: A big scene with many
# materials and complex node trees, and optimize for it.
@persistent
def handler(scene):
global using_image_sequences
global using_smoke_sequences
global have_to_check_node_trees

if not (using_image_sequences or using_smoke_sequences) or scene.render.engine != "LUXCORE":
if not have_to_check_node_trees or scene.render.engine != "LUXCORE":
return

found_image_sequence = False
found_smoke_sequence = False
found_relevant_node = False
for mat in bpy.data.materials:
if not mat.luxcore.node_tree:
continue

if (utils_node.has_nodes(mat.luxcore.node_tree, "LuxCoreNodeTexOpenVDB", True) or
utils_node.has_nodes(mat.luxcore.node_tree, "LuxCoreNodeTexSmoke", True)):
found_smoke_sequence = True
for node in mat.luxcore.node_tree.nodes:
if node.bl_idname == "LuxCoreNodeMatOutput" and node.active:
# Force a viewport update
mat.luxcore.node_tree.links.new(node.inputs["Material"], node.inputs["Material"].links[0].from_socket)
break

for node in utils_node.find_nodes(mat.luxcore.node_tree, "LuxCoreNodeTexImagemap", True) or \
utils_node.find_nodes(mat.luxcore.node_tree, "LuxCoreNodeTexTimeInfo", True):
found_image_sequence = True
if utils_node.has_nodes_multi(mat.luxcore.node_tree, RELEVANT_NODES, True):
found_relevant_node = True
# Force a viewport update
mat.diffuse_color = mat.diffuse_color
break

using_image_sequences = found_image_sequence
using_smoke_sequences = found_smoke_sequence
have_to_check_node_trees = found_relevant_node

# TODO we are not handling area lights with image sequence textures right now
# because I can't think of a check with good performance in large scenes.
Expand Down
2 changes: 1 addition & 1 deletion handlers/load_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ def handler(_):
# Run converters for backwards compatibility
compatibility.run()

frame_change_pre.using_image_sequences = False
frame_change_pre.have_to_check_node_trees = False
LuxCoreErrorLog.clear()
2 changes: 1 addition & 1 deletion nodes/textures/imagemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def sub_export(self, exporter, depsgraph, props, luxcore_name=None, output_socke
return [0, 0, 0]

if self.image.source == "SEQUENCE":
frame_change_pre.using_image_sequences = True
frame_change_pre.have_to_check_node_trees = True

try:
filepath = ImageExporter.export(self.image, self.image_user, exporter.scene)
Expand Down
4 changes: 2 additions & 2 deletions nodes/textures/openVDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,13 @@ def sub_export(self, exporter, depsgraph, props, luxcore_name=None, output_socke

file_path = self.get_cachefile_name(domain_eval, utils.clamp(frame, frame_start, frame_end), 0)
if frame_end > frame_start:
frame_change_pre.using_smoke_sequences = True
frame_change_pre.have_to_check_node_trees = True
else:
indexed_filepaths = utils.openVDB_sequence_resolve_all(self.file_path)
if len(indexed_filepaths) > 1:
index, file_path = indexed_filepaths[utils.clamp(frame, self.first_frame, self.last_frame)-1]
if self.last_frame > self.first_frame:
frame_change_pre.using_smoke_sequences = True
frame_change_pre.have_to_check_node_trees = True

#Get transformation of domain bounding box, local center is lower bounding box corner
scale = domain_eval.dimensions
Expand Down
2 changes: 0 additions & 2 deletions nodes/textures/smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from ...utils import node as utils_node
from ...ui import icons
from ...utils.errorlog import LuxCoreErrorLog
from ...handlers import frame_change_pre

class LuxCoreNodeTexSmoke(bpy.types.Node, LuxCoreNodeTexture):
bl_label = "Smoke"
Expand Down Expand Up @@ -76,7 +75,6 @@ def sub_export(self, exporter, depsgraph, props, luxcore_name=None, output_socke
}
return self.create_props(props, definitions, luxcore_name)

frame_change_pre.using_smoke_sequences = True
domain_eval = self.domain.evaluated_get(depsgraph)

scale = domain_eval.dimensions
Expand Down
2 changes: 1 addition & 1 deletion nodes/textures/timeinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def draw_buttons(self, context, layout):

def sub_export(self, exporter, depsgraph, props, luxcore_name=None, output_socket=None):
scene = depsgraph.scene_eval
frame_change_pre.using_image_sequences = True
frame_change_pre.have_to_check_node_trees = True

definitions = {
"type": "constfloat1",
Expand Down
20 changes: 20 additions & 0 deletions utils/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ def has_nodes(node_tree, bl_idname, follow_pointers):
return False


def has_nodes_multi(node_tree, bl_idname_set, follow_pointers):
for node in node_tree.nodes:
if follow_pointers and node.bl_idname == "LuxCoreNodeTreePointer" and node.node_tree:
try:
if has_nodes_multi(node.node_tree, bl_idname_set, follow_pointers):
return True
except RecursionError:
msg = (f'Pointer nodes in node trees "{node_tree.name}" and "{node.node_tree.name}" '
"create a dependency cycle! Delete one of them.")
LuxCoreErrorLog.add_error(msg)
# Mark the faulty nodes in red
node.use_custom_color = True
node.color = (0.9, 0, 0)
return False
if node.bl_idname in bl_idname_set:
return True

return False


def force_viewport_update(_, context):
"""
Since Blender 2.80, properties on custom sockets and custom nodes are not listed
Expand Down

0 comments on commit b09403f

Please sign in to comment.