From 3346ab034804c0d93e1c20d62e82dff4839b861a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 10 Nov 2014 17:10:58 +0100 Subject: Fix/workaround T37073: Crash updating custom props visible in the UI --- source/blender/blenkernel/BKE_idprop.h | 1 + source/blender/blenkernel/intern/idprop.c | 23 +++++++++++++++-------- source/blender/python/generic/idprop_py_api.c | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index cb73cc2896d..6d3d15e3565 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -91,6 +91,7 @@ void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) void IDP_SyncGroupTypes(struct IDProperty *dest, const struct IDProperty *src, const bool do_arraylen) ATTR_NONNULL(); void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL(); void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); +void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist); void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) ATTR_NONNULL(); bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); bool IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous, diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 5c06d5bd86b..23e7778ffd5 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -571,18 +571,18 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) * Checks if a property with the same name as prop exists, and if so replaces it. * Use this to preserve order! */ -void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) +void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist) { - IDProperty *loop; - BLI_assert(group->type == IDP_GROUP); - if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) { - BLI_insertlinkafter(&group->data.group, loop, prop); + BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name)); + + if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) { + BLI_insertlinkafter(&group->data.group, prop_exist, prop); - BLI_remlink(&group->data.group, loop); - IDP_FreeProperty(loop); - MEM_freeN(loop); + BLI_remlink(&group->data.group, prop_exist); + IDP_FreeProperty(prop_exist); + MEM_freeN(prop_exist); } else { group->len++; @@ -590,6 +590,13 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) } } +void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) +{ + IDProperty *prop_exist = IDP_GetPropertyFromGroup(group, prop->name); + + IDP_ReplaceInGroup_ex(group, prop, prop_exist); +} + /** * If a property is missing in \a dest, add it. */ diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 8c9e84af8ed..d2920df3e69 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -510,7 +510,22 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, MEM_freeN(prop); } else { - IDP_ReplaceInGroup(group, prop); + IDProperty *prop_exist; + + /* avoid freeing when types match incase they are referenced by the UI, see: T37073 + * obviously this isn't a complete solution, but helps for common cases. */ + prop_exist = IDP_GetPropertyFromGroup(group, prop->name); + if ((prop_exist != NULL) && + (prop_exist->type == prop->type) && + (prop_exist->subtype == prop->subtype)) + { + IDP_FreeProperty(prop_exist); + *prop_exist = *prop; + MEM_freeN(prop); + } + else { + IDP_ReplaceInGroup_ex(group, prop, prop_exist); + } } return true; -- cgit v1.2.3