From a6f2e47884b92b4886141fc6d27d2bf57500a9f8 Mon Sep 17 00:00:00 2001 From: Nicolas Predella Date: Thu, 14 May 2026 15:19:16 +0300 Subject: [PATCH] executors --- core/nodeslicer/nodes.py | 63 ++++++++++++++++++++++++++++++++++++++ core/nodeslicer/sockets.py | 6 ++++ core/nodeslicer/tree.py | 2 ++ 3 files changed, 71 insertions(+) diff --git a/core/nodeslicer/nodes.py b/core/nodeslicer/nodes.py index ddfb925..fa2763d 100644 --- a/core/nodeslicer/nodes.py +++ b/core/nodeslicer/nodes.py @@ -676,6 +676,21 @@ class SLICENODE_JoinPaths(SliceNodeJoiner): return SlicePaths() +@register_class +class SLICENODE_JoinExecution(SliceNodeJoiner): + bl_label = "Join Execution" + socket_type = "SLICESOCK_ExecutionLink" + + def evaluate_output(self, socket_name: str, **_kwargs) -> list[ExecSliceNode]: + nodes: list[ExecSliceNode] = [] + for input in self.inputs: + res = resolve_input(input) + if isinstance(res, ExecSliceNode): + nodes.append(res) + elif isinstance(res, list): + nodes.extend(res) + return nodes + ### I/O @register_class @@ -698,10 +713,18 @@ class SLICENODE_LoadGcode(SliceNode): class ExecSliceNode(SliceNode): button_label: str = 'Execute' + def _init_exec(self): + self.add_output("SLICESOCK_ExecutionLink") + def draw_buttons(self, context, layout): assert layout layout.operator("slicenode.execute", text=self.button_label).node_name = self.name + def evaluate_output(self, socket_name: str, **_kwargs) -> Any: + if socket_name == "Execution Link": + return self + return None + @register_class class SLICENODE_PrinterList(SliceNode): bl_label = "Printer List" @@ -769,6 +792,7 @@ class SLICENODE_GcodeToFile(ExecSliceNode): button_label = "Generate File" def init(self, context): + self._init_exec() self.add_input("SLICESOCK_Gcode") self.add_input("SLICESOCK_FilePath", "Filename") @@ -790,6 +814,7 @@ class SLICENODE_StartPrint(ExecSliceNode): button_label = "Send to Printer" def init(self, context): + self._init_exec() self.add_input("SLICESOCK_Gcode") self.add_input("SLICESOCK_Printer") @@ -851,6 +876,7 @@ class SLICENODE_GcodeToMesh(ExecSliceNode): button_label = "Update Debug Mesh" def init(self, context): + self._init_exec() self.add_input("SLICESOCK_Gcode") def evaluate(self, operator=None): @@ -952,6 +978,42 @@ class SLICENODE_GcodeToMesh(ExecSliceNode): return 'ok' +@register_class +class SLICENODE_Executor(ExecSliceNode, SliceNodeJoiner): + bl_label = "Executor" + button_label = "Execute All" + socket_type = "SLICESOCK_ExecutionLink" + + def init(self, context): + self._init_exec() + + def evaluate(self, operator=None): + for i, job in enumerate(self.inputs): + # Resolve the input to get the connected node(s) + res = resolve_input(job) + if res is None: + continue + + # Ensure we have a list of jobs to process (JoinExecution returns a list) + jobs_to_run = res if isinstance(res, list) else [res] + + for upstream_node in jobs_to_run: + if not hasattr(upstream_node, "evaluate"): + continue + + if operator: + operator.report({'INFO'}, f"Executing: {upstream_node.bl_label}") + + try: + exec_res = upstream_node.evaluate(operator=operator) + if exec_res != 'ok' and exec_res is not None: + if operator: operator.report({'WARNING'}, f"Node {upstream_node.bl_label} returned {exec_res}") + except Exception as e: + if operator: operator.report({'ERROR'}, f"Failed executing {upstream_node.bl_label}: {str(e)}") + return 'error' + + return 'ok' + @register_class class SLICENODE_Test(ExecSliceNode): bl_label = "Test" @@ -959,6 +1021,7 @@ class SLICENODE_Test(ExecSliceNode): button_label = "Test" def init(self, context): + self._init_exec() self.add_input("SLICESOCK_Gcode") def evaluate(self, operator=None): diff --git a/core/nodeslicer/sockets.py b/core/nodeslicer/sockets.py index db2f895..845edfa 100644 --- a/core/nodeslicer/sockets.py +++ b/core/nodeslicer/sockets.py @@ -115,6 +115,12 @@ class SLICESOCK_Intrinsics(LabelNodeSocket): default = None color = (0.2, 0.2, 0.2, 1.0) +@register_class +class SLICESOCK_ExecutionLink(LabelNodeSocket): + bl_label = "Execution Link" + default = None + color = (0.5, 0.0, 0.5, 1.0) # Purple + @register_class class SLICESOCK_Printer(InputNodeSocket): bl_label = "Printer" diff --git a/core/nodeslicer/tree.py b/core/nodeslicer/tree.py index f9cd581..9ecb079 100644 --- a/core/nodeslicer/tree.py +++ b/core/nodeslicer/tree.py @@ -72,11 +72,13 @@ class SLICENODE_MT_Menu(Menu): layout.operator("node.add_node", text="Join Gcode").type = "SLICENODE_JoinGcode" layout.operator("node.add_node", text="Join Mesh").type = "SLICENODE_JoinMesh" layout.operator("node.add_node", text="Join Paths").type = "SLICENODE_JoinPaths" + layout.operator("node.add_node", text="Join Execution").type = "SLICENODE_JoinExecution" layout.operator("node.add_node", text="Boolean Paths").type = "SLICENODE_JoinSlices" layout.separator() layout.operator("node.add_node", text="Gcode to File").type = "SLICENODE_GcodeToFile" layout.operator("node.add_node", text="Start Print").type = "SLICENODE_StartPrint" layout.operator("node.add_node", text="Gcode to Mesh").type = "SLICENODE_GcodeToMesh" + layout.operator("node.add_node", text="Executor").type = "SLICENODE_Executor" def draw_add_menu(self, context): space = context.space_data