[Bf-blender-cvs] [bc9eac28bab] ui-asset-view-template: Initial AssetList API & use it to load assets for the asset view tempate

Julian Eisel noreply at git.blender.org
Mon Mar 1 17:11:30 CET 2021


Commit: bc9eac28bab696de3cbfed8c2dfddd63271edd3f
Author: Julian Eisel
Date:   Mon Mar 1 16:45:42 2021 +0100
Branches: ui-asset-view-template
https://developer.blender.org/rBbc9eac28bab696de3cbfed8c2dfddd63271edd3f

Initial AssetList API & use it to load assets for the asset view tempate

Lots of hacks and temporary code here. I wanted a first working version to find
possible pain points before getting into details.

Basic idea is to store each asset library in an `AssetList`, with a globally
accessible storage. Internally the list uses the File Browser's `FileList`
which already does a fair amount of heavy lifting (threaded file & external
asset reading, lazy loading of visible previews, ...). The File Browser could
access the global asset-list storage as well.

The asset view template uses the new asset list to load and display the assets.

Current state: {F9856940}

Open TODOs: https://developer.blender.org/maniphest/query/M6RWFxFSDor3/#R

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

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenloader/intern/versioning_290.c
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/include/ED_asset.h
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_template_asset_view.cc
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/space_file/file_draw.c
M	source/blender/editors/space_file/filelist.c
M	source/blender/editors/space_file/filelist.h
M	source/blender/editors/space_file/filesel.c
M	source/blender/makesdna/DNA_asset_types.h
M	source/blender/makesdna/DNA_screen_types.h
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesdna/DNA_view3d_defaults.h
M	source/blender/makesdna/DNA_view3d_types.h
M	source/blender/makesrna/intern/rna_asset.c
M	source/blender/makesrna/intern/rna_internal.h
M	source/blender/makesrna/intern/rna_space.c
M	source/blender/makesrna/intern/rna_ui_api.c
M	source/blender/windowmanager/intern/wm_init_exit.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 3f4a082ed2e..5ebeca590dd 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -6992,7 +6992,9 @@ class VIEW3D_PT_asset_testing(Panel):
     def draw(self, context):
         layout = self.layout
 
-        layout.template_asset_view()
+        v3d = context.space_data
+
+        layout.template_asset_view(v3d, "active_asset_library")
 
 
 # Grease Pencil Object - Multiframe falloff tools
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 29041f4ae9d..fedc003e4ff 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -1755,4 +1755,21 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
 
     /* Keep this block, even when empty. */
   }
+
+  {
+    if (!DNA_struct_elem_find(
+            fd->filesdna, "View3D", "AssetLibraryReference", "active_asset_library")) {
+      LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+        LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+          LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
+            if (space->spacetype == SPACE_VIEW3D) {
+              View3D *v3d = (View3D *)space;
+              v3d->active_asset_library.type = ASSET_LIBRARY_LOCAL;
+              v3d->active_asset_library.custom_library_index = -1;
+            }
+          }
+        }
+      }
+    }
+  }
 }
diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
index 8c5f91561b7..ec917aa625a 100644
--- a/source/blender/editors/asset/CMakeLists.txt
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC_SYS
 
 set(SRC
   asset_edit.cc
+  asset_list.cc
   asset_ops.cc
 )
 
diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc
index d20de4141cb..2f9bd60edcb 100644
--- a/source/blender/editors/asset/asset_edit.cc
+++ b/source/blender/editors/asset/asset_edit.cc
@@ -23,6 +23,7 @@
 #include "BKE_lib_id.h"
 
 #include "DNA_ID.h"
+#include "DNA_asset_types.h"
 
 #include "UI_interface_icons.h"
 
@@ -65,3 +66,56 @@ bool ED_asset_can_make_single_from_context(const bContext *C)
   /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */
   return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr;
 }
+
+/* TODO better place? */
+/* TODO What about the setter and the itemf? */
+#include "BKE_preferences.h"
+#include "DNA_asset_types.h"
+#include "DNA_userdef_types.h"
+int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library)
+{
+  /* Simple case: Predefined repo, just set the value. */
+  if (library->type < ASSET_LIBRARY_CUSTOM) {
+    return library->type;
+  }
+
+  /* Note that the path isn't checked for validity here. If an invalid library path is used, the
+   * Asset Browser can give a nice hint on what's wrong. */
+  const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
+      &U, library->custom_library_index);
+  if (user_library) {
+    return ASSET_LIBRARY_CUSTOM + library->custom_library_index;
+  }
+
+  BLI_assert(0);
+  return ASSET_LIBRARY_LOCAL;
+}
+
+AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
+{
+  AssetLibraryReference library;
+
+  /* Simple case: Predefined repo, just set the value. */
+  if (value < ASSET_LIBRARY_CUSTOM) {
+    library.type = value;
+    library.custom_library_index = -1;
+    BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
+    return library;
+  }
+
+  const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
+      &U, value - ASSET_LIBRARY_CUSTOM);
+
+  /* Note that the path isn't checked for validity here. If an invalid library path is used, the
+   * Asset Browser can give a nice hint on what's wrong. */
+  const bool is_valid = (user_library->name[0] && user_library->path[0]);
+  if (!user_library) {
+    library.type = ASSET_LIBRARY_LOCAL;
+    library.custom_library_index = -1;
+  }
+  else if (user_library && is_valid) {
+    library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
+    library.type = ASSET_LIBRARY_CUSTOM;
+  }
+  return library;
+}
diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc
new file mode 100644
index 00000000000..1f60d69e335
--- /dev/null
+++ b/source/blender/editors/asset/asset_list.cc
@@ -0,0 +1,347 @@
+/*
+ * 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 "BLI_function_ref.hh"
+#include "BLI_hash.hh"
+#include "BLI_map.hh"
+
+#include "DNA_asset_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_preferences.h"
+
+#include "ED_asset.h"
+#include "ED_fileselect.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.
+ */
+struct AssetLibraryReferenceWrapper {
+  const AssetLibraryReference &reference_;
+
+  AssetLibraryReferenceWrapper(const AssetLibraryReference &reference) : reference_(reference)
+  {
+  }
+  ~AssetLibraryReferenceWrapper() = default;
+
+  friend 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 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.
+ * \{ */
+
+#include "BKE_context.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
+class AssetList {
+  static void filelist_free_wrapper(FileList *list)
+  {
+    filelist_free(list);
+    MEM_freeN(list);
+  }
+
+  using FileList_Ptr = std::unique_ptr<FileList, decltype(&filelist_free_wrapper)>;
+  FileList_Ptr filelist_;
+  AssetLibraryReference library_ref_;
+
+  struct wmTimer *previews_timer = nullptr;
+
+ public:
+  AssetList() = delete;
+  AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref)
+      : filelist_(filelist_new(filesel_type), filelist_free_wrapper),
+        library_ref_(asset_library_ref)
+  {
+  }
+  AssetList(AssetList &&other)
+      : filelist_(std::move(other.filelist_)), library_ref_(other.library_ref_)
+  {
+  }
+  AssetList(const AssetList &) = delete;
+  ~AssetList() = default;
+
+  void setup()
+  {
+    FileList *files = filelist_.get();
+
+    /* TODO there should only be one. */
+    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 = NULL;
+
+    /* 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);
+    }
+
+    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);
+    filelist_setsorting(files, FILE_SORT_ALPHA, false);
+    filelist_setlibrary(files, &file_asset_lib_ref);
+    filelist_setfilter_options(
+        files,
+        true,
+        true,
+        true, /* Just always hide parent, prefer to not add an extra user option for this. */
+        FILE_TYPE_BLENDERLIB,
+        FILTER_ID_ALL,
+        true,
+        "",
+        "");
+  }
+
+  void fetch(const bContext &C)
+  {
+    FileList *files = filelist_.get();
+
+    if (filelist_needs_reading(files)) {
+      if (!filelist_pending(files)) {
+        filelist_readjob_start(files, &C);
+      }
+    }
+    filelist_sort(files);
+    filelist_filter(files);
+  }
+
+  void iterate(AssetListIterFn fn)
+  {
+    FileList *files = filelist_.get();
+    int numfiles = filelist_files_ensure(files);
+
+    for (int i = 0; i < numfiles; i++) {
+      FileDirEntry *file = filelist_file(files, i);
+      if (!fn(*file)) {
+        break;
+      }
+    }
+  }
+
+  void ensurePreview

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list