Sculpt: Fix redo panel bugs

SCULPT_undo_push_begin no longer takes an explicit
name.  Instead it takes a wmOperator pointer and uses
op->type->name for the name.  This is necassary for
the redo panel to work and should fix the entire class
of bugs related to misspelled undo push names.

Cases where the calling operator is not registered
may use SCULPT_undo_push_begin_ex if desired; it
takes a name string as before.
This commit is contained in:
Joseph Eagar 2022-08-15 14:52:02 -07:00
parent 6b49b54bb1
commit 3f9299e45d
Notes: blender-bot 2023-10-12 12:49:04 +02:00
Referenced by issue #101209, Regression: Crash on changing the face sets threshold
Referenced by issue #101141, Scaling in sculpting mode. Numeric input - unpredictable behavior.
Referenced by issue #93113, Redo Panel of transform sculpt operation does not work properly
24 changed files with 93 additions and 65 deletions

View File

@ -20,6 +20,7 @@ struct rcti;
struct wmMsgSubscribeKey;
struct wmMsgSubscribeValue;
struct wmRegionMessageSubscribeParams;
struct wmOperator;
/* sculpt.c */
@ -33,7 +34,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C,
/* sculpt_transform.c */
void ED_sculpt_update_modal_transform(struct bContext *C, struct Object *ob);
void ED_sculpt_init_transform(struct bContext *C, struct Object *ob);
void ED_sculpt_init_transform(struct bContext *C, struct Object *ob, const char *undo_name);
void ED_sculpt_end_transform(struct bContext *C, struct Object *ob);
/* sculpt_undo.c */
@ -41,7 +42,12 @@ void ED_sculpt_end_transform(struct bContext *C, struct Object *ob);
/** Export for ED_undo_sys. */
void ED_sculpt_undosys_type(struct UndoType *ut);
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name);
/* Pushes an undo step using the operator name. This is necassary for
* redo panels to work; operators that do not support that may use
* ED_sculpt_undo_geometry_begin_ex instead if so desired.
*/
void ED_sculpt_undo_geometry_begin(struct Object *ob, const struct wmOperator *op);
void ED_sculpt_undo_geometry_begin_ex(struct Object *ob, const char *name);
void ED_sculpt_undo_geometry_end(struct Object *ob);
/* Face sets. */

View File

@ -486,7 +486,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
Mesh *new_mesh = (Mesh *)BKE_id_copy(bmain, &mesh->id);
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_begin(ob, "mask slice");
ED_sculpt_undo_geometry_begin(ob, op);
}
BMesh *bm;

View File

@ -144,7 +144,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
}
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_begin(ob, op->type->name);
ED_sculpt_undo_geometry_begin(ob, op);
}
if (mesh->flag & ME_REMESH_FIX_POLES && mesh->remesh_voxel_adaptivity <= 0.0f) {
@ -654,6 +654,7 @@ struct QuadriFlowJob {
short *stop, *do_update;
float *progress;
const struct wmOperator *op;
Scene *scene;
int target_faces;
int seed;
@ -891,7 +892,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
new_mesh = remesh_symmetry_mirror(qj->owner, new_mesh, qj->symmetry_axes);
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_begin(ob, "QuadriFlow Remesh");
ED_sculpt_undo_geometry_begin(ob, qj->op);
}
if (qj->preserve_paint_mask) {
@ -949,6 +950,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
{
QuadriFlowJob *job = (QuadriFlowJob *)MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob");
job->op = op;
job->owner = CTX_data_active_object(C);
job->scene = CTX_data_scene(C);

View File

@ -351,10 +351,10 @@ static int hide_show_exec(bContext *C, wmOperator *op)
/* Start undo. */
switch (action) {
case PARTIALVIS_HIDE:
SCULPT_undo_push_begin(ob, "Hide area");
SCULPT_undo_push_begin_ex(ob, "Hide area");
break;
case PARTIALVIS_SHOW:
SCULPT_undo_push_begin(ob, "Show area");
SCULPT_undo_push_begin_ex(ob, "Show area");
break;
}

View File

@ -152,7 +152,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
SCULPT_undo_push_begin(ob, "Mask flood fill");
SCULPT_undo_push_begin(ob, op);
MaskTaskData data = {
.ob = ob,
@ -687,10 +687,10 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P
return false;
}
static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext)
static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext, wmOperator *op)
{
SculptGestureOperation *operation = sgcontext->operation;
SCULPT_undo_push_begin(CTX_data_active_object(C), "Sculpt Gesture Apply");
SCULPT_undo_push_begin(CTX_data_active_object(C), op);
operation->sculpt_gesture_begin(C, sgcontext);
@ -1502,7 +1502,7 @@ static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_mask_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1514,7 +1514,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_mask_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1526,7 +1526,7 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_mask_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1538,7 +1538,7 @@ static int face_set_gesture_box_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_face_set_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1550,7 +1550,7 @@ static int face_set_gesture_lasso_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_face_set_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1575,7 +1575,7 @@ static int sculpt_trim_gesture_box_exec(bContext *C, wmOperator *op)
}
sculpt_gesture_init_trim_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1616,7 +1616,7 @@ static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_trim_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}
@ -1645,7 +1645,7 @@ static int project_gesture_line_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_project_properties(sgcontext, op);
sculpt_gesture_apply(C, sgcontext);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
}

View File

@ -3957,7 +3957,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BKE_pbvh_ensure_node_loops(ob->sculpt->pbvh);
}
SCULPT_undo_push_begin(ob, "Vertex Paint");
SCULPT_undo_push_begin_ex(ob, "Vertex Paint");
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
paint_stroke_free(C, op, (PaintStroke *)op->customdata);

View File

@ -5382,7 +5382,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT);
}
else {
SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
SCULPT_undo_push_begin_ex(ob, sculpt_tool_name(sd));
}
return true;

View File

@ -1579,7 +1579,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
/* Needs mask data to be available as it is used when solving the constraints. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
SCULPT_undo_push_begin(ob, "Cloth filter");
SCULPT_undo_push_begin(ob, op);
SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);

View File

@ -76,7 +76,7 @@ static bool sculpt_and_dynamic_topology_poll(bContext *C)
/** \name Detail Flood Fill
* \{ */
static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
@ -106,7 +106,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
SCULPT_undo_push_begin(ob, "Dynamic topology flood fill");
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
while (BKE_pbvh_bmesh_update_topology(

View File

@ -274,7 +274,7 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain,
/* May be false in background mode. */
const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true;
if (use_undo) {
SCULPT_undo_push_begin(ob, "Dynamic topology disable");
SCULPT_undo_push_begin_ex(ob, "Dynamic topology disable");
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
}
SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL);
@ -294,7 +294,7 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
/* May be false in background mode. */
const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true;
if (use_undo) {
SCULPT_undo_push_begin(ob, "Dynamic topology enable");
SCULPT_undo_push_begin_ex(ob, "Dynamic topology enable");
}
SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
if (use_undo) {

View File

@ -2124,7 +2124,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
sculpt_expand_ensure_sculptsession_data(ob);
/* Initialize undo. */
SCULPT_undo_push_begin(ob, "expand");
SCULPT_undo_push_begin(ob, op);
sculpt_expand_undo_push(ob, ss->expand_cache);
/* Set the initial element for expand from the event position. */

View File

@ -317,7 +317,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, "face set change");
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
const int next_face_set = SCULPT_face_set_next_available_get(ss);
@ -707,7 +707,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, "face set change");
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
const float threshold = RNA_float_get(op->ptr, "threshold");
@ -856,7 +856,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
const int active_face_set = SCULPT_active_face_set_get(ss);
SCULPT_undo_push_begin(ob, "Hide area");
SCULPT_undo_push_begin(ob, op);
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
@ -1317,9 +1317,10 @@ static void sculpt_face_set_edit_modify_geometry(bContext *C,
Object *ob,
const int active_face_set,
const eSculptFaceSetEditMode mode,
const bool modify_hidden)
const bool modify_hidden,
wmOperator *op)
{
ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry");
ED_sculpt_undo_geometry_begin(ob, op);
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
ED_sculpt_undo_geometry_end(ob);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@ -1349,7 +1350,8 @@ static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **node
static void sculpt_face_set_edit_modify_face_sets(Object *ob,
const int active_face_set,
const eSculptFaceSetEditMode mode,
const bool modify_hidden)
const bool modify_hidden,
wmOperator *op)
{
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
@ -1359,7 +1361,7 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
if (!nodes) {
return;
}
SCULPT_undo_push_begin(ob, "face set edit");
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
SCULPT_undo_push_end(ob);
@ -1370,7 +1372,8 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
static void sculpt_face_set_edit_modify_coordinates(bContext *C,
Object *ob,
const int active_face_set,
const eSculptFaceSetEditMode mode)
const eSculptFaceSetEditMode mode,
wmOperator *op)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = ob->sculpt;
@ -1378,7 +1381,7 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C,
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
SCULPT_undo_push_begin(ob, "face set edit");
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update(nodes[i]);
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COORDS);
@ -1421,15 +1424,15 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
switch (mode) {
case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY:
sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden);
sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden, op);
break;
case SCULPT_FACE_SET_EDIT_GROW:
case SCULPT_FACE_SET_EDIT_SHRINK:
sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden);
sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden, op);
break;
case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS:
case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY:
sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode);
sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode, op);
break;
}

View File

@ -346,7 +346,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, "color filter");
SCULPT_undo_push_begin(ob, op);
BKE_sculpt_color_layer_create_if_needed(ob);
/* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of

View File

@ -193,7 +193,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
int num_verts = SCULPT_vertex_count_get(ss);
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
SCULPT_undo_push_begin(ob, "Mask Filter");
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
@ -409,7 +409,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
}
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
SCULPT_undo_push_begin(ob, "Dirty Mask");
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);

View File

@ -694,7 +694,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_boundary_info_ensure(ob);
}
SCULPT_undo_push_begin(ob, "Mesh Filter");
SCULPT_undo_push_begin(ob, op);
SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);

View File

@ -1493,11 +1493,17 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node, SculptUndoType type);
SculptUndoNode *SCULPT_undo_get_first_node(void);
/**
* NOTE: `name` must match operator name for
* redo panels to work.
/* Pushes an undo step using the operator name. This is necassary for
* redo panels to work; operators that do not support that may use
* SCULPT_undo_push_begin_ex instead if so desired.
*/
void SCULPT_undo_push_begin(struct Object *ob, const char *name);
void SCULPT_undo_push_begin(struct Object *ob, const struct wmOperator *op);
/**
* NOTE: SCULPT_undo_push_begin is preferred since `name`
* must match operator name for redo panels to work.
*/
void SCULPT_undo_push_begin_ex(struct Object *ob, const char *name);
void SCULPT_undo_push_end(struct Object *ob);
void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo);

View File

@ -361,7 +361,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
BKE_pbvh_search_gather(pbvh, NULL, NULL, &ss->filter_cache->nodes, &ss->filter_cache->totnode);
SCULPT_undo_push_begin(ob, "Mask Expand");
SCULPT_undo_push_begin(ob, op);
if (create_face_set) {
SCULPT_undo_push_node(ob, ss->filter_cache->nodes[0], SCULPT_UNDO_FACE_SETS);

View File

@ -131,7 +131,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, "init mask");
SCULPT_undo_push_begin(ob, op);
if (mode == SCULPT_MASK_INIT_RANDOM_PER_LOOSE_PART) {
SCULPT_connected_components_ensure(ob);

View File

@ -215,7 +215,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op)
* as deleted, then after symmetrize operation all BMesh elements
* are logged as added (as opposed to attempting to store just the
* parts that symmetrize modifies). */
SCULPT_undo_push_begin(ob, "Dynamic topology symmetrize");
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
BM_log_before_all_removed(ss->bm, ss->bm_log);
@ -242,7 +242,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op)
break;
case PBVH_FACES:
/* Mesh Symmetrize. */
ED_sculpt_undo_geometry_begin(ob, "mesh symmetrize");
ED_sculpt_undo_geometry_begin(ob, op);
Mesh *mesh = ob->data;
BKE_mesh_mirror_apply_mirror_on_axis(bmain, mesh, sd->symmetrize_direction, dist);
@ -394,7 +394,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
bool has_undo = wm->undo_stack != NULL;
/* Undo push is needed to prevent memory leak. */
if (has_undo) {
SCULPT_undo_push_begin(ob, "Dynamic topology enable");
SCULPT_undo_push_begin_ex(ob, "Dynamic topology enable");
}
SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
if (has_undo) {
@ -510,7 +510,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
* while it works it causes lag when undoing the first undo step, see T71564. */
wmWindowManager *wm = CTX_wm_manager(C);
if (wm->op_undo_depth <= 1) {
SCULPT_undo_push_begin(ob, op->type->name);
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_end(ob);
}
}
@ -921,7 +921,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
const float mval_fl[2] = {UNPACK2(event->mval)};
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
SCULPT_undo_push_begin(ob, "Mask by color");
SCULPT_undo_push_begin(ob, op);
BKE_sculpt_color_layer_create_if_needed(ob);
const PBVHVertRef active_vertex = SCULPT_active_vertex_get(ss);

View File

@ -46,7 +46,7 @@
#include <math.h>
#include <stdlib.h>
void ED_sculpt_init_transform(struct bContext *C, Object *ob)
void ED_sculpt_init_transform(struct bContext *C, Object *ob, const char *undo_name)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = ob->sculpt;
@ -60,7 +60,7 @@ void ED_sculpt_init_transform(struct bContext *C, Object *ob)
copy_v4_v4(ss->prev_pivot_rot, ss->pivot_rot);
copy_v3_v3(ss->prev_pivot_scale, ss->pivot_scale);
SCULPT_undo_push_begin(ob, "Transform");
SCULPT_undo_push_begin_ex(ob, undo_name);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
ss->pivot_rot[3] = 1.0f;
@ -351,11 +351,6 @@ void ED_sculpt_end_transform(struct bContext *C, Object *ob)
if (ss->filter_cache) {
SCULPT_filter_cache_free(ss);
}
/* Force undo push to happen even inside transform operator, since the sculpt
* undo system works separate from regular undo and this is require to properly
* finish an undo step also when canceling. */
const bool use_nested_undo = true;
SCULPT_undo_push_end_ex(ob, use_nested_undo);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
}

View File

@ -1546,7 +1546,12 @@ static void sculpt_save_active_attribute(Object *ob, SculptAttrRef *attr)
attr->was_set = true;
}
void SCULPT_undo_push_begin(Object *ob, const char *name)
void SCULPT_undo_push_begin(Object *ob, const wmOperator *op)
{
SCULPT_undo_push_begin_ex(ob, op->type->name);
}
void SCULPT_undo_push_begin_ex(Object *ob, const char *name)
{
UndoStack *ustack = ED_undo_stack_get();
@ -1834,9 +1839,15 @@ static void sculpt_undosys_step_free(UndoStep *us_p)
sculpt_undo_free_list(&us->data.nodes);
}
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name)
void ED_sculpt_undo_geometry_begin(struct Object *ob, const wmOperator *op)
{
SCULPT_undo_push_begin(ob, name);
SCULPT_undo_push_begin(ob, op);
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
}
void ED_sculpt_undo_geometry_begin_ex(struct Object *ob, const char *name)
{
SCULPT_undo_push_begin_ex(ob, name);
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
}
@ -1949,7 +1960,7 @@ void ED_sculpt_undo_push_multires_mesh_begin(bContext *C, const char *str)
Object *object = CTX_data_active_object(C);
SCULPT_undo_push_begin(object, str);
SCULPT_undo_push_begin_ex(object, str);
SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY);
geometry_unode->geometry_clear_pbvh = false;

View File

@ -656,6 +656,9 @@ typedef struct TransInfo {
/** Typically for mode settings. */
TransCustomDataContainer custom;
/* Needed for sculpt transform. */
const char *undo_name;
} TransInfo;
/** \} */

View File

@ -85,7 +85,7 @@ static void createTransSculpt(bContext *C, TransInfo *t)
copy_m3_m4(td->axismtx, ob->obmat);
BLI_assert(!(t->options & CTX_PAINT_CURVE));
ED_sculpt_init_transform(C, ob);
ED_sculpt_init_transform(C, ob, t->undo_name);
}
/** \} */

View File

@ -379,6 +379,8 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event)
if (op->customdata == NULL) {
TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
t->undo_name = op->type->name;
int mode = transformops_mode(op);
retval = initTransform(C, t, op, event, mode);