1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2004 Blender Foundation
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edundo
22 */
23
24 #include <string.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "CLG_log.h"
29
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32
33 #include "BLI_listbase.h"
34 #include "BLI_utildefines.h"
35
36 #include "BLT_translation.h"
37
38 #include "BKE_blender_undo.h"
39 #include "BKE_callbacks.h"
40 #include "BKE_context.h"
41 #include "BKE_global.h"
42 #include "BKE_layer.h"
43 #include "BKE_main.h"
44 #include "BKE_paint.h"
45 #include "BKE_report.h"
46 #include "BKE_scene.h"
47 #include "BKE_screen.h"
48 #include "BKE_undo_system.h"
49 #include "BKE_workspace.h"
50
51 #include "BLO_blend_validate.h"
52
53 #include "ED_gpencil.h"
54 #include "ED_object.h"
55 #include "ED_outliner.h"
56 #include "ED_render.h"
57 #include "ED_screen.h"
58 #include "ED_undo.h"
59
60 #include "WM_api.h"
61 #include "WM_toolsystem.h"
62 #include "WM_types.h"
63
64 #include "RNA_access.h"
65 #include "RNA_define.h"
66
67 #include "UI_interface.h"
68 #include "UI_resources.h"
69
70 /** We only need this locally. */
71 static CLG_LogRef LOG = {"ed.undo"};
72
73 /* -------------------------------------------------------------------- */
74 /** \name Generic Undo System Access
75 *
76 * Non-operator undo editor functions.
77 * \{ */
78
79 /**
80 * Run from the main event loop, basic checks that undo is left in a correct state.
81 */
ED_undo_is_state_valid(bContext * C)82 bool ED_undo_is_state_valid(bContext *C)
83 {
84 wmWindowManager *wm = CTX_wm_manager(C);
85
86 /* Currently only checks matching begin/end calls. */
87 if (wm->undo_stack == NULL) {
88 /* No undo stack is valid, nothing to do. */
89 return true;
90 }
91 if (wm->undo_stack->group_level != 0) {
92 /* If this fails #ED_undo_grouped_begin, #ED_undo_grouped_end calls don't match. */
93 return false;
94 }
95 if (wm->undo_stack->step_active != NULL) {
96 if (wm->undo_stack->step_active->skip == true) {
97 /* Skip is only allowed between begin/end calls,
98 * a state that should never happen in main event loop. */
99 return false;
100 }
101 }
102 return true;
103 }
104
ED_undo_group_begin(bContext * C)105 void ED_undo_group_begin(bContext *C)
106 {
107 wmWindowManager *wm = CTX_wm_manager(C);
108 BKE_undosys_stack_group_begin(wm->undo_stack);
109 }
110
ED_undo_group_end(bContext * C)111 void ED_undo_group_end(bContext *C)
112 {
113 wmWindowManager *wm = CTX_wm_manager(C);
114 BKE_undosys_stack_group_end(wm->undo_stack);
115 }
116
ED_undo_push(bContext * C,const char * str)117 void ED_undo_push(bContext *C, const char *str)
118 {
119 CLOG_INFO(&LOG, 1, "name='%s'", str);
120 WM_file_tag_modified();
121
122 wmWindowManager *wm = CTX_wm_manager(C);
123 int steps = U.undosteps;
124
125 /* Ensure steps that have been initialized are always pushed,
126 * even when undo steps are zero.
127 *
128 * Note that some modes (paint, sculpt) initialize an undo step before an action runs,
129 * then accumulate changes there, or restore data from it in the case of 2D painting.
130 *
131 * For this reason we need to handle the undo step even when undo steps is set to zero.
132 */
133 if ((steps <= 0) && wm->undo_stack->step_init != NULL) {
134 steps = 1;
135 }
136 if (steps <= 0) {
137 return;
138 }
139 if (G.background) {
140 /* Python developers may have explicitly created the undo stack in background mode,
141 * otherwise allow it to be NULL, see: T60934.
142 * Otherwise it must never be NULL, even when undo is disabled. */
143 if (wm->undo_stack == NULL) {
144 return;
145 }
146 }
147
148 /* Only apply limit if this is the last undo step. */
149 if (wm->undo_stack->step_active && (wm->undo_stack->step_active->next == NULL)) {
150 BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, steps - 1, 0);
151 }
152
153 BKE_undosys_step_push(wm->undo_stack, C, str);
154
155 if (U.undomemory != 0) {
156 const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
157 BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, -1, memory_limit);
158 }
159
160 if (CLOG_CHECK(&LOG, 1)) {
161 BKE_undosys_print(wm->undo_stack);
162 }
163 }
164
165 /**
166 * \note Also check #undo_history_exec in bottom if you change notifiers.
167 */
ed_undo_step_impl(bContext * C,int step,const char * undoname,int undo_index,ReportList * reports)168 static int ed_undo_step_impl(
169 bContext *C, int step, const char *undoname, int undo_index, ReportList *reports)
170 {
171 /* Mutually exclusives, ensure correct input. */
172 BLI_assert(((undoname || undo_index != -1) && !step) ||
173 (!(undoname || undo_index != -1) && step));
174 CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
175 wmWindowManager *wm = CTX_wm_manager(C);
176 Scene *scene = CTX_data_scene(C);
177 ScrArea *area = CTX_wm_area(C);
178
179 /* undo during jobs are running can easily lead to freeing data using by jobs,
180 * or they can just lead to freezing job in some other cases */
181 WM_jobs_kill_all(wm);
182
183 if (G.debug & G_DEBUG_IO) {
184 Main *bmain = CTX_data_main(C);
185 if (bmain->lock != NULL) {
186 BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* undo step");
187 BLO_main_validate_libraries(bmain, reports);
188 }
189 }
190
191 /* TODO(campbell): undo_system: use undo system */
192 /* grease pencil can be can be used in plenty of spaces, so check it first */
193 if (ED_gpencil_session_active()) {
194 return ED_undo_gpencil_step(C, step, undoname);
195 }
196 if (area && (area->spacetype == SPACE_VIEW3D)) {
197 Object *obact = CTX_data_active_object(C);
198 if (obact && (obact->type == OB_GPENCIL)) {
199 ED_gpencil_toggle_brush_cursor(C, false, NULL);
200 }
201 }
202
203 UndoStep *step_data_from_name = NULL;
204 int step_for_callback = step;
205 if (undoname != NULL) {
206 step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
207 if (step_data_from_name == NULL) {
208 return OPERATOR_CANCELLED;
209 }
210
211 /* TODO(campbell), could use simple optimization. */
212 /* Pointers match on redo. */
213 step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) <
214 BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ?
215 1 :
216 -1;
217 }
218 else if (undo_index != -1) {
219 step_for_callback = (undo_index <
220 BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ?
221 1 :
222 -1;
223 }
224
225 /* App-Handlers (pre). */
226 {
227 /* Note: ignore grease pencil for now. */
228 Main *bmain = CTX_data_main(C);
229 wm->op_undo_depth++;
230 BKE_callback_exec_id(
231 bmain, &scene->id, (step_for_callback > 0) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE);
232 wm->op_undo_depth--;
233 }
234
235 /* Undo System */
236 {
237 if (undoname) {
238 BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name);
239 }
240 else if (undo_index != -1) {
241 BKE_undosys_step_undo_from_index(wm->undo_stack, C, undo_index);
242 }
243 else {
244 if (step == 1) {
245 BKE_undosys_step_undo(wm->undo_stack, C);
246 }
247 else {
248 BKE_undosys_step_redo(wm->undo_stack, C);
249 }
250 }
251
252 /* Set special modes for grease pencil */
253 if (area && (area->spacetype == SPACE_VIEW3D)) {
254 Object *obact = CTX_data_active_object(C);
255 if (obact && (obact->type == OB_GPENCIL)) {
256 /* set cursor */
257 if (ELEM(obact->mode,
258 OB_MODE_PAINT_GPENCIL,
259 OB_MODE_SCULPT_GPENCIL,
260 OB_MODE_WEIGHT_GPENCIL,
261 OB_MODE_VERTEX_GPENCIL)) {
262 ED_gpencil_toggle_brush_cursor(C, true, NULL);
263 }
264 else {
265 ED_gpencil_toggle_brush_cursor(C, false, NULL);
266 }
267 /* set workspace mode */
268 Base *basact = CTX_data_active_base(C);
269 ED_object_base_activate(C, basact);
270 }
271 }
272 }
273
274 /* App-Handlers (post). */
275 {
276 Main *bmain = CTX_data_main(C);
277 scene = CTX_data_scene(C);
278 wm->op_undo_depth++;
279 BKE_callback_exec_id(
280 bmain, &scene->id, step_for_callback > 0 ? BKE_CB_EVT_UNDO_POST : BKE_CB_EVT_REDO_POST);
281 wm->op_undo_depth--;
282 }
283
284 if (G.debug & G_DEBUG_IO) {
285 Main *bmain = CTX_data_main(C);
286 if (bmain->lock != NULL) {
287 BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* undo step");
288 BLO_main_validate_libraries(bmain, reports);
289 }
290 }
291
292 WM_event_add_notifier(C, NC_WINDOW, NULL);
293 WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
294
295 WM_toolsystem_refresh_active(C);
296
297 Main *bmain = CTX_data_main(C);
298 WM_toolsystem_refresh_screen_all(bmain);
299
300 if (CLOG_CHECK(&LOG, 1)) {
301 BKE_undosys_print(wm->undo_stack);
302 }
303
304 return OPERATOR_FINISHED;
305 }
306
ed_undo_step_direction(bContext * C,int step,ReportList * reports)307 static int ed_undo_step_direction(bContext *C, int step, ReportList *reports)
308 {
309 return ed_undo_step_impl(C, step, NULL, -1, reports);
310 }
311
ed_undo_step_by_name(bContext * C,const char * undo_name,ReportList * reports)312 static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *reports)
313 {
314 return ed_undo_step_impl(C, 0, undo_name, -1, reports);
315 }
316
ed_undo_step_by_index(bContext * C,int index,ReportList * reports)317 static int ed_undo_step_by_index(bContext *C, int index, ReportList *reports)
318 {
319 return ed_undo_step_impl(C, 0, NULL, index, reports);
320 }
321
ED_undo_grouped_push(bContext * C,const char * str)322 void ED_undo_grouped_push(bContext *C, const char *str)
323 {
324 /* do nothing if previous undo task is the same as this one (or from the same undo group) */
325 wmWindowManager *wm = CTX_wm_manager(C);
326 const UndoStep *us = wm->undo_stack->step_active;
327 if (us && STREQ(str, us->name)) {
328 BKE_undosys_stack_clear_active(wm->undo_stack);
329 }
330
331 /* push as usual */
332 ED_undo_push(C, str);
333 }
334
ED_undo_pop(bContext * C)335 void ED_undo_pop(bContext *C)
336 {
337 ed_undo_step_direction(C, 1, NULL);
338 }
ED_undo_redo(bContext * C)339 void ED_undo_redo(bContext *C)
340 {
341 ed_undo_step_direction(C, -1, NULL);
342 }
343
ED_undo_push_op(bContext * C,wmOperator * op)344 void ED_undo_push_op(bContext *C, wmOperator *op)
345 {
346 /* in future, get undo string info? */
347 ED_undo_push(C, op->type->name);
348 }
349
ED_undo_grouped_push_op(bContext * C,wmOperator * op)350 void ED_undo_grouped_push_op(bContext *C, wmOperator *op)
351 {
352 if (op->type->undo_group[0] != '\0') {
353 ED_undo_grouped_push(C, op->type->undo_group);
354 }
355 else {
356 ED_undo_grouped_push(C, op->type->name);
357 }
358 }
359
ED_undo_pop_op(bContext * C,wmOperator * op)360 void ED_undo_pop_op(bContext *C, wmOperator *op)
361 {
362 /* search back a couple of undo's, in case something else added pushes */
363 ed_undo_step_by_name(C, op->type->name, op->reports);
364 }
365
366 /* name optionally, function used to check for operator redo panel */
ED_undo_is_valid(const bContext * C,const char * undoname)367 bool ED_undo_is_valid(const bContext *C, const char *undoname)
368 {
369 wmWindowManager *wm = CTX_wm_manager(C);
370 return BKE_undosys_stack_has_undo(wm->undo_stack, undoname);
371 }
372
ED_undo_is_memfile_compatible(const bContext * C)373 bool ED_undo_is_memfile_compatible(const bContext *C)
374 {
375 /* Some modes don't co-exist with memfile undo, disable their use: T60593
376 * (this matches 2.7x behavior). */
377 ViewLayer *view_layer = CTX_data_view_layer(C);
378 if (view_layer != NULL) {
379 Object *obact = OBACT(view_layer);
380 if (obact != NULL) {
381 if (obact->mode & OB_MODE_EDIT) {
382 return false;
383 }
384 }
385 }
386 return true;
387 }
388
389 /**
390 * When a property of ID changes, return false.
391 *
392 * This is to avoid changes to a property making undo pushes
393 * which are ignored by the undo-system.
394 * For example, changing a brush property isn't stored by sculpt-mode undo steps.
395 * This workaround is needed until the limitation is removed, see: T61948.
396 */
ED_undo_is_legacy_compatible_for_property(struct bContext * C,ID * id)397 bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, ID *id)
398 {
399 ViewLayer *view_layer = CTX_data_view_layer(C);
400 if (view_layer != NULL) {
401 Object *obact = OBACT(view_layer);
402 if (obact != NULL) {
403 if (obact->mode & OB_MODE_ALL_PAINT) {
404 /* Don't store property changes when painting
405 * (only do undo pushes on brush strokes which each paint operator handles on its own). */
406 CLOG_INFO(&LOG, 1, "skipping undo for paint-mode");
407 return false;
408 }
409 if (obact->mode & OB_MODE_EDIT) {
410 if ((id == NULL) || (obact->data == NULL) ||
411 (GS(id->name) != GS(((ID *)obact->data)->name))) {
412 /* No undo push on id type mismatch in edit-mode. */
413 CLOG_INFO(&LOG, 1, "skipping undo for edit-mode");
414 return false;
415 }
416 }
417 }
418 }
419 return true;
420 }
421
422 /**
423 * Ideally we wont access the stack directly,
424 * this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
425 *
426 * Using global isn't great, this just avoids doing inline,
427 * causing 'BKE_global.h' & 'BKE_main.h' includes.
428 */
ED_undo_stack_get(void)429 UndoStack *ED_undo_stack_get(void)
430 {
431 wmWindowManager *wm = G_MAIN->wm.first;
432 return wm->undo_stack;
433 }
434
435 /** \} */
436
437 /* -------------------------------------------------------------------- */
438 /** \name Undo, Undo Push & Redo Operators
439 * \{ */
440
ed_undo_exec(bContext * C,wmOperator * op)441 static int ed_undo_exec(bContext *C, wmOperator *op)
442 {
443 /* "last operator" should disappear, later we can tie this with undo stack nicer */
444 WM_operator_stack_clear(CTX_wm_manager(C));
445 int ret = ed_undo_step_direction(C, 1, op->reports);
446 if (ret & OPERATOR_FINISHED) {
447 /* Keep button under the cursor active. */
448 WM_event_add_mousemove(CTX_wm_window(C));
449 }
450
451 ED_outliner_select_sync_from_all_tag(C);
452 return ret;
453 }
454
ed_undo_push_exec(bContext * C,wmOperator * op)455 static int ed_undo_push_exec(bContext *C, wmOperator *op)
456 {
457 if (G.background) {
458 /* Exception for background mode, see: T60934.
459 * Note: since the undo stack isn't initialized on startup, background mode behavior
460 * won't match regular usage, this is just for scripts to do explicit undo pushes. */
461 wmWindowManager *wm = CTX_wm_manager(C);
462 if (wm->undo_stack == NULL) {
463 wm->undo_stack = BKE_undosys_stack_create();
464 }
465 }
466 char str[BKE_UNDO_STR_MAX];
467 RNA_string_get(op->ptr, "message", str);
468 ED_undo_push(C, str);
469 return OPERATOR_FINISHED;
470 }
471
ed_redo_exec(bContext * C,wmOperator * op)472 static int ed_redo_exec(bContext *C, wmOperator *op)
473 {
474 int ret = ed_undo_step_direction(C, -1, op->reports);
475 if (ret & OPERATOR_FINISHED) {
476 /* Keep button under the cursor active. */
477 WM_event_add_mousemove(CTX_wm_window(C));
478 }
479
480 ED_outliner_select_sync_from_all_tag(C);
481 return ret;
482 }
483
ed_undo_redo_exec(bContext * C,wmOperator * UNUSED (op))484 static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
485 {
486 wmOperator *last_op = WM_operator_last_redo(C);
487 int ret = ED_undo_operator_repeat(C, last_op);
488 ret = ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
489 if (ret & OPERATOR_FINISHED) {
490 /* Keep button under the cursor active. */
491 WM_event_add_mousemove(CTX_wm_window(C));
492 }
493 return ret;
494 }
495
496 /* Disable in background mode, we could support if it's useful, T60934. */
497
ed_undo_is_init_poll(bContext * C)498 static bool ed_undo_is_init_poll(bContext *C)
499 {
500 wmWindowManager *wm = CTX_wm_manager(C);
501 if (wm->undo_stack == NULL) {
502 CTX_wm_operator_poll_msg_set(C, "Undo disabled at startup");
503 return false;
504 }
505 return true;
506 }
507
ed_undo_is_init_and_screenactive_poll(bContext * C)508 static bool ed_undo_is_init_and_screenactive_poll(bContext *C)
509 {
510 if (ed_undo_is_init_poll(C) == false) {
511 return false;
512 }
513 return ED_operator_screenactive(C);
514 }
515
ed_undo_redo_poll(bContext * C)516 static bool ed_undo_redo_poll(bContext *C)
517 {
518 wmOperator *last_op = WM_operator_last_redo(C);
519 return (last_op && ed_undo_is_init_and_screenactive_poll(C) &&
520 WM_operator_check_ui_enabled(C, last_op->type->name));
521 }
522
ed_undo_poll(bContext * C)523 static bool ed_undo_poll(bContext *C)
524 {
525 if (!ed_undo_is_init_and_screenactive_poll(C)) {
526 return false;
527 }
528 UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
529 return (undo_stack->step_active != NULL) && (undo_stack->step_active->prev != NULL);
530 }
531
ED_OT_undo(wmOperatorType * ot)532 void ED_OT_undo(wmOperatorType *ot)
533 {
534 /* identifiers */
535 ot->name = "Undo";
536 ot->description = "Undo previous action";
537 ot->idname = "ED_OT_undo";
538
539 /* api callbacks */
540 ot->exec = ed_undo_exec;
541 ot->poll = ed_undo_poll;
542 }
543
ED_OT_undo_push(wmOperatorType * ot)544 void ED_OT_undo_push(wmOperatorType *ot)
545 {
546 /* identifiers */
547 ot->name = "Undo Push";
548 ot->description = "Add an undo state (internal use only)";
549 ot->idname = "ED_OT_undo_push";
550
551 /* api callbacks */
552 ot->exec = ed_undo_push_exec;
553 /* Unlike others undo operators this initializes undo stack. */
554 ot->poll = ED_operator_screenactive;
555
556 ot->flag = OPTYPE_INTERNAL;
557
558 RNA_def_string(ot->srna,
559 "message",
560 "Add an undo step *function may be moved*",
561 BKE_UNDO_STR_MAX,
562 "Undo Message",
563 "");
564 }
565
ed_redo_poll(bContext * C)566 static bool ed_redo_poll(bContext *C)
567 {
568 if (!ed_undo_is_init_and_screenactive_poll(C)) {
569 return false;
570 }
571 UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
572 return (undo_stack->step_active != NULL) && (undo_stack->step_active->next != NULL);
573 }
574
ED_OT_redo(wmOperatorType * ot)575 void ED_OT_redo(wmOperatorType *ot)
576 {
577 /* identifiers */
578 ot->name = "Redo";
579 ot->description = "Redo previous action";
580 ot->idname = "ED_OT_redo";
581
582 /* api callbacks */
583 ot->exec = ed_redo_exec;
584 ot->poll = ed_redo_poll;
585 }
586
ED_OT_undo_redo(wmOperatorType * ot)587 void ED_OT_undo_redo(wmOperatorType *ot)
588 {
589 /* identifiers */
590 ot->name = "Undo and Redo";
591 ot->description = "Undo and redo previous action";
592 ot->idname = "ED_OT_undo_redo";
593
594 /* api callbacks */
595 ot->exec = ed_undo_redo_exec;
596 ot->poll = ed_undo_redo_poll;
597 }
598
599 /** \} */
600
601 /* -------------------------------------------------------------------- */
602 /** \name Operator Repeat
603 * \{ */
604
605 /* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
ED_undo_operator_repeat(bContext * C,wmOperator * op)606 int ED_undo_operator_repeat(bContext *C, wmOperator *op)
607 {
608 int ret = 0;
609
610 if (op) {
611 CLOG_INFO(&LOG, 1, "idname='%s'", op->type->idname);
612 wmWindowManager *wm = CTX_wm_manager(C);
613 struct Scene *scene = CTX_data_scene(C);
614
615 /* keep in sync with logic in view3d_panel_operator_redo() */
616 ARegion *region_orig = CTX_wm_region(C);
617 ARegion *region_win = BKE_area_find_region_active_win(CTX_wm_area(C));
618
619 if (region_win) {
620 CTX_wm_region_set(C, region_win);
621 }
622
623 if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) &&
624 /* note, undo/redo cant run if there are jobs active,
625 * check for screen jobs only so jobs like material/texture/world preview
626 * (which copy their data), wont stop redo, see T29579],
627 *
628 * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */
629 (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) {
630 int retval;
631
632 if (G.debug & G_DEBUG) {
633 printf("redo_cb: operator redo %s\n", op->type->name);
634 }
635
636 WM_operator_free_all_after(wm, op);
637
638 ED_undo_pop_op(C, op);
639
640 if (op->type->check) {
641 if (op->type->check(C, op)) {
642 /* check for popup and re-layout buttons */
643 ARegion *region_menu = CTX_wm_menu(C);
644 if (region_menu) {
645 ED_region_tag_refresh_ui(region_menu);
646 }
647 }
648 }
649
650 retval = WM_operator_repeat(C, op);
651 if ((retval & OPERATOR_FINISHED) == 0) {
652 if (G.debug & G_DEBUG) {
653 printf("redo_cb: operator redo failed: %s, return %d\n", op->type->name, retval);
654 }
655 ED_undo_redo(C);
656 }
657 else {
658 ret = 1;
659 }
660 }
661 else {
662 if (G.debug & G_DEBUG) {
663 printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name);
664 }
665 }
666
667 /* set region back */
668 CTX_wm_region_set(C, region_orig);
669 }
670 else {
671 CLOG_WARN(&LOG, "called with NULL 'op'");
672 }
673
674 return ret;
675 }
676
ED_undo_operator_repeat_cb(bContext * C,void * arg_op,void * UNUSED (arg_unused))677 void ED_undo_operator_repeat_cb(bContext *C, void *arg_op, void *UNUSED(arg_unused))
678 {
679 ED_undo_operator_repeat(C, (wmOperator *)arg_op);
680 }
681
ED_undo_operator_repeat_cb_evt(bContext * C,void * arg_op,int UNUSED (arg_unused))682 void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_unused))
683 {
684 ED_undo_operator_repeat(C, (wmOperator *)arg_op);
685 }
686
687 /** \} */
688
689 /* -------------------------------------------------------------------- */
690 /** \name Undo History Operator
691 * \{ */
692
693 /* create enum based on undo items */
rna_undo_itemf(bContext * C,int * totitem)694 static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
695 {
696 EnumPropertyItem item_tmp = {0}, *item = NULL;
697 int i = 0;
698
699 wmWindowManager *wm = CTX_wm_manager(C);
700 if (wm->undo_stack == NULL) {
701 return NULL;
702 }
703
704 for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
705 if (us->skip == false) {
706 item_tmp.identifier = us->name;
707 item_tmp.name = IFACE_(us->name);
708 if (us == wm->undo_stack->step_active) {
709 item_tmp.icon = ICON_LAYER_ACTIVE;
710 }
711 else {
712 item_tmp.icon = ICON_NONE;
713 }
714 item_tmp.value = i;
715 RNA_enum_item_add(&item, totitem, &item_tmp);
716 }
717 }
718 RNA_enum_item_end(&item, totitem);
719
720 return item;
721 }
722
undo_history_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))723 static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
724 {
725 int totitem = 0;
726
727 {
728 const EnumPropertyItem *item = rna_undo_itemf(C, &totitem);
729
730 if (totitem > 0) {
731 uiPopupMenu *pup = UI_popup_menu_begin(
732 C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
733 uiLayout *layout = UI_popup_menu_layout(pup);
734 uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
735 uiLayout *column = NULL;
736 const int col_size = 20 + totitem / 12;
737 int i, c;
738 bool add_col = true;
739
740 for (c = 0, i = totitem; i--;) {
741 if (add_col && !(c % col_size)) {
742 column = uiLayoutColumn(split, false);
743 add_col = false;
744 }
745 if (item[i].identifier) {
746 uiItemIntO(column, item[i].name, item[i].icon, op->type->idname, "item", item[i].value);
747 c++;
748 add_col = true;
749 }
750 }
751
752 MEM_freeN((void *)item);
753
754 UI_popup_menu_end(C, pup);
755 }
756 }
757 return OPERATOR_CANCELLED;
758 }
759
760 /* note: also check ed_undo_step() in top if you change notifiers */
undo_history_exec(bContext * C,wmOperator * op)761 static int undo_history_exec(bContext *C, wmOperator *op)
762 {
763 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
764 if (RNA_property_is_set(op->ptr, prop)) {
765 int item = RNA_property_int_get(op->ptr, prop);
766 WM_operator_stack_clear(CTX_wm_manager(C));
767 ed_undo_step_by_index(C, item, op->reports);
768 WM_event_add_notifier(C, NC_WINDOW, NULL);
769 return OPERATOR_FINISHED;
770 }
771 return OPERATOR_CANCELLED;
772 }
773
undo_history_poll(bContext * C)774 static bool undo_history_poll(bContext *C)
775 {
776 if (!ed_undo_is_init_and_screenactive_poll(C)) {
777 return false;
778 }
779 UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
780 /* More than just original state entry. */
781 return BLI_listbase_count_at_most(&undo_stack->steps, 2) > 1;
782 }
783
ED_OT_undo_history(wmOperatorType * ot)784 void ED_OT_undo_history(wmOperatorType *ot)
785 {
786 /* identifiers */
787 ot->name = "Undo History";
788 ot->description = "Redo specific action in history";
789 ot->idname = "ED_OT_undo_history";
790
791 /* api callbacks */
792 ot->invoke = undo_history_invoke;
793 ot->exec = undo_history_exec;
794 ot->poll = undo_history_poll;
795
796 RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX);
797 }
798
799 /** \} */
800
801 /* -------------------------------------------------------------------- */
802 /** \name Undo Helper Functions
803 * \{ */
804
ED_undo_object_set_active_or_warn(ViewLayer * view_layer,Object * ob,const char * info,CLG_LogRef * log)805 void ED_undo_object_set_active_or_warn(ViewLayer *view_layer,
806 Object *ob,
807 const char *info,
808 CLG_LogRef *log)
809 {
810 Object *ob_prev = OBACT(view_layer);
811 if (ob_prev != ob) {
812 Base *base = BKE_view_layer_base_find(view_layer, ob);
813 if (base != NULL) {
814 view_layer->basact = base;
815 }
816 else {
817 /* Should never fail, may not crash but can give odd behavior. */
818 CLOG_WARN(log, "'%s' failed to restore active object: '%s'", info, ob->id.name + 2);
819 }
820 }
821 }
822
ED_undo_object_editmode_restore_helper(struct bContext * C,Object ** object_array,uint object_array_len,uint object_array_stride)823 void ED_undo_object_editmode_restore_helper(struct bContext *C,
824 Object **object_array,
825 uint object_array_len,
826 uint object_array_stride)
827 {
828 Main *bmain = CTX_data_main(C);
829 ViewLayer *view_layer = CTX_data_view_layer(C);
830 uint bases_len = 0;
831 /* Don't request unique data because we want to de-select objects when exiting edit-mode
832 * for that to be done on all objects we can't skip ones that share data. */
833 Base **bases = ED_undo_editmode_bases_from_view_layer(view_layer, &bases_len);
834 for (uint i = 0; i < bases_len; i++) {
835 ((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT;
836 }
837 Scene *scene = CTX_data_scene(C);
838 Object **ob_p = object_array;
839 for (uint i = 0; i < object_array_len; i++, ob_p = POINTER_OFFSET(ob_p, object_array_stride)) {
840 Object *obedit = *ob_p;
841 ED_object_editmode_enter_ex(bmain, scene, obedit, EM_NO_CONTEXT);
842 ((ID *)obedit->data)->tag &= ~LIB_TAG_DOIT;
843 }
844 for (uint i = 0; i < bases_len; i++) {
845 ID *id = bases[i]->object->data;
846 if (id->tag & LIB_TAG_DOIT) {
847 ED_object_editmode_exit_ex(bmain, scene, bases[i]->object, EM_FREEDATA);
848 /* Ideally we would know the selection state it was before entering edit-mode,
849 * for now follow the convention of having them unselected when exiting the mode. */
850 ED_object_base_select(bases[i], BA_DESELECT);
851 }
852 }
853 MEM_freeN(bases);
854 }
855
856 /** \} */
857
858 /* -------------------------------------------------------------------- */
859 /** \name Undo View Layer Helper Functions
860 *
861 * Needed because view layer functions such as
862 * #BKE_view_layer_array_from_objects_in_edit_mode_unique_data also check visibility,
863 * which is not reliable when it comes to object undo operations,
864 * since hidden objects can be operated on in the properties editor,
865 * and local collections may be used.
866 * \{ */
867
undo_editmode_objects_from_view_layer_prepare(ViewLayer * view_layer,Object * obact,int * r_active_index)868 static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer,
869 Object *obact,
870 int *r_active_index)
871 {
872 const short object_type = obact->type;
873
874 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
875 Object *ob = base->object;
876 if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
877 ID *id = ob->data;
878 id->tag &= ~LIB_TAG_DOIT;
879 }
880 }
881
882 int len = 0;
883 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
884 Object *ob = base->object;
885 if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
886 if (ob == obact) {
887 *r_active_index = len;
888 }
889 ID *id = ob->data;
890 if ((id->tag & LIB_TAG_DOIT) == 0) {
891 len += 1;
892 id->tag |= LIB_TAG_DOIT;
893 }
894 }
895 }
896 return len;
897 }
898
ED_undo_editmode_objects_from_view_layer(ViewLayer * view_layer,uint * r_len)899 Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r_len)
900 {
901 Object *obact = OBACT(view_layer);
902 if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
903 return MEM_mallocN(0, __func__);
904 }
905 int active_index = 0;
906 const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, obact, &active_index);
907 const short object_type = obact->type;
908 int i = 0;
909 Object **objects = MEM_malloc_arrayN(len, sizeof(*objects), __func__);
910 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
911 Object *ob = base->object;
912 if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
913 ID *id = ob->data;
914 if (id->tag & LIB_TAG_DOIT) {
915 objects[i++] = ob;
916 id->tag &= ~LIB_TAG_DOIT;
917 }
918 }
919 }
920 BLI_assert(i == len);
921 if (active_index > 0) {
922 SWAP(Object *, objects[0], objects[active_index]);
923 }
924 *r_len = len;
925 return objects;
926 }
927
ED_undo_editmode_bases_from_view_layer(ViewLayer * view_layer,uint * r_len)928 Base **ED_undo_editmode_bases_from_view_layer(ViewLayer *view_layer, uint *r_len)
929 {
930 Object *obact = OBACT(view_layer);
931 if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
932 return MEM_mallocN(0, __func__);
933 }
934 int active_index = 0;
935 const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, obact, &active_index);
936 const short object_type = obact->type;
937 int i = 0;
938 Base **base_array = MEM_malloc_arrayN(len, sizeof(*base_array), __func__);
939 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
940 Object *ob = base->object;
941 if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
942 ID *id = ob->data;
943 if (id->tag & LIB_TAG_DOIT) {
944 base_array[i++] = base;
945 id->tag &= ~LIB_TAG_DOIT;
946 }
947 }
948 }
949 BLI_assert(i == len);
950 if (active_index > 0) {
951 SWAP(Base *, base_array[0], base_array[active_index]);
952 }
953 *r_len = len;
954 return base_array;
955 }
956
957 /** \} */
958