Fix T69156: Blender crash when baking rigid body world.

Issue was exposed by recent own rB03bf84db86b commit, but was actually
present in RNA API for PointCaches since (probably) ages: whole accessor
code here was assuming that owner ID was an Object, when it is actually
a scene for RigidBody simulations...

Had also to make `BKE_ptcache_id_find()` and friends a bit more
flexible, now they also accept a NULL object pointer parameter...
This commit is contained in:
Bastien Montagne 2019-08-26 16:01:16 +02:00
parent 51d9f56f87
commit 39439a3afe
Notes: blender-bot 2023-02-14 10:21:15 +01:00
Referenced by issue #69196, Rigid Body with dynamic will crash
Referenced by issue #69156, Blender crash when baking rigid body world
Referenced by issue #69095, Having Cache Tab open crashes blender
2 changed files with 113 additions and 56 deletions

View File

@ -1831,6 +1831,7 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
/** Both \param ob and \param scene may be NULL. */
PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
{
PTCacheID result = {0};
@ -1934,40 +1935,45 @@ static bool foreach_object_ptcache(
Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data)
{
PTCacheID pid;
/* Soft body. */
if (object->soft != NULL) {
BKE_ptcache_id_from_softbody(&pid, object, object->soft);
if (!callback(&pid, callback_user_data)) {
if (object != NULL) {
/* Soft body. */
if (object->soft != NULL) {
BKE_ptcache_id_from_softbody(&pid, object, object->soft);
if (!callback(&pid, callback_user_data)) {
return false;
}
}
/* Particle systems. */
if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
return false;
}
/* Modifiers. */
if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
return false;
}
/* Consider all object in dupli groups to be part of the same object,
* for baking with linking dupligroups. Once we have better overrides
* this can be revisited so users select the local objects directly. */
if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) {
if (current_object == object) {
continue;
}
foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
/* Particle systems. */
if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
return false;
}
/* Modifiers. */
if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
return false;
}
/* Rigid body. */
if (scene != NULL && object->rigidbody_object != NULL && scene->rigidbody_world != NULL) {
if (scene != NULL && (object == NULL || object->rigidbody_object != NULL) &&
scene->rigidbody_world != NULL) {
BKE_ptcache_id_from_rigidbody(&pid, object, scene->rigidbody_world);
if (!callback(&pid, callback_user_data)) {
return false;
}
}
/* Consider all object in dupli groups to be part of the same object,
* for baking with linking dupligroups. Once we have better overrides
* this can be revisited so users select the local objects directly. */
if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) {
if (current_object == object) {
continue;
}
foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
return true;
}

View File

@ -120,18 +120,38 @@ static const EnumPropertyItem empty_vortex_shape_items[] = {
# include "ED_object.h"
static bool rna_Cache_get_valid_owner_ID(PointerRNA *ptr, Object **ob, Scene **scene)
{
switch (GS(ptr->owner_id->name)) {
case ID_OB:
*ob = (Object *)ptr->owner_id;
break;
case ID_SCE:
*scene = (Scene *)ptr->owner_id;
break;
default:
BLI_assert(!"Trying to get PTCacheID from an invalid ID type "
"(Only scenes and objects are supported).");
break;
}
return (*ob != NULL || *scene != NULL);
}
static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = (PointCache *)ptr->data;
Object *ob = NULL;
Scene *scene = NULL;
if (!ob) {
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PointCache *cache = (PointCache *)ptr->data;
cache->flag |= PTCACHE_OUTDATED;
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@ -146,14 +166,16 @@ static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = (PointCache *)ptr->data;
Object *ob = NULL;
Scene *scene = NULL;
if (!ob) {
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
PointCache *cache = (PointCache *)ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
/* smoke can only use disk cache */
if (pid.cache && pid.type != PTCACHE_TYPE_SMOKE_DOMAIN) {
@ -166,18 +188,20 @@ static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene
static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = (PointCache *)ptr->data;
bool use_new_name = true;
Object *ob = NULL;
Scene *scene = NULL;
if (!ob) {
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PointCache *cache = (PointCache *)ptr->data;
bool use_new_name = true;
/* TODO: check for proper characters */
if (cache->flag & PTCACHE_EXTERNAL) {
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
BKE_ptcache_load_external(&pid);
@ -190,7 +214,7 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
PTCacheID *pid = NULL, *pid2 = NULL;
ListBase pidlist;
BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache) {
@ -240,13 +264,19 @@ static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *p
static void rna_Cache_active_point_cache_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
*min = 0;
*max = 0;
Object *ob = NULL;
Scene *scene = NULL;
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
*max = max_ii(0, BLI_listbase_count(pid.ptcaches) - 1);
}
@ -254,11 +284,18 @@ static void rna_Cache_active_point_cache_index_range(
static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
int num = 0;
Object *ob = NULL;
Scene *scene = NULL;
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return num;
}
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
num = BLI_findindex(pid.ptcaches, cache);
}
@ -268,9 +305,15 @@ static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value)
{
Object *ob = (Object *)ptr->owner_id;
Object *ob = NULL;
Scene *scene = NULL;
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
*(pid.cache_ptr) = BLI_findlink(pid.ptcaches, value);
@ -280,13 +323,19 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v
static void rna_PointCache_frame_step_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->owner_id;
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
*min = 1;
*max = 20;
Object *ob = NULL;
Scene *scene = NULL;
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
PointCache *cache = ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
*max = pid.max_step;
}
@ -294,14 +343,16 @@ static void rna_PointCache_frame_step_range(
int rna_Cache_info_length(PointerRNA *ptr)
{
PointCache *cache = (PointCache *)ptr->data;
Object *ob = (Object *)ptr->owner_id;
Object *ob = NULL;
Scene *scene = NULL;
if (!ob) {
if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return 0;
}
PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
PointCache *cache = (PointCache *)ptr->data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (cache->flag & PTCACHE_FLAG_INFO_DIRTY) {
BKE_ptcache_update_info(&pid);