[Bf-blender-cvs] [a26a059244f] master: Assets: Initial Asset List as part of the Asset System design

Julian Eisel noreply at git.blender.org
Thu Jul 15 16:14:25 CEST 2021


Commit: a26a059244f247a85c48a28dedeb4a551110c793
Author: Julian Eisel
Date:   Fri Jul 9 12:56:26 2021 +0200
Branches: master
https://developer.blender.org/rBa26a059244f247a85c48a28dedeb4a551110c793

Assets: Initial Asset List as part of the Asset System design

Implements a basic, WIP version of the asset list. This is needed to
give the asset view UI template asset reading and displaying
functionality.

See:
* Asset System: Data Storage, Reading & UI Access - https://developer.blender.org/T88184

Especially the asset list internals should change. It uses the
File/Asset Browser's `FileList` API, which isn't really meant for access
from outside the File Browser. But as explained in T88184, it does a lot
of the stuff we currently need, so we (Sybren Stüvel and I) decided to
go this route for now. Work on a file-list rewrite which integrates well
with the asset system started in the `asset-system-filelist` branch.

Further includes:
* Operator to reload the asset list.
* New `bpy.types.AssetHandle.get_full_library_path()` function, which
  gets the full path of the asset via the asset-list.
* Changes to preview loading to prevent the preview loading job to run
  eternally for asset views. File Browsers have this issue too, but
  should be fixed separately.

===================================================================

M	source/blender/editors/asset/CMakeLists.txt
M	source/blender/editors/asset/asset_edit.cc
A	source/blender/editors/asset/asset_list.cc
M	source/blender/editors/asset/asset_ops.cc
M	source/blender/editors/include/ED_asset.h
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/editors/util/ed_util_ops.cc
M	source/blender/makesdna/DNA_asset_types.h
M	source/blender/makesrna/intern/rna_asset.c
M	source/blender/makesrna/intern/rna_space.c
M	source/blender/makesrna/intern/rna_workspace.c
M	source/blender/windowmanager/WM_types.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_init_exit.c

===================================================================

diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
index 794e64fa420..d87879bea2a 100644
--- a/source/blender/editors/asset/CMakeLists.txt
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -31,11 +31,13 @@ set(INC_SYS
 
 set(SRC
   asset_edit.cc
+  asset_list.cc
   asset_ops.cc
 )
 
 set(LIB
   bf_blenloader
+  bf_blenkernel
 )
 
 blender_add_lib(bf_editor_asset "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc
index 949dc1890ad..0937af0dbf1 100644
--- a/source/blender/editors/asset/asset_edit.cc
+++ b/source/blender/editors/asset/asset_edit.cc
@@ -18,10 +18,15 @@
  * \ingroup edasset
  */
 
+#include <memory>
+#include <string>
+
 #include "BKE_asset.h"
 #include "BKE_context.h"
 #include "BKE_lib_id.h"
 
+#include "BLO_readfile.h"
+
 #include "DNA_ID.h"
 #include "DNA_asset_types.h"
 #include "DNA_space_types.h"
@@ -32,6 +37,8 @@
 
 #include "ED_asset.h"
 
+using namespace blender;
+
 bool ED_asset_mark_id(const bContext *C, ID *id)
 {
   if (id->asset_data) {
@@ -47,6 +54,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;
 }
 
@@ -59,6 +69,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;
 }
 
@@ -125,3 +138,18 @@ const char *ED_asset_handle_get_name(const AssetHandle *asset)
 {
   return asset->file_data->name;
 }
+
+void ED_asset_handle_get_full_library_path(const bContext *C,
+                                           const AssetLibraryReference *asset_library,
+                                           const AssetHandle *asset,
+                                           char r_full_lib_path[FILE_MAX_LIBEXTRA])
+{
+  *r_full_lib_path = '\0';
+
+  std::string asset_path = ED_assetlist_asset_filepath_get(C, *asset_library, *asset);
+  if (asset_path.empty()) {
+    return;
+  }
+
+  BLO_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr);
+}
diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc
new file mode 100644
index 00000000000..1ea948d97d4
--- /dev/null
+++ b/source/blender/editors/asset/asset_list.cc
@@ -0,0 +1,637 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edasset
+ *
+ * Abstractions to manage runtime asset lists with a global cache for multiple UI elements to
+ * access.
+ * Internally this uses the #FileList API and structures from `filelist.c`. This is just because it
+ * contains most necessary logic already and there's not much time for a more long-term solution.
+ */
+
+#include <optional>
+#include <string>
+
+#include "BKE_asset.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "BLI_function_ref.hh"
+#include "BLI_hash.hh"
+#include "BLI_map.hh"
+#include "BLI_path_util.h"
+#include "BLI_utility_mixins.hh"
+
+#include "DNA_asset_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_preferences.h"
+
+#include "ED_asset.h"
+#include "ED_fileselect.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* XXX uses private header of file-space. */
+#include "../space_file/filelist.h"
+
+using namespace blender;
+
+/**
+ * Wrapper to add logic to the AssetLibraryReference DNA struct.
+ */
+class AssetLibraryReferenceWrapper {
+  const AssetLibraryReference reference_;
+
+ public:
+  /* Intentionally not `explicit`, allow implicit conversion for convienience. Might have to be
+   * NOLINT */
+  AssetLibraryReferenceWrapper(const AssetLibraryReference &reference);
+  ~AssetLibraryReferenceWrapper() = default;
+
+  friend bool operator==(const AssetLibraryReferenceWrapper &a,
+                         const AssetLibraryReferenceWrapper &b);
+  uint64_t hash() const;
+};
+
+AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference)
+    : reference_(reference)
+{
+}
+
+bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b)
+{
+  return (a.reference_.type == b.reference_.type) && (a.reference_.type == ASSET_LIBRARY_CUSTOM) ?
+             (a.reference_.custom_library_index == b.reference_.custom_library_index) :
+             true;
+}
+
+uint64_t AssetLibraryReferenceWrapper::hash() const
+{
+  uint64_t hash1 = DefaultHash<decltype(reference_.type)>{}(reference_.type);
+  if (reference_.type != ASSET_LIBRARY_CUSTOM) {
+    return hash1;
+  }
+
+  uint64_t hash2 = DefaultHash<decltype(reference_.custom_library_index)>{}(
+      reference_.custom_library_index);
+  return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Asset list API
+ *
+ *  Internally re-uses #FileList from the File Browser. It does all the heavy lifting already.
+ * \{ */
+
+/**
+ * RAII wrapper for `FileList`
+ */
+class FileListWrapper {
+  static void filelist_free_fn(FileList *list)
+  {
+    filelist_free(list);
+    MEM_freeN(list);
+  }
+
+  std::unique_ptr<FileList, decltype(&filelist_free_fn)> file_list_;
+
+ public:
+  explicit FileListWrapper(eFileSelectType filesel_type)
+      : file_list_(filelist_new(filesel_type), filelist_free_fn)
+  {
+  }
+  FileListWrapper(FileListWrapper &&other) = default;
+  FileListWrapper &operator=(FileListWrapper &&other) = default;
+  ~FileListWrapper()
+  {
+    /* Destructs the owned pointer. */
+    file_list_ = nullptr;
+  }
+
+  operator FileList *() const
+  {
+    return file_list_.get();
+  }
+};
+
+class PreviewTimer {
+  /* Non-owning! The Window-Manager registers and owns this. */
+  wmTimer *timer_ = nullptr;
+
+ public:
+  void ensureRunning(const bContext *C)
+  {
+    if (!timer_) {
+      timer_ = WM_event_add_timer_notifier(
+          CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01);
+    }
+  }
+
+  void stop(const bContext *C)
+  {
+    if (timer_) {
+      WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), timer_);
+      timer_ = nullptr;
+    }
+  }
+};
+
+class AssetList : NonCopyable {
+  FileListWrapper filelist_;
+  AssetLibraryReference library_ref_;
+  PreviewTimer previews_timer_;
+
+ public:
+  AssetList() = delete;
+  AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref);
+  AssetList(AssetList &&other) = default;
+  ~AssetList() = default;
+
+  void setup(const AssetFilterSettings *filter_settings = nullptr);
+  void fetch(const bContext &C);
+  void ensurePreviewsJob(bContext *C);
+  void clear(bContext *C);
+
+  bool needsRefetch() const;
+  void iterate(AssetListIterFn fn) const;
+  bool listen(const wmNotifier &notifier) const;
+  int size() const;
+  void tagMainDataDirty() const;
+  void remapID(ID *id_old, ID *id_new) const;
+  StringRef filepath() const;
+};
+
+AssetList::AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref)
+    : filelist_(filesel_type), library_ref_(asset_library_ref)
+{
+}
+
+void AssetList::setup(const AssetFilterSettings *filter_settings)
+{
+  FileList *files = filelist_;
+
+  /* TODO there should only be one (FileSelectAssetLibraryUID vs. AssetLibraryReference). */
+  FileSelectAssetLibraryUID file_asset_lib_ref;
+  file_asset_lib_ref.type = library_ref_.type;
+  file_asset_lib_ref.custom_library_index = library_ref_.custom_library_index;
+
+  bUserAssetLibrary *user_library = nullptr;
+
+  /* Ensure valid repository, or fall-back to local one. */
+  if (library_ref_.type == ASSET_LIBRARY_CUSTOM) {
+    BLI_assert(library_ref_.custom_library_index >= 0);
+
+    user_library = BKE_preferences_asset_library_find_from_index(
+        &U, library_ref_.custom_library_index);
+  }
+
+  /* Relevant bits from file_refresh(). */
+  /* TODO pass options properly. */
+  filelist_setrecursion(files, 1);
+  filelist_setsorting(files, FILE_SORT_ALPHA, false);
+  filelist_setlibrary(files, &file_asset_lib_ref);
+  /* TODO different filtering settings require the list to be reread. That's a no-go for when we
+   * want to allow showing the same asset library with different filter settings (as in,
+   * different ID types). The filelist needs to be made smarter somehow, maybe goes together with
+   * the plan to separate the view (preview caching, filtering, etc. ) from the data. */
+  filelist_setfilter_options(
+      files,
+      filter_settings != nullptr,
+      true,
+      true, /* Just always hide parent, prefer to not add an extra user option for this. */
+      FILE_TYPE_BLENDERLIB,
+      filter_settings ? filter_settings->id_types : FILTER_ID_ALL,
+      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 AssetList::fetch(const bContext &C)
+{
+  FileList *files = filelist_;
+
+  if (filelist_needs_force_reset(files)) {
+    filelist_readjob_stop(files, CTX_wm_manager(&C));
+    filelist_clear(files);
+  }
+
+  if (filelist_needs_reading(files)) {
+    if (!f

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list