preview
This commit is contained in:
parent
a476d9fb33
commit
51d8aac2c4
3 changed files with 72 additions and 0 deletions
|
|
@ -1455,6 +1455,74 @@ class SLICENODE_PrusaslicerSlice(SliceNode):
|
||||||
|
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
|
@register_class
|
||||||
|
class SLICENODE_PrusaslicerPreview(ExecSliceNode):
|
||||||
|
bl_label = "PrusaSlicer Preview"
|
||||||
|
button_label = "Open Preview"
|
||||||
|
|
||||||
|
prusaslicer_executable: NfStringProperty(
|
||||||
|
name="PrusaSlicer Path",
|
||||||
|
subtype='FILE_PATH',
|
||||||
|
default='flatpak run com.prusa3d.PrusaSlicer'
|
||||||
|
) # pyright: ignore[reportInvalidTypeForm]
|
||||||
|
|
||||||
|
def init(self, context):
|
||||||
|
self._init_exec()
|
||||||
|
self.add_input("SLICESOCK_Gcode", "Gcode")
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
super().draw_buttons(context, layout)
|
||||||
|
layout.prop(self, "prusaslicer_executable")
|
||||||
|
|
||||||
|
def evaluate(self, operator=None):
|
||||||
|
gcode: str = self.resolve("Gcode")
|
||||||
|
if not gcode:
|
||||||
|
if operator: operator.report({'ERROR'}, "No Gcode to preview")
|
||||||
|
return 'no gcode'
|
||||||
|
|
||||||
|
exe_str = self.prusaslicer_executable
|
||||||
|
if not exe_str:
|
||||||
|
if operator: operator.report({'ERROR'}, "PrusaSlicer executable path is empty")
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
# Parse command (handles multi-word commands like flatpak)
|
||||||
|
cmd_parts = shlex.split(exe_str)
|
||||||
|
if not cmd_parts:
|
||||||
|
if operator: operator.report({'ERROR'}, "Invalid PrusaSlicer command")
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
# Try to resolve the first part as a path if it's not a command in PATH
|
||||||
|
if not shutil.which(cmd_parts[0]):
|
||||||
|
abs_path = bpy.path.abspath(cmd_parts[0])
|
||||||
|
if os.path.exists(abs_path):
|
||||||
|
cmd_parts[0] = abs_path
|
||||||
|
|
||||||
|
# Final check if command exists
|
||||||
|
if not shutil.which(cmd_parts[0]):
|
||||||
|
if operator: operator.report({'ERROR'}, f"Command or executable not found: {cmd_parts[0]}")
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
# Write to temp file
|
||||||
|
# We use a named temporary file that stays around for a bit.
|
||||||
|
# PrusaSlicer needs the file to exist when it starts.
|
||||||
|
fd, temp_path = tempfile.mkstemp(suffix='.gcode')
|
||||||
|
try:
|
||||||
|
with os.fdopen(fd, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(gcode)
|
||||||
|
|
||||||
|
cmd = cmd_parts + ["--gcodeviewer", temp_path]
|
||||||
|
|
||||||
|
# Use Popen to not block Blender
|
||||||
|
subprocess.Popen(cmd)
|
||||||
|
|
||||||
|
if operator:
|
||||||
|
operator.report({'INFO'}, f"PrusaSlicer Preview launched")
|
||||||
|
except Exception as e:
|
||||||
|
if operator: operator.report({'ERROR'}, f"Failed to launch preview: {str(e)}")
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
return 'ok'
|
||||||
|
|
||||||
@register_class
|
@register_class
|
||||||
class SLICENODE_GcodeToMesh(ExecSliceNode):
|
class SLICENODE_GcodeToMesh(ExecSliceNode):
|
||||||
bl_label = "Gcode Preview"
|
bl_label = "Gcode Preview"
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,7 @@ class SLICENODE_MT_ActionIO(Menu):
|
||||||
layout.operator("node.add_node", text="Airtable Submit").type = "SLICENODE_AirtableSubmit"
|
layout.operator("node.add_node", text="Airtable Submit").type = "SLICENODE_AirtableSubmit"
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator("node.add_node", text="Gcode Preview").type = "SLICENODE_GcodeToMesh"
|
layout.operator("node.add_node", text="Gcode Preview").type = "SLICENODE_GcodeToMesh"
|
||||||
|
layout.operator("node.add_node", text="PrusaSlicer Preview").type = "SLICENODE_PrusaslicerPreview"
|
||||||
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"
|
||||||
layout.operator("node.add_node", text="Test").type = "SLICENODE_Test"
|
layout.operator("node.add_node", text="Test").type = "SLICENODE_Test"
|
||||||
|
|
|
||||||
|
|
@ -94,4 +94,7 @@ All nodes are found in the **Add (Shift+A)** menu under the **SliceNodes** categ
|
||||||
- **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 Preview**: 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.
|
||||||
|
- **PrusaSlicer Preview**: Launches PrusaSlicer's built-in G-code viewer to visualize a G-code string.
|
||||||
|
- **Executable**: Path to the PrusaSlicer executable (default: `flatpak run com.prusa3d.PrusaSlicer`).
|
||||||
|
- **Gcode**: Input socket for the G-code string to preview.
|
||||||
- **Test**: Triggers evaluation for debugging purposes.
|
- **Test**: Triggers evaluation for debugging purposes.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue