UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
19 changed files with 360 additions and 233 deletions
Showing only changes of commit 50292f1018 - Show all commits

View File

@ -13,6 +13,8 @@
#include <memory>
#include <string>
#include "BLI_string_ref.hh"
namespace blender::asset_system {
class AssetIdentifier {
@ -25,6 +27,10 @@ class AssetIdentifier {
AssetIdentifier(const AssetIdentifier &) = default;
std::string full_path() const;
/**
* Get the identifier to locate the asset within the asset library.
*/
StringRefNull relative_path() const;
};
} // namespace blender::asset_system

View File

@ -92,6 +92,8 @@ class AssetRepresentation {
/* C-Handle */
struct AssetRepresentation;
const blender::StringRefNull AS_asset_representation_relative_path_get(
const AssetRepresentation *asset_handle);
const std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
const ::AssetRepresentation *asset_handle);

View File

@ -24,4 +24,9 @@ std::string AssetIdentifier::full_path() const
return path;
}
StringRefNull AssetIdentifier::relative_path() const
{
return relative_asset_path_;
}
} // namespace blender::asset_system

View File

@ -111,6 +111,15 @@ const AssetLibrary &AssetRepresentation::owner_asset_library() const
using namespace blender;
const StringRefNull AS_asset_representation_relative_path_get(
const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
const asset_system::AssetIdentifier &identifier = asset->get_identifier();
return identifier.relative_path();
}
const std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =

View File

@ -33,6 +33,7 @@ set(SRC
intern/asset_mark_clear.cc
intern/asset_ops.cc
intern/asset_shelf.cc
intern/asset_shelf_asset_view.cc
intern/asset_shelf_catalog_selector.cc
intern/asset_shelf_settings.cc
intern/asset_temp_id_consumer.cc

View File

@ -38,6 +38,7 @@ void ED_asset_handle_get_full_library_path(
#ifdef __cplusplus
# include "BLI_string_ref.hh"
# include <optional>
/** The asset library may have an import method (e.g. append vs. link) defined to use. If so, this
@ -45,6 +46,8 @@ void ED_asset_handle_get_full_library_path(
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
const struct AssetHandle *asset);
blender::StringRefNull ED_asset_handle_get_relative_path(const AssetHandle &asset);
namespace blender::ed::asset {
/** If the ID already exists in the database, return it, otherwise add it. */

View File

@ -10,6 +10,7 @@
extern "C" {
#endif
struct ARegion;
struct ARegionType;
struct AssetShelfSettings;
struct bContext;
@ -22,11 +23,11 @@ struct wmWindowManager;
/* Asset Shelf Regions */
/** Only needed for #RGN_TYPE_ASSET_SHELF (not #RGN_TYPE_ASSET_SHELF_FOOTER). */
void ED_asset_shelf_region_init(ARegion *region);
void ED_asset_shelf_region_listen(const struct wmRegionListenerParams *params);
void ED_asset_shelf_region_draw(const bContext *C, struct ARegion *region);
void ED_asset_shelf_region_register(ARegionType *region_type,
const char *idname,
const int space_type);
void ED_asset_shelf_region_draw(const bContext *C,
struct ARegion *region,
struct AssetShelfSettings *shelf_settings);
void ED_asset_shelf_footer_region_init(struct wmWindowManager *wm, struct ARegion *region);
void ED_asset_shelf_footer_region(const struct bContext *C, struct ARegion *region);

View File

@ -48,6 +48,11 @@ std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
return AS_asset_representation_import_method_get(asset_handle->file_data->asset);
}
blender::StringRefNull ED_asset_handle_get_relative_path(const AssetHandle &asset)
{
return AS_asset_representation_relative_path_get(asset.file_data->asset);
}
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
char r_full_lib_path[FILE_MAX_LIBEXTRA])
{

View File

@ -24,6 +24,7 @@
#include "UI_interface.hh"
#include "UI_resources.h"
#include "UI_tree_view.hh"
#include "UI_view2d.h"
#include "WM_api.h"
@ -77,6 +78,16 @@ void ED_asset_shelf_region_listen(const wmRegionListenerParams *params)
}
}
void ED_asset_shelf_region_init(ARegion *region)
{
View2D &v2d = region->v2d;
UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* Only allow scrolling in vertical direction. */
v2d.scroll = V2D_SCROLL_RIGHT;
v2d.keepofs = V2D_LOCKOFS_X;
}
/**
* Check if there is any asset shelf type returning true in it's poll. If not, no asset shelf
* region should be displayed.
@ -96,30 +107,45 @@ static bool asset_shelf_region_header_type_poll(const bContext *C, HeaderType *
return false;
}
void ED_asset_shelf_region_draw(const bContext *C, ARegion *region)
void ED_asset_shelf_region_draw(const bContext *C,
ARegion *region,
AssetShelfSettings *shelf_settings)
{
ED_region_header(C, region);
}
AssetLibraryReference all_library_ref = {};
all_library_ref.type = ASSET_LIBRARY_ALL;
all_library_ref.custom_library_index = -1;
static void asset_shelf_region_draw(const bContext *C, Header *header)
{
uiLayout *layout = header->layout;
AssetFilterSettings dummy_filter_settings{0};
UI_ThemeClearColor(TH_BACK);
uiTemplateAssetShelf(layout, C, &dummy_filter_settings);
}
/* Set view2d view matrix for scrolling. */
UI_view2d_view_ortho(&region->v2d);
void ED_asset_shelf_region_register(ARegionType *region_type,
const char *idname,
const int space_type)
{
HeaderType *ht = MEM_cnew<HeaderType>(__func__);
strcpy(ht->idname, idname);
ht->space_type = space_type;
ht->region_type = RGN_TYPE_ASSET_SHELF_FOOTER;
ht->draw = asset_shelf_region_draw;
ht->poll = asset_shelf_region_header_type_poll;
BLI_addtail(&region_type->headertypes, ht);
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
const uiStyle *style = UI_style_get();
const float padding = style->panelouter;
UI_block_layout(block,
UI_LAYOUT_VERTICAL,
UI_LAYOUT_PANEL,
padding,
-padding,
region->winx - 2 * padding,
1,
0,
style);
shelf::build_asset_view(block, all_library_ref, shelf_settings, *C, *region);
int layout_width, layout_height;
UI_block_layout_resolve(block, &layout_width, &layout_height);
UI_view2d_totRect_set(&region->v2d, layout_width, layout_height);
UI_view2d_curRect_validate(&region->v2d);
UI_block_end(C, block);
UI_block_draw(C, block);
/* Restore view matrix. */
UI_view2d_view_restore(C);
}
void ED_asset_shelf_footer_region_listen(const wmRegionListenerParams *params)

View File

@ -9,6 +9,7 @@
#include "BLI_function_ref.hh"
struct ARegion;
struct AssetLibraryReference;
struct AssetShelfSettings;
struct bContext;
struct uiBlock;
@ -19,6 +20,12 @@ class AssetCatalogPath;
namespace blender::ed::asset::shelf {
void build_asset_view(uiBlock *block,
const AssetLibraryReference &library_ref,
const AssetShelfSettings *shelf_settings,
const bContext &C,
ARegion &region);
uiBlock *catalog_selector_block_draw(bContext *C, ARegion *region, void * /*arg1*/);
AssetShelfSettings *settings_from_context(const bContext *C);

View File

@ -0,0 +1,229 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edasset
*
* Grid-view showing all assets according to the giving shelf-type and settings.
*/
#include "AS_asset_library.hh"
#include "BKE_screen.h"
#include "DNA_asset_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "ED_asset_handle.h"
#include "ED_asset_list.h"
#include "ED_asset_list.hh"
#include "UI_grid_view.hh"
#include "UI_interface.h"
#include "UI_interface.hh"
#include "UI_view2d.h"
#include "WM_api.h"
#include "asset_shelf.hh"
namespace blender::ed::asset::shelf {
class AssetView : public ui::AbstractGridView {
const AssetLibraryReference library_ref_;
std::optional<asset_system::AssetCatalogFilter> catalog_filter_ = std::nullopt;
/* XXX Temporary: Only for #asset_poll__() callback. Should use traits instead. */
bContext &evil_C_;
friend class AssetDragController;
public:
AssetView(const AssetLibraryReference &library_ref, bContext &evil_C);
void build_items() override;
void set_catalog_filter(const std::optional<asset_system::AssetCatalogFilter> &catalog_filter);
};
class AssetViewItem : public ui::PreviewGridItem {
AssetHandle asset_;
public:
AssetViewItem(const AssetHandle &asset,
StringRef identifier,
StringRef label,
int preview_icon_id);
std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override;
};
class AssetDragController : public ui::AbstractViewItemDragController {
AssetHandle asset_;
public:
AssetDragController(ui::AbstractGridView &view, const AssetHandle &asset);
int get_drag_type() const override;
void *create_drag_data() const override;
};
AssetView::AssetView(const AssetLibraryReference &library_ref, bContext &evil_C)
: library_ref_(library_ref), evil_C_(evil_C)
{
}
/* TODO calling a (.py defined) callback for every asset isn't exactly great. Should be a temporary
* solution until there is proper filtering by asset traits. */
/**
* Returns true if the asset should be visible. That is, if any of the visible asset shelves has no
* poll function (all assets should be displayed), or its #AssetShelfType.asset_poll function
* returns true.
*/
static bool asset_shelf_asset_poll(const SpaceType &space_type,
const bContext &C,
const AssetHandle &asset)
{
LISTBASE_FOREACH (AssetShelfType *, shelf_type, &space_type.asset_shelf_types) {
if (!shelf_type->poll || !shelf_type->poll(&C, shelf_type)) {
continue;
}
if (!shelf_type->asset_poll || shelf_type->asset_poll(shelf_type, &asset)) {
return true;
}
}
return false;
}
void AssetView::build_items()
{
const asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(
library_ref_);
if (!library) {
return;
}
const SpaceLink *space_link = CTX_wm_space_data(&evil_C_);
const SpaceType *space_type = BKE_spacetype_from_id(space_link->spacetype);
ED_assetlist_iterate(library_ref_, [&](AssetHandle asset) {
if (!asset_shelf_asset_poll(*space_type, evil_C_, asset)) {
// return true;
}
const AssetMetaData *asset_data = ED_asset_handle_get_metadata(&asset);
if (catalog_filter_ && !catalog_filter_->contains(asset_data->catalog_id)) {
/* Skip this asset. */
return true;
}
/* Use the path within the library as identifier, this should be unique. */
const StringRef identifier = ED_asset_handle_get_relative_path(asset);
const StringRef name = ED_asset_handle_get_name(&asset);
const int preview_id = ED_asset_handle_get_preview_icon_id(&asset);
add_item<AssetViewItem>(asset, identifier, name, preview_id);
return true;
});
}
void AssetView::set_catalog_filter(
const std::optional<asset_system::AssetCatalogFilter> &catalog_filter)
{
if (catalog_filter) {
catalog_filter_.emplace(*catalog_filter);
}
else {
catalog_filter_ = std::nullopt;
}
}
static std::optional<asset_system::AssetCatalogFilter> catalog_filter_from_shelf_settings(
const AssetShelfSettings *shelf_settings, const asset_system::AssetLibrary &library)
{
if (!shelf_settings || !shelf_settings->active_catalog_path) {
return {};
}
asset_system ::AssetCatalog *active_catalog = library.catalog_service->find_catalog_by_path(
shelf_settings->active_catalog_path);
if (!active_catalog) {
return {};
}
return library.catalog_service->create_catalog_filter(active_catalog->catalog_id);
}
/* ---------------------------------------------------------------------- */
AssetViewItem::AssetViewItem(const AssetHandle &asset,
StringRef identifier,
StringRef label,
int preview_icon_id)
: ui::PreviewGridItem(identifier, label, preview_icon_id), asset_(asset)
{
}
std::unique_ptr<ui::AbstractViewItemDragController> AssetViewItem::create_drag_controller() const
{
return std::make_unique<AssetDragController>(get_view(), asset_);
}
/* ---------------------------------------------------------------------- */
void build_asset_view(uiBlock *block,
const AssetLibraryReference &library_ref,
const AssetShelfSettings *shelf_settings,
const bContext &C,
ARegion &region)
{
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
const asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(library_ref);
if (!library) {
return;
}
std::unique_ptr asset_view = std::make_unique<AssetView>(library_ref, const_cast<bContext &>(C));
asset_view->set_catalog_filter(catalog_filter_from_shelf_settings(shelf_settings, *library));
asset_view->set_tile_size(UI_preview_tile_size_x() * 0.8, UI_preview_tile_size_y() * 0.8);
ui::AbstractGridView *grid_view = UI_block_add_view(
*block, "asset shelf asset view", std::move(asset_view));
ui::GridViewBuilder builder(*block);
builder.build_grid_view(*grid_view, region.v2d);
}
JulianEisel marked this conversation as resolved Outdated

If the dynamic_cast isn't meant to fail in some cases, it's probably better to use static_cast to avoid bloating the code with dynamic casting.

Also, class methods should generally be accessed with this->

If the dynamic_cast isn't meant to fail in some cases, it's probably better to use `static_cast` to avoid bloating the code with dynamic casting. Also, class methods should generally be accessed with `this->`

Not a fan of using static_cast for down casting. It removes type safety for virtually (pun intended) no benefit. Sure it's unlikely to cause issues here, but if it does it's good to get an exception thrown. There's a language feature designed for this, so I rather use it.

https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-dynamic_cast
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c147-use-dynamic_cast-to-a-reference-type-when-failure-to-find-the-required-class-is-considered-an-error

Not a fan of using `static_cast` for down casting. It removes type safety for virtually (pun intended) no benefit. Sure it's unlikely to cause issues here, but if it does it's good to get an exception thrown. There's a language feature designed for this, so I rather use it. https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-dynamic_cast https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c147-use-dynamic_cast-to-a-reference-type-when-failure-to-find-the-required-class-is-considered-an-error

Hard to argue with the code guidelines I guess.. Still though, I'd find it clearer to use static_cast, since dynamic_cast gives the impression that the author thinks the cast might fail. But using a reference for the variable negates that impression, making the whole thing confusing. Not a big deal though

Hard to argue with the code guidelines I guess.. Still though, I'd find it clearer to use `static_cast`, since `dynamic_cast` gives the impression that the author thinks the cast might fail. But using a reference for the variable negates that impression, making the whole thing confusing. Not a big deal though
/* ---------------------------------------------------------------------- */
/* Dragging. */
AssetDragController::AssetDragController(ui::AbstractGridView &view, const AssetHandle &asset)
: ui::AbstractViewItemDragController(view), asset_(asset)
{
}
int AssetDragController::get_drag_type() const
{
const ID *local_id = ED_asset_handle_get_local_id(&asset_);
return local_id ? WM_DRAG_ID : WM_DRAG_ASSET;
}
void *AssetDragController::create_drag_data() const
JulianEisel marked this conversation as resolved Outdated

This is crashing on a simple test (default sculpt brush made into an asset).

  • Default blend file (w/ experimental asset features enabled).
  • Enter sculpt mode.
  • Make default sculpt brush into an asset (from the properties toolbar).
  • RMB in the asset shelf.
  • Crash.
This is crashing on a simple test (default sculpt brush made into an asset). - Default blend file (w/ experimental asset features enabled). - Enter sculpt mode. - Make default sculpt brush into an asset (from the properties toolbar). - RMB in the asset shelf. - Crash.
{
ID *local_id = ED_asset_handle_get_local_id(&asset_);
if (local_id) {
return static_cast<void *>(local_id);
}
char asset_blend_path[FILE_MAX_LIBEXTRA];
ED_asset_handle_get_full_library_path(&asset_, asset_blend_path);
const eAssetImportMethod import_method = ED_asset_handle_get_import_method(&asset_).value_or(
ASSET_IMPORT_APPEND_REUSE);
AssetView &asset_view = get_view<AssetView>();
return static_cast<void *>(WM_drag_create_asset_data(
&asset_, BLI_strdup(asset_blend_path), import_method, &asset_view.evil_C_));
}
} // namespace blender::ed::asset::shelf

View File

@ -45,7 +45,7 @@ class AbstractGridViewItem : public AbstractViewItem {
virtual void build_grid_tile(uiLayout &layout) const = 0;
const AbstractGridView &get_view() const;
AbstractGridView &get_view() const;
protected:
AbstractGridViewItem(StringRef identifier);
@ -125,6 +125,8 @@ class AbstractGridView : public AbstractView {
const GridViewStyle &get_style() const;
int get_item_count() const;
void set_tile_size(int tile_width, int tile_height);
protected:
virtual void build_items() = 0;

View File

@ -63,7 +63,6 @@ set(SRC
interface_region_tooltip.cc
interface_regions.cc
interface_style.cc
interface_template_asset_shelf.cc
interface_template_asset_view.cc
interface_template_attribute_search.cc
interface_template_list.cc

View File

@ -35,14 +35,8 @@ void UI_but_drag_set_asset(uiBut *but,
struct ImBuf *imb,
float scale)
{
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset_handle, path, import_type);
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
* #wmDropBox.
* TODO: Handle link/append in operator called at the end of the drop process, and NOT in its
* copy callback.
* */
asset_drag->evil_C = static_cast<bContext *>(but->block->evil_C);
wmDragAsset *asset_drag = WM_drag_create_asset_data(
asset_handle, path, import_type, static_cast<bContext *>(but->block->evil_C));
but->dragtype = WM_DRAG_ASSET;
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */

View File

@ -1,188 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edinterface
*/
#include "AS_asset_library.hh"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "ED_asset.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "interface_intern.hh"
#include "RNA_prototypes.h"
using namespace blender;
/* TODO copy of #asset_view_item_but_drag_set(). */
static void asset_tile_but_drag_set(uiBut &but, AssetHandle &asset_handle)
{
ID *id = ED_asset_handle_get_local_id(&asset_handle);
if (id != nullptr) {
UI_but_drag_set_id(&but, id);
return;
}
char blend_path[FILE_MAX_LIBEXTRA];
/* Context can be null here, it's only needed for a File Browser specific hack that should go
* away before too long. */
ED_asset_handle_get_full_library_path(&asset_handle, blend_path);
if (blend_path[0]) {
ImBuf *imbuf = ED_assetlist_asset_image_get(&asset_handle);
UI_but_drag_set_asset(&but,
&asset_handle,
BLI_strdup(blend_path),
FILE_ASSET_IMPORT_APPEND,
ED_asset_handle_get_preview_icon_id(&asset_handle),
imbuf,
1.0f);
}
}
static void asset_tile_draw(uiLayout &layout,
AssetHandle &asset_handle,
const int width,
const int height,
const bool show_names)
{
PointerRNA file_ptr;
RNA_pointer_create(
nullptr,
&RNA_FileSelectEntry,
/* XXX passing file pointer here, should be asset handle or asset representation. */
const_cast<FileDirEntry *>(asset_handle.file_data),
&file_ptr);
uiLayoutSetContextPointer(&layout, "active_file", &file_ptr);
uiBlock *block = uiLayoutGetBlock(&layout);
const StringRefNull name = ED_asset_handle_get_name(&asset_handle);
uiBut *but = uiDefIconTextBut(block,
UI_BTYPE_PREVIEW_TILE,
0,
ED_asset_handle_get_preview_icon_id(&asset_handle),
show_names ? name.c_str() : "",
0,
0,
width,
height,
nullptr,
0,
0,
0,
0,
name.c_str());
ui_def_but_icon(but,
ED_asset_handle_get_preview_icon_id(&asset_handle),
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
asset_tile_but_drag_set(*but, asset_handle);
}
static std::optional<asset_system::AssetCatalogFilter> catalog_filter_from_shelf_settings(
const AssetShelfSettings *shelf_settings, const asset_system::AssetLibrary *library)
{
if (!shelf_settings || !shelf_settings->active_catalog_path) {
return {};
}
asset_system ::AssetCatalog *active_catalog = library->catalog_service->find_catalog_by_path(
shelf_settings->active_catalog_path);
if (!active_catalog) {
return {};
}
return library->catalog_service->create_catalog_filter(active_catalog->catalog_id);
}
/* TODO calling a (.py defined) callback for every asset isn't exactly great. Should be a temporary
* solution until there is proper filtering by asset traits. */
/**
* Returns true if the asset should be visible. That is, if any of the visible asset shelves has no
* poll function (all assets should be displayed), or its #AssetShelfType.asset_poll function
* returns true.
*/
static bool asset_shelf_asset_poll(const SpaceType &space_type,
const bContext &C,
const AssetHandle &asset)
{
LISTBASE_FOREACH (AssetShelfType *, shelf_type, &space_type.asset_shelf_types) {
if (!shelf_type->poll || !shelf_type->poll(&C, shelf_type)) {
continue;
}
if (!shelf_type->asset_poll || shelf_type->asset_poll(shelf_type, &asset)) {
return true;
}
}
return false;
}
void uiTemplateAssetShelf(uiLayout *layout,
const bContext *C,
const AssetFilterSettings *filter_settings)
{
const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C);
const PointerRNA shelf_settings_ptr = CTX_data_pointer_get_type(
C, "asset_shelf_settings", &RNA_AssetShelfSettings);
const AssetShelfSettings *shelf_settings = static_cast<AssetShelfSettings *>(
shelf_settings_ptr.data);
Vector<decltype(AssetShelfType::asset_poll)> asset_polls;
ED_assetlist_storage_fetch(library_ref, C);
ED_assetlist_ensure_previews_job(library_ref, C);
const asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(
*library_ref);
if (!library) {
return;
}
std::optional<asset_system::AssetCatalogFilter> catalog_filter =
catalog_filter_from_shelf_settings(shelf_settings, library);
uiLayoutSetScaleX(layout, 1.0f);
uiLayoutSetScaleY(layout, 1.0f);
const bool show_names = true;
const int height = uiLayoutGetRootHeight(layout) - UI_style_get_dpi()->boxspace * 2;
/* Width is derived from the height. It's the height without the space for the name (if there is
* any). */
const int width = height - (show_names ? 0 : UI_UNIT_Y);
uiLayout *box = uiLayoutBox(layout);
uiLayout *row = uiLayoutRow(box, false);
const SpaceLink *space_link = CTX_wm_space_data(C);
const SpaceType *space_type = BKE_spacetype_from_id(space_link->spacetype);
ED_assetlist_iterate(*library_ref, [&](AssetHandle asset) {
if (!asset_shelf_asset_poll(*space_type, *C, asset)) {
return true;
}
if (!ED_asset_filter_matches_asset(filter_settings, &asset)) {
/* Don't do anything else, but return true to continue iterating. */
return true;
}
/* Filter by active catalog. */
const AssetMetaData *asset_data = ED_asset_handle_get_metadata(&asset);
if (catalog_filter && !catalog_filter->contains(asset_data->catalog_id)) {
return true;
}
asset_tile_draw(*row, asset, width, height, show_names);
return true;
});
}

View File

@ -84,6 +84,12 @@ int AbstractGridView::get_item_count() const
return items_.size();
}
void AbstractGridView::set_tile_size(int tile_width, int tile_height)
{
style_.tile_width = tile_width;
style_.tile_height = tile_height;
}
GridViewStyle::GridViewStyle(int width, int height) : tile_width(width), tile_height(height)
{
}
@ -173,7 +179,7 @@ void AbstractGridViewItem::deactivate()
is_active_ = false;
}
const AbstractGridView &AbstractGridViewItem::get_view() const
AbstractGridView &AbstractGridViewItem::get_view() const
{
if (UNLIKELY(!view_)) {
throw std::runtime_error(

View File

@ -304,7 +304,6 @@ static SpaceLink *view3d_create(const ScrArea * /*area*/, const Scene *scene)
BLI_addtail(&v3d->regionbase, region);
region->regiontype = RGN_TYPE_ASSET_SHELF;
region->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
region->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* main region */
region = MEM_cnew<ARegion>("main region for view3d");
@ -1916,6 +1915,21 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *region)
ED_region_panels_ex(C, region, contexts);
}
static void view3d_asset_shelf_region_draw(const bContext *C, ARegion *region)
{
View3D *v3d = CTX_wm_view3d(C);
ED_asset_shelf_region_draw(C, region, v3d->asset_shelf);
}
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_asset_shelf_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
WM_event_add_keymap_handler(&region->handlers, keymap);
ED_asset_shelf_region_init(region);
}
/* area (not region) level listener */
static void space_view3d_listener(const wmSpaceTypeListenerParams *params)
{
@ -2245,10 +2259,9 @@ void ED_spacetype_view3d()
ED_KEYMAP_HEADER;
art->listener = ED_asset_shelf_region_listen;
art->context = view3d_asset_shelf_context;
art->init = view3d_header_region_init;
art->draw = ED_asset_shelf_region_draw;
art->init = view3d_asset_shelf_region_init;
art->draw = view3d_asset_shelf_region_draw;
BLI_addhead(&st->regiontypes, art);
ED_asset_shelf_region_register(art, "VIEW3D_HT_asset_shelf_main", SPACE_VIEW3D);
/* regions: asset shelf footer */
art = MEM_cnew<ARegionType>("spacetype view3d asset shelf footer region");

View File

@ -1352,7 +1352,8 @@ bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode);
*/
wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset,
const char *path,
int /* #eAssetImportMethod */ import_type);
int /* #eAssetImportMethod */ import_type,
struct bContext *evil_C);
struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode);
struct AssetMetaData *WM_drag_get_asset_meta_data(const struct wmDrag *drag, int idcode);
/**
@ -1381,7 +1382,9 @@ struct wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const struct wmDrag *d
/**
* \note Does not store \a asset in any way, so it's fine to pass a temporary.
*/
void WM_drag_add_asset_list_item(wmDrag *drag, const struct AssetHandle *asset);
void WM_drag_add_asset_list_item(wmDrag *drag,
const struct AssetHandle *asset,
struct bContext *evil_C);
const ListBase *WM_drag_asset_list_get(const wmDrag *drag);
const char *WM_drag_get_item_name(struct wmDrag *drag);

View File

@ -210,7 +210,7 @@ wmDrag *WM_drag_data_create(bContext *C, int icon, int type, void *poin, double
LISTBASE_FOREACH (const CollectionPointerLink *, link, &asset_file_links) {
const FileDirEntry *asset_file = static_cast<const FileDirEntry *>(link->ptr.data);
const AssetHandle asset_handle = {asset_file};
WM_drag_add_asset_list_item(drag, &asset_handle);
WM_drag_add_asset_list_item(drag, &asset_handle, C);
}
BLI_freelistN(&asset_file_links);
break;
@ -563,7 +563,10 @@ bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
}
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *path, int import_type)
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset,
const char *path,
int import_type,
bContext *evil_C)
{
wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__);
@ -572,6 +575,7 @@ wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *pat
asset_drag->path = path;
asset_drag->id_type = ED_asset_handle_get_id_type(asset);
asset_drag->import_method = import_type;
asset_drag->evil_C = static_cast<bContext *>(evil_C);
return asset_drag;
}
@ -718,7 +722,7 @@ wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const wmDrag *drag)
return static_cast<wmDragAssetCatalog *>(drag->poin);
}
void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset)
void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset, bContext *evil_C)
{
BLI_assert(drag->type == WM_DRAG_ASSET_LIST);
@ -736,7 +740,7 @@ void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset)
ED_asset_handle_get_full_library_path(asset, asset_blend_path);
drag_asset->is_external = true;
drag_asset->asset_data.external_info = WM_drag_create_asset_data(
asset, BLI_strdup(asset_blend_path), ASSET_IMPORT_APPEND);
asset, BLI_strdup(asset_blend_path), ASSET_IMPORT_APPEND, evil_C);
}
BLI_addtail(&drag->asset_items, drag_asset);
}