[Bf-blender-cvs] [3d706bb0f3d] ui-asset-view-template: Do proper updates when local asset data changes
Julian Eisel
noreply at git.blender.org
Thu Mar 11 18:14:49 CET 2021
Commit: 3d706bb0f3dd04f7f1d01dbe008463648a6f66f2
Author: Julian Eisel
Date: Thu Mar 11 18:05:18 2021 +0100
Branches: ui-asset-view-template
https://developer.blender.org/rB3d706bb0f3dd04f7f1d01dbe008463648a6f66f2
Do proper updates when local asset data changes
Makes sure the asset list is updated and redrawn correctly an local asset data
changes: Creating assets, removing assets, clearing assets, undo/redo, reading
files (with and without UI), parallel reading of asset data from files, ...
For redraws there now is a listener callback in the uiList type (C only) that
asks the asset lists if it needs a redraw after a given notifier. For the case
of asset data-block removal there is a ID remapping function in the asset list
now (just tags the list for a complete re-read). File reading, undo, redo and
the "Mark Asset"/"Clear Asset" operators explicitly tag asset lists showing
main data as dirty (via the global asset storage).
===================================================================
M source/blender/blenkernel/BKE_screen.h
M source/blender/blenkernel/intern/screen.c
M source/blender/editors/asset/asset_edit.cc
M source/blender/editors/asset/asset_list.cc
M source/blender/editors/include/ED_asset.h
M source/blender/editors/include/UI_interface.h
M source/blender/editors/interface/interface_template_asset_view.cc
M source/blender/editors/interface/interface_templates.c
M source/blender/editors/screen/area.c
M source/blender/editors/space_file/filelist.c
M source/blender/editors/space_file/filelist.h
M source/blender/editors/space_file/space_file.c
M source/blender/editors/undo/ed_undo.c
M source/blender/editors/util/ed_util.c
M source/blender/makesdna/DNA_screen_types.h
M source/blender/windowmanager/WM_types.h
M source/blender/windowmanager/intern/wm_event_system.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 085851ba5e6..2e6493a2fcb 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -332,6 +332,9 @@ typedef void (*uiListFilterItemsFunc)(struct uiList *ui_list,
struct PointerRNA *,
const char *propname);
+/* Listen to notifiers. Only for lists defined in C. */
+typedef void (*uiListListener)(struct uiList *ui_list, wmRegionListenerParams *params);
+
typedef struct uiListType {
struct uiListType *next, *prev;
@@ -341,6 +344,9 @@ typedef struct uiListType {
uiListDrawFilterFunc draw_filter;
uiListFilterItemsFunc filter_items;
+ /* For lists defined in C only. */
+ uiListListener listener;
+
/* RNA integration */
ExtensionRNA rna_ext;
} uiListType;
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index fd7f1acb456..5cd3659877e 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -683,6 +683,9 @@ void BKE_area_region_free(SpaceType *st, ARegion *region)
if (dyn_data->items_filter_neworder) {
MEM_freeN(dyn_data->items_filter_neworder);
}
+ if (dyn_data->customdata) {
+ MEM_freeN(dyn_data->customdata);
+ }
MEM_freeN(dyn_data);
}
if (uilst->properties) {
diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc
index 2f9bd60edcb..5681807e0aa 100644
--- a/source/blender/editors/asset/asset_edit.cc
+++ b/source/blender/editors/asset/asset_edit.cc
@@ -46,6 +46,9 @@ bool ED_asset_mark_id(const bContext *C, ID *id)
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
+ /* Important for asset storage to update properly! */
+ ED_assetlist_storage_tag_main_data_dirty();
+
return true;
}
@@ -58,6 +61,9 @@ bool ED_asset_clear_id(ID *id)
/* Don't clear fake user here, there's no guarantee that it was actually set by
* #ED_asset_mark_id(), it might have been something/someone else. */
+ /* Important for asset storage to update properly! */
+ ED_assetlist_storage_tag_main_data_dirty();
+
return true;
}
diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc
index 821d1577e0c..356c6dc1d33 100644
--- a/source/blender/editors/asset/asset_list.cc
+++ b/source/blender/editors/asset/asset_list.cc
@@ -25,6 +25,8 @@
#include <optional>
+#include "BKE_screen.h"
+
#include "BLI_function_ref.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
@@ -36,6 +38,7 @@
#include "ED_asset.h"
#include "ED_fileselect.h"
+#include "ED_screen.h"
/* XXX uses private header of file-space. */
#include "../space_file/filelist.h"
@@ -131,15 +134,6 @@ class AssetList {
&U, library_ref_.custom_library_index);
}
- char path[FILE_MAXDIR] = "";
- if (user_library) {
- BLI_strncpy(path, user_library->path, sizeof(path));
- filelist_setdir(files, path);
- }
- else {
- filelist_setdir(files, path);
- }
-
/* Relevant bits from file_refresh(). */
/* TODO pass options properly. */
filelist_setrecursion(files, 1);
@@ -151,7 +145,7 @@ class AssetList {
* the plan to separate the view (preview caching, filtering, etc. ) from the data. */
filelist_setfilter_options(
files,
- true,
+ filter_settings != nullptr,
true,
true, /* Just always hide parent, prefer to not add an extra user option for this. */
FILE_TYPE_BLENDERLIB,
@@ -159,21 +153,40 @@ class AssetList {
true,
"",
"");
+
+ char path[FILE_MAXDIR] = "";
+ if (user_library) {
+ BLI_strncpy(path, user_library->path, sizeof(path));
+ filelist_setdir(files, path);
+ }
+ else {
+ filelist_setdir(files, path);
+ }
}
void fetch(const bContext &C)
{
FileList *files = filelist_.get();
+ if (filelist_needs_force_reset(files)) {
+ filelist_readjob_stop(CTX_wm_manager(&C), CTX_data_scene(&C));
+ filelist_clear(files);
+ }
+
if (filelist_needs_reading(files)) {
if (!filelist_pending(files)) {
- filelist_readjob_start(files, &C);
+ filelist_readjob_start(files, NC_ASSET | ND_ASSET_LIST_READING, &C);
}
}
filelist_sort(files);
filelist_filter(files);
}
+ bool needsRefetch() const
+ {
+ return filelist_needs_force_reset(filelist_.get());
+ }
+
void iterate(AssetListIterFn fn)
{
FileList *files = filelist_.get();
@@ -202,9 +215,8 @@ class AssetList {
{
const bool previews_running = filelist_cache_previews_running(files);
if (previews_running && !previews_timer) {
- /* TODO NC_WINDOW_to force full redraw. */
previews_timer = WM_event_add_timer_notifier(
- CTX_wm_manager(C), CTX_wm_window(C), NC_WINDOW, 0.01);
+ CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01);
}
if (!previews_running && previews_timer) {
/* Preview is not running, no need to keep generating update events! */
@@ -214,6 +226,44 @@ class AssetList {
}
}
+ /**
+ * \return True if the asset-list needs a UI redraw.
+ */
+ bool listen(const wmNotifier ¬ifier) const
+ {
+ switch (notifier.category) {
+ case NC_ASSET:
+ if (ELEM(notifier.data, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
+ return true;
+ }
+ if (ELEM(notifier.action, NA_ADDED, NA_REMOVED)) {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
+ void tagMainDataDirty() const
+ {
+ FileList *files = filelist_.get();
+
+ if (filelist_needs_reset_on_main_changes(files)) {
+ /* Full refresh of the file list if local asset data was changed. Refreshing this view
+ * is cheap and users expect this to be updated immediately. */
+ filelist_tag_force_reset(files);
+ }
+ }
+
+ void remapID(ID * /*id_old*/, ID * /*id_new*/) const
+ {
+ /* Trigger full refetch of the file list if main data was changed, don't even attempt remap
+ * pointers. We could give file list types a id-remap callback, but it's probably not worth it.
+ * Refreshing local file lists is relatively cheap. */
+ tagMainDataDirty();
+ }
+
blender::StringRef filepath()
{
return filelist_dir(filelist_.get());
@@ -246,7 +296,7 @@ class AssetListStorage {
std::tuple list_create_info = ensure_list_storage(library_reference, *filesel_type);
AssetList &list = std::get<0>(list_create_info);
const bool is_new = std::get<1>(list_create_info);
- if (is_new) {
+ if (is_new || list.needsRefetch()) {
list.setup(filter_settings);
list.fetch(C);
}
@@ -262,6 +312,20 @@ class AssetListStorage {
return global_storage_.lookup_ptr(library_ref);
}
+ static void tagMainDataDirty()
+ {
+ for (AssetList &list : global_storage_.values()) {
+ list.tagMainDataDirty();
+ }
+ }
+
+ static void remapID(ID *id_new, ID *id_old)
+ {
+ for (AssetList &list : global_storage_.values()) {
+ list.remapID(id_new, id_old);
+ }
+ }
+
private:
/* Private constructor. Can't instantiate this. */
AssetListStorage() = default;
@@ -319,11 +383,6 @@ void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_refer
}
}
-void ED_assetlist_storage_exit()
-{
- AssetListStorage::destruct();
-}
-
/* TODO expose AssetList with an iterator? */
void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn)
{
@@ -352,4 +411,47 @@ const char *ED_assetlist_library_path(const AssetLibraryReference *library_refer
return nullptr;
}
+/**
+ * \return True if the region needs a UI redraw.
+ */
+bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
+ const wmNotifier *notifier)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ return list->listen(*notifier);
+ }
+ return false;
+}
+
+/**
+ * Tag all asset lists in the storage that show main data as needing an update (refetch).
+ *
+ * This only tags the data. If the asset list is visible on screen, the space is still responsible
+ * for ensuring the necessary redraw. It can use #ED_assetlist_listen() to check if the asset-list
+ * needs a redraw for a given notifier.
+ */
+void ED_assetlist_storage_tag_main_data_dirty()
+{
+ AssetListStorage::tagMainDataDirty();
+}
+
+/**
+ * Remapping of ID pointers within the asset lists. Typically called when an ID is deleted to clear
+ * all references to it (\a id_new is null then).
+ */
+void ED_assetlist_storage_id_remap(ID *id_old, ID *id_new)
+{
+ AssetListStorage::remapID(id_old, id_new);
+}
+
+/**
+ * Can't wait for static deallocation to run. There's nested data allocated with our guarded
+ * allocator, it will complain about unfreed memory on exit.
+ */
+void ED_assetlist_storage_exit()
+{
+ AssetListStorage::destruct();
+}
+
/** \} */
diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h
index 29de8fb93e7..65b1c690491 100644
--- a/source/blender/editors/include/ED_asset.h
+++ b/source/blender/editors/include/ED_asset.h
@@ -24,7 +24,10 @@
extern "C" {
#endif
+struct AssetFilterSettings;
struct AssetLibraryReference;
+struct bContext;
+struct wmNotifier;
bool ED_asset_mark_id(const struct bContext *C, struct ID *id);
bool ED_asset_clear_id(struct ID *id);
@@ -32,18 +35,23 @@ bool ED_asset_clear_id(struct ID *id);
bool ED_asset_can_make_single_from_context(const struct bContext *C);
int ED_asset_library_reference_to_enum_value(const struct AssetLibraryReference *library);
-AssetLibraryReference ED_asset_library_reference_from_enum_value(int value);
+struct AssetLibraryReference ED_asset_library_reference_from_enum_value(int value);
void ED_assetlist_fetch(const struct AssetLibraryReference *library_reference,
const struct AssetFilterSettings *filter_settings,
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list