Blender V4.3
interface_template_asset_view.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
10
11#include "DNA_space_types.h"
12#include "DNA_userdef_types.h"
13
14#include "BKE_screen.hh"
15
16#include "BLI_string.h"
17#include "BLI_string_ref.hh"
18
19#include "ED_asset.hh"
20#include "ED_screen.hh"
21
22#include "MEM_guardedalloc.h"
23
24#include "RNA_access.hh"
25#include "RNA_prototypes.hh"
26
27#include "UI_interface.hh"
28
29#include "WM_types.hh"
30
31#include "interface_intern.hh"
32
33using namespace blender;
34using namespace blender::ed;
35
42
43static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
44{
46 asset_handle);
47
49
50 ID *id = asset->local_id();
51 if (id != nullptr) {
52 UI_but_drag_set_id(but, id);
53 return;
54 }
55
56 const eAssetImportMethod import_method = asset->get_import_method().value_or(
58
59 ImBuf *imbuf = asset::list::asset_image_get(asset_handle);
61 but, asset, import_method, asset::handle_get_preview_icon_id(asset_handle), imbuf, 1.0f);
62}
63
64static void asset_view_draw_item(uiList *ui_list,
65 const bContext *C,
66 uiLayout *layout,
67 PointerRNA * /*dataptr*/,
68 PointerRNA * /*itemptr*/,
69 int /*icon*/,
70 PointerRNA * /*active_dataptr*/,
71 const char * /*active_propname*/,
72 int index,
73 int /*flt_flag*/)
74{
76
78 index);
79
80 PointerRNA file_ptr = RNA_pointer_create(&list_data->screen->id,
81 &RNA_FileSelectEntry,
82 const_cast<FileDirEntry *>(asset_handle.file_data));
83 uiLayoutSetContextPointer(layout, "active_file", &file_ptr);
84
86
87 uiBlock *block = uiLayoutGetBlock(layout);
88 const bool show_names = list_data->show_names;
89 const float size_x = UI_preview_tile_size_x();
90 const float size_y = show_names ? UI_preview_tile_size_y() : UI_preview_tile_size_y_no_label();
92 block,
94 0,
96 show_names ? asset::handle_get_representation(&asset_handle)->get_name().c_str() : "",
97 0,
98 0,
99 size_x,
100 size_y,
101 nullptr,
102 0,
103 0,
104 "");
105 ui_def_but_icon(but,
107 /* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
109 but->emboss = UI_EMBOSS_NONE;
110 if (!ui_list->dyn_data->custom_drag_optype) {
111 asset_view_item_but_drag_set(but, &asset_handle);
112 }
113}
114
115static void asset_view_filter_items(uiList *ui_list,
116 const bContext *C,
117 PointerRNA *dataptr,
118 const char *propname)
119{
120 AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
121 asset::AssetFilterSettings &filter_settings = list_data->filter_settings;
122
123 uiListNameFilter name_filter(*ui_list);
124
126 ui_list,
127 C,
128 [&name_filter, list_data, &filter_settings](
129 const PointerRNA &itemptr, blender::StringRefNull name, int index) {
131 list_data->asset_library_ref, index);
132
133 if (!asset::filter_matches_asset(&filter_settings, *asset)) {
135 }
136 return name_filter(itemptr, name, index);
137 },
138 dataptr,
139 propname,
140 [list_data](const PointerRNA & /*itemptr*/, int index) -> std::string {
142 list_data->asset_library_ref, index);
143
144 return asset->get_name();
145 });
146}
147
149{
150 const wmNotifier *notifier = params->notifier;
151
152 switch (notifier->category) {
153 case NC_ID: {
154 if (ELEM(notifier->action, NA_RENAME)) {
156 }
157 break;
158 }
159 }
160
161 if (asset::list::listen(params->notifier)) {
163 }
164}
165
167{
168 uiListType *list_type = (uiListType *)MEM_callocN(sizeof(*list_type), __func__);
169
170 STRNCPY(list_type->idname, "UI_UL_asset_view");
171 list_type->draw_item = asset_view_draw_item;
173 list_type->listener = asset_view_listener;
174
175 return list_type;
176}
177
178static void populate_asset_collection(const AssetLibraryReference &asset_library_ref,
179 PointerRNA &assets_dataptr,
180 const char *assets_propname)
181{
182 PropertyRNA *assets_prop = RNA_struct_find_property(&assets_dataptr, assets_propname);
183 if (!assets_prop) {
184 RNA_warning("Asset collection not found");
185 return;
186 }
187 if (RNA_property_type(assets_prop) != PROP_COLLECTION) {
188 RNA_warning("Expected a collection property");
189 return;
190 }
191 if (!RNA_struct_is_a(RNA_property_pointer_type(&assets_dataptr, assets_prop), &RNA_AssetHandle))
192 {
193 RNA_warning("Expected a collection property for AssetHandle items");
194 return;
195 }
196
197 RNA_property_collection_clear(&assets_dataptr, assets_prop);
198
199 asset::list::iterate(asset_library_ref, [&](AssetHandle /*asset*/) {
200 /* XXX creating a dummy #RNA_AssetHandle collection item. It's #file_data will be null. This is
201 * because the #FileDirEntry may be freed while iterating, there's a cache for them with a
202 * maximum size. Further code will query as needed it using the collection index. */
203
204 PointerRNA itemptr;
205 RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr);
206 PointerRNA fileptr = RNA_pointer_create(nullptr, &RNA_FileSelectEntry, nullptr);
207 RNA_pointer_set(&itemptr, "file_data", fileptr);
208
209 return true;
210 });
211}
212
214 const bContext *C,
215 const char *list_id,
216 PointerRNA *asset_library_dataptr,
217 const char *asset_library_propname,
218 PointerRNA *assets_dataptr,
219 const char *assets_propname,
220 PointerRNA *active_dataptr,
221 const char *active_propname,
222 const asset::AssetFilterSettings *filter_settings,
223 const int display_flags,
224 const char *activate_opname,
225 PointerRNA *r_activate_op_properties,
226 const char *drag_opname,
227 PointerRNA *r_drag_op_properties)
228{
229 if (!list_id || !list_id[0]) {
230 RNA_warning("Asset view needs a valid identifier");
231 return;
232 }
233
234 uiLayout *col = uiLayoutColumn(layout, false);
235
236 PropertyRNA *asset_library_prop = RNA_struct_find_property(asset_library_dataptr,
237 asset_library_propname);
239 RNA_property_enum_get(asset_library_dataptr, asset_library_prop));
240
241 uiLayout *row = uiLayoutRow(col, true);
242 if ((display_flags & UI_TEMPLATE_ASSET_DRAW_NO_LIBRARY) == 0) {
243 uiItemFullR(row,
244 asset_library_dataptr,
245 asset_library_prop,
247 0,
249 "",
250 ICON_NONE);
251 if (asset_library_ref.type != ASSET_LIBRARY_LOCAL) {
252 uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_library_refresh");
253 }
254 }
255
256 asset::list::storage_fetch(&asset_library_ref, C);
257 asset::list::previews_fetch(&asset_library_ref, C);
258 const int tot_items = asset::list::size(&asset_library_ref);
259
260 populate_asset_collection(asset_library_ref, *assets_dataptr, assets_propname);
261
262 AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
263 "AssetViewListData");
264 list_data->asset_library_ref = asset_library_ref;
265 list_data->filter_settings = *filter_settings;
266 list_data->screen = CTX_wm_screen(C);
267 list_data->show_names = (display_flags & UI_TEMPLATE_ASSET_DRAW_NO_NAMES) == 0;
268
269 uiTemplateListFlags template_list_flags = UI_TEMPLATE_LIST_NO_GRIP;
270 if ((display_flags & UI_TEMPLATE_ASSET_DRAW_NO_NAMES) != 0) {
271 template_list_flags |= UI_TEMPLATE_LIST_NO_NAMES;
272 }
273 if ((display_flags & UI_TEMPLATE_ASSET_DRAW_NO_FILTER) != 0) {
274 template_list_flags |= UI_TEMPLATE_LIST_NO_FILTER_OPTIONS;
275 }
276
277 uiLayout *subcol = uiLayoutColumn(col, false);
278
279 uiLayoutSetScaleX(subcol, 0.8f);
280 uiLayoutSetScaleY(subcol, 0.8f);
281
282 /* TODO can we have some kind of model-view API to handle referencing, filtering and lazy loading
283 * (of previews) of the items? */
284 uiList *list = uiTemplateList_ex(subcol,
285 C,
286 "UI_UL_asset_view",
287 list_id,
288 assets_dataptr,
289 assets_propname,
290 active_dataptr,
291 active_propname,
292 nullptr,
293 tot_items,
294 0,
296 0,
297 template_list_flags,
298 list_data);
299 if (!list) {
300 /* List creation failed. */
301 MEM_freeN(list_data);
302 return;
303 }
304
305 if (activate_opname) {
307 list, activate_opname, r_activate_op_properties != nullptr);
308 if (r_activate_op_properties && ptr) {
309 *r_activate_op_properties = *ptr;
310 }
311 }
312 if (drag_opname) {
314 list, drag_opname, r_drag_op_properties != nullptr);
315 if (r_drag_op_properties && ptr) {
316 *r_drag_op_properties = *ptr;
317 }
318 }
319}
Main runtime representation of an asset.
bScreen * CTX_wm_screen(const bContext *C)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
eAssetImportMethod
@ ASSET_IMPORT_APPEND_REUSE
@ ASSET_LIBRARY_LOCAL
@ UILST_LAYOUT_BIG_PREVIEW_GRID
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
Read Guarded memory(de)allocation.
#define RNA_warning(format,...)
@ PROP_COLLECTION
Definition RNA_types.hh:71
@ UI_LIST_ITEM_NEVER_SHOW
void UI_list_filter_and_sort_items(uiList *ui_list, const bContext *C, uiListItemFilterFn item_filter_fn, PointerRNA *dataptr, const char *propname, uiListItemGetNameFn get_name_fn=nullptr)
PointerRNA * UI_list_custom_drag_operator_set(uiList *ui_list, const char *opname, bool create_properties)
@ UI_EMBOSS_NONE
void uiLayoutSetScaleY(uiLayout *layout, float scale)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetScaleX(uiLayout *layout, float scale)
int UI_preview_tile_size_y(const int size_px=96)
void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, const char *name, int icon, const char *placeholder=nullptr)
uiBut * uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
#define UI_ITEM_NONE
void UI_but_dragflag_enable(uiBut *but, int flag)
@ UI_BUT_DRAG_FULL_BUT
uiList * uiTemplateList_ex(uiLayout *layout, const bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns, enum uiTemplateListFlags flags, void *customdata)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
int UI_preview_tile_size_x(const int size_px=96)
PointerRNA * UI_list_custom_activate_operator_set(uiList *ui_list, const char *opname, bool create_properties)
@ UI_BTYPE_PREVIEW_TILE
void UI_but_drag_set_id(uiBut *but, ID *id)
int UI_preview_tile_size_y_no_label(const int size_px=96)
@ UI_TEMPLATE_ASSET_DRAW_NO_NAMES
@ UI_TEMPLATE_ASSET_DRAW_NO_LIBRARY
@ UI_TEMPLATE_ASSET_DRAW_NO_FILTER
void UI_but_drag_set_asset(uiBut *but, const blender::asset_system::AssetRepresentation *asset, int import_method, int icon, const ImBuf *imb, float scale)
uiTemplateListFlags
@ UI_TEMPLATE_LIST_NO_NAMES
@ UI_TEMPLATE_LIST_NO_FILTER_OPTIONS
@ UI_TEMPLATE_LIST_NO_GRIP
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
@ UI_BUT_ICON_PREVIEW
#define NC_ID
Definition WM_types.hh:362
#define NA_RENAME
Definition WM_types.hh:554
std::optional< eAssetImportMethod > get_import_method() const
uint col
void ui_def_but_icon(uiBut *but, const int icon, const int flag)
#define RNA_NO_INDEX
@ UI_HAS_ICON
static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
static void asset_view_listener(uiList *, wmRegionListenerParams *params)
uiListType * UI_UL_asset_view()
static void asset_view_draw_item(uiList *ui_list, const bContext *C, uiLayout *layout, PointerRNA *, PointerRNA *, int, PointerRNA *, const char *, int index, int)
static void asset_view_filter_items(uiList *ui_list, const bContext *C, PointerRNA *dataptr, const char *propname)
static void populate_asset_collection(const AssetLibraryReference &asset_library_ref, PointerRNA &assets_dataptr, const char *assets_propname)
void uiTemplateAssetView(uiLayout *layout, const bContext *C, const char *list_id, PointerRNA *asset_library_dataptr, const char *asset_library_propname, PointerRNA *assets_dataptr, const char *assets_propname, PointerRNA *active_dataptr, const char *active_propname, const asset::AssetFilterSettings *filter_settings, const int display_flags, const char *activate_opname, PointerRNA *r_activate_op_properties, const char *drag_opname, PointerRNA *r_drag_op_properties)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void storage_fetch(const AssetLibraryReference *library_reference, const bContext *C)
void asset_preview_ensure_requested(const bContext &C, const AssetLibraryReference *library_reference, AssetHandle *asset_handle)
int size(const AssetLibraryReference *library_reference)
bool listen(const wmNotifier *notifier)
void iterate(const AssetLibraryReference &library_reference, AssetListHandleIterFn fn, FunctionRef< bool(asset_system::AssetRepresentation &)> prefilter_fn=nullptr)
asset_system::AssetRepresentation * asset_get_by_index(const AssetLibraryReference &library_reference, int asset_index)
AssetHandle asset_handle_get_by_index(const AssetLibraryReference *library_reference, int asset_index)
ImBuf * asset_image_get(const AssetHandle *asset_handle)
void previews_fetch(const AssetLibraryReference *library_reference, const bContext *C)
AssetLibraryReference library_reference_from_enum_value(int value)
asset_system::AssetRepresentation * handle_get_representation(const AssetHandle *asset)
bool filter_matches_asset(const AssetFilterSettings *filter, const blender::asset_system::AssetRepresentation &asset)
int handle_get_preview_icon_id(const AssetHandle *asset)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PropertyType RNA_property_type(PropertyRNA *prop)
void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const struct FileDirEntry * file_data
asset::AssetFilterSettings filter_settings
AssetLibraryReference asset_library_ref
Definition DNA_ID.h:413
eUIEmbossType emboss
struct wmOperatorType * custom_drag_optype
char idname[BKE_ST_MAXNAME]
uiListFilterItemsFunc filter_items
uiListDrawItemFunc draw_item
uiListListener listener
uiListDyn * dyn_data
unsigned int action
Definition WM_types.hh:325
unsigned int category
Definition WM_types.hh:325
PointerRNA * ptr
Definition wm_files.cc:4126