diff options
Diffstat (limited to 'source/blender/editors/space_node')
-rw-r--r-- | source/blender/editors/space_node/add_node_search.cc | 3 | ||||
-rw-r--r-- | source/blender/editors/space_node/link_drag_search.cc | 4 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 5 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.cc | 43 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.hh | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.cc | 12 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.cc | 332 |
7 files changed, 205 insertions, 196 deletions
diff --git a/source/blender/editors/space_node/add_node_search.cc b/source/blender/editors/space_node/add_node_search.cc index 819f0abac7c..28e18c20f46 100644 --- a/source/blender/editors/space_node/add_node_search.cc +++ b/source/blender/editors/space_node/add_node_search.cc @@ -182,6 +182,9 @@ static void gather_add_node_operations(const bContext &C, /* Skip the empty group type. */ continue; } + if (StringRefNull(node_type->ui_name).endswith("(Legacy)")) { + continue; + } AddNodeItem item{}; item.ui_name = IFACE_(node_type->ui_name); diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index 17410937d4c..ffa2d377056 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -274,7 +274,9 @@ static void gather_socket_link_operations(const bContext &C, if (!(node_type->poll && node_type->poll(node_type, &node_tree, &disabled_hint))) { continue; } - + if (StringRefNull(node_type->ui_name).endswith("(Legacy)")) { + continue; + } if (node_type->gather_link_search_ops) { nodes::GatherLinkSearchOpParams params{*node_type, node_tree, socket, search_link_ops}; node_type->gather_link_search_ops(params); diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index dc155f5e28d..98b2cacd162 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C, 0, ""); UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit"); + if (node.id) { + UI_but_icon_indicator_number_set(but, node.id->us); + } UI_block_emboss_set(&block, UI_EMBOSS); } if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) { @@ -3011,7 +3014,7 @@ static void node_draw_nodetree(const bContext &C, } } -/* Draw the breadcrumb on the bottom of the editor. */ +/* Draw the breadcrumb on the top of the editor. */ static void draw_tree_path(const bContext &C, ARegion ®ion) { using namespace blender; diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 3a80733f06c..48b3d711bdf 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -1361,12 +1361,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs"); + bool linked = RNA_boolean_get(op->ptr, "linked") || ((U.dupflag & USER_DUP_NTREE) == 0); + const bool dupli_node_tree = !linked; bool changed = false; ED_preview_kill_jobs(CTX_wm_manager(C), bmain); Map<const bNode *, bNode *> node_map; Map<const bNodeSocket *, bNodeSocket *> socket_map; + Map<const ID *, ID *> duplicated_node_groups; bNode *lastnode = (bNode *)ntree->nodes.last; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { @@ -1374,6 +1377,18 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) bNode *new_node = bke::node_copy_with_mapping( ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map); node_map.add_new(node, new_node); + + if (node->id && dupli_node_tree) { + ID *new_group = duplicated_node_groups.lookup_or_add_cb(node->id, [&]() { + ID *new_group = BKE_id_copy(bmain, node->id); + /* Remove user added by copying. */ + id_us_min(new_group); + return new_group; + }); + id_us_plus(new_group); + id_us_min(new_node->id); + new_node->id = new_group; + } changed = true; } @@ -1462,6 +1477,8 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) void NODE_OT_duplicate(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Duplicate Nodes"; ot->description = "Duplicate selected nodes"; @@ -1476,6 +1493,13 @@ void NODE_OT_duplicate(wmOperatorType *ot) RNA_def_boolean( ot->srna, "keep_inputs", false, "Keep Inputs", "Keep the input links to duplicated nodes"); + + prop = RNA_def_boolean(ot->srna, + "linked", + true, + "Linked", + "Duplicate node but not node trees, linking to the original data"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* XXX: some code needing updating to operators. */ @@ -2275,6 +2299,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator * /*op*/) newlink->tosock = socket_map.lookup(link->tosock); newlink->fromnode = node_map.lookup(link->fromnode); newlink->fromsock = socket_map.lookup(link->fromsock); + newlink->multi_input_socket_index = link->multi_input_socket_index; BKE_node_clipboard_add_link(newlink); } @@ -2396,11 +2421,19 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) } LISTBASE_FOREACH (bNodeLink *, link, clipboard_links_lb) { - nodeAddLink(ntree, - node_map.lookup(link->fromnode), - socket_map.lookup(link->fromsock), - node_map.lookup(link->tonode), - socket_map.lookup(link->tosock)); + bNodeLink *new_link = nodeAddLink(ntree, + node_map.lookup(link->fromnode), + socket_map.lookup(link->fromsock), + node_map.lookup(link->tonode), + socket_map.lookup(link->tosock)); + new_link->multi_input_socket_index = link->multi_input_socket_index; + } + + ntree->ensure_topology_cache(); + + for (bNode *new_node : node_map.values()) { + /* Update multi input socket indices in case all connected nodes weren't copied. */ + update_multi_input_indices_for_removed_links(*new_node); } Main *bmain = CTX_data_main(C); diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 50c03489027..1c3026628a6 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -270,6 +270,8 @@ void NODE_OT_group_edit(wmOperatorType *ot); /* node_relationships.cc */ +void update_multi_input_indices_for_removed_links(bNode &node); + void NODE_OT_link(wmOperatorType *ot); void NODE_OT_link_make(wmOperatorType *ot); void NODE_OT_links_cut(wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc index 6c52dae5b86..d45c33a3c59 100644 --- a/source/blender/editors/space_node/node_ops.cc +++ b/source/blender/editors/space_node/node_ops.cc @@ -174,7 +174,17 @@ void ED_operatormacros_node() "Duplicate", "Duplicate selected nodes and move them", OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); + mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); + RNA_boolean_set(mot->ptr, "linked", false); + WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); + + ot = WM_operatortype_append_macro( + "NODE_OT_duplicate_move_linked", + "Duplicate Linked", + "Duplicate selected nodes, but not their node trees, and move them", + OPTYPE_UNDO | OPTYPE_REGISTER); + mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); + RNA_boolean_set(mot->ptr, "linked", true); WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); /* modified operator call for duplicating with input links */ diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 7cf18e2f828..637c795d4d7 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -64,6 +64,10 @@ struct NodeInsertOfsData { float offset_x; /* offset to apply to node chain */ }; +namespace blender::ed::space_node { + +bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out); + static void clear_picking_highlight(ListBase *links) { LISTBASE_FOREACH (bNodeLink *, link, links) { @@ -71,10 +75,6 @@ static void clear_picking_highlight(ListBase *links) } } -namespace blender::ed::space_node { - -void update_multi_input_indices_for_removed_links(bNode &node); - /* -------------------------------------------------------------------- */ /** \name Add Node * \{ */ @@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/, nldrag->cursor[0]; const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC; - UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false); + UI_icon_draw_ex( + x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } static void draw_draglink_tooltip_activate(const ARegion ®ion, bNodeLinkDrag &nldrag) @@ -1750,29 +1751,31 @@ 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->parent == nullptr) { - /* disallow moving a parent into its child */ - if (nodeAttachNodeCheck(frame, node) == false) { - /* attach all unparented nodes */ - nodeAttachNode(node, frame); - } + if (!(node->flag & NODE_SELECT)) { + continue; + } + + if (node->parent == nullptr) { + /* disallow moving a parent into its child */ + if (nodeAttachNodeCheck(frame, node) == false) { + /* attach all unparented nodes */ + nodeAttachNode(node, frame); } - else { - /* attach nodes which share parent with the frame */ - bNode *parent; - for (parent = frame->parent; parent; parent = parent->parent) { - if (parent == node->parent) { - break; - } + } + else { + /* attach nodes which share parent with the frame */ + bNode *parent; + for (parent = frame->parent; parent; parent = parent->parent) { + if (parent == node->parent) { + break; } + } - if (parent) { - /* disallow moving a parent into its child */ - if (nodeAttachNodeCheck(frame, node) == false) { - nodeDetachNode(node); - nodeAttachNode(node, frame); - } + if (parent) { + /* disallow moving a parent into its child */ + if (nodeAttachNodeCheck(frame, node) == false) { + nodeDetachNode(node); + nodeAttachNode(node, frame); } } } @@ -1881,100 +1884,55 @@ void NODE_OT_detach(wmOperatorType *ot) /** \name Automatic Node Insert on Dragging * \{ */ -/* prevent duplicate testing code below */ -static bool ed_node_link_conditions(ScrArea *area, - bool test, - SpaceNode **r_snode, - bNode **r_select) +static bNode *get_selected_node_for_insertion(bNodeTree &node_tree) { - SpaceNode *snode = area ? (SpaceNode *)area->spacedata.first : nullptr; - - *r_snode = snode; - *r_select = nullptr; - - /* no unlucky accidents */ - if (area == nullptr || area->spacetype != SPACE_NODE) { - return false; - } - - if (!test) { - /* no need to look for a node */ - return true; - } - - bNode *node; - bNode *select = nullptr; - for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { + bNode *selected_node = nullptr; + int selected_node_count = 0; + for (bNode *node : node_tree.all_nodes()) { if (node->flag & SELECT) { - if (select) { - break; - } - select = node; + selected_node = node; + selected_node_count++; + } + if (selected_node_count > 1) { + return nullptr; } } - /* only one selected */ - if (node || select == nullptr) { - return false; + if (!selected_node) { + return nullptr; } - - /* correct node */ - if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) { - return false; + if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) { + return nullptr; } - - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); - - /* test node for links */ - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (node_link_is_hidden_or_dimmed(region->v2d, *link)) { - continue; - } - - if (link->tonode == select || link->fromnode == select) { - return false; - } + if (std::any_of(selected_node->input_sockets().begin(), + selected_node->input_sockets().end(), + [&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) { + return nullptr; } - - *r_select = select; - return true; + if (std::any_of(selected_node->output_sockets().begin(), + selected_node->output_sockets().end(), + [&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) { + return nullptr; + }; + return selected_node; } -/** \} */ - -} // namespace blender::ed::space_node - -/* -------------------------------------------------------------------- */ -/** \name Node Line Intersection Test - * \{ */ - -void ED_node_link_intersect_test(ScrArea *area, int test) +void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion) { - using namespace blender; - using namespace blender::ed::space_node; - - bNode *select; - SpaceNode *snode; - if (!ed_node_link_conditions(area, test, &snode, &select)) { - return; - } + bNodeTree &node_tree = *snode.edittree; + node_tree.ensure_topology_cache(); - /* clear flags */ - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - link->flag &= ~NODE_LINKFLAG_HILITE; - } + node_insert_on_link_flags_clear(node_tree); - if (test == 0) { + bNode *node_to_insert = get_selected_node_for_insertion(node_tree); + if (!node_to_insert) { return; } - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); - /* find link to select/highlight */ bNodeLink *selink = nullptr; float dist_best = FLT_MAX; - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - - if (node_link_is_hidden_or_dimmed(region->v2d, *link)) { + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } @@ -1986,10 +1944,10 @@ void ED_node_link_intersect_test(ScrArea *area, int test) * upper left node edge of a intersected line segment */ for (int i = 0; i < NODE_LINK_RESOL; i++) { /* Check if the node rectangle intersects the line from this point to next one. */ - if (BLI_rctf_isect_segment(&select->totr, coords[i], coords[i + 1])) { + if (BLI_rctf_isect_segment(&node_to_insert->totr, coords[i], coords[i + 1])) { /* store the shortest distance to the upper left edge * of all intersections found so far */ - const float node_xy[] = {select->totr.xmin, select->totr.ymax}; + const float node_xy[] = {node_to_insert->totr.xmin, node_to_insert->totr.ymax}; /* to be precise coords should be clipped by select->totr, * but not done since there's no real noticeable difference */ @@ -2009,9 +1967,89 @@ void ED_node_link_intersect_test(ScrArea *area, int test) } } -/** \} */ +void node_insert_on_link_flags_clear(bNodeTree &node_tree) +{ + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + link->flag &= ~NODE_LINKFLAG_HILITE; + } +} -namespace blender::ed::space_node { +void node_insert_on_link_flags(Main &bmain, SpaceNode &snode) +{ + bNodeTree &node_tree = *snode.edittree; + node_tree.ensure_topology_cache(); + bNode *node_to_insert = get_selected_node_for_insertion(node_tree); + if (!node_to_insert) { + return; + } + + /* Find link to insert on. */ + bNodeTree &ntree = *snode.edittree; + bNodeLink *old_link = nullptr; + LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { + if (link->flag & NODE_LINKFLAG_HILITE) { + old_link = link; + break; + } + } + if (old_link == nullptr) { + return; + } + + old_link->flag &= ~NODE_LINKFLAG_HILITE; + + bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN); + bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT); + + if (node_to_insert->type != NODE_REROUTE) { + /* Ignore main sockets when the types don't match. */ + if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), + static_cast<eNodeSocketDatatype>(best_input->type))) { + best_input = nullptr; + } + if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), + static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { + best_output = nullptr; + } + } + + bNode *from_node = old_link->fromnode; + bNodeSocket *from_socket = old_link->fromsock; + bNode *to_node = old_link->tonode; + + if (best_output != nullptr) { + /* Relink the "start" of the existing link to the newly inserted node. */ + old_link->fromnode = node_to_insert; + old_link->fromsock = best_output; + BKE_ntree_update_tag_link_changed(&ntree); + } + else { + nodeRemLink(&ntree, old_link); + } + + if (best_input != nullptr) { + /* Add a new link that connects the node on the left to the newly inserted node. */ + nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input); + } + + /* Set up insert offset data, it needs stuff from here. */ + if ((snode.flag & SNODE_SKIP_INSOFFSET) == 0) { + BLI_assert(snode.runtime->iofsd == nullptr); + NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__); + + iofsd->insert = node_to_insert; + iofsd->prev = from_node; + iofsd->next = to_node; + + snode.runtime->iofsd = iofsd; + } + + ED_node_tree_propagate_change(nullptr, &bmain, &ntree); +} + +/** \} */ /* -------------------------------------------------------------------- */ /** \name Node Insert Offset Operator @@ -2048,7 +2086,7 @@ static int get_main_socket_priority(const bNodeSocket *socket) } /** Get the "main" socket based on the node declaration or an heuristic. */ -static bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) +bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) { ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs; @@ -2426,85 +2464,3 @@ void NODE_OT_insert_offset(wmOperatorType *ot) /** \} */ } // namespace blender::ed::space_node - -/* -------------------------------------------------------------------- */ -/** \name Note Link Insert - * \{ */ - -void ED_node_link_insert(Main *bmain, ScrArea *area) -{ - using namespace blender::ed::space_node; - - bNode *node_to_insert; - SpaceNode *snode; - if (!ed_node_link_conditions(area, true, &snode, &node_to_insert)) { - return; - } - - /* Find link to insert on. */ - bNodeTree &ntree = *snode->edittree; - bNodeLink *old_link = nullptr; - LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (link->flag & NODE_LINKFLAG_HILITE) { - old_link = link; - break; - } - } - if (old_link == nullptr) { - return; - } - - old_link->flag &= ~NODE_LINKFLAG_HILITE; - - bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN); - bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT); - - if (node_to_insert->type != NODE_REROUTE) { - /* Ignore main sockets when the types don't match. */ - if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), - static_cast<eNodeSocketDatatype>(best_input->type))) { - best_input = nullptr; - } - if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), - static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { - best_output = nullptr; - } - } - - bNode *from_node = old_link->fromnode; - bNodeSocket *from_socket = old_link->fromsock; - bNode *to_node = old_link->tonode; - - if (best_output != nullptr) { - /* Relink the "start" of the existing link to the newly inserted node. */ - old_link->fromnode = node_to_insert; - old_link->fromsock = best_output; - BKE_ntree_update_tag_link_changed(&ntree); - } - else { - nodeRemLink(&ntree, old_link); - } - - if (best_input != nullptr) { - /* Add a new link that connects the node on the left to the newly inserted node. */ - nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input); - } - - /* Set up insert offset data, it needs stuff from here. */ - if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { - BLI_assert(snode->runtime->iofsd == nullptr); - NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__); - - iofsd->insert = node_to_insert; - iofsd->prev = from_node; - iofsd->next = to_node; - - snode->runtime->iofsd = iofsd; - } - - ED_node_tree_propagate_change(nullptr, bmain, snode->edittree); -} - -/** \} */ |