From 6c5ba130ae6174c8b7cfaf63906e3acebd5aa6bf Mon Sep 17 00:00:00 2001 From: DolphinDream Date: Fri, 25 Jan 2019 22:00:16 -0500 Subject: [PATCH] Add (new) MeshSwitch node The node allows to connect multiple mesh inputs (verts/edges/polys) and to select one of them to output. Useful for changing the input mesh model to be processed by a node tree. New input sockets are added as new meshes are connected to allow the next mesh (verts/edges/polys) to be connected. --- docs/nodes/modifier_change/mesh_switch.rst | 35 +++++++ index.md | 1 + nodes/modifier_change/mesh_switch.py | 103 +++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 docs/nodes/modifier_change/mesh_switch.rst create mode 100644 nodes/modifier_change/mesh_switch.py diff --git a/docs/nodes/modifier_change/mesh_switch.rst b/docs/nodes/modifier_change/mesh_switch.rst new file mode 100644 index 0000000000..d84260e76f --- /dev/null +++ b/docs/nodes/modifier_change/mesh_switch.rst @@ -0,0 +1,35 @@ +Mesh Switch +----------- + +This node allows to switch among an arbitrary number of mesh inputs (verts, edges, polys) connected to the node. + +Inputs +====== + +**Verts A** +Takes a Vertex list from outside nodes. + +**EdgePolys A** +Takes either an Edge or a Poly list from outside nodes. + +The node starts with one set of mesh input sockets ("Verts A" and "EdgePolys A") and will create new mesh sockets whenever the last Verts input socket is connected, thus allowing additional mesh inputs to be connected to the node. Whenever the last Verts input socket is disconnected the node will remove the all disconnected inputs at the end of the input list except the last disconnected set of inputs, thus always allowing one extra mesh to be connected to the node. + +Parameters +========== + +The **Selected** parameter accepts single input values directly from the node or from an outside node. The value is sanitized to be bounded to the range of the connected inputs (0, N-1) and it is also converted via a modulo-N function to wrap around within (0, N-1) range for values larger than N. In other words, as the **Selected** value increases the node essentially cycles through the connected meshes. + ++---------------+---------+---------+-------------------------------------------------+ +| Param | Type | Default | Description | ++===============+=========+=========+=================================================+ +| **Selected** | Int | 0 | The index of the selected mesh to output. | ++---------------+---------+---------+-------------------------------------------------+ + +Outputs +======= + +**Verts** +**EdgePolys** + +When an output socket is connected the node will output the mesh corresponding to the selected index. + diff --git a/index.md b/index.md index c1d9b31f98..566cadcc23 100644 --- a/index.md +++ b/index.md @@ -86,6 +86,7 @@ PolygonBoomNode Pols2EdgsNode SvMeshJoinNode + SvMeshSwitchNode --- SvBevelNode SvSubdivideNode diff --git a/nodes/modifier_change/mesh_switch.py b/nodes/modifier_change/mesh_switch.py new file mode 100644 index 0000000000..15490cd2c1 --- /dev/null +++ b/nodes/modifier_change/mesh_switch.py @@ -0,0 +1,103 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy +from bpy.props import IntProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode + +ABC = tuple('ABCDEFGHIJKLMNOPQRSTUVWXYZ') + + +class SvMeshSwitchNode(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: Mesh, Switch, Select + Tooltips: Switch among multiple Verts/Edge/Poly inputs + """ + bl_idname = 'SvMeshSwitchNode' + bl_label = 'Mesh Switch' + + selected = IntProperty( + name="Selected", description="Selected Mesh", + default=0, min=0, update=updateNode) + + def update(self): + inputs = self.inputs + if inputs[-2].links: # last Verts socket linked ? => create more sockets + name = ABC[int(len(inputs) / 2)] # pick the next letter A to Z + inputs.new("VerticesSocket", "Verts " + name) + inputs.new("StringsSocket", "EdgePolys " + name) + else: # last Verts input unlinked ? => remove all but last unlinked + # get the list of Verts socket labels (linked or unlinked) + vertSockets = filter(lambda s: "Verts" in s.name, inputs) + socketLabels = [s.name[-1] for s in vertSockets] # (ABCD) + # get the labels of last unlinked Verts sockets in reverse order + unlinkedSocketLabels = [] + for label in socketLabels[::-1]: # in reverse order (DCBA) + if inputs["Verts " + label].is_linked: + break + else: + unlinkedSocketLabels.append(label) + # delete all unlinked V-EP inputs sockets (except the last ones) + for label in unlinkedSocketLabels[:-1]: + inputs.remove(inputs["Verts " + label]) + inputs.remove(inputs["EdgePolys " + label]) + + def sv_init(self, context): + self.inputs.new('StringsSocket', "Selected").prop_name = "selected" + + self.inputs.new('VerticesSocket', "Verts A") + self.inputs.new('StringsSocket', "EdgePolys A") + + self.outputs.new('VerticesSocket', "Verts") + self.outputs.new('StringsSocket', "EdgePolys") + + def process(self): + # return if no outputs are connected + outputs = self.outputs + if not any(s.is_linked for s in outputs): + return + + inputs = self.inputs + + input_n = inputs["Selected"].sv_get()[0][0] + num = max(1, len(socketLabels)) + n = max(0, int(input_n)) % num + + # get the list of labels of the linked Verts input sockets + vertSockets = filter(lambda s: "Verts" in s.name and s.is_linked, inputs) + socketLabels = [s.name[-1] for s in vertSockets] # (ABCD) + + label = socketLabels[n] # the label of the selected input + + if outputs["Verts"].is_linked: + verts = inputs["Verts " + label].sv_get() + outputs["Verts"].sv_set(verts) + + if outputs["EdgePolys"].is_linked: + edgePolys = inputs["EdgePolys " + label].sv_get(default=[]) + outputs["EdgePolys"].sv_set(edgePolys) + + +def register(): + bpy.utils.register_class(SvMeshSwitchNode) + + +def unregister(): + bpy.utils.unregister_class(SvMeshSwitchNode)