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