Revert to master - those changes are globally valid, but remain incomplete,
[blender.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
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_gpencil_types.h"
39 #include "DNA_listBase.h"
40 #include "DNA_windowmanager_types.h"
41
42 #include "BLI_listbase.h"
43
44 #include "BKE_blender.h"
45 #include "BKE_context.h"
46 #include "BKE_gpencil.h"
47
48 #include "ED_gpencil.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "gpencil_intern.h"
54
55 typedef struct bGPundonode {
56         struct bGPundonode *next, *prev;
57         
58         char name[BKE_UNDO_STR_MAX];
59         struct bGPdata *gpd;
60 } bGPundonode;
61
62 static ListBase undo_nodes = {NULL, NULL};
63 static bGPundonode *cur_node = NULL;
64
65 int ED_gpencil_session_active(void)
66 {
67         return (BLI_listbase_is_empty(&undo_nodes) == false);
68 }
69
70 int ED_undo_gpencil_step(bContext *C, int step, const char *name)
71 {
72         bGPdata **gpd_ptr = NULL, *new_gpd = NULL;
73         
74         gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
75         
76         if (step == 1) {  /* undo */
77                 //printf("\t\tGP - undo step\n");
78                 if (cur_node->prev) {
79                         if (!name || STREQ(cur_node->name, name)) {
80                                 cur_node = cur_node->prev;
81                                 new_gpd = cur_node->gpd;
82                         }
83                 }
84         }
85         else if (step == -1) {
86                 //printf("\t\tGP - redo step\n");
87                 if (cur_node->next) {
88                         if (!name || STREQ(cur_node->name, name)) {
89                                 cur_node = cur_node->next;
90                                 new_gpd = cur_node->gpd;
91                         }
92                 }
93         }
94         
95         if (new_gpd) {
96                 if (gpd_ptr) {
97                         if (*gpd_ptr) {
98                                 bGPdata *gpd = *gpd_ptr;
99                                 bGPDlayer *gpl, *gpld;
100                                 
101                                 free_gpencil_layers(&gpd->layers);
102                                 
103                                 /* copy layers */
104                                 BLI_listbase_clear(&gpd->layers);
105                                 
106                                 for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
107                                         /* make a copy of source layer and its data */
108                                         gpld = gpencil_layer_duplicate(gpl);
109                                         BLI_addtail(&gpd->layers, gpld);
110                                 }
111                         }
112                 }
113         }
114         
115         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
116         
117         return OPERATOR_FINISHED;
118 }
119
120 void gpencil_undo_init(bGPdata *gpd)
121 {
122         gpencil_undo_push(gpd);
123 }
124
125 void gpencil_undo_push(bGPdata *gpd)
126 {
127         bGPundonode *undo_node;
128         
129         //printf("\t\tGP - undo push\n");
130         
131         if (cur_node) {
132                 /* remove all un-done nodes from stack */
133                 undo_node = cur_node->next;
134                 
135                 while (undo_node) {
136                         bGPundonode *next_node = undo_node->next;
137                         
138                         /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
139                          * or else the real copy will segfault when accessed
140                          */
141                         undo_node->gpd->adt = NULL;
142                         
143                         BKE_gpencil_free(undo_node->gpd);
144                         MEM_freeN(undo_node->gpd);
145                         
146                         BLI_freelinkN(&undo_nodes, undo_node);
147                         
148                         undo_node = next_node;
149                 }
150         }
151         
152         /* create new undo node */
153         undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
154         undo_node->gpd = gpencil_data_duplicate(gpd, true);
155         
156         cur_node = undo_node;
157         
158         BLI_addtail(&undo_nodes, undo_node);
159 }
160
161 void gpencil_undo_finish(void)
162 {
163         bGPundonode *undo_node = undo_nodes.first;
164         
165         while (undo_node) {
166                 /* HACK: animdata wasn't duplicated, so it shouldn't be freed here,
167                  * or else the real copy will segfault when accessed
168                  */
169                 undo_node->gpd->adt = NULL;
170                 
171                 BKE_gpencil_free(undo_node->gpd);
172                 MEM_freeN(undo_node->gpd);
173                 
174                 undo_node = undo_node->next;
175         }
176         
177         BLI_freelistN(&undo_nodes);
178         
179         cur_node = NULL;
180 }