nodeslicer/core/nodeslicer/sockets.py

178 lines
6.1 KiB
Python

from __future__ import annotations
from typing import Any
import bpy
from bpy.props import CollectionProperty
from .bpy_ns_types import NfStringProperty, NfFloatProperty, NfIntProperty, NfEnumProperty, NfPointerProperty, NfFloatVectorProperty
from ...registry import register_class
from ...infra.blender.blender_slice_nodes_generic import SliceNodeSocket
from ..slice import SlicePaths
from .bpy_ns_types import notify_tree_changed
class LabelNodeSocket(SliceNodeSocket):
default = ""
def draw(self, context: Any, layout: Any, node: Any, text: str | None):
assert layout
layout.label(text=text or self.name)
class InputNodeSocket(SliceNodeSocket):
def draw(self, context: Any, layout: Any, node: Any, text: str | None):
assert layout
if self.is_output or self.is_linked:
layout.label(text=text or self.name)
else:
self._draw_prop(text, layout)
def _draw_prop(self, text, layout):
layout.prop(self, "value", text=text or self.name)
def _draw_as_ro(self, context: Any, layout: Any, node: Any, text: str | None):
layout.label(text=text or self.name)
def _draw_as_rw(self, context: Any, layout: Any, node: Any, text: str | None):
layout.prop(self, "value", text=text or self.name)
class ReadonlySocket():
def draw(self, context: Any, layout: Any, node: Any, text: str | None):
return self._draw_as_ro(context, layout, node, text) # pyright: ignore[reportAttributeAccessIssue]
@register_class
class SLICESOCK_Geometry(LabelNodeSocket):
bl_label = "Geometry"
default = None
bl_color = (0.0, 0.75, 0.75, 1.0)
def draw_color(self, context, node) -> tuple[float, float, float, float]:
def _get_upstream_color(sock: Any) -> tuple[float, float, float, float]:
if not sock or not getattr(sock, "is_linked", False) or not getattr(sock, "links", None):
return self.bl_color
from_sock = sock.links[0].from_socket
if hasattr(from_sock, "draw_color"):
try:
from_node = getattr(from_sock, "node", None)
return from_sock.draw_color(context, from_node)
except Exception:
pass
return getattr(from_sock, "bl_color", self.bl_color)
if getattr(self, "is_output", False):
if node and hasattr(node, "inputs"):
sock_name = getattr(self, "name", "")
matching_in = (node.inputs.get(sock_name) if sock_name else None) or node.inputs.get("Geometry")
if matching_in:
return _get_upstream_color(matching_in)
return self.bl_color
else:
return _get_upstream_color(self)
@register_class
class SLICESOCK_Mesh(LabelNodeSocket):
bl_label = "Mesh"
default = None
bl_color = (0, 214/255, 163/255, 1.0)
@register_class
class SLICESOCK_Paths(LabelNodeSocket):
bl_label = "Paths"
default = SlicePaths()
bl_color = (214/255, 0, 120/255, 1.0)
@register_class
class SLICESOCK_Intrinsics(LabelNodeSocket):
bl_label = "Intrinsics"
default = None
bl_color = (0.2, 0.2, 0.2, 1.0)
@register_class
class SettingItem(bpy.types.PropertyGroup):
field: str = NfStringProperty(name="Field", default="")
value_str: str = NfStringProperty(name="Value", default="")
@property
def is_active(self):
return bool(self.field) or bool(self.value_str)
def draw_item(self, layout):
row = layout.row(align=True)
row.prop(self, "field", text="")
row.prop(self, "value_str", text="")
from ...infra.blender.mixins import CollectionMixin
class SLICESOCK_Settings_Common(CollectionMixin, InputNodeSocket):
bl_label = "Settings"
items: CollectionProperty(type=SettingItem) # pyright: ignore[reportInvalidTypeForm]
bl_color = (1.0, 1.0, 0.0, 1.0) # Yellow
@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
class SLICESOCK_Settings(SLICESOCK_Settings_Common): ...
@register_class
class SLICESOCK_SettingsRo(ReadonlySocket, SLICESOCK_Settings_Common): ...
@register_class
class SLICESOCK_ExecutionLink(LabelNodeSocket):
bl_label = "Execution Link"
default = None
bl_color = (0.5, 0.0, 0.5, 1.0) # Purple
@register_class
class SLICESOCK_Printer(InputNodeSocket):
bl_label = "Printer"
host: str = NfStringProperty(name="Host", default="localhost")
port: int = NfIntProperty(name="Port", default=80, min=1, max=65535)
prefix: str = NfStringProperty(name="Prefix", default="")
label: str = NfStringProperty(name="Label", default="Printer")
username: str = NfStringProperty(name="Username", default="")
password: str = NfStringProperty(name="Password", default="", subtype='PASSWORD')
host_type: str = NfEnumProperty(
name="Type",
items=[
('PRUSALINK', "PrusaLink", "PrusaLink API"),
('CREALITY', "Creality", "Creality Cloud API"),
('MOONRAKER', "Moonraker", "Moonraker (Klipper) API"),
],
default='PRUSALINK',
update=notify_tree_changed
)
bl_color = (1.0, 0.45, 0.1, 1.0) # Orange
def draw(self, context, layout, node, text):
if self.is_output or self.is_linked:
layout.label(text=text or self.name)
else:
col = layout.column(align=True)
col.prop(self, "label", text="")
col.prop(self, "host_type", text="")
col.prop(self, "host")
col.prop(self, "port")
col.prop(self, "prefix")
col.prop(self, "username")
col.prop(self, "password")
@property
def value(self) -> Any:
from ...infra.networking.printer_backends import PrinterConfig
return PrinterConfig(
host=self.host,
port=self.port,
prefix=self.prefix,
label=self.label,
username=self.username,
password=self.password,
host_type=self.host_type
)