diff options
Diffstat (limited to 'source')
4 files changed, 235 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_blendfile_link_append.h b/source/blender/blenkernel/BKE_blendfile_link_append.h index b70f2c2563a..bd00ed51d99 100644 --- a/source/blender/blenkernel/BKE_blendfile_link_append.h +++ b/source/blender/blenkernel/BKE_blendfile_link_append.h @@ -197,6 +197,9 @@ void BKE_blendfile_link(struct BlendfileLinkAppendContext *lapp_context, * - Add all IDs to search for to `lapp_context`. * - Mark which libraries should be considered for each ID. * - Call this function. + * + * NOTE: content of `lapp_context` after execution of that function should not be assumed valid + * anymore, and should immediately be freed. */ void BKE_blendfile_library_relocate(struct BlendfileLinkAppendContext *lapp_context, struct ReportList *reports, diff --git a/source/blender/blenkernel/BKE_lib_principle_properties.h b/source/blender/blenkernel/BKE_lib_principle_properties.h new file mode 100644 index 00000000000..10d0d33a0c4 --- /dev/null +++ b/source/blender/blenkernel/BKE_lib_principle_properties.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +#pragma once + +/** \file + * \ingroup bke + * + * API to manage principle properties in data-blocks. + * + * Principle properties are properties that are defined as the ones most user will need to + * edit when using this data-block. + * + * They current main usage in is library overrides. + * + * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might + * alter Main as well (when creating/renaming/deleting an ID e.g.). + * + * \section Function Names + * + * - `BKE_lib_principleprop_` should be used for function affecting a single ID. + * - `BKE_lib_principleprop_main_` should be used for function affecting the whole collection + * of IDs in a given Main data-base. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ID; +struct IDPrincipleProperties; +struct IDPrincipleProperty; +struct PointerRNA; +struct PropertyRNA; +struct ReportList; + +/** + * Initialize empty list of principle properties for \a id. + */ +struct IDPrincipleProperties *BKE_lib_principleprop_init(struct ID *id); +#if 0 +/** + * Shallow or deep copy of a whole princple properties from \a src_id to \a dst_id. + */ +void BKE_lib_principleprop_copy(struct ID *dst_id, const struct ID *src_id, bool do_full_copy); +#endif +/** + * Clear any principle properties data from given \a override. + */ +void BKE_lib_principleprop_clear(struct IDPrincipleProperties *principle_props, bool do_id_user); +/** + * Free given \a principle_props. + */ +void BKE_lib_principleprop_free(struct IDPrincipleProperties **principle_props, bool do_id_user); + +/** + * Find principle property from given RNA path, if it exists. + */ +struct IDPrincipleProperty *BKE_lib_principleprop_find( + struct IDPrincipleProperties *principle_props, const char *rna_path); +/** + * Find principle property from given RNA path, or create it if it does not exist. + */ +struct IDPrincipleProperty *BKE_lib_principleprop_get( + struct IDPrincipleProperties *principle_props, const char *rna_path, bool *r_created); +/** + * Remove and free given \a principle_prop from given ID \a principle_props. + */ +void BKE_lib_principleprop_delete(struct IDPrincipleProperties *principle_props, + struct IDPrincipleProperty *principle_prop); +/** + * Get the RNA-property matching the \a principle_prop principle property. Used for UI to query + * additional data about the principle property (e.g. UI name). + * + * \param idpoin: RNA Pointer of the ID. + * \param principle_prop: The principle property to find the matching RNA property for. + */ +bool BKE_lib_principleprop_rna_property_find(struct PointerRNA *idpoin, + const struct IDPrincipleProperty *principle_prop, + struct PointerRNA *r_principle_poin, + struct PropertyRNA **r_principle_prop); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index da48365a43e..555c4690308 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -1541,14 +1541,49 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, BKE_main_unlock(bmain); - for (item_idx = 0, itemlink = lapp_context->items.list; itemlink; - item_idx++, itemlink = itemlink->next) { - BlendfileLinkAppendContextItem *item = itemlink->link; - ID *old_id = item->userdata; + /* Delete all no more used old IDs. */ + /* NOTE: While this looping over until we are sure we deleted everything is very far from + * efficient, doing otherwise would require a much more complex handling of indirectly linked IDs + * in steps above. Currently, in case of relocation, those are skipped in remapping phase, though + * in some cases (essentially internal links between IDs from the same library) remapping should + * happen. But getting this to work reliably would be very difficult, so since this is not a + * performance-critical code, better to go with the (relatively) simpler, brute-force approach + * here in 'removal of old IDs' step. */ + bool keep_looping = true; + while (keep_looping) { + keep_looping = false; + + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + for (item_idx = 0, itemlink = lapp_context->items.list; itemlink; + item_idx++, itemlink = itemlink->next) { + BlendfileLinkAppendContextItem *item = itemlink->link; + ID *old_id = item->userdata; + + if (old_id == NULL) { + continue; + } + + if (GS(old_id->name) == ID_KE) { + /* Shape Keys are handled as part of their owning obdata (see below). This implies thar + * there is no way to know when the old pointer gets invalid, so just clear it immediately. + */ + item->userdata = NULL; + continue; + } - if (old_id->us == 0) { - BKE_id_free(bmain, old_id); + if (old_id->us == 0) { + old_id->tag |= LIB_TAG_DOIT; + item->userdata = NULL; + keep_looping = true; + Key *old_key = BKE_key_from_id(old_id); + if (old_key != NULL) { + old_key->id.tag |= LIB_TAG_DOIT; + } + } } + BKE_id_multi_tagged_delete(bmain); + /* Should not be needed, all tagged IDs should have been deleted above, just 'in case'. */ + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable diff --git a/source/blender/blenkernel/intern/lib_principle_properties.c b/source/blender/blenkernel/intern/lib_principle_properties.c new file mode 100644 index 00000000000..204ca9ff9d6 --- /dev/null +++ b/source/blender/blenkernel/intern/lib_principle_properties.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup bke + */ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "CLG_log.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" + +#include "BKE_lib_id.h" +#include "BKE_lib_principle_properties.h" +#include "BKE_report.h" + +#include "BLO_readfile.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "RNA_access.h" +#include "RNA_prototypes.h" +#include "RNA_types.h" + +static CLG_LogRef LOG = {"bke.idprincipleprops"}; + +IDPrincipleProperties *BKE_lib_principleprop_init(ID *id) +{ + BLI_assert(id->principle_properties == NULL); + + /* Else, generate new empty override. */ + id->principle_properties = MEM_callocN(sizeof(*id->principle_properties), __func__); + + return id->principle_properties; +} + +void BKE_lib_principleprop_clear(IDPrincipleProperties *principle_props, bool UNUSED(do_id_user)) +{ + LISTBASE_FOREACH_MUTABLE (IDPrincipleProperty *, pprop, &principle_props->properties) { + BLI_assert(pprop->rna_path != NULL); + MEM_freeN(pprop->rna_path); + MEM_freeN(pprop); + } + BLI_listbase_clear(&principle_props->properties); + principle_props->flag = 0; +} + +void BKE_lib_principleprop_free(IDPrincipleProperties **principle_props, bool do_id_user) +{ + BLI_assert(*principle_props != NULL); + + BKE_lib_principleprop_clear(*principle_props, do_id_user); + MEM_freeN(*principle_props); + *principle_props = NULL; +} + +IDPrincipleProperty *BKE_lib_principleprop_find(IDPrincipleProperties *principle_props, + const char *rna_path) +{ + return BLI_findstring_ptr( + &principle_props->properties, rna_path, offsetof(IDPrincipleProperty, rna_path)); +} + +IDPrincipleProperty *BKE_lib_principleprop_get(IDPrincipleProperties *principle_props, + const char *rna_path, + bool *r_created) +{ + IDPrincipleProperty *pprop = BKE_lib_principleprop_find(principle_props, rna_path); + + if (pprop == NULL) { + pprop = MEM_callocN(sizeof(*pprop), __func__); + pprop->rna_path = BLI_strdup(rna_path); + BLI_addtail(&principle_props->properties, pprop); + + if (r_created) { + *r_created = true; + } + } + else if (r_created) { + *r_created = false; + } + + return pprop; +} + +void BKE_lib_principleprop_delete(IDPrincipleProperties *principle_props, + IDPrincipleProperty *principle_prop) +{ + BLI_remlink(&principle_props->properties, principle_prop); +} + +bool BKE_lib_principleprop_rna_property_find(struct PointerRNA *idpoin, + const struct IDPrincipleProperty *principle_prop, + struct PointerRNA *r_principle_poin, + struct PropertyRNA **r_principle_prop) +{ + BLI_assert(RNA_struct_is_ID(idpoin->type)); + return RNA_path_resolve_property( + idpoin, principle_prop->rna_path, r_principle_poin, r_principle_prop); +} |