diff --git a/docs/nodes/logic/custom_switcher.rst b/docs/nodes/logic/custom_switcher.rst new file mode 100644 index 0000000000000000000000000000000000000000..fc17a82936fce5b7d7ec15274d3313e2ea6b0677 --- /dev/null +++ b/docs/nodes/logic/custom_switcher.rst @@ -0,0 +1,50 @@ +Custom switcher +=============== + +.. image:: https://user-images.githubusercontent.com/28003269/59678662-11dd6500-91de-11e9-9b28-a08aebaea8b8.png + +Functionality +------------- +Simple node which convert input sequence to buttons. It is useful for creating custom switcher. + +Inputs +------ + +- **Data** - any data you wish.There is no limitation of length of input data but all items above **32** will be ignored. + +Outputs +------- + +- **Item** - index of selected items. + +N panel +------- + ++--------------------+-------+--------------------------------------------------------------------------------+ +| Parameters | Type | Description | ++====================+=======+================================================================================+ +| Multiple selection | Bool | Allowed to select several items simultaneously | ++--------------------+-------+--------------------------------------------------------------------------------+ +| Show in 3d panel | Bool | Won't be ignored for adding parameter of the node to 3d panel | ++--------------------+-------+--------------------------------------------------------------------------------+ +| Size of buttons | float | controlling of size of buttons | ++--------------------+-------+--------------------------------------------------------------------------------+ + +3D panel +-------- + +It consists dropdown list of items and button for activation of multiple selection mode. + +Examples +-------- +**Controlling of light from 3d panel:** + +.. image:: https://user-images.githubusercontent.com/28003269/59653042-7deda800-91a1-11e9-892f-f3e927612d72.gif + +.. image:: https://user-images.githubusercontent.com/28003269/59653046-80500200-91a1-11e9-8314-3c7ebe98d3f8.png + +**controlling of material from 3d panel:** + +.. image:: https://user-images.githubusercontent.com/28003269/59654477-5d285100-91a7-11e9-8a9b-f436d6de57db.gif + +.. image:: https://user-images.githubusercontent.com/28003269/59654483-644f5f00-91a7-11e9-92cb-70da3cc641b0.png \ No newline at end of file diff --git a/index.md b/index.md index 5bb556f3f7c3f63fd69599efa4121194b90e8352..c87df3ce119639d9619f52a7d9cdc4e650192bc3 100644 --- a/index.md +++ b/index.md @@ -242,6 +242,7 @@ SvSwitchNode SvInputSwitchNode SvNeuroElman1LNode + SvCustomSwitcher ## Viz ViewerNode2 diff --git a/nodes/logic/custom_switcher.py b/nodes/logic/custom_switcher.py new file mode 100644 index 0000000000000000000000000000000000000000..9cf400e4914372364cd9282d01cf86cbacba86c5 --- /dev/null +++ b/nodes/logic/custom_switcher.py @@ -0,0 +1,130 @@ +# ##### 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 sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode + + +class SvCustomSwitcher(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: custom switcher + Convert input to buttons + + Output shows selected items + """ + bl_idname = 'SvCustomSwitcher' + bl_label = 'Switcher' + bl_icon = 'HAND' + + def update_mode(self, context): + # Select only one item in non multiple selection mode + if not self.multiple_selection: + self['previous_user_list'] = [False for _ in range(32)] + self.user_list = [True] + [False for _ in range(31)] + + def get_user_list(self): + return self['user_list'] + + def set_user_list(self, values): + # Implementation of single selection mode + if not self.multiple_selection: + values = [True if not old and new or old and not new else False + for old, new in zip(self['previous_user_list'], values)] + self['previous_user_list'] = values + self['user_list'] = values + + to3d = bpy.props.BoolProperty(name='Show in 3d panel', default=True, + description='Show items of this node in 3d panel of 3d view screen') + multiple_selection = bpy.props.BoolProperty(name='Multiple selection', default=True, update=update_mode, + description='Selection several items simultaneously') + ui_scale = bpy.props.FloatProperty(name='Size of buttons', default=1.0, min=0.5, max=5) + string_values = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup, description='Storage of items names') + user_list = bpy.props.BoolVectorProperty(name="User selection", size=32, update=updateNode, set=set_user_list, + get=get_user_list, description='Selection status of items') + show_in_3d = bpy.props.BoolProperty(name='show in panel', default=True, + description='Show properties in 3d panel or not') + + def sv_init(self, context): + self['user_list'] = [False for _ in range(32)] + self['previous_user_list'] = [False for _ in range(32)] + self.inputs.new('StringsSocket', 'Data') + self.outputs.new('StringsSocket', 'Item') + + def draw_buttons(self, context, layout): + col = layout.column(align=True) + col.scale_y = self.ui_scale + for i, val in enumerate(self.string_values): + col.prop(self, "user_list", toggle=True, index=i, text=val.name) + + def draw_buttons_ext(self, context, layout): + row = layout.row() + row.scale_y = 2 + row.prop(self, 'multiple_selection', toggle=True) + layout.prop(self, 'to3d', toggle=True) + layout.prop(self, 'ui_scale', text='Size of buttons') + + def draw_buttons_3dpanel(self, layout): + # I think it is moore appropriate place for coding layout of 3d panel + col = layout.column() + row = col.row(align=True) + if self.label: + name = self.label + else: + name = self.name + switch_icon = 'DOWNARROW_HLT' if self.show_in_3d else 'RIGHTARROW' + row.prop(self, 'show_in_3d', text=name, icon=switch_icon) + if self.multiple_selection: + mode_icon = 'COLLAPSEMENU' + else: + mode_icon = 'ZOOMOUT' + row.prop(self, 'multiple_selection', toggle=True, text='', icon=mode_icon) + if self.show_in_3d: + col = layout.column(align=True) + for i, val in enumerate(self.string_values): + col.prop(self, "user_list", toggle=True, index=i, text=val.name) + + def process(self): + # Storing names of items + if self.inputs['Data'].is_linked: + data = self.inputs['Data'].sv_get() + if isinstance(data[0], (list, tuple)): + data = [i for l in data for i in l] + if len(data) != len(self.string_values): + self.string_values.clear() + for i, val in enumerate(data): + if i == 32: + break + self.string_values.add().name = str(val) + else: + for val, str_val in zip(data, self.string_values): + str_val.name = str(val) + else: + self.string_values.clear() + + self.outputs['Item'].sv_set([[i for i, b in enumerate(self.user_list) if b]]) + + +def register(): + bpy.utils.register_class(SvCustomSwitcher) + + +def unregister(): + bpy.utils.unregister_class(SvCustomSwitcher) diff --git a/ui/sv_panels.py b/ui/sv_panels.py index f51ecd995100761b359ba2c3e82c1e8c68753207..15d87582e23eb5c77e16d3709ca632d29ef87c58 100644 --- a/ui/sv_panels.py +++ b/ui/sv_panels.py @@ -244,6 +244,9 @@ class Sv3DPanel(bpy.types.Panel): row.prop(node, node.mode, index=i, text=str(i)) row.scale_x = little_width * 2.5 + elif node.bl_idname in {'SvCustomSwitcher'}: + node.draw_buttons_3dpanel(col) + # Import/Export properties row = col.row(align=True) row.label(text='Export/Import:') diff --git a/utils/sv_panels_tools.py b/utils/sv_panels_tools.py index f4e9767857fcb39290db0a5168a732528eef29f7..ace1d20d6fed31e958a35d43bde41be38d7fefe4 100644 --- a/utils/sv_panels_tools.py +++ b/utils/sv_panels_tools.py @@ -196,14 +196,15 @@ class SvLayoutScanProperties(bpy.types.Operator): templist = [] for node in tree.nodes: idname = node.bl_idname - + if idname in {'ObjectsNodeMK2', 'SvObjectsNodeMK3'}: debug('scans for get option %s %s', node.label, node.name) if any((s.links for s in node.outputs)): templist.append([node.label, node.name, ""]) - elif idname in {'SvNumberNode', 'IntegerNode', 'FloatNode', 'SvListInputNode', 'SvColorInputNode', 'SvBmeshViewerNodeMK2'}: - if idname != 'SvBmeshViewerNodeMK2': + elif idname in {'SvNumberNode', 'IntegerNode', 'FloatNode', 'SvListInputNode', 'SvColorInputNode', + 'SvBmeshViewerNodeMK2', 'SvCustomSwitcher'}: + if idname not in {'SvBmeshViewerNodeMK2', 'SvCustomSwitcher'}: if not node.outputs: debug("Node %s does not have outputs", node.name) continue @@ -213,6 +214,10 @@ class SvLayoutScanProperties(bpy.types.Operator): if (not node.outputs[0].is_linked) or (node.to3d != True): debug("Node %s: first output is not linked or to3d == False", node.name) continue + elif idname == 'SvCustomSwitcher': + if not node.inputs[0].is_linked and not node.outputs[0].is_linked or (node.to3d != True): + debug("Node %s: output or input are not linked", node.name) + continue elif (node.to3d != True): debug("Node %s: first output is not linked or to3d == False", node.name) continue @@ -232,6 +237,8 @@ class SvLayoutScanProperties(bpy.types.Operator): templist.append([node.label, node.name, 'int_list']) elif node.mode == 'float_list': templist.append([node.label, node.name, 'float_list']) + elif 'SvCustomSwitcher' in idname: + templist.append([node.label, node.name, 'user_list']) else: kind = node.selected_mode templist.append([node.label, node.name, kind + '_'])