Blender  V3.3
gpencil_undo.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. All rights reserved. */
3 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_gpencil_types.h"
14 #include "DNA_listBase.h"
15 #include "DNA_object_types.h"
17 
18 #include "BLI_listbase.h"
19 
20 #include "BKE_blender_undo.h"
21 #include "BKE_context.h"
22 #include "BKE_gpencil.h"
23 #include "BKE_undo_system.h"
24 
25 #include "ED_gpencil.h"
26 
27 #include "WM_api.h"
28 #include "WM_types.h"
29 
30 #include "DEG_depsgraph.h"
31 
32 #include "gpencil_intern.h"
33 
34 typedef struct bGPundonode {
35  struct bGPundonode *next, *prev;
36 
38  struct bGPdata *gpd;
40 
43 
45 {
46  return (BLI_listbase_is_empty(&undo_nodes) == false);
47 }
48 
49 int ED_undo_gpencil_step(bContext *C, const int step)
50 {
51  bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
52 
54 
55  const eUndoStepDir undo_step = (eUndoStepDir)step;
56  if (undo_step == STEP_UNDO) {
57  if (cur_node->prev) {
59  new_gpd = cur_node->gpd;
60  }
61  }
62  else if (undo_step == STEP_REDO) {
63  if (cur_node->next) {
65  new_gpd = cur_node->gpd;
66  }
67  }
68 
69  if (new_gpd) {
70  if (gpd_ptr) {
71  if (*gpd_ptr) {
72  bGPdata *gpd = *gpd_ptr;
73  bGPDlayer *gpld;
74 
76 
77  /* copy layers */
79 
80  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
81  /* make a copy of source layer and its data */
82  gpld = BKE_gpencil_layer_duplicate(gpl, true, true);
83  BLI_addtail(&gpd->layers, gpld);
84  }
85  }
86  }
87  /* drawing batch cache is dirty now */
89  new_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
90  }
91 
93 
94  return OPERATOR_FINISHED;
95 }
96 
98 {
99  gpencil_undo_push(gpd);
100 }
101 
102 static void gpencil_undo_free_node(bGPundonode *undo_node)
103 {
104  /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
105  * or else the real copy will segfault when accessed
106  */
107  undo_node->gpd->adt = NULL;
108 
109  BKE_gpencil_free_data(undo_node->gpd, false);
110  MEM_freeN(undo_node->gpd);
111 }
112 
114 {
115  bGPundonode *undo_node;
116 
117  if (cur_node) {
118  /* Remove all undone nodes from stack. */
119  undo_node = cur_node->next;
120 
121  while (undo_node) {
122  bGPundonode *next_node = undo_node->next;
123 
124  gpencil_undo_free_node(undo_node);
125  BLI_freelinkN(&undo_nodes, undo_node);
126 
127  undo_node = next_node;
128  }
129  }
130 
131  /* limit number of undo steps to the maximum undo steps
132  * - to prevent running out of memory during **really**
133  * long drawing sessions (triggering swapping)
134  */
135  /* TODO: Undo-memory constraint is not respected yet,
136  * but can be added if we have any need for it. */
137  if (U.undosteps && !BLI_listbase_is_empty(&undo_nodes)) {
138  /* remove anything older than n-steps before cur_node */
139  int steps = 0;
140 
141  undo_node = (cur_node) ? cur_node : undo_nodes.last;
142  while (undo_node) {
143  bGPundonode *prev_node = undo_node->prev;
144 
145  if (steps >= U.undosteps) {
146  gpencil_undo_free_node(undo_node);
147  BLI_freelinkN(&undo_nodes, undo_node);
148  }
149 
150  steps++;
151  undo_node = prev_node;
152  }
153  }
154 
155  /* create new undo node */
156  undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
157  undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true);
158 
159  cur_node = undo_node;
160 
161  BLI_addtail(&undo_nodes, undo_node);
162 }
163 
165 {
166  bGPundonode *undo_node = undo_nodes.first;
167 
168  while (undo_node) {
169  gpencil_undo_free_node(undo_node);
170  undo_node = undo_node->next;
171  }
172 
174 
175  cur_node = NULL;
176 }
#define BKE_UNDO_STR_MAX
void BKE_gpencil_free_data(struct bGPdata *gpd, bool free_all)
Definition: gpencil.c:479
struct bGPDlayer * BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src, bool dup_frames, bool dup_strokes)
struct bGPdata * BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy)
void BKE_gpencil_free_layers(struct ListBase *list)
Definition: gpencil.c:456
eUndoStepDir
@ STEP_UNDO
@ STEP_REDO
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ GP_DATA_CACHE_IS_DIRTY
These structs are the foundation for all linked lists in the library system.
Object is a sort of wrapper for general info.
@ OPERATOR_FINISHED
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
#define NA_EDITED
Definition: WM_types.h:523
#define NC_GPENCIL
Definition: WM_types.h:349
unsigned int U
Definition: btGjkEpa3.h:78
void gpencil_undo_push(bGPdata *gpd)
Definition: gpencil_undo.c:113
void gpencil_undo_init(bGPdata *gpd)
Definition: gpencil_undo.c:97
static void gpencil_undo_free_node(bGPundonode *undo_node)
Definition: gpencil_undo.c:102
int ED_gpencil_session_active(void)
Definition: gpencil_undo.c:44
int ED_undo_gpencil_step(bContext *C, const int step)
Definition: gpencil_undo.c:49
struct bGPundonode bGPundonode
void gpencil_undo_finish(void)
Definition: gpencil_undo.c:164
static ListBase undo_nodes
Definition: gpencil_undo.c:41
static bGPundonode * cur_node
Definition: gpencil_undo.c:42
bGPdata ** ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static const int steps
Definition: sky_nishita.cpp:19
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
ListBase layers
struct AnimData * adt
char name[BKE_UNDO_STR_MAX]
Definition: gpencil_undo.c:37
struct bGPdata * gpd
Definition: gpencil_undo.c:38
struct bGPundonode * next
Definition: gpencil_undo.c:35
struct bGPundonode * prev
Definition: gpencil_undo.c:35
void WM_event_add_notifier(const bContext *C, uint type, void *reference)