def send(event: TreeEvent): # this should be first other wise other instructions can spoil the node statistic to redraw if NodesUpdater.is_running(): if event.cancel: NodesUpdater.cancel_task() else: return # ignore the event # frame update if event.type == TreeEvent.FRAME_CHANGE: ContextTrees.mark_nodes_outdated(event.tree, event.updated_nodes) # mark given nodes as outdated elif event.type == TreeEvent.NODES_UPDATE: ContextTrees.mark_nodes_outdated(event.tree, event.updated_nodes) # it will find changes in tree topology and mark related nodes as outdated elif event.type == TreeEvent.TREE_UPDATE: ContextTrees.mark_tree_outdated(event.tree) # force update elif event.type == TreeEvent.FORCE_UPDATE: ContextTrees.reset_data(event.tree) event.tree['FORCE_UPDATE'] = True # Unknown event else: raise TypeError(f'Detected unknown event - {event}') # Add update tusk for the tree NodesUpdater.add_task(event)
def process_ani(self): """ Process the Sverchok node tree if animation layers show true. For animation callback/handler """ if self.sv_animate: animated_nodes = ( n for n in self.nodes if hasattr(n, 'is_animatable') and n.is_animatable) TreeHandler.send( TreeEvent(TreeEvent.FRAME_CHANGE, self, animated_nodes))
def send(event: TreeEvent): # this should be first other wise other instructions can spoil the node statistic to redraw if NodesUpdater.is_running(): if event.cancel: NodesUpdater.cancel_task() else: return # ignore the event # frame update # This event can't be handled via NodesUpdater during animation rendering because new frame change event # can arrive before timer finishes its tusk. Or timer can start working before frame change is handled. if event.type == TreeEvent.FRAME_CHANGE: ContextTrees.mark_nodes_outdated(event.tree, event.updated_nodes) list(global_updater(event.type)) return # mark given nodes as outdated elif event.type == TreeEvent.NODES_UPDATE: ContextTrees.mark_nodes_outdated(event.tree, event.updated_nodes) # it will find changes in tree topology and mark related nodes as outdated elif event.type == TreeEvent.TREE_UPDATE: ContextTrees.mark_tree_outdated(event.tree) # force update elif event.type == TreeEvent.FORCE_UPDATE: ContextTrees.reset_data(event.tree) event.tree['FORCE_UPDATE'] = True # Unknown event else: raise TypeError(f'Detected unknown event - {event}') # Add update tusk for the tree NodesUpdater.add_task(event)
class SverchCustomTree(NodeTree, SvNodeTreeCommon): ''' Sverchok - architectural node programming of geometry in low level ''' bl_idname = 'SverchCustomTreeType' bl_label = 'Sverchok Nodes' bl_icon = 'RNA' def turn_off_ng(self, context): """ Turn on/off displaying objects in viewport generated by viewer nodes Viewer nodes should have `show_viewport` method which takes 'to_show' bool argument """ for node in self.nodes: try: node.show_viewport(self.sv_show) except AttributeError: pass def on_draft_mode_changed(self, context): """ This is triggered when Draft mode of the tree is toggled. """ draft_nodes = [] for node in self.nodes: if hasattr(node, 'does_support_draft_mode' ) and node.does_support_draft_mode(): draft_nodes.append(node) node.on_draft_mode_changed(self.sv_draft) # From the user perspective, some of node parameters # got new parameter values, so the setup should be recalculated; # but techically, node properties were not changed # (only other properties were shown in UI), so enabling/disabling # of draft mode does not automatically trigger tree update. # Here we trigger it manually. if draft_nodes: self.update_nodes(draft_nodes) sv_process: BoolProperty( name="Process", default=True, description='Update upon tree and node property changes', update=lambda s, c: TreeHandler.send( TreeEvent(TreeEvent.TREE_UPDATE, s)), options=set(), ) sv_animate: BoolProperty(name="Animate", default=True, description='Animate this layout', options=set()) sv_show: BoolProperty(name="Show", default=True, description='Show this layout', update=turn_off_ng, options=set()) sv_show_time_graph: BoolProperty(name="Time Graph", default=False, options=set()) # todo is not used now sv_show_time_nodes: BoolProperty(name="Node times", default=False, options=set(), update=lambda s, c: s.update_ui()) show_time_mode: EnumProperty( items=[(n, n, '') for n in ["Per node", "Cumulative"]], options=set(), update=lambda s, c: s.update_ui(), description="Mode of showing node update timings", ) sv_show_socket_menus: BoolProperty( name="Show socket menus", description= "Display socket dropdown menu buttons. NOTE: options that are enabled in those menus will be effective regardless of this checkbox!", default=False, options=set()) # draft mode replaces selected properties of certain nodes with smaller values to lighten cpu load. sv_draft: BoolProperty( name="Draft", description="Draft (simplified processing) mode", default=False, update=on_draft_mode_changed, options=set(), ) def update(self): """This method is called if collection of nodes or links of the tree was changed""" TreeHandler.send(TreeEvent(TreeEvent.TREE_UPDATE, self)) def force_update(self): """Update whole tree from scratch""" # ideally we would never like to use this method but we live in the real world TreeHandler.send(TreeEvent(TreeEvent.FORCE_UPDATE, self)) def update_nodes(self, nodes, cancel=True): """This method expects to get list of its nodes which should be updated""" return TreeHandler.send( TreeEvent(TreeEvent.NODES_UPDATE, self, nodes, cancel)) def process_ani(self): """ Process the Sverchok node tree if animation layers show true. For animation callback/handler """ if self.sv_animate: animated_nodes = ( n for n in self.nodes if hasattr(n, 'is_animatable') and n.is_animatable) TreeHandler.send( TreeEvent(TreeEvent.FRAME_CHANGE, self, animated_nodes)) def update_ui(self): """ The method get information about node statistic of last update from the handler to show in view space The method is usually called by main handler to reevaluate view of the nodes in the tree even if the tree is not in the Live update mode""" nodes_errors = TreeHandler.get_error_nodes(self) if self.sv_show_time_nodes: update_time = (TreeHandler.get_cum_time(self) if self.show_time_mode == "Cumulative" else TreeHandler.get_update_time(self)) else: update_time = cycle([None]) for node, error, update in zip(self.nodes, nodes_errors, update_time): if hasattr(node, 'update_ui'): node.update_ui(error, update)
def update_nodes(self, nodes, cancel=True): """This method expects to get list of its nodes which should be updated""" return TreeHandler.send( TreeEvent(TreeEvent.NODES_UPDATE, self, nodes, cancel))
def force_update(self): """Update whole tree from scratch""" # ideally we would never like to use this method but we live in the real world TreeHandler.send(TreeEvent(TreeEvent.FORCE_UPDATE, self))
def update(self): """This method is called if collection of nodes or links of the tree was changed""" TreeHandler.send(TreeEvent(TreeEvent.TREE_UPDATE, self))