c051678b86b303f85114d8e9b53731bcdb14be3b
[blender-staging.git] / source / blender / editors / gpencil / gpencil_buttons.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
21  * This is a new part of Blender
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27  
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_math.h"
36 #include "BLI_blenlib.h"
37
38 #include "DNA_gpencil_types.h"
39 #include "DNA_screen_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_gpencil.h"
44 #include "BKE_utildefines.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "RNA_access.h"
50
51 #include "BIF_gl.h"
52 #include "BIF_glutil.h"
53
54 #include "ED_gpencil.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58
59 #include "gpencil_intern.h"
60
61 /* ************************************************** */
62 /* GREASE PENCIL PANEL-UI DRAWING */
63
64 /* Every space which implements Grease-Pencil functionality should have a panel
65  * for the settings. All of the space-dependent parts should be coded in the panel
66  * code for that space, but the rest is all handled by generic panel here.
67  */
68
69 /* ------- Callbacks ----------- */
70 /* These are just 'dummy wrappers' around gpencil api calls */
71
72 /* make layer active one after being clicked on */
73 void gp_ui_activelayer_cb (bContext *C, void *gpd, void *gpl)
74 {
75         gpencil_layer_setactive(gpd, gpl);
76         
77         WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX please work!
78 }
79
80 /* delete 'active' layer */
81 void gp_ui_dellayer_cb (bContext *C, void *gpd, void *gpl)
82 {
83         /* make sure the layer we want to remove is the active one */
84         gpencil_layer_setactive(gpd, gpl); 
85         gpencil_layer_delactive(gpd);
86         
87         WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX please work!
88 }
89
90 /* ------- Drawing Code ------- */
91
92 /* draw the controls for a given layer */
93 static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl)
94 {
95         uiLayout *box=NULL, *split=NULL;
96         uiLayout *col=NULL, *subcol=NULL;
97         uiLayout *row=NULL, *subrow=NULL;
98         uiBlock *block;
99         uiBut *but;
100         PointerRNA ptr;
101         int icon;
102         
103         /* make pointer to layer data */
104         RNA_pointer_create((ID *)gpd, &RNA_GPencilLayer, gpl, &ptr);
105         
106         /* unless button has own callback, it adds this callback to button */
107         block= uiLayoutGetBlock(layout);
108         uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
109         
110         /* draw header ---------------------------------- */
111         /* get layout-row + UI-block for header */
112         box= uiLayoutBox(layout);
113         
114         row= uiLayoutRow(box, 0);
115         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
116         block= uiLayoutGetBlock(row); // err...
117         
118         uiBlockSetEmboss(block, UI_EMBOSSN);
119         
120         /* left-align ............................... */
121         subrow= uiLayoutRow(row, 0);
122         
123         /* active */
124         icon= (gpl->flag & GP_LAYER_ACTIVE) ? ICON_RADIOBUT_ON : ICON_RADIOBUT_OFF;
125         uiItemR(subrow, &ptr, "active", 0, "", icon);
126         
127         /* locked */
128         icon= (gpl->flag & GP_LAYER_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
129         uiItemR(subrow, &ptr, "lock", 0, "", icon);
130         
131         /* when layer is locked or hidden, only draw header */
132         if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
133                 char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
134                 
135                 /* visibility button (only if hidden but not locked!) */
136                 if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
137                         uiItemR(subrow, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_ON); 
138                         
139                 
140                 /* name */
141                 if (gpl->flag & GP_LAYER_HIDE)
142                         sprintf(name, "%s (Hidden)", gpl->info);
143                 else
144                         sprintf(name, "%s (Locked)", gpl->info);
145                 uiItemL(subrow, name, 0);
146                         
147                 /* delete button (only if hidden but not locked!) */
148                 if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
149                         /* right-align ............................... */
150                         subrow= uiLayoutRow(row, 1);
151                         uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
152                         block= uiLayoutGetBlock(subrow); // XXX... err...
153                         
154                         but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
155                         uiButSetFunc(but, gp_ui_dellayer_cb, gpd, gpl);
156                 }       
157                 uiBlockSetEmboss(block, UI_EMBOSS);
158         }
159         else {
160                 /* draw rest of header -------------------------------- */
161                 /* visibility button */
162                 uiItemR(subrow, &ptr, "hide", 0, "", ICON_RESTRICT_VIEW_OFF); 
163                 
164                 /* frame locking */
165                 // TODO: this needs its own icons...
166                 icon= (gpl->flag & GP_LAYER_FRAMELOCK) ? ICON_RENDER_STILL : ICON_RENDER_ANIMATION;
167                 uiItemR(subrow, &ptr, "frame_lock", 0, "", icon); 
168                 
169                 uiBlockSetEmboss(block, UI_EMBOSS);
170                 
171                 /* name */
172                 uiItemR(subrow, &ptr, "info", 0, "", 0);
173                 
174                 /* delete 'button' */
175                 uiBlockSetEmboss(block, UI_EMBOSSN);
176                         /* right-align ............................... */
177                         subrow= uiLayoutRow(row, 1);
178                         uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
179                         block= uiLayoutGetBlock(subrow); // XXX... err...
180                         
181                         but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
182                         uiButSetFunc(but, gp_ui_dellayer_cb, gpd, gpl);
183                 uiBlockSetEmboss(block, UI_EMBOSS);
184                 
185                 
186                 /* new backdrop ----------------------------------- */
187                 box= uiLayoutBox(layout);
188                 split= uiLayoutSplit(box, 0.5f, 0);
189                 
190                 /* draw settings ---------------------------------- */
191                 /* left column ..................... */
192                 col= uiLayoutColumn(split, 0);
193                 
194                 /* color */
195                 subcol= uiLayoutColumn(col, 1);
196                         uiItemR(subcol, &ptr, "color", 0, "", 0);
197                         uiItemR(subcol, &ptr, "opacity", UI_ITEM_R_SLIDER, NULL, 0);
198                         
199                 /* stroke thickness */
200                 subcol= uiLayoutColumn(col, 1);
201                         uiItemR(subcol, &ptr, "line_thickness", UI_ITEM_R_SLIDER, NULL, 0);
202                 
203                 /* debugging options */
204                 if (G.f & G_DEBUG) {
205                         subcol= uiLayoutColumn(col, 1);
206                                 uiItemR(subcol, &ptr, "show_points", 0, NULL, 0);
207                 }
208                 
209                 /* right column ................... */
210                 col= uiLayoutColumn(split, 0);
211                 
212                 /* onion-skinning */
213                 subcol= uiLayoutColumn(col, 1);
214                         uiItemR(subcol, &ptr, "use_onion_skinning", 0, "Onion Skinning", 0);
215                         uiItemR(subcol, &ptr, "max_ghost_range", 0, "Frames", 0); // XXX shorter name here? i.e. GStep
216                 
217                 /* additional options... */
218                 subcol= uiLayoutColumn(col, 1);
219                         uiItemO(subcol, "Delete Frame", 0, "GPENCIL_OT_active_frame_delete");
220                         uiItemO(subcol, "Convert...", 0, "GPENCIL_OT_convert");
221         }
222
223
224 /* stroke drawing options available */
225 typedef enum eGP_Stroke_Ops {
226         STROKE_OPTS_NORMAL = 0, 
227         STROKE_OPTS_V3D_OFF, 
228         STROKE_OPTS_V3D_ON,
229 } eGP_Stroke_Ops;
230
231 /* Draw the contents for a grease-pencil panel*/
232 static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, PointerRNA *ctx_ptr)
233 {
234         PointerRNA gpd_ptr;
235         bGPDlayer *gpl;
236         uiLayout *col, *row;
237         short v3d_stroke_opts = STROKE_OPTS_NORMAL;
238         
239         /* make new PointerRNA for Grease Pencil block */
240         RNA_id_pointer_create((ID *)gpd, &gpd_ptr);
241         
242         /* draw gpd settings first ------------------------------------- */
243         col= uiLayoutColumn(layout, 0);
244                 /* current Grease Pencil block */
245                 // TODO: show some info about who owns this?
246                 uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink"); 
247                 
248                 /* add new layer button - can be used even when no data, since it can add a new block too */
249                 uiItemO(col, NULL, 0, "GPENCIL_OT_layer_add");
250         
251         /* sanity checks... */
252         if (gpd == NULL)
253                 return;
254         
255         /* draw each layer --------------------------------------------- */
256         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
257                 col= uiLayoutColumn(layout, 1);
258                         gp_drawui_layer(col, gpd, gpl);
259         }
260         
261         /* draw gpd drawing settings first ------------------------------------- */
262         col= uiLayoutColumn(layout, 1);
263                 /* label */
264                 uiItemL(col, "Drawing Settings:", 0);
265                 
266                 /* check whether advanced 3D-View drawing space options can be used */
267                 if (CTX_wm_view3d(C)) {
268                         if (gpd->flag & (GP_DATA_DEPTH_STROKE|GP_DATA_DEPTH_VIEW))
269                                 v3d_stroke_opts = STROKE_OPTS_V3D_ON;
270                         else
271                                 v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
272                 }
273                 
274                 /* drawing space options */
275                 row= uiLayoutRow(col, 1);
276                         uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, 0);
277                         uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, 0);
278                 row= uiLayoutRow(col, 1);
279                         uiLayoutSetActive(row, v3d_stroke_opts);
280                         uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, 0);
281                         uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, 0);
282                 
283                 row= uiLayoutRow(col, 0);
284                         uiLayoutSetActive(row, v3d_stroke_opts==STROKE_OPTS_V3D_ON);
285                         uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, 0);
286 }       
287
288
289 /* Standard panel to be included whereever Grease Pencil is used... */
290 void gpencil_panel_standard(const bContext *C, Panel *pa)
291 {
292         bGPdata **gpd_ptr = NULL;
293         PointerRNA ptr;
294         
295         //if (v3d->flag2 & V3D_DISPGP)... etc.
296         
297         /* get pointer to Grease Pencil Data */
298         gpd_ptr= gpencil_data_get_pointers((bContext *)C, &ptr);
299         
300         if (gpd_ptr)
301                 draw_gpencil_panel((bContext *)C, pa->layout, *gpd_ptr, &ptr);
302 }
303
304 /* ************************************************** */