Assets: Replace most asset handle usages in BPY with asset representation #112536

Closed
Julian Eisel wants to merge 1 commits from JulianEisel:temp-asset-representation-bpy into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 144 additions and 146 deletions

View File

@ -20,10 +20,10 @@ from bpy_extras.asset_utils import (
class AssetBrowserMetadataOperator:
@classmethod
def poll(cls, context):
if not SpaceAssetInfo.is_asset_browser_poll(context) or not context.asset_file_handle:
if not SpaceAssetInfo.is_asset_browser_poll(context) or not context.asset:
return False
if not context.asset_file_handle.local_id:
if not context.asset.local_id:
Operator.poll_message_set(
"Asset metadata from external asset libraries can't be "
"edited, only assets stored in the current file can"
@ -58,13 +58,13 @@ class ASSET_OT_tag_remove(AssetBrowserMetadataOperator, Operator):
if not super().poll(context):
return False
active_asset_file = context.asset_file_handle
asset_metadata = active_asset_file.asset_data
active_asset = context.asset
asset_metadata = active_asset.metadata
return asset_metadata.active_tag in range(len(asset_metadata.tags))
def execute(self, context):
active_asset_file = context.asset_file_handle
asset_metadata = active_asset_file.asset_data
active_asset = context.asset
asset_metadata = active_asset.metadata
tag = asset_metadata.tags[asset_metadata.active_tag]
asset_metadata.tags.remove(tag)
@ -84,24 +84,24 @@ class ASSET_OT_open_containing_blend_file(Operator):
@classmethod
def poll(cls, context):
asset_file_handle = getattr(context, "asset_file_handle", None)
asset = getattr(context, "asset", None)
if not asset_file_handle:
if not asset:
cls.poll_message_set("No asset selected")
return False
if asset_file_handle.local_id:
if asset.local_id:
cls.poll_message_set("Selected asset is contained in the current file")
return False
return True
def execute(self, context):
asset_file_handle = context.asset_file_handle
asset = context.asset
if asset_file_handle.local_id:
if asset.local_id:
self.report({'WARNING'}, "This asset is stored in the current blend file")
return {'CANCELLED'}
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle)
asset_lib_path = asset.full_library_path
self.open_in_new_blender(asset_lib_path)
wm = context.window_manager

View File

@ -709,58 +709,58 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
bl_options = {'HIDE_HEADER'}
@staticmethod
def metadata_prop(layout, asset_data, propname):
def metadata_prop(layout, asset_metadata, propname):
"""
Only display properties that are either set or can be modified (i.e. the
asset is in the current file). Empty, non-editable fields are not really useful.
"""
if getattr(asset_data, propname) or not asset_data.is_property_readonly(propname):
layout.prop(asset_data, propname)
if getattr(asset_metadata, propname) or not asset_metadata.is_property_readonly(propname):
layout.prop(asset_metadata, propname)
def draw(self, context):
layout = self.layout
wm = context.window_manager
asset_file_handle = context.asset_file_handle
asset = context.asset
if asset_file_handle is None:
if asset is None:
layout.label(text="No active asset", icon='INFO')
return
prefs = context.preferences
show_asset_debug_info = prefs.view.show_developer_ui and prefs.experimental.show_asset_debug_info
is_local_asset = bool(asset_file_handle.local_id)
is_local_asset = bool(asset.local_id)
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
if is_local_asset:
# If the active file is an ID, use its name directly so renaming is possible from right here.
layout.prop(asset_file_handle.local_id, "name")
layout.prop(asset.local_id, "name")
if show_asset_debug_info:
col = layout.column(align=True)
col.label(text="Asset Catalog:")
col.prop(asset_file_handle.local_id.asset_data, "catalog_id", text="UUID")
col.prop(asset_file_handle.local_id.asset_data, "catalog_simple_name", text="Simple Name")
col.prop(asset.local_id.asset_data, "catalog_id", text="UUID")
col.prop(asset.local_id.asset_data, "catalog_simple_name", text="Simple Name")
else:
layout.prop(asset_file_handle, "name")
layout.prop(asset, "name")
if show_asset_debug_info:
col = layout.column(align=True)
col.enabled = False
col.label(text="Asset Catalog:")
col.prop(asset_file_handle.asset_data, "catalog_id", text="UUID")
col.prop(asset_file_handle.asset_data, "catalog_simple_name", text="Simple Name")
col.prop(asset.metadata, "catalog_id", text="UUID")
col.prop(asset.metadata, "catalog_simple_name", text="Simple Name")
row = layout.row(align=True)
row.prop(wm, "asset_path_dummy", text="Source", icon='CURRENT_FILE' if is_local_asset else 'NONE')
row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS')
asset_data = asset_file_handle.asset_data
self.metadata_prop(layout, asset_data, "description")
self.metadata_prop(layout, asset_data, "license")
self.metadata_prop(layout, asset_data, "copyright")
self.metadata_prop(layout, asset_data, "author")
metadata = asset.metadata
self.metadata_prop(layout, metadata, "description")
self.metadata_prop(layout, metadata, "license")
self.metadata_prop(layout, metadata, "copyright")
self.metadata_prop(layout, metadata, "author")
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
@ -877,14 +877,14 @@ classes = (
def asset_path_str_get(_self):
asset_file_handle = bpy.context.asset_file_handle
if asset_file_handle is None:
asset = bpy.context.asset
if asset is None:
return ""
if asset_file_handle.local_id:
if asset.local_id:
return "Current File"
return bpy.types.AssetHandle.get_full_library_path(asset_file_handle)
return asset.full_library_path
def register_props():

View File

@ -1514,8 +1514,20 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C)
{
return static_cast<blender::asset_system::AssetRepresentation *>(
ctx_data_pointer_get(C, "asset"));
if (auto *asset = static_cast<blender::asset_system::AssetRepresentation *>(
ctx_data_pointer_get(C, "asset")))
{
return asset;
}
/* Expose the asset representation from the asset-handle.
* TODO(Julian): #AssetHandle should be properly replaced by #AssetRepresentation. */
bool is_valid;
if (AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); is_valid) {
return handle.file_data->asset;
}
return nullptr;
}
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)

View File

@ -44,6 +44,8 @@ const EnumPropertyItem rna_enum_aset_library_type_items[] = {
# include "RNA_access.hh"
using namespace blender::asset_system;
static char *rna_AssetMetaData_path(const PointerRNA * /*ptr*/)
{
return BLI_strdup("asset_data");
@ -339,7 +341,7 @@ void rna_AssetMetaData_catalog_id_update(bContext *C, PointerRNA *ptr)
return;
}
AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
::AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
if (asset_library == nullptr) {
/* The SpaceFile may not be an asset browser but a regular file browser. */
return;
@ -365,31 +367,64 @@ static void rna_AssetHandle_file_data_set(PointerRNA *ptr,
asset_handle->file_data = static_cast<const FileDirEntry *>(value.data);
}
static void rna_AssetHandle_get_full_library_path(
// AssetHandle *asset,
FileDirEntry *asset_file,
char r_result[/*FILE_MAX_LIBEXTRA*/])
static void rna_AssetRepresentation_name_get(PointerRNA *ptr, char *value)
{
AssetHandle asset{};
asset.file_data = asset_file;
ED_asset_handle_get_full_library_path(&asset, r_result);
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
const blender::StringRefNull name = asset->get_name();
BLI_strncpy(value, name.c_str(), name.size() + 1);
}
static PointerRNA rna_AssetHandle_local_id_get(PointerRNA *ptr)
static int rna_AssetRepresentation_name_length(PointerRNA *ptr)
{
const AssetHandle *asset = static_cast<const AssetHandle *>(ptr->data);
ID *id = ED_asset_handle_get_representation(asset)->local_id();
return rna_pointer_inherit_refine(ptr, &RNA_ID, id);
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
const blender::StringRefNull name = asset->get_name();
return name.size();
}
static PointerRNA rna_AssetRepresentation_metadata_get(PointerRNA *ptr)
{
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
AssetMetaData &asset_data = asset->get_metadata();
/* Note that for local ID assets, the asset metadata is owned by the ID. Let the pointer inherit
* accordingly, so that the #PointerRNA.owner_id is set to the ID, and the metadata can be
* recognized as editable. */
if (asset->is_local_id()) {
PointerRNA id_ptr = RNA_id_pointer_create(asset->local_id());
return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, &asset_data);
}
return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, &asset_data);
}
static int rna_AssetRepresentation_id_type_get(PointerRNA *ptr)
{
using namespace blender::asset_system;
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
return asset->get_id_type();
}
static PointerRNA rna_AssetRepresentation_local_id_get(PointerRNA *ptr)
{
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
return rna_pointer_inherit_refine(ptr, &RNA_ID, asset->local_id());
}
static void rna_AssetRepresentation_full_library_path_get(PointerRNA *ptr, char *value)
{
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
const std::string full_library_path = asset->get_identifier().full_library_path();
BLI_strncpy(value, full_library_path.c_str(), full_library_path.size() + 1);
}
static int rna_AssetRepresentation_full_library_path_length(PointerRNA *ptr)
{
const AssetRepresentation *asset = static_cast<const AssetRepresentation *>(ptr->data);
const std::string full_library_path = asset->get_identifier().full_library_path();
return full_library_path.size();
}
const EnumPropertyItem *rna_asset_library_reference_itemf(bContext * /*C*/,
PointerRNA * /*ptr*/,
PropertyRNA * /*prop*/,
@ -545,22 +580,6 @@ static void rna_def_asset_data(BlenderRNA *brna)
"data recovery purposes");
}
static void rna_def_asset_handle_api(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "get_full_library_path", "rna_AssetHandle_get_full_library_path");
/* TODO temporarily static function, for until .py can receive the asset handle from context
* properly. `asset_file_handle` should go away too then. */
RNA_def_function_flag(func, FUNC_NO_SELF);
parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", "");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_string(func, "result", nullptr, FILE_MAX_LIBEXTRA, "result", "");
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
RNA_def_function_output(func, parm);
}
static void rna_def_asset_handle(BlenderRNA *brna)
{
StructRNA *srna;
@ -579,17 +598,6 @@ static void rna_def_asset_handle(BlenderRNA *brna)
prop, "rna_AssetHandle_file_data_get", "rna_AssetHandle_file_data_set", nullptr, nullptr);
RNA_def_property_ui_text(
prop, "File Entry", "TEMPORARY, DO NOT USE - File data used to refer to the asset");
prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_pointer_funcs(prop, "rna_AssetHandle_local_id_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop,
"",
"The local data-block this asset represents; only valid if that is a "
"data-block in this file");
RNA_def_property_flag(prop, PROP_HIDDEN);
rna_def_asset_handle_api(srna);
}
static void rna_def_asset_representation(BlenderRNA *brna)
@ -603,6 +611,19 @@ static void rna_def_asset_representation(BlenderRNA *brna)
"Information about an entity that makes it possible for the asset system "
"to deal with the entity as asset");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_FILENAME);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_funcs(
prop, "rna_AssetRepresentation_name_get", "rna_AssetRepresentation_name_length", nullptr);
RNA_def_property_ui_text(prop, "Name", "");
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "metadata", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "AssetMetaData");
RNA_def_property_pointer_funcs(
prop, "rna_AssetRepresentation_metadata_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop, "Asset Metadata", "Additional information about the asset");
prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_id_type_items);
RNA_def_property_enum_funcs(prop, "rna_AssetRepresentation_id_type_get", nullptr, nullptr);
@ -614,6 +635,27 @@ static void rna_def_asset_representation(BlenderRNA *brna)
* assets are supported. */
"The type of the data-block, if the asset represents one ('NONE' otherwise)");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_pointer_funcs(
prop, "rna_AssetRepresentation_local_id_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop,
"",
"The local data-block this asset represents; only valid if that is a "
"data-block in this file");
prop = RNA_def_property(srna, "full_library_path", PROP_STRING, PROP_FILENAME);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_funcs(prop,
"rna_AssetRepresentation_full_library_path_get",
"rna_AssetRepresentation_full_library_path_length",
nullptr);
RNA_def_property_ui_text(
prop,
"Full Library Path",
"Absolute path to the .blend file containing this asset extended with the path "
"of the asset inside the file");
}
static void rna_def_asset_catalog_path(BlenderRNA *brna)

View File

@ -125,19 +125,10 @@ static PointerRNA rna_Context_gizmo_group_get(PointerRNA *ptr)
return newptr;
}
static PointerRNA rna_Context_asset_file_handle_get(PointerRNA *ptr)
static PointerRNA rna_Context_asset_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
bool is_handle_valid;
AssetHandle asset_handle = CTX_wm_asset_handle(C, &is_handle_valid);
if (!is_handle_valid) {
return PointerRNA_NULL;
}
/* Have to cast away const, but the file entry API doesn't allow modifications anyway. */
PointerRNA newptr = RNA_pointer_create(
nullptr, &RNA_FileSelectEntry, (FileDirEntry *)asset_handle.file_data);
return newptr;
return RNA_pointer_create(nullptr, &RNA_AssetRepresentation, CTX_wm_asset(C));
}
static PointerRNA rna_Context_main_get(PointerRNA *ptr)
@ -290,17 +281,10 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GizmoGroup");
RNA_def_property_pointer_funcs(prop, "rna_Context_gizmo_group_get", nullptr, nullptr, nullptr);
/* TODO can't expose AssetHandle, since there is no permanent storage to it (so we can't
* return a pointer). Instead provide the FileDirEntry pointer it wraps. */
prop = RNA_def_property(srna, "asset_file_handle", PROP_POINTER, PROP_NONE);
prop = RNA_def_property(srna, "asset", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "FileSelectEntry");
RNA_def_property_pointer_funcs(
prop, "rna_Context_asset_file_handle_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop,
"",
"The file of an active asset. Avoid using this, it will be replaced by "
"a proper AssetHandle design");
RNA_def_property_struct_type(prop, "AssetRepresentation");
RNA_def_property_pointer_funcs(prop, "rna_Context_asset_get", nullptr, nullptr, nullptr);
/* Data */
prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE);

View File

@ -16,6 +16,15 @@
#include "UI_resources.hh"
#ifdef __cplusplus
namespace blender::asset_system {
class AssetRepresentation;
}
using AssetRepresentationHandle = blender::asset_system::AssetRepresentation;
#else
typedef struct AssetRepresentationHandle AssetRepresentationHandle;
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -2838,32 +2838,6 @@ static int rna_FileBrowser_FileSelectEntry_relative_path_length(PointerRNA *ptr)
return int(strlen(entry->relpath));
}
static const EnumPropertyItem *rna_FileBrowser_FileSelectEntry_id_type_itemf(
bContext * /*C*/, PointerRNA *ptr, PropertyRNA * /*prop*/, bool * /*r_free*/)
{
const FileDirEntry *entry = static_cast<const FileDirEntry *>(ptr->data);
if (entry->blentype == 0) {
static const EnumPropertyItem none_items[] = {
{0, "NONE", 0, "None", ""},
};
return none_items;
}
return rna_enum_id_type_items;
}
static int rna_FileBrowser_FileSelectEntry_id_type_get(PointerRNA *ptr)
{
const FileDirEntry *entry = static_cast<const FileDirEntry *>(ptr->data);
return entry->blentype;
}
static PointerRNA rna_FileBrowser_FileSelectEntry_local_id_get(PointerRNA *ptr)
{
const FileDirEntry *entry = static_cast<const FileDirEntry *>(ptr->data);
return rna_pointer_inherit_refine(ptr, &RNA_ID, entry->id);
}
static int rna_FileBrowser_FileSelectEntry_preview_icon_id_get(PointerRNA *ptr)
{
const FileDirEntry *entry = static_cast<const FileDirEntry *>(ptr->data);
@ -6674,29 +6648,6 @@ static void rna_def_fileselect_entry(BlenderRNA *brna)
"Browser (includes the file name)");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_id_type_items);
RNA_def_property_enum_funcs(prop,
"rna_FileBrowser_FileSelectEntry_id_type_get",
nullptr,
"rna_FileBrowser_FileSelectEntry_id_type_itemf");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop,
"Data-block Type",
"The type of the data-block, if the file represents one ('NONE' otherwise)");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_pointer_funcs(
prop, "rna_FileBrowser_FileSelectEntry_local_id_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop,
"",
"The local data-block this file represents; only valid if that is a "
"data-block in this file");
RNA_def_property_flag(prop, PROP_HIDDEN);
prop = RNA_def_int(
srna,
"preview_icon_id",