Esempio n. 1
0
class SvNodeTreeCommon(object):
    '''
    Common methods shared between Sverchok node trees (normal and monad trees)
    '''

    # auto update toggle of the node tree
    sv_process: BoolProperty(name="Process", default=True, description='Process layout')
    has_changed: BoolProperty(default=False)  # "True if changes of links in tree was detected"

    # for throttle method usage when links are created in the tree via Python
    skip_tree_update: BoolProperty(default=False)  # usage only via throttle_update method
    tree_id_memory: StringProperty(default="")  # identifier of the tree, should be used via `tree_id` property
    sv_links = SvLinks()  # cached Python links
    nodes_dict = SvNodesDict()  # cached Python nodes

    @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 get_groups(self):
        """
        It gets monads of node tree,
        Update them (the sv_update method will check if anything changed inside the monad
        and will change the monad outputs in that case)
        Return the monads that have changed (
        to inform the caller function that the nodes downstream have to be updated with the new data)
        """
        affected_groups =[]
        for node in self.nodes:
            if 'SvGroupNode' in node.bl_idname:
                sub_tree = node.monad
                sub_tree.sv_update()
                if sub_tree.has_changed:
                    affected_groups.append(node)
                    sub_tree.has_changed = False
        return affected_groups

    def sv_update(self):
        """
        the method checks if anything changed inside the normal tree or monad
        and update them if necessary
        """
        self.sv_links.create_new_links(self)
        if self.sv_links.links_have_changed(self):
            self.has_changed = True
            build_update_list(self)
            process_from_nodes(self.sv_links.get_nodes(self))
            self.sv_links.store_links_cache(self)
        else:
            process_from_nodes(self.get_groups())

    def animation_update(self):
        """Find animatable nodes and update from them"""
        animated_nodes = []
        for node in self.nodes:
            if hasattr(node, 'is_animatable'):
                if node.is_animatable:
                    animated_nodes.append(node)
        process_from_nodes(animated_nodes)

    @contextmanager
    def throttle_update(self):
        """ usage
        with tree.throttle_update():
            tree.nodes.new(...)
            tree.links.new(...)
        tree should be updated manually if needed
        """
        previous_state = self.skip_tree_update
        self.skip_tree_update = True
        try:
            yield self
        finally:
            self.skip_tree_update = previous_state
Esempio n. 2
0
class SvNodeTreeCommon(object):
    '''
    Common methods shared between Sverchok node trees
    '''
    sv_process: BoolProperty(name="Process", default=True, description='Process layout')
    has_changed: BoolProperty(default=False)
    limited_init: BoolProperty(default=False)
    skip_tree_update: BoolProperty(default=False)
    configuring_new_node: BoolProperty(name="indicate node initialization", default=False)
    tree_id_memory: StringProperty(default="")
    sv_links = SvLinks()
    nodes_dict = SvNodesDict()

    @property
    def tree_id(self):
        if not self.tree_id_memory:
            self.tree_id_memory = str(hash(self) ^ hash(time.monotonic()))
        return self.tree_id_memory

    def build_update_list(self):
        build_update_list(self)

    def adjust_reroutes(self):

        reroutes = [n for n in self.nodes if n.bl_idname == 'NodeReroute']
        if not reroutes:
            return
        for n in reroutes:
            s = n.inputs[0]
            if s.links:
                self.freeze(True)

                other = get_other_socket(s)
                s_type = other.bl_idname
                if n.outputs[0].bl_idname != s_type:
                    out_socket = n.outputs.new(s_type, "Output")
                    in_sockets = [l.to_socket for l in n.outputs[0].links]
                    n.outputs.remove(n.outputs[0])
                    for i_s in in_sockets:
                        l = self.links.new(i_s, out_socket)

                self.unfreeze(True)

    def freeze(self, hard=False):
        if hard:
            self["don't update"] = 1
        elif not self.is_frozen():
            self["don't update"] = 0

    def is_frozen(self):
        return "don't update" in self

    def unfreeze(self, hard=False):
        if self.is_frozen():
            if hard or self["don't update"] == 0:
                del self["don't update"]

    def get_update_lists(self):
        return get_update_lists(self)

    @property
    def sv_trees(self):
        res = []
        for ng in bpy.data.node_groups:
            if ng.bl_idname in {'SverchCustomTreeType', 'SverchGroupTreeType'}:
                res.append(ng)
        return res

    def update_sv_links(self):
        self.sv_links.create_new_links(self)

    def links_have_changed(self):
        return self.sv_links.links_have_changed(self)

    def store_links_cache(self):
        self.sv_links.store_links_cache(self)

    def get_nodes(self):
        return self.sv_links.get_nodes(self)

    def get_groups(self):
        affected_groups =[]
        for node in self.nodes:
            if 'SvGroupNode' in node.bl_idname:
                sub_tree = node.monad
                sub_tree.sv_update()
                if sub_tree.has_changed:
                    affected_groups.append(node)
                    sub_tree.has_changed = False
        return affected_groups

    def sv_update(self):
        self.update_sv_links()
        if self.links_have_changed():
            self.has_changed = True
            build_update_list(self)
            process_from_nodes(self.get_nodes())
            self.store_links_cache()
        else:
            process_from_nodes(self.get_groups())

    def animation_update(self):
        animated_nodes = []
        for node in self.nodes:
            if hasattr(node, 'is_animatable'):
                if node.is_animatable:
                    animated_nodes.append(node)
        process_from_nodes(animated_nodes)
Esempio n. 3
0
class SvNodeTreeCommon(object):
    '''
    Common methods shared between Sverchok node trees
    '''

    # auto update toggle of the node tree
    sv_process: BoolProperty(name="Process",
                             default=True,
                             description='Process layout')
    has_changed: BoolProperty(
        default=False)  # "True if changes of links in tree was detected"

    # for throttle method usage when links are created in the tree via Python
    skip_tree_update: BoolProperty(
        default=False)  # usage only via throttle_update method
    tree_id_memory: StringProperty(
        default=""
    )  # identifier of the tree, should be used via `tree_id` property
    sv_links = SvLinks()  # cached Python links
    nodes_dict = SvNodesDict()  # cached Python nodes

    @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 sv_update(self):
        """
        the method checks if anything changed inside the tree
        and update it if necessary
        """
        self.sv_links.create_new_links(self)
        if self.sv_links.links_have_changed(self):
            self.has_changed = True
            build_update_list(self)
            process_from_nodes(self.sv_links.get_nodes(self))
            self.sv_links.store_links_cache(self)

    def animation_update(self):
        """Find animatable nodes and update from them"""
        animated_nodes = []
        for node in self.nodes:
            if hasattr(node, 'is_animatable'):
                if node.is_animatable:
                    animated_nodes.append(node)
        process_from_nodes(animated_nodes)

    @contextmanager
    def throttle_update(self):
        """ usage
        with tree.throttle_update():
            tree.nodes.new(...)
            tree.links.new(...)
        tree should be updated manually if needed
        """
        previous_state = self.skip_tree_update
        self.skip_tree_update = True
        try:
            yield self
        finally:
            self.skip_tree_update = previous_state

    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']
Esempio n. 4
0
class SvNodeTreeCommon(object):
    '''
    Common methods shared between Sverchok node trees (normal and monad trees)
    '''

    # auto update toggle of the node tree
    sv_process: BoolProperty(name="Process",
                             default=True,
                             description='Process layout')
    has_changed: BoolProperty(
        default=False)  # "True if changes of links in tree was detected"

    # for throttle method usage when links are created in the tree via Python
    skip_tree_update: BoolProperty(default=False)
    tree_id_memory: StringProperty(
        default=""
    )  # identifier of the tree, should be used via `tree_id` property
    sv_links = SvLinks()  # cached Python links
    nodes_dict = SvNodesDict()  # cached Python nodes

    @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 freeze(self, hard=False):
        """Temporary prevent tree from updating nodes"""
        if hard:
            self["DoNotUpdate"] = 1
        elif not self.is_frozen():
            self["DoNotUpdate"] = 0

    def is_frozen(self):
        """Nodes of the tree won't be updated during changes events"""
        return "DoNotUpdate" in self

    def unfreeze(self, hard=False):
        """
        Remove freeze mode from tree.
        If freeze mode was in hard mode `hard` argument should be True to unfreeze tree
        """
        if self.is_frozen():
            if hard or self["DoNotUpdate"] == 0:
                del self["DoNotUpdate"]

    def get_groups(self):
        """
        It gets monads of node tree,
        Update them (the sv_update method will check if anything changed inside the monad
        and will change the monad outputs in that case)
        Return the monads that have changed (
        to inform the caller function that the nodes downstream have to be updated with the new data)
        """
        affected_groups = []
        for node in self.nodes:
            if 'SvGroupNode' in node.bl_idname:
                sub_tree = node.monad
                sub_tree.sv_update()
                if sub_tree.has_changed:
                    affected_groups.append(node)
                    sub_tree.has_changed = False
        return affected_groups

    def sv_update(self):
        """
        the method checks if anything changed inside the normal tree or monad
        and update them if necessary
        """
        self.sv_links.create_new_links(self)
        if self.sv_links.links_have_changed(self):
            self.has_changed = True
            build_update_list(self)
            process_from_nodes(self.sv_links.get_nodes(self))
            self.sv_links.store_links_cache(self)
        else:
            process_from_nodes(self.get_groups())

    def animation_update(self):
        """Find animatable nodes and update from them"""
        animated_nodes = []
        for node in self.nodes:
            if hasattr(node, 'is_animatable'):
                if node.is_animatable:
                    animated_nodes.append(node)
        process_from_nodes(animated_nodes)