WIP: Fix #108049: Nodes: Start to using node activity #108057

Closed
Iliya Katushenock wants to merge 6 commits from mod_moder:tmp_fix_node_active into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
14 changed files with 126 additions and 91 deletions

View File

@ -644,6 +644,16 @@ inline bool bNode::is_group_output() const
return this->type == NODE_GROUP_OUTPUT;
}
inline bool bNode::is_selected() const
{
return this->flag & NODE_SELECT;
}
inline bool bNode::is_active() const
{
return this->flag & NODE_ACTIVE;
}
inline blender::Span<bNodeLink> bNode::internal_links() const
{
return this->runtime->internal_links;

View File

@ -2750,7 +2750,7 @@ namespace blender::bke {
bool nodeLinkIsSelected(const bNodeLink *link)
{
return (link->fromnode->flag & NODE_SELECT) || (link->tonode->flag & NODE_SELECT);
return (link->fromnode->is_selected()) || (link->tonode->is_selected());
}
/* Adjust the indices of links connected to the given multi input socket after deleting the link at
@ -3811,8 +3811,21 @@ bNode *nodeGetActive(bNodeTree *ntree)
return nullptr;
}
BLI_assert([ntree]() -> bool {
int active_node_count = 0;
for (bNode *node : ntree->all_nodes()) {
if (node->is_active()) {
active_node_count++;
}
}
if (ELEM(active_node_count, 0, 1)) {
return true;
}
return false;
}());
for (bNode *node : ntree->all_nodes()) {
if (node->flag & NODE_ACTIVE) {
if (node->is_active()) {
return node;
}
}

View File

@ -42,6 +42,7 @@ struct NodeClipboardItem {
};
struct NodeClipboard {
bNode *active_node;
Vector<NodeClipboardItem> nodes;
Vector<bNodeLink> links;
@ -52,6 +53,7 @@ struct NodeClipboard {
}
this->nodes.clear_and_shrink();
this->links.clear_and_shrink();
this->active_node = nullptr;
}
/**
@ -130,11 +132,15 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator * /*op*/)
Map<const bNodeSocket *, bNodeSocket *> socket_map;
for (const bNode *node : tree.all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
clipboard.add_node(*node, node_map, socket_map);
}
}
if (bNode *active_node = nodeGetActive(&tree)) {
clipboard.active_node = node_map.lookup_default(active_node, nullptr);
}
for (bNode *new_node : node_map.values()) {
/* Parent pointer must be redirected to new node or detached if parent is not copied. */
if (new_node->parent) {
@ -151,7 +157,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator * /*op*/)
LISTBASE_FOREACH (bNodeLink *, link, &tree.links) {
BLI_assert(link->tonode);
BLI_assert(link->fromnode);
if (link->tonode->flag & NODE_SELECT && link->fromnode->flag & NODE_SELECT) {
if (link->tonode->is_selected() && link->fromnode->is_selected()) {
bNodeLink new_link{};
new_link.flag = link->flag;
new_link.tonode = node_map.lookup(link->tonode);
@ -320,6 +326,11 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
remap_pairing(tree, node_map);
if (clipboard.active_node != nullptr) {
bNode *new_active_node = node_map.lookup(clipboard.active_node);
nodeSetActive(&tree, new_active_node);
}
tree.ensure_topology_cache();
for (bNode *new_node : node_map.values()) {
/* Update multi input socket indices in case all connected nodes weren't copied. */

View File

@ -1575,7 +1575,7 @@ void draw_nodespace_back_pix(const bContext &C,
bNode *node = (bNode *)snode.edittree->nodes.first;
rctf *viewer_border = &snode.nodetree->viewer_border;
while (node) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
if (node->typeinfo->draw_backdrop) {
node->typeinfo->draw_backdrop(&snode, ibuf, node, x, y);
}

View File

@ -215,8 +215,8 @@ static bool compare_node_depth(const bNode *a, const bNode *b)
{
/* These tell if either the node or any of the parent nodes is selected.
* A selected parent means an unselected node is also in foreground! */
bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
bool a_select = a->is_selected(), b_select = b->is_selected();
bool a_active = a->is_active(), b_active = b->is_active();
/* If one is an ancestor of the other. */
/* XXX there might be a better sorting algorithm for stable topological sort,
@ -227,10 +227,10 @@ static bool compare_node_depth(const bNode *a, const bNode *b)
return false;
}
/* Any selected ancestor moves the node forward. */
if (parent->flag & NODE_ACTIVE) {
if (parent->is_active()) {
a_active = true;
}
if (parent->flag & NODE_SELECT) {
if (parent->is_selected()) {
a_select = true;
}
}
@ -240,10 +240,10 @@ static bool compare_node_depth(const bNode *a, const bNode *b)
return true;
}
/* Any selected ancestor moves the node forward. */
if (parent->flag & NODE_ACTIVE) {
if (parent->is_active()) {
b_active = true;
}
if (parent->flag & NODE_SELECT) {
if (parent->is_selected()) {
b_select = true;
}
}
@ -1425,7 +1425,7 @@ static void node_draw_shadow(const SpaceNode &snode,
{
const rctf &rct = node.runtime->totr;
UI_draw_roundbox_corner_set(UI_CNR_ALL);
ui_draw_dropshadow(&rct, radius, snode.runtime->aspect, alpha, node.flag & SELECT);
ui_draw_dropshadow(&rct, radius, snode.runtime->aspect, alpha, node.is_selected());
}
static void node_draw_sockets(const View2D &v2d,
@ -2286,14 +2286,6 @@ static void node_draw_basis(const bContext &C,
node_add_error_message_button(tree_draw_ctx, node, block, rct, iconofs);
/* Title. */
if (node.flag & SELECT) {
UI_GetThemeColor4fv(TH_SELECT, color);
}
else {
UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
}
/* Collapse/expand icon. */
{
const int but_size = U.widget_unit * 0.8f;
@ -2366,7 +2358,7 @@ static void node_draw_basis(const bContext &C,
}
/* Draw selected nodes fully opaque. */
if (node.flag & SELECT) {
if (node.is_active()) {
color[3] = 1.0f;
}
@ -2411,18 +2403,19 @@ static void node_draw_basis(const bContext &C,
/* Outline. */
{
const rctf rect = {
rct.xmin - outline_width,
rct.xmax + outline_width,
rct.ymin - outline_width,
rct.ymax + outline_width,
};
rctf rect = rct;
BLI_rctf_pad(&rect, outline_width, outline_width);
/* Color the outline according to active, selected, or undefined status. */
float color_outline[4];
if (node.flag & SELECT) {
UI_GetThemeColor4fv((node.flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, color_outline);
if (node.is_selected()) {
if (node.is_active()) {
UI_GetThemeColor4fv(TH_ACTIVE, color_outline);
}
else {
UI_GetThemeColor4fv(TH_SELECT, color_outline);
}
}
else if (bke::node_type_is_undefined(&node)) {
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
@ -2509,7 +2502,7 @@ static void node_draw_hidden(const bContext &C,
}
/* Draw selected nodes fully opaque. */
if (node.flag & SELECT) {
if (node.is_active()) {
color[3] = 1.0f;
}
@ -2522,7 +2515,7 @@ static void node_draw_hidden(const bContext &C,
}
/* Title. */
if (node.flag & SELECT) {
if (node.is_active()) {
UI_GetThemeColor4fv(TH_SELECT, color);
}
else {
@ -2577,18 +2570,19 @@ static void node_draw_hidden(const bContext &C,
/* Outline. */
{
const float outline_width = 1.0f;
const rctf rect = {
rct.xmin - outline_width,
rct.xmax + outline_width,
rct.ymin - outline_width,
rct.ymax + outline_width,
};
rctf rect = rct;
BLI_rctf_pad(&rect, outline_width, outline_width);
/* Color the outline according to active, selected, or undefined status. */
float color_outline[4];
if (node.flag & SELECT) {
UI_GetThemeColor4fv((node.flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, color_outline);
if (node.is_selected()) {
if (node.is_active()) {
UI_GetThemeColor4fv(TH_ACTIVE, color_outline);
}
else {
UI_GetThemeColor4fv(TH_SELECT, color_outline);
}
}
else if (bke::node_type_is_undefined(&node)) {
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
@ -2952,14 +2946,13 @@ static void frame_node_draw(const bContext &C,
UI_draw_roundbox_4fv(&rct, true, BASIS_RAD, color);
/* Outline active and selected emphasis. */
if (node.flag & SELECT) {
if (node.flag & NODE_ACTIVE) {
if (node.is_selected()) {
if (node.is_active()) {
UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
}
else {
UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
}
UI_draw_roundbox_aa(&rct, false, BASIS_RAD, color);
}
@ -3012,7 +3005,7 @@ static void reroute_node_draw(
/* Only draw input socket as they all are placed on the same position highlight
* if node itself is selected, since we don't display the node body separately. */
node_draw_sockets(region.v2d, C, ntree, node, block, false, node.flag & SELECT);
node_draw_sockets(region.v2d, C, ntree, node, block, false, node.is_selected());
UI_block_end(&C, &block);
UI_block_draw(&C, &block);

View File

@ -1239,7 +1239,7 @@ static void node_duplicate_reparent_recursive(bNodeTree *ntree,
/* Find first selected parent. */
for (parent = node->parent; parent; parent = parent->parent) {
if (parent->flag & SELECT) {
if (parent->is_selected()) {
if (!(parent->flag & NODE_TEST)) {
node_duplicate_reparent_recursive(ntree, node_map, parent);
}
@ -1295,6 +1295,8 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
Map<const bNodeSocket *, bNodeSocket *> socket_map;
Map<const ID *, ID *> duplicated_node_groups;
bNode *actibe_node = nodeGetActive(ntree);
for (bNode *node : get_selected_nodes(*ntree)) {
bNode *new_node = bke::node_copy_with_mapping(
ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map);
@ -1322,8 +1324,8 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
/* This creates new links between copied nodes. If keep_inputs is set, also copies input links
* from unselected (when fromnode is null)! */
if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
(keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT))))
if (link->tonode && (link->tonode->is_selected()) &&
(keep_inputs || (link->fromnode && (link->fromnode->is_selected()))))
{
bNodeLink *newlink = MEM_cnew<bNodeLink>("bNodeLink");
newlink->flag = link->flag;
@ -1334,7 +1336,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
newlink->multi_input_socket_index = link->multi_input_socket_index;
}
if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
if (link->fromnode && (link->fromnode->is_selected())) {
newlink->fromnode = node_map.lookup(link->fromnode);
newlink->fromsock = socket_map.lookup(link->fromsock);
}
@ -1370,14 +1372,17 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
remap_pairing(*ntree, node_map);
if (bNode *new_active_node = node_map.lookup_default(actibe_node, nullptr)) {
nodeSetActive(ntree, new_active_node);
}
/* Deselect old nodes, select the copies instead. */
for (const auto item : node_map.items()) {
bNode *src_node = item.key;
bNode *dst_node = item.value;
nodeSetSelected(src_node, false);
src_node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
nodeSetSelected(dst_node, true);
nodeSetSelected(src_node, false);
src_node->flag &= ~(NODE_ACTIVE_TEXTURE);
}
ED_node_tree_propagate_change(C, bmain, snode->edittree);
@ -1525,7 +1530,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
int tot_eq = 0, tot_neq = 0;
for (bNode *node : snode->edittree->all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
continue;
@ -1545,7 +1550,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
}
}
for (bNode *node : snode->edittree->all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
continue;
@ -1641,7 +1646,7 @@ static int node_deactivate_viewer_exec(bContext *C, wmOperator * /*op*/)
if (node->type != GEO_NODE_VIEWER) {
continue;
}
if (!(node->flag & SELECT)) {
if (!(node->is_selected())) {
continue;
}
if (node == active_viewer) {
@ -1715,7 +1720,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator * /*op*/)
/* Toggle for all selected nodes */
bool hidden = false;
for (bNode *node : snode->edittree->all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
if (node_has_hidden_sockets(node)) {
hidden = true;
break;
@ -1724,7 +1729,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator * /*op*/)
}
for (bNode *node : snode->edittree->all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
node_set_hidden_sockets(snode, node, !hidden);
}
}
@ -1765,7 +1770,7 @@ static int node_mute_exec(bContext *C, wmOperator * /*op*/)
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
for (bNode *node : snode->edittree->all_nodes()) {
if ((node->flag & SELECT) && !node->typeinfo->no_muting) {
if (node->is_selected() && !node->typeinfo->no_muting) {
node->flag ^= NODE_MUTED;
BKE_ntree_update_tag_node_mute(snode->edittree, node);
}
@ -1808,7 +1813,7 @@ static int node_delete_exec(bContext *C, wmOperator * /*op*/)
node_select_paired(*snode->edittree);
LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (node->is_selected()) {
nodeRemoveNode(bmain, snode->edittree, node, true);
}
}
@ -1855,7 +1860,7 @@ static int node_switch_view_exec(bContext *C, wmOperator * /*op*/)
SpaceNode *snode = CTX_wm_space_node(C);
LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (node->is_selected()) {
/* Call the update function from the Switch View node. */
node->runtime->update = NODE_UPDATE_OPERATOR;
}
@ -1898,7 +1903,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator * /*op*/)
node_select_paired(*snode->edittree);
LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) {
if (node->flag & SELECT) {
if (node->is_selected()) {
blender::bke::nodeInternalRelink(snode->edittree, node);
nodeRemoveNode(bmain, snode->edittree, node, true);
}
@ -2122,7 +2127,7 @@ static int node_copy_color_exec(bContext *C, wmOperator * /*op*/)
}
for (bNode *node : ntree.all_nodes()) {
if (node->flag & NODE_SELECT && node != active_node) {
if (node->is_selected() && node != active_node) {
if (active_node->flag & NODE_CUSTOM_COLOR) {
node->flag |= NODE_CUSTOM_COLOR;
copy_v3_v3(node->color, active_node->color);

View File

@ -519,7 +519,7 @@ static bool node_group_separate_selected(
}
/* ensure valid parent pointers, detach if parent stays inside the group */
if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) {
if (newnode->parent && !(newnode->parent->is_selected())) {
nodeDetachNode(&ngroup, newnode);
}

View File

@ -336,7 +336,7 @@ static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const
Vector<bNode *> sorted_nodes;
for (bNode *node : ntree->all_nodes()) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
sorted_nodes.append(node);
}
}
@ -1721,7 +1721,7 @@ static int detach_links_exec(bContext *C, wmOperator * /*op*/)
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
for (bNode *node : ntree.all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
bke::nodeInternalRelink(&ntree, node);
}
}
@ -1763,7 +1763,7 @@ static int node_parent_set_exec(bContext *C, wmOperator * /*op*/)
if (node == frame) {
continue;
}
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
nodeDetachNode(&ntree, node);
nodeAttachNode(&ntree, node, frame);
}
@ -1894,7 +1894,7 @@ static bNode *node_find_frame_to_attach(ARegion &region,
LISTBASE_FOREACH_BACKWARD (bNode *, frame, &ntree.nodes) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
if ((frame->type != NODE_FRAME) || (frame->is_selected())) {
continue;
}
if (BLI_rctf_isect_pt_v(&frame->runtime->totr, cursor)) {
@ -1917,7 +1917,7 @@ static int node_attach_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *e
}
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) {
if (!(node->flag & NODE_SELECT)) {
if (!(node->is_selected())) {
continue;
}
@ -1990,13 +1990,13 @@ static void node_detach_recursive(bNodeTree &ntree,
if (detach_states[node->parent->index()].descendent) {
detach_states[node->index()].descendent = true;
}
else if (node->flag & NODE_SELECT) {
else if (node->is_selected()) {
/* If parent is not a descendant of a selected node, detach. */
nodeDetachNode(&ntree, node);
detach_states[node->index()].descendent = true;
}
}
else if (node->flag & NODE_SELECT) {
else if (node->is_selected()) {
detach_states[node->index()].descendent = true;
}
}
@ -2048,7 +2048,7 @@ static bNode *get_selected_node_for_insertion(bNodeTree &node_tree)
bNode *selected_node = nullptr;
int selected_node_count = 0;
for (bNode *node : node_tree.all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
selected_node = node;
selected_node_count++;
}
@ -2453,7 +2453,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd,
/* check nodes front to back */
for (frame = (bNode *)ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) {
if ((frame->type != NODE_FRAME) || (frame->is_selected())) {
continue;
}

View File

@ -314,10 +314,10 @@ void node_select_paired(bNodeTree &node_tree)
for (bNode *input_node : node_tree.nodes_by_type("GeometryNodeSimulationInput")) {
const auto *storage = static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
if (bNode *output_node = node_tree.node_by_id(storage->output_node_id)) {
if (input_node->flag & NODE_SELECT) {
if (input_node->is_selected()) {
output_node->flag |= NODE_SELECT;
}
if (output_node->flag & NODE_SELECT) {
if (output_node->is_selected()) {
input_node->flag |= NODE_SELECT;
}
}
@ -328,7 +328,7 @@ VectorSet<bNode *> get_selected_nodes(bNodeTree &node_tree)
{
VectorSet<bNode *> selected_nodes;
for (bNode *node : node_tree.all_nodes()) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
selected_nodes.add(node);
}
}
@ -347,7 +347,7 @@ static bool node_select_grouped_type(bNodeTree &node_tree, bNode &node_act)
{
bool changed = false;
for (bNode *node : node_tree.all_nodes()) {
if ((node->flag & SELECT) == 0) {
if (!node->is_selected()) {
if (node->type == node_act.type) {
nodeSetSelected(node, true);
changed = true;
@ -361,7 +361,7 @@ static bool node_select_grouped_color(bNodeTree &node_tree, bNode &node_act)
{
bool changed = false;
for (bNode *node : node_tree.all_nodes()) {
if ((node->flag & SELECT) == 0) {
if (!node->is_selected()) {
if (compare_v3v3(node->color, node_act.color, 0.005f)) {
nodeSetSelected(node, true);
changed = true;
@ -388,7 +388,7 @@ static bool node_select_grouped_name(bNodeTree &node_tree, bNode &node_act, cons
}
for (bNode *node : node_tree.all_nodes()) {
if (node->flag & SELECT) {
if (node->is_selected()) {
continue;
}
pref_len_curr = BLI_str_partition_ex_utf8(
@ -566,7 +566,7 @@ static bool node_mouse_select(bContext *C,
if (sock) {
node = &sock->owner_node();
found = true;
node_was_selected = node->flag & SELECT;
node_was_selected = node->is_selected();
/* NOTE: SOCK_IN does not take into account the extend case...
* This feature is not really used anyway currently? */
@ -578,7 +578,7 @@ static bool node_mouse_select(bContext *C,
if (sock) {
node = &sock->owner_node();
found = true;
node_was_selected = node->flag & SELECT;
node_was_selected = node->is_selected();
if (sock->flag & SELECT) {
if (extend) {
@ -619,10 +619,10 @@ static bool node_mouse_select(bContext *C,
/* Find the closest visible node. */
node = node_under_mouse_select(node_tree, cursor);
found = (node != nullptr);
node_was_selected = node && (node->flag & SELECT);
node_was_selected = node && node->is_selected();
if (params->sel_op == SEL_OP_SET) {
if ((found && params->select_passthrough) && (node->flag & SELECT)) {
if (found && params->select_passthrough && node->is_selected()) {
found = false;
}
else if (found || params->deselect_all) {
@ -642,7 +642,7 @@ static bool node_mouse_select(bContext *C,
break;
case SEL_OP_XOR: {
/* Check active so clicking on an inactive node activates it. */
bool is_selected = (node->flag & NODE_SELECT) && (node->flag & NODE_ACTIVE);
bool is_selected = node->is_selected() && node->is_active();
nodeSetSelected(node, !is_selected);
break;
}
@ -983,7 +983,7 @@ static bool do_lasso_select_node(bContext *C,
BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
for (bNode *node : node_tree.all_nodes()) {
if (select && (node->flag & NODE_SELECT)) {
if (select && (node->is_selected())) {
continue;
}
@ -1083,7 +1083,7 @@ void NODE_OT_select_lasso(wmOperatorType *ot)
static bool any_node_selected(const bNodeTree &node_tree)
{
for (const bNode *node : node_tree.all_nodes()) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
return true;
}
}
@ -1118,7 +1118,7 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
break;
case SEL_INVERT:
for (bNode *node : node_tree.all_nodes()) {
nodeSetSelected(node, !(node->flag & SELECT));
nodeSetSelected(node, !(node->is_selected()));
}
break;
}

View File

@ -873,7 +873,7 @@ static int /*eContextResult*/ node_context(const bContext *C,
if (CTX_data_equals(member, "selected_nodes")) {
if (snode->edittree) {
LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node);
}
}

View File

@ -91,7 +91,7 @@ static void create_transform_data_for_node(TransData &td,
static bool is_node_parent_select(const bNode *node)
{
while ((node = node->parent)) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
return true;
}
}
@ -292,7 +292,7 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
/* remove selected nodes on cancel */
if (ntree) {
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
if (node->flag & NODE_SELECT) {
if (node->is_selected()) {
nodeRemoveNode(bmain, ntree, node, true);
}
}

View File

@ -1498,8 +1498,8 @@ bool peelObjectsTransform(TransInfo *t,
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetOP snap_target_select)
{
/* node is use for snapping only if a) snap mode matches and b) node is inside the view */
return (((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && !(node->flag & NODE_SELECT)) ||
(snap_target_select == SCE_SNAP_TARGET_ALL && !(node->flag & NODE_ACTIVE))) &&
return (((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && !(node->is_selected())) ||
(snap_target_select == SCE_SNAP_TARGET_ALL && !(node->is_active()))) &&
(node->runtime->totr.xmin < v2d->cur.xmax && node->runtime->totr.xmax > v2d->cur.xmin &&
node->runtime->totr.ymin < v2d->cur.ymax && node->runtime->totr.ymax > v2d->cur.ymin);
}

View File

@ -386,6 +386,9 @@ typedef struct bNode {
/** A span containing all internal links when the node is muted. */
blender::Span<bNodeLink> internal_links() const;
bool is_selected() const;
bool is_active() const;
/* The following methods are only available when #bNodeTree.ensure_topology_cache has been
* called. */

View File

@ -236,7 +236,7 @@ static bNode *node_get_active(bNodeTree *ntree, int sub_activity)
if (node->flag & sub_activity) {
activetexnode = node;
/* if active we can return immediately */
if (node->flag & NODE_ACTIVE) {
if (node->is_active()) {
return node;
}
}
@ -244,7 +244,7 @@ static bNode *node_get_active(bNodeTree *ntree, int sub_activity)
inactivenode = node;
}
else if (node->type == NODE_GROUP) {
if (node->flag & NODE_ACTIVE) {
if (node->is_active()) {
activegroup = node;
}
else {