Blender V4.3
asset_shelf_catalog_selector.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 "AS_asset_catalog.hh"
13
14#include "BLI_string.h"
15
16#include "DNA_screen_types.h"
17
18#include "BKE_context.hh"
19#include "BKE_screen.hh"
20
21#include "BLT_translation.hh"
22
23#include "ED_asset_filter.hh"
24#include "ED_asset_list.hh"
25
26#include "RNA_access.hh"
27#include "RNA_prototypes.hh"
28
29#include "UI_interface.hh"
30#include "UI_tree_view.hh"
31
32#include "WM_api.hh"
33
34#include "asset_shelf.hh"
35
37
39 AssetShelf &shelf_;
40 AssetShelfSettings &shelf_settings_;
42
43 public:
44 class Item;
45
47 : shelf_(shelf), shelf_settings_(shelf_.settings)
48 {
49 catalog_tree_ = build_filtered_catalog_tree(
50 library,
51 shelf_settings_.asset_library_reference,
52 [this](const asset_system::AssetRepresentation &asset) {
53 return (!shelf_.type->asset_poll || shelf_.type->asset_poll(shelf_.type, &asset));
54 });
55 }
56
57 void build_tree() override
58 {
59 if (catalog_tree_.is_empty()) {
60 auto &item = add_tree_item<ui::BasicTreeViewItem>(RPT_("No applicable assets found"),
61 ICON_INFO);
62 item.disable_interaction();
63 return;
64 }
65
66 catalog_tree_.foreach_root_item(
67 [this](const asset_system::AssetCatalogTreeItem &catalog_item) {
68 Item &item = build_catalog_items_recursive(*this, catalog_item);
70 });
71 }
72
74 const asset_system::AssetCatalogTreeItem &catalog_item) const
75 {
76 Item &view_item = parent_view_item.add_tree_item<Item>(catalog_item, shelf_);
77
78 const int parent_count = view_item.count_parents() + 1;
79 catalog_item.foreach_child([&, this](const asset_system::AssetCatalogTreeItem &child) {
80 Item &child_item = build_catalog_items_recursive(view_item, child);
81
82 /* Uncollapse to some level (gives quick access, but don't let the tree get too big). */
83 if (parent_count < 2) {
84 child_item.uncollapse_by_default();
85 }
86 });
87
88 return view_item;
89 }
90
92
93 class Item : public ui::BasicTreeViewItem {
94 const asset_system::AssetCatalogTreeItem &catalog_item_;
95 /* Is the catalog path enabled in this redraw? Set on construction, updated by the UI (which
96 * gets a pointer to it). The UI needs it as char. */
97 char catalog_path_enabled_ = false;
98
99 public:
101 : ui::BasicTreeViewItem(catalog_item.get_name()),
102 catalog_item_(catalog_item),
103 catalog_path_enabled_(
104 settings_is_catalog_path_enabled(shelf, catalog_item.catalog_path()))
105 {
107 }
108
110 {
111 return catalog_path_enabled_ != 0;
112 }
113
115 {
116 bool has_enabled = false;
117
119 [&has_enabled](const ui::AbstractTreeViewItem &abstract_item) {
120 const Item &item = dynamic_cast<const Item &>(abstract_item);
121 if (item.is_catalog_path_enabled()) {
122 has_enabled = true;
123 }
124 },
126
127 return has_enabled;
128 }
129
131 {
132 return catalog_item_.catalog_path();
133 }
134
135 void build_row(uiLayout &row) override
136 {
138 uiBlock *block = uiLayoutGetBlock(&row);
139
141
142 uiLayout *subrow = uiLayoutRow(&row, false);
143 uiLayoutSetActive(subrow, catalog_path_enabled_);
144 uiItemL(subrow, catalog_item_.get_name().c_str(), ICON_NONE);
145 UI_block_layout_set_current(block, &row);
146
147 uiBut *toggle_but = uiDefButC(block,
149 0,
150 "",
151 0,
152 0,
153 UI_UNIT_X,
154 UI_UNIT_Y,
155 (char *)&catalog_path_enabled_,
156 0,
157 0,
158 TIP_("Toggle catalog visibility in the asset shelf"));
159 UI_but_func_set(toggle_but, [&tree](bContext &C) {
160 tree.update_shelf_settings_from_enabled_catalogs();
162 });
165 }
166 UI_but_flag_disable(toggle_but, UI_BUT_UNDO);
167 }
168 };
169};
170
172{
174 foreach_item([this](ui::AbstractTreeViewItem &view_item) {
175 const auto &selector_tree_item = dynamic_cast<AssetCatalogSelectorTree::Item &>(view_item);
176 if (selector_tree_item.is_catalog_path_enabled()) {
177 settings_set_catalog_path_enabled(shelf_, selector_tree_item.catalog_path());
178 }
179 });
180}
181
182void library_selector_draw(const bContext *C, uiLayout *layout, AssetShelf &shelf)
183{
185
186 PointerRNA shelf_ptr = RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_AssetShelf, &shelf);
187
188 uiLayout *row = uiLayoutRow(layout, true);
189 uiItemR(row, &shelf_ptr, "asset_library_reference", UI_ITEM_NONE, "", ICON_NONE);
191 uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_library_refresh");
192 }
193}
194
195static void catalog_selector_panel_draw(const bContext *C, Panel *panel)
196{
198 if (!shelf) {
199 return;
200 }
201
202 uiLayout *layout = panel->layout;
203
204 library_selector_draw(C, layout, *shelf);
205
208 if (!library) {
209 return;
210 }
211
212 uiBlock *block = uiLayoutGetBlock(layout);
214 *block,
215 "asset catalog tree view",
216 std::make_unique<AssetCatalogSelectorTree>(*library, *shelf));
217 tree_view->set_context_menu_title("Catalog");
218 ui::TreeViewBuilder::build_tree_view(*tree_view, *layout);
219}
220
222{
223 /* Uses global paneltype registry to allow usage as popover. So only register this once (may be
224 * called from multiple spaces). */
225 if (WM_paneltype_find("ASSETSHELF_PT_catalog_selector", true)) {
226 return;
227 }
228
229 PanelType *pt = MEM_cnew<PanelType>(__func__);
230 STRNCPY(pt->idname, "ASSETSHELF_PT_catalog_selector");
231 STRNCPY(pt->label, N_("Catalog Selector"));
233 pt->description = N_(
234 "Select the asset library and the contained catalogs to display in the asset shelf");
237 BLI_addtail(&region_type->paneltypes, pt);
239}
240
241} // namespace blender::ed::asset::shelf
bScreen * CTX_wm_screen(const bContext *C)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define RPT_(msgid)
#define TIP_(msgid)
#define BLT_I18NCONTEXT_DEFAULT_BPYRNA
@ ASSET_LIBRARY_LOCAL
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
blender::ui::AbstractGridView * UI_block_add_view(uiBlock &block, blender::StringRef idname, std::unique_ptr< blender::ui::AbstractGridView > grid_view)
void UI_but_flag_disable(uiBut *but, int flag)
#define UI_UNIT_Y
void uiLayoutSetActive(uiLayout *layout, bool active)
@ UI_EMBOSS
uiBut * uiDefButC(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, char *poin, float min, float max, const char *tip)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void UI_but_drawflag_enable(uiBut *but, int flag)
#define UI_ITEM_NONE
void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
#define UI_UNIT_X
@ UI_BTYPE_CHECKBOX
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_BUT_INDETERMINATE
@ UI_BUT_UNDO
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
constexpr const char * c_str() const
void foreach_child(ItemIterFn callback) const
void foreach_root_item(ItemIterFn callback) const
Item(const asset_system::AssetCatalogTreeItem &catalog_item, AssetShelf &shelf)
Item & build_catalog_items_recursive(ui::TreeViewOrItem &parent_view_item, const asset_system::AssetCatalogTreeItem &catalog_item) const
AssetCatalogSelectorTree(asset_system::AssetLibrary &library, AssetShelf &shelf)
Abstract base class for defining a customizable tree-view item.
AbstractTreeView & get_tree_view() const
Definition tree_view.cc:565
void foreach_item(ItemIterFn iter_fn, IterOptions options=IterOptions::None) const
Definition tree_view.cc:105
void set_context_menu_title(const std::string &title)
BasicTreeViewItem(StringRef label, BIFIconID icon=ICON_NONE)
Definition tree_view.cc:942
static void build_tree_view(AbstractTreeView &tree_view, uiLayout &layout, std::optional< StringRef > search_string={}, bool add_box=true)
Definition tree_view.cc:918
ItemT & add_tree_item(Args &&...args)
void foreach_item_recursive(ItemIterFn iter_fn, IterOptions options=IterOptions::None) const
Definition tree_view.cc:69
KDTree_3d * tree
asset_system::AssetLibrary * library_get_once_available(const AssetLibraryReference &library_reference)
void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
static void catalog_selector_panel_draw(const bContext *C, Panel *panel)
void settings_clear_enabled_catalogs(AssetShelf &shelf)
void library_selector_draw(const bContext *C, uiLayout *layout, AssetShelf &shelf)
void catalog_selector_panel_register(ARegionType *region_type)
AssetShelf * active_shelf_from_context(const bContext *C)
bool settings_is_catalog_path_enabled(const AssetShelf &shelf, const asset_system::AssetCatalogPath &path)
void send_redraw_notifier(const bContext &C)
void settings_set_catalog_path_enabled(AssetShelf &shelf, const asset_system::AssetCatalogPath &path)
asset_system::AssetCatalogTree build_filtered_catalog_tree(const asset_system::AssetLibrary &library, const AssetLibraryReference &library_ref, blender::FunctionRef< bool(const asset_system::AssetRepresentation &)> is_asset_visible_fn)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
ListBase paneltypes
AssetLibraryReference asset_library_reference
AssetShelfSettings settings
void(* draw)(const bContext *C, Panel *panel)
char idname[BKE_ST_MAXNAME]
void(* listener)(const wmRegionListenerParams *params)
char translation_context[BKE_ST_MAXNAME]
char label[BKE_ST_MAXNAME]
const char * description
struct uiLayout * layout
#define N_(msgid)
bool WM_paneltype_add(PanelType *pt)
PanelType * WM_paneltype_find(const char *idname, bool quiet)