Blender V4.3
asset_shelf.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
11#include <algorithm>
12
14#include "AS_asset_library.hh"
15
16#include "BLI_function_ref.hh"
17#include "BLI_string.h"
18
19#include "BKE_context.hh"
20#include "BKE_main.hh"
21#include "BKE_screen.hh"
22
23#include "BLT_translation.hh"
24
25#include "DNA_screen_types.h"
26
27#include "ED_asset_list.hh"
28#include "ED_screen.hh"
29
30#include "RNA_access.hh"
31#include "RNA_prototypes.hh"
32
33#include "UI_interface.hh"
34#include "UI_resources.hh"
35#include "UI_tree_view.hh"
36#include "UI_view2d.hh"
37
38#include "WM_api.hh"
39#include "WM_message.hh"
40
41#include "ED_asset_shelf.hh"
42#include "asset_shelf.hh"
43
45
47
52
53/* -------------------------------------------------------------------- */
58{
60 return shelf_types;
61}
62
63void type_register(std::unique_ptr<AssetShelfType> type)
64{
66 shelf_types.append(std::move(type));
67}
68
69void type_unregister(const AssetShelfType &shelf_type)
70{
72 auto *const it = std::find_if(shelf_types.begin(),
73 shelf_types.end(),
74 [&](const std::unique_ptr<AssetShelfType> &iter_type) {
75 return iter_type.get() == &shelf_type;
76 });
77 BLI_assert(it != shelf_types.end());
78
79 shelf_types.remove(it - shelf_types.begin());
80}
81
82static bool type_poll_no_spacetype_check(const bContext &C, const AssetShelfType *shelf_type)
83{
84 if (!shelf_type) {
85 return false;
86 }
87
88#ifndef NDEBUG
90 BLI_assert_msg(std::find_if(shelf_types.begin(),
91 shelf_types.end(),
92 [&](const std::unique_ptr<AssetShelfType> &type) {
93 return type.get() == shelf_type;
94 }) != shelf_types.end(),
95 "Asset shelf type is not registered");
96#endif
97
98 return !shelf_type->poll || shelf_type->poll(&C, shelf_type);
99}
100
101bool type_poll_for_popup(const bContext &C, const AssetShelfType *shelf_type)
102{
103 return type_poll_no_spacetype_check(C, shelf_type);
104}
105
113 const AssetShelfType *shelf_type,
114 const int space_type)
115{
116 if (!shelf_type) {
117 return false;
118 }
119 if (shelf_type->space_type && (space_type != shelf_type->space_type)) {
120 return false;
121 }
122
123 return type_poll_no_spacetype_check(C, shelf_type);
124}
125
127{
128 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
129 if (idname == shelf_type->idname) {
130 return shelf_type.get();
131 }
132 }
133 return nullptr;
134}
135
137{
138 if (shelf.type) {
139 return shelf.type;
140 }
141
142 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
143 if (STREQ(shelf.idname, shelf_type->idname)) {
144 shelf.type = shelf_type.get();
145 return shelf_type.get();
146 }
147 }
148
149 return nullptr;
150}
151
153{
154 AssetShelf *shelf = MEM_new<AssetShelf>(__func__);
155 *shelf = dna::shallow_zero_initialize();
156 shelf->settings.preview_size = type.default_preview_size ? type.default_preview_size :
159 shelf->type = &type;
160 shelf->preferred_row_count = 1;
161 STRNCPY(shelf->idname, type.idname);
162 return shelf;
163}
164
167/* -------------------------------------------------------------------- */
176static void activate_shelf(RegionAssetShelf &shelf_regiondata, AssetShelf &shelf)
177{
178 shelf_regiondata.active_shelf = &shelf;
179 BLI_assert(BLI_findindex(&shelf_regiondata.shelves, &shelf) > -1);
180 BLI_remlink(&shelf_regiondata.shelves, &shelf);
181 BLI_addhead(&shelf_regiondata.shelves, &shelf);
182}
183
206 const eSpace_Type space_type,
207 RegionAssetShelf &shelf_regiondata,
208 FunctionRef<void(AssetShelf &new_shelf)> on_create,
209 FunctionRef<void(AssetShelf &shelf)> on_reactivate)
210{
211 /* NOTE: Don't access #AssetShelf.type directly, use #type_ensure(). */
212
213 /* Case 1: */
214 if (shelf_regiondata.active_shelf &&
216 C, ensure_shelf_has_type(*shelf_regiondata.active_shelf), space_type))
217 {
218 /* Not a strong precondition, but if this is wrong something weird might be going on. */
219 BLI_assert(shelf_regiondata.active_shelf == shelf_regiondata.shelves.first);
220 return shelf_regiondata.active_shelf;
221 }
222
223 /* Case 2 (no active shelf or the poll of it isn't succeeding anymore. Poll all shelf types to
224 * determine a new active one): */
225 LISTBASE_FOREACH (AssetShelf *, shelf, &shelf_regiondata.shelves) {
226 if (shelf == shelf_regiondata.active_shelf) {
227 continue;
228 }
229
230 if (type_poll_for_non_popup(C, ensure_shelf_has_type(*shelf), space_type)) {
231 /* Found a valid previously activated shelf, reactivate it. */
232 activate_shelf(shelf_regiondata, *shelf);
233 if (on_reactivate) {
234 on_reactivate(*shelf);
235 }
236 return shelf;
237 }
238 }
239
240 /* Case 3: */
241 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
242 if (type_poll_for_non_popup(C, shelf_type.get(), space_type)) {
243 AssetShelf *new_shelf = create_shelf_from_type(*shelf_type);
244 BLI_addhead(&shelf_regiondata.shelves, new_shelf);
245 /* Moves ownership to the regiondata. */
246 activate_shelf(shelf_regiondata, *new_shelf);
247 if (on_create) {
248 on_create(*new_shelf);
249 }
250 return new_shelf;
251 }
252 }
253
254 shelf_regiondata.active_shelf = nullptr;
255 return nullptr;
256}
257
260/* -------------------------------------------------------------------- */
264void *region_duplicate(void *regiondata)
265{
266 const RegionAssetShelf *shelf_regiondata = static_cast<RegionAssetShelf *>(regiondata);
267 if (!shelf_regiondata) {
268 return nullptr;
269 }
270
271 return regiondata_duplicate(shelf_regiondata);
272}
273
274void region_free(ARegion *region)
275{
276 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
277 if (shelf_regiondata) {
278 regiondata_free(shelf_regiondata);
279 }
280 region->regiondata = nullptr;
281}
282
287static bool asset_shelf_space_poll(const bContext *C, const SpaceLink *space_link)
288{
289 /* Is there any asset shelf type registered that returns true for it's poll? */
290 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
291 if (type_poll_for_non_popup(*C, shelf_type.get(), space_link->spacetype)) {
292 return true;
293 }
294 }
295
296 return false;
297}
298
300{
301 return asset_shelf_space_poll(params->context,
302 static_cast<SpaceLink *>(params->area->spacedata.first));
303}
304
306{
307 ARegion *region = params->region;
308 const wmNotifier *wmn = params->notifier;
309
310 switch (wmn->category) {
311 case NC_SPACE:
312 if (wmn->data == ND_REGIONS_ASSET_SHELF) {
313 ED_region_tag_redraw(region);
314 }
315 break;
316 case NC_SCENE:
317 /* Asset shelf polls typically check the mode. */
318 if (ELEM(wmn->data, ND_MODE)) {
319 ED_region_tag_redraw(region);
320 }
321 break;
322 case NC_ASSET:
323 ED_region_tag_redraw(region);
324 break;
325 }
326}
327
329{
330 if (list::listen(params->notifier)) {
332 }
333 /* If the asset list didn't catch the notifier, let the region itself listen. */
334 else {
336 }
337}
338
340{
341 wmMsgBus *mbus = params->message_bus;
342 WorkSpace *workspace = params->workspace;
343 ARegion *region = params->region;
344
345 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
346 msg_sub_value_region_tag_redraw.owner = region;
347 msg_sub_value_region_tag_redraw.user_data = region;
348 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
350 mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
351}
352
354{
355 /* Region-data should've been created by a previously called #region_on_poll_success(). */
356 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
358 shelf_regiondata,
359 "Region-data should've been created by a previously called `region_on_poll_success()`.");
360
361 AssetShelf *active_shelf = shelf_regiondata->active_shelf;
362
363 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
364
365 wmKeyMap *keymap = WM_keymap_ensure(
366 wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
367 WM_event_add_keymap_handler(&region->handlers, keymap);
368
369 region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
370 region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
371 region->v2d.keepofs |= V2D_KEEPOFS_Y;
372 region->v2d.keeptot |= V2D_KEEPTOT_STRICT;
373
374 region->v2d.flag |= V2D_SNAP_TO_PAGESIZE_Y;
375 region->v2d.page_size_y = active_shelf ? tile_height(active_shelf->settings) :
377
378 /* Ensure the view is snapped to a page still, especially for DPI changes. */
380}
381
383{
384 const uiStyle *style = UI_style_get_dpi();
385 return style->buttonspacey / 2;
386}
387
389{
390 /* Use the same as the height, equal padding looks nice. */
391 return main_region_padding_y();
392}
393
394static int current_tile_draw_height(const ARegion *region)
395{
396 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
397 *region);
398 const float aspect = BLI_rctf_size_y(&region->v2d.cur) /
399 (BLI_rcti_size_y(&region->v2d.mask) + 1);
400
401 /* It can happen that this function is called before the region is actually initialized, when
402 * user clicks & drags slightly on the 'up arrow' icon of the shelf. */
403 const AssetShelf *active_shelf = shelf_regiondata ? shelf_regiondata->active_shelf : nullptr;
404 return (active_shelf ? tile_height(active_shelf->settings) : asset_shelf_default_tile_height()) /
405 (IS_EQF(aspect, 0) ? 1.0f : aspect);
406}
407
411static int calculate_row_count_from_tile_draw_height(const int region_height_scaled,
412 const int tile_draw_height)
413{
414 return std::max(1, int((region_height_scaled - 2 * main_region_padding_y()) / tile_draw_height));
415}
416
418 const int tile_draw_height)
419{
420 return (row_count * tile_draw_height + 2 * main_region_padding_y());
421}
422
423int region_snap(const ARegion *region, const int size, const int axis)
424{
425 /* Only on Y axis. */
426 if (axis != 1) {
427 return size;
428 }
429
430 /* Using scaled values only simplifies things. Simply divide the result by the scale again. */
431
432 const int tile_height = current_tile_draw_height(region);
433
434 const int row_count = calculate_row_count_from_tile_draw_height(size * UI_SCALE_FAC,
436
437 const int new_size_scaled = calculate_scaled_region_height_from_row_count(row_count,
439 return new_size_scaled / UI_SCALE_FAC;
440}
441
447static void region_resize_to_preferred(ScrArea *area, ARegion *region)
448{
449 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
450 *region);
451 const AssetShelf *active_shelf = shelf_regiondata->active_shelf;
452
453 BLI_assert(active_shelf->preferred_row_count > 0);
454
455 const int tile_height = current_tile_draw_height(region);
457 active_shelf->preferred_row_count, tile_height) /
459
460 if (region->sizey != new_size_y) {
461 region->sizey = new_size_y;
462 ED_area_tag_region_size_update(area, region);
463 }
464}
465
467{
468 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
469 *region);
470 AssetShelf *active_shelf = shelf_regiondata->active_shelf;
471 if (!active_shelf) {
472 return;
473 }
474
475 const int tile_height = current_tile_draw_height(region);
477 region->sizey * UI_SCALE_FAC, tile_height);
478}
479
480int tile_width(const AssetShelfSettings &settings)
481{
482 return UI_preview_tile_size_x(settings.preview_size);
483}
484
485int tile_height(const AssetShelfSettings &settings)
486{
487 return (settings.display_flag & ASSETSHELF_SHOW_NAMES) ?
488 UI_preview_tile_size_y(settings.preview_size) :
489 UI_preview_tile_size_y_no_label(settings.preview_size);
490}
491
496
498{
499 /* One row by default (plus padding). */
501}
502
503void region_layout(const bContext *C, ARegion *region)
504{
505 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
507 shelf_regiondata,
508 "Region-data should've been created by a previously called `region_on_poll_success()`.");
509
510 const AssetShelf *active_shelf = shelf_regiondata->active_shelf;
511 if (!active_shelf) {
512 return;
513 }
514
515 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
516
517 const uiStyle *style = UI_style_get_dpi();
518 const int padding_y = main_region_padding_y();
519 const int padding_x = main_region_padding_x();
520 uiLayout *layout = UI_block_layout(block,
523 padding_x,
524 -padding_y,
525 region->winx - 2 * padding_x,
526 0,
527 0,
528 style);
529
531 *layout, active_shelf->settings.asset_library_reference, *active_shelf, *C, *region);
532
533 int layout_height;
534 UI_block_layout_resolve(block, nullptr, &layout_height);
535 BLI_assert(layout_height <= 0);
536 UI_view2d_totRect_set(&region->v2d, region->winx - 1, layout_height - padding_y);
537 UI_view2d_curRect_validate(&region->v2d);
538
540
541 /* View2D matrix might have changed due to dynamic sized regions.
542 * Without this, tooltips jump around, see #129347. Reason is that #UI_but_tooltip_refresh() is
543 * called as part of #UI_block_end(), so the block's window matrix needs to be up-to-date. */
544 {
545 UI_view2d_view_ortho(&region->v2d);
546 UI_blocklist_update_window_matrix(C, &region->uiblocks);
547 }
548
549 UI_block_end(C, block);
550}
551
552void region_draw(const bContext *C, ARegion *region)
553{
554 ED_region_clear(C, region, TH_BACK);
555
556 /* Set view2d view matrix for scrolling. */
557 UI_view2d_view_ortho(&region->v2d);
558
559 /* View2D matrix might have changed due to dynamic sized regions. */
560 UI_blocklist_update_window_matrix(C, &region->uiblocks);
561
562 UI_blocklist_draw(C, &region->uiblocks);
563
564 /* Restore view matrix. */
566
567 UI_view2d_scrollers_draw(&region->v2d, nullptr);
568}
569
571{
572 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::ensure_from_asset_shelf_region(*region);
573 if (!shelf_regiondata) {
575 return;
576 }
577
578 const int old_region_flag = region->flag;
579
580 ScrArea *area = CTX_wm_area(C);
582 *C,
583 eSpace_Type(area->spacetype),
584 *shelf_regiondata,
585 /*on_create=*/
586 [&](AssetShelf &new_shelf) {
587 /* Set region visibility for first time shelf is created (`'DEFAULT_VISIBLE'` option). */
588 SET_FLAG_FROM_TEST(region->flag,
589 (new_shelf.type->flag & ASSET_SHELF_TYPE_FLAG_DEFAULT_VISIBLE) == 0,
590 RGN_FLAG_HIDDEN);
591 },
592 /*on_reactivate=*/
593 [&](AssetShelf &shelf) {
594 /* Restore region visibility from previous asset shelf instantiation when reactivating. */
595 SET_FLAG_FROM_TEST(
596 region->flag, shelf.instance_flag & ASSETSHELF_REGION_IS_HIDDEN, RGN_FLAG_HIDDEN);
597 });
598
599 if (old_region_flag != region->flag) {
600 ED_region_visibility_change_update(const_cast<bContext *>(C), area, region);
601 }
602
603 if (shelf_regiondata->active_shelf) {
604 /* Remember current visibility state of the region in the shelf, so we can restore it on
605 * reactivation. */
607 region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER),
609 }
610}
611
616
618{
619 ED_region_header_init(region);
620 region->alignment |= RGN_SPLIT_SCALE_PREV;
622}
623
628
630{
631 /* Use a height that lets widgets sit just on top of the separator line drawn at the lower edge
632 * of the region (widgets will be centered).
633 *
634 * Note that this is usually a bit less than the header size. The asset shelf tends to look like
635 * a separate area, so making the shelf header smaller than a header helps. */
637}
638
640{
641 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
642 if (!shelf_regiondata) {
643 return;
644 }
645 regiondata_blend_read_data(reader, &shelf_regiondata);
646 region->regiondata = shelf_regiondata;
647}
648
650{
651 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
652 if (!shelf_regiondata) {
653 return;
654 }
655 regiondata_blend_write(writer, shelf_regiondata);
656}
657
660/* -------------------------------------------------------------------- */
665{
666 const ARegion *shelf_region = BKE_area_find_region_type(area, RGN_TYPE_ASSET_SHELF);
667 if (!shelf_region) {
668 /* Called in wrong context, area doesn't have a shelf. */
669 return nullptr;
670 }
671
672 if (shelf_region->flag & RGN_FLAG_POLL_FAILED) {
673 /* Don't return data when the region "doesn't exist" (poll failed). */
674 return nullptr;
675 }
676
677 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
678 *shelf_region);
679 if (!shelf_regiondata) {
680 return nullptr;
681 }
682
683 return shelf_regiondata->active_shelf;
684}
685
686int context(const bContext *C, const char *member, bContextDataResult *result)
687{
688 static const char *context_dir[] = {
689 "asset_shelf",
690 "asset_library_reference",
691 "active_file", /* XXX yuk... */
692 nullptr,
693 };
694
695 if (CTX_data_dir(member)) {
696 CTX_data_dir_set(result, context_dir);
697 return CTX_RESULT_OK;
698 }
699
700 bScreen *screen = CTX_wm_screen(C);
701
702 if (CTX_data_equals(member, "asset_shelf")) {
704 if (!active_shelf) {
705 return CTX_RESULT_NO_DATA;
706 }
707
708 CTX_data_pointer_set(result, &screen->id, &RNA_AssetShelf, active_shelf);
709 return CTX_RESULT_OK;
710 }
711
712 if (CTX_data_equals(member, "asset_library_reference")) {
714 if (!active_shelf) {
715 return CTX_RESULT_NO_DATA;
716 }
717
719 &screen->id,
720 &RNA_AssetLibraryReference,
721 &active_shelf->settings.asset_library_reference);
722 return CTX_RESULT_OK;
723 }
724
725 /* XXX hack. Get the asset from the active item, but needs to be the file... */
726 if (CTX_data_equals(member, "active_file")) {
727 const ARegion *region = CTX_wm_region(C);
728 const uiBut *but = UI_region_views_find_active_item_but(region);
729 if (!but) {
730 return CTX_RESULT_NO_DATA;
731 }
732
733 const bContextStore *but_context = UI_but_context_get(but);
734 if (!but_context) {
735 return CTX_RESULT_NO_DATA;
736 }
737
738 const PointerRNA *file_ptr = CTX_store_ptr_lookup(
739 but_context, "active_file", &RNA_FileSelectEntry);
740 if (!file_ptr) {
741 return CTX_RESULT_NO_DATA;
742 }
743
744 CTX_data_pointer_set_ptr(result, file_ptr);
745 return CTX_RESULT_OK;
746 }
747
749}
750
752{
753 return CTX_data_pointer_get_type(C, "asset_shelf", &RNA_AssetShelf);
754}
755
757{
758 PointerRNA shelf_settings_ptr = active_shelf_ptr_from_context(C);
759 return static_cast<AssetShelf *>(shelf_settings_ptr.data);
760}
761
764/* -------------------------------------------------------------------- */
769{
770 const uiStyle *style = UI_style_get_dpi();
771 const int string_width = UI_fontstyle_string_width(&style->widget, name.c_str());
772 const int pad_x = UI_UNIT_X * 0.3f;
773 const int but_width = std::min(string_width + 2 * pad_x, UI_UNIT_X * 8);
774
775 uiBut *but = uiDefBut(
776 &block,
778 0,
779 name,
780 0,
781 0,
782 but_width,
783 UI_UNIT_Y,
784 nullptr,
785 0,
786 0,
787 TIP_("Enable catalog, making contained assets visible in the asset shelf"));
788
791
792 return but;
793}
794
795static void add_catalog_tabs(AssetShelf &shelf, uiLayout &layout)
796{
797 uiBlock *block = uiLayoutGetBlock(&layout);
798 AssetShelfSettings &shelf_settings = shelf.settings;
799
800 /* "All" tab. */
801 {
802 uiBut *but = add_tab_button(*block, IFACE_("All"));
803 UI_but_func_set(but, [&shelf_settings](bContext &C) {
804 settings_set_all_catalog_active(shelf_settings);
806 });
807 UI_but_func_pushed_state_set(but, [&shelf_settings](const uiBut &) -> bool {
808 return settings_is_all_catalog_active(shelf_settings);
809 });
810 }
811
812 uiItemS(&layout);
813
814 /* Regular catalog tabs. */
816 uiBut *but = add_tab_button(*block, path.name());
817
818 UI_but_func_set(but, [&shelf_settings, path](bContext &C) {
819 settings_set_active_catalog(shelf_settings, path);
821 });
822 UI_but_func_pushed_state_set(but, [&shelf_settings, path](const uiBut &) -> bool {
823 return settings_is_active_catalog(shelf_settings, path);
824 });
825 });
826}
827
830/* -------------------------------------------------------------------- */
836static void asset_shelf_header_draw(const bContext *C, Header *header)
837{
838 uiLayout *layout = header->layout;
839 uiBlock *block = uiLayoutGetBlock(layout);
840 const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C);
841
842 list::storage_fetch(library_ref, C);
843
845 uiItemPopoverPanel(layout, C, "ASSETSHELF_PT_catalog_selector", "", ICON_COLLAPSEMENU);
847
848 uiItemS(layout);
849
851 if (AssetShelf *shelf = static_cast<AssetShelf *>(shelf_ptr.data)) {
852 add_catalog_tabs(*shelf, *layout);
853 }
854
855 uiItemSpacer(layout);
856
857 uiItemPopoverPanel(layout, C, "ASSETSHELF_PT_display", "", ICON_IMGDISPLAY);
858 uiLayout *sub = uiLayoutRow(layout, false);
859 /* Same as file/asset browser header. */
860 uiLayoutSetUnitsX(sub, 8);
861 uiItemR(sub, &shelf_ptr, "search_filter", UI_ITEM_NONE, "", ICON_VIEWZOOM);
862}
863
864static void header_regiontype_register(ARegionType *region_type, const int space_type)
865{
866 HeaderType *ht = MEM_cnew<HeaderType>(__func__);
867 STRNCPY(ht->idname, "ASSETSHELF_HT_settings");
868 ht->space_type = space_type;
871 ht->poll = [](const bContext *C, HeaderType *) {
873 };
874
875 BLI_addtail(&region_type->headertypes, ht);
876}
877
878void types_register(ARegionType *region_type, const int space_type)
879{
880 header_regiontype_register(region_type, space_type);
882 popover_panel_register(region_type);
883}
884
887/* -------------------------------------------------------------------- */
891void type_unlink(const Main &bmain, const AssetShelfType &shelf_type)
892{
893 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
894 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
895 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
896 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
897 LISTBASE_FOREACH (ARegion *, region, regionbase) {
898 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
899 continue;
900 }
901
902 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
903 *region);
904 if (!shelf_regiondata) {
905 continue;
906 }
907 LISTBASE_FOREACH (AssetShelf *, shelf, &shelf_regiondata->shelves) {
908 if (shelf->type == &shelf_type) {
909 shelf->type = nullptr;
910 }
911 }
912
913 BLI_assert((shelf_regiondata->active_shelf == nullptr) ||
914 (shelf_regiondata->active_shelf->type != &shelf_type));
915 }
916 }
917 }
918 }
919
920 type_popup_unlink(shelf_type);
921}
922
925} // namespace blender::ed::asset::shelf
void CTX_data_dir_set(bContextDataResult *result, const char **dir)
bool CTX_data_equals(const char *member, const char *str)
bScreen * CTX_wm_screen(const bContext *C)
void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
bool CTX_data_dir(const char *member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
ScrArea * CTX_wm_area(const bContext *C)
const AssetLibraryReference * CTX_wm_asset_library_ref(const bContext *C)
@ CTX_RESULT_MEMBER_NOT_FOUND
@ CTX_RESULT_OK
@ CTX_RESULT_NO_DATA
SpaceLink * CTX_wm_space_data(const bContext *C)
const PointerRNA * CTX_store_ptr_lookup(const bContextStore *store, blender::StringRefNull name, const StructRNA *type=nullptr)
void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr)
ARegion * CTX_wm_region(const bContext *C)
#define ASSET_SHELF_PREVIEW_SIZE_DEFAULT
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define IS_EQF(a, b)
#define STREQ(a, b)
#define TIP_(msgid)
#define IFACE_(msgid)
@ RGN_SPLIT_SCALE_PREV
@ ASSETSHELF_SHOW_NAMES
@ RGN_TYPE_ASSET_SHELF_HEADER
@ RGN_TYPE_WINDOW
@ RGN_TYPE_ASSET_SHELF
@ RGN_FLAG_RESIZE_RESPECT_BUTTON_SECTIONS
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_POLL_FAILED
@ RGN_FLAG_HIDDEN_BY_USER
@ ASSETSHELF_REGION_IS_HIDDEN
eSpace_Type
@ SPACE_EMPTY
#define UI_SCALE_FAC
@ V2D_SNAP_TO_PAGESIZE_Y
@ V2D_KEEPOFS_Y
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_RIGHT
@ V2D_KEEPTOT_STRICT
@ V2D_LOCKZOOM_X
@ V2D_LOCKZOOM_Y
void ED_region_clear(const bContext *C, const ARegion *region, int colorid)
Definition area.cc:2807
void ED_region_header_init(ARegion *region)
Definition area.cc:3661
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:653
void ED_region_header_with_button_sections(const bContext *C, ARegion *region, uiButtonSectionsAlign align)
Definition area.cc:3653
void ED_area_tag_region_size_update(ScrArea *area, ARegion *changed_region)
Definition area.cc:744
void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region)
Definition area.cc:2254
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:381
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
void UI_but_func_pushed_state_set(uiBut *but, std::function< bool(const uiBut &)> func)
void UI_but_flag_disable(uiBut *but, int flag)
void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
#define UI_UNIT_Y
@ UI_EMBOSS_NONE
@ UI_EMBOSS
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
const uiStyle * UI_style_get_dpi()
int UI_preview_tile_size_y(const int size_px=96)
void UI_but_drawflag_enable(uiBut *but, int flag)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
void uiLayoutSetUnitsX(uiLayout *layout, float unit)
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
void uiItemSpacer(uiLayout *layout)
@ UI_LAYOUT_VERTICAL
@ UI_LAYOUT_PANEL
int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void UI_blocklist_draw(const bContext *C, const ListBase *lb)
#define UI_BUTTON_SECTION_SEPERATOR_LINE_WITH
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
int UI_preview_tile_size_x(const int size_px=96)
#define UI_UNIT_X
@ UI_BTYPE_TAB
const bContextStore * UI_but_context_get(const uiBut *but)
int UI_preview_tile_size_y_no_label(const int size_px=96)
void UI_block_end(const bContext *C, uiBlock *block)
void uiItemPopoverPanel(uiLayout *layout, const bContext *C, const char *panel_type, const char *name, int icon)
uiBut * UI_region_views_find_active_item_but(const ARegion *region)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_BUT_ALIGN_DOWN
@ UI_BUT_UNDO
@ TH_BACK
void UI_view2d_curRect_validate(View2D *v2d)
Definition view2d.cc:824
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition view2d.cc:1605
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1158
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:212
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition view2d.cc:1032
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1091
void UI_view2d_offset_y_snap_to_closest_page(View2D *v2d)
Definition view2d.cc:1975
@ V2D_COMMONVIEW_PANELS_UI
Definition UI_view2d.hh:41
#define ND_REGIONS_ASSET_SHELF
Definition WM_types.hh:509
#define ND_MODE
Definition WM_types.hh:412
#define NC_SCENE
Definition WM_types.hh:345
#define NC_ASSET
Definition WM_types.hh:371
#define NC_SPACE
Definition WM_types.hh:359
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void append(const T &value)
void remove(const int64_t index)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
AssetLibraryReference all_library_reference()
void storage_fetch(const AssetLibraryReference *library_reference, const bContext *C)
bool listen(const wmNotifier *notifier)
static bool asset_shelf_space_poll(const bContext *C, const SpaceLink *space_link)
static int asset_shelf_default_tile_height()
void header_region(const bContext *C, ARegion *region)
void region_init(wmWindowManager *wm, ARegion *region)
AssetShelfType * type_find_from_idname(const StringRef idname)
void region_blend_read_data(BlendDataReader *reader, ARegion *region)
void build_asset_view(uiLayout &layout, const AssetLibraryReference &library_ref, const AssetShelf &shelf, const bContext &C, const ARegion &region)
static int current_tile_draw_height(const ARegion *region)
bool settings_is_all_catalog_active(const AssetShelfSettings &settings)
AssetShelf * create_shelf_from_type(AssetShelfType &type)
void type_popup_unlink(const AssetShelfType &shelf_type)
void popover_panel_register(ARegionType *region_type)
void types_register(ARegionType *region_type, const int space_type)
static Vector< std::unique_ptr< AssetShelfType > > & static_shelf_types()
void regiondata_free(RegionAssetShelf *shelf_regiondata)
static void header_regiontype_register(ARegionType *region_type, const int space_type)
void region_listen(const wmRegionListenerParams *params)
static int calculate_row_count_from_tile_draw_height(const int region_height_scaled, const int tile_draw_height)
void settings_foreach_enabled_catalog_path(const AssetShelf &shelf, FunctionRef< void(const asset_system::AssetCatalogPath &catalog_path)> fn)
void region_on_poll_success(const bContext *C, ARegion *region)
void catalog_selector_panel_register(ARegionType *region_type)
void header_region_listen(const wmRegionListenerParams *params)
static void asset_shelf_header_draw(const bContext *C, Header *header)
void settings_set_all_catalog_active(AssetShelfSettings &settings)
void type_unregister(const AssetShelfType &shelf_type)
void region_blend_write(BlendWriter *writer, ARegion *region)
void type_unlink(const Main &bmain, const AssetShelfType &shelf_type)
int tile_height(const AssetShelfSettings &settings)
static uiBut * add_tab_button(uiBlock &block, StringRefNull name)
AssetShelf * active_shelf_from_context(const bContext *C)
static AssetShelf * update_active_shelf(const bContext &C, const eSpace_Type space_type, RegionAssetShelf &shelf_regiondata, FunctionRef< void(AssetShelf &new_shelf)> on_create, FunctionRef< void(AssetShelf &shelf)> on_reactivate)
void regiondata_blend_write(BlendWriter *writer, const RegionAssetShelf *shelf_regiondata)
static PointerRNA active_shelf_ptr_from_context(const bContext *C)
static bool type_poll_for_non_popup(const bContext &C, const AssetShelfType *shelf_type, const int space_type)
void region_on_user_resize(const ARegion *region)
AssetShelfType * ensure_shelf_has_type(AssetShelf &shelf)
int context(const bContext *C, const char *member, bContextDataResult *result)
int tile_width(const AssetShelfSettings &settings)
int region_snap(const ARegion *region, int size, int axis)
void type_register(std::unique_ptr< AssetShelfType > type)
bool settings_is_active_catalog(const AssetShelfSettings &settings, const asset_system::AssetCatalogPath &path)
void * region_duplicate(void *regiondata)
void send_redraw_notifier(const bContext &C)
bool type_poll_for_popup(const bContext &C, const AssetShelfType *shelf_type)
static void asset_shelf_region_listen(const wmRegionListenerParams *params)
AssetShelf * active_shelf_from_area(const ScrArea *area)
bool regions_poll(const RegionPollParams *params)
static void region_resize_to_preferred(ScrArea *area, ARegion *region)
void header_region_init(wmWindowManager *wm, ARegion *region)
static bool type_poll_no_spacetype_check(const bContext &C, const AssetShelfType *shelf_type)
static int main_region_padding_y()
void regiondata_blend_read_data(BlendDataReader *reader, RegionAssetShelf **shelf_regiondata)
void settings_set_active_catalog(AssetShelfSettings &settings, const asset_system::AssetCatalogPath &path)
static int main_region_padding_x()
void region_draw(const bContext *C, ARegion *region)
void region_message_subscribe(const wmRegionMessageSubscribeParams *params)
RegionAssetShelf * regiondata_duplicate(const RegionAssetShelf *shelf_regiondata)
static int calculate_scaled_region_height_from_row_count(const int row_count, const int tile_draw_height)
static void activate_shelf(RegionAssetShelf &shelf_regiondata, AssetShelf &shelf)
void region_layout(const bContext *C, ARegion *region)
static void add_catalog_tabs(AssetShelf &shelf, uiLayout &layout)
void region_free(ARegion *region)
ListBase headertypes
AssetLibraryReference asset_library_reference
bool(* poll)(const bContext *C, const AssetShelfType *shelf_type)
struct AssetShelfType * type
AssetShelfSettings settings
short preferred_row_count
void(* draw)(const bContext *C, Header *header)
char idname[BKE_ST_MAXNAME]
bool(* poll)(const bContext *C, HeaderType *ht)
uiLayout * layout
void * first
ListBase screens
Definition BKE_main.hh:225
void * data
Definition RNA_types.hh:42
AssetShelf * active_shelf
uiFontStyle widget
unsigned int data
Definition WM_types.hh:325
unsigned int category
Definition WM_types.hh:325
struct wmKeyConfig * defaultconf
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:897
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value)