Grease Pencil notifier/listener cleanup
[blender.git] / source / blender / blenkernel / intern / gpencil.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) 2008, Blender Foundation
19  * This is a new part of Blender
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/blenkernel/intern/gpencil.c
27  *  \ingroup bke
28  */
29
30  
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41
42 #include "DNA_gpencil_types.h"
43
44 #include "BKE_global.h"
45 #include "BKE_gpencil.h"
46 #include "BKE_library.h"
47 #include "BKE_main.h"
48
49
50
51 /* ************************************************** */
52 /* GENERAL STUFF */
53
54 /* --------- Memory Management ------------ */
55
56 /* Free strokes belonging to a gp-frame */
57 void free_gpencil_strokes(bGPDframe *gpf)
58 {
59         bGPDstroke *gps, *gpsn;
60         
61         /* error checking */
62         if (gpf == NULL) return;
63         
64         /* free strokes */
65         for (gps = gpf->strokes.first; gps; gps = gpsn) {
66                 gpsn = gps->next;
67                 
68                 /* free stroke memory arrays, then stroke itself */
69                 if (gps->points) MEM_freeN(gps->points);
70                 BLI_freelinkN(&gpf->strokes, gps);
71         }
72 }
73
74 /* Free all of a gp-layer's frames */
75 void free_gpencil_frames(bGPDlayer *gpl)
76 {
77         bGPDframe *gpf, *gpfn;
78         
79         /* error checking */
80         if (gpl == NULL) return;
81         
82         /* free frames */
83         for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
84                 gpfn = gpf->next;
85                 
86                 /* free strokes and their associated memory */
87                 free_gpencil_strokes(gpf);
88                 BLI_freelinkN(&gpl->frames, gpf);
89         }
90 }
91
92 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
93 void free_gpencil_layers(ListBase *list)
94 {
95         bGPDlayer *gpl, *gpln;
96         
97         /* error checking */
98         if (list == NULL) return;
99         
100         /* delete layers */
101         for (gpl = list->first; gpl; gpl = gpln) {
102                 gpln = gpl->next;
103                 
104                 /* free layers and their data */
105                 free_gpencil_frames(gpl);
106                 BLI_freelinkN(list, gpl);
107         }
108 }
109
110 /* Free all of GPencil datablock's related data, but not the block itself */
111 void BKE_gpencil_free(bGPdata *gpd)
112 {
113         /* free layers */
114         free_gpencil_layers(&gpd->layers);
115 }
116
117 /* -------- Container Creation ---------- */
118
119 /* add a new gp-frame to the given layer */
120 bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
121 {
122         bGPDframe *gpf, *gf;
123         short state = 0;
124         
125         /* error checking */
126         if ((gpl == NULL) || (cframe <= 0))
127                 return NULL;
128                 
129         /* allocate memory for this frame */
130         gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
131         gpf->framenum = cframe;
132         
133         /* find appropriate place to add frame */
134         if (gpl->frames.first) {
135                 for (gf = gpl->frames.first; gf; gf = gf->next) {
136                         /* check if frame matches one that is supposed to be added */
137                         if (gf->framenum == cframe) {
138                                 state = -1;
139                                 break;
140                         }
141                         
142                         /* if current frame has already exceeded the frame to add, add before */
143                         if (gf->framenum > cframe) {
144                                 BLI_insertlinkbefore(&gpl->frames, gf, gpf);
145                                 state = 1;
146                                 break;
147                         }
148                 }
149         }
150         
151         /* check whether frame was added successfully */
152         if (state == -1) {
153                 MEM_freeN(gpf);
154                 printf("Error: frame (%d) existed already for this layer\n", cframe);
155         }
156         else if (state == 0) {
157                 /* add to end then! */
158                 BLI_addtail(&gpl->frames, gpf);
159         }
160         
161         /* return frame */
162         return gpf;
163 }
164
165 /* add a new gp-layer and make it the active layer */
166 bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive)
167 {
168         bGPDlayer *gpl;
169         
170         /* check that list is ok */
171         if (gpd == NULL)
172                 return NULL;
173                 
174         /* allocate memory for frame and add to end of list */
175         gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
176         
177         /* add to datablock */
178         BLI_addtail(&gpd->layers, gpl);
179         
180         /* set basic settings */
181         gpl->color[3] = 0.9f;
182         gpl->thickness = 3;
183         
184         /* auto-name */
185         strcpy(gpl->info, name);
186         BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
187         
188         /* make this one the active one */
189         if (setactive)
190             gpencil_layer_setactive(gpd, gpl);
191         
192         /* return layer */
193         return gpl;
194 }
195
196 /* add a new gp-datablock */
197 bGPdata *gpencil_data_addnew(const char name[])
198 {
199         bGPdata *gpd;
200         
201         /* allocate memory for a new block */
202         gpd = BKE_libblock_alloc(&G.main->gpencil, ID_GD, name);
203         
204         /* initial settings */
205         gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
206         
207         /* for now, stick to view is also enabled by default
208          * since this is more useful...
209          */
210         gpd->flag |= GP_DATA_VIEWALIGN;
211         
212         return gpd;
213 }
214
215 /* -------- Data Duplication ---------- */
216
217 /* make a copy of a given gpencil frame */
218 bGPDframe *gpencil_frame_duplicate(bGPDframe *src)
219 {
220         bGPDstroke *gps, *gpsd;
221         bGPDframe *dst;
222         
223         /* error checking */
224         if (src == NULL)
225                 return NULL;
226                 
227         /* make a copy of the source frame */
228         dst = MEM_dupallocN(src);
229         dst->prev = dst->next = NULL;
230         
231         /* copy strokes */
232         dst->strokes.first = dst->strokes.last = NULL;
233         for (gps = src->strokes.first; gps; gps = gps->next) {
234                 /* make copy of source stroke, then adjust pointer to points too */
235                 gpsd = MEM_dupallocN(gps);
236                 gpsd->points = MEM_dupallocN(gps->points);
237                 
238                 BLI_addtail(&dst->strokes, gpsd);
239         }
240         
241         /* return new frame */
242         return dst;
243 }
244
245 /* make a copy of a given gpencil layer */
246 bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src)
247 {
248         bGPDframe *gpf, *gpfd;
249         bGPDlayer *dst;
250         
251         /* error checking */
252         if (src == NULL)
253                 return NULL;
254                 
255         /* make a copy of source layer */
256         dst = MEM_dupallocN(src);
257         dst->prev = dst->next = NULL;
258         
259         /* copy frames */
260         dst->frames.first = dst->frames.last = NULL;
261         for (gpf = src->frames.first; gpf; gpf = gpf->next) {
262                 /* make a copy of source frame */
263                 gpfd = gpencil_frame_duplicate(gpf);
264                 BLI_addtail(&dst->frames, gpfd);
265                 
266                 /* if source frame was the current layer's 'active' frame, reassign that too */
267                 if (gpf == dst->actframe)
268                         dst->actframe = gpfd;
269         }
270         
271         /* return new layer */
272         return dst;
273 }
274
275 /* make a copy of a given gpencil datablock */
276 bGPdata *gpencil_data_duplicate(bGPdata *src)
277 {
278         bGPDlayer *gpl, *gpld;
279         bGPdata *dst;
280         
281         /* error checking */
282         if (src == NULL)
283                 return NULL;
284         
285         /* make a copy of the base-data */
286         dst = MEM_dupallocN(src);
287         
288         /* copy layers */
289         dst->layers.first = dst->layers.last = NULL;
290         for (gpl = src->layers.first; gpl; gpl = gpl->next) {
291                 /* make a copy of source layer and its data */
292                 gpld = gpencil_layer_duplicate(gpl);
293                 BLI_addtail(&dst->layers, gpld);
294         }
295         
296         /* return new */
297         return dst;
298 }
299
300 /* -------- GP-Frame API ---------- */
301
302 /* delete the last stroke of the given frame */
303 void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
304 {
305         bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
306         int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
307         
308         /* error checking */
309         if (ELEM(NULL, gpf, gps))
310                 return;
311         
312         /* free the stroke and its data */
313         MEM_freeN(gps->points);
314         BLI_freelinkN(&gpf->strokes, gps);
315         
316         /* if frame has no strokes after this, delete it */
317         if (gpf->strokes.first == NULL) {
318                 gpencil_layer_delframe(gpl, gpf);
319                 gpencil_layer_getframe(gpl, cfra, 0);
320         }
321 }
322
323 /* -------- GP-Layer API ---------- */
324
325 bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
326 {
327         bGPDframe *gpf;
328
329         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
330                 if (gpf->framenum == cframe) {
331                         return gpf;
332                 }
333         }
334
335         return NULL;
336 }
337
338 /* get the appropriate gp-frame from a given layer
339  *      - this sets the layer's actframe var (if allowed to)
340  *      - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
341  */
342 bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
343 {
344         bGPDframe *gpf = NULL;
345         short found = 0;
346         
347         /* error checking */
348         if (gpl == NULL) return NULL;
349         if (cframe <= 0) cframe = 1;
350         
351         /* check if there is already an active frame */
352         if (gpl->actframe) {
353                 gpf = gpl->actframe;
354                 
355                 /* do not allow any changes to layer's active frame if layer is locked from changes
356                  * or if the layer has been set to stay on the current frame
357                  */
358                 if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_FRAMELOCK))
359                         return gpf;
360                 /* do not allow any changes to actframe if frame has painting tag attached to it */
361                 if (gpf->flag & GP_FRAME_PAINT) 
362                         return gpf;
363                 
364                 /* try to find matching frame */
365                 if (gpf->framenum < cframe) {
366                         for (; gpf; gpf = gpf->next) {
367                                 if (gpf->framenum == cframe) {
368                                         found = 1;
369                                         break;
370                                 }
371                                 else if ((gpf->next) && (gpf->next->framenum > cframe)) {
372                                         found = 1;
373                                         break;
374                                 }
375                         }
376                         
377                         /* set the appropriate frame */
378                         if (addnew) {
379                                 if ((found) && (gpf->framenum == cframe))
380                                         gpl->actframe = gpf;
381                                 else
382                                         gpl->actframe = gpencil_frame_addnew(gpl, cframe);
383                         }
384                         else if (found)
385                                 gpl->actframe = gpf;
386                         else
387                                 gpl->actframe = gpl->frames.last;
388                 }
389                 else {
390                         for (; gpf; gpf = gpf->prev) {
391                                 if (gpf->framenum <= cframe) {
392                                         found = 1;
393                                         break;
394                                 }
395                         }
396                         
397                         /* set the appropriate frame */
398                         if (addnew) {
399                                 if ((found) && (gpf->framenum == cframe))
400                                         gpl->actframe = gpf;
401                                 else
402                                         gpl->actframe = gpencil_frame_addnew(gpl, cframe);
403                         }
404                         else if (found)
405                                 gpl->actframe = gpf;
406                         else
407                                 gpl->actframe = gpl->frames.first;
408                 }
409         }
410         else if (gpl->frames.first) {
411                 /* check which of the ends to start checking from */
412                 const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
413                 const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
414                 
415                 if (abs(cframe - first) > abs(cframe - last)) {
416                         /* find gp-frame which is less than or equal to cframe */
417                         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
418                                 if (gpf->framenum <= cframe) {
419                                         found = 1;
420                                         break;
421                                 }
422                         }
423                 }
424                 else {
425                         /* find gp-frame which is less than or equal to cframe */
426                         for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
427                                 if (gpf->framenum <= cframe) {
428                                         found = 1;
429                                         break;
430                                 }
431                         }
432                 }
433                 
434                 /* set the appropriate frame */
435                 if (addnew) {
436                         if ((found) && (gpf->framenum == cframe))
437                                 gpl->actframe = gpf;
438                         else
439                                 gpl->actframe = gpencil_frame_addnew(gpl, cframe);
440                 }
441                 else if (found)
442                         gpl->actframe = gpf;
443                 else {
444                         /* unresolved errogenous situation! */
445                         printf("Error: cannot find appropriate gp-frame\n");
446                         /* gpl->actframe should still be NULL */
447                 }
448         }
449         else {
450                 /* currently no frames (add if allowed to) */
451                 if (addnew)
452                         gpl->actframe = gpencil_frame_addnew(gpl, cframe);
453                 else {
454                         /* don't do anything... this may be when no frames yet! */
455                         /* gpl->actframe should still be NULL */
456                 }
457         }
458         
459         /* return */
460         return gpl->actframe;
461 }
462
463 /* delete the given frame from a layer */
464 void gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
465 {
466         /* error checking */
467         if (ELEM(NULL, gpl, gpf))
468                 return;
469                 
470         /* free the frame and its data */
471         free_gpencil_strokes(gpf);
472         BLI_freelinkN(&gpl->frames, gpf);
473         gpl->actframe = NULL;
474 }
475
476 /* get the active gp-layer for editing */
477 bGPDlayer *gpencil_layer_getactive(bGPdata *gpd)
478 {
479         bGPDlayer *gpl;
480         
481         /* error checking */
482         if (ELEM(NULL, gpd, gpd->layers.first))
483                 return NULL;
484                 
485         /* loop over layers until found (assume only one active) */
486         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
487                 if (gpl->flag & GP_LAYER_ACTIVE)
488                         return gpl;
489         }
490         
491         /* no active layer found */
492         return NULL;
493 }
494
495 /* set the active gp-layer */
496 void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
497 {
498         bGPDlayer *gpl;
499         
500         /* error checking */
501         if (ELEM3(NULL, gpd, gpd->layers.first, active))
502                 return;
503                 
504         /* loop over layers deactivating all */
505         for (gpl = gpd->layers.first; gpl; gpl = gpl->next)
506                 gpl->flag &= ~GP_LAYER_ACTIVE;
507         
508         /* set as active one */
509         active->flag |= GP_LAYER_ACTIVE;
510 }
511
512 /* delete the active gp-layer */
513 void gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
514 {
515         /* error checking */
516         if (ELEM(NULL, gpd, gpl)) 
517                 return;
518         
519         /* free layer */        
520         free_gpencil_frames(gpl);
521         BLI_freelinkN(&gpd->layers, gpl);
522 }
523
524 /* ************************************************** */