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