code cleanup: use single define for undo string size, was 64 mostly, but 512 in the UI.
[blender-staging.git] / source / blender / editors / gpencil / gpencil_undo.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/gpencil/gpencil_undo.c
29  *  \ingroup edgpencil
30  */
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_gpencil_types.h"
38 #include "DNA_listBase.h"
39 #include "DNA_windowmanager_types.h"
40
41 #include "BKE_blender.h"
42 #include "BKE_context.h"
43 #include "BKE_gpencil.h"
44
45 #include "BLI_listbase.h"
46
47 #include "ED_gpencil.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "gpencil_intern.h"
53
54 typedef struct bGPundonode {
55         struct bGPundonode *next, *prev;
56
57         char name[BKE_UNDO_STR_MAX];
58         struct bGPdata *gpd;
59 } bGPundonode;
60
61 static ListBase undo_nodes = {NULL, NULL};
62 static bGPundonode *cur_node = NULL;
63
64 int ED_gpencil_session_active(void)
65 {
66         return undo_nodes.first != NULL;
67 }
68
69 int ED_undo_gpencil_step(bContext *C, int step, const char *name)
70 {
71         bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
72
73         gpd_ptr = gpencil_data_get_pointers(C, NULL);
74
75         if (step == 1) {  /* undo */
76                 //printf("\t\tGP - undo step\n");
77                 if (cur_node->prev) {
78                         if (!name || strcmp(cur_node->name, name) == 0) {
79                                 cur_node = cur_node->prev;
80                                 new_gpd = cur_node->gpd;
81                         }
82                 }
83         }
84         else if (step == -1) {
85                 //printf("\t\tGP - redo step\n");
86                 if (cur_node->next) {
87                         if (!name || strcmp(cur_node->name, name) == 0) {
88                                 cur_node = cur_node->next;
89                                 new_gpd = cur_node->gpd;
90                         }
91                 }
92         }
93
94         if (new_gpd) {
95                 if (gpd_ptr) {
96                         if (*gpd_ptr) {
97                                 bGPdata *gpd = *gpd_ptr;
98                                 bGPDlayer *gpl, *gpld;
99
100                                 free_gpencil_layers(&gpd->layers);
101
102                                 /* copy layers */
103                                 gpd->layers.first = gpd->layers.last = NULL;
104
105                                 for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
106                                         /* make a copy of source layer and its data */
107                                         gpld = gpencil_layer_duplicate(gpl);
108                                         BLI_addtail(&gpd->layers, gpld);
109                                 }
110                         }
111                 }
112         }
113
114         WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL);
115
116         return OPERATOR_FINISHED;
117 }
118
119 void gpencil_undo_init(bGPdata *gpd)
120 {
121         gpencil_undo_push(gpd);
122 }
123
124 void gpencil_undo_push(bGPdata *gpd)
125 {
126         bGPundonode *undo_node;
127
128         //printf("\t\tGP - undo push\n");
129
130         if (cur_node) {
131                 /* remove all un-done nodes from stack */
132                 undo_node = cur_node->next;
133
134                 while (undo_node) {
135                         bGPundonode *next_node = undo_node->next;
136
137                         BKE_gpencil_free(undo_node->gpd);
138                         MEM_freeN(undo_node->gpd);
139
140                         BLI_freelinkN(&undo_nodes, undo_node);
141
142                         undo_node = next_node;
143                 }
144         }
145
146         /* create new undo node */
147         undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
148         undo_node->gpd = gpencil_data_duplicate(gpd);
149
150         cur_node = undo_node;
151
152         BLI_addtail(&undo_nodes, undo_node);
153 }
154
155 void gpencil_undo_finish(void)
156 {
157         bGPundonode *undo_node = undo_nodes.first;
158
159         while (undo_node) {
160                 BKE_gpencil_free(undo_node->gpd);
161                 MEM_freeN(undo_node->gpd);
162
163                 undo_node = undo_node->next;
164         }
165
166         BLI_freelistN(&undo_nodes);
167
168         cur_node = NULL;
169 }