Fix T69822: Switching sculpt objects breaks undo

This introduces object mode tagging for data which hasn't yet been
written back to the ID data.

Now when selecting other sculpt objects, the original objects data is
flushed back to the ID before writing a memfile undo step.
This commit is contained in:
Campbell Barton 2019-11-07 16:52:03 +11:00
parent 85637311c2
commit 79b703bb63
Notes: blender-bot 2023-02-14 00:49:40 +01:00
Referenced by commit 7711231838, Fix T71865: Separating mesh parts breaks shape keys
Referenced by issue #71865, Separating mesh parts breaks shape keys
Referenced by issue #71434, Sculpt Performance Regression in 2.81
Referenced by issue #69822, Undo is making objects to disappear in sculpt mode
24 changed files with 227 additions and 62 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -25,6 +25,7 @@
#define __ED_MBALL_H__
struct Base;
struct MetaBall;
struct Object;
struct UndoType;
struct bContext;

View File

@ -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,

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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... */

View File

@ -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;

View File

@ -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 {

View File

@ -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 {

View File

@ -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];