diff options
-rw-r--r-- | source/blender/blenkernel/intern/bpath.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/softbody.c | 23 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 13 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 19 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 8 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_force_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 2 |
9 files changed, 76 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 7c9e57b039e..34f54704f75 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -513,7 +513,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } if (ob->soft) { - BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); + BPATH_TRAVERSE_POINTCACHE(ob->soft->shared->ptcaches); } for (psys = ob->particlesystem.first; psys; psys = psys->next) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 3f5464156c5..61d38a4e937 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -834,6 +834,7 @@ void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src { SoftBody *sb = ob_src->soft; SoftBody *sbn; + bool tagged_no_main = ob_dst->id.tag & LIB_TAG_NO_MAIN; ob_dst->softflag = ob_src->softflag; if (sb == NULL) { @@ -872,7 +873,10 @@ void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src sbn->scratch = NULL; - sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, flag); + if (tagged_no_main == 0) { + sbn->shared = MEM_dupallocN(sb->shared); + sbn->shared->pointcache = BKE_ptcache_copy_list(&sbn->shared->ptcaches, &sb->shared->ptcaches, flag); + } if (sb->effector_weights) sbn->effector_weights = MEM_dupallocN(sb->effector_weights); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a8c6091124a..17e90d688a2 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1389,9 +1389,9 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->ob= ob; pid->calldata= sb; pid->type= PTCACHE_TYPE_SOFTBODY; - pid->cache= sb->pointcache; - pid->cache_ptr= &sb->pointcache; - pid->ptcaches= &sb->ptcaches; + pid->cache= sb->shared->pointcache; + pid->cache_ptr= &sb->shared->pointcache; + pid->ptcaches= &sb->shared->ptcaches; pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; pid->error = ptcache_softbody_error; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 4960714b47c..d3429622573 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3276,7 +3276,8 @@ SoftBody *sbNew(Scene *scene) sb->shearstiff = 1.0f; sb->solverflags |= SBSO_OLDERR; - sb->pointcache = BKE_ptcache_add(&sb->ptcaches); + sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared"); + sb->shared->pointcache = BKE_ptcache_add(&sb->shared->ptcaches); if (!sb->effector_weights) sb->effector_weights = BKE_add_effector_weights(NULL); @@ -3295,8 +3296,13 @@ void sbFree(Object *ob) } free_softbody_intern(sb); - BKE_ptcache_free_list(&sb->ptcaches); - sb->pointcache = NULL; + + if ((ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) { + /* Only free shared data on non-CoW copies */ + BKE_ptcache_free_list(&sb->shared->ptcaches); + sb->shared->pointcache = NULL; + MEM_freeN(sb->shared); + } if (sb->effector_weights) MEM_freeN(sb->effector_weights); MEM_freeN(sb); @@ -3608,7 +3614,7 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c float dtime, timescale; int framedelta, framenr, startframe, endframe; int cache_result; - cache= sb->pointcache; + cache= sb->shared->pointcache; framenr= (int)cfra; framedelta= framenr - cache->simframe; @@ -3676,7 +3682,8 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c } /* try to read from cache */ - bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED); + bool can_write_cache = DEG_is_active(depsgraph); + bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) && can_write_cache; cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate); @@ -3687,7 +3694,7 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c BKE_ptcache_validate(cache, framenr); - if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED && can_write_cache) BKE_ptcache_write(&pid, framenr); sb->last_frame = framenr; @@ -3699,7 +3706,9 @@ void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float c } else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */ /* if baked and nothing in cache, do nothing */ - BKE_ptcache_invalidate(cache); + if (can_write_cache) { + BKE_ptcache_invalidate(cache); + } return; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 79a552a5b86..2a48bf8fc5a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5437,7 +5437,18 @@ static void direct_link_object(FileData *fd, Object *ob) if (!sb->effector_weights) sb->effector_weights = BKE_add_effector_weights(NULL); - direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, 0); + sb->shared = newdataadr(fd, sb->shared); + if (sb->shared == NULL) { + /* Link deprecated caches if they exist, so we can use them for versioning. + * We should only do this when sb->shared == NULL, because those pointers + * are always set (for compatibility with older Blenders). We mustn't link + * the same pointcache twice. */ + direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, false); + } + else { + /* link caches */ + direct_link_pointcache_list(fd, &sb->shared->ptcaches, &sb->shared->pointcache, false); + } } ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */ diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 3fa059989a3..757e17ce82b 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1559,5 +1559,24 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!DNA_struct_elem_find(fd->filesdna, "SoftBody", "SoftBody_Shared", "*shared")) { + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + SoftBody *sb = ob->soft; + if (sb == NULL) { + continue; + } + if (sb->shared == NULL) { + sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared"); + } + + /* Move shared pointers from deprecated location to current location */ + sb->shared->pointcache = sb->pointcache; + sb->shared->ptcaches = sb->ptcaches; + + sb->pointcache = NULL; + BLI_listbase_clear(&sb->ptcaches); + } + } + } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e7bca4c7e5b..146494e6196 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1816,9 +1816,13 @@ static void write_object(WriteData *wd, Object *ob) write_motionpath(wd, ob->mpath); writestruct(wd, DATA, PartDeflect, 1, ob->pd); - writestruct(wd, DATA, SoftBody, 1, ob->soft); if (ob->soft) { - write_pointcaches(wd, &ob->soft->ptcaches); + /* Set deprecated pointers to prevent crashes of older Blenders */ + ob->soft->pointcache = ob->soft->shared->pointcache; + ob->soft->ptcaches = ob->soft->shared->ptcaches; + writestruct(wd, DATA, SoftBody, 1, ob->soft); + writestruct(wd, DATA, SoftBody_Shared, 1, ob->soft->shared); + write_pointcaches(wd, &(ob->soft->shared->ptcaches)); writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights); } diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h index ac7c969a810..3538abcff1a 100644 --- a/source/blender/makesdna/DNA_object_force_types.h +++ b/source/blender/makesdna/DNA_object_force_types.h @@ -37,6 +37,7 @@ extern "C" { #endif #include "DNA_listBase.h" +#include "DNA_defs.h" /* pd->forcefield: Effector Fields types */ typedef enum ePFieldType { @@ -218,6 +219,15 @@ typedef struct SBVertex { float vec[4]; } SBVertex; +/* Container for data that is shared among CoW copies. + * + * This is placed in a separate struct so that values can be changed + * without having to update all CoW copies. */ +typedef struct SoftBody_Shared { + struct PointCache *pointcache; + struct ListBase ptcaches; +} SoftBody_Shared; + typedef struct SoftBody { /* dynamic data */ int totpoint, totspring; @@ -289,8 +299,9 @@ typedef struct SoftBody { float shearstiff; float inpush; - struct PointCache *pointcache; - struct ListBase ptcaches; + struct SoftBody_Shared *shared; + struct PointCache *pointcache DNA_DEPRECATED; /* Moved to SoftBody_Shared */ + struct ListBase ptcaches DNA_DEPRECATED; /* Moved to SoftBody_Shared */ struct Collection *collision_group; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index f0001852da2..a2a21a194ea 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -716,7 +716,7 @@ static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr) static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; - return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->pointcache); + return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->shared->pointcache); } static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr) |