File: node_functions.py

package info (click to toggle)
blender 4.3.2%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 309,564 kB
  • sloc: cpp: 2,385,210; python: 330,236; ansic: 280,972; xml: 2,446; sh: 972; javascript: 317; makefile: 170
file content (95 lines) | stat: -rw-r--r-- 2,990 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# SPDX-FileCopyrightText: 2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later

from bpy.app.translations import pgettext_tip as tip_


def node_editor_poll(cls, context):
    space = context.space_data
    if space is None or (space.type != 'NODE_EDITOR'):
        cls.poll_message_set("Active editor is not a node editor.")
        return False
    if space.node_tree is None:
        cls.poll_message_set("Node tree was not found in the active node editor.")
        return False
    if space.node_tree.library is not None:
        cls.poll_message_set("Active node tree is linked from another .blend file.")
        return False
    if not space.edit_tree.nodes:
        cls.poll_message_set("Active node tree does not contain any nodes.")
        return False
    return True


def node_space_type_poll(cls, context, types):
    if context.space_data.tree_type not in types:
        tree_types_str = ", ".join(t.split('NodeTree')[0].lower() for t in sorted(types))
        poll_message = tip_("Current node tree type not supported.\n"
                            "Should be one of {:s}.").format(tree_types_str)
        cls.poll_message_set(poll_message)
        return False
    return True


def get_group_output_node(tree, output_node_idname='NodeGroupOutput'):
    for node in tree.nodes:
        if node.bl_idname == output_node_idname and node.is_active_output:
            return node


def get_output_location(tree):
    # get right-most location.
    sorted_by_xloc = (sorted(tree.nodes, key=lambda x: x.location.x))
    max_xloc_node = sorted_by_xloc[-1]

    # get average y location.
    sum_yloc = 0
    for node in tree.nodes:
        sum_yloc += node.location.y

    loc_x = max_xloc_node.location.x + max_xloc_node.dimensions.x + 80
    loc_y = sum_yloc / len(tree.nodes)
    return loc_x, loc_y


def get_internal_socket(socket):
    # get the internal socket from a socket inside or outside the group.
    node = socket.node
    if node.type == 'GROUP_OUTPUT':
        iterator = node.id_data.interface.items_tree
    elif node.type == 'GROUP_INPUT':
        iterator = node.id_data.interface.items_tree
    elif hasattr(node, "node_tree"):
        iterator = node.node_tree.interface.items_tree
    else:
        return None

    for s in iterator:
        if s.identifier == socket.identifier:
            return s
    return iterator[0]


def is_visible_socket(socket):
    return not socket.hide and socket.enabled and socket.type != 'CUSTOM'


def is_viewer_link(link, output_node):
    if link.to_node == output_node and link.to_socket == output_node.inputs[0]:
        return True
    if link.to_node.type == 'GROUP_OUTPUT':
        socket = get_internal_socket(link.to_socket)
        if socket.is_inspect_output:
            return True
    return False


def force_update(context):
    context.space_data.node_tree.update_tag()


class NodeEditorBase:
    @classmethod
    def poll(cls, context):
        return node_editor_poll(cls, context)