Коммит bf3d8ae4 создал по автору durman's avatar durman
Просмотр файлов

Merge remote-tracking branch 'origin/master' into fixing_old_nodes_register

# Conflicts:
#	core/__init__.py
#	core/handlers.py
#	old_nodes/__init__.py
владельцы 85aa264e 9a39b998
......@@ -18,10 +18,7 @@
# ##### END GPL LICENSE BLOCK #####
import bpy
from sverchok.ui.nodeview_rclick_menu import get_output_sockets_map
from sverchok.utils.sv_node_utils import frame_adjust
sv_tree_types = {'SverchCustomTreeType', 'SverchGroupTreeType'}
def similar_sockets(node_out, node_in, term):
socket_out, socket_in = -1, -1
......@@ -95,7 +92,7 @@ class SvNodeConnectorOperator(bpy.types.Operator):
space = context.space_data
tree_type = space.tree_type
return space.type == 'NODE_EDITOR' and tree_type in sv_tree_types
return space.type == 'NODE_EDITOR' and tree_type in {'SverchCustomTreeType', }
def execute(self, context):
verts_edges_faces_connector(self, context)
......
......@@ -136,9 +136,9 @@ utils_modules = [
"text_editor_submenu", "text_editor_plugins",
# UI operators and tools
"sv_IO_pointer_helpers",
"sv_IO_monad_helpers", "sv_operator_mixins",
"sv_operator_mixins",
"sv_gist_tools", "sv_IO_panel_tools", "sv_load_archived_blend",
"monad", "sv_help", "sv_default_macros", "sv_macro_utils", "sv_extra_search", "sv_3dview_tools",
"sv_help", "sv_default_macros", "sv_macro_utils", "sv_extra_search", "sv_3dview_tools",
"sv_update_utils", "sv_obj_helper", "sv_batch_primitives", "sv_idx_viewer28_draw",
"sv_texture_utils",
# geom 2d tools
......
......@@ -95,7 +95,7 @@ def delete_data_block(data_block) -> None:
def get_sv_trees():
return [ng for ng in bpy.data.node_groups if ng.bl_idname in {'SverchCustomTreeType', 'SverchGroupTreeType'}]
return [ng for ng in bpy.data.node_groups if ng.bl_idname in {'SverchCustomTreeType',}]
# ~~~~ encapsulation Blender objects ~~~~
......
......@@ -210,13 +210,6 @@ def setLevel(level):
for handler in logging.getLogger().handlers:
handler.setLevel(level)
def inject_logger(name):
logger = getLogger(name)
globals()["debug"] = logger.debug
globals()["info"] = logger.info
globals()["warning"] = logger.warning
globals()["error"] = logger.error
globals()["exception"] = logger.exception
consoleHandler = None
......
Это отличие свёрнуто
# ##### 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
import json
from sverchok.utils.logging import error
def pack_monad(node, node_items, groups_dict, create_dict_of_tree):
"""
we can not rely on .items() to be present for various reasons, so we must gather
something to fill .params with - due to dynamic nature of node.
"""
name = node.monad.name
node_items['all_props'] = node.monad.get_all_props()
node_items['monad'] = name
node_items['cls_dict'] = {}
node_items['cls_dict']['cls_bl_idname'] = node.bl_idname
for template in ['input_template', 'output_template']:
node_items['cls_dict'][template] = getattr(node, template)
if name not in groups_dict:
group_ng = bpy.data.node_groups[name]
group_dict = create_dict_of_tree(group_ng)
group_dict['bl_idname'] = group_ng.bl_idname
group_dict['cls_bl_idname'] = node.bl_idname
group_json = json.dumps(group_dict)
groups_dict[name] = group_json
# [['Y', 'SvStringsSocket', {'prop_name': 'y'}], [....
for idx, (socket_name, socket_type, prop_dict) in enumerate(node.input_template):
socket = node.inputs[idx]
if not socket.is_linked and prop_dict:
prop_name = prop_dict['prop_name']
v = getattr(node, prop_name)
if not isinstance(v, (float, int, str)):
v = v[:]
node_items[prop_name] = v
def unpack_monad(nodes, node_ref):
params = node_ref.get('params')
if params:
socket_prop_data = params.get('all_props')
monad_name = params.get('monad')
monad = bpy.data.node_groups[monad_name]
if socket_prop_data:
# including this to keep bw comp for trees that don't include this info.
monad.set_all_props(socket_prop_data)
cls_ref = monad.update_cls()
node = nodes.new(cls_ref.bl_idname)
# -- addition 1 --------- setting correct properties on sockets.
cls_dict = params.get('cls_dict')
input_template = cls_dict['input_template']
for idx, (sock_name, sock_type, sock_props) in enumerate(input_template):
socket_reference = node.inputs[idx]
if sock_props:
for prop, val in sock_props.items():
setattr(socket_reference, prop, val)
# -- addition 2 --------- force push param values
# -- (this step is skipped by apply_core_props because this node has a cls_dict)
for prop_data in ('float_props', 'int_props'):
data_list = socket_prop_data.get(prop_data)
if not data_list:
continue
for k, v in data_list.items():
if hasattr(node, k):
if k in params:
setattr(node, k, params[k])
# else:
# print(k, 'not in', params)
#else:
# print('node name:', node, node.name, 'has no property called', k, 'yet..')
# node.output_template = cls_dict['output_template']
for attr in 'vectorize', 'loop_me', 'loops_max', 'loops':
if attr in params:
setattr(node, attr, params[attr])
return node
else:
error('no parameters found! .json might be broken')
......@@ -50,8 +50,6 @@ macros = {
description="load snlite w/ petalsine", term='snl demo/petal_sine.py'),
"> Subdiv to quads": simple_macro(
description="snlite w/ subdiv to quads", term='snl demo/subidivide_to_quads.py'),
"> monad info": simple_macro(
description="output current idx / total", term='monad info'),
"> multiply *": simple_macro(
description="multiply selected nodes", term='mathMUL'),
"> add +": simple_macro(
......@@ -91,10 +89,6 @@ macros = {
}
sv_types = {'SverchCustomTreeType', 'SverchGroupTreeType'}
def sn_loader(snlite, script_name=None):
sv_path = os.path.dirname(sv_get_local_path()[0])
snlite_template_path = os.path.join(sv_path, 'node_scripts', 'SNLite_templates')
......@@ -113,7 +107,7 @@ class DefaultMacros():
if no active nodetree
add new empty node tree, set fakeuser immediately
'''
if not context.space_data.tree_type in sv_types:
if not context.space_data.tree_type in {'SverchCustomTreeType', }:
print('not running from a sv nodetree')
return
......@@ -174,11 +168,6 @@ class DefaultMacros():
snlite.location = context.space_data.cursor_location
sn_loader(snlite, script_name=file)
elif term == 'monad info':
x, y = context.space_data.cursor_location[:]
monad_info = nodes.new('SvMonadInfoNode')
monad_info.location = x, y
elif "join" in term:
join_macros(context, operator, term, nodes, links)
......
......@@ -19,19 +19,17 @@
import os
import importlib.util as getutil
import bpy
import nodeitems_utils
import sverchok
from sverchok.menu import make_node_cats
from sverchok.utils import get_node_class_reference
from sverchok.utils.docstring import SvDocstring
from sverchok.ui.sv_icons import custom_icon
from sverchok.utils.sv_default_macros import macros, DefaultMacros
from nodeitems_utils import _node_categories
from sverchok.utils.extra_categories import get_extra_categories
# pylint: disable=c0326
sv_tree_types = {'SverchCustomTreeType', 'SverchGroupTreeType'}
node_cats = make_node_cats()
addon_name = sverchok.__name__
......@@ -146,7 +144,7 @@ class SvExtraSearch(bpy.types.Operator):
@classmethod
def poll(cls, context):
tree_type = context.space_data.tree_type
if tree_type in sv_tree_types:
if tree_type in {'SverchCustomTreeType', }:
return True
def bl_idname_from_bl_label(self, context):
......
......@@ -8,18 +8,14 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Union, List, Generator
from typing import TYPE_CHECKING, Union
import bpy
from sverchok.utils.sv_node_utils import recursive_framed_location_finder
from sverchok.utils.handle_blender_data import BPYProperty
from sverchok.utils.sv_IO_monad_helpers import pack_monad
from sverchok.utils.sv_json_struct import FileStruct, NodePresetFileStruct
if TYPE_CHECKING:
from sverchok.node_tree import SverchCustomTree, SverchCustomTreeNode
from sverchok.node_tree import SverchCustomTree
SverchCustomTree = Union[SverchCustomTree, bpy.types.NodeTree]
SverchCustomTreeNode = Union[SverchCustomTreeNode, bpy.types.Node]
class JSONExporter:
......@@ -27,200 +23,9 @@ class JSONExporter:
@staticmethod
def get_tree_structure(tree: SverchCustomTree, use_selection=False) -> dict:
"""Generate structure of given tree which van be saved into json format"""
has_monads = any('SvGroupNodeMonad' in n.bl_idname for n in tree.nodes)
if has_monads: # todo this part should be deleted with monads
if use_selection:
return JSONExporter._get_nodes_structure([n for n in tree.nodes if n.select])
else:
return TreeExporter01().export_tree(tree)
else:
return FileStruct().export_tree(tree, use_selection)
return FileStruct().export_tree(tree, use_selection)
@staticmethod
def get_node_structure(node) -> dict:
"""For exporting node properties"""
return NodePresetFileStruct().export(node)
@staticmethod
def _get_nodes_structure(nodes: List[SverchCustomTreeNode]) -> dict:
"""Generate structure of given nodes which can be saved into json format"""
return TreeExporter01().export_nodes(nodes)
class TreeExporter01:
"""
It keeps structure of tree which can be saved into json format
Structure including:
export version
nodes, node_name and node structure
links which are determined by node names adn socket indexes
frames
monad(s) which are reading recursively what is efficiently
"""
def __init__(self):
self._structure = {
"export_version": "0.10",
"framed_nodes": dict(),
"groups": dict(),
"nodes": dict(),
"update_lists": []
}
def export_tree(self, tree: SverchCustomTree) -> dict:
"""Generate structure from given tree"""
for node in tree.nodes:
self._add_node(node)
self._add_node_in_frame(node)
for link in self._ordered_links(tree):
self._add_link(link)
return self._structure
def export_nodes(self, nodes: List[SverchCustomTreeNode]):
"""
Generate structure from given node
Expecting get nodes from one tree, for example importing only selected nodes in a tree
"""
for node in nodes:
self._add_node(node)
self._add_node_in_frame(node)
if nodes:
tree = nodes[0].id_data
input_node_names = {node.name for node in nodes}
for link in self._ordered_links(tree):
if link.from_node.name in input_node_names and link.to_node.name in input_node_names:
self._add_link(link)
return self._structure
def _add_node(self, node: SverchCustomTreeNode):
"""Add into structure name of given node and its structure"""
self._structure['nodes'][node.name] = NodeExporter01().export_node(node, self._structure['groups'])
def _add_link(self, link: bpy.types.NodeLink):
"""Add link into tree structure, it can have to formats:
(from_node_name, from_socket_index, to_node_name, to_socket_index)
and if at least at one side there is reroute node
(from_node_name, from_socket_name, to_node_name, to_socket_name)
"""
if hasattr(link.from_socket, 'index') and hasattr(link.to_socket, 'index'):
# there are normal nodes from both sides of the link, get their indexes
self._structure['update_lists'].append([
link.from_node.name, link.from_socket.index, link.to_node.name, link.to_socket.index
])
else:
# from one side or both there are reroute nodes, get socket names instead
# it is strange solution but it is how current exporter works
# potentially it can bring troubles in case if normal node has several sockets with equal names
# what is not forbidden by Blender API
self._structure['update_lists'].append([
link.from_node.name, link.from_socket.name, link.to_node.name, link.to_socket.name
])
def _add_node_in_frame(self, node: SverchCustomTreeNode):
"""It adds information to structure node name: frame name"""
if node.parent:
self._structure["framed_nodes"][node.name] = node.parent.name
@staticmethod
def _ordered_links(tree: SverchCustomTree) -> Generator[bpy.types.NodeLink]:
"""Returns all links in whole tree where links always are going in order from top input socket to bottom"""
for node in tree.nodes:
for input_socket in node.inputs:
for link in input_socket.links:
yield link
class NodeExporter01:
"""
It keeps structure of node data which can be converted into json format
it keeps attributes like location, color, width
all kinds of node properties including nesting collections and pointers
the same properties for sockets
only non default properties will get into the structure
pointer properties will get only name of assigned data block
also it calls `save_to_json(node_data: dict)` method of given node if it has got it
but ut is not recommended to use it
it saves special attributes for monad(s)
it is possible to made it skip saving a property by marking it like that BoolProperty(option={'SKIP_SAVE'})
this option will impact only on saving the property into json file
"""
def __init__(self):
self._structure = {
"bl_idname": "",
"height": None,
"width": None,
"label": '',
"hide": False,
"location": (0, 0),
"params": dict(),
"custom_socket_props": dict()
}
def export_node(self, node: SverchCustomTreeNode, groups: dict) -> dict:
"""It returns structure of given node"""
self._add_mandatory_attributes(node)
self._add_node_properties(node)
self._add_socket_properties(node)
if hasattr(node, 'monad') and node.monad:
self._structure['bl_idname'] = 'SvMonadGenericNode'
pack_monad(node, self._structure['params'], groups, TreeExporter01().export_tree)
if node.bl_idname in {'SvGroupInputsNodeExp', 'SvGroupOutputsNodeExp'}:
self._structure[node.node_kind] = node.stash()
if hasattr(node, 'save_to_json'):
node.save_to_json(self._structure)
return self._structure
def _add_mandatory_attributes(self, node: SverchCustomTreeNode):
"""It adds attributes which all nodes have"""
self._structure['bl_idname'] = node.bl_idname
self._structure['height'] = node.height
self._structure['width'] = node.width
self._structure['label'] = node.label
self._structure['hide'] = node.hide
self._structure['location'] = recursive_framed_location_finder(node, node.location[:])
if node.use_custom_color:
self._structure['color'] = node.color[:]
self._structure['use_custom_color'] = True
def _add_node_properties(self, node: SverchCustomTreeNode):
"""adds non default node properties"""
for prop_name in node.keys():
prop = BPYProperty(node, prop_name)
if self._is_property_to_export(prop):
if prop.type == 'COLLECTION':
# protection from storing default values
self._structure["params"][prop_name] = prop.filter_collection_values()
else:
self._structure["params"][prop.name] = prop.value
def _add_socket_properties(self, node: SverchCustomTreeNode):
"""
add non default input socket properties
output sockets does not have anything worth exporting
"""
for i, sock in enumerate(node.inputs):
sock_props = dict()
for prop_name in sock.keys():
prop = BPYProperty(sock, prop_name)
if self._is_property_to_export(prop):
if prop.type == 'COLLECTION':
sock_props[prop_name] = prop.filter_collection_values()
else:
sock_props[prop.name] = prop.value
if sock_props:
self._structure['custom_socket_props'][str(i)] = sock_props
@staticmethod
def _is_property_to_export(prop: BPYProperty) -> bool:
"""Mark properties which should be skipped to save into json"""
if not prop.is_valid:
return False # deprecated property
elif not prop.is_to_save:
return False
elif prop.default_value == prop.value:
return False # the value will be loaded from code
else:
return True
return NodePresetFileStruct().export(node)
\ Нет новой строки в конце файла
......@@ -19,7 +19,6 @@ from sverchok import old_nodes
from sverchok.utils.sv_IO_panel_tools import get_file_obj_from_zip
from sverchok.utils.logging import info, warning, getLogger, logging
from sverchok.utils.handle_blender_data import BPYProperty, BPYNode
from sverchok.utils.sv_IO_monad_helpers import unpack_monad
from sverchok.utils.sv_json_struct import FileStruct, NodePresetFileStruct
if TYPE_CHECKING:
......@@ -112,24 +111,10 @@ class TreeImporter01:
self._new_node_names = dict() # map(old_node_name, new_node_name)
def import_tree(self):
"""Reads and generates nodes, frames, links, monad"""
# create recursion, this is how monad import intend to work
# in original module monad does not take in account that they can get another name
# it logic remains and in this module
# monad is designed to be imported recursively
with self._fails_log.add_fail("Reading monads", f'Tree: {self._tree.name}'):
for name, str_struct in self._structure.get('groups', dict()).items():
monad = bpy.data.node_groups.new(name, 'SverchGroupTreeType')
TreeImporter01(monad, json.loads(str_struct), self._fails_log).import_tree()
"""Reads and generates nodes, frames, links"""
with TreeGenerator.start_from_tree(self._tree, self._fails_log) as tree_builder:
for node_name, node_type, node_structure in self.nodes():
if node_type == 'SvMonadGenericNode':
node = None
with self._fails_log.add_fail("Creating monad node", f'Tree: {self._tree.name}'):
node = unpack_monad(self._tree.nodes, node_structure)
else:
node = tree_builder.add_node(node_type, node_name)
node = tree_builder.add_node(node_type, node_name)
if node:
self._new_node_names[node_name] = node.name
NodeImporter01(node, node_structure, self._fails_log, self.file_version).import_node()
......@@ -203,8 +188,6 @@ class NodeImporter01:
setattr(self._node, attr_name, attr_value)
for prop_name, prop_value in self._node_properties():
if prop_name in {"all_props", "cls_dict", "monad"}:
return # this properties for monads which are applied in another place
with self._fails_log.add_fail(
"Setting node property",
f'Tree: {self._node.id_data.name}, Node: {self._node.name}, prop: {prop_name}'):
......
......@@ -5,8 +5,6 @@
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
sv_tree_types = {'SverchCustomTreeType', 'SverchGroupTreeType'}
def recursive_framed_location_finder(node, loc_xy):
locx, locy = loc_xy
......@@ -25,23 +23,6 @@ def frame_adjust(caller_node, new_node):
locx, locy = recursive_framed_location_finder(new_node, loc_xy)
new_node.location = locx, locy
def absolute_location_generic(node):
"""
all nodes of type Sverchok Custom will have the absolute_location attribute,
but some nodes (at the moment only ReRoute) are "part of the pynodes API" and can not
be augmented, so this function will return the appropriate location for all nodes
"""
if hasattr(node, 'absolute_location'):
return node.absolute_location
return recursive_framed_location_finder(node, node.location[:])
def scaled_dpi():
"""
find the xy position for the blf content, adjusted for screen res.
"""
ps = bpy.context.preferences.system
return ps.dpi * ps.pixel_size / 72
def nodes_bounding_box(selected_nodes):
"""
......
......@@ -5,9 +5,9 @@
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import re
import bpy
from sverchok.utils.logging import getLogger, inject_logger
from sverchok.utils.logging import getLogger
def has_selection(self, text):
return not (text.select_end_line == text.current_line and
......@@ -42,7 +42,7 @@ class SvNodeRefreshFromTextEditor(bpy.types.Operator):
edit_text = bpy.context.edit_text
text_file_name = edit_text.name
is_sv_tree = lambda ng: ng.bl_idname in {'SverchCustomTreeType', 'SverchGroupTreeType'}
is_sv_tree = lambda ng: ng.bl_idname in {'SverchCustomTreeType', }
ngs = list(filter(is_sv_tree, ngs))
if not ngs:
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать