separate by range
This commit is contained in:
parent
0cf055876c
commit
9c144a7465
2 changed files with 90 additions and 1 deletions
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||
from typing import Any
|
||||
import numpy as np
|
||||
|
||||
from ..bpy_ns_types import NfBoolProperty, NfEnumProperty, notify_tree_changed
|
||||
from ..bpy_ns_types import NfBoolProperty, NfEnumProperty, NfIntProperty, notify_tree_changed
|
||||
from ....registry import register_class
|
||||
from .base import SliceNode, SlicingCollection, get_all_children, SliceNodeJoiner, SlicingGroup, SlicingObject
|
||||
|
||||
|
|
@ -157,3 +157,91 @@ class SLICENODE_SeparateMesh(SliceNode):
|
|||
if socket_name == "Selection":
|
||||
return res_selection
|
||||
return res_inverted
|
||||
|
||||
@register_class
|
||||
class SLICENODE_SeparateMeshByRange(SliceNode):
|
||||
bl_label = "Separate Mesh by Range"
|
||||
|
||||
start_val: NfIntProperty(name="Start", default=0, update=notify_tree_changed) # pyright: ignore[reportInvalidTypeForm]
|
||||
end_val: NfIntProperty(name="End", default=1, update=notify_tree_changed) # pyright: ignore[reportInvalidTypeForm]
|
||||
|
||||
def init(self, context):
|
||||
self.add_input("SLICESOCK_Mesh")
|
||||
self.add_input("SLICESOCK_String", "Attribute")
|
||||
self._update_outputs()
|
||||
|
||||
def update(self):
|
||||
super().update()
|
||||
self._update_outputs()
|
||||
|
||||
def _update_outputs(self):
|
||||
# Ensure end >= start
|
||||
start = self.start_val
|
||||
end = max(start, self.end_val)
|
||||
expected_ids = [str(i) for i in range(start, end + 1)]
|
||||
|
||||
# Remove outputs that are no longer in the range
|
||||
# We use a list to avoid modification-during-iteration issues
|
||||
to_remove = [o for o in self.outputs if o.identifier not in expected_ids]
|
||||
for o in to_remove:
|
||||
self.outputs.remove(o)
|
||||
|
||||
# Add new outputs
|
||||
for id_str in expected_ids:
|
||||
if id_str not in self.outputs:
|
||||
self.add_output("SLICESOCK_Mesh", id_str, identifier=id_str)
|
||||
|
||||
# Re-order to match range
|
||||
for i, id_str in enumerate(expected_ids):
|
||||
current_index = self.outputs.find(id_str)
|
||||
if current_index != -1 and current_index != i:
|
||||
self.outputs.move(current_index, i)
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
col = layout.column(align=True)
|
||||
col.prop(self, "start_val")
|
||||
col.prop(self, "end_val")
|
||||
|
||||
def evaluate_output(self, socket_name: str, **_kwargs) -> SlicingCollection | None:
|
||||
coll: SlicingCollection | None = self.resolve("Mesh")
|
||||
attr_name: str = self.resolve("Attribute")
|
||||
|
||||
if not coll: return None
|
||||
|
||||
# Check if we can parse the socket name as an integer
|
||||
try:
|
||||
target_val = int(socket_name)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
res = SlicingCollection([], f"{coll.name}_{target_val}")
|
||||
|
||||
for so in coll.objects:
|
||||
if attr_name not in so.attributes:
|
||||
continue
|
||||
|
||||
attr = so.attributes[attr_name]
|
||||
vals = attr["values"]
|
||||
|
||||
# Attribute values might be floats or ints, we check for equality
|
||||
mask = vals == target_val
|
||||
|
||||
if np.all(mask):
|
||||
res.objects.append(so)
|
||||
elif np.any(mask):
|
||||
# Split the object
|
||||
so_new = SlicingObject()
|
||||
so_new.name = f"{so.name}_{target_val}"
|
||||
so_new.parent = so.parent
|
||||
so_new.object_type = so.object_type
|
||||
so_new.extruder = so.extruder
|
||||
so_new.mesh = so.mesh[mask]
|
||||
for k, v in so.attributes.items():
|
||||
so_new.attributes[k] = {
|
||||
"domain": v["domain"],
|
||||
"type": v["type"],
|
||||
"values": v["values"][mask]
|
||||
}
|
||||
res.objects.append(so_new)
|
||||
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ class SLICENODE_MT_Geometry(Menu):
|
|||
assert layout
|
||||
layout.operator("node.add_node", text="Get Mesh").type = "SLICENODE_GetMesh"
|
||||
layout.operator("node.add_node", text="Separate Mesh").type = "SLICENODE_SeparateMesh"
|
||||
layout.operator("node.add_node", text="Separate Mesh by Range").type = "SLICENODE_SeparateMeshByRange"
|
||||
layout.operator("node.add_node", text="Get Paths").type = "SLICENODE_GetPaths"
|
||||
layout.separator()
|
||||
layout.operator("node.add_node", text="Slice Shells").type = "SLICENODE_SliceShells"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue