Merge branch 'blender-v4.3-release'

This commit is contained in:
Julian Eisel
2024-11-13 15:59:22 +01:00
8 changed files with 191 additions and 58 deletions

View File

@@ -69,7 +69,7 @@ void iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn)
*/
void storage_fetch(const AssetLibraryReference *library_reference, const bContext *C);
bool is_loaded(const AssetLibraryReference *library_reference);
void ensure_previews_job(const AssetLibraryReference *library_reference, const bContext *C);
void previews_fetch(const AssetLibraryReference *library_reference, const bContext *C);
/**
* Clears this asset library and the "All" asset library for reload in both the static asset list
* storage, as well as for all open asset browsers. Call this whenever the content of the given
@@ -109,6 +109,9 @@ asset_system::AssetRepresentation *asset_get_by_index(
bool asset_image_is_loading(const AssetLibraryReference *library_reference,
const AssetHandle *asset_handle);
void asset_preview_ensure_requested(const bContext &C,
const AssetLibraryReference *library_reference,
AssetHandle *asset_handle);
ImBuf *asset_image_get(const AssetHandle *asset_handle);
/**

View File

@@ -114,14 +114,16 @@ class AssetList : NonCopyable {
void setup();
void fetch(const bContext &C);
void ensure_previews_job(const bContext *C);
void update_previews(const bContext &C);
void clear(const bContext *C);
AssetHandle asset_get_by_index(int index) const;
void previews_job_update(const bContext *C);
bool needs_refetch() const;
bool is_loaded() const;
bool is_asset_preview_loading(const AssetHandle &asset) const;
void ensure_asset_preview_requested(const bContext &C, AssetHandle &asset);
asset_system::AssetLibrary *asset_library() const;
void iterate(AssetListHandleIterFn fn,
FunctionRef<bool(asset_system::AssetRepresentation &)> prefilter_fn) const;
@@ -156,6 +158,7 @@ void AssetList::setup()
true,
"",
"");
filelist_set_no_preview_auto_cache(files);
const bool use_asset_indexer = !USER_EXPERIMENTAL_TEST(&U, no_asset_indexing);
filelist_setindexer(files, use_asset_indexer ? &index::file_indexer_asset : &file_indexer_noop);
@@ -185,6 +188,16 @@ void AssetList::fetch(const bContext &C)
filelist_filter(files);
}
void AssetList::update_previews(const bContext &C)
{
if (filelist_cache_previews_enabled(filelist_)) {
/* Get newest loaded previews from the background thread queue. */
filelist_cache_previews_update(filelist_);
}
/* Update preview job, it might have to be stopped. */
this->previews_job_update(&C);
}
bool AssetList::needs_refetch() const
{
return filelist_needs_force_reset(filelist_) || filelist_needs_reading(filelist_);
@@ -195,6 +208,18 @@ bool AssetList::is_loaded() const
return filelist_is_ready(filelist_);
}
void AssetList::ensure_asset_preview_requested(const bContext &C, AssetHandle &asset)
{
/* Ensure previews are enabled. */
filelist_cache_previews_set(filelist_, true);
if (filelist_file_ensure_preview_requested(filelist_,
const_cast<FileDirEntry *>(asset.file_data)))
{
previews_timer_.ensure_running(&C);
}
}
bool AssetList::is_asset_preview_loading(const AssetHandle &asset) const
{
return filelist_file_is_preview_pending(filelist_, asset.file_data);
@@ -248,17 +273,14 @@ void AssetList::iterate(AssetListIterFn fn) const
}
}
void AssetList::ensure_previews_job(const bContext *C)
void AssetList::previews_job_update(const bContext *C)
{
FileList *files = filelist_;
int numfiles = filelist_files_ensure(files);
filelist_cache_previews_set(files, true);
/* TODO fetch all previews for now. */
/* Add one extra entry to ensure nothing is lost because of integer division. */
filelist_file_cache_slidingwindow_set(files, numfiles / 2 + 1);
filelist_file_cache_block(files, 0);
filelist_cache_previews_update(files);
if (!filelist_cache_previews_enabled(files)) {
previews_timer_.stop(C);
return;
}
{
const bool previews_running = filelist_cache_previews_running(files) &&
@@ -416,7 +438,7 @@ void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
switch (wmn->category) {
case NC_ASSET:
if (wmn->data == ND_ASSET_LIST_READING) {
if (ELEM(wmn->data, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
ED_region_tag_refresh_ui(region);
}
break;
@@ -453,11 +475,11 @@ bool is_loaded(const AssetLibraryReference *library_reference)
return list->is_loaded();
}
void ensure_previews_job(const AssetLibraryReference *library_reference, const bContext *C)
void previews_fetch(const AssetLibraryReference *library_reference, const bContext *C)
{
AssetList *list = lookup_list(*library_reference);
if (list) {
list->ensure_previews_job(C);
list->update_previews(*C);
}
}
@@ -552,6 +574,14 @@ bool asset_image_is_loading(const AssetLibraryReference *library_reference,
return list->is_asset_preview_loading(*asset_handle);
}
void asset_preview_ensure_requested(const bContext &C,
const AssetLibraryReference *library_reference,
AssetHandle *asset_handle)
{
AssetList *list = lookup_list(*library_reference);
list->ensure_asset_preview_requested(C, *asset_handle);
}
ImBuf *asset_image_get(const AssetHandle *asset_handle)
{
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);

View File

@@ -65,7 +65,7 @@ class AssetViewItem : public ui::PreviewGridItem {
int preview_icon_id);
void disable_asset_drag();
void build_grid_tile(uiLayout &layout) const override;
void build_grid_tile(const bContext &C, uiLayout &layout) const override;
void build_context_menu(bContext &C, uiLayout &column) const override;
std::optional<bool> should_be_active() const override;
void on_activate(bContext &C) override;
@@ -111,12 +111,7 @@ void AssetView::build_items()
const bool show_names = (shelf_.settings.display_flag & ASSETSHELF_SHOW_NAMES);
const StringRef identifier = asset->library_relative_identifier();
const int preview_id = [&]() -> int {
if (list::asset_image_is_loading(&library_ref_, &asset_handle)) {
return ICON_TEMP;
}
return handle_get_preview_or_type_icon_id(&asset_handle);
}();
const int preview_id = handle_get_preview_or_type_icon_id(&asset_handle);
AssetViewItem &item = this->add_item<AssetViewItem>(
asset_handle, identifier, asset->get_name(), preview_id);
@@ -220,7 +215,7 @@ static std::optional<wmOperatorCallParams> create_activate_operator_params(
return wmOperatorCallParams{ot, op_props, WM_OP_INVOKE_REGION_WIN};
}
void AssetViewItem::build_grid_tile(uiLayout &layout) const
void AssetViewItem::build_grid_tile(const bContext &C, uiLayout &layout) const
{
const AssetView &asset_view = reinterpret_cast<const AssetView &>(this->get_view());
const AssetShelfType &shelf_type = *asset_view.shelf_.type;
@@ -263,7 +258,20 @@ void AssetViewItem::build_grid_tile(uiLayout &layout) const
const_cast<asset_system::AssetRepresentation *>(asset),
nullptr);
ui::PreviewGridItem::build_grid_tile_button(layout);
/* Request preview when drawing. Grid views have an optimization to only draw items that are
* actually visible, so only previews scrolled into view will be loaded this way. This reduces
* total loading time and memory footprint. */
list::asset_preview_ensure_requested(
C, &asset_view.library_ref_, const_cast<AssetHandle *>(&asset_));
const int preview_id = [&]() -> int {
if (list::asset_image_is_loading(&asset_view.library_ref_, &asset_)) {
return ICON_TEMP;
}
return handle_get_preview_or_type_icon_id(&asset_);
}();
ui::PreviewGridItem::build_grid_tile_button(layout, preview_id);
}
void AssetViewItem::build_context_menu(bContext &C, uiLayout &column) const
@@ -341,7 +349,7 @@ void build_asset_view(uiLayout &layout,
const ARegion &region)
{
list::storage_fetch(&library_ref, &C);
list::ensure_previews_job(&library_ref, &C);
list::previews_fetch(&library_ref, &C);
const asset_system::AssetLibrary *library = list::library_get_once_available(library_ref);
if (!library) {
@@ -363,7 +371,7 @@ void build_asset_view(uiLayout &layout,
grid_view->set_context_menu_title("Asset Shelf");
ui::GridViewBuilder builder(*block);
builder.build_grid_view(*grid_view, region.v2d, layout, filter_string_get(shelf));
builder.build_grid_view(C, *grid_view, region.v2d, layout, filter_string_get(shelf));
}
/* ---------------------------------------------------------------------- */

View File

@@ -45,7 +45,7 @@ class AbstractGridViewItem : public AbstractViewItem {
public:
/* virtual */ ~AbstractGridViewItem() override = default;
virtual void build_grid_tile(uiLayout &layout) const = 0;
virtual void build_grid_tile(const bContext &C, uiLayout &layout) const = 0;
/* virtual */ std::optional<std::string> debug_name() const override;
@@ -170,7 +170,8 @@ class GridViewBuilder {
public:
GridViewBuilder(uiBlock &block);
void build_grid_view(AbstractGridView &grid_view,
void build_grid_view(const bContext &C,
AbstractGridView &grid_view,
const View2D &v2d,
uiLayout &layout,
std::optional<StringRef> search_string = {});
@@ -206,9 +207,10 @@ class PreviewGridItem : public AbstractGridViewItem {
PreviewGridItem(StringRef identifier, StringRef label, int preview_icon_id);
void build_grid_tile(uiLayout &layout) const override;
void build_grid_tile(const bContext &C, uiLayout &layout) const override;
void build_grid_tile_button(uiLayout &layout) const;
void build_grid_tile_button(uiLayout &layout,
BIFIconID override_preview_icon_id = ICON_NONE) const;
/**
* Set a custom callback to execute when activating this view item. This way users don't have to

View File

@@ -62,7 +62,7 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
}
static void asset_view_draw_item(uiList *ui_list,
const bContext * /*C*/,
const bContext *C,
uiLayout *layout,
PointerRNA * /*dataptr*/,
PointerRNA * /*itemptr*/,
@@ -82,6 +82,8 @@ static void asset_view_draw_item(uiList *ui_list,
const_cast<FileDirEntry *>(asset_handle.file_data));
uiLayoutSetContextPointer(layout, "active_file", &file_ptr);
asset::list::asset_preview_ensure_requested(*C, &list_data->asset_library_ref, &asset_handle);
uiBlock *block = uiLayoutGetBlock(layout);
const bool show_names = list_data->show_names;
const float size_x = UI_preview_tile_size_x();
@@ -252,7 +254,7 @@ void uiTemplateAssetView(uiLayout *layout,
}
asset::list::storage_fetch(&asset_library_ref, C);
asset::list::ensure_previews_job(&asset_library_ref, C);
asset::list::previews_fetch(&asset_library_ref, C);
const int tot_items = asset::list::size(&asset_library_ref);
populate_asset_collection(asset_library_ref, *assets_dataptr, assets_propname);

View File

@@ -368,10 +368,12 @@ class GridViewLayoutBuilder {
public:
GridViewLayoutBuilder(uiLayout &layout);
void build_from_view(const AbstractGridView &grid_view, const View2D &v2d) const;
void build_from_view(const bContext &C,
const AbstractGridView &grid_view,
const View2D &v2d) const;
private:
void build_grid_tile(uiLayout &grid_layout, AbstractGridViewItem &item) const;
void build_grid_tile(const bContext &C, uiLayout &grid_layout, AbstractGridViewItem &item) const;
uiLayout *current_layout() const;
};
@@ -380,17 +382,19 @@ GridViewLayoutBuilder::GridViewLayoutBuilder(uiLayout &layout) : block_(*uiLayou
{
}
void GridViewLayoutBuilder::build_grid_tile(uiLayout &grid_layout,
void GridViewLayoutBuilder::build_grid_tile(const bContext &C,
uiLayout &grid_layout,
AbstractGridViewItem &item) const
{
uiLayout *overlap = uiLayoutOverlap(&grid_layout);
uiLayoutSetFixedSize(overlap, true);
item.add_grid_tile_button(block_);
item.build_grid_tile(*uiLayoutRow(overlap, false));
item.build_grid_tile(C, *uiLayoutRow(overlap, false));
}
void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view,
void GridViewLayoutBuilder::build_from_view(const bContext &C,
const AbstractGridView &grid_view,
const View2D &v2d) const
{
uiLayout *parent_layout = this->current_layout();
@@ -428,7 +432,7 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view,
row = uiLayoutRow(&layout, true);
}
this->build_grid_tile(*row, item);
this->build_grid_tile(C, *row, item);
item_idx++;
});
@@ -446,7 +450,8 @@ uiLayout *GridViewLayoutBuilder::current_layout() const
GridViewBuilder::GridViewBuilder(uiBlock & /*block*/) {}
void GridViewBuilder::build_grid_view(AbstractGridView &grid_view,
void GridViewBuilder::build_grid_view(const bContext &C,
AbstractGridView &grid_view,
const View2D &v2d,
uiLayout &layout,
std::optional<StringRef> search_string)
@@ -462,7 +467,7 @@ void GridViewBuilder::build_grid_view(AbstractGridView &grid_view,
UI_block_layout_set_current(&block, &layout);
GridViewLayoutBuilder builder(layout);
builder.build_from_view(grid_view, v2d);
builder.build_from_view(C, grid_view, v2d);
}
/* ---------------------------------------------------------------------- */
@@ -472,7 +477,8 @@ PreviewGridItem::PreviewGridItem(StringRef identifier, StringRef label, int prev
{
}
void PreviewGridItem::build_grid_tile_button(uiLayout &layout) const
void PreviewGridItem::build_grid_tile_button(uiLayout &layout,
BIFIconID override_preview_icon_id) const
{
const GridViewStyle &style = this->get_view().get_style();
uiBlock *block = uiLayoutGetBlock(&layout);
@@ -493,20 +499,21 @@ void PreviewGridItem::build_grid_tile_button(uiLayout &layout) const
0,
"");
const BIFIconID icon_id = override_preview_icon_id ? override_preview_icon_id : preview_icon_id;
/* 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)) ?
const int is_preview_flag = (BKE_icon_is_preview(icon_id) || BKE_icon_is_image(icon_id)) ?
int(UI_BUT_ICON_PREVIEW) :
0;
ui_def_but_icon(but,
preview_icon_id,
icon_id,
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
UI_HAS_ICON | is_preview_flag);
but->emboss = UI_EMBOSS_NONE;
}
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
void PreviewGridItem::build_grid_tile(const bContext & /*C*/, uiLayout &layout) const
{
this->build_grid_tile_button(layout);
}

View File

@@ -303,6 +303,12 @@ enum {
FL_NEED_SORTING = 1 << 4,
FL_NEED_FILTERING = 1 << 5,
FL_SORT_INVERT = 1 << 6,
/**
* By default, #filelist_file_cache_block() will attempt to load previews around the visible
* "window" of visible files. When this flag is set it won't do so, and each preview has to be
* queried through a #filelist_cache_previews_push() call.
*/
FL_PREVIEWS_NO_AUTO_CACHE = 1 << 7,
};
/** #FileList.tags */
@@ -353,6 +359,8 @@ static int groupname_to_code(const char *group);
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
static bool filelist_intern_entry_is_main_file(const FileListInternEntry *intern_entry);
static bool filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index);
static bool filelist_file_preview_load_poll(const FileDirEntry *entry);
/* ********** Sort helpers ********** */
@@ -1157,6 +1165,35 @@ bool filelist_file_is_preview_pending(const FileList *filelist, const FileDirEnt
return !filelist_ready || file->flags & FILE_ENTRY_PREVIEW_LOADING;
}
bool filelist_file_ensure_preview_requested(FileList *filelist, FileDirEntry *file)
{
if (file->preview_icon_id) {
/* Already loaded. */
return false;
}
/* Wait with requests until file list reading is done, and previews may be loaded. */
if (!filelist_cache_previews_enabled(filelist)) {
return false;
}
/* #filelist_cache_previews_push() will repeat this, do here already to avoid lookup below. */
if (!filelist_file_preview_load_poll(file)) {
return false;
}
const int numfiles = filelist_files_ensure(filelist);
for (int i = 0; i < numfiles; i++) {
if (filelist->filelist_intern.filtered[i]->uid == file->uid) {
if (filelist_cache_previews_push(filelist, file, i)) {
return true;
}
break;
}
}
return false;
}
static FileDirEntry *filelist_geticon_get_file(FileList *filelist, const int index)
{
BLI_assert(G.background == false);
@@ -1620,25 +1657,22 @@ static void filelist_cache_previews_free(FileListEntryCache *cache)
cache->flags &= ~FLC_PREVIEWS_ACTIVE;
}
static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index)
/**
* Check if a preview for \a entry may be requested. Further conditions may apply, this just helps
* to skip plenty of entries where it's easy to tell that no valid preview will be available or is
* being loaded already.
*/
static bool filelist_file_preview_load_poll(const FileDirEntry *entry)
{
FileListEntryCache *cache = &filelist->filelist_cache;
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
if (entry->preview_icon_id) {
return;
}
if (entry->flags & (FILE_ENTRY_INVALID_PREVIEW | FILE_ENTRY_PREVIEW_LOADING)) {
return;
return false;
}
if (!(entry->typeflag &
(FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_OBJECT_IO |
FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)))
{
return;
return false;
}
/* If we know this is an external ID without a preview, skip loading the preview. Can save quite
@@ -1647,21 +1681,42 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
if ((entry->typeflag & FILE_TYPE_BLENDERLIB) &&
(entry->flags & FILE_ENTRY_BLENDERLIB_NO_PREVIEW))
{
return;
return false;
}
/* External ID that is also a directory is never previewed. */
if ((entry->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR)) ==
(FILE_TYPE_BLENDERLIB | FILE_TYPE_DIR))
{
return;
return false;
}
return true;
}
/**
* \return True if a new preview request was pushed, false otherwise (e.g. because the preview is
* already loaded, invalid or not supported).
*/
static bool filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index)
{
FileListEntryCache *cache = &filelist->filelist_cache;
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
if (entry->preview_icon_id) {
return false;
}
if (!filelist_file_preview_load_poll(entry)) {
return false;
}
FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index];
PreviewImage *preview_in_memory = intern_entry->local_data.preview_image;
if (preview_in_memory && !BKE_previewimg_is_finished(preview_in_memory, ICON_SIZE_PREVIEW)) {
/* Nothing to set yet. Wait for next call. */
return;
return false;
}
filelist_cache_preview_ensure_running(cache);
@@ -1701,6 +1756,8 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
filelist_cache_preview_freef);
}
cache->previews_todo_count++;
return true;
}
static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
@@ -2057,6 +2114,11 @@ void filelist_setrecursion(FileList *filelist, const int recursion_level)
}
}
void filelist_set_no_preview_auto_cache(FileList *filelist)
{
filelist->flags |= FL_PREVIEWS_NO_AUTO_CACHE;
}
bool filelist_needs_force_reset(const FileList *filelist)
{
return (filelist->flags & (FL_FORCE_RESET | FL_FORCE_RESET_MAIN_FILES)) != 0;
@@ -2555,7 +2617,7 @@ bool filelist_file_cache_block(FileList *filelist, const int index)
// printf("Re-queueing previews...\n");
if (cache->flags & FLC_PREVIEWS_ACTIVE) {
if ((cache->flags & FLC_PREVIEWS_ACTIVE) && !(filelist->flags & FL_PREVIEWS_NO_AUTO_CACHE)) {
/* Note we try to preview first images around given index - i.e. assumed visible ones. */
int block_index = cache->block_cursor + (index - start_index);
int offs_max = max_ii(end_index - index, index - start_index);
@@ -2578,6 +2640,11 @@ bool filelist_file_cache_block(FileList *filelist, const int index)
return true;
}
bool filelist_cache_previews_enabled(const FileList *filelist)
{
return (filelist->filelist_cache.flags & FLC_PREVIEWS_ACTIVE) != 0;
}
void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
{
FileListEntryCache *cache = &filelist->filelist_cache;
@@ -2603,6 +2670,11 @@ void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
}
}
void filelist_cache_previews_ensure_running(FileList *filelist)
{
filelist_cache_preview_ensure_running(&filelist->filelist_cache);
}
bool filelist_cache_previews_update(FileList *filelist)
{
FileListEntryCache *cache = &filelist->filelist_cache;

View File

@@ -78,6 +78,11 @@ 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);
/**
* \return True if a new preview request was pushed, false otherwise (e.g. because the preview is
* already loaded, invalid or not supported).
*/
bool filelist_file_ensure_preview_requested(FileList *filelist, FileDirEntry *file);
ImBuf *filelist_getimage(FileList *filelist, int index);
ImBuf *filelist_file_getimage(const FileDirEntry *file);
ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
@@ -163,6 +168,8 @@ void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_siz
*/
bool filelist_file_cache_block(FileList *filelist, int index);
void filelist_set_no_preview_auto_cache(FileList *filelist);
bool filelist_needs_force_reset(const FileList *filelist);
void filelist_tag_force_reset(FileList *filelist);
void filelist_tag_force_reset_mainfiles(FileList *filelist);
@@ -221,7 +228,9 @@ void filelist_readjob_start(FileList *filelist, int space_notifier, const bConte
void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm);
int filelist_readjob_running(FileList *filelist, wmWindowManager *wm);
void filelist_cache_previews_ensure_running(FileList *filelist);
bool filelist_cache_previews_update(FileList *filelist);
bool filelist_cache_previews_enabled(const FileList *filelist);
void filelist_cache_previews_set(FileList *filelist, bool use_previews);
bool filelist_cache_previews_running(FileList *filelist);
bool filelist_cache_previews_done(FileList *filelist);