Пример #1
0
    def check_reroutes_sockets(self):
        """
        Fix reroute sockets type
        For now it does work properly in first update
        because all new sockets even if they have links have `is_linked` attribute with False value
        at next update events all works perfectly (skip first update?)

        There is hope this will be fixed https://developer.blender.org/T82390
        """
        tree = Tree(self)
        socket_job = []
        Requirements = namedtuple('Requirements', [
            'left_n_i', 'left_s_i', 'left_t', 'reroute_n_i', 'right_n_is',
            'right_s_is'
        ])
        # analytical part, it's impossible to use Tree structure and modify the tree
        for node in tree.sorted_walk(tree.output_nodes):
            # walk should be sorted in case if reroute nodes are going one after other
            if node.bl_tween.bl_idname == 'NodeReroute':
                rer_in_s = node.inputs[0]
                rer_out_s = node.outputs[0]
                if rer_in_s.links:
                    left_s = rer_in_s.linked_sockets[0]
                    left_type = left_s.type if hasattr(
                        left_s, 'type') else left_s.bl_tween.bl_idname
                    if left_type != rer_in_s.bl_tween.bl_idname:
                        rer_out_s.type = left_type
                        socket_job.append(
                            Requirements(
                                left_s.node.index, left_s.index, left_type,
                                node.index, [
                                    s.node.index
                                    for s in rer_out_s.linked_sockets
                                ], [s.index
                                    for s in rer_out_s.linked_sockets]))

        # regenerating sockets
        for props in socket_job:
            left_s = self.nodes[props.left_n_i].outputs[props.left_s_i]
            reroute = self.nodes[props.reroute_n_i]

            # handle input socket
            in_s = reroute.inputs.new(props.left_t, left_s.name)
            self.links.new(in_s, left_s)
            reroute.inputs.remove(reroute.inputs[0])

            # handle output sockets
            out_s = reroute.outputs.new(props.left_t, left_s.name)
            for right_n_i, right_s_i in zip(props.right_n_is,
                                            props.right_s_is):
                left_s = self.nodes[right_n_i].inputs[right_s_i]
                self.links.new(left_s, out_s)
            reroute.outputs.remove(reroute.outputs[0])
Пример #2
0
def group_global_handler() -> Generator[Node]:
    """
    It should find changes and update group nodes
    After that update system of main trees should update themselves
    meanwhile group nodes should be switched off because they already was updated
    """
    for bl_tree in (t for t in bpy.data.node_groups if t.bl_idname == 'SvGroupTree'):
        # for now it always update all trees todo should be optimized later (keep in mind, trees can become outdated)
        ContextTrees.update_tree(bl_tree)

    for bl_tree in (t for t in bpy.data.node_groups if t.bl_idname == 'SverchCustomTreeType'):
        outdated_group_nodes = set()
        tree = Tree(bl_tree)
        for node in tree.sorted_walk(tree.output_nodes):
            if hasattr(node.bl_tween, 'updater'):

                group_updater = node.bl_tween.updater(is_input_changed=False)  # just searching inner changes
                try:
                    # it should return only nodes which should be updated
                    while True:
                        yield next(group_updater)
                except CancelError:
                    group_updater.throw(CancelError)
                except StopIteration as stop_error:
                    sub_tree_changed, error = stop_error.value
                    if sub_tree_changed:
                        outdated_group_nodes.add(node.bl_tween)
        # passing running to update system of main tree
        if outdated_group_nodes:
            outdated_group_nodes = list(outdated_group_nodes)
            active_states = [n.is_active for n in outdated_group_nodes]
            try:
                [n.toggle_active(False) for n in outdated_group_nodes]
                bl_tree.update_nodes(list(outdated_group_nodes))
            except Exception:
                traceback.print_exc()
            finally:
                [n.toggle_active(s, to_update=False) for s, n in zip(active_states, outdated_group_nodes)]