diff options
24 files changed, 227 insertions, 62 deletions
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 47c8f31ead3..1b9e318146e 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -79,6 +79,13 @@ typedef struct BMEditMesh { /*temp variables for x-mirror editing*/ int mirror_cdlayer; /* -1 is invalid */ + + /** + * ID data is older than edit-mode data. + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; + } BMEditMesh; /* editmesh.c */ diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index e440d617f7a..3dd2a551a93 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -61,6 +61,12 @@ typedef struct EditFont { int len, pos; int selstart, selend; + /** + * ID data is older than edit-mode data. + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; + } EditFont; bool BKE_vfont_is_builtin(struct VFont *vfont); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 1b2e8bcbf42..c48a9cad443 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -80,6 +80,11 @@ typedef struct Main { char recovered; /* indicate the main->name (file) is the recovered one */ /** All current ID's exist in the last memfile undo step. */ char is_memfile_undo_written; + /** + * An ID needs it's data to be flushed back. + * use "needs_flush_to_id" in edit data to flag data which needs updating. + */ + char is_memfile_undo_flush_needed; BlendThumbnail *blen_thumb; diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index ffdcb9cd2c0..d76c55f0815 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -99,6 +99,8 @@ bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode) bool BKE_object_data_is_in_editmode(const struct ID *id); +char *BKE_object_data_editmode_flush_ptr_get(struct ID *id); + void BKE_object_update_select_id(struct Main *bmain); typedef enum eObjectVisibilityResult { diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 4413ad2a70f..48f9e1fd95e 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -306,6 +306,13 @@ typedef struct SculptSession { /* This flag prevents PBVH from being freed when creating the vp_handle for texture paint. */ bool building_vp_handle; + + /** + * ID data is older than sculpt-mode data. + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; + } SculptSession; void BKE_sculptsession_free(struct Object *ob); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 773e2d19b22..b50e152527e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -81,6 +81,7 @@ #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_effect.h" +#include "BKE_font.h" #include "BKE_fcurve.h" #include "BKE_gpencil_modifier.h" #include "BKE_icons.h" @@ -629,6 +630,54 @@ bool BKE_object_data_is_in_editmode(const ID *id) } } +char *BKE_object_data_editmode_flush_ptr_get(struct ID *id) +{ + const short type = GS(id->name); + switch (type) { + case ID_ME: { + BMEditMesh *em = ((Mesh *)id)->edit_mesh; + if (em != NULL) { + return &em->needs_flush_to_id; + } + break; + } + case ID_CU: { + if (((Curve *)id)->vfont != NULL) { + EditFont *ef = ((Curve *)id)->editfont; + if (ef != NULL) { + return &ef->needs_flush_to_id; + } + } + else { + EditNurb *editnurb = ((Curve *)id)->editnurb; + if (editnurb) { + return &editnurb->needs_flush_to_id; + } + } + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)id; + return &mb->needs_flush_to_id; + } + case ID_LT: { + EditLatt *editlatt = ((Lattice *)id)->editlatt; + if (editlatt) { + return &editlatt->needs_flush_to_id; + } + break; + } + case ID_AR: { + bArmature *arm = (bArmature *)id; + return &arm->needs_flush_to_id; + } + default: + BLI_assert(0); + return NULL; + } + return NULL; +} + bool BKE_object_is_in_wpaint_select_vert(const Object *ob) { if (ob->type == OB_MESH) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3866878b12a..452e75081d6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3862,6 +3862,8 @@ static void direct_link_armature(FileData *fd, bArmature *arm) link_list(fd, &arm->bonebase); arm->bonehash = NULL; arm->edbo = NULL; + /* Must always be cleared (armatures don't have their own edit-data). */ + arm->needs_flush_to_id = 0; arm->adt = newdataadr(fd, arm->adt); direct_link_animdata(fd, arm->adt); @@ -4079,6 +4081,8 @@ static void direct_link_mball(FileData *fd, MetaBall *mb) BLI_listbase_clear(&mb->disp); mb->editelems = NULL; + /* Must always be cleared (meta's don't have their own edit-data). */ + mb->needs_flush_to_id = 0; /* mb->edit_elems.first= mb->edit_elems.last= NULL;*/ mb->lastelem = NULL; mb->batch_cache = NULL; diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index 4a82a8fccee..4e3ab11a9f7 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -32,6 +32,7 @@ #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_main.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" @@ -142,9 +143,7 @@ static bool armature_undosys_poll(bContext *C) return editarm_object_from_context(C) != NULL; } -static bool armature_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { ArmatureUndoStep *us = (ArmatureUndoStep *)us_p; @@ -165,17 +164,18 @@ static bool armature_undosys_step_encode(struct bContext *C, elem->obedit_ref.ptr = ob; bArmature *arm = elem->obedit_ref.ptr->data; undoarm_from_editarm(&elem->data, arm); + arm->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; } MEM_freeN(objects); + + bmain->is_memfile_undo_flush_needed = true; + return true; } -static void armature_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void armature_undosys_step_decode( + struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { ArmatureUndoStep *us = (ArmatureUndoStep *)us_p; @@ -198,6 +198,7 @@ static void armature_undosys_step_decode(struct bContext *C, continue; } undoarm_to_editarm(&elem->data, arm); + arm->needs_flush_to_id = 1; DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } @@ -205,6 +206,8 @@ static void armature_undosys_step_decode(struct bContext *C, ED_undo_object_set_active_or_warn( CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); + bmain->is_memfile_undo_flush_needed = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index f21b4f06246..ff3a1386fd9 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -208,9 +208,7 @@ static bool curve_undosys_poll(bContext *C) return (obedit != NULL); } -static bool curve_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { CurveUndoStep *us = (CurveUndoStep *)us_p; @@ -226,13 +224,18 @@ static bool curve_undosys_step_encode(struct bContext *C, for (uint i = 0; i < objects_len; i++) { Object *ob = objects[i]; + Curve *cu = ob->data; CurveUndoStep_Elem *elem = &us->elems[i]; elem->obedit_ref.ptr = ob; undocurve_from_editcurve(&elem->data, ob->data, ob->shapenr); + cu->editnurb->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; } MEM_freeN(objects); + + bmain->is_memfile_undo_flush_needed = true; + return true; } @@ -260,6 +263,7 @@ static void curve_undosys_step_decode( continue; } undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); + cu->editnurb->needs_flush_to_id = 1; DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } @@ -267,6 +271,8 @@ static void curve_undosys_step_decode( ED_undo_object_set_active_or_warn( CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); + bmain->is_memfile_undo_flush_needed = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index ae858ec4c24..26c0e5cf6c9 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -32,6 +32,7 @@ #include "BKE_context.h" #include "BKE_font.h" +#include "BKE_main.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" @@ -341,23 +342,21 @@ static bool font_undosys_poll(bContext *C) return editfont_object_from_context(C) != NULL; } -static bool font_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool font_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { FontUndoStep *us = (FontUndoStep *)us_p; us->obedit_ref.ptr = editfont_object_from_context(C); Curve *cu = us->obedit_ref.ptr->data; undofont_from_editfont(&us->data, cu); us->step.data_size = us->data.undo_size; + cu->editfont->needs_flush_to_id = 1; + bmain->is_memfile_undo_flush_needed = true; + return true; } -static void font_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void font_undosys_step_decode( + struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { /* TODO(campbell): undo_system: use low-level API to set mode. */ ED_object_mode_set(C, OB_MODE_EDIT); @@ -368,6 +367,8 @@ static void font_undosys_step_decode(struct bContext *C, Curve *cu = obedit->data; undofont_to_editfont(&us->data, cu); DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + cu->editfont->needs_flush_to_id = 1; + bmain->is_memfile_undo_flush_needed = true; WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h index 8ffae0f2b66..5afb645d9e7 100644 --- a/source/blender/editors/include/ED_mball.h +++ b/source/blender/editors/include/ED_mball.h @@ -25,6 +25,7 @@ #define __ED_MBALL_H__ struct Base; +struct MetaBall; struct Object; struct UndoType; struct bContext; diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 87f57b4e144..003e84bbf05 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -34,6 +34,8 @@ struct wmOperatorType; void ED_editors_init_for_undo(struct Main *bmain); void ED_editors_init(struct bContext *C); void ED_editors_exit(struct Main *bmain, bool do_undo_system); + +bool ED_editors_flush_edits_ex(struct Main *bmain, bool for_render, bool check_needs_flush); bool ED_editors_flush_edits(struct Main *bmain, bool for_render); void ED_spacedata_id_remap(struct ScrArea *sa, diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index abc5224c4d6..2790e6b5558 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -39,6 +39,7 @@ #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_main.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" @@ -154,9 +155,7 @@ static bool lattice_undosys_poll(bContext *C) return editlatt_object_from_context(C) != NULL; } -static bool lattice_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoStep *us_p) { LatticeUndoStep *us = (LatticeUndoStep *)us_p; @@ -177,17 +176,18 @@ static bool lattice_undosys_step_encode(struct bContext *C, elem->obedit_ref.ptr = ob; Lattice *lt = ob->data; undolatt_from_editlatt(&elem->data, lt->editlatt); + lt->editlatt->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; } MEM_freeN(objects); + + bmain->is_memfile_undo_flush_needed = true; + return true; } -static void lattice_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void lattice_undosys_step_decode( + struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { LatticeUndoStep *us = (LatticeUndoStep *)us_p; @@ -210,6 +210,7 @@ static void lattice_undosys_step_decode(struct bContext *C, continue; } undolatt_to_editlatt(&elem->data, lt->editlatt); + lt->editlatt->needs_flush_to_id = 1; DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } @@ -217,6 +218,8 @@ static void lattice_undosys_step_decode(struct bContext *C, ED_undo_object_set_active_or_warn( CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); + bmain->is_memfile_undo_flush_needed = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 7071258d8cf..44984251243 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -34,6 +34,7 @@ #include "BKE_context.h" #include "BKE_key.h" #include "BKE_layer.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_editmesh.h" #include "BKE_undo_system.h" @@ -708,9 +709,7 @@ static bool mesh_undosys_poll(bContext *C) return editmesh_object_from_context(C) != NULL; } -static bool mesh_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { MeshUndoStep *us = (MeshUndoStep *)us_p; @@ -730,18 +729,20 @@ static bool mesh_undosys_step_encode(struct bContext *C, elem->obedit_ref.ptr = ob; Mesh *me = elem->obedit_ref.ptr->data; + BMEditMesh *em = me->edit_mesh; undomesh_from_editmesh(&elem->data, me->edit_mesh, me->key); + em->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; } MEM_freeN(objects); + + bmain->is_memfile_undo_flush_needed = true; + return true; } -static void mesh_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void mesh_undosys_step_decode( + struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { MeshUndoStep *us = (MeshUndoStep *)us_p; @@ -765,6 +766,7 @@ static void mesh_undosys_step_decode(struct bContext *C, } BMEditMesh *em = me->edit_mesh; undomesh_to_editmesh(&elem->data, em, obedit->data); + em->needs_flush_to_id = 1; DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } @@ -775,6 +777,8 @@ static void mesh_undosys_step_decode(struct bContext *C, Scene *scene = CTX_data_scene(C); scene->toolsettings->selectmode = us->elems[0].data.selectmode; + bmain->is_memfile_undo_flush_needed = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index 9a95560ccdd..e8700e94e91 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -35,6 +35,7 @@ #include "BKE_context.h" #include "BKE_layer.h" +#include "BKE_main.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" @@ -153,9 +154,7 @@ static bool mball_undosys_poll(bContext *C) return editmball_object_from_context(C) != NULL; } -static bool mball_undosys_step_encode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p) +static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { MBallUndoStep *us = (MBallUndoStep *)us_p; @@ -176,17 +175,18 @@ static bool mball_undosys_step_encode(struct bContext *C, elem->obedit_ref.ptr = ob; MetaBall *mb = ob->data; editmball_from_undomball(&elem->data, mb); + mb->needs_flush_to_id = 1; us->step.data_size += elem->data.undo_size; } MEM_freeN(objects); + + bmain->is_memfile_undo_flush_needed = true; + return true; } -static void mball_undosys_step_decode(struct bContext *C, - struct Main *UNUSED(bmain), - UndoStep *us_p, - int UNUSED(dir), - bool UNUSED(is_final)) +static void mball_undosys_step_decode( + struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { MBallUndoStep *us = (MBallUndoStep *)us_p; @@ -209,6 +209,7 @@ static void mball_undosys_step_decode(struct bContext *C, continue; } undomball_to_editmball(&elem->data, mb); + mb->needs_flush_to_id = 1; DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } @@ -216,6 +217,8 @@ static void mball_undosys_step_decode(struct bContext *C, ED_undo_object_set_active_or_warn( CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); + bmain->is_memfile_undo_flush_needed = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 70d024c7902..be815fb0d10 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -514,6 +514,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f } } + char *needs_flush_ptr = BKE_object_data_editmode_flush_ptr_get(obedit->data); + if (needs_flush_ptr) { + *needs_flush_ptr = false; + } + return true; } @@ -616,10 +621,13 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL); } else if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; ok = 1; - ED_armature_to_edit(ob->data); + ED_armature_to_edit(arm); /* to ensure all goes in restposition and without striding */ + arm->needs_flush_to_id = 0; + /* XXX: should this be ID_RECALC_GEOMETRY? */ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -632,9 +640,13 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene); } else if (ob->type == OB_MBALL) { + MetaBall *mb = ob->data; + ok = 1; ED_mball_editmball_make(ob); + mb->needs_flush_to_id = 0; + WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene); } else if (ob->type == OB_LATTICE) { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index fc990c01bfb..052f2bd03a4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1027,6 +1027,8 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType /* list is manipulated by multiple threads, so we lock */ BLI_thread_lock(LOCK_CUSTOM1); + ss->needs_flush_to_id = 1; + if (ss->bm || ELEM(type, SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END)) { /* Dynamic topology stores only one undo node per stroke, * regardless of the number of PBVH nodes modified */ @@ -1142,17 +1144,6 @@ typedef struct SculptUndoStep { UndoSculpt data; } SculptUndoStep; -static bool sculpt_undosys_poll(bContext *C) -{ - Object *obact = CTX_data_active_object(C); - if (obact && obact->type == OB_MESH) { - if (obact && (obact->mode & OB_MODE_SCULPT)) { - return true; - } - } - return false; -} - static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p) { SculptUndoStep *us = (SculptUndoStep *)us_p; @@ -1161,7 +1152,7 @@ static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep } static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), - struct Main *UNUSED(bmain), + struct Main *bmain, UndoStep *us_p) { /* dummy, encoding is done along the way by adding tiles @@ -1174,6 +1165,11 @@ static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), us->step.use_memfile_step = true; } us->step.is_applied = true; + + if (!BLI_listbase_is_empty(&us->data.nodes)) { + bmain->is_memfile_undo_flush_needed = true; + } + return true; } @@ -1256,7 +1252,11 @@ static void sculpt_undosys_step_decode( me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL); } - BLI_assert(sculpt_undosys_poll(C)); + + if (ob->sculpt) { + ob->sculpt->needs_flush_to_id = 1; + } + bmain->is_memfile_undo_flush_needed = true; } else { BLI_assert(0); @@ -1295,7 +1295,6 @@ void ED_sculpt_undo_geometry_end(struct Object *ob) void ED_sculpt_undosys_type(UndoType *ut) { ut->name = "Sculpt"; - ut->poll = sculpt_undosys_poll; ut->step_encode_init = sculpt_undosys_step_encode_init; ut->step_encode = sculpt_undosys_step_encode; ut->step_decode = sculpt_undosys_step_decode; diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 315a4c73e5f..9770b52158a 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -322,7 +322,7 @@ bool ED_undo_is_memfile_compatible(const bContext *C) if (view_layer != NULL) { Object *obact = OBACT(view_layer); if (obact != NULL) { - if (obact->mode & (OB_MODE_SCULPT | OB_MODE_EDIT)) { + if (obact->mode & OB_MODE_EDIT) { return false; } } diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index f3e2ee92558..a5f30409aa6 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -28,6 +28,7 @@ #include "BKE_blender_undo.h" #include "BKE_context.h" #include "BKE_undo_system.h" +#include "BKE_main.h" #include "WM_api.h" #include "WM_types.h" @@ -74,6 +75,10 @@ static bool memfile_undosys_step_encode(struct bContext *UNUSED(C), /* Important we only use 'main' from the context (see: BKE_undosys_stack_init_from_main). */ UndoStack *ustack = ED_undo_stack_get(); + if (bmain->is_memfile_undo_flush_needed) { + ED_editors_flush_edits_ex(bmain, false, true); + } + /* can be NULL, use when set. */ MemFileUndoStep *us_prev = (MemFileUndoStep *)BKE_undosys_step_find_by_type( ustack, BKE_UNDOSYS_TYPE_MEMFILE); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index f5548119e0a..1a33b50ff10 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -230,7 +230,7 @@ void ED_editors_exit(Main *bmain, bool do_undo_system) /* flush any temp data from object editing to DNA before writing files, * rendering, copying, etc. */ -bool ED_editors_flush_edits(Main *bmain, bool for_render) +bool ED_editors_flush_edits_ex(Main *bmain, bool for_render, bool check_needs_flush) { bool has_edited = false; Object *ob; @@ -244,6 +244,15 @@ bool ED_editors_flush_edits(Main *bmain, bool for_render) * Auto-save prevents this from happening but scripts * may cause a flush on saving: T53986. */ if ((ob->sculpt && ob->sculpt->cache) == 0) { + + { + char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id; + if (check_needs_flush && (*needs_flush_ptr == 0)) { + continue; + } + *needs_flush_ptr = 0; + } + /* flush multires changes (for sculpt) */ multires_flush_sculpt_updates(ob); has_edited = true; @@ -260,15 +269,31 @@ bool ED_editors_flush_edits(Main *bmain, bool for_render) } } else if (ob->mode & OB_MODE_EDIT) { + + char *needs_flush_ptr = BKE_object_data_editmode_flush_ptr_get(ob->data); + if (needs_flush_ptr != NULL) { + if (check_needs_flush && (*needs_flush_ptr == 0)) { + continue; + } + *needs_flush_ptr = 0; + } + /* get editmode results */ has_edited = true; ED_object_editmode_load(bmain, ob); } } + bmain->is_memfile_undo_flush_needed = false; + return has_edited; } +bool ED_editors_flush_edits(Main *bmain, bool for_render) +{ + return ED_editors_flush_edits_ex(bmain, for_render, false); +} + /* ***** XXX: functions are using old blender names, cleanup later ***** */ /* now only used in 2d spaces, like time, ipo, nla, sima... */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 1b2345809ad..3bad2a04a65 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -126,6 +126,10 @@ typedef struct bArmature { /** Active editbone (in editmode). */ struct EditBone *act_edbone; + /** ID data is older than edit-mode data (TODO: move to edit-mode struct). */ + char needs_flush_to_id; + char _pad0[7]; + int flag; int drawtype; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 7a641189bcb..13eaa8925bc 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -206,7 +206,12 @@ typedef struct EditNurb { /* shape key being edited */ int shapenr; - char _pad[4]; + /** + * ID data is older than edit-mode data. + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; + } EditNurb; typedef struct Curve { diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 3864593158d..f67553c34de 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -39,6 +39,12 @@ typedef struct EditLatt { struct Lattice *latt; int shapenr; + + /** + * ID data is older than edit-mode data. + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; } EditLatt; typedef struct Lattice { diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h index c98842eb6d7..8b218dd7ce6 100644 --- a/source/blender/makesdna/DNA_meta_types.h +++ b/source/blender/makesdna/DNA_meta_types.h @@ -81,7 +81,13 @@ typedef struct MetaBall { short totcol; /** Used to store MB_AUTOSPACE. */ short texflag; - char _pad[2]; + char _pad[1]; + + /** + * ID data is older than edit-mode data (TODO: move to edit-mode struct). + * Set #Main.is_memfile_undo_flush_needed when enabling. + */ + char needs_flush_to_id; /* texture space, copied as one block in editobject.c */ float loc[3]; |