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