Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update system mem #2393

Closed
wants to merge 85 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
b72083b
adresses bug in upstream list modification
zeffii Nov 3, 2018
c92ebe0
add some error prevention
zeffii Nov 8, 2018
33af0e1
"Gcode Exporter" and "Evaluate Image" (#2298)
alessandro-zomparelli Nov 8, 2018
7f8f096
Add default font scale to index viewer node settable via preferences
DolphinDream Nov 13, 2018
c5551c9
Fix render scale and location of easing and texture viewer nodes
DolphinDream Nov 14, 2018
4a85936
line mk3 with AB and OD modes (#2294)
vicdoval Nov 17, 2018
65f187f
small prophylactic for no output
zeffii Nov 18, 2018
ab50e95
Added "BW" Grayscale and "A" Alpha channel support (#2314)
alessandro-zomparelli Nov 18, 2018
065af54
Update evaluate_image.py
zeffii Nov 18, 2018
283a662
Optimize the linear edge list generation using caching
DolphinDream Nov 27, 2018
f3379f2
Merge pull request #2321 from DolphinDream/edgeGenerationSpeedUp
DolphinDream Nov 29, 2018
503e629
smooth about poligons
nortikin Dec 3, 2018
f5424a4
Update smooth.rst
nortikin Dec 3, 2018
9992a5b
Add new PolygonSort node to sort polygons by distance, area, and norm…
DolphinDream Dec 7, 2018
1a4622e
Merge pull request #2324 from DolphinDream/polygonSortNode
DolphinDream Dec 7, 2018
987fc40
fixes lobsided edges (#2330)
zeffii Dec 9, 2018
98b1632
added Tension Node
vicdoval Dec 13, 2018
88c92e9
Update tree_generator.py
Kosvor2 Dec 17, 2018
421d246
Add node to compute various statistical quantities, currently support…
DolphinDream Dec 13, 2018
2f660fa
Merge pull request #2334 from DolphinDream/statisticsNode
DolphinDream Dec 18, 2018
5f6c38d
Add scale/multiplier to TextureViewerLite node to fix rendering
DolphinDream Dec 23, 2018
ca22b47
Merge pull request #2343 from DolphinDream/textureViewerLiteRenderFix
DolphinDream Dec 24, 2018
ad968de
Add new combinatorics node (WIP)
DolphinDream Feb 22, 2018
321544a
Add documentation + optimize and cleanup code
DolphinDream Dec 29, 2018
72896c4
Merge pull request #2346 from DolphinDream/combinatoricsNode
DolphinDream Dec 29, 2018
e6251c9
Fix comment
DolphinDream Dec 29, 2018
57106ac
Add quaternion nodes
DolphinDream Dec 21, 2018
9df2933
Merge pull request #2341 from DolphinDream/quaternionNodes
DolphinDream Dec 31, 2018
c8c8e0f
Renamed Deformation, cleaned and docs
vicdoval Jan 1, 2019
9490bd2
Restructure the MixNumber node as MixInput node + add new types & fea…
DolphinDream Dec 31, 2018
256d61a
Merge pull request #2347 from DolphinDream/mixInputs
DolphinDream Jan 1, 2019
79f5c15
Docs format fixed and some more explanations
vicdoval Jan 1, 2019
4102947
Changed Node Icon
vicdoval Jan 1, 2019
7deef78
Removed underscores from output sockets
vicdoval Jan 2, 2019
c983209
Removed underscores from Outputs' names
vicdoval Jan 2, 2019
4a6e77b
Add Quadrance to Quaternion Math node, fix bug in QIN node and add no…
DolphinDream Jan 6, 2019
7414ba6
Add Scalar-Vector mode to quaternion IN/OUT nodes
DolphinDream Jan 6, 2019
04e9a55
Update nodeview_rclick_menu.py
zeffii Jan 8, 2019
28b9f7c
Merge pull request #2337 from nortikin/Matrix()-in-scripts
Kosvor2 Jan 8, 2019
e8f8ffa
Merge pull request #2333 from vicdoval/tension_node
vicdoval Jan 8, 2019
5caad0a
Fixed typo in deformation Node
vicdoval Jan 8, 2019
eeb194f
added Length Node
vicdoval Jan 9, 2019
8589199
added images to length node docs
vicdoval Jan 9, 2019
7456972
Corrected typo from length docs
vicdoval Jan 9, 2019
aa05b55
minor refactoring on Length node
vicdoval Jan 9, 2019
3e75273
renamed to Path Length
vicdoval Jan 16, 2019
7e17d5a
update gp macro with Path Length node
vicdoval Jan 16, 2019
31f7b11
Typos and icon
vicdoval Jan 18, 2019
6bbd868
Merge pull request #2352 from vicdoval/length_node
vicdoval Jan 23, 2019
6c5ba13
Add (new) MeshSwitch node
DolphinDream Jan 26, 2019
5e71cfc
Merge pull request #2359 from DolphinDream/meshSwitchNode
DolphinDream Jan 26, 2019
9f85006
Fix bug in Mesh Switch node
DolphinDream Jan 26, 2019
3564ef5
Update iterate.py
zeffii Feb 15, 2019
2b43589
Add new InputSwitch Node
DolphinDream Feb 24, 2019
3ea8ccd
Merge pull request #2367 from DolphinDream/inputSwitchNode
DolphinDream Feb 24, 2019
154e10e
Add new SuperEllipsoid generator node (WIP)
DolphinDream Mar 5, 2019
b6133d3
Various updates
DolphinDream Mar 5, 2019
5161fb0
Merge pull request #2378 from DolphinDream/superEllipsoidNode
DolphinDream Mar 6, 2019
2564959
Relocate SuperEllipsoid node to extended generators
DolphinDream Mar 6, 2019
7a51add
Formula Mk3 node, take 1...
portnov Mar 6, 2019
9e3882f
Formula mk3: more extensive features.
portnov Mar 6, 2019
7dc3f98
More correct definition of free variables.
portnov Mar 7, 2019
d02448b
Add documentation
portnov Mar 7, 2019
9d3866b
Typo.
portnov Mar 8, 2019
909e5a5
Code documentation.
portnov Mar 8, 2019
763ad51
Support for easy migration from formula2 to formula3.
portnov Mar 8, 2019
6a094ce
Merge pull request #2379 from nortikin/formula3
portnov Mar 8, 2019
6ebff79
Minor comments & code updates to SuperEllipsoid to keep consistent wi…
DolphinDream Mar 8, 2019
301874b
Add new Cylinder node MK2 (WIP)
DolphinDream Mar 3, 2019
50f7d01
Various optimizations, cleanup + documentation
DolphinDream Mar 4, 2019
d542b3c
Add angle units option
DolphinDream Mar 10, 2019
c0af4e8
Merge pull request #2377 from DolphinDream/cylinderNodeMK2
DolphinDream Mar 10, 2019
38803f9
deleting unused operator
Durman Mar 15, 2019
899a0a8
Merge pull request #2387 from nortikin/del_SverchokUpdateObjectIn
Durman Mar 15, 2019
14af970
testing work wia PyCharm
Durman Mar 26, 2019
c667d6e
New update system module
Durman Mar 26, 2019
a0549b8
new setting for switching between old and new update system
Durman Mar 27, 2019
8bbfb6f
improving of setting color to a node
Durman Mar 27, 2019
2578320
connection new update system to update events
Durman Mar 28, 2019
b1bd5a6
connection new update system to buttons update all and update current…
Durman Mar 28, 2019
3401e9e
new approach to switcher "show laout" for new update system
Durman Mar 28, 2019
a5e3036
adding logic to process layout switcher on N panel
Durman Mar 28, 2019
19ef0a6
external properties - frame_info_mk2
Durman Mar 28, 2019
09ff6f1
support reroute nodes
Durman Mar 29, 2019
31293be
catching errors nodes
Durman Mar 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
375 changes: 375 additions & 0 deletions core/update_system_mem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

import bpy

from sverchok.core.socket_data import SvNoDataError
from sverchok.utils.logging import debug, exception
from sverchok.utils.profile import profile


swich_off_debug = lambda _: None
debug_process = swich_off_debug
#debug = swich_off_debug

list_debugs = [debug, debug_process]
if False:
for d in list_debugs:
d = swich_off_debug

# Notes
# Reroute nodes does not have "other" and "set_color" methods.


class UpdateDataStructure:
def __init__(self):
self._node_has_changed = dict()
self._sock_has_changed = dict()
self._prop_has_changed = dict()
self._sock_cache = dict()
self._prop_cache = dict()
self._root_nodes = dict()
self._ani_nodes = dict()
self._error_nodes = dict()

@staticmethod
def _get_id(obj, prop=None):
if prop:
return str(hash(obj.id_data.name + obj.name + prop))
elif isinstance(obj, bpy.types.NodeSocket):
# avoiding the same names of input and output sockets
position = 'output' if obj.is_output else 'input'
return str(hash(obj.id_data.name + obj.node.name + position + obj.identifier))
elif isinstance(obj, bpy.types.Node):
return str(hash(obj.id_data.name + obj.name))
else:
raise TypeError

@staticmethod
def get_node_props(node):
main = {k: v for k, v in node.items()}
if hasattr(node, 'additional_properties'):
main.update(node.additional_properties())
return main

def _update_sock_cache(self, sock):
cache = self._sock_cache
status = self._sock_has_changed
id = self._get_id(sock)
if not sock.is_output and sock.is_linked:
if id not in cache:
cache[id] = sock.links[0].from_node.name
status[id] = True
debug('Sock "{}" in node "{}" was linked'.format(sock.name, sock.node.name))
elif cache[id] == sock.links[0].from_node.name:
status[id] = False
else:
cache[id] = sock.links[0].from_node.name
status[id] = True
debug('Sock "{}" in node "{}" was relinked'.format(sock.name, sock.node.name))
elif not sock.is_output:
if id not in cache:
status[id] = False
elif cache[id] == '':
status[id] = False
else:
cache[id] = ''
status[id] = True
debug('Sock "{}" in node "{}" was unlinked'.format(sock.name, sock.node.name))

def _update_prop_cache(self, node):
# updating prop_cache and status of properties
cache = self._prop_cache
status = self._prop_has_changed
props = self.get_node_props(node)

def assign_value(cache, id, value):
try:
cache[id] = value[:]
except TypeError:
cache[id] = value

for k in props:
v = props[k]
id = self._get_id(node, k)
if id not in cache:
status[id] = True
assign_value(cache, id, v)
debug('Prop "{}" in node "{}" was changed (init)'.format(k, node.name))
else:
# iterable objects of blender props should be compared one by one
try:
equal = True
for nested_v, nested_c in zip(v, cache[id]):
if nested_v != nested_c:
equal = False
break
except TypeError:
equal = v == cache[id]
finally:
if equal:
status[id] = False
else:
status[id] = True
assign_value(cache, id, v)
debug('Prop "{}" in node "{}" was changed'.format(k, node.name))

def has_changed(self, obj, prop=None):
id = self._get_id(obj, prop)
if prop == 'ANY':
prop_names = [k for k in self.get_node_props(obj)]
return True in [self._prop_has_changed[self._get_id(obj, pn)] for pn in prop_names]
elif prop:
return self._prop_has_changed[id]
elif isinstance(obj, bpy.types.NodeSocket):
return self._sock_has_changed[id]
elif isinstance(obj, bpy.types.Node):
return self._node_has_changed.setdefault(id, False)
else:
raise TypeError

def _set_has_changed(self, obj, change=False, prop=None):
id = self._get_id(obj, prop)
if prop:
self._prop_has_changed[id] = change
elif isinstance(obj, bpy.types.NodeSocket):
self._sock_has_changed[id] = change
elif isinstance(obj, bpy.types.Node):
self._node_has_changed[id] = change
else:
raise TypeError

def _set_error_node(self, node, err):
self._error_nodes[self._get_id(node)] = err

def _get_error_node(self, node):
return self._error_nodes.get(self._get_id(node))


class UpdateSystemMem(UpdateDataStructure):
def _get_root_nodes(self, node_tree):
if node_tree.name in self._root_nodes:
return self._root_nodes[node_tree.name]
else:
root_nodes = []
for node in node_tree.nodes:
if True not in [soc.is_linked for soc in node.inputs]:
root_nodes.append(node)
self._root_nodes[node_tree.name] = root_nodes
return root_nodes

def _get_animate_nodes(self, node_tree):
if node_tree.name in self._ani_nodes:
return self._ani_nodes[node_tree.name]
else:
ani_nodes = [node for node in node_tree.nodes if node.bl_idname == 'SvFrameInfoNodeMK2']
self._ani_nodes[node_tree.name] = ani_nodes
return ani_nodes

@staticmethod
def _get_next_nodes(node):
next_nodes = []
for soc in node.outputs:
for link in soc.links:
next_nodes.append(link.to_node)
return next_nodes

def _update_prop_soc_status(self, node_tree):
for node in node_tree.nodes:
self._update_prop_cache(node)
for sock in node.inputs:
self._update_sock_cache(sock)

def _update_nodes_status(self, start_nodes):
root_nodes = start_nodes[:] # input was not changed, check only property
was_changed_nodes = [] # input was changed
check_nodes = [] # ready for check, should get through all tests
done = set() # if node not in so node was not checked yet

def set_changed_nodes(node):
nonlocal was_changed_nodes, done, self
next_nodes = [nn for nn in self._get_next_nodes(node) if nn.name not in done]
self._set_has_changed(node, True)
[self._set_has_changed(sock, True) for sock in node.outputs]
was_changed_nodes.extend(next_nodes)
done.add(node.name)

def set_check_nodes(node):
nonlocal check_nodes, done, self
next_nodes = [nn for nn in self._get_next_nodes(node) if nn.name not in done]
self._set_has_changed(node, False)
[self._set_has_changed(sock, False) for sock in node.outputs]
check_nodes.extend(next_nodes)
done.add(node.name)

def should_node_changed(node):
nonlocal self
for sock in node.inputs:
if self.has_changed(sock):
debug('"{}" is changed - input sock - "{}" - was relinked'.format(node.name, sock.name))
return True
if self.has_changed(node, prop='ANY'):
debug('"{}" is changed - a prop was changed'.format(node.name))
return True
for sock in node.inputs:
if sock.links and self.has_changed(sock.links[0].from_socket):
debug('"{}" is changed - data of "{}" - was changed'.format(
node.name, sock.links[0].from_node.name))
return True
for sock in node.outputs:
for link in sock.links:
if self.has_changed(link.to_socket):
debug('"{}" is changed - output sock - "{}" - was relinked'.format(node.name, sock.name))
return True
return False

while was_changed_nodes or check_nodes or root_nodes:
if was_changed_nodes:
node = was_changed_nodes.pop()
set_changed_nodes(node)
debug('Changed - "{}" - input was changed'.format(node.name))
elif check_nodes:
node = check_nodes.pop()
if False in [soc.links[0].from_node.name in done for soc in node.inputs if soc.links]:
debug('Cant decide - "{}" - input is undefined'.format(node.name))
continue
else:
if not should_node_changed(node):
set_check_nodes(node)
debug('Remain - "{}"'.format(node.name))
else:
set_changed_nodes(node)

elif root_nodes:
node = root_nodes.pop()
if should_node_changed(node):
set_changed_nodes(node)
else:
set_check_nodes(node)
debug('Remain - "{}"'.format(node.name))

def _process_node(self, node):
try:
node.process()
self._set_error_node(node, None)
except Exception as err:
self._set_error_node(node, err)
exception("Node {} had exception: {}".format(node.name, err))

def _process_nodes_hard(self, start_nodes):
debug_process('==========Start process nodes==========')
next_nodes = start_nodes[:]
done = set()
while next_nodes:
debug_process('Next nodes in process - "{}"'.format([node.name for node in next_nodes]))
node = next_nodes.pop()
next_nodes.extend([nn for nn in self._get_next_nodes(node) if nn not in done])
if self.has_changed(node) and hasattr(node, 'process'):
previous_nodes = [sock.links[0].from_node for sock in node.inputs if sock.links]
if True not in [self.has_changed(node) for node in previous_nodes]:
debug_process('Process - "{}"'.format(node.name))
self._process_node(node)
elif False in [node.name in done for node in previous_nodes]:
debug_process('Node "{}" is skipped - input is undefined'.format(node.name))
else:
debug_process('Process - "{}"'.format(node.name))
self._process_node(node)
done.add(node.name)

def _process_nodes_easy(self, start_nodes):
next_nodes = start_nodes[:]
done = set()
while next_nodes:
node = next_nodes.pop()
next_nodes.extend([nn for nn in self._get_next_nodes(node) if nn not in done])
self._set_has_changed(node, change=True)
if hasattr(node, 'process'):
self._process_node(node)
done.add(node.name)

def _set_update_color(self, node):
if self.has_changed(node):
node.set_color((1, 0, 0.3))
else:
node.set_color()

@staticmethod
def _set_error_color(node, err):
if isinstance(err, SvNoDataError):
node.set_color(color=(1, 0.3, 0))
else:
node.set_color(color=(0.8, 0.0, 0))

def _set_colors(self, node_tree):
for node in node_tree.nodes:
if hasattr(node, 'set_color'):
err = self._get_error_node(node)
if err:
self._set_error_color(node, err)
else:
self._set_update_color(node)


def _update_tree(self, node_tree):
self._root_nodes.pop(node_tree.name, None)
self._ani_nodes.pop(node_tree.name, None)
self._update_prop_soc_status(node_tree)
root_nodes = self._get_root_nodes(node_tree)
self._update_nodes_status(root_nodes)
self._process_nodes_hard(root_nodes)

def _update_from_node(self, node):
self._update_prop_cache(node)
self._process_nodes_easy([node])

def _update_from_nodes(self, nodes):
[self._update_prop_cache(node) for node in nodes]
self._process_nodes_easy(nodes)

@profile
def update(self, obj=None, props=None):
sv_types = {'SverchCustomTreeType', 'SverchGroupTreeType'}
node_trees = list(ng for ng in bpy.data.node_groups if ng.bl_idname in sv_types and ng.nodes)
self._node_has_changed.clear()
if props == 'ANIMATE':
debug('===========Start animation update================')
ani_nodes = []
for ng in node_trees:
if ng.sv_process and ng.sv_animate:
ani_nodes.extend([node for node in self._get_animate_nodes(ng)])
debug('Next animate nodes was found - {}'.format([node.name for node in ani_nodes]))
self._update_from_nodes(ani_nodes)
elif props:
raise ValueError
elif obj is None:
debug('=============Start all trees update===============')
[self._update_tree(ng) for ng in node_trees if ng.sv_process]
elif isinstance(obj, bpy.types.NodeTree):
debug('=============Start "{}" tree update==============='.format(obj.name))
if obj.sv_process:
self._update_tree(obj)
elif isinstance(obj, bpy.types.Node):
debug('=============Start "{}" node update==============='.format(obj.name))
if obj.id_data.sv_process:
self._update_from_node(obj)
else:
raise TypeError
[self._set_colors(ng) for ng in node_trees]


tree_updater = UpdateSystemMem()
Loading