Assets: Sanitize threaded preview creation with undo

Basically, this fixes disappearing previews when editing asset metadata
or performing undo/redo actions.

The preview generation in a background job will eventually modify ID
data, but the undo push was done prior to that. So obviously, an undo
then would mean the preview is lost.

This patch makes it so undo/redo will regenerate the preview, if the preview
rendering was invoked but not finished in the undone/redone state.

The preview flag PRV_UNFINISHED wasn't entirely what we needed. So I had to
change it to a slightly different flag, with different semantics.
This commit is contained in:
2021-11-24 11:20:35 +01:00
parent 785503a7e4
commit cd818fd081
10 changed files with 115 additions and 20 deletions

View File

@@ -103,6 +103,8 @@
#include "ED_view3d.h"
#include "ED_view3d_offscreen.h"
#include "UI_interface_icons.h"
#ifndef NDEBUG
/* Used for database init assert(). */
# include "BLI_threads.h"
@@ -1948,4 +1950,45 @@ void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
}
}
typedef struct PreviewRestartQueueEntry {
struct PreviewRestartQueueEntry *next, *prev;
enum eIconSizes size;
ID *id;
} PreviewRestartQueueEntry;
static ListBase /* #PreviewRestartQueueEntry */ G_restart_previews_queue;
void ED_preview_restart_queue_free(void)
{
BLI_freelistN(&G_restart_previews_queue);
}
void ED_preview_restart_queue_add(ID *id, enum eIconSizes size)
{
PreviewRestartQueueEntry *queue_entry = MEM_mallocN(sizeof(*queue_entry), __func__);
queue_entry->size = size;
queue_entry->id = id;
BLI_addtail(&G_restart_previews_queue, queue_entry);
}
void ED_preview_restart_queue_work(const bContext *C)
{
LISTBASE_FOREACH_MUTABLE (PreviewRestartQueueEntry *, queue_entry, &G_restart_previews_queue) {
PreviewImage *preview = BKE_previewimg_id_get(queue_entry->id);
if (!preview) {
continue;
}
if (preview->flag[queue_entry->size] & PRV_USER_EDITED) {
/* Don't touch custom previews. */
continue;
}
BKE_previewimg_clear_single(preview, queue_entry->size);
UI_icon_render_id(C, NULL, queue_entry->id, queue_entry->size, true);
BLI_freelinkN(&G_restart_previews_queue, queue_entry);
}
}
/** \} */