From 4b75ecb80357f7cbc5fb3ab89245e18c74946dce Mon Sep 17 00:00:00 2001 From: Nicolas Predella Date: Thu, 30 Jul 2026 14:51:57 +0300 Subject: [PATCH] translation --- core/nodeslicer/nodes/mesh.py | 15 ++++++++++++++- core/nodeslicer/nodes/path.py | 1 + core/nodeslicer/nodes/preview.py | 12 ++---------- core/slice.py | 2 ++ doc/NODES.md | 6 ++++-- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/core/nodeslicer/nodes/mesh.py b/core/nodeslicer/nodes/mesh.py index 9b0c750..245866a 100644 --- a/core/nodeslicer/nodes/mesh.py +++ b/core/nodeslicer/nodes/mesh.py @@ -512,8 +512,21 @@ class SLICENODE_DropGeometry(SliceNode): self.add_input("SLICESOCK_Mesh", "Mesh") self.add_input("SLICESOCK_Float", "Z") self.add_output("SLICESOCK_Mesh", "Mesh") + self.add_output("SLICESOCK_VectorRo", "Translation") - def evaluate_output(self, socket_name: str, **_kwargs) -> SlicingCollection | SlicingGroup | None: + def evaluate_output(self, socket_name: str, **_kwargs) -> SlicingCollection | SlicingGroup | tuple[float, float, float] | None: + if socket_name == "Translation": + mesh_data: SlicingCollection | SlicingGroup | None = self.resolve("Mesh") + if not mesh_data: + return None + z = self.resolve('Z') + if z is None: + z = 0.0 + assert mesh_data.min_z is not None + min_z = round(mesh_data.min_z, 6) + offset_z = float(z - min_z) + return (0.0, 0.0, offset_z) + if socket_name != "Mesh": return None diff --git a/core/nodeslicer/nodes/path.py b/core/nodeslicer/nodes/path.py index 421dd6b..93a1bc6 100644 --- a/core/nodeslicer/nodes/path.py +++ b/core/nodeslicer/nodes/path.py @@ -342,6 +342,7 @@ class SLICENODE_Infill(SliceNode): items=[ ('GRID', "Grid", "Cross-hatch grid"), ('RECTILINEAR', "Rectilinear", "Alternating parallel lines"), + ('LINES', "Lines", "Parallel lines in one direction"), ], default='GRID', update=notify_tree_changed diff --git a/core/nodeslicer/nodes/preview.py b/core/nodeslicer/nodes/preview.py index ef2296e..0d54e98 100644 --- a/core/nodeslicer/nodes/preview.py +++ b/core/nodeslicer/nodes/preview.py @@ -314,17 +314,9 @@ class SLICENODE_GcodeToMesh(ExecSliceNode): if not base_mesh_name: base_mesh_name = "GcodePreview" - # Filter out empty inputs but keep structure to index properly - valid_gcodes = [g for g in gcodes if g] + for i, gcode in enumerate(gcodes): + if not gcode: continue - if not valid_gcodes: - if base_mesh_name in bpy.data.objects: - obj = bpy.data.objects[base_mesh_name] - if obj.type == 'MESH': - obj.data.clear_geometry() - return 'empty' - - for i, gcode in enumerate(valid_gcodes): mesh_name = base_mesh_name if i == 0 else f"{base_mesh_name}_{i+1}" try: self._process_gcode(gcode, mesh_name, operator) diff --git a/core/slice.py b/core/slice.py index fe6d6aa..2f0022a 100644 --- a/core/slice.py +++ b/core/slice.py @@ -1495,6 +1495,8 @@ def infill_slice(slice_paths: 'SlicePaths', density: float, rotation_deg: float current_grid_paths = vertical_lines + horizontal_lines elif infill_type == 'RECTILINEAR': current_grid_paths = vertical_lines if layer_idx % 2 == 0 else horizontal_lines + elif infill_type == 'LINES': + current_grid_paths = vertical_lines else: current_grid_paths = [] diff --git a/doc/NODES.md b/doc/NODES.md index 65f15a2..370b759 100644 --- a/doc/NODES.md +++ b/doc/NODES.md @@ -68,9 +68,11 @@ All nodes are found in the **Add (Shift+A)** menu under the **SliceNodes** categ - **Translation**: 3D vector specifying the translation offset. - **Rotation**: 3D vector/Euler rotation values. - **Scale**: 3D vector specifying scaling factors along the X, Y, and Z axes (defaults to `1.0, 1.0, 1.0`). -- **Drop Geometry**: Moves a `SlicingCollection` or `SlicingGroup` along Z so that its minimum Z sits at the specified value. +- **Drop Geometry**: Moves a `SlicingCollection` or `SlicingGroup` along Z so that its minimum Z sits at the specified value. Outputs both the dropped geometry and the translation vector. - **Mesh**: Input mesh data. - **Z**: Target minimum Z coordinate (defaults to `0.0`). + - **Mesh**: Output dropped mesh data. + - **Translation**: Output translation vector (X, Y, Z) applied to the geometry. - **Get Paths**: Extracts existing edges from a mesh as paths. - **Extrusion Multiplier Attribute**: Mesh attribute to use for per-segment extrusion rates. - **Feedrate Attribute**: Mesh attribute to use for per-segment feedrates. @@ -92,7 +94,7 @@ All nodes are found in the **Add (Shift+A)** menu under the **SliceNodes** categ - **Distance**: The offset distance (positive for left side, negative for right side). - **Rotation**: Optional Euler rotation for non-planar offsetting. - **Infill**: Generates a cross-hatch grid or parallel lines clipped by boundary paths. - - **Infill Type**: Switch between **Grid** (cross-hatch) and **Rectilinear** (alternating parallel lines). + - **Infill Type**: Switch between **Grid** (cross-hatch), **Rectilinear** (alternating parallel lines), and **Lines** (parallel lines in one direction). - **Density**: Distance between lines in units. - **Infill Rotation**: Base rotation of the infill pattern. - **Layer Rotation**: Rotation of the entire slice to align infill with specific planes.