34#include "RNA_prototypes.hh"
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) {
221 if (node->is_reroute()) {
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;
330 return a->location[0] < b->location[0];
334 for (
const int i : sorted_nodes.
as_mutable_span().drop_back(1).index_range()) {
335 bool has_selected_inputs =
false;
337 bNode *node_fr = sorted_nodes[
i];
338 bNode *node_to = sorted_nodes[
i + 1];
341 std::swap(node_fr, node_to);
346 if (sock_to->flag &
SELECT) {
347 has_selected_inputs =
true;
365 if (!has_selected_inputs) {
369 for (
int i = 0;
i < num_inputs;
i++) {
403 if (!socket.is_icon_visible()) {
441 ntree.ensure_topology_cache();
463 const bNode &node = socket.owner_node();
468 return socket.index() == 0;
488 if (link->tonode == &viewer_node) {
498 int last_linked_data_socket_index = -1;
499 bool has_linked_geometry_socket =
false;
504 for (
bNodeLink *link : socket->directly_linked_links()) {
506 bNode &target_node = *link->tonode;
513 has_linked_geometry_socket =
true;
516 last_linked_data_socket_index = socket->index();
522 if (last_linked_data_socket_index == -1 && !has_linked_geometry_socket) {
535 const int tot_outputs =
node_to_view.output_sockets().size();
536 for (
const int offset :
IndexRange(1, tot_outputs)) {
537 const int index = (last_linked_data_socket_index + offset) % tot_outputs;
544 already_viewed_socket = &output_socket;
548 bool is_currently_viewed =
false;
549 for (
const bNodeLink *link : output_socket.directly_linked_links()) {
551 bNode &target_node = *link->tonode;
555 if (link->is_muted()) {
561 is_currently_viewed =
true;
564 if (is_currently_viewed) {
565 already_viewed_socket = &output_socket;
568 return &output_socket;
570 return already_viewed_socket;
589 if (node->is_type(
"CompositorNodeViewer") && node != &viewer_node) {
602 for (
const bNode *node :
tree.all_nodes()) {
603 if (node->is_frame()) {
609 if (
BLI_rctf_isect(&rect, &node->runtime->draw_bounds,
nullptr)) {
621 const float step_distance,
622 const float max_distance)
625 const float y_scale = 0.5f;
628 candidates.
append(initial);
631 const int checks = std::max<int>(2,
ceilf(
arc_length / step_distance));
633 const float angle =
i / float(checks - 1) *
M_PI;
634 const float candidate_x = initial.x +
distance * std::sin(
angle);
635 const float candidate_y = initial.y +
distance * std::cos(
angle) * y_scale;
636 candidates.
append({candidate_x, candidate_y});
656 tree.ensure_topology_cache();
660 region_rect.
xmin = 0;
662 region_rect.
ymin = 0;
675 if (!is_new_viewer_node &&
684 const float default_padding_x =
U.node_margin;
685 const float default_padding_y = 10;
686 const float viewer_width = is_new_viewer_node ?
689 const float viewer_height = is_new_viewer_node ?
693 const float2 main_candidate{
node_to_view.runtime->draw_bounds.xmax + default_padding_x,
694 node_to_view.runtime->draw_bounds.ymax + viewer_height +
697 std::optional<float2> new_viewer_position;
701 for (
const float2 &candidate_pos : position_candidates) {
703 candidate.
xmin = candidate_pos.x;
704 candidate.
xmax = candidate_pos.x + viewer_width;
705 candidate.
ymin = candidate_pos.y - viewer_height;
706 candidate.
ymax = candidate_pos.y;
713 rctf padded_candidate = candidate;
714 BLI_rctf_pad(&padded_candidate, default_padding_x - 1, default_padding_y - 1);
718 if (!overlapping_node) {
719 new_viewer_position = candidate_pos;
724 if (!new_viewer_position) {
725 new_viewer_position = main_candidate;
730 viewer_node.
parent =
nullptr;
736 bNode &bnode_to_view,
739 bNode *viewer_node =
nullptr;
741 for (
bNode *node : btree.all_nodes()) {
751 for (
bNodeLink *link : bsocket_to_view.directly_linked_links()) {
753 bNode &target_node = *link->tonode;
761 if (viewer_node ==
nullptr) {
762 for (
bNode *node : btree.all_nodes()) {
769 if (viewer_node ==
nullptr) {
770 const float2 socket_location = bsocket_to_view.
runtime->location;
778 if (viewer_bsocket ==
nullptr) {
785 if (link->tosock == viewer_bsocket) {
790 if (viewer_link ==
nullptr) {
792 btree, bnode_to_view, bsocket_to_view, *viewer_node, *viewer_bsocket);
795 viewer_link->
fromnode = &bnode_to_view;
796 viewer_link->
fromsock = &bsocket_to_view;
808 btree->ensure_topology_cache();
810 if (bsocket_to_view ==
nullptr) {
814 if (bsocket_to_view ==
nullptr) {
818 return view_socket(
C, snode, *btree, bnode_to_view, *bsocket_to_view);
842 if (socket->flag &
SELECT) {
843 socket_to_view = socket;
879 ot->name =
"Link to Viewer Node";
880 ot->description =
"Link to viewer node";
881 ot->idname =
"NODE_OT_link_viewer";
970 const int icon = !swap_links ? ICON_ADD : (new_link ? ICON_ANIM : ICON_UV_SYNC_SELECT);
996 if (
ELEM(&socket, link->fromsock, link->tosock)) {
1012 while (socket != socket_to_match) {
1013 if (socket->is_visible()) {
1014 const bool sockets_are_compatible = socket->
typeinfo == socket_to_match->
typeinfo;
1015 if (sockets_are_compatible) {
1018 if (socket_has_capacity) {
1025 socket = socket->
next ? socket->
next : first_socket;
1037 if (linked_socket->is_input()) {
1038 BLI_assert(!linked_socket->is_multi_input());
1039 ntree->ensure_topology_cache();
1041 if (linked_socket->directly_linked_links().is_empty()) {
1044 bNodeLink *displaced_link = linked_socket->directly_linked_links().first();
1046 if (!replacement_socket) {
1051 displaced_link->
tosock = replacement_socket;
1053 if (replacement_socket->is_multi_input()) {
1055 for (
bNodeLink *existing_link : replacement_socket->
runtime->directly_linked_links) {
1070 if (link->fromsock == linked_socket) {
1071 if (replacement_socket) {
1072 link->fromsock = replacement_socket;
1103 if (linked_socket.is_input()) {
1105 if (link->tosock != &linked_socket) {
1108 if (link->fromnode == start_node) {
1114 link->tosock = start_socket;
1115 link->tonode = start_node;
1120 if (link->fromsock != &linked_socket) {
1123 if (link->tonode == start_node) {
1128 link->fromsock = start_socket;
1129 link->fromnode = start_node;
1144 ntree.ensure_topology_cache();
1148 if (linked_socket.is_input()) {
1151 if (duplicate_link) {
1152 links_to_remove.
add(link);
1159 const bool duplicate_link = link->
tosock == dragged_link.
tosock;
1160 if (duplicate_link) {
1161 links_to_remove.
add(link);
1169 const bool link_limit_exceeded = !(link_count < link_limit);
1170 if (link_limit_exceeded) {
1171 if (links_to_remove.
add(link)) {
1177 for (
bNodeLink *link : links_to_remove) {
1192 const bool connecting_to_multi_input = linked_socket->is_multi_input() ||
1194 if (nldrag.
swap_links && !connecting_to_multi_input) {
1267 bNode &tnode = tsock->owner_node();
1275 bNodeLink *existing_link_connected_to_fromsock =
nullptr;
1277 if (existing_link->fromsock == link.
fromsock && existing_link->tosock == tsock) {
1278 existing_link_connected_to_fromsock = existing_link;
1287 if (existing_link_connected_to_fromsock) {
1291 if (tsock && tsock->is_multi_input()) {
1311 bNode &node = tsock->owner_node();
1318 if (link.
tonode == &node) {
1351 {0,
nullptr, 0,
nullptr,
nullptr},
1378 nldrag.
cursor[0] =
event->mval[0];
1379 nldrag.
cursor[1] =
event->mval[1];
1382 switch (event->
val) {
1436 tree.ensure_topology_cache();
1439 if (!link->is_available()) {
1452 snode.
edittree->ensure_topology_cache();
1453 bNode &node = sock->owner_node();
1455 std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
1456 nldrag->start_node = &node;
1457 nldrag->start_socket = sock;
1460 if (nldrag->start_link_count > 0 && (nldrag->start_link_count >= link_limit || detach)) {
1465 if (link->fromsock == sock) {
1467 oplink.
next = oplink.
prev =
nullptr;
1470 nldrag->links.append(oplink);
1485 snode.
edittree->ensure_topology_cache();
1486 bNode &node = sock->owner_node();
1487 std::unique_ptr<bNodeLinkDrag> nldrag = std::make_unique<bNodeLinkDrag>();
1488 nldrag->last_node_hovered_while_dragging_a_link = &node;
1489 nldrag->start_node = &node;
1490 nldrag->start_socket = sock;
1493 if (nldrag->start_link_count > 0) {
1499 if (link->tosock == sock) {
1500 link_to_pick = link;
1504 if (link_to_pick !=
nullptr && !nldrag->start_socket->is_multi_input()) {
1506 oplink.
next = oplink.
prev =
nullptr;
1509 nldrag->links.append(oplink);
1544 std::unique_ptr<bNodeLinkDrag> nldrag =
node_link_init(region, snode, cursor, detach);
1566 ot->name =
"Link Nodes";
1567 ot->idname =
"NODE_OT_link";
1568 ot->description =
"Use the mouse to create a link between two nodes";
1579 RNA_def_boolean(
ot->srna,
"detach",
false,
"Detach",
"Detach and redirect existing links");
1587 "The position of the mouse cursor at the start of the operation",
1630 ot->name =
"Make Links";
1631 ot->description =
"Make a link between selected output and input sockets";
1632 ot->idname =
"NODE_OT_link_make";
1643 ot->srna,
"replace",
false,
"Replace",
"Replace socket connections with the new links");
1665 if (path.
size() >= 256) {
1680 node_tree.ensure_topology_cache();
1695 links_to_remove.
add(link);
1700 for (
bNodeLink *link : links_to_remove) {
1701 bNode *to_node = link->tonode;
1703 affected_nodes.
add(to_node);
1706 node_tree.ensure_topology_cache();
1707 for (
bNode *node : affected_nodes) {
1721 ot->name =
"Cut Links";
1722 ot->idname =
"NODE_OT_links_cut";
1723 ot->description =
"Use the mouse to cut (remove) some links";
1752 for (
const bNodeLink *link : socket.directly_linked_links()) {
1774 if (path.
size() >= 256) {
1786 ntree.ensure_topology_cache();
1796 affected_links.
add(link);
1805 for (
bNodeLink *link : affected_links) {
1810 if (link->tonode->is_reroute()) {
1812 links.
push_multiple(link->tonode->output_socket(0).directly_linked_links());
1816 if (!link->
tonode->is_reroute()) {
1823 if (link->fromnode->is_reroute()) {
1826 links.
push_multiple(link->fromnode->input_socket(0).directly_linked_links());
1830 if (!link->
fromnode->is_reroute()) {
1847 ot->name =
"Mute Links";
1848 ot->idname =
"NODE_OT_links_mute";
1849 ot->description =
"Use the mouse to mute links";
1883 for (
bNode *node : ntree.all_nodes()) {
1884 if (node->flag &
SELECT) {
1895 ot->name =
"Detach Links";
1896 ot->idname =
"NODE_OT_links_detach";
1898 "Remove all links to selected nodes, and try to connect neighbor nodes together";
1918 if (!frame || !frame->is_frame()) {
1922 for (
bNode *node : ntree.all_nodes()) {
1923 if (node == frame) {
1941 ot->name =
"Make Parent";
1942 ot->description =
"Attach selected nodes";
1943 ot->idname =
"NODE_OT_parent_set";
1970 join_states[node->index()].done =
true;
1972 if (node == frame) {
1973 join_states[node->index()].descendent =
true;
1977 if (!join_states[node->
parent->index()].done) {
1982 if (join_states[node->
parent->index()].descendent) {
1983 join_states[node->index()].descendent =
true;
1985 else if (selected_nodes.
contains(node)) {
1989 join_states[node->index()].descendent =
true;
1992 else if (selected_nodes.
contains(node)) {
1994 join_states[node->index()].descendent =
true;
2005 std::reverse(parents.
begin(), parents.
end());
2011 if (
nodes.is_empty()) {
2016 for (
const bNode *node :
nodes.drop_front(1)) {
2022 if (candidates[
i] != parents[
i]) {
2034 return candidates.
last();
2049 ntree.ensure_topology_cache();
2053 for (
bNode *node : ntree.all_nodes()) {
2054 if (!join_states[node->index()].done) {
2087 ot->name =
"Join Nodes";
2088 ot->description =
"Attach selected nodes to a new common frame";
2089 ot->idname =
"NODE_OT_join";
2114 if (!frame->is_frame() || (frame->flag &
NODE_SELECT)) {
2131 if (node.
parent ==
nullptr) {
2134 if (node.
parent == &frame) {
2139 if (!share_parent) {
2151 if (frame ==
nullptr) {
2156 bool changed =
false;
2180 ot->name =
"Attach Nodes";
2181 ot->description =
"Attach active node to a frame";
2182 ot->idname =
"NODE_OT_attach";
2205 detach_states[node->index()].done =
true;
2209 if (!detach_states[node->
parent->index()].done) {
2214 if (detach_states[node->
parent->index()].descendent) {
2215 detach_states[node->index()].descendent =
true;
2220 detach_states[node->index()].descendent =
true;
2224 detach_states[node->index()].descendent =
true;
2237 for (
bNode *node : ntree.all_nodes()) {
2238 if (!detach_states[node->index()].done) {
2252 ot->name =
"Detach Nodes";
2253 ot->description =
"Detach selected nodes from parents";
2254 ot->idname =
"NODE_OT_detach";
2272 bNode *selected_node =
nullptr;
2273 int selected_node_count = 0;
2274 for (
bNode *node : node_tree.all_nodes()) {
2275 if (node->flag &
SELECT) {
2276 selected_node = node;
2277 selected_node_count++;
2279 if (selected_node_count > 1) {
2283 if (!selected_node) {
2286 if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) {
2289 return selected_node;
2296 if (
ELEM(
nullptr, main_input, main_output)) {
2299 if (node.is_reroute()) {
2302 if (!
tree.typeinfo->validate_link) {
2320 const bool attach_enabled,
2321 const bool is_new_node)
2324 node_tree.ensure_topology_cache();
2329 if (!node_to_insert) {
2333 for (
bNodeSocket *socket : node_to_insert->input_sockets()) {
2334 already_linked_sockets.
extend(socket->directly_linked_sockets());
2336 for (
bNodeSocket *socket : node_to_insert->output_sockets()) {
2337 already_linked_sockets.
extend(socket->directly_linked_sockets());
2339 if (!is_new_node && !already_linked_sockets.
is_empty()) {
2350 if (
ELEM(node_to_insert, link->fromnode, link->tonode)) {
2354 if (is_new_node && !already_linked_sockets.
is_empty()) {
2357 bool is_linked_to_linked =
false;
2358 for (
const bNodeSocket *socket : already_linked_sockets) {
2359 if (
ELEM(socket, link->fromsock, link->tosock)) {
2360 is_linked_to_linked =
true;
2364 if (!is_linked_to_linked) {
2369 std::array<float2, NODE_LINK_RESOL + 1> coords;
2380 const float node_xy[] = {node_to_insert->
runtime->draw_bounds.xmin,
2381 node_to_insert->
runtime->draw_bounds.ymax};
2390 if (dist < dist_best) {
2410 snode.
edittree->ensure_topology_cache();
2443 node_tree.ensure_topology_cache();
2445 if (!node_to_insert) {
2461 if (old_link ==
nullptr) {
2467 for (
bNodeSocket *socket : node_to_insert->input_sockets()) {
2468 if (!socket->directly_linked_sockets().is_empty()) {
2469 best_input = socket;
2479 for (
bNodeSocket *socket : node_to_insert->output_sockets()) {
2480 if (!socket->directly_linked_sockets().is_empty()) {
2481 best_output = socket;
2490 if (!node_to_insert->is_reroute()) {
2492 if (best_input !=
nullptr && ntree.
typeinfo->validate_link !=
nullptr &&
2496 best_input =
nullptr;
2498 if (best_output !=
nullptr && ntree.
typeinfo->validate_link !=
nullptr &&
2502 best_output =
nullptr;
2510 const bool best_input_is_linked = best_input && best_input->is_directly_linked();
2512 if (best_output !=
nullptr) {
2514 old_link->
fromnode = node_to_insert;
2522 if (best_input !=
nullptr) {
2524 if (!best_input_is_linked) {
2535 iofsd->
insert = node_to_insert;
2536 iofsd->
prev = from_node;
2537 iofsd->
next = to_node;
2591 if (node_decl !=
nullptr) {
2595 if (!socket_decl->is_default_link_socket) {
2599 if (socket && socket->is_visible()) {
2606 int maxpriority = -1;
2615 for (
int priority = maxpriority; priority >= 0; priority--) {
2643#define NODE_INSOFS_ANIM_DURATION 0.25f
2652 const bool reversed)
2655 bNode *ofs_node = reversed ? fromnode : tonode;
2664 const int mouse_xy[2],
2665 const bool right_alignment)
2674 const bool needs_alignment = (
next->runtime->draw_bounds.xmin -
2675 prev->runtime->draw_bounds.xmax) < (width + (min_margin * 2.0f));
2677 float margin = width;
2695 (prev->parent && (prev->parent ==
next->parent) && (prev->parent !=
insert.parent)))
2702 if (!frame->is_frame() || (frame->flag &
NODE_SELECT)) {
2726 float dist = right_alignment ? totr_insert.
xmin - prev->runtime->draw_bounds.xmax :
2727 next->runtime->draw_bounds.xmin - totr_insert.
xmax;
2729 if (dist < min_margin) {
2730 const float addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
2734 totr_insert.
xmin += addval;
2735 totr_insert.
xmax += addval;
2736 margin += min_margin;
2741 dist = right_alignment ?
next->runtime->draw_bounds.xmin - totr_insert.
xmax :
2742 totr_insert.
xmin - prev->runtime->draw_bounds.xmax;
2744 if (dist < min_margin) {
2745 const float addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
2746 if (needs_alignment) {
2747 bNode *offs_node = right_alignment ?
next : prev;
2758 if (needs_alignment) {
2765 right_alignment ?
next : prev,
2771 insert.parent = init_parent;
2781 bool redraw =
false;
2793 if (
UNLIKELY(node->runtime->anim_ofsx)) {
2797 if (prev_duration < clamped_duration) {
2798 const float offset_step = node->runtime->anim_ofsx *
2803 node->location[0] += offset_step;
2817 node->runtime->anim_ofsx = 0.0f;
2828#undef NODE_INSOFS_ANIM_DURATION
2839 if (!iofsd || !iofsd->
insert) {
2860 ot->name =
"Insert Offset";
2861 ot->description =
"Automatically offset nodes on insertion";
2862 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_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
void BKE_ntree_update_tag_active_output_changed(bNodeTree *ntree)
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)
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
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
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const 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_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
ATTR_WARN_UNUSED_RESULT const size_t num
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_VIEWER_SHORTCUT_NONE
@ NODE_LINK_TEMP_HIGHLIGHT
@ NODE_LINK_INSERT_TARGET
@ NODE_LINK_INSERT_TARGET_INVALID
@ SNODE_INSERTOFS_DIR_RIGHT
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
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
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
BMesh const char void * data
ccl_device_inline float arc_length(const float e2, const float gamma)
void append(const T &value)
constexpr bool contains(const T &value) const
void push_multiple(Span< T > values)
bool contains(const Key &key) const
Span< Key > as_span() 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
float distance(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_mallocN(size_t len, const char *str)
void * MEM_callocN(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)
bNode * node_get_active(bNodeTree &ntree)
void node_remove_link(bNodeTree *ntree, bNodeLink &link)
void node_chain_iterator(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *, const bool), void *userdata, bool reversed)
void node_parents_iterator(bNode *node, bool(*callback)(bNode *, void *), void *userdata)
int node_count_socket_links(const bNodeTree &ntree, const bNodeSocket &sock)
void node_internal_relink(bNodeTree &ntree, bNode &node)
void node_detach_node(bNodeTree &ntree, bNode &node)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
void node_link_set_mute(bNodeTree &ntree, bNodeLink &link, const bool muted)
void node_remove_socket_links(bNodeTree &ntree, bNodeSocket &sock)
bool node_declaration_ensure(bNodeTree &ntree, bNode &node)
void node_set_active(bNodeTree &ntree, bNode &node)
int node_socket_link_limit(const bNodeSocket &sock)
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
void node_tree_node_flag_set(bNodeTree &ntree, int flag, bool enable)
static int view_socket(const bContext &C, SpaceNode &snode, bNodeTree &btree, bNode &bnode_to_view, bNodeSocket &bsocket_to_view)
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 socket_can_be_viewed(const bNodeSocket &socket)
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 int get_default_viewer_type(const bContext *C)
static void position_viewer_node(const bContext &C, bNodeTree &tree, bNode &viewer_node, const bNode &node_to_view)
void NODE_OT_parent_set(wmOperatorType *ot)
static wmOperatorStatus node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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 wmOperatorStatus mute_links_exec(bContext *C, wmOperator *op)
static void node_swap_links(bNodeLinkDrag &nldrag, bNodeTree &ntree)
void tree_draw_order_update(bNodeTree &ntree)
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 wmOperatorStatus node_join_exec(bContext *C, wmOperator *)
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)
void invoke_node_link_drag_add_menu(bContext &C, bNode &node, bNodeSocket &socket, const float2 &cursor)
static wmOperatorStatus node_active_link_viewer_exec(bContext *C, wmOperator *)
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 can_attach_node_to_frame(const bNode &node, const bNode &frame)
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 wmOperatorStatus node_insert_offset_modal(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
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 wmOperatorStatus node_attach_invoke(bContext *C, wmOperator *, const wmEvent *event)
static void node_detach_recursive(bNodeTree &ntree, MutableSpan< NodeDetachstate > detach_states, bNode *node)
static void node_displace_existing_links(bNodeLinkDrag &nldrag, bNodeTree &ntree)
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 wmOperatorStatus node_detach_exec(bContext *C, wmOperator *)
static wmOperatorStatus detach_links_exec(bContext *C, wmOperator *)
static bool node_can_be_inserted_on_link(bNodeTree &tree, bNode &node, const bNodeLink &link)
void NODE_OT_attach(wmOperatorType *ot)
void node_insert_on_frame_flag_set(bContext &C, SpaceNode &snode, const int2 &cursor)
bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
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 wmOperatorStatus node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
float2 node_to_view(const float2 &co)
void node_insert_on_link_flags_clear(bNodeTree &node_tree)
static void add_dragged_links_to_tree(bContext &C, bNodeLinkDrag &nldrag)
static void remove_unavailable_links(bNodeTree &tree, bNodeSocket &socket)
static wmOperatorStatus node_parent_set_exec(bContext *C, wmOperator *)
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 wmOperatorStatus node_make_link_exec(bContext *C, wmOperator *op)
static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, ARegion *region, const int mouse_xy[2], const bool right_alignment)
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 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)
void node_insert_on_frame_flag_clear(SpaceNode &snode)
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)
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 wmOperatorStatus cut_links_exec(bContext *C, wmOperator *op)
static void node_offset_apply(bNode &node, const float offset_x)
static wmOperatorStatus node_join_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bNode * get_selected_node_for_insertion(bNodeTree &node_tree)
static void draw_draglink_tooltip(const bContext *, ARegion *, void *arg)
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< int32_t, 2 > int2
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)
ARegionRuntimeHandle * runtime
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
struct bNodeTree * nodetree
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
bNodeTreeTypeHandle * typeinfo
bNodeTypeHandle * typeinfo
bNodeRuntimeHandle * runtime
float2 multi_socket_position
std::optional< int > frame_identifier_to_highlight
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
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)
void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
wmOperatorStatus WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus 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)
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const wmEventType event_type, const double time_step)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)