Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/undo/memfile_undo.c
| Show All 29 Lines | |||||
| #include "DNA_collection_types.h" | #include "DNA_collection_types.h" | ||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| #include "DNA_object_enums.h" | #include "DNA_object_enums.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "BKE_blender_undo.h" | #include "BKE_blender_undo.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_icons.h" | |||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_lib_query.h" | #include "BKE_lib_query.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_node.h" | #include "BKE_node.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_undo_system.h" | #include "BKE_undo_system.h" | ||||
| #include "../depsgraph/DEG_depsgraph.h" | #include "../depsgraph/DEG_depsgraph.h" | ||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "ED_object.h" | #include "ED_object.h" | ||||
| #include "ED_render.h" | |||||
| #include "ED_undo.h" | #include "ED_undo.h" | ||||
| #include "ED_util.h" | #include "ED_util.h" | ||||
| #include "../blenloader/BLO_undofile.h" | #include "../blenloader/BLO_undofile.h" | ||||
| #include "undo_intern.h" | #include "undo_intern.h" | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | if (id != NULL && !ID_IS_LINKED(id) && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) == 0) { | ||||
| } | } | ||||
| return do_stop_iter ? IDWALK_RET_STOP_ITER : IDWALK_RET_NOP; | return do_stop_iter ? IDWALK_RET_STOP_ITER : IDWALK_RET_NOP; | ||||
| } | } | ||||
| return IDWALK_RET_NOP; | 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, | static void memfile_undosys_step_decode(struct bContext *C, | ||||
| struct Main *bmain, | struct Main *bmain, | ||||
| UndoStep *us_p, | UndoStep *us_p, | ||||
| const eUndoStepDir undo_direction, | const eUndoStepDir undo_direction, | ||||
| bool UNUSED(is_final)) | bool UNUSED(is_final)) | ||||
| { | { | ||||
| BLI_assert(undo_direction != STEP_INVALID); | BLI_assert(undo_direction != STEP_INVALID); | ||||
| Show All 30 Lines | static void memfile_undosys_step_decode(struct bContext *C, | ||||
| /* Extract depsgraphs from current bmain (which may be freed during undo step reading), | /* Extract depsgraphs from current bmain (which may be freed during undo step reading), | ||||
| * and store them for re-use. */ | * and store them for re-use. */ | ||||
| GHash *depsgraphs = NULL; | GHash *depsgraphs = NULL; | ||||
| if (use_old_bmain_data) { | if (use_old_bmain_data) { | ||||
| depsgraphs = BKE_scene_undo_depsgraphs_extract(bmain); | depsgraphs = BKE_scene_undo_depsgraphs_extract(bmain); | ||||
| } | } | ||||
| ED_editors_exit(bmain, false); | 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; | MemFileUndoStep *us = (MemFileUndoStep *)us_p; | ||||
| BKE_memfile_undo_decode(us->data, undo_direction, use_old_bmain_data, C); | BKE_memfile_undo_decode(us->data, undo_direction, use_old_bmain_data, C); | ||||
| for (UndoStep *us_iter = us_p->next; us_iter; us_iter = us_iter->next) { | for (UndoStep *us_iter = us_p->next; us_iter; us_iter = us_iter->next) { | ||||
| if (BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(us_iter->type)) { | if (BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(us_iter->type)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| Show All 35 Lines | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| } | } | ||||
| if (GS(id->name) == ID_SCE) { | if (GS(id->name) == ID_SCE) { | ||||
| Scene *scene = (Scene *)id; | Scene *scene = (Scene *)id; | ||||
| if (scene->master_collection != NULL && scene->master_collection->id.recalc != 0) { | if (scene->master_collection != NULL && scene->master_collection->id.recalc != 0) { | ||||
| DEG_id_tag_update_ex( | DEG_id_tag_update_ex( | ||||
| bmain, &scene->master_collection->id, scene->master_collection->id.recalc); | 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; | FOREACH_MAIN_ID_END; | ||||
| FOREACH_MAIN_ID_BEGIN (bmain, id) { | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| /* Clear temporary tag. */ | /* Clear temporary tag. */ | ||||
| id->tag &= ~LIB_TAG_UNDO_OLD_ID_REUSED; | id->tag &= ~LIB_TAG_UNDO_OLD_ID_REUSED; | ||||
| /* We only start accumulating from this point, any tags set up to here | /* We only start accumulating from this point, any tags set up to here | ||||
| * are already part of the current undo state. This is done in a second | * are already part of the current undo state. This is done in a second | ||||
| * loop because DEG_id_tag_update may set tags on other datablocks. */ | * loop because DEG_id_tag_update may set tags on other datablocks. */ | ||||
| id->recalc_after_undo_push = 0; | id->recalc_after_undo_push = 0; | ||||
| bNodeTree *nodetree = ntreeFromID(id); | bNodeTree *nodetree = ntreeFromID(id); | ||||
| if (nodetree != NULL) { | if (nodetree != NULL) { | ||||
| nodetree->id.recalc_after_undo_push = 0; | nodetree->id.recalc_after_undo_push = 0; | ||||
| } | } | ||||
| if (GS(id->name) == ID_SCE) { | if (GS(id->name) == ID_SCE) { | ||||
| Scene *scene = (Scene *)id; | Scene *scene = (Scene *)id; | ||||
| if (scene->master_collection != NULL) { | if (scene->master_collection != NULL) { | ||||
| scene->master_collection->id.recalc_after_undo_push = 0; | scene->master_collection->id.recalc_after_undo_push = 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| FOREACH_MAIN_ID_END; | 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)); | WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C)); | ||||
| } | } | ||||
| static void memfile_undosys_step_free(UndoStep *us_p) | static void memfile_undosys_step_free(UndoStep *us_p) | ||||
| { | { | ||||
| /* To avoid unnecessary slow down, free backwards | /* To avoid unnecessary slow down, free backwards | ||||
| * (so we don't need to merge when clearing all). */ | * (so we don't need to merge when clearing all). */ | ||||
| ▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines | |||||