Fix broken pointcache on disk in some cases.

Root of the issue is that point caches are added to the object's list
on-demand, which often ends up with them being added only during
depsgraph evaluation, i.e. on COW objects.

This could result in having 'orig' data caches with invalid/unset stack
index at some points (e.g. when reading a file and applying
liboverrides), leading to discarding valid existing disk cache files.
Fact that one of those index is signed, and the other not, does not
help...

While this is very weak, fixing broken PointCache code is out of the
scope of a bug fix, so this patch merely:
* Simplifies and factorizes the code generating the 'extension' part of
  caches filenames;
* Ensures `BKE_object_insert_ptcache` is called when needed so that we
  always have a valid stack index to generate that filename extension.

This is only a bandaid, but it is simple and should be safe enough for
now.

Related to T82503.
This commit is contained in:
Bastien Montagne 2020-11-16 12:29:21 +01:00
parent 97d52daf96
commit 13bcb000fa
Notes: blender-bot 2023-02-13 20:36:20 +01:00
Referenced by issue #82503, Add Support of PointCaches to Library Overrides
2 changed files with 60 additions and 31 deletions

View File

@ -4311,6 +4311,10 @@ static int pc_cmp(const void *a, const void *b)
return 0;
}
/* TODO: Review the usages of this function, currently with COW it will be called for orig object
* and then again for COW copies of it, think this is bad since there is no guarantee that we get
* the same stack index in both cases? Order is important since this index is used for filenames on
* disk. */
int BKE_object_insert_ptcache(Object *ob)
{
LinkData *link = NULL;

View File

@ -1366,6 +1366,58 @@ static int ptcache_path(PTCacheID *pid, char *filename)
return BLI_path_slash_ensure(filename); /* new strlen() */
}
static size_t ptcache_filename_ext_append(PTCacheID *pid,
char *filename,
const size_t filename_len,
const bool use_frame_number,
const int cfra)
{
size_t len = filename_len;
char *filename_ext;
filename_ext = filename + filename_len;
*filename_ext = '\0';
/* PointCaches are inserted in object's list on demand, we need a valid index now. */
if (pid->cache->index < 0) {
BLI_assert(GS(pid->owner_id->name) == ID_OB);
pid->cache->index = pid->stack_index = BKE_object_insert_ptcache((Object *)pid->owner_id);
}
const char *ext = ptcache_file_extension(pid);
if (use_frame_number) {
if (pid->cache->flag & PTCACHE_EXTERNAL) {
if (pid->cache->index >= 0) {
len += BLI_snprintf_rlen(
filename_ext, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
}
else {
len += BLI_snprintf_rlen(filename_ext, MAX_PTCACHE_FILE - len, "_%06d%s", cfra, ext);
}
}
else {
len += BLI_snprintf_rlen(
filename_ext, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
}
}
else {
if (pid->cache->flag & PTCACHE_EXTERNAL) {
if (pid->cache->index >= 0) {
len += BLI_snprintf_rlen(
filename_ext, MAX_PTCACHE_FILE - len, "_%02u%s", pid->stack_index, ext);
}
else {
len += BLI_snprintf_rlen(filename_ext, MAX_PTCACHE_FILE - len, "%s", ext);
}
}
else {
len += BLI_snprintf_rlen(
filename_ext, MAX_PTCACHE_FILE - len, "_%02u%s", pid->stack_index, ext);
}
}
return len;
}
static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
{
int len = 0;
@ -1400,28 +1452,7 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
}
if (do_ext) {
if (pid->cache->index < 0) {
BLI_assert(GS(pid->owner_id->name) == ID_OB);
pid->cache->index = pid->stack_index = BKE_object_insert_ptcache((Object *)pid->owner_id);
}
const char *ext = ptcache_file_extension(pid);
if (pid->cache->flag & PTCACHE_EXTERNAL) {
if (pid->cache->index >= 0) {
/* Always 6 chars. */
BLI_snprintf(newname, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
}
else {
/* Always 6 chars. */
BLI_snprintf(newname, MAX_PTCACHE_FILE - len, "_%06d%s", cfra, ext);
}
}
else {
/* Always 6 chars. */
BLI_snprintf(newname, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
}
len += 16;
len += ptcache_filename_ext_append(pid, filename, (size_t)len, true, cfra);
}
return len; /* make sure the above string is always 16 chars */
@ -2591,8 +2622,6 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
/*if (!G.relbase_valid) return; */ /* save blend file before using pointcache */
const char *fext = ptcache_file_extension(pid);
/* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
switch (mode) {
case PTCACHE_CLEAR_ALL:
@ -2615,7 +2644,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
len += 1;
}
BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
ptcache_filename_ext_append(pid, ext, 0, false, 0);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
@ -2812,9 +2841,7 @@ void BKE_ptcache_id_time(
return;
}
const char *fext = ptcache_file_extension(pid);
BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
ptcache_filename_ext_append(pid, ext, 0, false, 0);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
@ -3526,9 +3553,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
return;
}
const char *fext = ptcache_file_extension(pid);
BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
ptcache_filename_ext_append(pid, ext, 0, false, 0);
/* put new name into cache */
BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));