diff options
Diffstat (limited to 'source/blender/editors/space_node')
-rw-r--r-- | source/blender/editors/space_node/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/add_menu_assets.cc | 314 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_add.cc | 143 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 3 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.cc | 19 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.hh | 19 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.cc | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.cc | 5 | ||||
-rw-r--r-- | source/blender/editors/space_node/space_node.cc | 3 |
9 files changed, 479 insertions, 29 deletions
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index d7eccbf0b68..ff9e5352d0a 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC set(SRC add_node_search.cc + add_menu_assets.cc drawnode.cc link_drag_search.cc node_add.cc diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc new file mode 100644 index 00000000000..1ba1d67d854 --- /dev/null +++ b/source/blender/editors/space_node/add_menu_assets.cc @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_multi_value_map.hh" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "BKE_asset.h" +#include "BKE_asset_catalog.hh" +#include "BKE_asset_library.hh" +#include "BKE_idprop.h" +#include "BKE_screen.h" + +#include "BLT_translation.h" + +#include "RNA_access.h" +#include "RNA_prototypes.h" + +#include "ED_asset.h" +#include "ED_screen.h" + +#include "node_intern.hh" + +namespace blender::ed::space_node { + +static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/) +{ + return CTX_wm_space_node(C); +} + +static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params) +{ + const wmNotifier *wmn = params->notifier; + ARegion *region = params->region; + + switch (wmn->category) { + case NC_ASSET: + if (wmn->data == ND_ASSET_LIST_READING) { + ED_region_tag_refresh_ui(region); + } + break; + } +} + +struct LibraryAsset { + AssetLibraryReference library_ref; + AssetHandle handle; +}; + +struct LibraryCatalog { + bke::AssetLibrary *library; + const bke::AssetCatalog *catalog; +}; + +struct AssetItemTree { + bke::AssetCatalogTree catalogs; + MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path; + Map<const bke::AssetCatalogTreeItem *, bke::AssetCatalogPath> full_catalog_per_tree_item; +}; + +static bool all_loading_finished() +{ + for (const AssetLibraryReference &library : bke::all_valid_asset_library_refs()) { + if (!ED_assetlist_is_loaded(&library)) { + return false; + } + } + return true; +} + +static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node_tree) +{ + if (!node_tree) { + return {}; + } + const Main &bmain = *CTX_data_main(&C); + const Vector<AssetLibraryReference> all_libraries = bke::all_valid_asset_library_refs(); + + /* Merge catalogs from all libraries to deduplicate menu items. Also store the catalog and + * library for each asset ID in order to use them later when retrieving assets and removing + * empty catalogs. */ + Map<bke::CatalogID, LibraryCatalog> id_to_catalog_map; + bke::AssetCatalogTree catalogs_from_all_libraries; + for (const AssetLibraryReference &library_ref : all_libraries) { + if (bke::AssetLibrary *library = BKE_asset_library_load(&bmain, library_ref)) { + if (bke::AssetCatalogTree *tree = library->catalog_service->get_catalog_tree()) { + tree->foreach_item([&](bke::AssetCatalogTreeItem &item) { + const bke::CatalogID &id = item.get_catalog_id(); + bke::AssetCatalog *catalog = library->catalog_service->find_catalog(id); + catalogs_from_all_libraries.insert_item(*catalog); + id_to_catalog_map.add(item.get_catalog_id(), LibraryCatalog{library, catalog}); + }); + } + } + } + + /* Find all the matching node group assets for every catalog path. */ + MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path; + for (const AssetLibraryReference &library_ref : all_libraries) { + AssetFilterSettings type_filter{}; + type_filter.id_types = FILTER_ID_NT; + + ED_assetlist_storage_fetch(&library_ref, &C); + ED_assetlist_ensure_previews_job(&library_ref, &C); + ED_assetlist_iterate(library_ref, [&](AssetHandle asset) { + if (!ED_asset_filter_matches_asset(&type_filter, &asset)) { + return true; + } + const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset); + const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type"); + if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) { + return true; + } + if (BLI_uuid_is_nil(meta_data.catalog_id)) { + return true; + } + const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(meta_data.catalog_id); + assets_per_path.add(library_catalog.catalog->path, LibraryAsset{library_ref, asset}); + return true; + }); + } + + /* Build the final tree without any of the catalogs that don't have proper node group assets. */ + bke::AssetCatalogTree catalogs_with_node_assets; + catalogs_from_all_libraries.foreach_item([&](bke::AssetCatalogTreeItem &item) { + if (!assets_per_path.lookup(item.catalog_path()).is_empty()) { + const bke::CatalogID &id = item.get_catalog_id(); + const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(id); + bke::AssetCatalog *catalog = library_catalog.library->catalog_service->find_catalog(id); + catalogs_with_node_assets.insert_item(*catalog); + } + }); + + /* Build another map storing full asset paths for each tree item, in order to have stable + * pointers to asset catalog paths to use for context pointers. This is necessary because + * #bke::AssetCatalogTreeItem doesn't store its full path directly. */ + Map<const bke::AssetCatalogTreeItem *, bke::AssetCatalogPath> full_catalog_per_tree_item; + catalogs_with_node_assets.foreach_item([&](bke::AssetCatalogTreeItem &item) { + full_catalog_per_tree_item.add_new(&item, item.catalog_path()); + }); + + return {std::move(catalogs_with_node_assets), + std::move(assets_per_path), + std::move(full_catalog_per_tree_item)}; +} + +static void node_add_catalog_assets_draw(const bContext *C, Menu *menu) +{ + bScreen &screen = *CTX_wm_screen(C); + const SpaceNode &snode = *CTX_wm_space_node(C); + if (!snode.runtime->assets_for_menu) { + BLI_assert_unreachable(); + return; + } + AssetItemTree &tree = *snode.runtime->assets_for_menu; + const bNodeTree *edit_tree = snode.edittree; + if (!edit_tree) { + return; + } + + const PointerRNA menu_path_ptr = CTX_data_pointer_get(C, "asset_catalog_path"); + if (RNA_pointer_is_null(&menu_path_ptr)) { + return; + } + const bke::AssetCatalogPath &menu_path = *static_cast<const bke::AssetCatalogPath *>( + menu_path_ptr.data); + + const Span<LibraryAsset> asset_items = tree.assets_per_path.lookup(menu_path); + bke::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(menu_path); + BLI_assert(catalog_item != nullptr); + + if (asset_items.is_empty() && !catalog_item->has_children()) { + return; + } + + uiLayout *layout = menu->layout; + uiItemS(layout); + + for (const LibraryAsset &item : asset_items) { + uiLayout *col = uiLayoutColumn(layout, false); + PointerRNA file{ + &screen.id, &RNA_FileSelectEntry, const_cast<FileDirEntry *>(item.handle.file_data)}; + uiLayoutSetContextPointer(col, "active_file", &file); + + PointerRNA library_ptr{&screen.id, + &RNA_AssetLibraryReference, + const_cast<AssetLibraryReference *>(&item.library_ref)}; + uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr); + + uiItemO(col, ED_asset_handle_get_name(&item.handle), ICON_NONE, "NODE_OT_add_group_asset"); + } + + catalog_item->foreach_child([&](bke::AssetCatalogTreeItem &child_item) { + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&child_item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)}; + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE); + }); +} + +static void add_root_catalogs_draw(const bContext *C, Menu *menu) +{ + bScreen &screen = *CTX_wm_screen(C); + SpaceNode &snode = *CTX_wm_space_node(C); + const bNodeTree *edit_tree = snode.edittree; + uiLayout *layout = menu->layout; + + snode.runtime->assets_for_menu = std::make_shared<AssetItemTree>( + build_catalog_tree(*C, edit_tree)); + + const bool loading_finished = all_loading_finished(); + + AssetItemTree &tree = *snode.runtime->assets_for_menu; + if (tree.catalogs.is_empty() && loading_finished) { + return; + } + + uiItemS(layout); + + if (!loading_finished) { + uiItemL(layout, IFACE_("Loading Asset Libraries"), ICON_INFO); + } + + /* Avoid adding a separate root catalog when the assets have already been added to one of the + * builtin menus. + * TODO: The need to define the builtin menu labels here is completely non-ideal. We don't have + * any UI introspection that can do this though. This can be solved in the near future by + * removing the need to define the add menu completely, instead using a per-node-type path which + * can be merged with catalog tree. + */ + static Set<std::string> all_builtin_menus = []() { + Set<std::string> menus; + menus.add_new("Attribute"); + menus.add_new("Color"); + menus.add_new("Curve"); + menus.add_new("Curve Primitives"); + menus.add_new("Curve Topology"); + menus.add_new("Geometry"); + menus.add_new("Input"); + menus.add_new("Instances"); + menus.add_new("Material"); + menus.add_new("Mesh"); + menus.add_new("Mesh Primitives"); + menus.add_new("Mesh Topology"); + menus.add_new("Output"); + menus.add_new("Point"); + menus.add_new("Text"); + menus.add_new("Texture"); + menus.add_new("Utilities"); + menus.add_new("UV"); + menus.add_new("Vector"); + menus.add_new("Volume"); + menus.add_new("Group"); + menus.add_new("Layout"); + return menus; + }(); + + tree.catalogs.foreach_root_item([&](bke::AssetCatalogTreeItem &item) { + if (all_builtin_menus.contains(item.get_name())) { + return; + } + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)}; + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE); + }); +} + +MenuType add_catalog_assets_menu_type() +{ + MenuType type{}; + BLI_strncpy(type.idname, "NODE_MT_node_add_catalog_assets", sizeof(type.idname)); + type.poll = node_add_menu_poll; + type.draw = node_add_catalog_assets_draw; + type.listener = node_add_menu_assets_listen_fn; + return type; +} + +MenuType add_root_catalogs_menu_type() +{ + MenuType type{}; + BLI_strncpy(type.idname, "NODE_MT_node_add_root_catalogs", sizeof(type.idname)); + type.poll = node_add_menu_poll; + type.draw = add_root_catalogs_draw; + type.listener = node_add_menu_assets_listen_fn; + return type; +} + +} // namespace blender::ed::space_node + +/* Note: This is only necessary because Python can't set an asset catalog path context item. */ +void uiTemplateNodeAssetMenuItems(uiLayout *layout, bContext *C, const char *catalog_path) +{ + using namespace blender; + using namespace blender::ed::space_node; + bScreen &screen = *CTX_wm_screen(C); + SpaceNode &snode = *CTX_wm_space_node(C); + AssetItemTree &tree = *snode.runtime->assets_for_menu; + const bke::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path); + if (!item) { + return; + } + const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(item); + PointerRNA path_ptr{ + &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)}; + uiItemS(layout); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr); + uiItemMContents(col, "NODE_MT_node_add_catalog_assets"); +} diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 07eecff320a..41f70a6d8cf 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -30,6 +30,7 @@ #include "DEG_depsgraph_build.h" +#include "ED_asset.h" #include "ED_node.h" /* own include */ #include "ED_render.h" #include "ED_screen.h" @@ -244,38 +245,36 @@ void NODE_OT_add_reroute(wmOperatorType *ot) /** \name Add Node Group Operator * \{ */ -static bNodeTree *node_add_group_get_and_poll_group_node_tree(Main *bmain, - wmOperator *op, - bNodeTree *ntree) +static bool node_group_add_poll(const bNodeTree &node_tree, + const bNodeTree &node_group, + ReportList &reports) { - bNodeTree *node_group = reinterpret_cast<bNodeTree *>( - WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT)); - if (!node_group) { - return nullptr; + if (node_group.type != node_tree.type) { + return false; } const char *disabled_hint = nullptr; - if ((node_group->type != ntree->type) || !nodeGroupPoll(ntree, node_group, &disabled_hint)) { + if (!nodeGroupPoll(&node_tree, &node_group, &disabled_hint)) { if (disabled_hint) { - BKE_reportf(op->reports, + BKE_reportf(&reports, RPT_ERROR, "Can not add node group '%s' to '%s':\n %s", - node_group->id.name + 2, - ntree->id.name + 2, + node_group.id.name + 2, + node_tree.id.name + 2, disabled_hint); } else { - BKE_reportf(op->reports, + BKE_reportf(&reports, RPT_ERROR, "Can not add node group '%s' to '%s'", - node_group->id.name + 2, - ntree->id.name + 2); + node_group.id.name + 2, + node_tree.id.name + 2); } - return nullptr; + return false; } - return node_group; + return true; } static int node_add_group_exec(bContext *C, wmOperator *op) @@ -284,10 +283,14 @@ static int node_add_group_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNodeTree *node_group = node_add_group_get_and_poll_group_node_tree(bmain, op, ntree); + bNodeTree *node_group = reinterpret_cast<bNodeTree *>( + WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT)); if (!node_group) { return OPERATOR_CANCELLED; } + if (!node_group_add_poll(*ntree, *node_group, *op->reports)) { + return OPERATOR_CANCELLED; + } ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); @@ -320,9 +323,8 @@ static bool node_add_group_poll(bContext *C) } const SpaceNode *snode = CTX_wm_space_node(C); if (snode->edittree->type == NTREE_CUSTOM) { - CTX_wm_operator_poll_msg_set(C, - "This node editor displays a custom (Python defined) node tree. " - "Dropping node groups isn't supported for this"); + CTX_wm_operator_poll_msg_set( + C, "Adding node groups isn't supported for custom (Python defined) node trees"); return false; } return true; @@ -367,6 +369,105 @@ void NODE_OT_add_group(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Add Node Group Asset Operator + * \{ */ + +static bool add_node_group_asset(const bContext &C, + const AssetLibraryReference &library_ref, + const AssetHandle asset, + ReportList &reports) +{ + Main &bmain = *CTX_data_main(&C); + SpaceNode &snode = *CTX_wm_space_node(&C); + bNodeTree &edit_tree = *snode.edittree; + + bNodeTree *node_group = reinterpret_cast<bNodeTree *>( + asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset)); + if (!node_group) { + return false; + } + if (!node_group_add_poll(edit_tree, *node_group, reports)) { + /* Remove the node group if it was newly appended but can't be added to the tree. */ + id_us_plus(&node_group->id); + BKE_id_free_us(&bmain, node_group); + return false; + } + + ED_preview_kill_jobs(CTX_wm_manager(&C), CTX_data_main(&C)); + + bNode *group_node = add_node( + C, ntreeTypeFind(node_group->idname)->group_idname, snode.runtime->cursor); + if (!group_node) { + BKE_report(&reports, RPT_WARNING, "Could not add node group"); + return false; + } + /* By default, don't show the data-block selector since it's not usually necessary for assets. */ + group_node->flag &= ~NODE_OPTIONS; + + group_node->id = &node_group->id; + id_us_plus(group_node->id); + BKE_ntree_update_tag_node_property(&edit_tree, group_node); + + nodeSetActive(&edit_tree, group_node); + ED_node_tree_propagate_change(&C, &bmain, nullptr); + DEG_relations_tag_update(&bmain); + + return true; +} + +static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion ®ion = *CTX_wm_region(C); + SpaceNode &snode = *CTX_wm_space_node(C); + + const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C); + if (!library_ref) { + return OPERATOR_CANCELLED; + } + bool is_valid; + const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); + if (!is_valid) { + return OPERATOR_CANCELLED; + } + + /* Convert mouse coordinates to v2d space. */ + UI_view2d_region_to_view(®ion.v2d, + event->mval[0], + event->mval[1], + &snode.runtime->cursor[0], + &snode.runtime->cursor[1]); + + snode.runtime->cursor /= UI_DPI_FAC; + + if (!add_node_group_asset(*C, *library_ref, handle, *op->reports)) { + return OPERATOR_CANCELLED; + } + + wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach_remove_on_cancel", true); + BLI_assert(ot); + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); + WM_operator_properties_free(&ptr); + + return OPERATOR_FINISHED; +} + +void NODE_OT_add_group_asset(wmOperatorType *ot) +{ + ot->name = "Add Node Group Asset"; + ot->description = "Add a node group asset to the active node tree"; + ot->idname = "NODE_OT_add_group_asset"; + + ot->invoke = node_add_group_asset_invoke; + ot->poll = node_add_group_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Add Node Object Operator * \{ */ @@ -393,7 +494,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op) bNodeSocket *sock = nodeFindSocket(object_node, SOCK_IN, "Object"); if (!sock) { - BKE_report(op->reports, RPT_WARNING, "Could not find node object socket"); + BLI_assert_unreachable(); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index ee9ebd541a0..5ae6573df7c 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, ID_REAL_USERS(node.id)); + } UI_block_emboss_set(&block, UI_EMBOSS); } if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) { diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index b01be5ff234..48b3d711bdf 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -2299,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); } @@ -2420,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..88be9a52c61 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -38,6 +38,8 @@ extern const char *node_context_dir[]; namespace blender::ed::space_node { +struct AssetItemTree; + /** Temporary data used in node link drag modal operator. */ struct bNodeLinkDrag { /** Links dragged by the operator. */ @@ -96,6 +98,15 @@ struct SpaceNode_Runtime { /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ /** Temporary data for node insert offset (in UI called Auto-offset). */ struct NodeInsertOfsData *iofsd; + + /** + * Temporary data for node add menu in order to provide longer-term storage for context pointers. + * Recreated every time the root menu is opened. In the future this will be replaced with an "all + * libraries" cache in the asset system itself. + * + * Stored with a shared pointer so that it can be forward declared. + */ + std::shared_ptr<AssetItemTree> assets_for_menu; }; enum NodeResizeDirection { @@ -253,6 +264,7 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location); void NODE_OT_add_reroute(wmOperatorType *ot); void NODE_OT_add_search(wmOperatorType *ot); void NODE_OT_add_group(wmOperatorType *ot); +void NODE_OT_add_group_asset(wmOperatorType *ot); void NODE_OT_add_object(wmOperatorType *ot); void NODE_OT_add_collection(wmOperatorType *ot); void NODE_OT_add_file(wmOperatorType *ot); @@ -270,6 +282,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); @@ -381,4 +395,9 @@ void invoke_node_link_drag_add_menu(bContext &C, void invoke_add_node_search_menu(bContext &C, const float2 &cursor, bool use_transform); +/* add_menu_assets.cc */ + +MenuType add_catalog_assets_menu_type(); +MenuType add_root_catalogs_menu_type(); + } // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc index d45c33a3c59..104d1acf3b4 100644 --- a/source/blender/editors/space_node/node_ops.cc +++ b/source/blender/editors/space_node/node_ops.cc @@ -78,6 +78,7 @@ void node_operatortypes() WM_operatortype_append(NODE_OT_add_search); WM_operatortype_append(NODE_OT_add_group); + WM_operatortype_append(NODE_OT_add_group_asset); WM_operatortype_append(NODE_OT_add_object); WM_operatortype_append(NODE_OT_add_collection); WM_operatortype_append(NODE_OT_add_file); diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index f53eaf0f2bd..637c795d4d7 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -75,8 +75,6 @@ static void clear_picking_highlight(ListBase *links) } } -void update_multi_input_indices_for_removed_links(bNode &node); - /* -------------------------------------------------------------------- */ /** \name Add Node * \{ */ @@ -817,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) diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index ac49115959c..5754e77399f 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -1170,5 +1170,8 @@ void ED_spacetype_node() art->draw = node_toolbar_region_draw; BLI_addhead(&st->regiontypes, art); + WM_menutype_add(MEM_new<MenuType>(__func__, add_catalog_assets_menu_type())); + WM_menutype_add(MEM_new<MenuType>(__func__, add_root_catalogs_menu_type())); + BKE_spacetype_register(st); } |