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