offset paths, execution highlighting only when manual exec
This commit is contained in:
parent
64eff798ac
commit
7e642f4c32
5 changed files with 168 additions and 70 deletions
|
|
@ -64,6 +64,10 @@ class SLICENODE_InputInt(InputNode):
|
||||||
class SLICENODE_InputVectorRotation(InputNode):
|
class SLICENODE_InputVectorRotation(InputNode):
|
||||||
input_type = "VectorRotation"
|
input_type = "VectorRotation"
|
||||||
|
|
||||||
|
@register_class
|
||||||
|
class SLICENODE_InputVector(InputNode):
|
||||||
|
input_type = "Vector"
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_InputObject(InputNode):
|
class SLICENODE_InputObject(InputNode):
|
||||||
input_type = "Object"
|
input_type = "Object"
|
||||||
|
|
@ -421,26 +425,24 @@ class SLICENODE_BufferShells(SliceNode):
|
||||||
|
|
||||||
if not paths: return SlicePaths()
|
if not paths: return SlicePaths()
|
||||||
|
|
||||||
if any(rotation):
|
return paths.buffer(distance, miter=self.shape_option, rotation=rotation)
|
||||||
# De-rotate shells to Z-perpendicular plane
|
|
||||||
mat = Euler(rotation).to_matrix().inverted()
|
|
||||||
mat_np = np.array(mat)
|
|
||||||
prepared_paths = [s @ mat_np.T for s in paths]
|
|
||||||
else:
|
|
||||||
prepared_paths = paths
|
|
||||||
|
|
||||||
# Buffer
|
@register_class
|
||||||
res_paths, res_groups = slice.buffer_slice(prepared_paths, distance, miter=self.shape_option)
|
class SLICENODE_PathOffset(SliceNode):
|
||||||
|
bl_label = "Path Offset"
|
||||||
|
|
||||||
if any(rotation):
|
def init(self, context):
|
||||||
# Re-rotate shells back
|
self.add_input("SLICESOCK_Paths", "Paths")
|
||||||
mat_inv = Euler(rotation).to_matrix()
|
self.add_input("SLICESOCK_Vector", "Offset")
|
||||||
mat_inv_np = np.array(mat_inv)
|
self.add_output("SLICESOCK_Paths", "Paths")
|
||||||
final_paths = [s @ mat_inv_np.T for s in res_paths]
|
|
||||||
else:
|
|
||||||
final_paths = res_paths
|
|
||||||
|
|
||||||
return SlicePaths(final_paths, res_groups)
|
def evaluate_output(self, socket_name: str, **_kwargs) -> Any:
|
||||||
|
paths: SlicePaths = self.resolve("Paths")
|
||||||
|
offset: Any = self.resolve("Offset") or (0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
if not paths: return SlicePaths()
|
||||||
|
|
||||||
|
return paths.offset(np.array(offset, dtype=np.float32))
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_BufferShellsMultiple(SliceNode):
|
class SLICENODE_BufferShellsMultiple(SliceNode):
|
||||||
|
|
@ -478,19 +480,11 @@ class SLICENODE_BufferShellsMultiple(SliceNode):
|
||||||
|
|
||||||
if not paths: return SlicePaths()
|
if not paths: return SlicePaths()
|
||||||
|
|
||||||
if any(rotation):
|
|
||||||
mat = Euler(rotation).to_matrix().inverted()
|
|
||||||
mat_np = np.array(mat)
|
|
||||||
prepared_paths = [s @ mat_np.T for s in paths]
|
|
||||||
else:
|
|
||||||
prepared_paths = paths
|
|
||||||
|
|
||||||
all_buffers: list[SlicePaths] = []
|
all_buffers: list[SlicePaths] = []
|
||||||
|
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
dist = base_distance + (i * width_step)
|
dist = base_distance + (i * width_step)
|
||||||
res_paths, res_groups = slice.buffer_slice(prepared_paths, dist, miter=self.shape_option)
|
all_buffers.append(paths.buffer(dist, miter=self.shape_option, rotation=rotation))
|
||||||
all_buffers.append(SlicePaths(res_paths, res_groups))
|
|
||||||
|
|
||||||
# Zip Logic: Interleave paths by group (Z-layer)
|
# Zip Logic: Interleave paths by group (Z-layer)
|
||||||
all_groups = set()
|
all_groups = set()
|
||||||
|
|
@ -511,13 +505,7 @@ class SLICENODE_BufferShellsMultiple(SliceNode):
|
||||||
for p in group_paths:
|
for p in group_paths:
|
||||||
merged.append_with_group(p, g)
|
merged.append_with_group(p, g)
|
||||||
|
|
||||||
if any(rotation):
|
return paths.copy_with(merged, merged.groups)
|
||||||
mat_inv = Euler(rotation).to_matrix()
|
|
||||||
mat_inv_np = np.array(mat_inv)
|
|
||||||
final_paths = [s @ mat_inv_np.T for s in merged]
|
|
||||||
return SlicePaths(final_paths, merged.groups)
|
|
||||||
|
|
||||||
return merged
|
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_Infill(SliceNode):
|
class SLICENODE_Infill(SliceNode):
|
||||||
|
|
@ -554,32 +542,13 @@ class SLICENODE_Infill(SliceNode):
|
||||||
|
|
||||||
if not paths: return SlicePaths()
|
if not paths: return SlicePaths()
|
||||||
|
|
||||||
p: SlicePaths
|
return paths.infill(
|
||||||
if any(rotation):
|
|
||||||
# De-rotate shells to Z-perpendicular plane
|
|
||||||
mat = Euler(rotation).to_matrix().inverted()
|
|
||||||
mat_np = np.array(mat)
|
|
||||||
p = SlicePaths([s @ mat_np.T for s in paths], paths.groups)
|
|
||||||
else:
|
|
||||||
p = paths
|
|
||||||
|
|
||||||
res_paths, res_groups = slice.infill_slice(
|
|
||||||
p,
|
|
||||||
density,
|
density,
|
||||||
rotation_deg=infill_rotation,
|
rotation_deg=infill_rotation,
|
||||||
infill_type=self.infill_type # pyright: ignore[reportOptionalMemberAccess]
|
infill_type=self.infill_type, # pyright: ignore[reportOptionalMemberAccess]
|
||||||
|
layer_rotation=rotation
|
||||||
)
|
)
|
||||||
|
|
||||||
if any(rotation):
|
|
||||||
# Re-rotate shells back
|
|
||||||
mat_inv = Euler(rotation).to_matrix()
|
|
||||||
mat_inv_np = np.array(mat_inv)
|
|
||||||
p = SlicePaths([s @ mat_inv_np.T for s in res_paths], res_groups)
|
|
||||||
else:
|
|
||||||
p = SlicePaths(res_paths, res_groups)
|
|
||||||
|
|
||||||
return p
|
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_PathsToGcode(SliceNode):
|
class SLICENODE_PathsToGcode(SliceNode):
|
||||||
bl_label = "Paths to Gcode"
|
bl_label = "Paths to Gcode"
|
||||||
|
|
@ -644,6 +613,31 @@ class SLICENODE_AssignMetadata(SliceNode):
|
||||||
lines.append(f'; printer_model = {printer}')
|
lines.append(f'; printer_model = {printer}')
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
@register_class
|
||||||
|
class SLICENODE_GcodeRegexReplace(SliceNode):
|
||||||
|
bl_label = "Gcode Regex Replace"
|
||||||
|
|
||||||
|
def init(self, context):
|
||||||
|
self.add_input("SLICESOCK_Gcode", "Gcode")
|
||||||
|
self.add_input("SLICESOCK_String", "Find")
|
||||||
|
self.add_input("SLICESOCK_String", "Replace")
|
||||||
|
self.add_output("SLICESOCK_GcodeRo", "Gcode")
|
||||||
|
|
||||||
|
def evaluate_output(self, socket_name: str, **_kwargs) -> str:
|
||||||
|
import re
|
||||||
|
gcode = self.resolve("Gcode") or ""
|
||||||
|
find = self.resolve("Find") or ""
|
||||||
|
replace = self.resolve("Replace") or ""
|
||||||
|
|
||||||
|
if not find:
|
||||||
|
return gcode
|
||||||
|
|
||||||
|
try:
|
||||||
|
return re.sub(find, replace, gcode)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Regex error in node {self.name}: {e}")
|
||||||
|
return gcode
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_GcodeHelper(SliceNode):
|
class SLICENODE_GcodeHelper(SliceNode):
|
||||||
bl_label = "Gcode Helper"
|
bl_label = "Gcode Helper"
|
||||||
|
|
@ -771,14 +765,11 @@ class SLICENODE_JoinSlices(SliceNodeJoiner):
|
||||||
|
|
||||||
if not accumulated:
|
if not accumulated:
|
||||||
accumulated = current
|
accumulated = current
|
||||||
current = SlicePaths()
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Boolean operation loses specific per-segment grouping as it merges polygons.
|
# Boolean operation loses specific per-segment grouping as it merges polygons.
|
||||||
# We return a new SlicePaths from the result.
|
# We return a new SlicePaths from the result.
|
||||||
res = slice.boolean_slice(accumulated, current, self.operation)
|
accumulated = accumulated.boolean(current, self.operation)
|
||||||
accumulated = SlicePaths(res)
|
|
||||||
current = SlicePaths()
|
|
||||||
|
|
||||||
return accumulated
|
return accumulated
|
||||||
|
|
||||||
|
|
@ -1696,7 +1687,11 @@ class SLICENODE_Executor(ExecSliceNode, SliceNodeJoiner):
|
||||||
layout.prop(self, "auto_refresh")
|
layout.prop(self, "auto_refresh")
|
||||||
|
|
||||||
def evaluate(self, operator=None):
|
def evaluate(self, operator=None):
|
||||||
from ...infra.blender.blender_slice_nodes_generic import node_execution_feedback
|
from ...infra.blender.blender_slice_nodes_generic import node_execution_feedback, feedback_disabled, execution_cache
|
||||||
|
|
||||||
|
# If auto_refresh is on, we don't want highlighting/redraws for upstream nodes either
|
||||||
|
maybe_disabled = feedback_disabled if self.auto_refresh else lambda: execution_cache()
|
||||||
|
|
||||||
for i, job in enumerate(self.inputs):
|
for i, job in enumerate(self.inputs):
|
||||||
# Resolve the input to get the connected node(s)
|
# Resolve the input to get the connected node(s)
|
||||||
res = resolve_input(job)
|
res = resolve_input(job)
|
||||||
|
|
@ -1714,6 +1709,7 @@ class SLICENODE_Executor(ExecSliceNode, SliceNodeJoiner):
|
||||||
operator.report({'INFO'}, f"Executing: {upstream_node.bl_label}")
|
operator.report({'INFO'}, f"Executing: {upstream_node.bl_label}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
with maybe_disabled():
|
||||||
with node_execution_feedback(upstream_node):
|
with node_execution_feedback(upstream_node):
|
||||||
exec_res = upstream_node.evaluate(operator=operator)
|
exec_res = upstream_node.evaluate(operator=operator)
|
||||||
if exec_res != 'ok' and exec_res is not None:
|
if exec_res != 'ok' and exec_res is not None:
|
||||||
|
|
|
||||||
|
|
@ -100,13 +100,25 @@ class SLICESOCK_VectorRotation_Common(InputNodeSocket):
|
||||||
bl_label = "VectorRotation"
|
bl_label = "VectorRotation"
|
||||||
|
|
||||||
value: bpy.props.FloatVectorProperty(name="Vector", size=3, default=(0.0, 0.0, 0.0), subtype='EULER') # pyright: ignore[reportInvalidTypeForm]
|
value: bpy.props.FloatVectorProperty(name="Vector", size=3, default=(0.0, 0.0, 0.0), subtype='EULER') # pyright: ignore[reportInvalidTypeForm]
|
||||||
bl_color = (0.39, 0.39, 0.78, 1.0)
|
bl_color = (166/255, 99/255, 199/255, 1.0)
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICESOCK_VectorRotation(SLICESOCK_VectorRotation_Common): ...
|
class SLICESOCK_VectorRotation(SLICESOCK_VectorRotation_Common): ...
|
||||||
@register_class
|
@register_class
|
||||||
class SLICESOCK_VectorRotationRo(ReadonlySocket, SLICESOCK_VectorRotation_Common): ...
|
class SLICESOCK_VectorRotationRo(ReadonlySocket, SLICESOCK_VectorRotation_Common): ...
|
||||||
|
|
||||||
|
@register_class
|
||||||
|
class SLICESOCK_Vector_Common(InputNodeSocket):
|
||||||
|
bl_label = "Vector"
|
||||||
|
|
||||||
|
value: bpy.props.FloatVectorProperty(name="Vector", size=3, default=(0.0, 0.0, 0.0)) # pyright: ignore[reportInvalidTypeForm]
|
||||||
|
bl_color = (0.39, 0.39, 0.78, 1.0)
|
||||||
|
|
||||||
|
@register_class
|
||||||
|
class SLICESOCK_Vector(SLICESOCK_Vector_Common): ...
|
||||||
|
@register_class
|
||||||
|
class SLICESOCK_VectorRo(ReadonlySocket, SLICESOCK_Vector_Common): ...
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICESOCK_Mesh(LabelNodeSocket):
|
class SLICESOCK_Mesh(LabelNodeSocket):
|
||||||
bl_label = "Mesh"
|
bl_label = "Mesh"
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,8 @@ def tree_update_handler(scene, depsgraph):
|
||||||
if should_refresh:
|
if should_refresh:
|
||||||
_is_updating = True
|
_is_updating = True
|
||||||
try:
|
try:
|
||||||
|
from ...infra.blender.blender_slice_nodes_generic import feedback_disabled
|
||||||
|
with feedback_disabled():
|
||||||
with node_execution_feedback(node):
|
with node_execution_feedback(node):
|
||||||
node.evaluate()
|
node.evaluate()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -155,6 +157,7 @@ class SLICENODE_MT_DataInput(Menu):
|
||||||
layout.operator("node.add_node", text="Float").type = "SLICENODE_InputFloat"
|
layout.operator("node.add_node", text="Float").type = "SLICENODE_InputFloat"
|
||||||
layout.operator("node.add_node", text="Integer").type = "SLICENODE_InputInt"
|
layout.operator("node.add_node", text="Integer").type = "SLICENODE_InputInt"
|
||||||
layout.operator("node.add_node", text="Rotation").type = "SLICENODE_InputVectorRotation"
|
layout.operator("node.add_node", text="Rotation").type = "SLICENODE_InputVectorRotation"
|
||||||
|
layout.operator("node.add_node", text="Vector").type = "SLICENODE_InputVector"
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator("node.add_node", text="Object").type = "SLICENODE_InputObject"
|
layout.operator("node.add_node", text="Object").type = "SLICENODE_InputObject"
|
||||||
layout.operator("node.add_node", text="Overrides").type = "SLICENODE_InputOverrides"
|
layout.operator("node.add_node", text="Overrides").type = "SLICENODE_InputOverrides"
|
||||||
|
|
@ -178,6 +181,7 @@ class SLICENODE_MT_Geometry(Menu):
|
||||||
layout.operator("node.add_node", text="Slice Shells").type = "SLICENODE_SliceShells"
|
layout.operator("node.add_node", text="Slice Shells").type = "SLICENODE_SliceShells"
|
||||||
layout.operator("node.add_node", text="Buffer Shells").type = "SLICENODE_BufferShells"
|
layout.operator("node.add_node", text="Buffer Shells").type = "SLICENODE_BufferShells"
|
||||||
layout.operator("node.add_node", text="Buffer Shells Multiple").type = "SLICENODE_BufferShellsMultiple"
|
layout.operator("node.add_node", text="Buffer Shells Multiple").type = "SLICENODE_BufferShellsMultiple"
|
||||||
|
layout.operator("node.add_node", text="Path Offset").type = "SLICENODE_PathOffset"
|
||||||
layout.operator("node.add_node", text="Infill").type = "SLICENODE_Infill"
|
layout.operator("node.add_node", text="Infill").type = "SLICENODE_Infill"
|
||||||
layout.operator("node.add_node", text="Boolean Paths").type = "SLICENODE_JoinSlices"
|
layout.operator("node.add_node", text="Boolean Paths").type = "SLICENODE_JoinSlices"
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
@ -194,6 +198,7 @@ class SLICENODE_MT_Gcode(Menu):
|
||||||
assert layout
|
assert layout
|
||||||
layout.operator("node.add_node", text="Paths to Gcode").type = "SLICENODE_PathsToGcode"
|
layout.operator("node.add_node", text="Paths to Gcode").type = "SLICENODE_PathsToGcode"
|
||||||
layout.operator("node.add_node", text="Gcode Block").type = "SLICENODE_GcodeBlock"
|
layout.operator("node.add_node", text="Gcode Block").type = "SLICENODE_GcodeBlock"
|
||||||
|
layout.operator("node.add_node", text="Gcode Regex Replace").type = "SLICENODE_GcodeRegexReplace"
|
||||||
layout.operator("node.add_node", text="Assign Metadata").type = "SLICENODE_AssignMetadata"
|
layout.operator("node.add_node", text="Assign Metadata").type = "SLICENODE_AssignMetadata"
|
||||||
layout.operator("node.add_node", text="Gcode Helper").type = "SLICENODE_GcodeHelper"
|
layout.operator("node.add_node", text="Gcode Helper").type = "SLICENODE_GcodeHelper"
|
||||||
layout.operator("node.add_node", text="Load Gcode").type = "SLICENODE_LoadGcode"
|
layout.operator("node.add_node", text="Load Gcode").type = "SLICENODE_LoadGcode"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,75 @@ class SlicePaths(list[np.ndarray]):
|
||||||
if groups: self.groups = list(groups)
|
if groups: self.groups = list(groups)
|
||||||
else: self.groups = list(range(0,len(paths)))
|
else: self.groups = list(range(0,len(paths)))
|
||||||
|
|
||||||
|
def copy_with(self, paths: list[np.ndarray], groups: list[int] | None = None) -> SlicePaths:
|
||||||
|
"""Returns a new SlicePaths object with new paths/groups but preserving all other metadata."""
|
||||||
|
new_obj = SlicePaths(paths, groups if groups is not None else self.groups)
|
||||||
|
# Copy any other attributes that might have been added
|
||||||
|
for k, v in self.__dict__.items():
|
||||||
|
if k != "groups":
|
||||||
|
setattr(new_obj, k, v)
|
||||||
|
return new_obj
|
||||||
|
|
||||||
|
def offset(self, offset_vec: np.ndarray) -> SlicePaths:
|
||||||
|
"""Returns a new SlicePaths object shifted by the given vector."""
|
||||||
|
return self.copy_with([p + offset_vec for p in self])
|
||||||
|
|
||||||
|
def transform(self, matrix: np.ndarray) -> SlicePaths:
|
||||||
|
"""Applies a transformation matrix to all paths."""
|
||||||
|
return self.copy_with([p @ matrix.T for p in self])
|
||||||
|
|
||||||
|
def buffer(self, distance: float, miter: str = 'round', rotation: Any = None) -> SlicePaths:
|
||||||
|
"""Buffers (offsets) the paths. Handles optional rotation for non-planar buffering."""
|
||||||
|
p = self
|
||||||
|
if rotation and any(rotation):
|
||||||
|
from mathutils import Euler
|
||||||
|
mat = Euler(rotation).to_matrix().inverted()
|
||||||
|
p = self.transform(np.array(mat))
|
||||||
|
|
||||||
|
res_paths, res_groups = buffer_slice(p, distance, miter=miter)
|
||||||
|
new_paths = SlicePaths(res_paths, res_groups)
|
||||||
|
|
||||||
|
# Copy other metadata from self
|
||||||
|
for k, v in self.__dict__.items():
|
||||||
|
if k != "groups":
|
||||||
|
setattr(new_paths, k, v)
|
||||||
|
|
||||||
|
if rotation and any(rotation):
|
||||||
|
from mathutils import Euler
|
||||||
|
mat_inv = Euler(rotation).to_matrix()
|
||||||
|
new_paths = new_paths.transform(np.array(mat_inv))
|
||||||
|
|
||||||
|
return new_paths
|
||||||
|
|
||||||
|
def infill(self, density: float, rotation_deg: float = 0.0, infill_type: str = 'GRID', layer_rotation: Any = None) -> SlicePaths:
|
||||||
|
"""Generates infill for the paths."""
|
||||||
|
p = self
|
||||||
|
if layer_rotation and any(layer_rotation):
|
||||||
|
from mathutils import Euler
|
||||||
|
mat = Euler(layer_rotation).to_matrix().inverted()
|
||||||
|
p = self.transform(np.array(mat))
|
||||||
|
|
||||||
|
res_paths, res_groups = infill_slice(p, density, rotation_deg=rotation_deg, infill_type=infill_type)
|
||||||
|
new_paths = SlicePaths(res_paths, res_groups)
|
||||||
|
|
||||||
|
# Copy other metadata from self
|
||||||
|
for k, v in self.__dict__.items():
|
||||||
|
if k != "groups":
|
||||||
|
setattr(new_paths, k, v)
|
||||||
|
|
||||||
|
if layer_rotation and any(layer_rotation):
|
||||||
|
from mathutils import Euler
|
||||||
|
mat_inv = Euler(layer_rotation).to_matrix()
|
||||||
|
new_paths = new_paths.transform(np.array(mat_inv))
|
||||||
|
|
||||||
|
return new_paths
|
||||||
|
|
||||||
|
def boolean(self, other: SlicePaths, operation: str = 'UNION') -> SlicePaths:
|
||||||
|
"""Performs a 2D boolean operation with another set of paths."""
|
||||||
|
res = boolean_slice(self, other, operation)
|
||||||
|
# Boolean operations merge paths across layers, so we don't preserve original grouping as precisely.
|
||||||
|
return self.copy_with(res)
|
||||||
|
|
||||||
def extend_with_groups(self, other: SlicePaths | list[np.ndarray]):
|
def extend_with_groups(self, other: SlicePaths | list[np.ndarray]):
|
||||||
if isinstance(other, SlicePaths):
|
if isinstance(other, SlicePaths):
|
||||||
self.extend(other)
|
self.extend(other)
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ class SliceNode(Node, AutoBlIdName):
|
||||||
## Evaluation helpers
|
## Evaluation helpers
|
||||||
|
|
||||||
_current_execution_cache: _EvalCache | None = None
|
_current_execution_cache: _EvalCache | None = None
|
||||||
|
_feedback_enabled: bool = True
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def execution_cache():
|
def execution_cache():
|
||||||
|
|
@ -100,8 +101,23 @@ def execution_cache():
|
||||||
finally:
|
finally:
|
||||||
_current_execution_cache = None
|
_current_execution_cache = None
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def feedback_disabled():
|
||||||
|
global _feedback_enabled
|
||||||
|
old = _feedback_enabled
|
||||||
|
_feedback_enabled = False
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
_feedback_enabled = old
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def node_execution_feedback(node: bpy.types.Node):
|
def node_execution_feedback(node: bpy.types.Node):
|
||||||
|
if not _feedback_enabled:
|
||||||
|
with execution_cache():
|
||||||
|
yield
|
||||||
|
return
|
||||||
|
|
||||||
# Save original color
|
# Save original color
|
||||||
old_use_color = node.use_custom_color
|
old_use_color = node.use_custom_color
|
||||||
old_color = node.color[:]
|
old_color = node.color[:]
|
||||||
|
|
@ -150,7 +166,7 @@ def resolve_input(
|
||||||
assert socket.node
|
assert socket.node
|
||||||
|
|
||||||
if cache is None:
|
if cache is None:
|
||||||
cache = getattr(socket.node, "_current_cache", _current_execution_cache)
|
cache = getattr(socket.node, "_current_cache", None) or _current_execution_cache
|
||||||
if visited is None:
|
if visited is None:
|
||||||
visited = getattr(socket.node, "_current_visited", None)
|
visited = getattr(socket.node, "_current_visited", None)
|
||||||
|
|
||||||
|
|
@ -222,7 +238,7 @@ def _resolve_output(
|
||||||
cache[key] = value
|
cache[key] = value
|
||||||
return value
|
return value
|
||||||
finally:
|
finally:
|
||||||
if hasattr(socket.node, "_current_cache"): del socket.node._current_cache
|
socket.node._current_cache = None # type: ignore
|
||||||
if hasattr(socket.node, "_current_visited"): del socket.node._current_visited
|
socket.node._current_visited = None # type: ignore
|
||||||
finally:
|
finally:
|
||||||
visited.remove(node_key)
|
visited.remove(node_key)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue