Blender V4.3
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/Group",
75 "Input/Scene",
76 "Output",
77 "Geometry",
78 "Geometry/Read",
79 "Geometry/Sample",
80 "Geometry/Write",
81 "Geometry/Operations",
82 "Curve",
83 "Curve/Read",
84 "Curve/Sample",
85 "Curve/Write",
86 "Curve/Operations",
87 "Curve/Primitives",
88 "Curve/Topology",
89 "Instances",
90 "Mesh",
91 "Mesh/Read",
92 "Mesh/Sample",
93 "Mesh/Write",
94 "Mesh/Operations",
95 "Mesh/Primitives",
96 "Mesh/Topology",
97 "Mesh/UV",
98 "Point",
99 "Volume",
100 "Volume/Operations",
101 "Volume/Primitives",
102 "Simulation",
103 "Material",
104 "Texture",
105 "Utilities",
106 "Utilities/Color",
107 "Utilities/Text",
108 "Utilities/Vector",
109 "Utilities/Field",
110 "Utilities/Math",
111 "Utilities/Matrix",
112 "Utilities/Rotation",
113 "Utilities/Deprecated",
114 "Group",
115 "Layout",
116 "Unassigned"};
117 case NTREE_COMPOSIT:
118 return {"Input",
119 "Input/Constant",
120 "Input/Scene",
121 "Output",
122 "Color",
123 "Color/Adjust",
124 "Color/Mix",
125 "Filter",
126 "Filter/Blur",
127 "Keying",
128 "Mask",
129 "Tracking",
130 "Transform",
131 "Utilities",
132 "Vector",
133 "Group",
134 "Layout"};
135 case NTREE_SHADER:
136 return {"Input",
137 "Output",
138 "Color",
139 "Converter",
140 "Shader",
141 "Texture",
142 "Vector",
143 "Script",
144 "Group",
145 "Layout"};
146 }
147 return {};
148}
149
150static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
151{
152 SpaceNode &snode = *CTX_wm_space_node(C);
153 const bNodeTree *edit_tree = snode.edittree;
154 if (!edit_tree) {
155 return;
156 }
157 if (!snode.runtime->assets_for_menu) {
158 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
159 build_catalog_tree(*C, *edit_tree));
160 return;
161 }
163
164 const std::optional<blender::StringRefNull> menu_path = CTX_data_string_get(
165 C, "asset_catalog_path");
166 if (!menu_path) {
167 return;
168 }
169 const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(
170 menu_path->c_str());
171 const asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(
172 menu_path->c_str());
173 BLI_assert(catalog_item != nullptr);
174
175 if (assets.is_empty() && !catalog_item->has_children()) {
176 return;
177 }
178
179 uiLayout *layout = menu->layout;
180 bool add_separator = true;
181
182 for (const asset_system::AssetRepresentation *asset : assets) {
183 if (add_separator) {
184 uiItemS(layout);
185 add_separator = false;
186 }
187 PointerRNA op_ptr;
188 uiItemFullO(layout,
189 "NODE_OT_add_group_asset",
190 IFACE_(asset->get_name().c_str()),
191 ICON_NONE,
192 nullptr,
195 &op_ptr);
197 }
198
199 const Set<StringRef> all_builtin_menus = get_builtin_menus(edit_tree->type);
200
201 catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
202 if (all_builtin_menus.contains_as(item.catalog_path().str())) {
203 return;
204 }
205 if (add_separator) {
206 uiItemS(layout);
207 add_separator = false;
208 }
209 asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
210 });
211}
212
214{
215 SpaceNode &snode = *CTX_wm_space_node(C);
216 const bNodeTree *edit_tree = snode.edittree;
217 if (!edit_tree) {
218 return;
219 }
220 if (!snode.runtime->assets_for_menu) {
221 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
222 build_catalog_tree(*C, *edit_tree));
223 return;
224 }
226 for (const asset_system::AssetRepresentation *asset : tree.unassigned_assets) {
227 PointerRNA op_ptr;
228 uiItemFullO(menu->layout,
229 "NODE_OT_add_group_asset",
230 IFACE_(asset->get_name().c_str()),
231 ICON_NONE,
232 nullptr,
235 &op_ptr);
237 }
238}
239
240static void add_root_catalogs_draw(const bContext *C, Menu *menu)
241{
242 SpaceNode &snode = *CTX_wm_space_node(C);
243 uiLayout *layout = menu->layout;
244 const bNodeTree *edit_tree = snode.edittree;
245 if (!edit_tree) {
246 return;
247 }
248
249 snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
250 build_catalog_tree(*C, *edit_tree));
251
252 const bool loading_finished = all_loading_finished();
253
255 if (tree.catalogs.is_empty() && loading_finished) {
256 return;
257 }
258
259 uiItemS(layout);
260
261 if (!loading_finished) {
262 uiItemL(layout, IFACE_("Loading Asset Libraries"), ICON_INFO);
263 }
264
265 const Set<StringRef> all_builtin_menus = get_builtin_menus(edit_tree->type);
266
267 tree.catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
268 if (!all_builtin_menus.contains_as(item.catalog_path().str())) {
269 asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
270 }
271 });
272
273 if (!tree.unassigned_assets.is_empty()) {
274 uiItemS(layout);
275 uiItemM(layout, "NODE_MT_node_add_unassigned_assets", IFACE_("Unassigned"), ICON_FILE_HIDDEN);
276 }
277}
278
280{
281 MenuType type{};
282 STRNCPY(type.idname, "NODE_MT_node_add_catalog_assets");
283 type.poll = node_add_menu_poll;
287 return type;
288}
289
291{
292 MenuType type{};
293 STRNCPY(type.idname, "NODE_MT_node_add_unassigned_assets");
294 type.poll = node_add_menu_poll;
298 type.description = N_(
299 "Node group assets not assigned to a catalog.\n"
300 "Catalogs can be assigned in the Asset Browser");
301 return type;
302}
303
305{
306 MenuType type{};
307 STRNCPY(type.idname, "NODE_MT_node_add_root_catalogs");
308 type.poll = node_add_menu_poll;
309 type.draw = add_root_catalogs_draw;
311 return type;
312}
313
315 const bContext &C,
316 const StringRef catalog_path)
317{
318 SpaceNode &snode = *CTX_wm_space_node(&C);
319 if (snode.runtime->assets_for_menu == nullptr) {
320 return;
321 }
323 const asset_system::AssetCatalogTreeItem *item = tree.catalogs.find_item(catalog_path);
324 if (!item) {
325 return;
326 }
327 uiLayout *col = uiLayoutColumn(&layout, false);
328 uiLayoutSetContextString(col, "asset_catalog_path", item->catalog_path().str());
329 uiItemMContents(col, "NODE_MT_node_add_catalog_assets");
330}
331
332} // 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:186
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:50
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define IFACE_(msgid)
#define FILTER_ID_NT
Definition DNA_ID.h:1180
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiItemFullO(uiLayout *layout, const char *opname, const char *name, int icon, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, PointerRNA *r_opptr)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
void uiItemMContents(uiLayout *layout, const char *menuname)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetContextString(uiLayout *layout, const char *name, blender::StringRef value)
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:219
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:295
constexpr bool is_empty() const
Definition BLI_span.hh:261
void foreach_child(ItemIterFn callback) const
KDTree_3d * tree
uint col
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),...
char type
Definition DNA_ID.h:154
uiLayout * layout
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
std::shared_ptr< asset::AssetItemTree > assets_for_menu
#define N_(msgid)