Blender V4.5
add_menu_assets.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "AS_asset_catalog.hh"
7#include "AS_asset_library.hh"
9
11#include "BLI_string.h"
12
13#include "DNA_space_types.h"
14
15#include "BKE_asset.hh"
16#include "BKE_idprop.hh"
17#include "BKE_screen.hh"
18
19#include "BLT_translation.hh"
20
21#include "RNA_access.hh"
22
23#include "ED_asset.hh"
25#include "ED_node.hh"
26
27#include "node_intern.hh"
28
30
31static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/)
32{
33 return CTX_wm_space_node(C);
34}
35
37{
39 return asset::list::is_loaded(&all_library_ref);
40}
41
43{
44 asset::AssetFilterSettings type_filter{};
45 type_filter.id_types = FILTER_ID_NT;
46 auto meta_data_filter = [&](const AssetMetaData &meta_data) {
47 const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
48 if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
49 return false;
50 }
51 return true;
52 };
55 return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
56}
57
66static Set<StringRef> get_builtin_menus(const int tree_type)
67{
68 Set<StringRef> menus;
69 switch (tree_type) {
70 case NTREE_GEOMETRY:
71 return {"Attribute",
72 "Input",
73 "Input/Constant",
74 "Input/Gizmo",
75 "Input/Group",
76 "Input/Import",
77 "Input/Scene",
78 "Output",
79 "Geometry",
80 "Geometry/Read",
81 "Geometry/Sample",
82 "Geometry/Write",
83 "Geometry/Operations",
84 "Curve",
85 "Curve/Read",
86 "Curve/Sample",
87 "Curve/Write",
88 "Curve/Operations",
89 "Curve/Primitives",
90 "Curve/Topology",
91 "Grease Pencil",
92 "Grease Pencil/Read",
93 "Grease Pencil/Operations",
94 "Grease Pencil/Write",
95 "Instances",
96 "Mesh",
97 "Mesh/Read",
98 "Mesh/Sample",
99 "Mesh/Write",
100 "Mesh/Operations",
101 "Mesh/Primitives",
102 "Mesh/Topology",
103 "Mesh/UV",
104 "Point",
105 "Volume",
106 "Volume/Operations",
107 "Volume/Primitives",
108 "Simulation",
109 "Material",
110 "Texture",
111 "Utilities",
112 "Utilities/Color",
113 "Utilities/Text",
114 "Utilities/Vector",
115 "Utilities/Field",
116 "Utilities/Math",
117 "Utilities/Matrix",
118 "Utilities/Rotation",
119 "Utilities/Deprecated",
120 "Group",
121 "Layout"};
122 case NTREE_COMPOSIT:
123 return {"Input",
124 "Input/Constant",
125 "Input/Scene",
126 "Output",
127 "Color",
128 "Color/Adjust",
129 "Color/Mix",
130 "Filter",
131 "Filter/Blur",
132 "Keying",
133 "Mask",
134 "Tracking",
135 "Transform",
136 "Texture",
137 "Utilities",
138 "Vector",
139 "Group",
140 "Layout"};
141 case NTREE_SHADER:
142 return {"Input",
143 "Output",
144 "Color",
145 "Converter",
146 "Shader",
147 "Texture",
148 "Vector",
149 "Script",
150 "Group",
151 "Layout"};
152 }
153 return {};
154}
155
156static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
157{
158 SpaceNode &snode = *CTX_wm_space_node(C);
159 const bNodeTree *edit_tree = snode.edittree;
160 if (!edit_tree) {
161 return;
162 }
163 if (!snode.runtime->assets_for_menu) {
164 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
165 build_catalog_tree(*C, *edit_tree));
166 return;
167 }
169
170 const std::optional<blender::StringRefNull> menu_path = CTX_data_string_get(
171 C, "asset_catalog_path");
172 if (!menu_path) {
173 return;
174 }
175 const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(
176 menu_path->c_str());
177 const asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(
178 menu_path->c_str());
179 BLI_assert(catalog_item != nullptr);
180
181 if (assets.is_empty() && !catalog_item->has_children()) {
182 return;
183 }
184
185 uiLayout *layout = menu->layout;
186 bool add_separator = true;
187
188 for (const asset_system::AssetRepresentation *asset : assets) {
189 if (add_separator) {
190 layout->separator();
191 add_separator = false;
192 }
193 PointerRNA op_ptr = layout->op("NODE_OT_add_group_asset",
194 IFACE_(asset->get_name()),
195 ICON_NONE,
199 }
200
201 const Set<StringRef> all_builtin_menus = get_builtin_menus(edit_tree->type);
202
203 catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
204 if (all_builtin_menus.contains_as(item.catalog_path().str())) {
205 return;
206 }
207 if (add_separator) {
208 layout->separator();
209 add_separator = false;
210 }
211 asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
212 });
213}
214
216{
217 SpaceNode &snode = *CTX_wm_space_node(C);
218 const bNodeTree *edit_tree = snode.edittree;
219 if (!edit_tree) {
220 return;
221 }
222 if (!snode.runtime->assets_for_menu) {
223 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
224 build_catalog_tree(*C, *edit_tree));
225 return;
226 }
228 for (const asset_system::AssetRepresentation *asset : tree.unassigned_assets) {
229 PointerRNA op_ptr = menu->layout->op("NODE_OT_add_group_asset",
230 IFACE_(asset->get_name()),
231 ICON_NONE,
235 }
236}
237
238static void add_root_catalogs_draw(const bContext *C, Menu *menu)
239{
240 SpaceNode &snode = *CTX_wm_space_node(C);
241 uiLayout *layout = menu->layout;
242 const bNodeTree *edit_tree = snode.edittree;
243 if (!edit_tree) {
244 return;
245 }
246
247 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
248 build_catalog_tree(*C, *edit_tree));
249
250 const bool loading_finished = all_loading_finished();
251
253 if (tree.catalogs.is_empty() && loading_finished && tree.unassigned_assets.is_empty()) {
254 return;
255 }
256
257 layout->separator();
258
259 if (!loading_finished) {
260 layout->label(IFACE_("Loading Asset Libraries"), ICON_INFO);
261 }
262
263 const Set<StringRef> all_builtin_menus = get_builtin_menus(edit_tree->type);
264
265 tree.catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
266 if (!all_builtin_menus.contains_as(item.catalog_path().str())) {
267 asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
268 }
269 });
270
271 if (!tree.unassigned_assets.is_empty()) {
272 layout->separator();
273 layout->menu("NODE_MT_node_add_unassigned_assets", IFACE_("Unassigned"), ICON_FILE_HIDDEN);
274 }
275}
276
278{
279 MenuType type{};
280 STRNCPY(type.idname, "NODE_MT_node_add_catalog_assets");
285 return type;
286}
287
289{
290 MenuType type{};
291 STRNCPY(type.idname, "NODE_MT_node_add_unassigned_assets");
296 type.description = N_(
297 "Node group assets not assigned to a catalog.\n"
298 "Catalogs can be assigned in the Asset Browser");
299 return type;
300}
301
303{
304 MenuType type{};
305 STRNCPY(type.idname, "NODE_MT_node_add_root_catalogs");
309 return type;
310}
311
313 const bContext &C,
314 const StringRef catalog_path)
315{
316 SpaceNode &snode = *CTX_wm_space_node(&C);
317 if (snode.runtime->assets_for_menu == nullptr) {
318 return;
319 }
321 const asset_system::AssetCatalogTreeItem *item = tree.catalogs.find_item(catalog_path);
322 if (!item) {
323 return;
324 }
325 uiLayout *col = &layout.column(false);
326 uiLayoutSetContextString(col, "asset_catalog_path", item->catalog_path().str());
327 uiItemMContents(col, "NODE_MT_node_add_catalog_assets");
328}
329
330} // namespace blender::ed::space_node
Main runtime representation of an asset.
IDProperty * BKE_asset_metadata_idprop_find(const AssetMetaData *asset_data, const char *name) ATTR_WARN_UNUSED_RESULT
Definition asset.cc:179
SpaceNode * CTX_wm_space_node(const bContext *C)
std::optional< blender::StringRefNull > CTX_data_string_get(const bContext *C, const char *member)
#define IDP_Int(prop)
#define BLI_assert(a)
Definition BLI_assert.h:46
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define IFACE_(msgid)
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
#define C
Definition RandGen.cpp:29
void uiLayoutSetContextString(uiLayout *layout, blender::StringRef name, blender::StringRef value)
#define UI_ITEM_NONE
void uiItemMContents(uiLayout *layout, blender::StringRef menuname)
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:239
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:314
constexpr bool is_empty() const
Definition BLI_span.hh:260
void foreach_child(ItemIterFn callback) const
KDTree_3d * tree
uint col
#define FILTER_ID_NT
AssetLibraryReference all_library_reference()
void all_library_reload_catalogs_if_dirty()
bool is_loaded(const AssetLibraryReference *library_reference)
void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
AssetItemTree build_filtered_all_catalog_tree(const AssetLibraryReference &library_ref, const bContext &C, const AssetFilterSettings &filter_settings, FunctionRef< bool(const AssetMetaData &)> meta_data_filter={})
void draw_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item, const StringRefNull menu_name, uiLayout &layout)
void operator_asset_reference_props_set(const asset_system::AssetRepresentation &asset, PointerRNA &ptr)
static bool all_loading_finished()
static Set< StringRef > get_builtin_menus(const int tree_type)
MenuType add_catalog_assets_menu_type()
MenuType add_unassigned_assets_menu_type()
static void node_add_unassigned_assets_draw(const bContext *C, Menu *menu)
void ui_template_node_asset_menu_items(uiLayout &layout, const bContext &C, StringRef catalog_path)
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
static asset::AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree &node_tree)
static void add_root_catalogs_draw(const bContext *C, Menu *menu)
static bool node_add_menu_poll(const bContext *C, MenuType *)
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
MenuTypeFlag flag
const char * description
bool(* poll)(const bContext *C, MenuType *mt)
char idname[BKE_ST_MAXNAME]
void(* draw)(const bContext *C, Menu *menu)
void(* listener)(const wmRegionListenerParams *params)
uiLayout * layout
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
std::shared_ptr< asset::AssetItemTree > assets_for_menu
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void menu(MenuType *mt, std::optional< blender::StringRef > name, int icon)
#define N_(msgid)