Assets: add function to copy asset data to another ID #108547

Manually merged
Sybren A. Stüvel merged 7 commits from dr.sybren/blender:pr/asset-data-copy-to-id into main 2023-06-08 10:15:03 +02:00
5 changed files with 102 additions and 1 deletions

View File

@ -38,6 +38,13 @@ typedef struct AssetTypeInfo {
struct AssetMetaData *BKE_asset_metadata_create(void);
void BKE_asset_metadata_free(struct AssetMetaData **asset_data);
/**
* Create a copy of the #AssetMetaData so that it can be assigned to another asset.
*
* The caller becomes the owner of the returned pointer.
*/
struct AssetMetaData *BKE_asset_metadata_copy(const struct AssetMetaData *source);
struct AssetTagEnsureResult {
struct AssetTag *tag;
/* Set to false if a tag of this name was already present. */

View File

@ -39,6 +39,38 @@ void BKE_asset_metadata_free(AssetMetaData **asset_data)
*asset_data = nullptr;
}
AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
{
AssetMetaData *copy = BKE_asset_metadata_create();
copy->local_type_info = source->local_type_info;
if (source->properties) {
copy->properties = IDP_CopyProperty(source->properties);
}
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
if (source->author) {
copy->author = BLI_strdup(source->author);
}
if (source->description) {
copy->description = BLI_strdup(source->description);
}
if (source->copyright) {
copy->copyright = BLI_strdup(source->copyright);
}
if (source->license) {
copy->license = BLI_strdup(source->license);
}
BLI_duplicatelist(&copy->tags, &source->tags);
copy->active_tag = source->active_tag;
copy->tot_tags = source->tot_tags;
return copy;
}
AssetMetaData::~AssetMetaData()
{
if (properties) {

View File

@ -12,6 +12,7 @@
extern "C" {
#endif
struct AssetMetaData;
struct ID;
struct Main;
struct bContext;
@ -42,6 +43,18 @@ void ED_asset_generate_preview(const struct bContext *C, struct ID *id);
*/
bool ED_asset_clear_id(struct ID *id);
/**
* Copy the asset metadata to the given destination ID.
*
* The copy is assigned to \a destination, any pre-existing asset metadata is
* freed before that. If \a destination was not yet marked as asset, it will be
* after this call.
*
* \return true when the copy succeeded, false otherwise. The only reason for
* failure is when \a destination is of a type that cannot be an asset.
*/
bool ED_asset_copy_to_id(const struct AssetMetaData *asset_data, struct ID *destination);
void ED_assets_pre_save(struct Main *bmain);
bool ED_asset_can_mark_single_from_context(const struct bContext *C);

View File

@ -27,6 +27,9 @@
#include "ED_asset_mark_clear.h"
#include "ED_asset_type.h"
#include "WM_api.h"
#include "WM_types.h"
bool ED_asset_mark_id(ID *id)
{
if (id->asset_data) {
@ -96,3 +99,16 @@ bool ED_asset_can_mark_single_from_context(const bContext *C)
}
return ED_asset_type_is_supported(id);
}
bool ED_asset_copy_to_id(const struct AssetMetaData *asset_data, struct ID *destination)
{
if (!BKE_id_can_be_asset(destination)) {
return false;
}
if (destination->asset_data) {
BKE_asset_metadata_free(&destination->asset_data);
}
destination->asset_data = BKE_asset_metadata_copy(asset_data);
return true;
}

View File

@ -725,6 +725,38 @@ static void rna_ID_asset_clear(ID *id)
}
}
static void rna_ID_asset_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
{
ID *destination = ptr->data;
/* Avoid marking as asset by assigning. This should be done wiht .asset_mark(). This is just for
* clarity of the API, and to accomodate future changes. */
if (destination->asset_data == NULL) {
BKE_report(reports,
RPT_ERROR,
"Asset data can only be assigned to assets. Use asset_mark() to mark as an asset");
return;
}
const AssetMetaData *asset_data = value.data;
if (asset_data == NULL) {
/* Avoid clearing the asset data on assets. Un-marking as asset should be done with
* .asset_clear(). This is just for clarity of the API, and to accomodate future changes. */
BKE_report(reports, RPT_ERROR, "Asset data cannot be None");
return;
}
const bool assigned_ok = ED_asset_copy_to_id(asset_data, destination);
if (!assigned_ok) {
BKE_reportf(
reports, RPT_ERROR, "'%s' is of a type that cannot be an asset", destination->name + 2);
return;
}
WM_main_add_notifier(NC_ASSET | NA_EDITED, NULL);
WM_main_add_notifier(NC_ID | NA_EDITED, NULL);
}
static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
{
if (!ID_IS_OVERRIDABLE_LIBRARY(id)) {
@ -2131,7 +2163,8 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
prop = RNA_def_property(srna, "asset_data", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_ID_asset_data_set", NULL, NULL);
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Asset Data", "Additional data for an asset data-block");