Blender V4.5
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
10
11#include <algorithm>
12
14#include "AS_asset_library.hh"
15
16#include "BLI_function_ref.hh"
17#include "BLI_listbase.h"
18#include "BLI_string.h"
19
20#include "BKE_context.hh"
21#include "BKE_main.hh"
22#include "BKE_screen.hh"
23
24#include "BLT_translation.hh"
25
26#include "DNA_screen_types.h"
27
28#include "ED_asset_list.hh"
29#include "ED_screen.hh"
30
31#include "RNA_access.hh"
32#include "RNA_prototypes.hh"
33
34#include "UI_interface.hh"
35#include "UI_resources.hh"
36#include "UI_tree_view.hh"
37#include "UI_view2d.hh"
38
39#include "WM_api.hh"
40#include "WM_message.hh"
41
42#include "ED_asset_shelf.hh"
43#include "asset_shelf.hh"
44
46
48
53
54/* -------------------------------------------------------------------- */
57
59{
61 return shelf_types;
62}
63
64void type_register(std::unique_ptr<AssetShelfType> type)
65{
67 shelf_types.append(std::move(type));
68}
69
70void type_unregister(const AssetShelfType &shelf_type)
71{
73 auto *const it = std::find_if(shelf_types.begin(),
74 shelf_types.end(),
75 [&](const std::unique_ptr<AssetShelfType> &iter_type) {
76 return iter_type.get() == &shelf_type;
77 });
78 BLI_assert(it != shelf_types.end());
79
80 shelf_types.remove(it - shelf_types.begin());
81}
82
83static bool type_poll_no_spacetype_check(const bContext &C, const AssetShelfType *shelf_type)
84{
85 if (!shelf_type) {
86 return false;
87 }
88
89#ifndef NDEBUG
91 BLI_assert_msg(std::find_if(shelf_types.begin(),
92 shelf_types.end(),
93 [&](const std::unique_ptr<AssetShelfType> &type) {
94 return type.get() == shelf_type;
95 }) != shelf_types.end(),
96 "Asset shelf type is not registered");
97#endif
98
99 return !shelf_type->poll || shelf_type->poll(&C, shelf_type);
100}
101
102bool type_poll_for_popup(const bContext &C, const AssetShelfType *shelf_type)
103{
104 return type_poll_no_spacetype_check(C, shelf_type);
105}
106
114 const AssetShelfType *shelf_type,
115 const int space_type)
116{
117 if (!shelf_type) {
118 return false;
119 }
120 if (shelf_type->space_type && (space_type != shelf_type->space_type)) {
121 return false;
122 }
123
124 return type_poll_no_spacetype_check(C, shelf_type);
125}
126
128{
129 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
130 if (idname == shelf_type->idname) {
131 return shelf_type.get();
132 }
133 }
134 return nullptr;
135}
136
138{
139 if (shelf.type) {
140 return shelf.type;
141 }
142
143 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
144 if (STREQ(shelf.idname, shelf_type->idname)) {
145 shelf.type = shelf_type.get();
146 return shelf_type.get();
147 }
148 }
149
150 return nullptr;
151}
152
154{
155 AssetShelf *shelf = MEM_new<AssetShelf>(__func__);
156 *shelf = dna::shallow_zero_initialize();
157 shelf->settings.preview_size = type.default_preview_size ? type.default_preview_size :
159 shelf->settings.asset_library_reference = asset_system::all_library_reference();
160 shelf->type = &type;
161 shelf->preferred_row_count = 1;
162 STRNCPY(shelf->idname, type.idname);
163 return shelf;
164}
165
167
168/* -------------------------------------------------------------------- */
171
177static void activate_shelf(RegionAssetShelf &shelf_regiondata, AssetShelf &shelf)
178{
179 shelf_regiondata.active_shelf = &shelf;
180 BLI_assert(BLI_findindex(&shelf_regiondata.shelves, &shelf) > -1);
181 BLI_remlink(&shelf_regiondata.shelves, &shelf);
182 BLI_addhead(&shelf_regiondata.shelves, &shelf);
183}
184
207 const eSpace_Type space_type,
208 RegionAssetShelf &shelf_regiondata,
209 FunctionRef<void(AssetShelf &new_shelf)> on_create,
210 FunctionRef<void(AssetShelf &shelf)> on_reactivate)
211{
212 /* NOTE: Don't access #AssetShelf.type directly, use #type_ensure(). */
213
214 /* Case 1: */
215 if (shelf_regiondata.active_shelf &&
217 C, ensure_shelf_has_type(*shelf_regiondata.active_shelf), space_type))
218 {
219 /* Not a strong precondition, but if this is wrong something weird might be going on. */
220 BLI_assert(shelf_regiondata.active_shelf == shelf_regiondata.shelves.first);
221 return shelf_regiondata.active_shelf;
222 }
223
224 /* Case 2 (no active shelf or the poll of it isn't succeeding anymore. Poll all shelf types to
225 * determine a new active one): */
226 LISTBASE_FOREACH (AssetShelf *, shelf, &shelf_regiondata.shelves) {
227 if (shelf == shelf_regiondata.active_shelf) {
228 continue;
229 }
230
232 /* Found a valid previously activated shelf, reactivate it. */
233 activate_shelf(shelf_regiondata, *shelf);
234 if (on_reactivate) {
235 on_reactivate(*shelf);
236 }
237 return shelf;
238 }
239 }
240
241 /* Case 3: */
242 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
243 if (type_poll_for_non_popup(C, shelf_type.get(), space_type)) {
244 AssetShelf *new_shelf = create_shelf_from_type(*shelf_type);
245 BLI_addhead(&shelf_regiondata.shelves, new_shelf);
246 /* Moves ownership to the regiondata. */
247 activate_shelf(shelf_regiondata, *new_shelf);
248 if (on_create) {
249 on_create(*new_shelf);
250 }
251 return new_shelf;
252 }
253 }
254
255 shelf_regiondata.active_shelf = nullptr;
256 return nullptr;
257}
258
260
261/* -------------------------------------------------------------------- */
264
265void *region_duplicate(void *regiondata)
266{
267 const RegionAssetShelf *shelf_regiondata = static_cast<RegionAssetShelf *>(regiondata);
268 if (!shelf_regiondata) {
269 return nullptr;
270 }
271
272 return regiondata_duplicate(shelf_regiondata);
273}
274
275void region_free(ARegion *region)
276{
277 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
278 if (shelf_regiondata) {
279 regiondata_free(shelf_regiondata);
280 }
281 region->regiondata = nullptr;
282}
283
288static bool asset_shelf_space_poll(const bContext *C, const SpaceLink *space_link)
289{
290 /* Is there any asset shelf type registered that returns true for it's poll? */
291 for (const std::unique_ptr<AssetShelfType> &shelf_type : static_shelf_types()) {
292 if (type_poll_for_non_popup(*C, shelf_type.get(), space_link->spacetype)) {
293 return true;
294 }
295 }
296
297 return false;
298}
299
301{
302 return asset_shelf_space_poll(params->context,
303 static_cast<SpaceLink *>(params->area->spacedata.first));
304}
305
307{
308 ARegion *region = params->region;
309 const wmNotifier *wmn = params->notifier;
310
311 switch (wmn->category) {
312 case NC_SPACE:
313 if (wmn->data == ND_REGIONS_ASSET_SHELF) {
314 ED_region_tag_redraw(region);
315 }
316 break;
317 case NC_SCENE:
318 /* Asset shelf polls typically check the mode. */
319 if (ELEM(wmn->data, ND_MODE)) {
320 ED_region_tag_redraw(region);
321 }
322 break;
323 case NC_ASSET:
324 ED_region_tag_redraw(region);
325 break;
326 }
327}
328
330{
331 if (list::listen(params->notifier)) {
333 }
334 /* If the asset list didn't catch the notifier, let the region itself listen. */
335 else {
337 }
338}
339
341{
342 wmMsgBus *mbus = params->message_bus;
343 WorkSpace *workspace = params->workspace;
344 ARegion *region = params->region;
345
346 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
347 msg_sub_value_region_tag_redraw.owner = region;
348 msg_sub_value_region_tag_redraw.user_data = region;
349 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
351 mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
352}
353
355{
356 /* Region-data should've been created by a previously called #region_on_poll_success(). */
357 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
359 shelf_regiondata,
360 "Region-data should've been created by a previously called `region_on_poll_success()`.");
361
362 AssetShelf *active_shelf = shelf_regiondata->active_shelf;
363
364 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
365
366 wmKeyMap *keymap = WM_keymap_ensure(
367 wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
368 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
369
372 region->v2d.keepofs |= V2D_KEEPOFS_Y;
373 region->v2d.keeptot |= V2D_KEEPTOT_STRICT;
374
376 region->v2d.page_size_y = active_shelf ? tile_height(active_shelf->settings) :
378
379 /* Ensure the view is snapped to a page still, especially for DPI changes. */
381}
382
384{
385 const uiStyle *style = UI_style_get_dpi();
386 return style->buttonspacey / 2;
387}
388
390{
391 /* Use the same as the height, equal padding looks nice. */
392 return main_region_padding_y();
393}
394
395static int current_tile_draw_height(const ARegion *region)
396{
397 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
398 *region);
399 const float aspect = BLI_rctf_size_y(&region->v2d.cur) /
400 (BLI_rcti_size_y(&region->v2d.mask) + 1);
401
402 /* It can happen that this function is called before the region is actually initialized, when
403 * user clicks & drags slightly on the 'up arrow' icon of the shelf. */
404 const AssetShelf *active_shelf = shelf_regiondata ? shelf_regiondata->active_shelf : nullptr;
405 return (active_shelf ? tile_height(active_shelf->settings) : asset_shelf_default_tile_height()) /
406 (IS_EQF(aspect, 0) ? 1.0f : aspect);
407}
408
412static int calculate_row_count_from_tile_draw_height(const int region_height_scaled,
413 const int tile_draw_height)
414{
415 return std::max(1, int((region_height_scaled - 2 * main_region_padding_y()) / tile_draw_height));
416}
417
419 const int tile_draw_height)
420{
421 return (row_count * tile_draw_height + 2 * main_region_padding_y());
422}
423
424int region_snap(const ARegion *region, const int size, const int axis)
425{
426 /* Only on Y axis. */
427 if (axis != 1) {
428 return size;
429 }
430
431 /* Using scaled values only simplifies things. Simply divide the result by the scale again. */
432
433 const int tile_height = current_tile_draw_height(region);
434
437
438 const int new_size_scaled = calculate_scaled_region_height_from_row_count(row_count,
440 return new_size_scaled / UI_SCALE_FAC;
441}
442
448static void region_resize_to_preferred(ScrArea *area, ARegion *region)
449{
450 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
451 *region);
452 const AssetShelf *active_shelf = shelf_regiondata->active_shelf;
453
454 BLI_assert(active_shelf->preferred_row_count > 0);
455 const int tile_height = current_tile_draw_height(region);
456
457 /* Prevent the AssetShelf from getting too high (and thus being hidden) in case many rows are
458 * used and preview size is increased. */
459 const int size_y_avail = ED_area_max_regionsize(area, region, AE_TOP_TO_BOTTOMRIGHT);
460 const short int max_row_count = calculate_row_count_from_tile_draw_height(
461 size_y_avail * UI_SCALE_FAC, tile_height);
462
464 std::min(max_row_count, active_shelf->preferred_row_count),
465 tile_height) /
467
468 if (region->sizey != new_size_y) {
469 region->sizey = new_size_y;
470 ED_area_tag_region_size_update(area, region);
471 }
472}
473
475{
476 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
477 *region);
478 AssetShelf *active_shelf = shelf_regiondata->active_shelf;
479 if (!active_shelf) {
480 return;
481 }
482
483 const int tile_height = current_tile_draw_height(region);
485 region->sizey * UI_SCALE_FAC, tile_height);
486}
487
488int tile_width(const AssetShelfSettings &settings)
489{
490 return UI_preview_tile_size_x(settings.preview_size);
491}
492
493int tile_height(const AssetShelfSettings &settings)
494{
495 return (settings.display_flag & ASSETSHELF_SHOW_NAMES) ?
498}
499
504
506{
507 /* One row by default (plus padding). */
509}
510
511void region_layout(const bContext *C, ARegion *region)
512{
513 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
515 shelf_regiondata,
516 "Region-data should've been created by a previously called `region_on_poll_success()`.");
517
518 const AssetShelf *active_shelf = shelf_regiondata->active_shelf;
519 if (!active_shelf) {
520 return;
521 }
522
523 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
524
525 const uiStyle *style = UI_style_get_dpi();
526 const int padding_y = main_region_padding_y();
527 const int padding_x = main_region_padding_x();
528 uiLayout *layout = UI_block_layout(block,
531 padding_x,
532 -padding_y,
533 region->winx - 2 * padding_x,
534 0,
535 0,
536 style);
537
538 build_asset_view(*layout, active_shelf->settings.asset_library_reference, *active_shelf, *C);
539
540 int layout_height;
541 UI_block_layout_resolve(block, nullptr, &layout_height);
542 BLI_assert(layout_height <= 0);
543 UI_view2d_totRect_set(&region->v2d, region->winx - 1, layout_height - padding_y);
545
547
548 /* View2D matrix might have changed due to dynamic sized regions.
549 * Without this, tooltips jump around, see #129347. Reason is that #UI_but_tooltip_refresh() is
550 * called as part of #UI_block_end(), so the block's window matrix needs to be up-to-date. */
551 {
552 UI_view2d_view_ortho(&region->v2d);
553 UI_blocklist_update_window_matrix(C, &region->runtime->uiblocks);
554 }
555
556 UI_block_end(C, block);
557}
558
559void region_draw(const bContext *C, ARegion *region)
560{
561 ED_region_clear(C, region, TH_BACK);
562
563 /* Set view2d view matrix for scrolling. */
564 UI_view2d_view_ortho(&region->v2d);
565
566 /* View2D matrix might have changed due to dynamic sized regions. */
567 UI_blocklist_update_window_matrix(C, &region->runtime->uiblocks);
568
569 UI_blocklist_draw(C, &region->runtime->uiblocks);
570
571 /* Restore view matrix. */
573
574 UI_view2d_scrollers_draw(&region->v2d, nullptr);
575}
576
578{
579 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::ensure_from_asset_shelf_region(*region);
580 if (!shelf_regiondata) {
582 return;
583 }
584
585 const int old_region_flag = region->flag;
586
587 ScrArea *area = CTX_wm_area(C);
589 *C,
590 eSpace_Type(area->spacetype),
591 *shelf_regiondata,
592 /*on_create=*/
593 [&](AssetShelf &new_shelf) {
594 /* Set region visibility for first time shelf is created (`'DEFAULT_VISIBLE'` option). */
595 SET_FLAG_FROM_TEST(region->flag,
596 (new_shelf.type->flag & ASSET_SHELF_TYPE_FLAG_DEFAULT_VISIBLE) == 0,
597 RGN_FLAG_HIDDEN);
598 },
599 /*on_reactivate=*/
600 [&](AssetShelf &shelf) {
601 /* Restore region visibility from previous asset shelf instantiation when reactivating. */
602 SET_FLAG_FROM_TEST(
603 region->flag, shelf.instance_flag & ASSETSHELF_REGION_IS_HIDDEN, RGN_FLAG_HIDDEN);
604 });
605
606 if (old_region_flag != region->flag) {
607 ED_region_visibility_change_update(const_cast<bContext *>(C), area, region);
608 }
609
610 if (shelf_regiondata->active_shelf) {
611 /* Remember current visibility state of the region in the shelf, so we can restore it on
612 * reactivation. */
616 }
617}
618
623
630
635
637{
638 /* Use a height that lets widgets sit just on top of the separator line drawn at the lower edge
639 * of the region (widgets will be centered).
640 *
641 * Note that this is usually a bit less than the header size. The asset shelf tends to look like
642 * a separate area, so making the shelf header smaller than a header helps. */
644}
645
647{
648 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
649 if (!shelf_regiondata) {
650 return;
651 }
652 regiondata_blend_read_data(reader, &shelf_regiondata);
653 region->regiondata = shelf_regiondata;
654}
655
657{
658 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
659 if (!shelf_regiondata) {
660 return;
661 }
662 regiondata_blend_write(writer, shelf_regiondata);
663}
664
666
667/* -------------------------------------------------------------------- */
670
672{
673 const ARegion *shelf_region = BKE_area_find_region_type(area, RGN_TYPE_ASSET_SHELF);
674 if (!shelf_region) {
675 /* Called in wrong context, area doesn't have a shelf. */
676 return nullptr;
677 }
678
679 if (shelf_region->flag & RGN_FLAG_POLL_FAILED) {
680 /* Don't return data when the region "doesn't exist" (poll failed). */
681 return nullptr;
682 }
683
684 const RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
685 *shelf_region);
686 if (!shelf_regiondata) {
687 return nullptr;
688 }
689
690 return shelf_regiondata->active_shelf;
691}
692
693int context(const bContext *C, const char *member, bContextDataResult *result)
694{
695 static const char *context_dir[] = {
696 "asset_shelf",
697 "asset_library_reference",
698 "active_file", /* XXX yuk... */
699 nullptr,
700 };
701
702 if (CTX_data_dir(member)) {
703 CTX_data_dir_set(result, context_dir);
704 return CTX_RESULT_OK;
705 }
706
707 bScreen *screen = CTX_wm_screen(C);
708
709 if (CTX_data_equals(member, "asset_shelf")) {
711 if (!active_shelf) {
712 return CTX_RESULT_NO_DATA;
713 }
714
715 CTX_data_pointer_set(result, &screen->id, &RNA_AssetShelf, active_shelf);
716 return CTX_RESULT_OK;
717 }
718
719 if (CTX_data_equals(member, "asset_library_reference")) {
721 if (!active_shelf) {
722 return CTX_RESULT_NO_DATA;
723 }
724
726 &screen->id,
727 &RNA_AssetLibraryReference,
728 &active_shelf->settings.asset_library_reference);
729 return CTX_RESULT_OK;
730 }
731
732 /* XXX hack. Get the asset from the active item, but needs to be the file... */
733 if (CTX_data_equals(member, "active_file")) {
734 const ARegion *region = CTX_wm_region(C);
735 const uiBut *but = UI_region_views_find_active_item_but(region);
736 if (!but) {
737 return CTX_RESULT_NO_DATA;
738 }
739
740 const bContextStore *but_context = UI_but_context_get(but);
741 if (!but_context) {
742 return CTX_RESULT_NO_DATA;
743 }
744
745 const PointerRNA *file_ptr = CTX_store_ptr_lookup(
746 but_context, "active_file", &RNA_FileSelectEntry);
747 if (!file_ptr) {
748 return CTX_RESULT_NO_DATA;
749 }
750
752 return CTX_RESULT_OK;
753 }
754
756}
757
759{
760 return CTX_data_pointer_get_type(C, "asset_shelf", &RNA_AssetShelf);
761}
762
764{
765 PointerRNA shelf_settings_ptr = active_shelf_ptr_from_context(C);
766 return static_cast<AssetShelf *>(shelf_settings_ptr.data);
767}
768
770
771/* -------------------------------------------------------------------- */
774
776{
777 const uiStyle *style = UI_style_get_dpi();
778 const int string_width = UI_fontstyle_string_width(&style->widget, name.c_str());
779 const int pad_x = UI_UNIT_X * 0.3f;
780 const int but_width = std::min(string_width + 2 * pad_x, UI_UNIT_X * 8);
781
782 uiBut *but = uiDefBut(
783 &block,
785 0,
786 name,
787 0,
788 0,
789 but_width,
790 UI_UNIT_Y,
791 nullptr,
792 0,
793 0,
794 TIP_("Enable catalog, making contained assets visible in the asset shelf"));
795
798
799 return but;
800}
801
803{
804 uiBlock *block = uiLayoutGetBlock(&layout);
805 AssetShelfSettings &shelf_settings = shelf.settings;
806
807 /* "All" tab. */
808 {
809 uiBut *but = add_tab_button(*block, IFACE_("All"));
810 UI_but_func_set(but, [&shelf_settings](bContext &C) {
811 settings_set_all_catalog_active(shelf_settings);
813 });
814 UI_but_func_pushed_state_set(but, [&shelf_settings](const uiBut &) -> bool {
815 return settings_is_all_catalog_active(shelf_settings);
816 });
817 }
818
819 layout.separator();
820
821 /* Regular catalog tabs. */
823 uiBut *but = add_tab_button(*block, path.name());
824
825 UI_but_func_set(but, [&shelf_settings, path](bContext &C) {
826 settings_set_active_catalog(shelf_settings, path);
828 });
829 UI_but_func_pushed_state_set(but, [&shelf_settings, path](const uiBut &) -> bool {
830 return settings_is_active_catalog(shelf_settings, path);
831 });
832 });
833}
834
836
837/* -------------------------------------------------------------------- */
842
843static void asset_shelf_header_draw(const bContext *C, Header *header)
844{
845 uiLayout *layout = header->layout;
846 uiBlock *block = uiLayoutGetBlock(layout);
848
849 list::storage_fetch(library_ref, C);
850
852 uiItemPopoverPanel(layout, C, "ASSETSHELF_PT_catalog_selector", "", ICON_COLLAPSEMENU);
854
855 layout->separator();
856
858 if (AssetShelf *shelf = static_cast<AssetShelf *>(shelf_ptr.data)) {
859 add_catalog_tabs(*shelf, *layout);
860 }
861
862 uiItemSpacer(layout);
863
864 uiItemPopoverPanel(layout, C, "ASSETSHELF_PT_display", "", ICON_IMGDISPLAY);
865 uiLayout *sub = &layout->row(false);
866 /* Same as file/asset browser header. */
867 uiLayoutSetUnitsX(sub, 8);
868 sub->prop(&shelf_ptr, "search_filter", UI_ITEM_NONE, "", ICON_VIEWZOOM);
869}
870
871static void header_regiontype_register(ARegionType *region_type, const int space_type)
872{
873 HeaderType *ht = MEM_callocN<HeaderType>(__func__);
874 STRNCPY(ht->idname, "ASSETSHELF_HT_settings");
875 ht->space_type = space_type;
878 ht->poll = [](const bContext *C, HeaderType *) {
880 };
881
882 BLI_addtail(&region_type->headertypes, ht);
883}
884
885void types_register(ARegionType *region_type, const int space_type)
886{
887 header_regiontype_register(region_type, space_type);
889 popover_panel_register(region_type);
890}
891
893
894/* -------------------------------------------------------------------- */
897
898void type_unlink(const Main &bmain, const AssetShelfType &shelf_type)
899{
900 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
901 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
902 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
903 ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
904 LISTBASE_FOREACH (ARegion *, region, regionbase) {
905 if (region->regiontype != RGN_TYPE_ASSET_SHELF) {
906 continue;
907 }
908
909 RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
910 *region);
911 if (!shelf_regiondata) {
912 continue;
913 }
914 LISTBASE_FOREACH (AssetShelf *, shelf, &shelf_regiondata->shelves) {
915 if (shelf->type == &shelf_type) {
916 shelf->type = nullptr;
917 }
918 }
919
920 BLI_assert((shelf_regiondata->active_shelf == nullptr) ||
921 (shelf_regiondata->active_shelf->type != &shelf_type));
922 }
923 }
924 }
925 }
926
927 type_popup_unlink(shelf_type);
928}
929
931
932/* -------------------------------------------------------------------- */
935
937{
939 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
940 const bScreen *screen = WM_window_get_active_screen(win);
941 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
944 }
945 }
946 }
947}
948
950
951} // 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)
const PointerRNA * CTX_store_ptr_lookup(const bContextStore *store, blender::StringRef name, const StructRNA *type=nullptr)
@ CTX_RESULT_MEMBER_NOT_FOUND
@ CTX_RESULT_OK
@ CTX_RESULT_NO_DATA
SpaceLink * CTX_wm_space_data(const bContext *C)
void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define ASSET_SHELF_PREVIEW_SIZE_DEFAULT
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:840
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#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)
@ ASSETSHELF_SHOW_NAMES
@ RGN_TYPE_ASSET_SHELF_HEADER
@ RGN_TYPE_WINDOW
@ RGN_TYPE_ASSET_SHELF
@ ASSETSHELF_REGION_IS_HIDDEN
@ RGN_FLAG_RESIZE_RESPECT_BUTTON_SECTIONS
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_POLL_FAILED
@ RGN_FLAG_HIDDEN_BY_USER
@ RGN_SPLIT_SCALE_PREV
eSpace_Type
@ SPACE_EMPTY
#define UI_SCALE_FAC
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_RIGHT
@ V2D_SNAP_TO_PAGESIZE_Y
@ V2D_KEEPOFS_Y
@ V2D_LOCKZOOM_X
@ V2D_LOCKZOOM_Y
@ V2D_KEEPTOT_STRICT
int ED_area_max_regionsize(const ScrArea *area, const ARegion *scale_region, const AZEdge edge)
Definition area.cc:783
void ED_region_clear(const bContext *C, const ARegion *region, int colorid)
Definition area.cc:2927
void ED_region_header_init(ARegion *region)
Definition area.cc:3769
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:659
void ED_region_header_with_button_sections(const bContext *C, ARegion *region, uiButtonSectionsAlign align)
Definition area.cc:3761
void ED_area_tag_region_size_update(ScrArea *area, ARegion *changed_region)
Definition area.cc:750
void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region)
Definition area.cc:2355
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:384
@ AE_TOP_TO_BOTTOMRIGHT
#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
void UI_block_emboss_set(uiBlock *block, blender::ui::EmbossType emboss)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType 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, std::optional< blender::StringRef > tip)
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)
@ UI_BUT_ALIGN_DOWN
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
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)
@ UI_BUT_UNDO
void UI_block_end(const bContext *C, uiBlock *block)
uiBut * UI_region_views_find_active_item_but(const ARegion *region)
@ UI_LAYOUT_VERTICAL
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
@ UI_LAYOUT_PANEL
#define UI_ITEM_NONE
void uiLayoutSetUnitsX(uiLayout *layout, float unit)
void uiItemSpacer(uiLayout *layout)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
void uiItemPopoverPanel(uiLayout *layout, const bContext *C, blender::StringRef panel_type, std::optional< blender::StringRef > name_opt, int icon)
@ TH_BACK
void UI_view2d_curRect_validate(View2D *v2d)
Definition view2d.cc:828
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition view2d.cc:1503
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1162
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:221
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition view2d.cc:1036
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
void UI_view2d_offset_y_snap_to_closest_page(View2D *v2d)
Definition view2d.cc:1979
@ V2D_COMMONVIEW_PANELS_UI
Definition UI_view2d.hh:41
#define ND_REGIONS_ASSET_SHELF
Definition WM_types.hh:540
#define ND_MODE
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:375
#define NC_ASSET
Definition WM_types.hh:401
#define NC_SPACE
Definition WM_types.hh:389
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr const char * c_str() const
void append(const T &value)
void remove(const int64_t index)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
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)
AssetShelfType * type_find_from_idname(StringRef idname)
void region_init(wmWindowManager *wm, ARegion *region)
void region_blend_read_data(BlendDataReader *reader, 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 show_catalog_in_visible_shelves(const bContext &C, const StringRefNull catalog_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)
void settings_set_catalog_path_enabled(AssetShelf &shelf, const asset_system::AssetCatalogPath &path)
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 build_asset_view(uiLayout &layout, const AssetLibraryReference &library_ref, const AssetShelf &shelf, const bContext &C)
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
void * regiondata
ARegionRuntimeHandle * runtime
AssetLibraryReference asset_library_reference
short default_preview_size
char idname[BKE_ST_MAXNAME]
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:261
void * data
Definition RNA_types.hh:53
AssetShelf * active_shelf
short keeptot
short keepzoom
short keepofs
float page_size_y
ListBase areabase
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
short buttonspacey
uiFontStyle widget
unsigned int data
Definition WM_types.hh:355
unsigned int category
Definition WM_types.hh:355
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:893
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value)
bScreen * WM_window_get_active_screen(const wmWindow *win)