diff options
author | Julian Eisel <julian@blender.org> | 2021-11-24 13:20:35 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-11-24 13:26:37 +0300 |
commit | 3850fdd5b957aa3b8f70d3c0b952b07af6b07fe1 (patch) | |
tree | 790b234b0d86f9c8494a1610a2728a3ff0c59da5 /source/blender/editors/undo | |
parent | 98a5658239bb61a701f20309c741ab895ed92b7a (diff) |
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.
Diffstat (limited to 'source/blender/editors/undo')
-rw-r--r-- | source/blender/editors/undo/memfile_undo.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index 1bdc2b2251e..ee7221bd2a8 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -35,6 +35,7 @@ #include "BKE_blender_undo.h" #include "BKE_context.h" +#include "BKE_icons.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_main.h" @@ -48,6 +49,7 @@ #include "WM_types.h" #include "ED_object.h" +#include "ED_render.h" #include "ED_undo.h" #include "ED_util.h" @@ -142,6 +144,32 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data) return IDWALK_RET_NOP; } +/** + * ID previews may be generated in a parallel job. So whatever operation generates the preview + * likely does the undo push before the preview is actually done and stored in the ID. Hence they + * get some extra treatement here: + * When undoing back to the moment the preview generation was triggered, this function schedules + * the preview for regeneration. + */ +static void memfile_undosys_unfinished_id_previews_restart(ID *id) +{ + PreviewImage *preview = BKE_previewimg_id_get(id); + if (!preview) { + return; + } + + for (int i = 0; i < NUM_ICON_SIZES; i++) { + if (preview->flag[i] & PRV_USER_EDITED) { + /* Don't modify custom previews. */ + continue; + } + + if (!BKE_previewimg_is_finished(preview, i)) { + ED_preview_restart_queue_add(id, i); + } + } +} + static void memfile_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, @@ -188,6 +216,9 @@ static void memfile_undosys_step_decode(struct bContext *C, } ED_editors_exit(bmain, false); + /* Ensure there's no preview job running. Unfinished previews will be scheduled for regeneration + * via #memfile_undosys_unfinished_id_previews_restart(). */ + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); MemFileUndoStep *us = (MemFileUndoStep *)us_p; BKE_memfile_undo_decode(us->data, undo_direction, use_old_bmain_data, C); @@ -239,6 +270,9 @@ static void memfile_undosys_step_decode(struct bContext *C, bmain, &scene->master_collection->id, scene->master_collection->id.recalc); } } + + /* Restart preview generation if the undo state was generating previews. */ + memfile_undosys_unfinished_id_previews_restart(id); } FOREACH_MAIN_ID_END; @@ -263,6 +297,14 @@ static void memfile_undosys_step_decode(struct bContext *C, } FOREACH_MAIN_ID_END; } + else { + ID *id = NULL; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + /* Restart preview generation if the undo state was generating previews. */ + memfile_undosys_unfinished_id_previews_restart(id); + } + FOREACH_MAIN_ID_END; + } WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C)); } |