GPencil UI: Color swatches for both Stroke and Fill colors are now shown
[blender.git] / source / blender / makesrna / intern / rna_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  * Contributor(s): Blender Foundation (2009), Joshua Leung
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_gpencil.c
24  *  \ingroup RNA
25  */
26
27 #include <stdlib.h>
28
29 #include "DNA_gpencil_types.h"
30 #include "DNA_scene_types.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_utildefines.h"
35
36 #include "BLF_translation.h"
37
38 #include "RNA_access.h"
39 #include "RNA_define.h"
40
41 #include "rna_internal.h"
42
43 #include "WM_types.h"
44
45 #ifdef RNA_RUNTIME
46
47 #include "BLI_math.h"
48
49 #include "WM_api.h"
50
51 #include "BKE_gpencil.h"
52
53 static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
54 {
55         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
56 }
57
58 static char *rna_GPencilLayer_path(PointerRNA *ptr)
59 {
60         bGPDlayer *gpl = (bGPDlayer *)ptr->data;
61         char name_esc[sizeof(gpl->info) * 2];
62         
63         BLI_strescape(name_esc, gpl->info, sizeof(name_esc));
64         
65         return BLI_sprintfN("layers[\"%s\"]", name_esc);
66 }
67
68 static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
69 {
70         bGPDlayer *gpl = (bGPDlayer *)ptr->data;
71
72         /* surely there must be other criteria too... */
73         if (gpl->flag & GP_LAYER_LOCKED)
74                 return 0;
75         else
76                 return 1;
77 }
78
79 static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *max,
80                                               int *softmin, int *softmax)
81 {
82         bGPDlayer *gpl = ptr->data;
83         
84         /* The restrictions on max width here are due to OpenGL on Windows not supporting
85          * any widths greater than 10 (for driver-drawn) strokes/points.
86          *
87          * Although most of our 2D strokes also don't suffer from this restriction,
88          * it's relatively hard to test for that. So, for now, only volumetric strokes
89          * get to be larger...
90          */
91         if (gpl->flag & GP_LAYER_VOLUMETRIC) {
92                 *min = 1;
93                 *max = 300;
94                 
95                 *softmin = 1;
96                 *softmax = 100;
97         }
98         else {
99                 *min = 1;
100                 *max = 10;
101                 
102                 *softmin = 1;
103                 *softmax = 10;
104         }
105 }
106
107 static int rna_GPencilLayer_is_stroke_visible_get(PointerRNA *ptr)
108 {
109         /* see drawgpencil.c -> gp_draw_data_layers() for more details
110          * about this limit for showing/not showing
111          */
112         bGPDlayer *gpl = (bGPDlayer *)ptr->data;
113         return (gpl->color[3] > 0.001f);
114 }
115
116 static int rna_GPencilLayer_is_fill_visible_get(PointerRNA *ptr)
117 {
118         /* see drawgpencil.c -> gp_draw_data_layers() for more details
119          * about this limit for showing/not showing
120          */
121         bGPDlayer *gpl = (bGPDlayer *)ptr->data;
122         return (gpl->fill[3] > 0.001f);
123 }
124
125 static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
126 {
127         bGPdata *gpd = ptr->id.data;
128
129         if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
130                 bGPDlayer *gl;
131
132                 for (gl = gpd->layers.first; gl; gl = gl->next) {
133                         if (gl->flag & GP_LAYER_ACTIVE) {
134                                 break;
135                         }
136                 }
137
138                 if (gl) {
139                         return rna_pointer_inherit_refine(ptr, &RNA_GPencilLayer, gl);
140                 }
141         }
142
143         return rna_pointer_inherit_refine(ptr, NULL, NULL);
144 }
145
146 static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value)
147 {
148         bGPdata *gpd = ptr->id.data;
149
150         if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
151                 bGPDlayer *gl;
152
153                 for (gl = gpd->layers.first; gl; gl = gl->next) {
154                         if (gl == value.data) {
155                                 gl->flag |= GP_LAYER_ACTIVE;
156                         }
157                         else {
158                                 gl->flag &= ~GP_LAYER_ACTIVE;
159                         }
160                 }
161                 
162                 WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
163         }
164 }
165
166 static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
167 {
168         bGPdata *gpd = (bGPdata *)ptr->id.data;
169         bGPDlayer *gpl = gpencil_layer_getactive(gpd);
170         
171         return BLI_findindex(&gpd->layers, gpl);
172 }
173
174 static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
175 {
176         bGPdata *gpd   = (bGPdata *)ptr->id.data;
177         bGPDlayer *gpl = BLI_findlink(&gpd->layers, value);
178
179         gpencil_layer_setactive(gpd, gpl);
180 }
181
182 static void rna_GPencil_active_layer_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
183 {
184         bGPdata *gpd = (bGPdata *)ptr->id.data;
185
186         *min = 0;
187         *max = max_ii(0, BLI_listbase_count(&gpd->layers) - 1);
188
189         *softmin = *min;
190         *softmax = *max;
191 }
192
193 static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
194 {
195         bGPdata *gpd = ptr->id.data;
196         bGPDlayer *gpl = ptr->data;
197
198         /* copy the new name into the name slot */
199         BLI_strncpy_utf8(gpl->info, value, sizeof(gpl->info));
200
201         BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
202 }
203
204
205 static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, const bGPDspoint *pt, bGPDlayer **r_gpl, bGPDframe **r_gpf)
206 {
207         bGPDlayer *gpl;
208         bGPDstroke *gps;
209         
210         /* sanity checks */
211         if (ELEM(NULL, gpd, pt)) {
212                 return NULL;
213         }
214         
215         if (r_gpl) *r_gpl = NULL;
216         if (r_gpf) *r_gpf = NULL;
217         
218         /* there's no faster alternative than just looping over everything... */
219         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
220                 if (gpl->actframe) {
221                         for (gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
222                                 if ((pt >= gps->points) && (pt < &gps->points[gps->totpoints])) {
223                                         /* found it */
224                                         if (r_gpl) *r_gpl = gpl;
225                                         if (r_gpf) *r_gpf = gpl->actframe;
226                                         
227                                         return gps;
228                                 }
229                         }
230                 }
231         }
232         
233         /* didn't find it */
234         return NULL;
235 }
236
237 static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value)
238 {
239         bGPdata *gpd = ptr->id.data;
240         bGPDspoint *pt = ptr->data;
241         bGPDstroke *gps = NULL;
242         
243         /* Ensure that corresponding stroke is set 
244          * - Since we don't have direct access, we're going to have to search
245          * - We don't apply selection value unless we can find the corresponding
246          *   stroke, so that they don't get out of sync
247          */
248         gps = rna_GPencil_stroke_point_find_stroke(gpd, pt, NULL, NULL);
249         if (gps) {
250                 /* Set the new selection state for the point */
251                 if (value)
252                         pt->flag |= GP_SPOINT_SELECT;
253                 else
254                         pt->flag &= ~GP_SPOINT_SELECT;
255                 
256                 /* Check if the stroke should be selected or not... */
257                 gpencil_stroke_sync_selection(gps);
258         }
259 }
260
261 static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count)
262 {
263         if (count > 0) {
264                 stroke->points = MEM_recallocN_id(stroke->points,
265                                                   sizeof(bGPDspoint) * (stroke->totpoints + count),
266                                                   "gp_stroke_points");
267                 stroke->totpoints += count;
268         }
269 }
270
271 static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports, int index)
272 {
273         bGPDspoint *pt_tmp = stroke->points;
274
275         /* python style negative indexing */
276         if (index < 0) {
277                 index += stroke->totpoints;
278         }
279
280         if (stroke->totpoints <= index || index < 0) {
281                 BKE_report(reports, RPT_ERROR, "GPencilStrokePoints.pop: index out of range");
282                 return;
283         }
284
285         stroke->totpoints--;
286
287         stroke->points = MEM_callocN(sizeof(bGPDspoint) * stroke->totpoints, "gp_stroke_points");
288
289         if (index > 0)
290                 memcpy(stroke->points, pt_tmp, sizeof(bGPDspoint) * index);
291
292         if (index < stroke->totpoints)
293                 memcpy(&stroke->points[index], &pt_tmp[index + 1], sizeof(bGPDspoint) * (stroke->totpoints - index));
294
295         /* free temp buffer */
296         MEM_freeN(pt_tmp);
297
298         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
299 }
300
301 static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame)
302 {
303         bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
304
305         BLI_addtail(&frame->strokes, stroke);
306
307         return stroke;
308 }
309
310 static void rna_GPencil_stroke_remove(bGPDframe *frame, ReportList *reports, PointerRNA *stroke_ptr)
311 {
312         bGPDstroke *stroke = stroke_ptr->data;
313         if (BLI_findindex(&frame->strokes, stroke) == -1) {
314                 BKE_report(reports, RPT_ERROR, "Stroke not found in grease pencil frame");
315                 return;
316         }
317
318         BLI_freelinkN(&frame->strokes, stroke);
319         RNA_POINTER_INVALIDATE(stroke_ptr);
320
321         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
322 }
323
324 static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const int value)
325 {
326         bGPDstroke *gps = ptr->data;
327         bGPDspoint *pt;
328         int i;
329         
330         /* set new value */
331         if (value)
332                 gps->flag |= GP_STROKE_SELECT;
333         else
334                 gps->flag &= ~GP_STROKE_SELECT;
335                 
336         /* ensure that the stroke's points are selected in the same way */
337         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
338                 if (value)
339                         pt->flag |= GP_SPOINT_SELECT;
340                 else
341                         pt->flag &= ~GP_SPOINT_SELECT;
342         }
343 }
344
345 static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, int frame_number)
346 {
347         bGPDframe *frame;
348
349         if (BKE_gpencil_layer_find_frame(layer, frame_number)) {
350                 BKE_reportf(reports, RPT_ERROR, "Frame already exists on this frame number %d", frame_number);
351                 return NULL;
352         }
353
354         frame = gpencil_frame_addnew(layer, frame_number);
355
356         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
357
358         return frame;
359 }
360
361 static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, PointerRNA *frame_ptr)
362 {
363         bGPDframe *frame = frame_ptr->data;
364         if (BLI_findindex(&layer->frames, frame) == -1) {
365                 BKE_report(reports, RPT_ERROR, "Frame not found in grease pencil layer");
366                 return;
367         }
368
369         gpencil_layer_delframe(layer, frame);
370         RNA_POINTER_INVALIDATE(frame_ptr);
371
372         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
373 }
374
375 static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src)
376 {
377         bGPDframe *frame = gpencil_frame_duplicate(src);
378
379         while (BKE_gpencil_layer_find_frame(layer, frame->framenum)) {
380                 frame->framenum++;
381         }
382
383         BLI_addtail(&layer->frames, frame);
384
385         WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
386
387         return frame;
388 }
389
390 static bGPDlayer *rna_GPencil_layer_new(bGPdata *gpd, const char *name, int setactive)
391 {
392         bGPDlayer *gl = gpencil_layer_addnew(gpd, name, setactive);
393
394         WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
395
396         return gl;
397 }
398
399 static void rna_GPencil_layer_remove(bGPdata *gpd, ReportList *reports, PointerRNA *layer_ptr)
400 {
401         bGPDlayer *layer = layer_ptr->data;
402         if (BLI_findindex(&gpd->layers, layer) == -1) {
403                 BKE_report(reports, RPT_ERROR, "Layer not found in grease pencil data");
404                 return;
405         }
406
407         gpencil_layer_delete(gpd, layer);
408         RNA_POINTER_INVALIDATE(layer_ptr);
409
410         WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
411 }
412
413 static void rna_GPencil_frame_clear(bGPDframe *frame)
414 {
415         free_gpencil_strokes(frame);
416
417         WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
418 }
419
420 static void rna_GPencil_layer_clear(bGPDlayer *layer)
421 {
422         free_gpencil_frames(layer);
423
424         WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
425 }
426
427 static void rna_GPencil_clear(bGPdata *gpd)
428 {
429         free_gpencil_layers(&gpd->layers);
430
431         WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
432 }
433
434 #else
435
436 static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
437 {
438         StructRNA *srna;
439         PropertyRNA *prop;
440         
441         srna = RNA_def_struct(brna, "GPencilStrokePoint", NULL);
442         RNA_def_struct_sdna(srna, "bGPDspoint");
443         RNA_def_struct_ui_text(srna, "Grease Pencil Stroke Point", "Data point for freehand stroke curve");
444         
445         prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ);
446         RNA_def_property_float_sdna(prop, NULL, "x");
447         RNA_def_property_array(prop, 3);
448         RNA_def_property_ui_text(prop, "Coordinates", "");
449         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
450         
451         prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE);
452         RNA_def_property_float_sdna(prop, NULL, "pressure");
453         RNA_def_property_range(prop, 0.0f, 1.0f);
454         RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it");
455         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
456         
457         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
458         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SPOINT_SELECT);
459         RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_point_select_set");
460         RNA_def_property_ui_text(prop, "Select", "Point is selected for viewport editing");
461         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
462 }
463
464 static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop)
465 {
466         StructRNA *srna;
467
468         FunctionRNA *func;
469         /* PropertyRNA *parm; */
470
471         RNA_def_property_srna(cprop, "GPencilStrokePoints");
472         srna = RNA_def_struct(brna, "GPencilStrokePoints", NULL);
473         RNA_def_struct_sdna(srna, "bGPDstroke");
474         RNA_def_struct_ui_text(srna, "Grease Pencil Stroke Points", "Collection of grease pencil stroke points");
475
476         func = RNA_def_function(srna, "add", "rna_GPencil_stroke_point_add");
477         RNA_def_function_ui_description(func, "Add a new grease pencil stroke point");
478         RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the stroke", 0, INT_MAX);
479
480         func = RNA_def_function(srna, "pop", "rna_GPencil_stroke_point_pop");
481         RNA_def_function_ui_description(func, "Remove a grease pencil stroke point");
482         RNA_def_function_flag(func, FUNC_USE_REPORTS);
483         RNA_def_int(func, "index", -1, INT_MIN, INT_MAX, "Index", "point index", INT_MIN, INT_MAX);
484 }
485
486 static void rna_def_gpencil_stroke(BlenderRNA *brna)
487 {
488         StructRNA *srna;
489         PropertyRNA *prop;
490
491         static EnumPropertyItem stroke_draw_mode_items[] = {
492                 {0, "SCREEN", 0, "Screen", "Stroke is in screen-space"},
493                 {GP_STROKE_3DSPACE, "3DSPACE", 0, "3D Space", "Stroke is in 3D-space"},
494                 {GP_STROKE_2DSPACE, "2DSPACE", 0, "2D Space", "Stroke is in 2D-space"},
495                 {GP_STROKE_2DIMAGE, "2DIMAGE", 0, "2D Image", "Stroke is in 2D-space (but with special 'image' scaling)"},
496                 {0, NULL, 0, NULL, NULL}
497         };
498         
499         srna = RNA_def_struct(brna, "GPencilStroke", NULL);
500         RNA_def_struct_sdna(srna, "bGPDstroke");
501         RNA_def_struct_ui_text(srna, "Grease Pencil Stroke", "Freehand curve defining part of a sketch");
502         
503         /* Points */
504         prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
505         RNA_def_property_collection_sdna(prop, NULL, "points", "totpoints");
506         RNA_def_property_struct_type(prop, "GPencilStrokePoint");
507         RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points");
508         rna_def_gpencil_stroke_points_api(brna, prop);
509         
510         /* Settings */
511         prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
512         RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
513         RNA_def_property_enum_items(prop, stroke_draw_mode_items);
514         RNA_def_property_ui_text(prop, "Draw Mode", "");
515         RNA_def_property_update(prop, 0, "rna_GPencil_update");
516         
517         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
518         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_SELECT);
519         RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_select_set");
520         RNA_def_property_ui_text(prop, "Select", "Stroke is selected for viewport editing");
521         RNA_def_property_update(prop, 0, "rna_GPencil_update");
522 }
523
524 static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
525 {
526         StructRNA *srna;
527
528         FunctionRNA *func;
529         PropertyRNA *parm;
530
531         RNA_def_property_srna(cprop, "GPencilStrokes");
532         srna = RNA_def_struct(brna, "GPencilStrokes", NULL);
533         RNA_def_struct_sdna(srna, "bGPDframe");
534         RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil stroke");
535
536         func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new");
537         RNA_def_function_ui_description(func, "Add a new grease pencil stroke");
538         parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke");
539         RNA_def_function_return(func, parm);
540
541         func = RNA_def_function(srna, "remove", "rna_GPencil_stroke_remove");
542         RNA_def_function_ui_description(func, "Remove a grease pencil stroke");
543         RNA_def_function_flag(func, FUNC_USE_REPORTS);
544         parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove");
545         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
546         RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
547 }
548
549 static void rna_def_gpencil_frame(BlenderRNA *brna)
550 {
551         StructRNA *srna;
552         PropertyRNA *prop;
553
554         FunctionRNA *func;
555         
556         srna = RNA_def_struct(brna, "GPencilFrame", NULL);
557         RNA_def_struct_sdna(srna, "bGPDframe");
558         RNA_def_struct_ui_text(srna, "Grease Pencil Frame", "Collection of related sketches on a particular frame");
559         
560         /* Strokes */
561         prop = RNA_def_property(srna, "strokes", PROP_COLLECTION, PROP_NONE);
562         RNA_def_property_collection_sdna(prop, NULL, "strokes", NULL);
563         RNA_def_property_struct_type(prop, "GPencilStroke");
564         RNA_def_property_ui_text(prop, "Strokes", "Freehand curves defining the sketch on this frame");
565         rna_def_gpencil_strokes_api(brna, prop);
566
567         /* Frame Number */
568         prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
569         RNA_def_property_int_sdna(prop, NULL, "framenum");
570         /* XXX note: this cannot occur on the same frame as another sketch */
571         RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
572         RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
573         
574         /* Flags */
575         prop = RNA_def_property(srna, "is_edited", PROP_BOOLEAN, PROP_NONE);
576         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_PAINT); /* XXX should it be editable? */
577         RNA_def_property_ui_text(prop, "Paint Lock", "Frame is being edited (painted on)");
578         
579         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
580         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_SELECT);
581         RNA_def_property_ui_text(prop, "Select", "Frame is selected for editing in the Dope Sheet");
582
583         func = RNA_def_function(srna, "clear", "rna_GPencil_frame_clear");
584         RNA_def_function_ui_description(func, "Remove all the grease pencil frame data");
585 }
586
587 static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop)
588 {
589         StructRNA *srna;
590
591         FunctionRNA *func;
592         PropertyRNA *parm;
593
594         RNA_def_property_srna(cprop, "GPencilFrames");
595         srna = RNA_def_struct(brna, "GPencilFrames", NULL);
596         RNA_def_struct_sdna(srna, "bGPDlayer");
597         RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames");
598
599         func = RNA_def_function(srna, "new", "rna_GPencil_frame_new");
600         RNA_def_function_ui_description(func, "Add a new grease pencil frame");
601         RNA_def_function_flag(func, FUNC_USE_REPORTS);
602         parm = RNA_def_int(func, "frame_number", 1, MINAFRAME, MAXFRAME, "Frame Number",
603                            "The frame on which this sketch appears", MINAFRAME, MAXFRAME);
604         RNA_def_property_flag(parm, PROP_REQUIRED);
605         parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame");
606         RNA_def_function_return(func, parm);
607
608         func = RNA_def_function(srna, "remove", "rna_GPencil_frame_remove");
609         RNA_def_function_ui_description(func, "Remove a grease pencil frame");
610         RNA_def_function_flag(func, FUNC_USE_REPORTS);
611         parm = RNA_def_pointer(func, "frame", "GPencilFrame", "Frame", "The frame to remove");
612         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
613         RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
614
615         func = RNA_def_function(srna, "copy", "rna_GPencil_frame_copy");
616         RNA_def_function_ui_description(func, "Copy a grease pencil frame");
617         parm = RNA_def_pointer(func, "source", "GPencilFrame", "Source", "The source frame");
618         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
619         parm = RNA_def_pointer(func, "copy", "GPencilFrame", "", "The newly copied frame");
620         RNA_def_function_return(func, parm);
621 }
622
623 static void rna_def_gpencil_layer(BlenderRNA *brna)
624 {
625         StructRNA *srna;
626         PropertyRNA *prop;
627
628         FunctionRNA *func;
629         
630         srna = RNA_def_struct(brna, "GPencilLayer", NULL);
631         RNA_def_struct_sdna(srna, "bGPDlayer");
632         RNA_def_struct_ui_text(srna, "Grease Pencil Layer", "Collection of related sketches");
633         RNA_def_struct_path_func(srna, "rna_GPencilLayer_path");
634         
635         /* Name */
636         prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
637         RNA_def_property_ui_text(prop, "Info", "Layer name");
638         RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilLayer_info_set");
639         RNA_def_struct_name_property(srna, prop);
640         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
641
642         /* Frames */
643         prop = RNA_def_property(srna, "frames", PROP_COLLECTION, PROP_NONE);
644         RNA_def_property_collection_sdna(prop, NULL, "frames", NULL);
645         RNA_def_property_struct_type(prop, "GPencilFrame");
646         RNA_def_property_ui_text(prop, "Frames", "Sketches for this layer on different frames");
647         rna_def_gpencil_frames_api(brna, prop);
648
649         /* Active Frame */
650         prop = RNA_def_property(srna, "active_frame", PROP_POINTER, PROP_NONE);
651         RNA_def_property_pointer_sdna(prop, NULL, "actframe");
652         RNA_def_property_ui_text(prop, "Active Frame", "Frame currently being displayed for this layer");
653         RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable");
654         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
655
656         /* Draw Style */
657         // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)?
658         prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE);
659         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC);
660         RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect");
661         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
662         
663         /* Stroke Drawing Color */
664         prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
665         RNA_def_property_array(prop, 3);
666         RNA_def_property_range(prop, 0.0f, 1.0f);
667         RNA_def_property_ui_text(prop, "Color", "Color for all strokes in this layer");
668         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
669         
670         prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
671         RNA_def_property_float_sdna(prop, NULL, "color[3]");
672         RNA_def_property_range(prop, 0.0, 1.0f);
673         RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity");
674         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
675         
676         /* Fill Drawing Color */
677         prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
678         RNA_def_property_float_sdna(prop, NULL, "fill");
679         RNA_def_property_array(prop, 3);
680         RNA_def_property_range(prop, 0.0f, 1.0f);
681         RNA_def_property_ui_text(prop, "Fill Color", "Color for filling region bounded by each stroke");
682         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
683         
684         prop = RNA_def_property(srna, "fill_alpha", PROP_FLOAT, PROP_NONE);
685         RNA_def_property_float_sdna(prop, NULL, "fill[3]");
686         RNA_def_property_range(prop, 0.0, 1.0f);
687         RNA_def_property_ui_text(prop, "Fill Opacity", "Opacity for filling region bounded by each stroke");
688         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
689         
690         /* Line Thickness */
691         prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_PIXEL);
692         RNA_def_property_int_sdna(prop, NULL, "thickness");
693         //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */
694         RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range");
695         RNA_def_property_ui_text(prop, "Thickness", "Thickness of strokes (in pixels)");
696         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
697         
698         /* Onion-Skinning */
699         prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE);
700         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ONIONSKIN);
701         RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame");
702         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
703         
704         prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
705         RNA_def_property_int_sdna(prop, NULL, "gstep");
706         RNA_def_property_range(prop, 0, 120);
707         RNA_def_property_ui_text(prop, "Frames Before",
708                                  "Maximum number of frames to show before current frame "
709                                  "(0 = show only the previous sketch)");
710         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
711         
712         prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
713         RNA_def_property_int_sdna(prop, NULL, "gstep_next");
714         RNA_def_property_range(prop, 0, 120);
715         RNA_def_property_ui_text(prop, "Frames After",
716                                  "Maximum number of frames to show after current frame "
717                                  "(0 = show only the next sketch)");
718         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
719         
720         prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
721         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL);
722         RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
723         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
724         
725         prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
726         RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
727         RNA_def_property_array(prop, 3);
728         RNA_def_property_range(prop, 0.0f, 1.0f);
729         RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
730         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
731         
732         prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
733         RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
734         RNA_def_property_array(prop, 3);
735         RNA_def_property_range(prop, 0.0f, 1.0f);
736         RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
737         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
738         
739         /* Flags */
740         prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
741         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
742         RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
743         RNA_def_property_ui_text(prop, "Hide", "Set layer Visibility");
744         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
745         
746         prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
747         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED);
748         RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
749         RNA_def_property_ui_text(prop, "Locked", "Protect layer from further editing and/or frame changes");
750         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
751         
752         prop = RNA_def_property(srna, "lock_frame", PROP_BOOLEAN, PROP_NONE);
753         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK);
754         RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
755         RNA_def_property_ui_text(prop, "Frame Locked", "Lock current frame displayed by layer");
756         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
757
758         /* expose as layers.active */
759 #if 0
760         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
761         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ACTIVE);
762         RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencilLayer_active_set");
763         RNA_def_property_ui_text(prop, "Active", "Set active layer for editing");
764         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
765 #endif
766
767         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
768         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SELECT);
769         RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the Dope Sheet");
770         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
771         
772         /* XXX keep this option? */
773         prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE);
774         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG);
775         RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)");
776         RNA_def_property_update_runtime(prop, "rna_GPencil_update");
777
778         /* X-Ray */
779         prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE);
780         RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY);
781         RNA_def_property_ui_text(prop, "X Ray", "Make the layer draw in front of objects");
782         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
783         
784         
785         /* Read-only state props (for simpler UI code) */
786         prop = RNA_def_property(srna, "is_stroke_visible", PROP_BOOLEAN, PROP_NONE);
787         RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_stroke_visible_get", NULL);
788         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
789         RNA_def_property_ui_text(prop, "Is Stroke Visible", "True when opacity of stroke is set high enough to be visible");
790         
791         prop = RNA_def_property(srna, "is_fill_visible", PROP_BOOLEAN, PROP_NONE);
792         RNA_def_property_boolean_funcs(prop, "rna_GPencilLayer_is_fill_visible_get", NULL);
793         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
794         RNA_def_property_ui_text(prop, "Is Fill Visible", "True when opacity of fill is set high enough to be visible");
795         
796         /* Layers API */
797         func = RNA_def_function(srna, "clear", "rna_GPencil_layer_clear");
798         RNA_def_function_ui_description(func, "Remove all the grease pencil layer data");
799 }
800
801 static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
802 {
803         StructRNA *srna;
804         PropertyRNA *prop;
805
806         FunctionRNA *func;
807         PropertyRNA *parm;
808
809         RNA_def_property_srna(cprop, "GreasePencilLayers");
810         srna = RNA_def_struct(brna, "GreasePencilLayers", NULL);
811         RNA_def_struct_sdna(srna, "bGPdata");
812         RNA_def_struct_ui_text(srna, "Grease Pencil Layers", "Collection of grease pencil layers");
813
814         func = RNA_def_function(srna, "new", "rna_GPencil_layer_new");
815         RNA_def_function_ui_description(func, "Add a new grease pencil layer");
816         parm = RNA_def_string(func, "name", "GPencilLayer", MAX_NAME, "Name", "Name of the layer");
817         RNA_def_property_flag(parm, PROP_REQUIRED);
818         RNA_def_boolean(func, "set_active", 0, "Set Active", "Set the newly created layer to the active layer");
819         parm = RNA_def_pointer(func, "layer", "GPencilLayer", "", "The newly created layer");
820         RNA_def_function_return(func, parm);
821
822         func = RNA_def_function(srna, "remove", "rna_GPencil_layer_remove");
823         RNA_def_function_ui_description(func, "Remove a grease pencil layer");
824         RNA_def_function_flag(func, FUNC_USE_REPORTS);
825         parm = RNA_def_pointer(func, "layer", "GPencilLayer", "", "The layer to remove");
826         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
827         RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
828
829         prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
830         RNA_def_property_struct_type(prop, "GPencilLayer");
831         RNA_def_property_pointer_funcs(prop, "rna_GPencil_active_layer_get", "rna_GPencil_active_layer_set", NULL, NULL);
832         RNA_def_property_flag(prop, PROP_EDITABLE);
833         RNA_def_property_ui_text(prop, "Active Layer", "Active grease pencil layer");
834         
835         prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
836         
837         RNA_def_property_int_funcs(prop,
838                                    "rna_GPencil_active_layer_index_get", 
839                                    "rna_GPencil_active_layer_index_set", 
840                                    "rna_GPencil_active_layer_index_range");
841         RNA_def_property_ui_text(prop, "Active Layer Index", "Index of active grease pencil layer");
842 }
843
844 static void rna_def_gpencil_data(BlenderRNA *brna)
845 {
846         StructRNA *srna;
847         PropertyRNA *prop;
848         FunctionRNA *func;
849
850         static EnumPropertyItem draw_mode_items[] = {
851                 {GP_DATA_VIEWALIGN, "CURSOR", 0, "Cursor", "Draw stroke at the 3D cursor"},
852                 {0, "VIEW", 0, "View", "Stick stroke to the view "}, /* weird, GP_DATA_VIEWALIGN is inverted */
853                 {GP_DATA_VIEWALIGN | GP_DATA_DEPTH_VIEW, "SURFACE", 0, "Surface", "Stick stroke to surfaces"},
854                 {GP_DATA_VIEWALIGN | GP_DATA_DEPTH_STROKE, "STROKE", 0, "Stroke", "Stick stroke to other strokes"},
855                 {0, NULL, 0, NULL, NULL}
856         };
857
858         srna = RNA_def_struct(brna, "GreasePencil", "ID");
859         RNA_def_struct_sdna(srna, "bGPdata");
860         RNA_def_struct_ui_text(srna, "Grease Pencil", "Freehand annotation sketchbook");
861         RNA_def_struct_ui_icon(srna, ICON_GREASEPENCIL);
862         
863         /* Layers */
864         prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
865         RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
866         RNA_def_property_struct_type(prop, "GPencilLayer");
867         RNA_def_property_ui_text(prop, "Layers", "");
868         rna_def_gpencil_layers_api(brna, prop);
869         
870         /* Animation Data */
871         rna_def_animdata_common(srna);
872         
873         /* Flags */
874         prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
875         RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
876         RNA_def_property_enum_items(prop, draw_mode_items);
877         RNA_def_property_ui_text(prop, "Draw Mode", "");
878         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
879
880         prop = RNA_def_property(srna, "use_stroke_endpoints", PROP_BOOLEAN, PROP_NONE);
881         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS);
882         RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping");
883         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
884         
885         prop = RNA_def_property(srna, "use_stroke_edit_mode", PROP_BOOLEAN, PROP_NONE);
886         RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_EDITMODE);
887         RNA_def_property_ui_text(prop, "Stroke Edit Mode", "Enable alternative keymap to make editing stroke points easier");
888         RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_update");
889         
890         /* API Functions */
891         func = RNA_def_function(srna, "clear", "rna_GPencil_clear");
892         RNA_def_function_ui_description(func, "Remove all the grease pencil data");
893 }
894
895 /* --- */
896
897 void RNA_def_gpencil(BlenderRNA *brna)
898 {
899         rna_def_gpencil_data(brna);
900
901         rna_def_gpencil_layer(brna);
902         rna_def_gpencil_frame(brna);
903         rna_def_gpencil_stroke(brna);
904         rna_def_gpencil_stroke_point(brna);
905 }
906
907 #endif