diff --git a/README.md b/README.md index 5ceb325..475507c 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ NodeSlicer is a high-performance Blender extension that provides a custom node-b * Add internal structure with the **Infill** node. * Combine or modify paths using **Join Paths** or **Join Slices**. 5. **Generate**: Convert paths to G-code using **Paths to Gcode**. -6. **Export & Preview**: Use **Gcode To File** to save the result, and **Gcode to Mesh** to visualize the final toolpaths in the viewport. +6. **Export & Preview**: Use **Gcode To File** to save the result, and **Gcode Preview** to visualize the final toolpaths in the viewport. ## Documentation diff --git a/core/nodeslicer/nodes.py b/core/nodeslicer/nodes.py index 4e81f93..d03ffc8 100644 --- a/core/nodeslicer/nodes.py +++ b/core/nodeslicer/nodes.py @@ -8,6 +8,7 @@ from math import floor from pathlib import Path from typing import Any, TypeAlias import bpy +from bpy.props import BoolProperty import numpy as np from mathutils import Euler from .bpy_ns_types import NfStringProperty, NfEnumProperty, NfBoolProperty @@ -1147,7 +1148,7 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode): bl_label = "PrusaSlicer Slice" button_label = "Slice with PrusaSlicer" - prusaslicer_executable: NfStringProperty(name="PrusaSlicer Path", subtype='FILE_PATH') # pyright: ignore[reportInvalidTypeForm] + prusaslicer_executable: NfStringProperty(name="PrusaSlicer Path", subtype='FILE_PATH', default='flatpak run com.prusa3d.PrusaSlicer') # pyright: ignore[reportInvalidTypeForm] gcode_result: NfStringProperty(name="Gcode Result", default="") # pyright: ignore[reportInvalidTypeForm] def init(self, context): @@ -1293,15 +1294,20 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode): @register_class class SLICENODE_GcodeToMesh(ExecSliceNode): - bl_label = "Gcode to Mesh" + bl_label = "Gcode Preview" - button_label = "Update Debug Mesh" + button_label = "Update Preview" + show_e_0: NfBoolProperty(name="Show Zero Extrusions", default=False) # pyright: ignore[reportInvalidTypeForm] def init(self, context): self._init_exec() self.add_input("SLICESOCK_Gcode", "Gcode") self.add_input("SLICESOCK_String", "Name") + def draw_buttons(self, context, layout): + super().draw_buttons(context, layout) + layout.prop(self, 'show_e_0') + def evaluate(self, operator=None): gcode: str = self.resolve("Gcode") mesh_name: str = self.resolve("Name") @@ -1352,7 +1358,11 @@ class SLICENODE_GcodeToMesh(ExecSliceNode): new_z = params.get('Z', last_z) new_e = params.get('E', last_e) - if cmd == 'G1': + show = False + if self.show_e_0: show = True + if cmd == 'G1' and new_e > 0: show = True + + if show: # Subtract offsets (scaled to Blender units) to return to original space ox, oy = offset_x * 0.001, offset_y * 0.001 segments.append(( diff --git a/core/nodeslicer/tree.py b/core/nodeslicer/tree.py index 5c7e0e7..4f93362 100644 --- a/core/nodeslicer/tree.py +++ b/core/nodeslicer/tree.py @@ -185,7 +185,7 @@ class SLICENODE_MT_Menu(Menu): layout.operator("node.add_node", text="Gcode to File").type = "SLICENODE_GcodeToFile" layout.operator("node.add_node", text="Gcode to Text Block").type = "SLICENODE_GcodeToTextBlock" 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="Gcode Preview").type = "SLICENODE_GcodeToMesh" layout.operator("node.add_node", text="PrusaSlicer Slice").type = "SLICENODE_PrusaslicerSlice" layout.operator("node.add_node", text="Executor").type = "SLICENODE_Executor" diff --git a/doc/NODES.md b/doc/NODES.md index 73afd8d..318ae66 100644 --- a/doc/NODES.md +++ b/doc/NODES.md @@ -80,5 +80,5 @@ All nodes are found in the **Add (Shift+A)** menu under the **SliceNodes** categ - **Config**: PrusaSlicer configuration (from the **PrusaSlicer Config** node). - **Gcode**: Output socket providing the generated G-code string. - **Gcode to Text Block**: Creates a new Blender text block containing the G-code and opens it in any active text editors. -- **Gcode to Mesh**: Decodes G-code and creates a Blender mesh ("Debug" object) for visualization. +- **Gcode Preview**: Decodes G-code and creates a Blender mesh ("Debug" object) for visualization. - **Test**: Triggers evaluation for debugging purposes. diff --git a/doc/USER_GUIDE.md b/doc/USER_GUIDE.md index a9dde3b..12fcb37 100644 --- a/doc/USER_GUIDE.md +++ b/doc/USER_GUIDE.md @@ -33,13 +33,11 @@ Follow these steps to generate G-code for a simple object and preview it: * This node generates the raw G-code text. ### Step 4: Preview the Result -* Add a **Gcode to Mesh** node. +* Add a **Gcode Preview** node. * Connect the Gcode output to it. * Click the **Update Debug Mesh** button on the node. * A new object named **Debug** will appear in your scene, showing the toolpaths. -> **Pro Tip**: If your file contains a Geometry Nodes group called "Nonplanar Slicing Preview", it will be automatically assigned to the Debug object for a high-quality visualization. - --- ## 3. Adding Perimeters and Infill diff --git a/ui/panels.py b/ui/panels.py index 0ce6713..159b550 100644 --- a/ui/panels.py +++ b/ui/panels.py @@ -27,5 +27,6 @@ class SlicerObjectPanel(Panel, DrawCollectionMixin): layout.prop(pg, "object_type", text="Object type") layout.prop(pg, "extruder", text="Extruder") + layout.label(text="Modifiers:") if pg.object_type in ['ParameterModifier', 'ModelPart']: self.draw_collection(pg.modifiers, layout)