Files
test/source/blender/blenkernel/intern/lib_principle_properties.c
Bastien Montagne 3c7a6718dd Fix T95480: Crash when relocating libraries in some cases.
While code deleting old (relocated to new ones) IDs would work fine in
typical cases, it would fail badly in others, when e.g. drivers would
create 'reversed' dependency from the obdata ID to the object ID.

This commit uses a less efficient, but much safer method. It also
ensures no relocated old IDs is left over in the file (previous version
could easily leave some old IDs from the old library until a full
save/reload cycle happened).
2022-04-29 17:57:46 +02:00

107 lines
3.0 KiB
C

/* 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);
}