flattening in join

This commit is contained in:
Nicolas Predella 2026-10-13 16:22:23 +03:00
parent 47e66bb030
commit c5c8df0973
2 changed files with 76 additions and 2 deletions

View file

@ -164,6 +164,8 @@ class SliceNodeListJoiner(SliceNode):
def evaluate_output(self, socket_name: str, **kwargs) -> list[Any]: def evaluate_output(self, socket_name: str, **kwargs) -> list[Any]:
from ....infra.blender.list_utils import flatten_list, is_list_data from ....infra.blender.list_utils import flatten_list, is_list_data
items: list[Any] = [] items: list[Any] = []
if "resolve_multi_input" in self.__dict__:
raw_inputs = self.resolve_multi_input(self.socket_label) raw_inputs = self.resolve_multi_input(self.socket_label)
for val in raw_inputs: for val in raw_inputs:
if val is not None: if val is not None:
@ -173,6 +175,45 @@ class SliceNodeListJoiner(SliceNode):
items.append(val) items.append(val)
return items return items
target_inputs = [
i for i in getattr(self, "inputs", [])
if getattr(i, "name", "") == self.socket_label or getattr(i, "identifier", "").startswith(f"{self.socket_label}_ms_in_")
]
if not target_inputs:
raw_inputs = self.resolve_multi_input(self.socket_label)
for val in raw_inputs:
if val is not None:
if is_list_data(val):
items.extend(flatten_list(val))
else:
items.append(val)
return items
cache = getattr(self, "_current_cache", None)
visited = getattr(self, "_current_visited", None)
from ....infra.blender.blender_slice_nodes_generic import resolve_input
for inp in target_inputs:
if not getattr(inp, "is_linked", False):
val = getattr(inp, "value", None)
if val is None or val == "":
val = getattr(inp, "default_value", None)
if val is None or val == "":
continue
if type(val).__name__ == "SlicePaths" and len(val) == 0:
continue
else:
val = resolve_input(inp, cache=cache, visited=visited, fieldname=self.socket_label, node=self)
if val is not None:
if is_list_data(val):
items.extend(flatten_list(val))
else:
items.append(val)
return items
class ExecSliceNode(SliceNode): class ExecSliceNode(SliceNode):
button_label: str = 'Execute' button_label: str = 'Execute'

View file

@ -383,6 +383,39 @@ class TestNodeEvaluationsWithLists(unittest.TestCase):
g_node.resolve_multi_input = lambda label: [["G1 X1"], "G1 X2"] g_node.resolve_multi_input = lambda label: [["G1 X1"], "G1 X2"]
self.assertEqual(g_node.evaluate_output("Gcode"), ["G1 X1", "G1 X2"]) self.assertEqual(g_node.evaluate_output("Gcode"), ["G1 X1", "G1 X2"])
def test_x_to_list_flattens_nested_and_incoming_lists(self):
from NodeSlicer.core.nodeslicer.nodes.inputs import SLICENODE_ObjectsToList
from NodeSlicer.core.nodeslicer.nodes.mesh import SLICENODE_MeshesToList
from NodeSlicer.core.nodeslicer.nodes.path import SLICENODE_PathsToList
from NodeSlicer.core.nodeslicer.nodes.gcode import SLICENODE_GcodesToList
# ObjectsToList with nested lists and single elements
obj1, obj2, obj3, obj4 = DummyObject("O1"), DummyObject("O2"), DummyObject("O3"), DummyObject("O4")
o_node = SLICENODE_ObjectsToList()
o_node.resolve_multi_input = lambda label: [[obj1, obj2], obj3, [obj4]]
self.assertEqual(o_node.evaluate_output("Objects"), [obj1, obj2, obj3, obj4])
# MeshesToList with nested lists
sc1 = SlicingCollection([], "M1")
sc2 = SlicingCollection([], "M2")
sc3 = SlicingCollection([], "M3")
m_node = SLICENODE_MeshesToList()
m_node.resolve_multi_input = lambda label: [[sc1, sc2], [sc3]]
self.assertEqual(m_node.evaluate_output("Meshes"), [sc1, sc2, sc3])
# PathsToList with list input and single input
sp1 = SlicePaths([np.array([[0, 0, 0], [1, 1, 0]], dtype=np.float64)])
sp2 = SlicePaths([np.array([[2, 2, 0], [3, 3, 0]], dtype=np.float64)])
sp3 = SlicePaths([np.array([[4, 4, 0], [5, 5, 0]], dtype=np.float64)])
p_node = SLICENODE_PathsToList()
p_node.resolve_multi_input = lambda label: [[sp1, sp2], sp3]
self.assertEqual(p_node.evaluate_output("Paths"), [sp1, sp2, sp3])
# GcodesToList with list input and single input
g_node = SLICENODE_GcodesToList()
g_node.resolve_multi_input = lambda label: [["G1 X1", "G1 X2"], "G1 X3", ["G1 X4", "G1 X5"]]
self.assertEqual(g_node.evaluate_output("Gcode"), ["G1 X1", "G1 X2", "G1 X3", "G1 X4", "G1 X5"])
def test_join_mesh_flattens_lists(self): def test_join_mesh_flattens_lists(self):
from NodeSlicer.core.nodeslicer.nodes.mesh import SLICENODE_JoinMesh from NodeSlicer.core.nodeslicer.nodes.mesh import SLICENODE_JoinMesh