better preview

This commit is contained in:
Nicolas Predella 2026-05-18 12:45:46 +03:00
parent 8ec3ae38fa
commit 3c6a88667e
6 changed files with 19 additions and 10 deletions

View file

@ -35,7 +35,7 @@ NodeSlicer is a high-performance Blender extension that provides a custom node-b
* Add internal structure with the **Infill** node. * Add internal structure with the **Infill** node.
* Combine or modify paths using **Join Paths** or **Join Slices**. * Combine or modify paths using **Join Paths** or **Join Slices**.
5. **Generate**: Convert paths to G-code using **Paths to Gcode**. 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 ## Documentation

View file

@ -8,6 +8,7 @@ from math import floor
from pathlib import Path from pathlib import Path
from typing import Any, TypeAlias from typing import Any, TypeAlias
import bpy import bpy
from bpy.props import BoolProperty
import numpy as np import numpy as np
from mathutils import Euler from mathutils import Euler
from .bpy_ns_types import NfStringProperty, NfEnumProperty, NfBoolProperty from .bpy_ns_types import NfStringProperty, NfEnumProperty, NfBoolProperty
@ -1147,7 +1148,7 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode):
bl_label = "PrusaSlicer Slice" bl_label = "PrusaSlicer Slice"
button_label = "Slice with PrusaSlicer" 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] gcode_result: NfStringProperty(name="Gcode Result", default="") # pyright: ignore[reportInvalidTypeForm]
def init(self, context): def init(self, context):
@ -1293,15 +1294,20 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode):
@register_class @register_class
class SLICENODE_GcodeToMesh(ExecSliceNode): 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): def init(self, context):
self._init_exec() self._init_exec()
self.add_input("SLICESOCK_Gcode", "Gcode") self.add_input("SLICESOCK_Gcode", "Gcode")
self.add_input("SLICESOCK_String", "Name") 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): def evaluate(self, operator=None):
gcode: str = self.resolve("Gcode") gcode: str = self.resolve("Gcode")
mesh_name: str = self.resolve("Name") mesh_name: str = self.resolve("Name")
@ -1352,7 +1358,11 @@ class SLICENODE_GcodeToMesh(ExecSliceNode):
new_z = params.get('Z', last_z) new_z = params.get('Z', last_z)
new_e = params.get('E', last_e) 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 # Subtract offsets (scaled to Blender units) to return to original space
ox, oy = offset_x * 0.001, offset_y * 0.001 ox, oy = offset_x * 0.001, offset_y * 0.001
segments.append(( segments.append((

View file

@ -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 File").type = "SLICENODE_GcodeToFile"
layout.operator("node.add_node", text="Gcode to Text Block").type = "SLICENODE_GcodeToTextBlock" 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="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="PrusaSlicer Slice").type = "SLICENODE_PrusaslicerSlice"
layout.operator("node.add_node", text="Executor").type = "SLICENODE_Executor" layout.operator("node.add_node", text="Executor").type = "SLICENODE_Executor"

View file

@ -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). - **Config**: PrusaSlicer configuration (from the **PrusaSlicer Config** node).
- **Gcode**: Output socket providing the generated G-code string. - **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 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. - **Test**: Triggers evaluation for debugging purposes.

View file

@ -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. * This node generates the raw G-code text.
### Step 4: Preview the Result ### Step 4: Preview the Result
* Add a **Gcode to Mesh** node. * Add a **Gcode Preview** node.
* Connect the Gcode output to it. * Connect the Gcode output to it.
* Click the **Update Debug Mesh** button on the node. * Click the **Update Debug Mesh** button on the node.
* A new object named **Debug** will appear in your scene, showing the toolpaths. * 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 ## 3. Adding Perimeters and Infill

View file

@ -27,5 +27,6 @@ class SlicerObjectPanel(Panel, DrawCollectionMixin):
layout.prop(pg, "object_type", text="Object type") layout.prop(pg, "object_type", text="Object type")
layout.prop(pg, "extruder", text="Extruder") layout.prop(pg, "extruder", text="Extruder")
layout.label(text="Modifiers:")
if pg.object_type in ['ParameterModifier', 'ModelPart']: if pg.object_type in ['ParameterModifier', 'ModelPart']:
self.draw_collection(pg.modifiers, layout) self.draw_collection(pg.modifiers, layout)