This commit is contained in:
Nicolas Predella 2026-10-13 19:16:35 +03:00
parent 8dd61f5858
commit 8e8a0a5993
5 changed files with 40 additions and 87 deletions

View file

@ -165,29 +165,21 @@ class SliceNodeListJoiner(SliceNode):
from ....infra.blender.list_utils import flatten_list, is_list_data from ....infra.blender.list_utils import flatten_list, is_list_data
items: list[Any] = [] items: list[Any] = []
if "resolve_multi_input" in self.__dict__: def _append_val(v: Any) -> None:
raw_inputs = self.resolve_multi_input(self.socket_label) if v is not None:
for val in raw_inputs: if is_list_data(v):
if val is not None: items.extend(flatten_list(v))
if is_list_data(val): else:
items.extend(flatten_list(val)) items.append(v)
else:
items.append(val)
return items
target_inputs = [ target_inputs = [
i for i in getattr(self, "inputs", []) i for i in getattr(self, "inputs", [])
if getattr(i, "name", "") == self.socket_label or getattr(i, "identifier", "").startswith(f"{self.socket_label}_ms_in_") if getattr(i, "name", "") == self.socket_label or getattr(i, "identifier", "").startswith(f"{self.socket_label}_ms_in_")
] ]
if not target_inputs: if "resolve_multi_input" in self.__dict__ or not target_inputs:
raw_inputs = self.resolve_multi_input(self.socket_label) for val in self.resolve_multi_input(self.socket_label):
for val in raw_inputs: _append_val(val)
if val is not None:
if is_list_data(val):
items.extend(flatten_list(val))
else:
items.append(val)
return items return items
cache = getattr(self, "_current_cache", None) cache = getattr(self, "_current_cache", None)
@ -206,11 +198,7 @@ class SliceNodeListJoiner(SliceNode):
else: else:
val = resolve_input(inp, cache=cache, visited=visited, fieldname=self.socket_label, node=self) val = resolve_input(inp, cache=cache, visited=visited, fieldname=self.socket_label, node=self)
if val is not None: _append_val(val)
if is_list_data(val):
items.extend(flatten_list(val))
else:
items.append(val)
return items return items

View file

@ -2,14 +2,12 @@ from __future__ import annotations
from typing import Any from typing import Any
import bpy import bpy
from bpy.props import CollectionProperty from bpy.props import CollectionProperty
from .bpy_ns_types import NfStringProperty, NfFloatProperty, NfIntProperty, NfEnumProperty, NfPointerProperty, NfFloatVectorProperty from .bpy_ns_types import NfStringProperty, NfIntProperty, NfEnumProperty, notify_tree_changed
from ...registry import register_class from ...registry import register_class
from ...infra.blender.blender_slice_nodes_generic import SliceNodeSocket from ...infra.blender.blender_slice_nodes_generic import SliceNodeSocket
from ..slice import SlicePaths from ..slice import SlicePaths
from .bpy_ns_types import notify_tree_changed
class LabelNodeSocket(SliceNodeSocket): class LabelNodeSocket(SliceNodeSocket):
default = "" default = ""
def draw(self, context: Any, layout: Any, node: Any, text: str | None): def draw(self, context: Any, layout: Any, node: Any, text: str | None):

View file

@ -170,8 +170,8 @@ class SLICETREE_NodeTree(NodeTree):
) )
compatible = ( compatible = (
(from_socket.bl_idname in geom_sockets and to_socket.bl_idname in geom_sockets) (out_s.bl_idname in geom_sockets and in_s.bl_idname in geom_sockets)
or from_socket.bl_idname == to_socket.bl_idname or out_s.bl_idname == in_s.bl_idname
or is_obj_to_mesh or is_obj_to_mesh
) )
if not compatible: if not compatible:

View file

@ -661,12 +661,11 @@ def object_to_mesh(data: Any, include_children: bool = True) -> Any:
"""Converts an Object (or list of Objects) into SlicingCollection, matching SLICENODE_GetMesh.""" """Converts an Object (or list of Objects) into SlicingCollection, matching SLICENODE_GetMesh."""
from .blender_mesh_capture import SlicingCollection, SlicingGroup, SlicingObject from .blender_mesh_capture import SlicingCollection, SlicingGroup, SlicingObject
from .blender_bridge import get_all_children from .blender_bridge import get_all_children
from .list_utils import is_list_data
mesh_types = (SlicingCollection, SlicingGroup, SlicingObject)
def _to_collection(o: Any) -> Any: def _to_collection(o: Any) -> Any:
if not o: if not o or isinstance(o, mesh_types):
return None
if isinstance(o, (SlicingCollection, SlicingGroup, SlicingObject)):
return o return o
family = [o] + (get_all_children(o) if include_children else []) family = [o] + (get_all_children(o) if include_children else [])
return SlicingCollection(family, getattr(o, "name", "Mesh")) return SlicingCollection(family, getattr(o, "name", "Mesh"))
@ -682,26 +681,20 @@ def _is_already_mesh(val: Any) -> bool:
if val is None: if val is None:
return False return False
from .blender_mesh_capture import SlicingCollection, SlicingGroup, SlicingObject from .blender_mesh_capture import SlicingCollection, SlicingGroup, SlicingObject
if isinstance(val, (SlicingCollection, SlicingGroup, SlicingObject)): mesh_types = (SlicingCollection, SlicingGroup, SlicingObject)
if isinstance(val, mesh_types):
return True return True
if is_list_data(val): if is_list_data(val):
flat = flatten_list(val) flat = flatten_list(val)
if flat and all(isinstance(x, (SlicingCollection, SlicingGroup, SlicingObject)) for x in flat): return bool(flat) and all(isinstance(x, mesh_types) for x in flat)
return True
return False return False
def _is_object_data(val: Any) -> bool: def _is_object_data(val: Any) -> bool:
if val is None: if val is None or _is_already_mesh(val) or isinstance(val, (str, int, float, bool, bytes, dict)):
return False
if _is_already_mesh(val):
return False
if isinstance(val, (str, int, float, bool, bytes, dict)):
return False return False
if is_list_data(val): if is_list_data(val):
flat = flatten_list(val) flat = flatten_list(val)
if not flat: return bool(flat) and any(_is_object_data(x) for x in flat)
return False
return any(_is_object_data(x) for x in flat)
obj_type = getattr(bpy.types, "Object", None) obj_type = getattr(bpy.types, "Object", None)
if isinstance(obj_type, type) and isinstance(val, obj_type): if isinstance(obj_type, type) and isinstance(val, obj_type):
return True return True
@ -772,7 +765,7 @@ def resolve_input(
) )
if is_mesh_socket and val is not None: if is_mesh_socket and val is not None:
is_obj_source = getattr(from_socket, "bl_idname", "") in ("NodeSocketObject", "SLICESOCK_Object") is_obj_source = getattr(from_socket, "bl_idname", "") in ("NodeSocketObject", "SLICESOCK_Object")
if (is_obj_source or _is_object_data(val)) and not _is_already_mesh(val): if not _is_already_mesh(val) and (is_obj_source or _is_object_data(val)):
group_stack = tuple(n.as_pointer() for n in _get_group_stack(cache)) group_stack = tuple(n.as_pointer() for n in _get_group_stack(cache))
from_node = getattr(from_socket, "node", None) from_node = getattr(from_socket, "node", None)
from_ptr = from_node.as_pointer() if (from_node and hasattr(from_node, "as_pointer")) else id(from_node) from_ptr = from_node.as_pointer() if (from_node and hasattr(from_node, "as_pointer")) else id(from_node)

View file

@ -183,69 +183,43 @@ def socket_accepts_list(sock: Any, visited: set | None = None) -> bool:
return False return False
def _get_input_interface_item(tree: Any, sock_or_idx_or_ident: Any) -> Any: def _get_interface_item(tree: Any, sock_or_idx_or_ident: Any, in_out: str) -> Any:
attr_name = "inputs" if in_out == 'INPUT' else "outputs"
if not hasattr(tree, "interface"): if not hasattr(tree, "interface"):
inputs = getattr(tree, "inputs", []) sockets = getattr(tree, attr_name, [])
if isinstance(sock_or_idx_or_ident, int) and 0 <= sock_or_idx_or_ident < len(inputs): if isinstance(sock_or_idx_or_ident, int) and 0 <= sock_or_idx_or_ident < len(sockets):
return inputs[sock_or_idx_or_ident] return sockets[sock_or_idx_or_ident]
ident = getattr(sock_or_idx_or_ident, "identifier", str(sock_or_idx_or_ident)) ident = getattr(sock_or_idx_or_ident, "identifier", str(sock_or_idx_or_ident))
for s in inputs: for s in sockets:
if s.identifier == ident or s.name == ident: if s.identifier == ident or s.name == ident:
return s return s
return None return None
input_items = [ items = [
item for item in getattr(tree.interface, "items_tree", []) item for item in getattr(tree.interface, "items_tree", [])
if getattr(item, "item_type", "") == 'SOCKET' and getattr(item, "in_out", "") == 'INPUT' if getattr(item, "item_type", "") == 'SOCKET' and getattr(item, "in_out", "") == in_out
] ]
if isinstance(sock_or_idx_or_ident, int): if isinstance(sock_or_idx_or_ident, int):
if 0 <= sock_or_idx_or_ident < len(input_items): return items[sock_or_idx_or_ident] if 0 <= sock_or_idx_or_ident < len(items) else None
return input_items[sock_or_idx_or_ident]
return None
ident = getattr(sock_or_idx_or_ident, "identifier", None) ident = getattr(sock_or_idx_or_ident, "identifier", None)
name = getattr(sock_or_idx_or_ident, "name", None) name = getattr(sock_or_idx_or_ident, "name", None)
if isinstance(sock_or_idx_or_ident, str): if isinstance(sock_or_idx_or_ident, str):
ident = sock_or_idx_or_ident ident = name = sock_or_idx_or_ident
name = sock_or_idx_or_ident
for item in input_items: for item in items:
if ident and getattr(item, "identifier", None) == ident: if ident and getattr(item, "identifier", None) == ident:
return item return item
for item in input_items: for item in items:
if name and getattr(item, "name", None) == name: if name and getattr(item, "name", None) == name:
return item return item
return None return None
def _get_input_interface_item(tree: Any, sock_or_idx_or_ident: Any) -> Any:
return _get_interface_item(tree, sock_or_idx_or_ident, 'INPUT')
def _get_output_interface_item(tree: Any, sock_or_idx_or_ident: Any) -> Any: def _get_output_interface_item(tree: Any, sock_or_idx_or_ident: Any) -> Any:
if not hasattr(tree, "interface"): return _get_interface_item(tree, sock_or_idx_or_ident, 'OUTPUT')
outputs = getattr(tree, "outputs", [])
if isinstance(sock_or_idx_or_ident, int) and 0 <= sock_or_idx_or_ident < len(outputs):
return outputs[sock_or_idx_or_ident]
ident = getattr(sock_or_idx_or_ident, "identifier", str(sock_or_idx_or_ident))
for s in outputs:
if s.identifier == ident or s.name == ident:
return s
return None
output_items = [
item for item in getattr(tree.interface, "items_tree", [])
if getattr(item, "item_type", "") == 'SOCKET' and getattr(item, "in_out", "") == 'OUTPUT'
]
if isinstance(sock_or_idx_or_ident, int):
if 0 <= sock_or_idx_or_ident < len(output_items):
return output_items[sock_or_idx_or_ident]
return None
ident = getattr(sock_or_idx_or_ident, "identifier", None)
name = getattr(sock_or_idx_or_ident, "name", None)
if isinstance(sock_or_idx_or_ident, str):
ident = sock_or_idx_or_ident
name = sock_or_idx_or_ident
for item in output_items:
if ident and getattr(item, "identifier", None) == ident:
return item
for item in output_items:
if name and getattr(item, "name", None) == name:
return item
return None
def _find_group_input_socket(tree: Any, item: Any) -> Any: def _find_group_input_socket(tree: Any, item: Any) -> Any:
if not item or not hasattr(tree, "nodes"): if not item or not hasattr(tree, "nodes"):