예제 #1
0
    def update(self):
        """trigger on links or nodes collections changes, on assigning tree to a group node
        also it is triggered when a tree, next in the path, was changed (even if this tree was not effected)"""
        # When group input or output nodes are connected some extra work should be done
        if 'init_tree' in self.id_data:  # tree is building by a script - let it do this
            return

        self.check_last_socket(
        )  # Should not be too expensive to call it each update

        if self.name not in bpy.data.node_groups:  # load new file event
            return
        if not hasattr(bpy.context.space_data,
                       'path'):  # 3D panel also can call update method O_o
            return
        if not self.group_node_name:  # initialization tree
            return

        group_node: SvGroupTreeNode = None
        # update tree can lead to calling update of previous tree too, so should find position tree in the path
        for i, path in zip(range(-1, -1000, -1),
                           reversed(bpy.context.space_data.path)):
            if path.node_tree == self:
                group_node = bpy.context.space_data.path[
                    i - 1].node_tree.nodes[self.group_node_name]
                break
        if group_node is None:
            # the tree was assigned to a group node, it does not have sense to update
            return

        self.check_reroutes_sockets()
        self.update_sockets(
        )  # probably more precise trigger could be found for calling this method
        handle_event(ev.GroupTreeEvent(self, self.get_update_path()))
예제 #2
0
 def execute(self, context):
     group_node = context.node
     sub_tree: SvGroupTree = context.node.node_tree
     context.space_data.path.append(sub_tree, node=group_node)
     sub_tree.group_node_name = group_node.name
     event = ev.GroupTreeEvent(sub_tree, sub_tree.get_update_path())
     handle_event(event)
     # todo make protection from editing the same trees in more then one area
     # todo add the same logic to exit from tree operator
     return {'FINISHED'}
예제 #3
0
def sv_pre_load(scene):
    """
    This method is called whenever new file is opening
    THe update order is next:
    1. pre_load handler
    2. update methods of trees in a file
    3. post_load handler
    4. evaluate trees from main tree handler
    """
    clear_all_socket_cache()
    sv_clean(scene)

    handle_event(ev.FileEvent())
예제 #4
0
    def update_nodes(self, nodes: list):
        """
        This method expect to get list of its nodes which should be updated
        Execution won't be immediately, use cases -
        1. Node property of was changed
        2. ???
        """
        # the method can be called during tree reconstruction from JSON file
        # in this case we does not intend doing any updates
        if not self.group_node_name:  # initialization tree
            return

        handle_event(ev.GroupPropertyEvent(self, self.get_update_path(),
                                           nodes))
예제 #5
0
 def update_group_tree(self, context):
     """Apply filtered tree to `node_tree` attribute.
     By this attribute Blender is aware of linking between the node and nested tree."""
     handle_event(ev.TreesGraphEvent())
     self.node_tree: SvGroupTree = self.group_tree
     # also default values should be fixed
     if self.node_tree:
         self.node_tree.use_fake_user = True
         for node_sock, interface_sock in zip(self.inputs,
                                              self.node_tree.inputs):
             if hasattr(interface_sock, 'default_value') and hasattr(
                     node_sock, 'default_property'):
                 node_sock.default_property = interface_sock.default_value
             self.node_tree.update_sockets(
             )  # properties of input socket properties should be updated
     else:  # in case if None is assigned to node_tree
         self.inputs.clear()
         self.outputs.clear()
예제 #6
0
 def sv_free(self):
     handle_event(ev.TreesGraphEvent())
예제 #7
0
 def sv_copy(self, original):
     handle_event(ev.TreesGraphEvent())
예제 #8
0
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: handle_event(ev.TreeEvent(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_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(),
    )
    sv_scene_update: BoolProperty(
        name="Scene update",
        description="Update upon changes in the scene",
        options=set(),
        default=True)

    def update(self):
        """This method is called if collection of nodes or links of the tree was changed"""
        handle_event(ev.TreeEvent(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
        handle_event(ev.ForceEvent(self))

    def update_nodes(self, nodes, cancel=True):
        """This method expects to get list of its nodes which should be updated"""
        return handle_event(ev.PropertyEvent(self, nodes))

    def scene_update(self):
        """This method should be called by scene changes handler
        it ignores events related with S
        sverchok trees in other cases it updates nodes which read data from Blender"""
        handle_event(ev.SceneEvent(self))

    def process_ani(self, frame_changed: bool, animation_playing: bool):
        """
        Process the Sverchok node tree if animation layers show true.
        For animation callback/handler
        """
        handle_event(ev.AnimationEvent(self, frame_changed, animation_playing))
예제 #9
0
class SvNodeTreeCommon:
    """Common class for all Sverchok trees (regular trees and group ones)"""
    tree_id_memory: StringProperty(
        default=""
    )  # identifier of the tree, should be used via `tree_id` property
    sv_show_time_nodes: BoolProperty(
        name="Node times",
        default=False,
        options=set(),
        update=lambda s, c: handle_event(ev.TreeEvent(s)))
    show_time_mode: EnumProperty(
        items=[(n, n, '') for n in ["Per node", "Cumulative"]],
        options=set(),
        update=lambda s, c: handle_event(ev.TreeEvent(s)),
        description="Mode of showing node update timings",
    )

    @property
    def tree_id(self):
        """Identifier of the tree"""
        if not self.tree_id_memory:
            self.tree_id_memory = str(hash(self) ^ hash(time.monotonic()))
        return self.tree_id_memory

    def update_gl_scale_info(self, origin=None):
        """
        the nodeview scale and dpi differs between users and must be queried to get correct nodeview
        x,y and dpi scale info.

        this is instead of calling `get_dpi_factor` on every redraw.
        """

        debug(f"update_gl_scale_info called from {origin or self.name}")
        try:
            from sverchok.utils.context_managers import sv_preferences
            with sv_preferences() as prefs:
                prefs.set_nodeview_render_params(None)
        except Exception as err:
            debug('failed to get gl scale info', err)

    @contextmanager
    def init_tree(self):
        """It suppresses calling the update method of nodes,
        main usage of it is during generating tree with python (JSON import)"""
        is_already_initializing = 'init_tree' in self
        if is_already_initializing:
            yield self
        else:
            self['init_tree'] = ''
            try:
                yield self
            finally:
                del self['init_tree']

    def update_ui(self, nodes_errors, update_time):
        """ 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"""
        update_time = update_time if self.sv_show_time_nodes else cycle([None])
        for node, error, update in zip(self.nodes, nodes_errors, update_time):
            if hasattr(node, 'update_ui'):
                node.update_ui(error, update)
예제 #10
0
 def process_ani(self, frame_changed: bool, animation_playing: bool):
     """
     Process the Sverchok node tree if animation layers show true.
     For animation callback/handler
     """
     handle_event(ev.AnimationEvent(self, frame_changed, animation_playing))
예제 #11
0
 def scene_update(self):
     """This method should be called by scene changes handler
     it ignores events related with S
     sverchok trees in other cases it updates nodes which read data from Blender"""
     handle_event(ev.SceneEvent(self))
예제 #12
0
 def update_nodes(self, nodes, cancel=True):
     """This method expects to get list of its nodes which should be updated"""
     return handle_event(ev.PropertyEvent(self, nodes))
예제 #13
0
 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
     handle_event(ev.ForceEvent(self))
예제 #14
0
 def update(self):
     """This method is called if collection of nodes or links of the tree was changed"""
     handle_event(ev.TreeEvent(self))