[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 &notifier) 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