Cleanup: Centralize/unify asset library reference from/to enum code

This was an open TODO, I wanted to have code for translating asset
library references from and to enum values in a central place, and
access that in the same way from both the Asset Browser and the
Workspace RNA code.

* Adds own file for the related functions.
* Adds doxygen comments.
* Updates RNA callbacks to properly use these functions.
* Let these functions call each other, avoid duplicating logic.
This commit is contained in:
Julian Eisel 2021-07-21 19:30:31 +02:00
parent 10e28bd270
commit e850c2b06d
8 changed files with 172 additions and 215 deletions

View File

@ -36,6 +36,7 @@ set(SRC
asset_temp_id_consumer.cc
intern/asset_handle.cc
intern/asset_library_reference.cc
intern/asset_library_reference_enum.cc
intern/asset_library_reference.hh
)

View File

@ -80,56 +80,3 @@ 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` callback? */
#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 repository, 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 repository, 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;
}

View File

@ -0,0 +1,156 @@
/*
* 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
*
* Helpers to convert asset library references from and to enum values and RNA enums.
* In some cases it's simply not possible to reference an asset library with
* #AssetLibraryReferences. This API guarantees a safe translation to indices/enum values for as
* long as there is no change in the order of registered custom asset libraries.
*/
#include "BLI_listbase.h"
#include "BKE_preferences.h"
#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
#include "ED_asset.h"
#include "UI_resources.h"
#include "RNA_define.h"
/**
* Return an index that can be used to uniquely identify \a library, assuming
* that all relevant indices were created with this function.
*/
int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library)
{
/* Simple case: Predefined repository, 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_unreachable();
return ASSET_LIBRARY_LOCAL;
}
/**
* Return an asset library reference matching the index returned by
* #ED_asset_library_reference_to_enum_value().
*/
AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
{
AssetLibraryReference library;
/* Simple case: Predefined repository, 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 there is no check if the path exists 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;
}
/**
* Translate all available asset libraries to an RNA enum, whereby the enum values match the result
* of #ED_asset_library_reference_to_enum_value() for any given library.
*
* Since this is meant for UI display, skips non-displayable libraries, that is, libraries with an
* empty name or path.
*/
const EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf()
{
const EnumPropertyItem predefined_items[] = {
/* For the future. */
// {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
{ASSET_LIBRARY_LOCAL,
"LOCAL",
ICON_BLENDER,
"Current File",
"Show the assets currently available in this Blender session"},
{0, NULL, 0, NULL, NULL},
};
EnumPropertyItem *item = NULL;
int totitem = 0;
/* Add separator if needed. */
if (!BLI_listbase_is_empty(&U.asset_libraries)) {
const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
}
int i = 0;
for (bUserAssetLibrary *user_library = (bUserAssetLibrary *)U.asset_libraries.first;
user_library;
user_library = user_library->next, i++) {
/* Note that the path itself 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 (!is_valid) {
continue;
}
AssetLibraryReference library_reference;
library_reference.type = ASSET_LIBRARY_CUSTOM;
library_reference.custom_library_index = i;
const int enum_value = ED_asset_library_reference_to_enum_value(&library_reference);
/* Use library path as description, it's a nice hint for users. */
EnumPropertyItem tmp = {
enum_value, user_library->name, ICON_NONE, user_library->name, user_library->path};
RNA_enum_item_add(&item, &totitem, &tmp);
}
if (totitem) {
const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
}
/* Add predefined items. */
RNA_enum_items_add(&item, &totitem, predefined_items);
RNA_enum_item_end(&item, &totitem);
return item;
}

View File

@ -42,6 +42,7 @@ bool ED_asset_can_make_single_from_context(const struct bContext *C);
int ED_asset_library_reference_to_enum_value(const struct AssetLibraryReference *library);
struct AssetLibraryReference ED_asset_library_reference_from_enum_value(int value);
const struct EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf(void);
const char *ED_asset_handle_get_name(const AssetHandle *asset);
AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset);

View File

@ -160,71 +160,18 @@ static PointerRNA rna_AssetHandle_local_id_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ID, id);
}
int rna_asset_library_reference_get(const AssetLibraryReference *library)
{
return ED_asset_library_reference_to_enum_value(library);
}
void rna_asset_library_reference_set(AssetLibraryReference *library, int value)
{
*library = ED_asset_library_reference_from_enum_value(value);
}
const EnumPropertyItem *rna_asset_library_reference_itemf(bContext *UNUSED(C),
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
bool *r_free)
{
const EnumPropertyItem predefined_items[] = {
/* For the future. */
// {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
{ASSET_LIBRARY_LOCAL,
"LOCAL",
ICON_BLENDER,
"Current File",
"Show the assets currently available in this Blender session"},
{0, NULL, 0, NULL, NULL},
};
EnumPropertyItem *item = NULL;
int totitem = 0;
/* Add separator if needed. */
if (!BLI_listbase_is_empty(&U.asset_libraries)) {
const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
const EnumPropertyItem *items = ED_asset_library_reference_to_rna_enum_itemf();
if (!items) {
*r_free = false;
}
int i = 0;
for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library;
user_library = user_library->next, i++) {
/* Note that the path itself 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 (!is_valid) {
continue;
}
/* Use library path as description, it's a nice hint for users. */
EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
user_library->name,
ICON_NONE,
user_library->name,
user_library->path};
RNA_enum_item_add(&item, &totitem, &tmp);
}
if (totitem) {
const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
}
/* Add predefined items. */
RNA_enum_items_add(&item, &totitem, predefined_items);
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
return items;
}
#else

View File

@ -270,8 +270,6 @@ void rna_def_view_layer_common(struct BlenderRNA *brna, struct StructRNA *srna,
PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
const char *get,
const char *set);
int rna_asset_library_reference_get(const struct AssetLibraryReference *library);
void rna_asset_library_reference_set(struct AssetLibraryReference *library, int value);
const EnumPropertyItem *rna_asset_library_reference_itemf(struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop,

View File

@ -536,6 +536,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
# include "DEG_depsgraph_build.h"
# include "ED_anim_api.h"
# include "ED_asset.h"
# include "ED_buttons.h"
# include "ED_clip.h"
# include "ED_fileselect.h"
@ -2562,112 +2563,19 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data);
}
/* TODO use rna_def_asset_library_reference_common() */
static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
{
FileAssetSelectParams *params = ptr->data;
/* Just an extra sanity check to ensure this isn't somehow called for RNA_FileSelectParams. */
BLI_assert(ptr->type == &RNA_FileAssetSelectParams);
/* Simple case: Predefined repo, just set the value. */
if (params->asset_library.type < ASSET_LIBRARY_CUSTOM) {
return params->asset_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, params->asset_library.custom_library_index);
if (user_library) {
return ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index;
}
BLI_assert(0);
return ASSET_LIBRARY_LOCAL;
return ED_asset_library_reference_to_enum_value(&params->asset_library);
}
static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value)
{
FileAssetSelectParams *params = ptr->data;
/* Simple case: Predefined repo, just set the value. */
if (value < ASSET_LIBRARY_CUSTOM) {
params->asset_library.type = value;
params->asset_library.custom_library_index = -1;
BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
return;
}
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) {
params->asset_library.type = ASSET_LIBRARY_LOCAL;
params->asset_library.custom_library_index = -1;
}
else if (user_library && is_valid) {
params->asset_library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
params->asset_library.type = ASSET_LIBRARY_CUSTOM;
}
}
static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf(
bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
const EnumPropertyItem predefined_items[] = {
/* For the future. */
// {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
{ASSET_LIBRARY_LOCAL,
"LOCAL",
ICON_BLENDER,
"Current File",
"Show the assets currently available in this Blender session"},
{0, NULL, 0, NULL, NULL},
};
EnumPropertyItem *item = NULL;
int totitem = 0;
/* Add separator if needed. */
if (!BLI_listbase_is_empty(&U.asset_libraries)) {
const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
}
int i = 0;
for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library;
user_library = user_library->next, i++) {
/* Note that the path itself 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 (!is_valid) {
continue;
}
/* Use library path as description, it's a nice hint for users. */
EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
user_library->name,
ICON_NONE,
user_library->name,
user_library->path};
RNA_enum_item_add(&item, &totitem, &tmp);
}
if (totitem) {
const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL};
RNA_enum_item_add(&item, &totitem, &sepr);
}
/* Add predefined items. */
RNA_enum_items_add(&item, &totitem, predefined_items);
RNA_enum_item_end(&item, &totitem);
*r_free = true;
return item;
params->asset_library = ED_asset_library_reference_from_enum_value(value);
}
static void rna_FileAssetSelectParams_asset_category_set(PointerRNA *ptr, uint64_t value)
@ -6559,12 +6467,9 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Asset Select Parameters", "Settings for the file selection in Asset Browser mode");
prop = RNA_def_property(srna, "asset_library", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, DummyRNA_NULL_items);
RNA_def_property_enum_funcs(prop,
"rna_FileAssetSelectParams_asset_library_get",
"rna_FileAssetSelectParams_asset_library_set",
"rna_FileAssetSelectParams_asset_library_itemf");
prop = rna_def_asset_library_reference_common(srna,
"rna_FileAssetSelectParams_asset_library_get",
"rna_FileAssetSelectParams_asset_library_set");
RNA_def_property_ui_text(prop, "Asset Library", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);

View File

@ -45,6 +45,8 @@
# include "DNA_screen_types.h"
# include "DNA_space_types.h"
# include "ED_asset.h"
# include "RNA_access.h"
# include "WM_toolsystem.h"
@ -110,13 +112,13 @@ static void rna_WorkSpace_owner_ids_clear(WorkSpace *workspace)
static int rna_WorkSpace_asset_library_get(PointerRNA *ptr)
{
const WorkSpace *workspace = ptr->data;
return rna_asset_library_reference_get(&workspace->asset_library);
return ED_asset_library_reference_to_enum_value(&workspace->asset_library);
}
static void rna_WorkSpace_asset_library_set(PointerRNA *ptr, int value)
{
WorkSpace *workspace = ptr->data;
rna_asset_library_reference_set(&workspace->asset_library, value);
workspace->asset_library = ED_asset_library_reference_from_enum_value(value);
}
static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace,