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