30#include "RNA_prototypes.hh"
63 link->flag &= ~NODE_LINK_TEMP_HIGHLIGHT;
76 oplink.fromsock = &socket;
79 oplink.tonode = &
node;
80 oplink.tosock = &socket;
97 snode.
edittree->ensure_topology_cache();
119 bNode &node = socket->owner_node();
122 const float cursor_link_touch_distance = 12.5f *
UI_SCALE_FAC;
126 for (
bNodeLink *link : socket->directly_linked_links()) {
128 std::array<float2, NODE_LINK_RESOL + 1> coords;
131 for (
const int i :
IndexRange(coords.size() - 1)) {
133 if (distance < cursor_link_touch_distance) {
145 if (last_picked_link) {
146 link_to_pick = last_picked_link;
156 pick_link(nldrag, *snode, &node, *link_to_pick);
163 if (!sock->is_visible()) {
180 const bool allow_multiple)
188 if (sock->flag &
SELECT) {
200 if (sock->type == sock_target->
type) {
201 if (
STREQ(sock->name, sock_target->
name)) {
214 if (sock->type == sock_target->
type) {
234 maxtype =
max_ii(sock->type, maxtype);
239 for (
int socktype = maxtype; socktype >= 0; socktype--) {
246 if (sock->type == socktype) {
289 for (
bNodeLink *link : socket.directly_linked_links()) {
291 socket_location, link->multi_input_sort_id, link->tosock->runtime->total_inputs);
292 links.
append({link, location});
295 links.
append({&drag_link, cursor});
298 return a.multi_socket_position.y < b.multi_socket_position.y;
302 links[i].link->multi_input_sort_id = i;
309 if (!socket->is_multi_input()) {
314 return a->multi_input_sort_id < b->multi_input_sort_id;
318 links[i]->multi_input_sort_id = i;
328 for (
bNode *node : ntree->all_nodes()) {
330 sorted_nodes.
append(node);
336 return a->locx < b->locx;
340 for (
const int i : sorted_nodes.
as_mutable_span().drop_back(1).index_range()) {
341 bool has_selected_inputs =
false;
343 bNode *node_fr = sorted_nodes[i];
344 bNode *node_to = sorted_nodes[i + 1];
347 std::swap(node_fr, node_to);
352 if (sock_to->flag &
SELECT) {
353 has_selected_inputs =
true;
371 if (!has_selected_inputs) {
375 for (
int i = 0; i < num_inputs; i++) {
400namespace viewer_linking {
409 if (!node.is_socket_icon_drawn(socket)) {
437 if (viewer_node.
type != GEO_NODE_VIEWER) {
447 ntree.ensure_topology_cache();
464 return ELEM(node.type, CMP_NODE_VIEWER, GEO_NODE_VIEWER);
469 const bNode &node = socket.owner_node();
471 if (node.typeinfo->type == GEO_NODE_VIEWER) {
474 return socket.index() == 0;
494 if (link->tonode == &viewer_node) {
504 int last_linked_data_socket_index = -1;
505 bool has_linked_geometry_socket =
false;
510 for (
bNodeLink *link : socket->directly_linked_links()) {
512 bNode &target_node = *link->tonode;
519 has_linked_geometry_socket =
true;
522 last_linked_data_socket_index = socket->index();
528 if (last_linked_data_socket_index == -1 && !has_linked_geometry_socket) {
541 const int tot_outputs =
node_to_view.output_sockets().size();
542 for (
const int offset :
IndexRange(1, tot_outputs)) {
543 const int index = (last_linked_data_socket_index + offset) % tot_outputs;
550 already_viewed_socket = &output_socket;
554 bool is_currently_viewed =
false;
555 for (
const bNodeLink *link : output_socket.directly_linked_links()) {
557 bNode &target_node = *link->tonode;
561 if (link->is_muted()) {
567 is_currently_viewed =
true;
570 if (is_currently_viewed) {
571 already_viewed_socket = &output_socket;
574 return &output_socket;
576 return already_viewed_socket;
586 viewer_link.
flag &= ~NODE_LINK_MUTED;
587 viewer_node.
flag &= ~NODE_MUTED;
599 for (
const bNode *node :
tree.all_nodes()) {
600 if (node->is_frame()) {
618 const float step_distance,
619 const float max_distance)
622 const float y_scale = 0.5f;
625 candidates.
append(initial);
626 for (
float distance = step_distance; distance <= max_distance; distance += step_distance) {
628 const int checks = std::max<int>(2,
ceilf(
arc_length / step_distance));
630 const float angle = i /
float(checks - 1) *
M_PI;
631 const float candidate_x = initial.x + distance * std::sin(angle);
632 const float candidate_y = initial.y + distance * std::cos(angle) * y_scale;
633 candidates.
append({candidate_x, candidate_y});
649 tree.ensure_topology_cache();
651 const View2D &v2d = region.v2d;
653 region_rect.
xmin = 0;
654 region_rect.
xmax = region.winx;
655 region_rect.
ymin = 0;
656 region_rect.
ymax = region.winy;
663 const float default_padding_x =
U.node_margin;
664 const float default_padding_y = 10;
667 if (viewer_height == 0) {
674 node_to_view.runtime->totr.ymax + viewer_height + default_padding_y};
676 std::optional<float2> new_viewer_position;
680 for (
const float2 &candidate_pos : position_candidates) {
682 candidate.
xmin = candidate_pos.x;
683 candidate.
xmax = candidate_pos.x + viewer_width;
684 candidate.
ymin = candidate_pos.y - viewer_height;
685 candidate.
ymax = candidate_pos.y;
692 rctf padded_candidate = candidate;
693 BLI_rctf_pad(&padded_candidate, default_padding_x - 1, default_padding_y - 1);
697 if (!overlapping_node) {
698 new_viewer_position = candidate_pos;
703 if (!new_viewer_position) {
704 new_viewer_position = main_candidate;
717 old_position +
float2(0, viewer_height),
718 node_to_view_top_right,
719 node_to_view_bottom_right);
721 *new_viewer_position +
float2(0, viewer_height),
722 node_to_view_top_right,
723 node_to_view_bottom_right);
724 if (old_distance <= new_distance) {
725 new_viewer_position = old_position;
732 viewer_node.
parent =
nullptr;
738 bNode &bnode_to_view,
743 bNode *viewer_node =
nullptr;
745 for (
bNode *node : btree.all_nodes()) {
755 for (
bNodeLink *link : bsocket_to_view.directly_linked_links()) {
757 bNode &target_node = *link->tonode;
765 if (viewer_node ==
nullptr) {
766 for (
bNode *node : btree.all_nodes()) {
773 if (viewer_node ==
nullptr) {
774 const float2 socket_location = bsocket_to_view.
runtime->location;
782 if (viewer_bsocket ==
nullptr) {
785 viewer_bsocket->
flag &= ~SOCK_HIDDEN;
789 if (link->tosock == viewer_bsocket) {
794 if (viewer_link ==
nullptr) {
796 &btree, &bnode_to_view, &bsocket_to_view, viewer_node, viewer_bsocket);
799 viewer_link->
fromnode = &bnode_to_view;
800 viewer_link->
fromsock = &bsocket_to_view;
812 btree->ensure_topology_cache();
814 if (bsocket_to_view ==
nullptr) {
818 if (bsocket_to_view ==
nullptr) {
822 return view_socket(C, snode, *btree, bnode_to_view, *bsocket_to_view);
846 if (socket->flag &
SELECT) {
847 socket_to_view = socket;
883 ot->
name =
"Link to Viewer Node";
909 if (link.tonode && link.tosock) {
916 if (link.fromnode && link.fromsock) {
974 const int icon = !swap_links ? ICON_ADD : (new_link ? ICON_ANIM : ICON_UV_SYNC_SELECT);
1000 if (
ELEM(&socket, link->fromsock, link->tosock)) {
1016 while (socket != socket_to_match) {
1017 if (!socket->is_hidden() && socket->is_available()) {
1018 const bool sockets_are_compatible = socket->
typeinfo == socket_to_match->
typeinfo;
1019 if (sockets_are_compatible) {
1022 if (socket_has_capacity) {
1029 socket = socket->
next ? socket->
next : first_socket;
1041 if (linked_socket->is_input()) {
1042 BLI_assert(!linked_socket->is_multi_input());
1043 ntree->ensure_topology_cache();
1045 if (linked_socket->directly_linked_links().is_empty()) {
1048 bNodeLink *displaced_link = linked_socket->directly_linked_links().first();
1050 if (!replacement_socket) {
1055 displaced_link->
tosock = replacement_socket;
1057 if (replacement_socket->is_multi_input()) {
1059 for (
bNodeLink *existing_link : replacement_socket->
runtime->directly_linked_links) {
1060 if (existing_link->fromsock == displaced_link->
fromsock) {
1074 if (link->fromsock == linked_socket) {
1075 if (replacement_socket) {
1076 link->fromsock = replacement_socket;
1107 if (linked_socket.is_input()) {
1109 if (link->tosock != &linked_socket) {
1112 if (link->fromnode == start_node) {
1118 link->tosock = start_socket;
1119 link->tonode = start_node;
1124 if (link->fromsock != &linked_socket) {
1127 if (link->tonode == start_node) {
1132 link->fromsock = start_socket;
1133 link->fromnode = start_node;
1148 ntree.ensure_topology_cache();
1152 if (linked_socket.is_input()) {
1154 const bool duplicate_link = link->fromsock == dragged_link.fromsock;
1155 if (duplicate_link) {
1156 links_to_remove.
add(link);
1163 const bool duplicate_link = link->tosock == dragged_link.tosock;
1164 if (duplicate_link) {
1165 links_to_remove.
add(link);
1173 const bool link_limit_exceeded = !(link_count < link_limit);
1174 if (link_limit_exceeded) {
1175 if (links_to_remove.
add(link)) {
1181 for (
bNodeLink *link : links_to_remove) {
1196 const bool connecting_to_multi_input = linked_socket->is_multi_input() ||
1198 if (nldrag.
swap_links && !connecting_to_multi_input) {
1213 if (!link.tosock || !link.fromsock) {
1221 if (link.fromnode->typeinfo->insert_link) {
1222 if (!link.fromnode->typeinfo->insert_link(&ntree, link.fromnode, new_link)) {
1227 if (link.tonode->typeinfo->insert_link) {
1228 if (!link.tonode->typeinfo->insert_link(&ntree, link.tonode, new_link)) {
1271 bNode &tnode = tsock->owner_node();
1274 if (link.fromnode == &tnode) {
1279 bNodeLink *existing_link_connected_to_fromsock =
nullptr;
1281 if (existing_link->fromsock == link.fromsock && existing_link->tosock == tsock) {
1282 existing_link_connected_to_fromsock = existing_link;
1289 link.tosock = tsock;
1291 if (existing_link_connected_to_fromsock) {
1295 if (tsock && tsock->is_multi_input()) {
1303 link.tonode =
nullptr;
1304 link.tosock =
nullptr;
1315 bNode &node = tsock->owner_node();
1318 if (link.fromsock == tsock) {
1322 if (link.tonode == &node) {
1327 link.fromnode = &
node;
1328 link.fromsock = tsock;
1334 link.fromnode =
nullptr;
1335 link.fromsock =
nullptr;
1355 {0,
nullptr, 0,
nullptr,
nullptr},
1382 nldrag.
cursor[0] =
event->mval[0];
1383 nldrag.
cursor[1] =
event->mval[1];
1386 switch (event->
val) {
1444 bNode &node = sock->owner_node();
1446 std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
1447 nldrag->start_node = &
node;
1448 nldrag->start_socket = sock;
1451 if (nldrag->start_link_count > 0 && (nldrag->start_link_count >= link_limit || detach)) {
1456 if (link->fromsock == sock) {
1458 oplink.
next = oplink.
prev =
nullptr;
1461 nldrag->links.append(oplink);
1475 bNode &node = sock->owner_node();
1476 std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
1477 nldrag->last_node_hovered_while_dragging_a_link = &
node;
1478 nldrag->start_node = &
node;
1479 nldrag->start_socket = sock;
1482 if (nldrag->start_link_count > 0) {
1488 if (link->tosock == sock) {
1489 link_to_pick = link;
1493 if (link_to_pick !=
nullptr && !nldrag->start_socket->is_multi_input()) {
1495 oplink.
next = oplink.
prev =
nullptr;
1498 nldrag->links.append(oplink);
1533 std::unique_ptr<bNodeLinkDrag> nldrag =
node_link_init(region, snode, cursor, detach);
1557 ot->
description =
"Use the mouse to create a link between two nodes";
1576 "The position of the mouse cursor at the start of the operation",
1620 ot->
description =
"Make a link between selected output and input sockets";
1632 ot->
srna,
"replace",
false,
"Replace",
"Replace socket connections with the new links");
1654 if (path.
size() >= 256) {
1684 links_to_remove.
add(link);
1689 for (
bNodeLink *link : links_to_remove) {
1690 bNode *to_node = link->tonode;
1692 affected_nodes.
add(to_node);
1696 for (
bNode *node : affected_nodes) {
1712 ot->
description =
"Use the mouse to cut (remove) some links";
1741 for (
const bNodeLink *link : socket.directly_linked_links()) {
1763 if (path.
size() >= 256) {
1775 ntree.ensure_topology_cache();
1785 affected_links.
add(link);
1794 for (
bNodeLink *link : affected_links) {
1799 if (link->tonode->is_reroute()) {
1801 links.
push_multiple(link->tonode->output_socket(0).directly_linked_links());
1805 if (!link->
tonode->is_reroute()) {
1812 if (link->fromnode->is_reroute()) {
1815 links.
push_multiple(link->fromnode->input_socket(0).directly_linked_links());
1819 if (!link->
fromnode->is_reroute()) {
1872 for (
bNode *node : ntree.all_nodes()) {
1873 if (node->flag &
SELECT) {
1884 ot->
name =
"Detach Links";
1885 ot->
idname =
"NODE_OT_links_detach";
1887 "Remove all links to selected nodes, and try to connect neighbor nodes together";
1911 for (
bNode *node : ntree.all_nodes()) {
1912 if (node == frame) {
1930 ot->
name =
"Make Parent";
1959 join_states[node->index()].done =
true;
1961 if (node == frame) {
1962 join_states[node->index()].descendent =
true;
1964 else if (node->parent) {
1966 if (!join_states[node->parent->index()].done) {
1971 if (join_states[node->parent->index()].descendent) {
1972 join_states[node->index()].descendent =
true;
1974 else if (selected_nodes.
contains(node)) {
1978 join_states[node->index()].descendent =
true;
1981 else if (selected_nodes.
contains(node)) {
1983 join_states[node->index()].descendent =
true;
1990 for (
const bNode *parent = node.
parent; parent; parent = parent->parent) {
1994 std::reverse(parents.
begin(), parents.
end());
2000 if (nodes.is_empty()) {
2005 for (
const bNode *node : nodes.drop_front(1)) {
2011 if (candidates[i] != parents[i]) {
2023 return candidates.
last();
2038 ntree.ensure_topology_cache();
2042 for (
bNode *node : ntree.all_nodes()) {
2043 if (!join_states[node->index()].done) {
2059 ot->
description =
"Attach selected nodes to a new common frame";
2084 if (!frame->is_frame() || (frame->flag &
NODE_SELECT)) {
2101 if (frame ==
nullptr) {
2106 bool changed =
false;
2118 if (node->parent ==
nullptr) {
2124 if (node->parent == frame) {
2130 if (!share_parent) {
2149 ot->
name =
"Attach Nodes";
2174 detach_states[node->index()].done =
true;
2178 if (!detach_states[node->parent->index()].done) {
2183 if (detach_states[node->parent->index()].descendent) {
2184 detach_states[node->index()].descendent =
true;
2189 detach_states[node->index()].descendent =
true;
2193 detach_states[node->index()].descendent =
true;
2206 for (
bNode *node : ntree.all_nodes()) {
2207 if (!detach_states[node->index()].done) {
2221 ot->
name =
"Detach Nodes";
2241 bNode *selected_node =
nullptr;
2242 int selected_node_count = 0;
2244 if (node->flag &
SELECT) {
2245 selected_node =
node;
2246 selected_node_count++;
2248 if (selected_node_count > 1) {
2252 if (!selected_node) {
2255 if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) {
2258 return selected_node;
2265 if (
ELEM(
nullptr, main_input, main_output)) {
2268 if (node.is_reroute()) {
2271 if (!
tree.typeinfo->validate_link) {
2289 const bool attach_enabled,
2290 const bool is_new_node)
2298 if (!node_to_insert) {
2302 for (
bNodeSocket *socket : node_to_insert->input_sockets()) {
2303 already_linked_sockets.
extend(socket->directly_linked_sockets());
2305 for (
bNodeSocket *socket : node_to_insert->output_sockets()) {
2306 already_linked_sockets.
extend(socket->directly_linked_sockets());
2308 if (!is_new_node && !already_linked_sockets.
is_empty()) {
2319 if (
ELEM(node_to_insert, link->fromnode, link->tonode)) {
2323 if (is_new_node && !already_linked_sockets.
is_empty()) {
2326 bool is_linked_to_linked =
false;
2327 for (
const bNodeSocket *socket : already_linked_sockets) {
2328 if (
ELEM(socket, link->fromsock, link->tosock)) {
2329 is_linked_to_linked =
true;
2333 if (!is_linked_to_linked) {
2338 std::array<float2, NODE_LINK_RESOL + 1> coords;
2348 const float node_xy[] = {node_to_insert->
runtime->totr.xmin,
2349 node_to_insert->
runtime->totr.ymax};
2358 if (dist < dist_best) {
2384 if (!node_to_insert) {
2400 if (old_link ==
nullptr) {
2406 for (
bNodeSocket *socket : node_to_insert->input_sockets()) {
2407 if (!socket->directly_linked_sockets().is_empty()) {
2408 best_input = socket;
2418 for (
bNodeSocket *socket : node_to_insert->output_sockets()) {
2419 if (!socket->directly_linked_sockets().is_empty()) {
2420 best_output = socket;
2431 if (best_input !=
nullptr && ntree.
typeinfo->validate_link !=
nullptr &&
2435 best_input =
nullptr;
2437 if (best_output !=
nullptr && ntree.
typeinfo->validate_link !=
nullptr &&
2441 best_output =
nullptr;
2449 const bool best_input_is_linked = best_input && best_input->is_directly_linked();
2451 if (best_output !=
nullptr) {
2453 old_link->
fromnode = node_to_insert;
2461 if (best_input !=
nullptr) {
2463 if (!best_input_is_linked) {
2474 iofsd->
insert = node_to_insert;
2475 iofsd->
prev = from_node;
2476 iofsd->
next = to_node;
2523 ListBase *sockets = (in_out ==
SOCK_IN) ? &node.inputs : &node.outputs;
2528 if (node_decl !=
nullptr) {
2534 if (!socket->is_visible()) {
2544 int maxpriority = -1;
2553 for (
int priority = maxpriority; priority >= 0; priority--) {
2562 for (
int priority = maxpriority; priority >= 0; priority--) {
2568 sock->flag &= ~SOCK_HIDDEN;
2600 for (
bNode *node : data->ntree->all_nodes()) {
2608#define NODE_INSOFS_ANIM_DURATION 0.25f
2617 const bool reversed)
2620 bNode *ofs_node = reversed ? fromnode : tonode;
2622 if (ofs_node->
parent && ofs_node->
parent != data->insert_parent) {
2636 const bNode *parent,
2638 const bool reversed)
2640 for (
bNode *node : ntree->all_nodes()) {
2655 const bool reversed)
2658 bNode *ofs_node = reversed ? fromnode : tonode;
2660 if (data->insert_parent) {
2670 data->insert_parent =
nullptr;
2673 else if (ofs_node->
parent) {
2686 const int mouse_xy[2],
2687 const bool right_alignment)
2696 const bool needs_alignment = (
next->runtime->totr.xmin - prev->runtime->totr.xmax) <
2697 (width + (min_margin * 2.0f));
2699 float margin = width;
2717 (prev->parent && (prev->parent ==
next->parent) && (prev->parent !=
insert.parent)))
2748 float dist = right_alignment ? totr_insert.
xmin - prev->runtime->totr.xmax :
2749 next->runtime->totr.xmin - totr_insert.
xmax;
2751 if (dist < min_margin) {
2752 const float addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
2756 totr_insert.
xmin += addval;
2757 totr_insert.
xmax += addval;
2758 margin += min_margin;
2763 dist = right_alignment ?
next->runtime->totr.xmin - totr_insert.
xmax :
2764 totr_insert.
xmin - prev->runtime->totr.xmax;
2766 if (dist < min_margin) {
2767 const float addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
2768 if (needs_alignment) {
2769 bNode *offs_node = right_alignment ?
next : prev;
2787 if (needs_alignment) {
2795 right_alignment ?
next : prev,
2801 insert.parent = init_parent;
2811 bool redraw =
false;
2823 if (
UNLIKELY(node->runtime->anim_ofsx)) {
2827 if (prev_duration < clamped_duration) {
2828 const float offset_step = node->runtime->anim_ofsx *
2833 node->locx += offset_step;
2847 node->runtime->anim_ofsx = 0.0f;
2858#undef NODE_INSOFS_ANIM_DURATION
2867 if (!iofsd || !iofsd->
insert) {
2888 ot->
name =
"Insert Offset";
2889 ot->
description =
"Automatically offset nodes on insertion";
2890 ot->
idname =
"NODE_OT_insert_offset";
SpaceNode * CTX_wm_space_node(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_ntree_update_tag_link_changed(bNodeTree *ntree)
void BKE_ntree_update_tag_link_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_link_added(bNodeTree *ntree, bNodeLink *link)
float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float duration)
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
float dist_seg_seg_v2(const float a1[3], const float a2[3], const float b1[3], const float b2[3])
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
bool BLI_rctf_isect_x(const rctf *rect, float x)
bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2])
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
bool BLI_rctf_isect_y(const rctf *rect, float y)
bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2])
void BLI_rctf_pad(struct rctf *rect, float pad_x, float pad_y)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
@ NODE_LINK_TEMP_HIGHLIGHT
@ NODE_LINK_INSERT_TARGET
@ NODE_LINK_INSERT_TARGET_INVALID
@ SNODE_INSERTOFS_DIR_RIGHT
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *ntree)
bool ED_node_is_compositor(const SpaceNode *snode)
#define NODE_EDGE_PAN_OUTSIDE_PAD
#define NODE_EDGE_PAN_INSIDE_PAD
#define NODE_EDGE_PAN_MAX_SPEED
#define NODE_EDGE_PAN_DELAY
bool ED_node_is_geometry(SpaceNode *snode)
#define NODE_EDGE_PAN_ZOOM_INFLUENCE
#define NODE_EDGE_PAN_SPEED_RAMP
void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
void ED_area_tag_redraw(ScrArea *area)
bool ED_operator_node_editable(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
void ED_region_tag_redraw(ARegion *region)
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
#define REGION_DRAW_POST_PIXEL
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
#define UI_PRECISION_FLOAT_MAX
#define UI_NO_ICON_OVERLAY_TEXT
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border, const IconTextOverlay *text_overlay, const bool inverted=false)
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
void UI_view2d_edge_pan_operator_init(bContext *C, View2DEdgePanData *vpd, wmOperator *op)
void UI_view2d_edge_pan_cancel(bContext *C, View2DEdgePanData *vpd)
void UI_view2d_edge_pan_operator_properties_ex(wmOperatorType *ot, float inside_pad, float outside_pad, float speed_ramp, float max_speed, float delay, float zoom_influence)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
void void UI_view2d_edge_pan_apply_event(bContext *C, View2DEdgePanData *vpd, const wmEvent *event)
void UI_view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst) ATTR_NONNULL()
@ OPTYPE_DEPENDS_ON_CURSOR
ccl_device_inline float arc_length(float e2, float gamma)
constexpr bool contains(const T &value) const
void push_multiple(Span< T > values)
Span< Key > as_span() const
bool contains(const Key &key) const
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
void extend(Span< T > array)
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
bool is_default_link_socket
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
bool node_is_parent_and_child(const bNode *parent, const bNode *child)
void node_attach_node(bNodeTree *ntree, bNode *node, bNode *parent)
void node_set_active(bNodeTree *ntree, bNode *node)
void node_detach_node(bNodeTree *ntree, bNode *node)
void node_remove_socket_links(bNodeTree *ntree, bNodeSocket *sock)
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
void node_internal_relink(bNodeTree *ntree, bNode *node)
void node_link_set_mute(bNodeTree *ntree, bNodeLink *link, const bool muted)
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
bNode * node_find_root_parent(bNode *node)
void node_tree_node_flag_set(const bNodeTree *ntree, int flag, bool enable)
void node_chain_iterator(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *, const bool), void *userdata, bool reversed)
bNode * node_get_active(bNodeTree *ntree)
void node_parents_iterator(bNode *node, bool(*callback)(bNode *, void *), void *userdata)
void node_remove_link(bNodeTree *ntree, bNodeLink *link)
int node_socket_link_limit(const bNodeSocket *sock)
bool node_declaration_ensure(bNodeTree *ntree, bNode *node)
int node_count_socket_links(const bNodeTree *ntree, const bNodeSocket *sock)
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
static int view_socket(const bContext &C, SpaceNode &snode, bNodeTree &btree, bNode &bnode_to_view, bNodeSocket &bsocket_to_view)
static void position_viewer_node(bNodeTree &tree, bNode &viewer_node, const bNode &node_to_view, const ARegion ®ion)
static const bNode * find_overlapping_node(const bNodeTree &tree, const rctf &rect, const Span< const bNode * > ignored_nodes)
static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket *bsocket_to_view)
static bNodeSocket * determine_socket_to_view(bNode &node_to_view)
static void finalize_viewer_link(const bContext &C, SpaceNode &snode, bNode &viewer_node, bNodeLink &viewer_link)
static bNodeSocket * node_link_viewer_get_socket(bNodeTree &ntree, bNode &viewer_node, bNodeSocket &src_socket)
static void remove_links_to_unavailable_viewer_sockets(bNodeTree &btree, bNode &viewer_node)
static bool is_viewer_socket(const bNodeSocket &socket)
static bool is_viewer_node(const bNode &node)
static bool is_viewer_socket_in_viewer(const bNodeSocket &socket)
static Vector< float2 > get_viewer_node_position_candidates(const float2 initial, const float step_distance, const float max_distance)
static bool socket_can_be_viewed(const bNode &node, const bNodeSocket &socket)
static int get_default_viewer_type(const bContext *C)
void NODE_OT_parent_set(wmOperatorType *ot)
static int cut_links_exec(bContext *C, wmOperator *op)
static void draw_draglink_tooltip_activate(const ARegion ®ion, bNodeLinkDrag &nldrag)
void node_deselect_all_input_sockets(bNodeTree &node_tree, bool deselect_nodes)
static bNodeSocket * best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion, bool attach_enabled, bool is_new_node)
static void node_swap_links(bNodeLinkDrag &nldrag, bNodeTree &ntree)
void tree_draw_order_update(bNodeTree &ntree)
static int node_detach_exec(bContext *C, wmOperator *)
static int node_attach_invoke(bContext *C, wmOperator *, const wmEvent *event)
static bool need_drag_link_tooltip(const bNodeTree &node_tree, const bNodeLinkDrag &nldrag)
static bNodeLink create_drag_link(bNode &node, bNodeSocket &socket)
static void clear_picking_highlight(ListBase *links)
static void sort_multi_input_socket_links_with_drag(bNodeSocket &socket, bNodeLink &drag_link, const float2 &cursor)
bNode * add_static_node(const bContext &C, int type, const float2 &location)
static bool snode_autoconnect_input(SpaceNode &snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace)
static std::unique_ptr< bNodeLinkDrag > node_link_init(ARegion ®ion, SpaceNode &snode, const float2 cursor, const bool detach)
static int node_parent_set_exec(bContext *C, wmOperator *)
void invoke_node_link_drag_add_menu(bContext &C, bNode &node, bNodeSocket &socket, const float2 &cursor)
void NODE_OT_detach(wmOperatorType *ot)
static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const bool replace)
static Vector< const bNode * > get_sorted_node_parents(const bNode &node)
bool all_links_muted(const bNodeSocket &socket)
static bool socket_is_available(bNodeTree *, bNodeSocket *sock, const bool allow_used)
bNodeSocket * node_find_indicated_socket(SpaceNode &snode, ARegion ®ion, const float2 &cursor, const eNodeSocketInOut in_out)
static bNodeSocket * node_find_linkable_socket(const bNodeTree &ntree, const bNode *node, bNodeSocket *socket_to_match)
static void node_link_insert_offset_frame_chains(bNodeTree *ntree, const bNode *parent, NodeInsertOfsData *data, const bool reversed)
void NODE_OT_insert_offset(wmOperatorType *ot)
Array< bNode * > tree_draw_order_calc_nodes_reversed(bNodeTree &ntree)
static int get_main_socket_priority(const bNodeSocket *socket)
float2 node_link_calculate_multi_input_position(const float2 &socket_position, const int index, const int total_inputs)
void NODE_OT_links_detach(wmOperatorType *ot)
static bool dragged_links_are_detached(const bNodeLinkDrag &nldrag)
void NODE_OT_links_cut(wmOperatorType *ot)
static void pick_input_link_by_link_intersect(const bContext &C, wmOperator &op, bNodeLinkDrag &nldrag, const float2 &cursor)
static void node_detach_recursive(bNodeTree &ntree, MutableSpan< NodeDetachstate > detach_states, bNode *node)
static void node_displace_existing_links(bNodeLinkDrag &nldrag, bNodeTree &ntree)
static int mute_links_exec(bContext *C, wmOperator *op)
static void node_link_cancel(bContext *C, wmOperator *op)
static void pick_link(bNodeLinkDrag &nldrag, SpaceNode &snode, bNode *node, bNodeLink &link_to_pick)
static void displace_links(bNodeTree *ntree, const bNode *node, bNodeLink *inserted_link)
void NODE_OT_join(wmOperatorType *ot)
static bNode * node_find_frame_to_attach(ARegion ®ion, bNodeTree &ntree, const int2 mouse_xy)
static bool node_active_link_viewer_poll(bContext *C)
static bool node_can_be_inserted_on_link(bNodeTree &tree, bNode &node, const bNodeLink &link)
void NODE_OT_attach(wmOperatorType *ot)
bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int node_active_link_viewer_exec(bContext *C, wmOperator *)
static void draw_draglink_tooltip_deactivate(const ARegion ®ion, bNodeLinkDrag &nldrag)
std::optional< float2 > link_path_intersection(const bNodeLink &link, const Span< float2 > path)
void NODE_OT_link_viewer(wmOperatorType *ot)
VectorSet< bNode * > get_selected_nodes(bNodeTree &node_tree)
void node_deselect_all_output_sockets(bNodeTree &node_tree, bool deselect_nodes)
static int detach_links_exec(bContext *C, wmOperator *)
static int node_make_link_exec(bContext *C, wmOperator *op)
void node_insert_on_link_flags_clear(bNodeTree &node_tree)
static void add_dragged_links_to_tree(bContext &C, bNodeLinkDrag &nldrag)
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
void NODE_OT_link_make(wmOperatorType *ot)
void node_link_bezier_points_evaluated(const bNodeLink &link, std::array< float2, NODE_LINK_RESOL+1 > &coords)
wmKeyMap * node_link_modal_keymap(wmKeyConfig *keyconf)
static int node_join_exec(bContext *C, wmOperator *)
float2 node_to_view(const bNode &node, const float2 &co)
static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, ARegion *region, const int mouse_xy[2], const bool right_alignment)
static int node_insert_offset_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bNodeSocket * best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, const bool allow_multiple)
static int node_socket_count_links(const bNodeTree &ntree, const bNodeSocket &socket)
static bool node_link_insert_offset_chain_cb(bNode *fromnode, bNode *tonode, void *userdata, const bool reversed)
void node_to_updated_rect(const bNode &node, rctf &r_rect)
static bool should_create_drag_link_search_menu(const bNodeTree &node_tree, const bNodeLinkDrag &nldrag)
static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cursor)
void NODE_OT_link(wmOperatorType *ot)
void NODE_OT_links_mute(wmOperatorType *ot)
static const bNode * find_common_parent_node(const Span< const bNode * > nodes)
bNodeSocket * get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out)
static void node_join_attach_recursive(bNodeTree &ntree, MutableSpan< NodeJoinState > join_states, bNode *node, bNode *frame, const VectorSet< bNode * > &selected_nodes)
void update_multi_input_indices_for_removed_links(bNode &node)
static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode, bNode *tonode, void *userdata, const bool reversed)
void node_insert_on_link_flags(Main &bmain, SpaceNode &snode, bool is_new_node)
static bool node_parents_offset_flag_enable_cb(bNode *parent, void *)
static void node_remove_existing_links_if_needed(bNodeLinkDrag &nldrag, bNodeTree &ntree)
static void node_offset_apply(bNode &node, const float offset_x)
static bNode * get_selected_node_for_insertion(bNodeTree &node_tree)
static void draw_draglink_tooltip(const bContext *, ARegion *, void *arg)
static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, const float offset_x)
void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node)
T min(const T &a, const T &b)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
VecBase< float, 2 > float2
#define NODE_INSOFS_ANIM_DURATION
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
PropertyRNA * RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
bNodeTreeTypeHandle * typeinfo
bNodeRuntimeHandle * runtime
float2 multi_socket_position
std::unique_ptr< bNodeLinkDrag > linkdrag
NodeInsertOfsData * iofsd
Vector< bNodeLink > links
View2DEdgePanData pan_data
bNodeSocket * hovered_socket
bNodeLink * last_picked_multi_input_socket_link
bNode * last_node_hovered_while_dragging_a_link
std::array< int, 2 > cursor
bNodeSocket * start_socket
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
void(* cancel)(bContext *C, wmOperator *op)
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const int event_type, const double time_step)