From 6ba4e8603e03bf787cae6c2a0bb5d3b3fa35316c Mon Sep 17 00:00:00 2001 From: zeffii Date: Tue, 28 Apr 2020 13:40:34 +0200 Subject: [PATCH 01/12] defensive snlite coding first --- nodes/generator/script1_lite.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nodes/generator/script1_lite.py b/nodes/generator/script1_lite.py index d2878e305..c53d4f522 100644 --- a/nodes/generator/script1_lite.py +++ b/nodes/generator/script1_lite.py @@ -280,6 +280,8 @@ class SvScriptNodeLite(bpy.types.Node, SverchCustomTreeNode): if self.script_name in bpy.data.texts: self.script_str = bpy.data.texts.get(self.script_name).as_string() + elif self.script_name[3:] in bpy.data.texts: + self.script_str = bpy.data.texts.get(self.script_name[3:]).as_string() else: print('bpy.data.texts not read yet') if self.script_str: -- GitLab From a3ea990e4f2b3a9dc46ff74e9c7cefb0ef423a74 Mon Sep 17 00:00:00 2001 From: zeffii Date: Tue, 28 Apr 2020 15:40:26 +0200 Subject: [PATCH 02/12] test it --- core/sockets.py | 2 +- node_tree.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/sockets.py b/core/sockets.py index fd55b796d..d44563b98 100644 --- a/core/sockets.py +++ b/core/sockets.py @@ -306,7 +306,7 @@ class SvObjectSocket(NodeSocket, SvSocketCommon): if self.is_linked and not self.is_output: return self.convert_data(SvGetSocket(self, deepcopy), implicit_conversions) elif self.object_ref: - obj_ref = bpy.data.objects.get(self.object_ref.strip()) + obj_ref = self.node.get_bpy_data_from_name(self.object_ref, bpy.data.objects) if not obj_ref: raise SvNoDataError(self) return [obj_ref] diff --git a/node_tree.py b/node_tree.py index a33f57d33..e5968892c 100644 --- a/node_tree.py +++ b/node_tree.py @@ -841,6 +841,16 @@ class SverchCustomTreeNode: except Exception as err: print('failed to get gl scale info', err) + def get_bpy_data_from_name(self, stored_name, bpy_data_kind): + if isinstance(stored_name, str): + if stored_name in bpy_data_kind: + return bpy_data_kind.get(stored_name) + elif stored_name[3:] in bpy_data_kind: + return bpy_data_kind.get(stored_name[3:]) + + self.error(f"stored_name (string) '{stored_name}' not found in {bpy_data_kind}") + return None + classes = [ SverchCustomTree, -- GitLab From 84cc7649d6b8b7c87825b50a258e213fd9e2904e Mon Sep 17 00:00:00 2001 From: zeffii Date: Tue, 28 Apr 2020 15:45:46 +0200 Subject: [PATCH 03/12] small rework of string storage --- nodes/generator/script1_lite.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/nodes/generator/script1_lite.py b/nodes/generator/script1_lite.py index c53d4f522..7f8cb7733 100644 --- a/nodes/generator/script1_lite.py +++ b/nodes/generator/script1_lite.py @@ -274,16 +274,14 @@ class SvScriptNodeLite(bpy.types.Node, SverchCustomTreeNode): def load(self): - ''' ----- ''' if not self.script_name: return - if self.script_name in bpy.data.texts: - self.script_str = bpy.data.texts.get(self.script_name).as_string() - elif self.script_name[3:] in bpy.data.texts: - self.script_str = bpy.data.texts.get(self.script_name[3:]).as_string() + text = self.get_bpy_data_from_name(self.script_name, bpy.data.texts) + if text: + self.script_str = text.as_string() else: - print('bpy.data.texts not read yet') + print(f'bpy.data.texts not read yet, self.script_name="{self.script_name}"') if self.script_str: print('but script loaded locally anyway.') -- GitLab From 353f82b06f79303a19be5483c702dad7f8c86e32 Mon Sep 17 00:00:00 2001 From: zeffii Date: Tue, 28 Apr 2020 16:17:27 +0200 Subject: [PATCH 04/12] does this work ok? --- core/sockets.py | 7 ++++++- node_tree.py | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/sockets.py b/core/sockets.py index d44563b98..94f54c767 100644 --- a/core/sockets.py +++ b/core/sockets.py @@ -290,7 +290,12 @@ class SvObjectSocket(NodeSocket, SvSocketCommon): bl_idname = "SvObjectSocket" bl_label = "Object Socket" - object_ref: StringProperty(update=process_from_socket) + # object_ref: StringProperty(update=process_from_socket) + object_ref: bpy.props.PointerProperty( + name="Object Reference", + poll=lambda s, o: True, # optionally filter items out of the list of Collections presented to user + type=bpy.types.Object, # what kind of objects are we showing + update=process_from_socket) def draw(self, context, layout, node, text): if self.custom_draw: diff --git a/node_tree.py b/node_tree.py index e5968892c..3ae507c23 100644 --- a/node_tree.py +++ b/node_tree.py @@ -847,6 +847,8 @@ class SverchCustomTreeNode: return bpy_data_kind.get(stored_name) elif stored_name[3:] in bpy_data_kind: return bpy_data_kind.get(stored_name[3:]) + elif isinstance(stored_name, bpy.types.Object) and stored_name.name in bpy_data_kind: + return stored_name self.error(f"stored_name (string) '{stored_name}' not found in {bpy_data_kind}") return None -- GitLab From 340b73875d846b9f0eb04ed4fff0c338de354116 Mon Sep 17 00:00:00 2001 From: zeffii Date: Tue, 28 Apr 2020 20:57:46 +0200 Subject: [PATCH 05/12] fix comment --- node_tree.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/node_tree.py b/node_tree.py index 3ae507c23..c3ca2ffe6 100644 --- a/node_tree.py +++ b/node_tree.py @@ -842,6 +842,24 @@ class SverchCustomTreeNode: print('failed to get gl scale info', err) def get_bpy_data_from_name(self, stored_name, bpy_data_kind): + """ + this function acknowledges that the stored_name being passed can be a string or an object proper. + for a long time Sverchok stored the result of a prop_search as a StringProperty, and many nodes will + be stored with that data in .blends, here we try to permit older blends from having data stored as + a string, but newly used prop_search results will be stored as a pointerproperty of type bpy.types.Object + + regarding the need to trim the first 3 chars of a stored StringProperty, best let Blender devs enlighten you + https://developer.blender.org/T58641 + + example usage inside a node: + + text = self.get_bpy_data_from_name(self.filename, bpy.data.texts) + + if the text exit + + + """ + if isinstance(stored_name, str): if stored_name in bpy_data_kind: return bpy_data_kind.get(stored_name) -- GitLab From 7af1600206d3191ff862682f572d5db32fe11084 Mon Sep 17 00:00:00 2001 From: zeffii Date: Wed, 29 Apr 2020 10:25:57 +0200 Subject: [PATCH 06/12] use identifier as param name --- node_tree.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/node_tree.py b/node_tree.py index c3ca2ffe6..0caa9ffb1 100644 --- a/node_tree.py +++ b/node_tree.py @@ -841,12 +841,14 @@ class SverchCustomTreeNode: except Exception as err: print('failed to get gl scale info', err) - def get_bpy_data_from_name(self, stored_name, bpy_data_kind): + def get_bpy_data_from_name(self, identifier, bpy_data_kind): """ - this function acknowledges that the stored_name being passed can be a string or an object proper. + fail gracefuly? + + This function acknowledges that the identifier being passed can be a string or an object proper. for a long time Sverchok stored the result of a prop_search as a StringProperty, and many nodes will - be stored with that data in .blends, here we try to permit older blends from having data stored as - a string, but newly used prop_search results will be stored as a pointerproperty of type bpy.types.Object + be stored with that data in .blends, here we try to permit older blends having data stored as a string, + but newly used prop_search results will be stored as a pointerproperty of type bpy.types.Object regarding the need to trim the first 3 chars of a stored StringProperty, best let Blender devs enlighten you https://developer.blender.org/T58641 @@ -855,20 +857,20 @@ class SverchCustomTreeNode: text = self.get_bpy_data_from_name(self.filename, bpy.data.texts) - if the text exit + if the text does not exist you get None """ - if isinstance(stored_name, str): - if stored_name in bpy_data_kind: - return bpy_data_kind.get(stored_name) - elif stored_name[3:] in bpy_data_kind: - return bpy_data_kind.get(stored_name[3:]) - elif isinstance(stored_name, bpy.types.Object) and stored_name.name in bpy_data_kind: - return stored_name + if isinstance(identifier, str): + if identifier in bpy_data_kind: + return bpy_data_kind.get(identifier) + elif identifier[3:] in bpy_data_kind: + return bpy_data_kind.get(identifier[3:]) + elif isinstance(identifier, bpy.types.Object) and identifier.name in bpy_data_kind: + return identifier - self.error(f"stored_name (string) '{stored_name}' not found in {bpy_data_kind}") + self.error(f"identifier '{identifier}' not found in {bpy_data_kind}") return None -- GitLab From 85d6b95627ddc30c3070403ea12c3a36d9f6ea67 Mon Sep 17 00:00:00 2001 From: zeffii Date: Wed, 29 Apr 2020 11:19:50 +0200 Subject: [PATCH 07/12] restore ctrl_enter hotreload from texteditor --- utils/text_editor_plugins.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index a0230d9d7..b71f971e2 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -72,6 +72,14 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): 'SvProfileNode', 'SvTextInNode', 'SvGenerativeArtNode', 'SvSNFunctorB', 'SvRxNodeScript', 'SvProfileNodeMK2', 'SvVDExperimental', 'SvProfileNodeMK3']) + def compare_permutations_of_name(named_seeker, named_current): + """ try to find the stored datablock name, if these things fail then there is no compare anyway """ + try: + if named_seeker == named_current: return True + elif named_seeker[3:] == named_current: return True + except Exception as err: + print(f"Refesh Current Script called but encountered error {errr}") + for ng in ngs: # make sure this tree has nodes that demand updating. @@ -81,21 +89,22 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): for n in nodes: - if hasattr(n, "script_name") and n.script_name == text_file_name: + if hasattr(n, "script_name") and compare_permutations_of_name(n.script_name, text_file_name): try: n.load() + n.process_node(context) except SyntaxError as err: msg = "SyntaxError : {0}".format(err) self.report({"WARNING"}, msg) return {'CANCELLED'} - except: - self.report({"WARNING"}, 'unspecified error in load()') + except Exception as err: + self.report({"WARNING"}, f'unspecified error in load()\n{err}^^^^') return {'CANCELLED'} - elif hasattr(n, "text_file_name") and n.text_file_name == text_file_name: + elif hasattr(n, "text_file_name") and compare_permutations_of_name(n.text_file_name, text_file_name): pass # no nothing for profile node, just update ng, could use break... - elif hasattr(n, "current_text") and n.current_text == text_file_name: + elif hasattr(n, "current_text") and compare_permutations_of_name(n.current_text, text_file_name): n.reload() elif n.bl_idname == 'SvVDExperimental' and n.selected_draw_mode == "fragment": @@ -104,13 +113,13 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): n.custom_shader_location = n.custom_shader_location elif n.bl_idname == 'SvSNFunctorB': - if n.script_name.strip() == text_file_name.strip(): + if compare_permutations_of_name(n.script_name, text_file_name): with n.sv_throttle_tree_update(): print('handle the shortcut') n.handle_reload(context) # update node group with affected nodes - ng.update() + ng.sv_update() return {'FINISHED'} -- GitLab From c8595a7e7af46d6ef16c659f61f8006a41b0dbc3 Mon Sep 17 00:00:00 2001 From: zeffii Date: Wed, 29 Apr 2020 12:41:30 +0200 Subject: [PATCH 08/12] can return early --- utils/text_editor_plugins.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index b71f971e2..3a8c4b7e3 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -93,6 +93,7 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): try: n.load() n.process_node(context) + return {'FINISHED'} except SyntaxError as err: msg = "SyntaxError : {0}".format(err) self.report({"WARNING"}, msg) -- GitLab From 6c2e2515f6446575bae42e15c31b3a0dc4e04a06 Mon Sep 17 00:00:00 2001 From: zeffii Date: Thu, 30 Apr 2020 10:51:18 +0200 Subject: [PATCH 09/12] remove redundant things --- utils/text_editor_plugins.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index 3a8c4b7e3..ebeae1d67 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -22,24 +22,6 @@ import bpy from sverchok.utils.logging import debug, info, error -sv_error_message = '''\ -______________Sverchok Script Generator Node rules_______________ - -For this operation to work the current line must contain the text: -: 'def sv_main(**variables**):' - -Where '**variables**' is something like: -: 'verts=[], petal_size=2.3, num_petals=1' - -There are three types of input streams that this node can interpret: -- 'v' (vertices, 3-tuple coordinates) -- 's' (data: float, integer), -- 'm' (matrices: nested lists 4*4) - - For more information see the wiki - see also the bundled templates for clarification -''' - def has_selection(self, text): return not (text.select_end_line == text.current_line and @@ -78,7 +60,7 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): if named_seeker == named_current: return True elif named_seeker[3:] == named_current: return True except Exception as err: - print(f"Refesh Current Script called but encountered error {errr}") + print(f"Refesh Current Script called but encountered error {err}") for ng in ngs: -- GitLab From b3a5185801e0fceb168f9ecd43f941c53ce1c217 Mon Sep 17 00:00:00 2001 From: zeffii Date: Thu, 30 Apr 2020 11:32:52 +0200 Subject: [PATCH 10/12] revert to c8595a7 --- core/handlers.py | 74 +-- core/node_id_dict.py | 6 +- core/update_system.py | 12 +- .../modifier_change/merge_by_distance.rst | 52 -- .../modifier_change/modifier_change_index.rst | 2 +- .../modifier_change}/remove_doubles.rst | 0 docs/nodes/scene/scene_index.rst | 1 - docs/nodes/scene/viewer_layer.rst | 77 --- index.md | 6 +- .../Design/Adaptive_Voronoi_panel.json | 94 ++-- json_examples/Shapes/Holes_in_cone.json | 50 +- .../demo/Genetic_algorithm.py | 22 +- .../demo/recursive_subdivision.py | 22 +- .../demo/subidivide_to_quads.py | 9 +- nodes/generators_extended/polygon_grid.py | 4 +- nodes/modifier_change/merge_by_distance.py | 165 ------ .../modifier_change}/remove_doubles.py | 2 - nodes/scene/viewer_layer.py | 497 ------------------ utils/sv_default_macros.py | 1 - utils/text_editor_plugins.py | 20 +- 20 files changed, 139 insertions(+), 977 deletions(-) delete mode 100644 docs/nodes/modifier_change/merge_by_distance.rst rename docs/{old/nodes => nodes/modifier_change}/remove_doubles.rst (100%) delete mode 100644 docs/nodes/scene/viewer_layer.rst delete mode 100644 nodes/modifier_change/merge_by_distance.py rename {old_nodes => nodes/modifier_change}/remove_doubles.py (98%) delete mode 100644 nodes/scene/viewer_layer.py diff --git a/core/handlers.py b/core/handlers.py index 7b1152e72..fee0bdee4 100644 --- a/core/handlers.py +++ b/core/handlers.py @@ -18,56 +18,19 @@ pre_running = False sv_depsgraph = [] depsgraph_need = False -subscription_owner = object() - -""" -The nodes that need to subscribe to object/attribute changes should call this -convenience function from within their setup_subscription method (typically -invoked by the sv_setup_subscriptions below, after loading a blender file). -""" -def subscribe_to_changes(subscribe_to, message, callback): - debug("* handlers: subscribe_to_changes: %s", message) - bpy.msgbus.subscribe_rna( - key=subscribe_to, - owner=subscription_owner, - args=(message,), - notify=callback, - options={"PERSISTENT", } - ) - - -""" -This is called automatically after loading a blender file (load_post) to give -all the nodes the opportunity to (re)subscribe to object/attribute changes. - -A node that needs to subscribe to object/attribute changes should implement a -setup_subscriptions method and within that method use the subscribe_to_changes -convenience function above to setup all its necesssary subscriptions. -""" -def sv_setup_subscriptions(): - debug("* handlers: sv_setup_subscriptions") - - for node_tree in sverchok_trees(): - for node in node_tree.nodes: - setup_subscriptions = getattr(node, "setup_subscriptions", None) - if callable(setup_subscriptions): - node.setup_subscriptions() - - def get_sv_depsgraph(): global sv_depsgraph global depsgraph_need if not depsgraph_need: + sv_depsgraph = bpy.context.evaluated_depsgraph_get() depsgraph_need = True return sv_depsgraph - def set_sv_depsgraph_need(val): global depsgraph_need depsgraph_need = val - def sverchok_trees(): for ng in bpy.data.node_groups: if ng.bl_idname == 'SverchCustomTreeType': @@ -90,7 +53,6 @@ def has_frame_changed(scene): # If at any time the undo system is fixed and does call "node.free()" when a node is removed # after ctrl+z. then these two functions and handlers are no longer needed. - @persistent def sv_handler_undo_pre(scene): from sverchok.core import undo_handler_node_count @@ -99,7 +61,6 @@ def sv_handler_undo_pre(scene): undo_handler_node_count['sv_groups'] += len(ng.nodes) - @persistent def sv_handler_undo_post(scene): CurrentEvents.new_event(BlenderEventsTypes.undo) @@ -189,6 +150,7 @@ def sv_main_handler(scene): pre_running = False +@persistent def sv_clean(scene): """ Cleanup callbacks, clean dicts. @@ -199,14 +161,15 @@ def sv_clean(scene): data_structure.sv_Vars = {} data_structure.temp_handle = {} - @persistent -def sv_handler_load_pre(scene): - """ Various things to do before (re)loading a blend file """ +def sv_pre_load(scene): + sv_clean(scene) + set_first_run(True) -def sv_ensure_nodetree_data_after_blender_load(): +@persistent +def sv_post_load(scene): """ Upgrade nodes, apply preferences and do an update. """ @@ -215,7 +178,8 @@ def sv_ensure_nodetree_data_after_blender_load(): # ensure current nodeview view scale / location parameters reflect users' system settings from sverchok import node_tree - node_tree.SverchCustomTreeNode.get_and_set_gl_scale_info(None, "sv_ensure_nodetree_data_after_blender_load") + node_tree.SverchCustomTreeNode.get_and_set_gl_scale_info(None, "sv_post_load") + for monad in (ng for ng in bpy.data.node_groups if ng.bl_idname == 'SverchGroupTreeType'): if monad.input_node and monad.output_node: @@ -251,17 +215,6 @@ def sv_ensure_nodetree_data_after_blender_load(): ng.update() -@persistent -def sv_handler_load_post(scene): - """ Various things to do after (re)loading a blend file """ - - # update node tree data - sv_ensure_nodetree_data_after_blender_load() - - # update setup subscriptions - sv_setup_subscriptions() - - def set_frame_change(mode): post = bpy.app.handlers.frame_change_post pre = bpy.app.handlers.frame_change_pre @@ -272,7 +225,7 @@ def set_frame_change(mode): post.remove(sv_update_handler) if sv_update_handler in pre: pre.remove(sv_update_handler) - # if sv_scene_handler in scene: + #if sv_scene_handler in scene: # scene.remove(sv_scene_handler) # apply the right one @@ -285,13 +238,14 @@ def set_frame_change(mode): handler_dict = { 'undo_pre': sv_handler_undo_pre, 'undo_post': sv_handler_undo_post, - 'load_pre': sv_handler_load_pre, - 'load_post': sv_handler_load_post, - 'depsgraph_update_pre': sv_main_handler, + 'load_pre': sv_pre_load, + 'load_post': sv_post_load, + 'depsgraph_update_pre': sv_main_handler } def register(): + app_handler_ops(append=handler_dict) data_structure.setup_init() diff --git a/core/node_id_dict.py b/core/node_id_dict.py index ccecd6de8..c81087bfe 100644 --- a/core/node_id_dict.py +++ b/core/node_id_dict.py @@ -49,9 +49,9 @@ class SvNodesDict: tree_id = node_tree.tree_id if not tree_id in self.sv_node_dict_cache: self.load_nodes(node_tree) - - if n_id in self.sv_node_dict_cache[tree_id]: - del self.sv_node_dict_cache[tree_id][n_id] + else: + if n_id in self.sv_node_dict_cache[tree_id]: + del self.sv_node_dict_cache[tree_id][n_id] def load_nodes(self, node_tree): tree_id = node_tree.tree_id diff --git a/core/update_system.py b/core/update_system.py index c071493f3..a93f7377e 100644 --- a/core/update_system.py +++ b/core/update_system.py @@ -198,7 +198,7 @@ def separate_nodes(ng, links=None): node_set_list[-1].add(n) found_node_sets = [ns for ns in node_set_list if len(ns) > 1] - + if hasattr(ng, "sv_subtree_evaluation_order"): sorting_type = ng.sv_subtree_evaluation_order if sorting_type in {'X', 'Y'}: @@ -357,7 +357,7 @@ def do_update_general(node_list, nodes, procesed_nodes=set()): timings = [] graph = [] gather = graph.append - + total_time = 0 done_nodes = set(procesed_nodes) @@ -387,19 +387,19 @@ def do_update_general(node_list, nodes, procesed_nodes=set()): update_error_nodes(ng, node_name, err) #traceback.print_tb(err.__traceback__) exception("Node %s had exception: %s", node_name, err) - + if hasattr(ng, "sv_show_error_in_tree"): # not yet supported in monad trees.. if ng.sv_show_error_in_tree: error_text = traceback.format_exc() start_exception_drawing_with_bgl(ng, node_name, error_text, err) - + return None graphs.append(graph) if data_structure.DEBUG_MODE: debug("Node set updated in: %.4f seconds", total_time) - + return timings @@ -522,7 +522,7 @@ def process_tree(ng=None): def reload_sverchok(): data_structure.RELOAD_EVENT = False from sverchok.core import handlers - handlers.sv_handler_load_post([]) + handlers.sv_post_load([]) def get_update_lists(ng): """ diff --git a/docs/nodes/modifier_change/merge_by_distance.rst b/docs/nodes/modifier_change/merge_by_distance.rst deleted file mode 100644 index 4431e5d90..000000000 --- a/docs/nodes/modifier_change/merge_by_distance.rst +++ /dev/null @@ -1,52 +0,0 @@ -Merge by Distance -================= - -Functionality -------------- - -This merges vertices that are closer that a defined threshold, as do same-named command in blender - -Inputs ------- - -- **Distance** -- **Vertices** -- **PolyEdge** -- **FaceData**. List containing an arbitrary data item for each face of input - mesh. For example, this may be used to provide material indexes of input - mesh faces. Optional input. -- **Mask**. Vector mask to select the affected vertices - - -Parameters ----------- - -+-----------+-----------+-----------+-------------------------------------------+ -| Param | Type | Default | Description | -+===========+===========+===========+===========================================+ -| Distance | Float | 0.001 | Maximum distance to weld vertices | -+-----------+-----------+-----------+-------------------------------------------+ - -Outputs -------- - -This node has the following outputs: - -- **Vertices** -- **Edges** -- **Polygons** -- **Doubles**. Vertices, that were deleted. -- **FaceData**. List containing data items from the **FaceData** input, which - contains one item for each output mesh face. -- **Mask** The mask after the merge - -Examples of usage ------------------ - -.. image:: https://raw.githubusercontent.com/vicdoval/sverchok/docs_images/images_for_docs/modifier_change/merge_by_distance/sverchok_blender_merge_by_distance_example_01.png - -.. image:: https://raw.githubusercontent.com/vicdoval/sverchok/docs_images/images_for_docs/modifier_change/merge_by_distance/sverchok_blender_merge_by_distance_example_02.png - -.. image:: https://raw.githubusercontent.com/vicdoval/sverchok/docs_images/images_for_docs/modifier_change/merge_by_distance/sverchok_blender_merge_by_distance_example_03.png - -.. image:: https://raw.githubusercontent.com/vicdoval/sverchok/docs_images/images_for_docs/modifier_change/merge_by_distance/sverchok_blender_merge_by_distance_example_04.png diff --git a/docs/nodes/modifier_change/modifier_change_index.rst b/docs/nodes/modifier_change/modifier_change_index.rst index 9f2b95d7d..f2a76585a 100644 --- a/docs/nodes/modifier_change/modifier_change_index.rst +++ b/docs/nodes/modifier_change/modifier_change_index.rst @@ -19,7 +19,6 @@ Modifier Change extrude_region holes_fill flip_normals - merge_by_distance mesh_join mesh_separate objects_along_edge @@ -28,6 +27,7 @@ Modifier Change edge_boom polygons_to_edges recalc_normals + remove_doubles triangulate triangulate_heavy planar_faces diff --git a/docs/old/nodes/remove_doubles.rst b/docs/nodes/modifier_change/remove_doubles.rst similarity index 100% rename from docs/old/nodes/remove_doubles.rst rename to docs/nodes/modifier_change/remove_doubles.rst diff --git a/docs/nodes/scene/scene_index.rst b/docs/nodes/scene/scene_index.rst index b99baefaa..4cfa0c754 100644 --- a/docs/nodes/scene/scene_index.rst +++ b/docs/nodes/scene/scene_index.rst @@ -21,4 +21,3 @@ Scene particles_MK2 node_remote selection_grabber_lite - viewer_layer diff --git a/docs/nodes/scene/viewer_layer.rst b/docs/nodes/scene/viewer_layer.rst deleted file mode 100644 index ce85decf6..000000000 --- a/docs/nodes/scene/viewer_layer.rst +++ /dev/null @@ -1,77 +0,0 @@ -Viewer Layer -============ - -Functionality -------------- - -This node helps you manage multiple viewer nodes in a centralized way. - -It allows you to create multiple layers (groups) to which you can add any of the supported viewer nodes [1] available in the node tree. Once the viewer nodes are added to the ViewerLayer node you can change their attributes (ON/OFF status, vert/edge/face display status and colors etc) directly from within the ViewerLayer node without having to navigate to each viewer node in the node tree to adjust those settings. Additionally, the ViewerLayer node also allows for various operations to be applied to all layers or all viewers in a layer at once (e.g. hide/show all, turn ON/OFF vert/edge/face display for all, collapse viewers in a layer or collapse all layers). - -Notes: -[1] : Currently the supported viewer nodes are the "Viewer Draw" and the "Viewer Index" nodes. - -One usefulness of this node is that you can group together various viewer nodes that belong together in rendering some information in the viewport and you can easily turn ON/OFF all those viewers at once with miminal interaction (sometimes with just one click). - - -Node Operations ---------------- -The node level operations that apply to all layers in the node are: -* Collapse/Expand all layers (via mix-status toggle button) -* Turn ON/OFF vert/edge/face display (via corresponding mix-status toggle buttons) -* Turn ON/OFF visibility of layers/viewers (via corresponding mix-status toggle buttons) -* Add Layer to node (via "Add Layer" (plus list) button at the bottom of the node) - - -Layer Operations ----------------- -The layer level operations that apply to all viewers in the layer are: -* Remove Layer from node (via "Remove Layer" (minus) button following the layer name) -* Rename Layer (layers are allowed to have same name) -* Collapse/Expand Layer (via "Expand" button in front of the layer name) -* Turn ON/OFF (visibility status) of all viewers in Layer -* Add Viewer to Layer (via "Add Viewer" (plus) button at the bottom of the layer) - -Notes: -- There are no limitations on the number of layers a ViewerLayer node can create. -- Once a layer is created, a "Add Viewer" (plus) button is shown at the bottom of the layer to allow viewer entries to be created for each layer. Once the number of viewer entries is the same as the number of available viewer nodes in the node tree, the "Add Viewer" button is hidden. - - -Viewer Operations ------------------ -The viewer level operations that apply to each viewer in the layer are: -* Remove Viewer (via "Remove Viewer" (minus) button next to the viewer entry) -* Select Viewer (from drop down of avaialable viewer nodes) -* Update ON/OFF status and vert/edge/face display status and colors (via corresponding UI) - -Notes: -- The "Remove Viewer" button is only displayed when the viewer entry is empty. -- The viewer selection options (viewer name drop down list) of a viewer entry is the list of the names of all the available viewer nodes in the node tree, excluding the viewer nodes already added to the layer. This is to ensure no duplicate viewers are added to a layer, and also to facilitate selection by providing a shorter list with only those viewers that have not yet been selected yet for a layer. - - -ON, OFF and MIX status ----------------------- -When the layers in the node or the viewers in a layer have an ON status, the corresponding ON/OFF toggle button will show the "Eye Open" icon, indicating the overall status of its descendants. Tapping on the toggle button will turn all its descendants status to OFF. - -When the layers in the node or the viewers in a layer have an OFF status, the ON/OFF toggle button will show the "Eye Close" icon indicating the overall status of its descendants. Tapping on the toggle button will turn all its descendants status to ON. - -When the layers in the node or the viewers in a layer have a MIX (ON and OFF) status, the ON/OF toggle button will show a "Dot" icon, indicating the overall status of its descendants (layers or viewers). Tapping on the toggle button will turn all its descendants status to ON. - -Note: If a parent level (node or layer) has a MIX status and you want to turn all descendants OFF, you need to tap the ON/OFF toggle button twice: once to turn all ON and second to turn all OFF. - -Similar ON/OFF/MIX behavior holds true for the for the vert/edge/face display toggle buttons, except that the icons stays the same (vert/edge/face icon). - - -Renaming viewer nodes externally --------------------------------- -When a viewer node is renamed externally the ViewerLayer node will capture the name change and will invalidate all the viewer entries in all layers that reference the older names (those entries will be highlighted in RED, assuming the default Blender color theme). In this case you can either chose to remove that viewer entry from the layers or reselect a new viewer for those entries from the latest list of viewers. - -Note: Once SV provides a feature to have a fixed, unique ID assigned to every node created (and saved with the blend file), which could be used as a reference, instead of the viewer nodes name, the ViewerLayer node would be able to capture the external changes to the viewer node names and automatically update the names in the layer entries without needing to invalidate viewer entries. Until then, the manual removal / update of the invalidated viewer entries is necessary. So, keep this in mind when you change the viewer node names externally. For this reason it's best to rename the viewer nodes before adding them to the ViewerLayer nodes, and then resist the temptation to change their names. :) - - -Extra Viewer settings ---------------------- -Based on the width of the ViewerLayer node additional settings for the viewers are shown/hidden. For narrow width, the viewer name and visibility toggle button are shown. For larger (>300px) width the vert/edge/face colors are also shown. And for even larger width (>400px) the vert/edge/face display status toggle buttons are also shown. - - - diff --git a/index.md b/index.md index ff2dbdf11..5832d905a 100644 --- a/index.md +++ b/index.md @@ -185,7 +185,7 @@ ## Modifier Change SvDeleteLooseNode - SvMergeByDistanceNode + SvRemoveDoublesNode SvSeparateMeshNode SvSeparatePartsToIndexes SvLimitedDissolve @@ -438,8 +438,6 @@ SvFCurveInNodeMK1 SvCollectionPicker SvSelectionGrabberLite - --- - SvViewerLayerNode ## Objects SvVertexGroupNodeMK2 @@ -484,7 +482,6 @@ --- SvCombinatoricsNode - ## Alpha Nodes SvBManalyzinNode SvBMObjinputNode @@ -508,4 +505,3 @@ --- SvGetPropNodeMK2 SvSetPropNodeMK2 - diff --git a/json_examples/Design/Adaptive_Voronoi_panel.json b/json_examples/Design/Adaptive_Voronoi_panel.json index 18d31293b..4ced47be0 100644 --- a/json_examples/Design/Adaptive_Voronoi_panel.json +++ b/json_examples/Design/Adaptive_Voronoi_panel.json @@ -9,13 +9,13 @@ "List Math.001": "Frame.001", "Map Range": "Frame.001", "Map Range.001": "Frame", - "Merge by Distance": "Frame.002", "Mesh Expression": "Frame", "Move.001": "Frame.003", "Note": "Frame.002", "Note.001": "Frame.002", "Origins": "Frame.001", "Plane": "Frame.003", + "Remove Doubles": "Frame.002", "Vector Math": "Frame.003", "Vector Math.001": "Frame.003", "Vector Noise": "Frame.001", @@ -216,20 +216,6 @@ }, "width": 140.0 }, - "Merge by Distance": { - "bl_idname": "SvMergeByDistanceNode", - "height": 100.0, - "hide": false, - "label": "", - "location": [ - 184.88937377929688, - 143.97623443603516 - ], - "params": { - "distance": 0.10000000149011612 - }, - "width": 140.0 - }, "Mesh Expression": { "bl_idname": "SvMeshEvalNode", "geom": "{\n \"defaults\": {\n \"Close\": 0.0\n },\n \"vertices\": [\n [\n 0.0,\n 0.0,\n 0.0\n ],\n [\n 2.0,\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 2.0,\n 0.0\n ],\n [\n 2.0,\n 2.0,\n 0.0\n ],\n [\n 0.0,\n 0.2,\n 0.0\n ],\n [\n 2.0,\n 0.2,\n 0.0\n ],\n [\n 2.0,\n 1.0,\n 0.0\n ],\n [\n 0.0,\n 1.0,\n 0.0\n ],\n [\n 0.0,\n \"0.2 + Close\",\n 0.7,\n [\n \"Selected\"\n ]\n ],\n [\n 2.0,\n \"0.2 + Close\",\n 0.7,\n [\n \"Selected\"\n ]\n ],\n [\n 2.0,\n \"1.0 + Close\",\n 0.7,\n [\n \"Selected\"\n ]\n ],\n [\n 0.0,\n \"1.0 + Close\",\n 0.7,\n [\n \"Selected\"\n ]\n ]\n ],\n \"edges\": [\n [\n 0,\n 4\n ],\n [\n 0,\n 1\n ],\n [\n 3,\n 6\n ],\n [\n 2,\n 3\n ],\n [\n 1,\n 5\n ],\n [\n 4,\n 5\n ],\n [\n 2,\n 7\n ],\n [\n 6,\n 7\n ],\n [\n 8,\n 11\n ],\n [\n 8,\n 9\n ],\n [\n 9,\n 10\n ],\n [\n 10,\n 11\n ],\n [\n 5,\n 9\n ],\n [\n 4,\n 8\n ],\n [\n 7,\n 11\n ],\n [\n 6,\n 10\n ]\n ],\n \"faces\": [\n [\n 7,\n 6,\n 3,\n 2\n ],\n [\n 0,\n 1,\n 5,\n 4\n ],\n [\n 4,\n 5,\n 9,\n 8\n ],\n [\n 8,\n 9,\n 10,\n 11\n ],\n [\n 6,\n 7,\n 11,\n 10\n ]\n ],\n \"vertexdata\": [],\n \"facedata\": [\n 0,\n 0,\n 0,\n 0,\n 0\n ]\n}", @@ -336,6 +322,20 @@ "use_custom_color": true, "width": 140.0 }, + "Remove Doubles": { + "bl_idname": "SvRemoveDoublesNode", + "height": 100.0, + "hide": false, + "label": "", + "location": [ + 177.19818115234375, + 128.98429107666016 + ], + "params": { + "distance": 0.10000000149011612 + }, + "width": 140.0 + }, "Reroute": { "bl_idname": "NodeReroute", "height": 100.0, @@ -575,23 +575,23 @@ [ "Voronoi 2D", 0, - "Merge by Distance", - 0 + "Remove Doubles", + 1 ], [ "Voronoi 2D", 1, - "Merge by Distance", - 1 + "Remove Doubles", + 2 ], [ - "Merge by Distance", + "Remove Doubles", 0, "Fill Holes", 0 ], [ - "Merge by Distance", + "Remove Doubles", 1, "Fill Holes", 1 @@ -610,14 +610,14 @@ ], [ "Flip normals", - "Polygons", - "Reroute", + "Vertices", + "Reroute.001", "Input" ], [ "Flip normals", - "Vertices", - "Reroute.001", + "Polygons", + "Reroute", "Input" ], [ @@ -641,57 +641,57 @@ [ "Vector Noise", 0, - "List Math.001", + "List Math", 0 ], [ "Vector Noise", 0, - "List Math", + "List Math.001", 0 ], [ "Vector Noise", 0, - "Map Range.001", + "Map Range", 0 ], [ "List Math", 0, - "Map Range.001", + "Map Range", 1 ], [ "List Math.001", 0, - "Map Range.001", + "Map Range", 2 ], - [ - "Map Range.001", - 0, - "Mesh Expression", - 0 - ], [ "Vector Noise", 0, - "Map Range", + "Map Range.001", 0 ], [ "List Math", 0, - "Map Range", + "Map Range.001", 1 ], [ "List Math.001", 0, - "Map Range", + "Map Range.001", 2 ], + [ + "Map Range.001", + 0, + "Mesh Expression", + 0 + ], [ "Reroute.001", "Output", @@ -735,27 +735,27 @@ 2 ], [ - "Voronoi 2D", + "Move.001", 0, - "Viewer Draw Mk3.001", + "Viewer Draw Mk3.002", 0 ], [ - "Voronoi 2D", + "Plane", 1, - "Viewer Draw Mk3.001", + "Viewer Draw Mk3.002", 1 ], [ - "Move.001", + "Voronoi 2D", 0, - "Viewer Draw Mk3.002", + "Viewer Draw Mk3.001", 0 ], [ - "Plane", + "Voronoi 2D", 1, - "Viewer Draw Mk3.002", + "Viewer Draw Mk3.001", 1 ] ] diff --git a/json_examples/Shapes/Holes_in_cone.json b/json_examples/Shapes/Holes_in_cone.json index 008e6d3de..fa38bb860 100644 --- a/json_examples/Shapes/Holes_in_cone.json +++ b/json_examples/Shapes/Holes_in_cone.json @@ -4,9 +4,9 @@ "Circle": "Frame.001", "Crop mesh 2D": "Frame.001", "Matrix Apply.001": "Frame.002", - "Merge by Distance": "Frame.002", "Origins": "Frame", "Polygon Boom": "Frame", + "Remove Doubles": "Frame.002", "Vector Drop": "Frame" }, "groups": {}, @@ -73,7 +73,7 @@ }, "Frame": { "bl_idname": "NodeFrame", - "height": 274.2661437988281, + "height": 273.26617431640625, "hide": false, "label": "Take each face and put it into XOY plane", "location": [ @@ -93,11 +93,11 @@ 10.079999923706055 ], "params": {}, - "width": 442.3966064453125 + "width": 442.39654541015625 }, "Frame.002": { "bl_idname": "NodeFrame", - "height": 335.32904052734375, + "height": 293.3472900390625, "hide": false, "label": "Put faces back in their places", "location": [ @@ -105,7 +105,7 @@ 10.079999923706055 ], "params": {}, - "width": 419.053955078125 + "width": 466.843505859375 }, "Matrix Apply.001": { "bl_idname": "SvMatrixApplyJoinNode", @@ -121,18 +121,6 @@ }, "width": 141.03147888183594 }, - "Merge by Distance": { - "bl_idname": "SvMergeByDistanceNode", - "height": 100.0, - "hide": false, - "label": "", - "location": [ - 1569.7108039855957, - 63.329030990600586 - ], - "params": {}, - "width": 140.0 - }, "Origins": { "bl_idname": "SvOrigins", "height": 100.0, @@ -160,6 +148,18 @@ "params": {}, "width": 140.0 }, + "Remove Doubles": { + "bl_idname": "SvRemoveDoublesNode", + "height": 100.0, + "hide": false, + "label": "", + "location": [ + 1617.5003547668457, + 54.68060874938965 + ], + "params": {}, + "width": 140.0 + }, "Solidify": { "bl_idname": "SvSolidifyNode", "height": 100.0, @@ -169,9 +169,7 @@ 1814.6839599609375, 116.75218963623047 ], - "params": { - "thickness": 0.09999999403953552 - }, + "params": {}, "width": 140.0 }, "Vector Drop": { @@ -292,23 +290,23 @@ [ "Matrix Apply.001", 0, - "Merge by Distance", - 0 + "Remove Doubles", + 1 ], [ "Matrix Apply.001", 2, - "Merge by Distance", - 1 + "Remove Doubles", + 2 ], [ - "Merge by Distance", + "Remove Doubles", 0, "Solidify", 1 ], [ - "Merge by Distance", + "Remove Doubles", 2, "Solidify", 2 diff --git a/node_scripts/SNLite_templates/demo/Genetic_algorithm.py b/node_scripts/SNLite_templates/demo/Genetic_algorithm.py index eff89288d..0b130b479 100644 --- a/node_scripts/SNLite_templates/demo/Genetic_algorithm.py +++ b/node_scripts/SNLite_templates/demo/Genetic_algorithm.py @@ -13,9 +13,7 @@ in population s d=20 n=2 in generations s d=10000 n=2 in threshold s d=0.9 n=2 in mutator s d=0.1 n=2 -in mutofactor s d=0.1 n=2 in selector s d=0.2 n=2 -in random_seed s d=0 n=2 in all_apart s d=0 n=2 out vers_final v out vers_descr v @@ -64,7 +62,7 @@ def compare_two_lists(agent_list,pattern): def ga(): agents = init_agents(population, in_str_len) - stepper = 0.76 + stepper = 0.1 for generation in range(generations): @@ -77,14 +75,14 @@ def ga(): if any(agent.fitness >= stepper for agent in agents): combo.append(sorted(agents, key=lambda agent: agent.fitness, reverse=True)[0].string) - print(f"GA fitness >= {round(stepper,2)}, in #{generation} generation") - stepper += 0.02 + stepper += 0.1 if any(agent.fitness >= threshold for agent in agents): + print (f'Last generation #{str(generation)}') agent = sorted(agents, key=lambda agent: agent.fitness, reverse=True)[0] - print (f'GA ended \ - \nGA fitness: {round(agent.fitness,4)}, in #{str(generation)} generation \ - \nGA values: {[[round(i,2) for i in x] for x in agent.string[:2]]} ... ') + print (f'GA ended with {type(agent.string)} {len(agent.string)}, \ + \n{agent.string[:3]}... \ + \nFitness: {agent.fitness}') return agent.string return [None] @@ -138,7 +136,7 @@ def mutation(agents): for agent in agents: for idx, param in enumerate(agent.string): - if random.uniform(0.0, 1.0) <= mutofactor: + if random.uniform(0.0, 1.0) <= mutator: if all_apart == 0: agent.string = agent.string[0:idx] + \ [(random.choice(data[0]))] + \ @@ -155,16 +153,14 @@ def mutation(agents): return agents if data and pattern: - random.seed(random_seed) in_str = pattern[0] emax = lambda a,b: a if (a > b) else b emin = lambda a,b: a if (a < b) else b all_max = reduce(emax,[reduce(emax, x) for x in in_str]) all_min = reduce(emin,[reduce(emin, x) for x in in_str]) all_dif = all_max-all_min - print(f'------------------------------------ \ - \nGA started \ - \nGA values: {[[round(i,2) for i in x] for x in in_str[:2]]} ...') + print(f'GA initialised with {type(in_str)} {len(in_str)} \ + \n{in_str[:3]}...') in_str_len = len(in_str) combo = [] vers_final = [ga()] diff --git a/node_scripts/SNLite_templates/demo/recursive_subdivision.py b/node_scripts/SNLite_templates/demo/recursive_subdivision.py index 4d84e4684..e110d8285 100644 --- a/node_scripts/SNLite_templates/demo/recursive_subdivision.py +++ b/node_scripts/SNLite_templates/demo/recursive_subdivision.py @@ -5,13 +5,12 @@ in seed s d=1 n=2 in random_factor s d=0.1 n=2 in iterations s d=1 n=2 out verts v -out edges s out faces s """ from sverchok.utils.modules.geom_utils import interp_v3_v3v3 as lerp from sverchok.utils.sv_mesh_utils import mesh_join -from sverchok.utils.sv_bmesh_utils import remove_doubles +from sverchok.nodes.modifier_change.remove_doubles import remove_doubles import random # loosly based on https://www.youtube.com/watch?v=GhquYJ9m1Oc @@ -20,7 +19,7 @@ sort = lambda vex, pox: [vex[i] for i in pox] def random_subdiv_mesh(verts_m, pols_m, iteration): - verts, faces = [], [] + verts, faces =[],[] for pol in pols_m: verts_out, faces_out = [], [] new_quad = faces_out.append @@ -36,7 +35,7 @@ def random_subdiv_mesh(verts_m, pols_m, iteration): pos_f = lerp(pos_d, pos_b, 1-Y) # indices = 0, 1, 2, 3 - verts_out.extend(pts) + verts_out.extend(pts) # indices = 4, 5, 6, 7, 8, 9 verts_out.extend([pos_a, pos_b, pos_c, pos_d, pos_e, pos_f]) @@ -47,17 +46,16 @@ def random_subdiv_mesh(verts_m, pols_m, iteration): new_quad([7, 9, 6, 3]) faces.append(faces_out) verts.append(verts_out) - - verts, _, faces = mesh_join(verts, [], faces) - if iteration < 2 : - return verts, faces + + verts, _, faces = mesh_join(verts, [],faces) + if iteration <2 : + return verts,faces else: return random_subdiv_mesh(verts, faces, iteration - 1) - + if quad_verts and quad_faces: random.seed(seed) - verts, faces = random_subdiv_mesh(quad_verts[0], quad_faces[0], iterations) - verts, edges, faces = remove_doubles(verts, [], faces, 1e-5) + verts, faces = random_subdiv_mesh(quad_verts[0], quad_faces[0], iterations) + verts, _, faces, _, _ = remove_doubles(verts, faces, 1e-5, False) verts = [verts] - edges = [edges] faces = [faces] diff --git a/node_scripts/SNLite_templates/demo/subidivide_to_quads.py b/node_scripts/SNLite_templates/demo/subidivide_to_quads.py index 4ba97780a..15b521309 100644 --- a/node_scripts/SNLite_templates/demo/subidivide_to_quads.py +++ b/node_scripts/SNLite_templates/demo/subidivide_to_quads.py @@ -6,12 +6,11 @@ in random_factor s d=0. n=1 in seed s d=1 n=1 out verts v -out edges s out faces s """ from sverchok.utils.modules.geom_utils import interp_v3_v3v3 as lerp -from sverchok.utils.sv_bmesh_utils import remove_doubles +from sverchok.nodes.modifier_change.remove_doubles import remove_doubles from sverchok.data_structure import match_long_repeat as mlr import random @@ -71,7 +70,6 @@ def subdiv_mesh_to_quads(verts_mesh, pols_m, it, random_f): if verts_in and faces_in: verts = [] - edges = [] faces = [] seed_l = enusure_list(seed) iterations_l = enusure_list(iterations) @@ -79,8 +77,7 @@ if verts_in and faces_in: for v, f, s, it, r in zip(*mlr([verts_in, faces_in, seed_l, iterations_l, random_fac])): random.seed(s) - verts_out, faces_out = subdiv_mesh_to_quads(v, f, min(it, 5), r) - verts_out, edges_out, faces_out = remove_doubles(verts_out, [], faces_out, 1e-5) + verts_out, faces_out = subdiv_mesh_to_quads(v, f, min(it,5), r) + verts_out, _, faces_out, _, _ = remove_doubles(verts_out, faces_out, 1e-5, False) verts.append(verts_out) - edges.append(edges_out) faces.append(faces_out) diff --git a/nodes/generators_extended/polygon_grid.py b/nodes/generators_extended/polygon_grid.py index 7297b07dc..d10b64001 100644 --- a/nodes/generators_extended/polygon_grid.py +++ b/nodes/generators_extended/polygon_grid.py @@ -26,7 +26,7 @@ from sverchok.data_structure import updateNode, match_long_repeat from sverchok.ui.sv_icons import custom_icon from sverchok.utils.geom import circle from sverchok.utils.sv_mesh_utils import mesh_join -from sverchok.utils.sv_bmesh_utils import remove_doubles +from sverchok.nodes.modifier_change.remove_doubles import remove_doubles grid_layout_items = [ ("RECTANGLE", "Rectangle", "", custom_icon("SV_HEXA_GRID_RECTANGLE"), 0), @@ -216,7 +216,7 @@ def generate_tiles(tile_settings): if not separate: vert_list, edge_list, poly_list = mesh_join(vert_list, edge_list, poly_list) if scale == 1.0: - vert_list, edge_list, poly_list = remove_doubles(vert_list, [], poly_list, 0.001) + vert_list, edge_list, poly_list, _, _ = remove_doubles(vert_list, poly_list, 0.01, False) vert_grid_list.append(vert_list) edge_grid_list.append(edge_list) diff --git a/nodes/modifier_change/merge_by_distance.py b/nodes/modifier_change/merge_by_distance.py deleted file mode 100644 index fbcb765f4..000000000 --- a/nodes/modifier_change/merge_by_distance.py +++ /dev/null @@ -1,165 +0,0 @@ -# ##### 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 ##### -from itertools import chain, repeat -import bpy -from bpy.props import FloatProperty -import bmesh - -from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode, Vector_generate, repeat_last, zip_long_repeat -from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata, face_data_from_bmesh_faces, vert_data_from_bmesh_verts -from sverchok.utils.logging import info, debug - - -def remove_doubles(vertices, faces, distance, face_data=None, find_doubles=False, mask=[], output_mask=False): - - if faces: - edge_mode = (len(faces[0]) == 2) - else: - edge_mode = False - if face_data: - mark_face_data = True - else: - mark_face_data = False - - bm = bmesh_from_pydata( - vertices, - faces if edge_mode else [], - [] if edge_mode else faces, - markup_face_data=mark_face_data, - markup_vert_data=output_mask) - bm_verts = bm.verts - - if mask: - mask_full = chain(mask, repeat(mask[-1])) - bm_verts = [v for v, m in zip(bm_verts, mask_full) if m] - - if find_doubles: - res = bmesh.ops.find_doubles(bm, verts=bm_verts, dist=distance) - doubles = [vert.co[:] for vert in res['targetmap'].keys()] - else: - doubles = [] - - bmesh.ops.remove_doubles(bm, verts=bm_verts, dist=distance) - edges = [] - faces = [] - face_data_out = [] - bm.verts.index_update() - verts = [vert.co[:] for vert in bm.verts[:]] - - bm.edges.index_update() - bm.faces.index_update() - for edge in bm.edges[:]: - edges.append([v.index for v in edge.verts[:]]) - for face in bm.faces: - faces.append([v.index for v in face.verts[:]]) - if face_data: - face_data_out = face_data_from_bmesh_faces(bm, face_data) - if output_mask: - mask_out = vert_data_from_bmesh_verts(bm, mask) - else: - mask_out = [] - - bm.clear() - bm.free() - return (verts, edges, faces, face_data_out, doubles, mask_out) - - -class SvMergeByDistanceNode(bpy.types.Node, SverchCustomTreeNode): - """ - Triggers: Remove Doubles - Tooltip: Merge Vertices that are closer than a distance. - """ - bl_idname = 'SvMergeByDistanceNode' - bl_label = 'Merge by Distance' - bl_icon = 'OUTLINER_OB_EMPTY' - sv_icon = 'SV_REMOVE_DOUBLES' - - distance: FloatProperty( - name='Distance', description='Remove distance', - default=0.001, precision=3, min=0, update=updateNode) - - def sv_init(self, context): - self.inputs.new('SvVerticesSocket', 'Vertices') - self.inputs.new('SvStringsSocket', 'PolyEdge') - self.inputs.new('SvStringsSocket', 'FaceData') - self.inputs.new('SvStringsSocket', 'Mask') - self.inputs.new('SvStringsSocket', 'Distance').prop_name = 'distance' - - self.outputs.new('SvVerticesSocket', 'Vertices') - self.outputs.new('SvStringsSocket', 'Edges') - self.outputs.new('SvStringsSocket', 'Polygons') - self.outputs.new('SvStringsSocket', 'FaceData') - self.outputs.new('SvVerticesSocket', 'Doubles') - self.outputs.new('SvStringsSocket', 'Mask') - - def draw_buttons(self, context, layout): - #layout.prop(self, 'distance', text="Distance") - pass - - def process(self): - if not any(s.is_linked for s in self.outputs): - return - - if not self.inputs['Vertices'].is_linked: - return - - verts = Vector_generate(self.inputs['Vertices'].sv_get()) - polys = self.inputs['PolyEdge'].sv_get(default=[[]]) - face_data = self.inputs['FaceData'].sv_get(default=[[]]) - distance = self.inputs['Distance'].sv_get(default=[self.distance])[0] - has_double_out = self.outputs['Doubles'].is_linked - mask_s = self.inputs['Mask'].sv_get(default=[[]], deepcopy=False) - has_mask_out = self.inputs['Mask'].is_linked, self.outputs['Mask'].is_linked - verts_out = [] - edges_out = [] - polys_out = [] - face_data_out = [] - d_out = [] - mask_out = [] - - for v, p, ms, d, mask in zip_long_repeat(verts, polys, face_data, distance, mask_s): - res = remove_doubles(v, p, d, ms, has_double_out, mask=mask, output_mask=has_mask_out) - if not res: - return - verts_out.append(res[0]) - edges_out.append(res[1]) - polys_out.append(res[2]) - face_data_out.append(res[3]) - d_out.append(res[4]) - mask_out.append(res[5]) - - self.outputs['Vertices'].sv_set(verts_out) - - # restrict setting this output when there is no such input - if self.inputs['PolyEdge'].is_linked: - self.outputs['Edges'].sv_set(edges_out) - self.outputs['Polygons'].sv_set(polys_out) - - self.outputs['FaceData'].sv_set(face_data_out) - self.outputs['Doubles'].sv_set(d_out) - - self.outputs['Mask'].sv_set(mask_out) - - -def register(): - bpy.utils.register_class(SvMergeByDistanceNode) - - -def unregister(): - bpy.utils.unregister_class(SvMergeByDistanceNode) diff --git a/old_nodes/remove_doubles.py b/nodes/modifier_change/remove_doubles.py similarity index 98% rename from old_nodes/remove_doubles.py rename to nodes/modifier_change/remove_doubles.py index 32ef27b2b..ebda3059f 100644 --- a/old_nodes/remove_doubles.py +++ b/nodes/modifier_change/remove_doubles.py @@ -91,8 +91,6 @@ class SvRemoveDoublesNode(bpy.types.Node, SverchCustomTreeNode): bl_icon = 'OUTLINER_OB_EMPTY' sv_icon = 'SV_REMOVE_DOUBLES' - replacement_nodes = [('SvMergeByDistanceNode', None, None)] - distance: FloatProperty( name='Distance', description='Remove distance', default=0.001, precision=3, min=0, update=updateNode) diff --git a/nodes/scene/viewer_layer.py b/nodes/scene/viewer_layer.py deleted file mode 100644 index a86bff941..000000000 --- a/nodes/scene/viewer_layer.py +++ /dev/null @@ -1,497 +0,0 @@ -# This file is part of project Sverchok. It's copyrighted by the contributors -# recorded in the version control history of the file, available from -# its original location https://github.com/nortikin/sverchok/commit/master -# -# SPDX-License-Identifier: GPL3 -# License-Filename: LICENSE - - -import bpy -from bpy.props import FloatProperty, BoolProperty, StringProperty, CollectionProperty, IntProperty - -import sverchok -from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode -from sverchok.core.handlers import subscribe_to_changes, sverchok_trees -from sverchok.utils.logging import debug - - -layer_names = [ - "Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", - "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", - "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega"] - -# set of supported viewer nodes + mapping of their various respective attributes -viewer_dict = { - 'SvVDExperimental': { - 'display': { - 'vert': "display_verts", - 'edge': "display_edges", - 'face': "display_faces" - }, - 'colors': { - 'vert': "vert_color", - 'edge': "edge_color", - 'face': "face_color" - } - }, - 'SvIDXViewer28': { - 'display': { - 'vert': "display_vert_index", - 'edge': "display_edge_index", - 'face': "display_face_index" - }, - 'colors': { - 'vert': "numid_verts_col", - 'edge': "numid_edges_col", - 'face': "numid_faces_col" - } - } -} - -elements = {'vert': 'UV_VERTEXSEL', 'edge': 'UV_EDGESEL', 'face': 'UV_FACESEL'} - - -def viewer_name_change_callback(self): - ''' Subscription callback for viewer node name change (calls from handlers.py) ''' - debug("* VLN: viewer_name_change_callback") - # propagate the name change callback to all Viewer Layer nodes - for node_tree in sverchok_trees(): - layer_nodes = [n for n in node_tree.nodes if n.bl_idname == "SvViewerLayerNode"] - for node in layer_nodes: - debug("VLN: propagate name change callback to: %s", node.bl_idname) - node.viewer_changed_name() - - -def subscribe_to_viewer_nodes_name_changes(): - ''' Subscribe to name change of various viewer nodes (calls to handlers.py) ''' - debug("* VLN: layer_nodes_subscribe_to_viewer_changes") - VIZ_NODE1 = sverchok.nodes.viz.vd_draw_experimental.SvVDExperimental - VIZ_NODE2 = sverchok.nodes.viz.viewer_idx28.SvIDXViewer28 - - subscribe_to_list = [(VIZ_NODE1, "name"), (VIZ_NODE2, "name")] - - for subscribe_to in subscribe_to_list: - subscribe_to_changes(subscribe_to, "Viewer node name changed", viewer_name_change_callback) - - -def update_viewer_list(self, context): - ''' Update callback (wrapper) when a viewer entry name changes in the layer node ''' - debug("* VLN: SvViewerGroup: update_viewer_list") - viewer_name_change_callback(None) - - -class SvLayerOperatorCallback(bpy.types.Operator): - ''' Delegate layer changes to the layer node ''' - bl_idname = "nodes.sv_viewer_layer_callback" - bl_label = "Sv Ops Layer callback" - - function_name: StringProperty() # what function to call - layer_name: StringProperty() # layer name - layer_id: IntProperty() # unique id to find layer in the node - element_type: StringProperty() # "vert", "edge" or "face" - - def execute(self, context): - n = context.node - getattr(n, self.function_name)(self) - return {"FINISHED"} - - -class SvViewerOperatorCallback(bpy.types.Operator): - ''' Delegate viewer changes to the layer node ''' - bl_idname = "nodes.sv_viewer_callback" - bl_label = "Sv Ops Viewer callback" - - function_name: StringProperty() # what function to call - layer_name: StringProperty() # layer name - layer_id: IntProperty() # unique id to find layer in the node - viewer_id: IntProperty() # unique id to find viewer in the layer - - def execute(self, context): - n = context.node - getattr(n, self.function_name)(self.layer_id, self.viewer_id) - return {"FINISHED"} - - -class SvViewerGroup(bpy.types.PropertyGroup): - ''' Property group for the viewer entries ''' - collection_name: CollectionProperty(name="List of Viewers", type=bpy.types.PropertyGroup) - node_name: StringProperty(update=update_viewer_list) - viewer_id: IntProperty(name="Viewer ID", description="ID of the viewer's entry in the layer") - - -class SvViewerLayerGroup(bpy.types.PropertyGroup): - ''' Property group for the layer entries ''' - collection_name: CollectionProperty(name="List of Layers", type=bpy.types.PropertyGroup) - viewers: CollectionProperty(name="Viewers", type=SvViewerGroup) - expand: BoolProperty(name="Expand Layer", default=True) - layer_id: IntProperty(name="Layer ID", description="ID of the layer's entry in the node") - - -class SvViewerLayerNode(bpy.types.Node, SverchCustomTreeNode): - """ - Triggers: Layer, Viewer - Tooltip: Group viewer nodes into layers to easily manipulate their settings - """ - bl_idname = 'SvViewerLayerNode' - bl_label = 'Viewer Layers' - bl_icon = 'HIDE_OFF' - - layers: CollectionProperty(name="Layers", type=SvViewerLayerGroup) - layer_id: IntProperty(name="Layer ID", default=0) - viewer_id: IntProperty(name="Viewer ID", default=0) - - def viewer_changed_name(self): - ''' Callback used when external viewer nodes name changed ''' - debug("* VLN: SvViewerLayerNode: viewer_changed_name") - self.update_layers_viewers_lists() - - def number_of_viewer_nodes(self): - ''' Total number of viewer nodes in the tree ''' - count = 0 - for node in self.id_data.nodes: - if node.bl_idname in viewer_dict.keys(): - count += 1 - return count - - def get_next_default_layer_name(self): - return layer_names[len(self.layers)-1] - - def get_next_layer_id(self): - self.layer_id += 1 - return self.layer_id - - def get_next_viewer_id(self): - self.viewer_id += 1 - return self.viewer_id - - def status_icon(self, status): - # status all ON status all OFF status MIX - return "HIDE_OFF" if status == 1 else "HIDE_ON" if status == 2 else "DOT" - - def new_status(self, status): - if status == 1: # all ON => next will make all OFF - new_status = False - elif status == 2: # all OFF => next will make all ON - new_status = True - else: # a MIX => next will make all ON - new_status = True - - return new_status - - def layer_visibility_status(self, layer): - """ - Return the layer's cummulative viewer [ON/OFF/MIX] status: [1, 2 or 3] - status = (hidden bit) | (visible bit) - 1 = 0x01 : status all ON (visible) - 2 = 0x10 : status all OFF (hidden) - 3 = 0x11 : status MIX (both visible & hidden) - """ - tree_nodes = self.id_data.nodes - status = 0 - for viewer in layer.viewers: - viewer_node = tree_nodes.get(viewer.node_name) - if viewer_node: - if viewer_node.activate: # mark that the layer has active viewers - status = status | 1 - else: # mark that the layer has inactive viewers - status = status | 2 - - return status - - def all_layer_visibility_status(self): - ''' Return the cummulative visibility status of all layers ''' - status = 0 - for layer in self.layers: - status = status | self.layer_visibility_status(layer) - - return status - - def setup_subscriptions(self): - """ - Setup node/attribute subscriptions - - This is called from the handlers.py after loading blender file to allow - existing viewer layer node to subscribe to viewer node name changes. - """ - debug("* setup_subscriptions in class: %s", self.bl_idname) - subscribe_to_viewer_nodes_name_changes() - # also, update all layers viewers lists (if any exist) - self.update_layers_viewers_lists() - - def update_layers_viewers_lists(self): - ''' Update the viewer name lists for viwers in all layers ''' - debug("* update_layers_viewers_lists") - - all_viewer_names = [n.name for n in self.id_data.nodes if n.bl_idname in viewer_dict.keys()] - debug("all viewer names = {}".format(all_viewer_names)) - - if self.layers: - debug("update node ({0} layers)".format(len(self.layers))) - for layer in self.layers: - debug(" update layer \"{0}\" ({1} viewers): ".format(layer.name, len(layer.viewers))) - - layer_viewer_names = list(set([v.node_name for v in layer.viewers if v.node_name != ""])) - debug("layer viewer names = {}".format(layer_viewer_names)) - - unused_names = [name for name in all_viewer_names if name not in layer_viewer_names] - debug("unused names = {}".format(unused_names)) - - if layer.viewers: - for viewer in layer.viewers: - debug(" update viewer: %s", viewer.name) - - viewer.collection_name.clear() - - for name in unused_names: - debug(" adding viewer %s to the list", name) - viewer.collection_name.add().name = name - - if viewer.node_name in all_viewer_names and viewer.node_name not in unused_names: - viewer.collection_name.add().name = viewer.node_name - else: - debug("layer \"{0}\" has no viewers".format(layer.name)) - else: - debug("node has no layers") - - def draw_buttons(self, context, layout): - lcb = SvLayerOperatorCallback.bl_idname # LAYER callback - vcb = SvViewerOperatorCallback.bl_idname # VIEWER callback - - tree_nodes = self.id_data.nodes - - if self.layers: - # overall controls - box = layout.box() - row = box.row(align=True) - split = row.split(factor=0.5) - - all_expand = split.operator(lcb, text='', icon='COLLAPSEMENU') - all_expand.function_name = 'ops_toggle_all_layer_expansion' - - for element in elements: - toggle_element = split.operator(lcb, text='', icon=elements[element]) - toggle_element.function_name = "ops_toggle_element_visibility" - toggle_element.element_type = element - - status = self.all_layer_visibility_status() - all_toggle = split.operator(lcb, text='', icon=self.status_icon(status)) - all_toggle.function_name = 'ops_toggle_all_layer_visibility' - - for layer in self.layers: - row = layout.row(align=True) - split = row.split(factor=0.1) - - split.prop(layer, "expand", icon="COLLAPSEMENU", text="") - split = split.split(factor=0.6) - row = split.row(align=True) - row.prop(layer, "name", text="") - - # show the REMOVE LAYER button - rm_button = row.operator(lcb, text='', icon='REMOVE') - rm_button.function_name = "ops_remove_layer" - rm_button.layer_name = layer.name - rm_button.layer_id = layer.layer_id - - # show the LAYER VISIBILITY button - status = self.layer_visibility_status(layer) - viz_button = split.operator(lcb, text='', icon=self.status_icon(status)) - viz_button.function_name = "ops_toggle_layer_visibility" - viz_button.layer_name = layer.name - viz_button.layer_id = layer.layer_id - - if layer.expand: - # show entries for all the viewers in the layer - box = layout.box() - for viewer in layer.viewers: - row = box.row(align=True) - part1 = row.split(factor=0.7 if self.width < 300 else 0.5 if self.width < 400 else 0.4) - part1.prop_search(viewer, "node_name", viewer, 'collection_name', icon='NODE', text='') - - viewer_node = tree_nodes.get(viewer.node_name) - if viewer_node: - display = viewer_dict[viewer_node.bl_idname]['display'] - color = viewer_dict[viewer_node.bl_idname]['colors'] - - part2 = part1.split(align=True) - if self.width > 400: - for element in elements: - part2.prop(viewer_node, display[element], text='', icon=elements[element]) - - if self.width > 300: - for element in elements: - part2.prop(viewer_node, color[element], text='') - - if viewer_node.bl_idname == "SvIDXViewer28": - if self.width > 400: - part2.prop(viewer_node, "draw_bface", text='', icon="GHOST_ENABLED") - - icon_name = "HIDE_OFF" if viewer_node.activate else "HIDE_ON" - part2.prop(viewer_node, "activate", toggle=True, icon=icon_name, text='') - - else: # no viewer node for viewer entry => show remove option - part2 = part1.split(align=True) - # add the REMOVE VIEWER button - rm_button = part2.operator(vcb, text='', icon='REMOVE') - rm_button.function_name = "ops_remove_viewer" - rm_button.layer_name = layer.name - rm_button.layer_id = layer.layer_id - rm_button.viewer_id = viewer.viewer_id - - # show the ADD NEW VIEWER to layer button - # max number of viewer enties <= number of available viewers - if len(layer.viewers) < self.number_of_viewer_nodes(): - add_button = box.row().operator(lcb, text='', icon='PLUS') - add_button.function_name = "ops_add_new_viewer" - add_button.layer_name = layer.name - add_button.layer_id = layer.layer_id - - # show the ADD NEW LAYER button - layout.row().operator(lcb, text='', icon='COLLECTION_NEW').function_name = "ops_add_new_layer" - - def ops_add_new_viewer(self, op): - debug("* VLN: SvViewerLayerNode: ops_add_new_viewer") - layer_name = op.layer_name - layer_id = op.layer_id - debug("add new viewer to layer: %s", layer_name) - debug("number of layers: %d", len(self.layers)) - for layer in self.layers: - if layer.layer_id == layer_id: - viewer_id = self.get_next_viewer_id() - debug("creating viewer with entry id: %d", viewer_id) - viewer = layer.viewers.add() - viewer.name = str(viewer_id) - viewer.viewer_id = viewer_id - debug("mark viewer name empty") - viewer.node_name = '' # trigger a list update - - self.update_layers_viewers_lists() - - def ops_remove_viewer(self, layer_id, viewer_id): - debug("* VLN: SvViewerLayerNode: ops_remove_viewer") - debug("remove viewer in layer_id: %d with viewer_id: %d", layer_id, viewer_id) - for layer in self.layers: - if layer.layer_id == layer_id: - for index, viewer in enumerate(layer.viewers): - if viewer.viewer_id == viewer_id: - debug("removing viewer from index: %d with viewer_id: %d", index, viewer_id) - debug("viewer name: %s", viewer.node_name) - layer.viewers.remove(index) - self.update_layers_viewers_lists() - return - - def ops_add_new_layer(self, dummy): - debug("* VLN: SvViewerLayerNode: ops_add_new_layer") - layer = self.layers.add() - layer.name = self.get_next_default_layer_name() - layer.layer_id = self.get_next_layer_id() - debug("add new layer: %s", layer.name) - - def ops_remove_layer(self, op): - debug("* VLN: SvViewerLayerNode: ops_remove_layer") - layer_name = op.layer_name - layer_id = op.layer_id - debug("remove layer: %s", layer_name) - for index, layer in enumerate(self.layers): - if layer.layer_id == layer_id: - debug("removing layer from index: %d", index) - self.layers.remove(index) - return - - def ops_toggle_layer_visibility(self, op): - debug("* VLN: SvViewerLayerNode: ops_toggle_layer_visibility") - layer_name = op.layer_name - layer_id = op.layer_id - debug("toggle layer: %s", layer_name) - tree_nodes = self.id_data.nodes - for layer in self.layers: - if layer.layer_id == layer_id: - # check layer's viewers active state - status = self.layer_visibility_status(layer) - - new_status = self.new_status(status) - - for viewer in layer.viewers: - viewer_node = tree_nodes.get(viewer.node_name) - if viewer_node: - viewer_node.activate = new_status - - def ops_toggle_all_layer_visibility(self, dummy): - debug("* VLN: SvViewerLayerNode: ops_toggle_all_layer_visibility") - status = 0 - for layer in self.layers: - status = status | self.layer_visibility_status(layer) - - new_status = self.new_status(status) - - tree_nodes = self.id_data.nodes - for layer in self.layers: - for viewer in layer.viewers: - viewer_node = tree_nodes.get(viewer.node_name) - if viewer_node: - viewer_node.activate = new_status - - def ops_toggle_all_layer_expansion(self, dummy): - debug("* VLN: SvViewerLayerNode: ops_toggle_all_layer_expansion") - status = 0 - for layer in self.layers: - if layer.expand: - status = status | 1 - else: - status = status | 2 - - new_status = self.new_status(status) - - for layer in self.layers: - layer.expand = new_status - - def ops_toggle_element_visibility(self, op): - ''' Toggle visibility for vert, edge or face elements ''' - debug("* VLN: ops_toggle_element_visibility") - - element = op.element_type # vert, edge or face - - tree_nodes = self.id_data.nodes - - status = 0 - for layer in self.layers: - for viewer in layer.viewers: - viewer_node = tree_nodes.get(viewer.node_name) - - if viewer_node: - attribute = viewer_dict[viewer_node.bl_idname]['display'][element] - viewer_status = getattr(viewer_node, attribute) - - if viewer_status: # accumulate visible and invisible status - status = status | 1 - else: - status = status | 2 - - new_status = self.new_status(status) - - for layer in self.layers: - for viewer in layer.viewers: - viewer_node = tree_nodes.get(viewer.node_name) - if viewer_node: - attribute = viewer_dict[viewer_node.bl_idname]['display'][element] - setattr(viewer_node, attribute, new_status) - - def sv_init(self, context): - self.width = 432 - - def process(self): - ... - - -classes = SvLayerOperatorCallback, SvViewerOperatorCallback, SvViewerGroup, SvViewerLayerGroup, SvViewerLayerNode - - -def register(): - debug("* VLN: REGISTER the SvViewerLayerNode classes") - _ = [bpy.utils.register_class(cls) for cls in classes] - # setup subscriptions (useful when reloading the addon) - subscribe_to_viewer_nodes_name_changes() - - -def unregister(): - _ = [bpy.utils.unregister_class(cls) for cls in reversed(classes)] diff --git a/utils/sv_default_macros.py b/utils/sv_default_macros.py index 134ddf7f6..a8f6b2324 100644 --- a/utils/sv_default_macros.py +++ b/utils/sv_default_macros.py @@ -186,7 +186,6 @@ class DefaultMacros(): elif 'snl' in term: file = term.split(' ')[1] snlite = nodes.new('SvScriptNodeLite') - snlite.location = context.space_data.cursor_location sn_loader(snlite, script_name=file) elif term == 'monad info': diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index ebeae1d67..3a8c4b7e3 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -22,6 +22,24 @@ import bpy from sverchok.utils.logging import debug, info, error +sv_error_message = '''\ +______________Sverchok Script Generator Node rules_______________ + +For this operation to work the current line must contain the text: +: 'def sv_main(**variables**):' + +Where '**variables**' is something like: +: 'verts=[], petal_size=2.3, num_petals=1' + +There are three types of input streams that this node can interpret: +- 'v' (vertices, 3-tuple coordinates) +- 's' (data: float, integer), +- 'm' (matrices: nested lists 4*4) + + For more information see the wiki + see also the bundled templates for clarification +''' + def has_selection(self, text): return not (text.select_end_line == text.current_line and @@ -60,7 +78,7 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): if named_seeker == named_current: return True elif named_seeker[3:] == named_current: return True except Exception as err: - print(f"Refesh Current Script called but encountered error {err}") + print(f"Refesh Current Script called but encountered error {errr}") for ng in ngs: -- GitLab From b871ae803b20750a90dca8ce08808b53d00a6a5f Mon Sep 17 00:00:00 2001 From: zeffii Date: Thu, 30 Apr 2020 16:24:05 +0200 Subject: [PATCH 11/12] restore plugin code --- utils/text_editor_plugins.py | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index 3a8c4b7e3..7309d5a77 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -17,29 +17,9 @@ # ##### END GPL LICENSE BLOCK ##### import re - import bpy - from sverchok.utils.logging import debug, info, error -sv_error_message = '''\ -______________Sverchok Script Generator Node rules_______________ - -For this operation to work the current line must contain the text: -: 'def sv_main(**variables**):' - -Where '**variables**' is something like: -: 'verts=[], petal_size=2.3, num_petals=1' - -There are three types of input streams that this node can interpret: -- 'v' (vertices, 3-tuple coordinates) -- 's' (data: float, integer), -- 'm' (matrices: nested lists 4*4) - - For more information see the wiki - see also the bundled templates for clarification -''' - def has_selection(self, text): return not (text.select_end_line == text.current_line and @@ -64,12 +44,11 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): ngs = list(filter(is_sv_tree, ngs)) if not ngs: - self.report({'INFO'}, "No Sverchok / svrx NodeGroups") + self.report({'INFO'}, "No Sverchok NodeGroups") return {'FINISHED'} node_types = set([ - 'SvScriptNode', 'SvScriptNodeMK2', 'SvScriptNodeLite', - 'SvProfileNode', 'SvTextInNode', 'SvGenerativeArtNode', 'SvSNFunctorB', + 'SvScriptNodeLite', 'SvProfileNode', 'SvTextInNode', 'SvGenerativeArtNode', 'SvSNFunctorB', 'SvRxNodeScript', 'SvProfileNodeMK2', 'SvVDExperimental', 'SvProfileNodeMK3']) def compare_permutations_of_name(named_seeker, named_current): @@ -78,7 +57,7 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator): if named_seeker == named_current: return True elif named_seeker[3:] == named_current: return True except Exception as err: - print(f"Refesh Current Script called but encountered error {errr}") + print(f"Refesh Current Script called but encountered error {err}") for ng in ngs: @@ -155,7 +134,6 @@ def add_keymap(): def remove_keymap(): - for km, kmi in addon_keymaps: km.keymap_items.remove(kmi) addon_keymaps.clear() -- GitLab From e7d1c3199b8f9c4bb31a3eecd6e9c3bddeec6737 Mon Sep 17 00:00:00 2001 From: zeffii Date: Thu, 30 Apr 2020 16:27:14 +0200 Subject: [PATCH 12/12] restore here --- utils/text_editor_plugins.py | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/utils/text_editor_plugins.py b/utils/text_editor_plugins.py index 7309d5a77..afb9c56b3 100644 --- a/utils/text_editor_plugins.py +++ b/utils/text_editor_plugins.py @@ -1,20 +1,9 @@ -# ##### 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 ##### +# This file is part of project Sverchok. It's copyrighted by the contributors +# recorded in the version control history of the file, available from +# its original location https://github.com/nortikin/sverchok/commit/master +# +# SPDX-License-Identifier: GPL3 +# License-Filename: LICENSE import re import bpy -- GitLab