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.
13 changed files with 127 additions and 8 deletions
Showing only changes of commit 50259e62bf - Show all commits

View File

@ -20,6 +20,7 @@ extern "C" {
#endif
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
#include "DNA_ID_enums.h"
@ -110,6 +111,9 @@ struct ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) ATTR_WARN_UNUSED_RESULT;
*/
struct Icon *BKE_icon_get(int icon_id);
bool BKE_icon_is_preview(int icon_id);
bool BKE_icon_is_image(int icon_id);
/**
* Set icon for id if not already defined.
* Used for inserting the internal icons.

View File

@ -860,6 +860,18 @@ Icon *BKE_icon_get(const int icon_id)
return icon;
}
bool BKE_icon_is_preview(const int icon_id)
{
const Icon *icon = BKE_icon_get(icon_id);
return icon->obj_type == ICON_DATA_PREVIEW;
}
bool BKE_icon_is_image(const int icon_id)
{
const Icon *icon = BKE_icon_get(icon_id);
return icon->obj_type == ICON_DATA_IMBUF;
}
void BKE_icon_set(const int icon_id, Icon *icon)
{
void **val_p;

View File

@ -37,6 +37,7 @@ struct AssetHandle;
AssetRepresentationHandle *ED_asset_handle_get_representation(const struct AssetHandle *asset);
ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
int ED_asset_handle_get_preview_or_type_icon_id(const struct AssetHandle *asset);
void ED_asset_handle_get_full_library_path(
const struct AssetHandle *asset,
/* `1024` for #FILE_MAX,

View File

@ -66,6 +66,8 @@ blender::asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
const AssetLibraryReference &library_reference, int asset_index);
#endif
bool ED_assetlist_asset_image_is_loading(const AssetLibraryReference *library_reference,
const AssetHandle *asset_handle);
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
/**

View File

@ -18,6 +18,8 @@
#include "DNA_space_types.h"
#include "ED_fileselect.h"
#include "RNA_prototypes.h"
#include "ED_asset_handle.h"
@ -38,6 +40,11 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
return asset->file_data->preview_icon_id;
}
int ED_asset_handle_get_preview_or_type_icon_id(const AssetHandle *asset)
{
return ED_file_icon(asset->file_data);
}
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
char r_full_lib_path[FILE_MAX])
{

View File

@ -122,6 +122,7 @@ class AssetList : NonCopyable {
bool needsRefetch() const;
bool isLoaded() const;
bool isAssetPreviewLoading(const AssetHandle &asset) const;
asset_system::AssetLibrary *asset_library() const;
void iterate(AssetListHandleIterFn fn) const;
void iterate(AssetListIterFn fn) const;
@ -194,6 +195,11 @@ bool AssetList::isLoaded() const
return filelist_is_ready(filelist_);
}
bool AssetList::isAssetPreviewLoading(const AssetHandle &asset) const
{
return filelist_file_is_preview_pending(filelist_, asset.file_data);
}
asset_system::AssetLibrary *AssetList::asset_library() const
{
return reinterpret_cast<asset_system::AssetLibrary *>(filelist_asset_library(filelist_));
@ -533,6 +539,13 @@ asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
return reinterpret_cast<asset_system::AssetRepresentation *>(asset_handle.file_data->asset);
}
bool ED_assetlist_asset_image_is_loading(const AssetLibraryReference *library_reference,
const AssetHandle *asset_handle)
{
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
return list->isAssetPreviewLoading(*asset_handle);
}
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
{
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);

View File

@ -118,7 +118,12 @@ void AssetView::build_items()
const bool show_names = (shelf_.settings.display_flag & ASSETSHELF_SHOW_NAMES);
const StringRef identifier = asset->get_identifier().library_relative_identifier();
const int preview_id = ED_asset_handle_get_preview_icon_id(&asset_handle);
const int preview_id = [this, &asset_handle]() -> int {
if (ED_assetlist_asset_image_is_loading(&library_ref_, &asset_handle)) {
return ICON_TEMP;
}
return ED_asset_handle_get_preview_or_type_icon_id(&asset_handle);
}();
AssetViewItem &item = add_item<AssetViewItem>(
asset_handle, identifier, asset->get_name(), preview_id);

View File

@ -1191,13 +1191,18 @@ void ui_draw_preview_item(const uiFontStyle *fstyle,
/**
* Version of #ui_draw_preview_item() that does not draw the menu background and item text based on
* state. It just draws the preview and text directly.
*
* \param draw_as_icon: Instead of stretching the preview/icon to the available width/height, draw
* it at the standard icon size. Mono-icons will draw with \a text_col or the
* corresponding theme override for this type of icon.
*/
void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
const uchar text_col[4],
eFontStyle_Align text_align);
eFontStyle_Align text_align,
bool draw_as_icon = false);
#define UI_TEXT_MARGIN_X 0.4f
#define UI_POPUP_MARGIN (UI_SCALE_FAC * 12)

View File

@ -1344,6 +1344,32 @@ static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
}
}
static void widget_draw_icon_centered(const BIFIconID icon,
const float aspect,
const float alpha,
const rcti *rect,
const uchar mono_color[4])
{
if (icon == ICON_NONE) {
return;
}
const float size = ICON_DEFAULT_HEIGHT / (aspect * UI_INV_SCALE_FAC);
if (size > 0) {
const int x = BLI_rcti_cent_x(rect) - size / 2;
const int y = BLI_rcti_cent_y(rect) - size / 2;
const bTheme *btheme = UI_GetTheme();
const float desaturate = 1.0 - btheme->tui.icon_saturation;
uchar color[4] = {mono_color[0], mono_color[1], mono_color[2], mono_color[3]};
const bool has_theme = UI_icon_get_theme_color(int(icon), color);
UI_icon_draw_ex(
x, y, icon, aspect * UI_INV_SCALE_FAC, alpha, desaturate, color, has_theme, nullptr);
}
}
static int ui_but_draw_menu_icon(const uiBut *but)
{
return (but->flag & UI_BUT_ICON_SUBMENU) && (but->emboss == UI_EMBOSS_PULLDOWN);
@ -4202,8 +4228,17 @@ static void widget_preview_tile(uiBut *but,
widget_list_itembut(wcol, rect, state, roundboxalign, zoom);
}
ui_draw_preview_item_stateless(
&UI_style_get()->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER);
/* When the button is not tagged as having a preview icon, do regular icon drawing with the
* standard icon size. */
const bool draw_as_icon = !(but->flag & UI_BUT_ICON_PREVIEW);
ui_draw_preview_item_stateless(&UI_style_get()->widget,
rect,
but->drawstr,
but->icon,
wcol->text,
UI_STYLE_TEXT_CENTER,
draw_as_icon);
}
static void widget_optionbut(uiWidgetColors *wcol,
@ -5570,18 +5605,36 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
const char *name,
int iconid,
const uchar text_col[4],
eFontStyle_Align text_align)
eFontStyle_Align text_align,
bool draw_as_icon)
{
rcti trect = *rect;
const float text_size = UI_UNIT_Y;
const bool has_text = name && name[0];
float alpha = 1.0f;
{
/* Special handling: Previews often want to show a loading icon while the preview is being
* loaded. Draw this with reduced opacity. */
const bool is_loading_icon = iconid == ICON_TEMP;
if (is_loading_icon) {
alpha *= 0.5f;
draw_as_icon = true;
}
}
if (has_text) {
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
}
GPU_blend(GPU_BLEND_ALPHA);
widget_draw_preview(BIFIconID(iconid), 1.0f, rect);
if (draw_as_icon) {
widget_draw_icon_centered(BIFIconID(iconid), 1.0f, alpha, rect, text_col);
}
else {
widget_draw_preview(BIFIconID(iconid), alpha, rect);
}
GPU_blend(GPU_BLEND_NONE);
if (!has_text) {

View File

@ -9,6 +9,8 @@
#include <limits>
#include <stdexcept>
#include "BKE_icons.h"
#include "BLI_index_range.hh"
#include "WM_types.h"
@ -424,10 +426,16 @@ void PreviewGridItem::build_grid_tile(uiLayout &layout) const
0,
0,
"");
/* Draw icons that are not previews or images as normal icons with a fixed icon size. Otherwise
* they will be upscaled to the button size. Should probably be done by the widget code. */
const int is_preview_flag = (BKE_icon_is_preview(preview_icon_id) ||
BKE_icon_is_image(preview_icon_id)) ?
UI_BUT_ICON_PREVIEW :
JulianEisel marked this conversation as resolved Outdated

-Wextra warns: grid_view.cc:432:68: warning: enumerated and non-enumerated type in conditional expression. int(UI_BUT_ICON_PREVIEW).

`-Wextra` warns: `grid_view.cc:432:68: warning: enumerated and non-enumerated type in conditional expression`. `int(UI_BUT_ICON_PREVIEW)`.
0;
ui_def_but_icon(but,
preview_icon_id,
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
UI_HAS_ICON | is_preview_flag);
UI_but_func_tooltip_label_set(but, [this](const uiBut * /*but*/) { return label; });
but->emboss = UI_EMBOSS_NONE;
}

View File

@ -361,7 +361,7 @@ static void file_draw_preview(const FileList *files,
bool show_outline = !is_icon && (file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_OBJECT_IO |
FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
const bool is_offline = (file->attributes & FILE_ATTR_OFFLINE);
const bool is_loading = !filelist_is_ready(files) || file->flags & FILE_ENTRY_PREVIEW_LOADING;
const bool is_loading = filelist_file_is_preview_pending(files, file);
BLI_assert(imb != nullptr);

View File

@ -1160,6 +1160,14 @@ void filelist_file_get_full_path(const FileList *filelist,
BLI_path_join(r_filepath, FILE_MAX_LIBEXTRA, root, file->relpath);
}
bool filelist_file_is_preview_pending(const FileList *filelist, const FileDirEntry *file)
{
/* Actual preview loading is only started after the filelist is loaded, so the file isn't flagged
* with #FILE_ENTRY_PREVIEW_LOADING yet. */
const bool filelist_ready = filelist_is_ready(filelist);
return !filelist_ready || file->flags & FILE_ENTRY_PREVIEW_LOADING;
}
static FileDirEntry *filelist_geticon_get_file(FileList *filelist, const int index)
{
BLI_assert(G.background == false);

View File

@ -74,6 +74,7 @@ void filelist_free_icons(void);
void filelist_file_get_full_path(const FileList *filelist,
const FileDirEntry *file,
char r_filepath[/*FILE_MAX_LIBEXTRA*/]);
bool filelist_file_is_preview_pending(const FileList *filelist, const FileDirEntry *file);
ImBuf *filelist_getimage(FileList *filelist, int index);
ImBuf *filelist_file_getimage(const FileDirEntry *file);
ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);