keep only first name

This commit is contained in:
Nicolas Predella 2026-09-27 18:22:00 +03:00
parent c0b71ab16b
commit 7a8506e34c
6 changed files with 63 additions and 18 deletions

View file

@ -593,7 +593,7 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
out_dir = folder_path if folder_path.suffix == "" else folder_path.parent
os.makedirs(out_dir, exist_ok=True)
if isinstance(target_item, SlicingGroup) and target_item.collections:
raw_name = "_".join(target_item.collections.keys())
raw_name = next(iter(target_item.collections.keys()))
elif hasattr(target_item, 'name') and getattr(target_item, 'name'):
raw_name = str(getattr(target_item, 'name'))
else:

View file

@ -188,7 +188,7 @@ class SLICENODE_SliceShells(SliceNode):
names.append(str(getattr(coll, "name")))
if names:
slices.name = "-".join(names)
slices.name = names[0]
slices.objects_info = {"objects": [{"name": n, "polygon": []} for n in names]}
if len(z_values) > 0 and fl_height is not None and layer_height > 0:

View file

@ -392,7 +392,7 @@ class SlicePaths(list[np.ndarray]):
merged.transforms = [dict(t) for t in getattr(base, "transforms", [])]
if merged_objs:
merged.objects_info = {"objects": merged_objs}
merged.name = "-".join(merged_names)
merged.name = merged_names[0] if merged_names else ""
return merged
@ -1233,7 +1233,7 @@ def boolean_slice(subject: SlicePaths, object: SlicePaths, operation: str = 'UNI
results.transforms = [dict(t) for t in subj_trans] if subj_trans else ([dict(t) for t in obj_trans] if obj_trans else [])
if merged_objs:
results.objects_info = {"objects": merged_objs}
results.name = "-".join(merged_names)
results.name = merged_names[0] if merged_names else ""
return results
@ -1361,7 +1361,7 @@ def minimum_coverage_slice(
results.transforms = [dict(t) for t in getattr(primary, "transforms", [])]
if merged_objs:
results.objects_info = {"objects": merged_objs}
results.name = "-".join(merged_names)
results.name = merged_names[0] if merged_names else ""
return results
@ -1429,6 +1429,8 @@ def maximum_coverage_slice(
setattr(results, attr, copy.deepcopy(val) if isinstance(val, (list, dict)) else val)
results.transforms = [dict(t) for t in getattr(sp, "transforms", [])]
results.name = getattr(sp, "name", "")
results.objects_info = copy.deepcopy(getattr(sp, "objects_info", None))
return results
# Multiple inputs: sequentially union all inputs with boolean_slice

View file

@ -136,7 +136,7 @@ class SlicingObject():
if not objects: return merged
# Take metadata from first object if available
merged.name = objects[0].name + "_merged"
merged.name = objects[0].name if objects else ""
merged.parent = objects[0].parent
merged.pdf_properties = copy.deepcopy(objects[0].pdf_properties) if hasattr(objects[0], "pdf_properties") and objects[0].pdf_properties else PdfProperties()
merged.pdf_object_properties = list(getattr(objects[0], "pdf_object_properties", []))

View file

@ -54,11 +54,11 @@ def get_gcode_name_from_metadata(gcode: str, default: str = "output") -> str:
if parts_match:
try:
gcode_info = json.loads(parts_match.group(1))
names: list[str] = [str(v['name'].split(" id:")[0]) for v in gcode_info['objects']]
counts = Counter(names)
object_names = "-".join(f"{c}x{n}" if c > 1 else n for n, c in counts.items())
parts = [object_names, filament, printer]
return "-".join([str(p) for p in parts if p])
names: list[str] = [str(v['name'].split(" id:")[0]) for v in gcode_info.get('objects', []) if v.get('name')]
if names:
object_names = names[0]
parts = [object_names, filament, printer]
return "-".join([str(p) for p in parts if p])
except Exception:
pass
@ -67,8 +67,7 @@ def get_gcode_name_from_metadata(gcode: str, default: str = "output") -> str:
if obj_matches:
names = [m.strip().split(" id:")[0] for m in obj_matches if m.strip()]
if names:
counts = Counter(names)
object_names = "-".join(f"{c}x{n}" if c > 1 else n for n, c in counts.items())
object_names = names[0]
parts = [object_names, filament, printer]
return "-".join([str(p) for p in parts if p])

View file

@ -829,7 +829,7 @@ class TestSlice(unittest.TestCase):
gcode_multi = pather_multi.to_gcode(include_header=True)
self.assertIn("; objects_info =", gcode_multi)
name_multi = get_gcode_name_from_metadata(gcode_multi)
self.assertEqual(name_multi, "PartA-PartB")
self.assertEqual(name_multi, "PartA")
# 3. Test get_gcode_name_from_metadata fallback object comments
gcode_fallback = "; Generated Gcode\n; OBJECT_NAME = CustomBracket\nG1 X10 Y10\n"
@ -1529,13 +1529,11 @@ class TestSlice(unittest.TestCase):
sp2.transforms = [{"type": "transform", "translation": (0.0, 0.0, 0.0), "rotation": (0.0, 0.0, 0.0), "scale": (2.0, 2.0, 2.0)}]
merged_zip = SlicePaths.zip_paths([sp1, sp2])
self.assertIn("ObjectA", merged_zip.name)
self.assertIn("ObjectB", merged_zip.name)
self.assertEqual(merged_zip.name, "ObjectA")
self.assertEqual(len(merged_zip.transforms), 1)
merged_inter = SlicePaths.path_operations([sp1, sp2], operation='INTERSECTION')
self.assertIn("ObjectA", merged_inter.name)
self.assertIn("ObjectB", merged_inter.name)
self.assertEqual(merged_inter.name, "ObjectA")
self.assertEqual(len(merged_inter.transforms), 1)
def test_complex_donut_intersection_and_bullseye(self):
@ -1828,6 +1826,52 @@ class TestCodeReviewBugFixes(unittest.TestCase):
self.assertAlmostEqual(np.min(res[0][:, 0]), -1.0, places=2)
self.assertAlmostEqual(np.max(res[0][:, 0]), 21.0, places=2)
def test_name_preservation_across_all_nodes_and_operations(self):
from NodeSlicer.core.nodeslicer.nodes.path import SLICENODE_SliceShells
from NodeSlicer.core.slice import SlicePaths, path_operations_slice
from NodeSlicer.infra.blender.blender_mesh_capture import SlicingCollection, SlicingObject
from NodeSlicer.infra.networking.gcode_utils import get_gcode_name_from_metadata
# 1. SlicingObject.merge
so1 = SlicingObject()
so1.name = "FirstMesh"
so1.mesh = np.zeros((1, 4, 3))
so2 = SlicingObject()
so2.name = "SecondMesh"
so2.mesh = np.zeros((1, 4, 3))
so_merged = SlicingObject.merge([so1, so2])
self.assertEqual(so_merged.name, "FirstMesh")
# 2. SLICENODE_SliceShells
coll = SlicingCollection([], "MyCollection")
coll.objects = [so1, so2]
node = SLICENODE_SliceShells()
resolve_map = {
"Mesh": coll,
"Layer Height": 0.2,
"First Layer Height": 0.2,
"Rotation": (0.0, 0.0, 0.0)
}
with patch.object(node, "resolve", side_effect=lambda name: resolve_map.get(name)):
with patch("NodeSlicer.core.nodeslicer.nodes.path.slice_at_range", return_value=[[np.array([[0, 0, 0.2], [10, 0, 0.2], [10, 10, 0.2], [0, 10, 0.2], [0, 0, 0.2]])]]):
slices = node.evaluate_output("Paths")
self.assertEqual(slices.name, "FirstMesh")
# 3. Path Operations (ZIP, EXTEND, MAX_COVERAGE, MIN_COVERAGE, INTERSECTION, SUBTRACT, XOR)
p1 = np.array([[0, 0, 0.2], [10, 0, 0.2], [10, 10, 0.2], [0, 10, 0.2], [0, 0, 0.2]])
p2 = np.array([[5, 0, 0.2], [15, 0, 0.2], [15, 10, 0.2], [5, 10, 0.2], [5, 0, 0.2]])
sp_a = SlicePaths([p1], groups=[0], name="Alpha")
sp_b = SlicePaths([p2], groups=[0], name="Beta")
for op in ['ZIP', 'EXTEND', 'MAX_COVERAGE', 'MIN_COVERAGE', 'INTERSECTION', 'SUBTRACT', 'XOR']:
res = path_operations_slice([sp_a, sp_b], operation=op)
self.assertEqual(res.name, "Alpha", f"Failed for operation {op}")
# 4. G-code name from metadata with multiple objects in objects_info
gc = '; objects_info = {"objects": [{"name": "BracketA", "polygon": []}, {"name": "BracketB", "polygon": []}]}\n; filament_type = PLA\n; printer_model = MK4\n'
gname = get_gcode_name_from_metadata(gc)
self.assertEqual(gname, "BracketA-PLA-MK4")
if __name__ == '__main__':
unittest.main()