overrides

This commit is contained in:
Nicolas Predella 2026-05-16 18:26:01 +03:00
parent 340f7a0612
commit d2bb1b5cb0
4 changed files with 105 additions and 3 deletions

View file

@ -1,16 +1,50 @@
import bpy import bpy
from bpy.props import PointerProperty, StringProperty, FloatProperty, IntProperty, EnumProperty, BoolProperty from bpy.props import PointerProperty, StringProperty, FloatProperty, IntProperty, EnumProperty, BoolProperty, CollectionProperty
from . import tree from . import tree
def notify_tree_changed(self, context): def notify_tree_changed(self, context):
from . import tree
tree._tree_changed = True tree._tree_changed = True
node = None node = None
socket = None
if isinstance(self, bpy.types.Node): if isinstance(self, bpy.types.Node):
node = self node = self
elif isinstance(self, bpy.types.NodeSocket): elif isinstance(self, bpy.types.NodeSocket):
socket = self
node = self.node node = self.node
elif isinstance(self, bpy.types.PropertyGroup):
try:
id_data = self.id_data
if isinstance(id_data, bpy.types.NodeTree):
path = self.path_from_id()
if ".inputs[" in path or ".outputs[" in path:
socket_path = path.split(".items[")[0] if ".items[" in path else path.rsplit(".", 1)[0]
resolved = id_data.path_resolve(socket_path)
if isinstance(resolved, bpy.types.NodeSocket):
socket = resolved
node = socket.node
else:
node_path = path.rsplit(".", 1)[0]
resolved = id_data.path_resolve(node_path)
if isinstance(resolved, bpy.types.Node):
node = resolved
except Exception:
pass
# Fallback to context
if node is None:
node = getattr(context, "node", None)
if socket is None:
socket = getattr(context, "socket", None)
if socket and hasattr(socket, "update"):
try:
socket.update() # pyright: ignore[reportAttributeAccessIssue]
except Exception as e:
print(f"Error updating socket: {e}")
if node and hasattr(node, "update"): if node and hasattr(node, "update"):
try: try:

View file

@ -68,6 +68,11 @@ class SLICENODE_InputObject(InputNode):
input_type = "Object" input_type = "Object"
bl_icon = "OBJECT_DATA" bl_icon = "OBJECT_DATA"
@register_class
class SLICENODE_InputOverrides(InputNode):
input_type = "Overrides"
bl_icon = "OBJECT_DATA"
@register_class @register_class
class SLICENODE_PrusaslicerConf(SliceNode): class SLICENODE_PrusaslicerConf(SliceNode):
bl_label = "PrusaSlicer Config" bl_label = "PrusaSlicer Config"
@ -1103,6 +1108,7 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode):
self._init_exec() self._init_exec()
self.add_input("SLICESOCK_Object", "Object") self.add_input("SLICESOCK_Object", "Object")
self.add_input("SLICESOCK_PrusaslicerConf", "Config") self.add_input("SLICESOCK_PrusaslicerConf", "Config")
self.add_input("SLICESOCK_Overrides", "Overrides")
self.add_output("SLICESOCK_GcodeRo") self.add_output("SLICESOCK_GcodeRo")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
@ -1117,6 +1123,7 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode):
def evaluate(self, operator=None): def evaluate(self, operator=None):
obj = resolve_input(self.inputs.get("Object")) obj = resolve_input(self.inputs.get("Object"))
conf_data = resolve_input(self.inputs.get("Config")) conf_data = resolve_input(self.inputs.get("Config"))
overrides = resolve_input(self.inputs.get("Overrides"))
if not obj: if not obj:
if operator: operator.report({'ERROR'}, "No Object connected") if operator: operator.report({'ERROR'}, "No Object connected")
@ -1153,12 +1160,17 @@ class SLICENODE_PrusaslicerSlice(ExecSliceNode):
offset = np.array([bed_center[0], bed_center[1], a_z]) - np.array([slicing_group.center_xy[0], slicing_group.center_xy[1], 0]) offset = np.array([bed_center[0], bed_center[1], a_z]) - np.array([slicing_group.center_xy[0], slicing_group.center_xy[1], 0])
slicing_group.offset(offset) slicing_group.offset(offset)
# Generate the ConfigWriter, forcing binary_gcode to 0 to ensure readable ASCII output # Prepare overrides for generate_conf_writer
# The format expected by generate_conf_writer is overrides={'key': {'value': 'val'}}
writer_overrides = {k: {'value': v} for k, v in overrides.items()}
writer_overrides['binary_gcode'] = {'value': '0'}
# Generate the ConfigWriter
conf_writer = cache.generate_conf_writer( conf_writer = cache.generate_conf_writer(
printer_id, printer_id,
filament_ids, filament_ids,
print_id, print_id,
overrides={'binary_gcode': {'value': '0'}} overrides=writer_overrides
) )
# Prepare 3mf path # Prepare 3mf path

View file

@ -1,6 +1,8 @@
from __future__ import annotations from __future__ import annotations
from typing import Any from typing import Any
import bpy import bpy
from bpy.props import CollectionProperty
from bpy.types import Property, PropertyGroup, bpy_struct
from .bpy_ns_types import NfStringProperty, NfFloatProperty, NfIntProperty, NfEnumProperty, NfPointerProperty from .bpy_ns_types import NfStringProperty, NfFloatProperty, NfIntProperty, NfEnumProperty, NfPointerProperty
from ...registry import register_class from ...registry import register_class
@ -129,6 +131,59 @@ class SLICESOCK_PrusaslicerConf(LabelNodeSocket):
default = None default = None
bl_color = (0.95, 0., 0., 1.0) # #F26C21 bl_color = (0.95, 0., 0., 1.0) # #F26C21
@register_class
class SLICENODE_OverrideItem(bpy.types.PropertyGroup):
field: NfStringProperty(name="Field", default="") # pyright: ignore[reportInvalidTypeForm]
value_str: NfStringProperty(name="Value", default="") # pyright: ignore[reportInvalidTypeForm]
@property
def is_active(self):
return bool(self.field) or bool(self.value_str)
@register_class
class SLICESOCK_Overrides(InputNodeSocket):
bl_label = "Overrides"
items: CollectionProperty(type=SLICENODE_OverrideItem) # pyright: ignore[reportInvalidTypeForm]
bl_color = (1.0, 1.0, 0.0, 1.0) # Yellow
def draw(self, context, layout, node, text):
if self.is_output or self.is_linked:
layout.label(text=text or self.name)
return
col = layout.column(align=True)
for item in self.items:
row = col.row(align=True)
row.prop(item, "field", text="")
row.prop(item, "value_str", text="")
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
if len(self.items) == 0:
self.items.add()
def update(self):
if self.items[-1].is_active:
self.items.add()
while len(self.items) >= 2:
if not self.items[-1].is_active and not self.items[-2].is_active:
self.items.remove(len(self.items) - 1)
else:
break
@property
def value(self) -> dict[str, str]:
overrides = {}
for item in self.items:
if item.field:
overrides[item.field] = item.value_str
return overrides
@register_class @register_class
class SLICESOCK_ExecutionLink(LabelNodeSocket): class SLICESOCK_ExecutionLink(LabelNodeSocket):
bl_label = "Execution Link" bl_label = "Execution Link"

View file

@ -141,6 +141,7 @@ class SLICENODE_MT_Menu(Menu):
layout.operator("node.add_node", text="Math").type = "SLICENODE_FloatMath" layout.operator("node.add_node", text="Math").type = "SLICENODE_FloatMath"
layout.operator("node.add_node", text="Integer Math").type = "SLICENODE_IntMath" layout.operator("node.add_node", text="Integer Math").type = "SLICENODE_IntMath"
layout.operator("node.add_node", text="Object").type = "SLICENODE_InputObject" layout.operator("node.add_node", text="Object").type = "SLICENODE_InputObject"
layout.operator("node.add_node", text="Overrides").type = "SLICENODE_InputOverrides"
layout.operator("node.add_node", text="Printer").type = "SLICENODE_InputPrinter" layout.operator("node.add_node", text="Printer").type = "SLICENODE_InputPrinter"
layout.operator("node.add_node", text="PrusaSlicer Config").type = "SLICENODE_PrusaslicerConf" layout.operator("node.add_node", text="PrusaSlicer Config").type = "SLICENODE_PrusaslicerConf"
layout.operator("node.add_node", text="Printer List").type = "SLICENODE_PrinterList" layout.operator("node.add_node", text="Printer List").type = "SLICENODE_PrinterList"