Asset System: Support custom asset library paths through Preferences
One of the core design aspects of the Asset Browser is that users can "mount" custom asset libraries via the Preferences. Currently an asset library is just a directory with one or more .blend files in it. We could easily support a single .blend file as asset library as well (rather than a directory). It's just disabled currently. Note that in earlier designs, asset libraries were called repositories. Idea is simple: In Preferences > File Paths, you can create custom libraries, by setting a name and selecting a path. The name is ensured to be unique. If the name or path are empty, the Asset Browser will not show it in the list of available asset libraries. The library path is not checked for validity, the Asset Browser will allow selecting invalid libraries, but show a message instead of the file list, to help the user understand what's going on. Of course the actual Asset Browser UI is not part of this commit, it's in one of the following ones. {F9497950} Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9722 Reviewed by: Brecht Van Lommel, Hans Goudey
This commit is contained in:
parent
b5d778a7d4
commit
e413c80371
Notes:
blender-bot
2023-02-14 02:13:08 +01:00
Referenced by issue #82819, Merge Asset Browser Milestone 1 (Not Necessarily Feature-Complete)
|
@ -1339,6 +1339,39 @@ class USERPREF_PT_saveload_autorun(FilePathsPanel, Panel):
|
|||
row.operator("preferences.autoexec_path_remove", text="", icon='X', emboss=False).index = i
|
||||
|
||||
|
||||
class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel):
|
||||
bl_label = "Asset Libraries"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = False
|
||||
layout.use_property_decorate = False
|
||||
|
||||
paths = context.preferences.filepaths
|
||||
|
||||
box = layout.box()
|
||||
split = box.split(factor=0.35)
|
||||
name_col = split.column()
|
||||
path_col = split.column()
|
||||
|
||||
row = name_col.row(align=True) # Padding
|
||||
row.separator()
|
||||
row.label(text="Name")
|
||||
|
||||
row = path_col.row(align=True) # Padding
|
||||
row.separator()
|
||||
row.label(text="Path")
|
||||
|
||||
subrow = row.row()
|
||||
subrow.operator("preferences.asset_library_add", text="", icon='ADD', emboss=False)
|
||||
|
||||
for i, library in enumerate(paths.asset_libraries):
|
||||
name_col.prop(library, "name", text="")
|
||||
row = path_col.row()
|
||||
row.prop(library, "path", text="")
|
||||
row.operator("preferences.asset_library_remove", text="", icon='X', emboss=False).index = i
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Save/Load Panels
|
||||
|
||||
|
@ -2288,6 +2321,7 @@ classes = (
|
|||
USERPREF_PT_file_paths_render,
|
||||
USERPREF_PT_file_paths_applications,
|
||||
USERPREF_PT_file_paths_development,
|
||||
USERPREF_PT_file_paths_asset_libraries,
|
||||
|
||||
USERPREF_PT_saveload_blend,
|
||||
USERPREF_PT_saveload_blend_autosave,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
struct UserDef;
|
||||
struct bUserAssetLibrary;
|
||||
|
||||
void BKE_preferences_asset_library_free(struct bUserAssetLibrary *library) ATTR_NONNULL();
|
||||
|
||||
struct bUserAssetLibrary *BKE_preferences_asset_library_add(struct UserDef *userdef,
|
||||
const char *name,
|
||||
const char *path) ATTR_NONNULL(1);
|
||||
void BKE_preferences_asset_library_name_set(struct UserDef *userdef,
|
||||
struct bUserAssetLibrary *library,
|
||||
const char *name) ATTR_NONNULL();
|
||||
|
||||
void BKE_preferences_asset_library_remove(struct UserDef *userdef,
|
||||
struct bUserAssetLibrary *library) ATTR_NONNULL();
|
||||
|
||||
struct bUserAssetLibrary *BKE_preferences_asset_library_find_from_index(
|
||||
const struct UserDef *userdef, int index) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
|
||||
struct bUserAssetLibrary *BKE_preferences_asset_library_find_from_name(
|
||||
const struct UserDef *userdef, const char *name) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
|
||||
int BKE_preferences_asset_library_get_index(const struct UserDef *userdef,
|
||||
const struct bUserAssetLibrary *library)
|
||||
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
void BKE_preferences_asset_library_default_add(struct UserDef *userdef) ATTR_NONNULL();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -215,6 +215,7 @@ set(SRC
|
|||
intern/pbvh_bmesh.c
|
||||
intern/pointcache.c
|
||||
intern/pointcloud.cc
|
||||
intern/preferences.c
|
||||
intern/report.c
|
||||
intern/rigidbody.c
|
||||
intern/scene.c
|
||||
|
@ -376,6 +377,7 @@ set(SRC
|
|||
BKE_persistent_data_handle.hh
|
||||
BKE_pointcache.h
|
||||
BKE_pointcloud.h
|
||||
BKE_preferences.h
|
||||
BKE_report.h
|
||||
BKE_rigidbody.h
|
||||
BKE_scene.h
|
||||
|
|
|
@ -296,6 +296,7 @@ void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
|
|||
}
|
||||
|
||||
BLI_freelistN(&userdef->autoexec_paths);
|
||||
BLI_freelistN(&userdef->asset_libraries);
|
||||
|
||||
BLI_freelistN(&userdef->uistyles);
|
||||
BLI_freelistN(&userdef->uifonts);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_preferences.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
@ -645,6 +646,8 @@ UserDef *BKE_blendfile_userdef_from_defaults(void)
|
|||
/* Default studio light. */
|
||||
BKE_studiolight_default(userdef->light_param, userdef->light_ambient);
|
||||
|
||||
BKE_preferences_asset_library_default_add(userdef);
|
||||
|
||||
return userdef;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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 bke
|
||||
*
|
||||
* User defined asset library API.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "BKE_appdir.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#define U BLI_STATIC_ASSERT(false, "Global 'U' not allowed, only use arguments passed in!")
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Asset Libraries
|
||||
* \{ */
|
||||
|
||||
bUserAssetLibrary *BKE_preferences_asset_library_add(UserDef *userdef,
|
||||
const char *name,
|
||||
const char *path)
|
||||
{
|
||||
bUserAssetLibrary *library = MEM_callocN(sizeof(*library), "bUserAssetLibrary");
|
||||
|
||||
BLI_addtail(&userdef->asset_libraries, library);
|
||||
|
||||
if (name) {
|
||||
BKE_preferences_asset_library_name_set(userdef, library, name);
|
||||
}
|
||||
if (path) {
|
||||
BLI_strncpy(library->path, path, sizeof(library->path));
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
void BKE_preferences_asset_library_name_set(UserDef *userdef,
|
||||
bUserAssetLibrary *library,
|
||||
const char *name)
|
||||
{
|
||||
BLI_strncpy_utf8(library->name, name, sizeof(library->name));
|
||||
BLI_uniquename(&userdef->asset_libraries,
|
||||
library,
|
||||
name,
|
||||
'.',
|
||||
offsetof(bUserAssetLibrary, name),
|
||||
sizeof(library->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink and free a library preference member.
|
||||
* \note Free's \a library itself.
|
||||
*/
|
||||
void BKE_preferences_asset_library_remove(UserDef *userdef, bUserAssetLibrary *library)
|
||||
{
|
||||
BLI_freelinkN(&userdef->asset_libraries, library);
|
||||
}
|
||||
|
||||
bUserAssetLibrary *BKE_preferences_asset_library_find_from_index(const UserDef *userdef, int index)
|
||||
{
|
||||
return BLI_findlink(&userdef->asset_libraries, index);
|
||||
}
|
||||
|
||||
bUserAssetLibrary *BKE_preferences_asset_library_find_from_name(const UserDef *userdef,
|
||||
const char *name)
|
||||
{
|
||||
return BLI_findstring(&userdef->asset_libraries, name, offsetof(bUserAssetLibrary, name));
|
||||
}
|
||||
|
||||
int BKE_preferences_asset_library_get_index(const UserDef *userdef,
|
||||
const bUserAssetLibrary *library)
|
||||
{
|
||||
return BLI_findindex(&userdef->asset_libraries, library);
|
||||
}
|
||||
|
||||
void BKE_preferences_asset_library_default_add(UserDef *userdef)
|
||||
{
|
||||
const char *asset_blend_name = "assets.blend";
|
||||
const char *doc_path = BKE_appdir_folder_default();
|
||||
|
||||
/* No home or documents path found, not much we can do. */
|
||||
if (!doc_path || !doc_path[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add new "Default" library under '[doc_path]/assets.blend'. */
|
||||
|
||||
bUserAssetLibrary *library = BKE_preferences_asset_library_add(userdef, DATA_("Default"), NULL);
|
||||
BLI_join_dirfile(library->path, sizeof(library->path), doc_path, asset_blend_name);
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -3904,6 +3904,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
|
|||
BLO_read_list(reader, &user->user_menus);
|
||||
BLO_read_list(reader, &user->addons);
|
||||
BLO_read_list(reader, &user->autoexec_paths);
|
||||
BLO_read_list(reader, &user->asset_libraries);
|
||||
|
||||
LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) {
|
||||
keymap->modal_items = NULL;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "BKE_idprop.h"
|
||||
#include "BKE_keyconfig.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
|
@ -830,6 +831,9 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
if (BLI_listbase_is_empty(&userdef->asset_libraries)) {
|
||||
BKE_preferences_asset_library_default_add(userdef);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
|
||||
|
|
|
@ -756,6 +756,10 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
|
|||
BLO_write_struct(writer, bPathCompare, path_cmp);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (const bUserAssetLibrary *, asset_library, &userdef->asset_libraries) {
|
||||
BLO_write_struct(writer, bUserAssetLibrary, asset_library);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (const uiStyle *, style, &userdef->uistyles) {
|
||||
BLO_write_struct(writer, uiStyle, style);
|
||||
}
|
||||
|
|
|
@ -626,7 +626,11 @@ static bool ui_rna_is_userdef(PointerRNA *ptr, PropertyRNA *prop)
|
|||
if (base == NULL) {
|
||||
base = ptr->type;
|
||||
}
|
||||
if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
|
||||
if (ELEM(base,
|
||||
&RNA_AddonPreferences,
|
||||
&RNA_KeyConfigPreferences,
|
||||
&RNA_KeyMapItem,
|
||||
&RNA_UserAssetLibrary)) {
|
||||
tag = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
is_relative = BLI_path_is_rel(str);
|
||||
}
|
||||
|
||||
if (UNLIKELY(ptr.data == &U)) {
|
||||
if (UNLIKELY(ptr.data == &U || is_userdef)) {
|
||||
is_relative = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_preferences.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
@ -133,9 +134,69 @@ static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Asset Library Operator
|
||||
* \{ */
|
||||
|
||||
static int preferences_asset_library_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
|
||||
{
|
||||
BKE_preferences_asset_library_add(&U, NULL, NULL);
|
||||
U.runtime.is_dirty = true;
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void PREFERENCES_OT_asset_library_add(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Add Asset Library";
|
||||
ot->idname = "PREFERENCES_OT_asset_library_add";
|
||||
ot->description =
|
||||
"Add a path to a .blend file to be used by the Asset Browser as source of assets";
|
||||
|
||||
ot->exec = preferences_asset_library_add_exec;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Remove Asset Library Operator
|
||||
* \{ */
|
||||
|
||||
static int preferences_asset_library_remove_exec(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
const int index = RNA_int_get(op->ptr, "index");
|
||||
bUserAssetLibrary *library = BLI_findlink(&U.asset_libraries, index);
|
||||
if (library) {
|
||||
BKE_preferences_asset_library_remove(&U, library);
|
||||
U.runtime.is_dirty = true;
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Remove Asset Library";
|
||||
ot->idname = "PREFERENCES_OT_asset_library_remove";
|
||||
ot->description =
|
||||
"Remove a path to a .blend file, so the Asset Browser will not attempt to show it anymore";
|
||||
|
||||
ot->exec = preferences_asset_library_remove_exec;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void ED_operatortypes_userpref(void)
|
||||
{
|
||||
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
|
||||
|
||||
WM_operatortype_append(PREFERENCES_OT_autoexec_path_add);
|
||||
WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove);
|
||||
|
||||
WM_operatortype_append(PREFERENCES_OT_asset_library_add);
|
||||
WM_operatortype_append(PREFERENCES_OT_asset_library_remove);
|
||||
}
|
||||
|
|
|
@ -569,6 +569,13 @@ enum {
|
|||
USER_MENU_TYPE_PROP = 4,
|
||||
};
|
||||
|
||||
typedef struct bUserAssetLibrary {
|
||||
struct bUserAssetLibrary *next, *prev;
|
||||
|
||||
char name[64]; /* MAX_NAME */
|
||||
char path[1024]; /* FILE_MAX */
|
||||
} bUserAssetLibrary;
|
||||
|
||||
typedef struct SolidLight {
|
||||
int flag;
|
||||
float smooth;
|
||||
|
@ -740,6 +747,8 @@ typedef struct UserDef {
|
|||
struct ListBase autoexec_paths;
|
||||
/** #bUserMenu. */
|
||||
struct ListBase user_menus;
|
||||
/** #bUserAssetLibrary */
|
||||
struct ListBase asset_libraries;
|
||||
|
||||
char keyconfigstr[64];
|
||||
|
||||
|
|
|
@ -697,6 +697,7 @@ extern StructRNA RNA_UVProjector;
|
|||
extern StructRNA RNA_UVWarpModifier;
|
||||
extern StructRNA RNA_UnitSettings;
|
||||
extern StructRNA RNA_UnknownType;
|
||||
extern StructRNA RNA_UserAssetLibrary;
|
||||
extern StructRNA RNA_UserSolidLight;
|
||||
extern StructRNA RNA_VertexcolorGpencilModifier;
|
||||
extern StructRNA RNA_VectorFont;
|
||||
|
|
|
@ -184,6 +184,7 @@ static const EnumPropertyItem rna_enum_userdef_viewport_aa_items[] = {
|
|||
# include "BKE_mesh_runtime.h"
|
||||
# include "BKE_paint.h"
|
||||
# include "BKE_pbvh.h"
|
||||
# include "BKE_preferences.h"
|
||||
# include "BKE_screen.h"
|
||||
|
||||
# include "DEG_depsgraph.h"
|
||||
|
@ -335,6 +336,12 @@ static void rna_userdef_language_update(Main *UNUSED(bmain),
|
|||
USERDEF_TAG_DIRTY;
|
||||
}
|
||||
|
||||
static void rna_userdef_asset_library_name_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
bUserAssetLibrary *library = (bUserAssetLibrary *)ptr->data;
|
||||
BKE_preferences_asset_library_name_set(&U, library, value);
|
||||
}
|
||||
|
||||
static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain),
|
||||
Scene *UNUSED(scene),
|
||||
PointerRNA *ptr)
|
||||
|
@ -5968,6 +5975,29 @@ static void rna_def_userdef_keymap(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Key Config", "The name of the active key configuration");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_filepaths_asset_library(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "UserAssetLibrary", NULL);
|
||||
RNA_def_struct_sdna(srna, "bUserAssetLibrary");
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Asset Library", "Settings to define a reusable library for Asset Browsers to use");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Name", "Identifier (not necessarily unique) for the asset library");
|
||||
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_userdef_asset_library_name_set");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH);
|
||||
RNA_def_property_ui_text(prop, "Path", "Path to a .blend file to use as an asset library");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_filepaths(BlenderRNA *brna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
@ -6140,6 +6170,12 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop,
|
||||
"Save Preview Images",
|
||||
"Enables automatic saving of preview images in the .blend file");
|
||||
|
||||
rna_def_userdef_filepaths_asset_library(brna);
|
||||
|
||||
prop = RNA_def_property(srna, "asset_libraries", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "UserAssetLibrary");
|
||||
RNA_def_property_ui_text(prop, "Asset Libraries", "");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_experimental(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue