Grease Pencil: WIP Code Reordering + Context Stuff
[blender.git] / source / blender / editors / gpencil / gpencil_buttons.c
1 /**
2  * $Id: drawgpencil.c 22802 2009-08-26 12:01:15Z aligorith $
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_arithb.h"
36 #include "BLI_blenlib.h"
37
38 #include "DNA_gpencil_types.h"
39 #include "DNA_listBase.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_userdef_types.h"
43 #include "DNA_windowmanager_types.h"
44
45 #include "BKE_context.h"
46 #include "BKE_global.h"
47 #include "BKE_gpencil.h"
48 #include "BKE_utildefines.h"
49
50 #include "PIL_time.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "BIF_gl.h"
56 #include "BIF_glutil.h"
57
58 #include "ED_gpencil.h"
59 #include "ED_sequencer.h"
60 #include "ED_util.h"
61
62 #include "UI_interface.h"
63 #include "UI_resources.h"
64 #include "UI_view2d.h"
65
66 #include "gpencil_intern.h"
67
68 /* ************************************************** */
69 /* GREASE PENCIL PANEL-UI DRAWING */
70
71 /* Every space which implements Grease-Pencil functionality should have a panel
72  * for the settings. All of the space-dependent parts should be coded in the panel
73  * code for that space, but the rest is all handled by generic panel here.
74  */
75
76 /* ------- Callbacks ----------- */
77 /* These are just 'dummy wrappers' around gpencil api calls */
78
79 #if 0
80 // XXX
81 /* make layer active one after being clicked on */
82 void gp_ui_activelayer_cb (void *gpd, void *gpl)
83 {
84         gpencil_layer_setactive(gpd, gpl);
85         
86         scrarea_queue_winredraw(curarea);
87         allqueue(REDRAWACTION, 0);
88 }
89
90 /* rename layer and set active */
91 void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
92 {
93         bGPdata *gpd= (bGPdata *)gpd_arg;
94         bGPDlayer *gpl= (bGPDlayer *)gpl_arg;
95         
96         BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128);
97         gpencil_layer_setactive(gpd, gpl);
98         
99         scrarea_queue_winredraw(curarea);
100         allqueue(REDRAWACTION, 0);
101 }
102
103 /* add a new layer */
104 void gp_ui_addlayer_cb (void *gpd, void *dummy)
105 {
106         gpencil_layer_addnew(gpd);
107         
108         scrarea_queue_winredraw(curarea);
109         allqueue(REDRAWACTION, 0);
110 }
111
112 /* delete active layer */
113 void gp_ui_dellayer_cb (void *gpd, void *dummy)
114 {
115         gpencil_layer_delactive(gpd);
116         
117         scrarea_queue_winredraw(curarea);
118         allqueue(REDRAWACTION, 0);
119 }
120
121 /* delete last stroke of active layer */
122 void gp_ui_delstroke_cb (void *gpd, void *gpl)
123 {
124         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
125         
126         if (gpf) {
127                 if (gpf->framenum != CFRA) return;
128
129                 gpencil_layer_setactive(gpd, gpl);
130                 gpencil_frame_delete_laststroke(gpl, gpf);
131                 
132                 scrarea_queue_winredraw(curarea);
133         }
134 }
135
136 /* delete active frame of active layer */
137 void gp_ui_delframe_cb (void *gpd, void *gpl)
138 {
139         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
140         
141         gpencil_layer_setactive(gpd, gpl);
142         gpencil_layer_delframe(gpl, gpf);
143         
144         scrarea_queue_winredraw(curarea);
145         allqueue(REDRAWACTION, 0);
146 }
147
148 /* convert the active layer to geometry */
149 void gp_ui_convertlayer_cb (void *gpd, void *gpl)
150 {
151         gpencil_layer_setactive(gpd, gpl);
152         gpencil_convert_menu();
153         
154         scrarea_queue_winredraw(curarea);
155 }
156 #endif
157
158 /* ------- Drawing Code ------- */
159
160 #if 0
161 /* XXX */
162 /* draw the controls for a given layer */
163 static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
164 {
165         uiBut *but;
166         short active= (gpl->flag & GP_LAYER_ACTIVE);
167         short width= 314;
168         short height;
169         int rb_col;
170         
171         /* unless button has own callback, it adds this callback to button */
172         uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
173         
174         /* draw header */
175         {
176                 uiBlockSetEmboss(block, UI_EMBOSSN);
177                 
178                 /* rounded header */
179                 if (active) uiBlockSetCol(block, TH_BUT_ACTION);
180                         rb_col= (active)?-20:20;
181                         uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), ""); 
182                 if (active) uiBlockSetCol(block, TH_AUTO);
183                 
184                 /* lock toggle */
185                 uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED,        *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
186         }
187         
188         /* when layer is locked or hidden, only draw header */
189         if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
190                 char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
191                 
192                 height= 0;
193                 
194                 /* visibility button (only if hidden but not locked!) */
195                 if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
196                         uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
197                 
198                 /* name */
199                 if (gpl->flag & GP_LAYER_HIDE)
200                         sprintf(name, "%s (Hidden)", gpl->info);
201                 else
202                         sprintf(name, "%s (Locked)", gpl->info);
203                 uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
204                         
205                 /* delete button (only if hidden but not locked!) */
206                 if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
207                         but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
208                         uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
209                 }       
210                 uiBlockSetEmboss(block, UI_EMBOSS);
211         }
212         else {
213                 height= 97;
214                 
215                 /* draw rest of header */
216                 {
217                         /* visibility button */
218                         uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
219                         
220                         uiBlockSetEmboss(block, UI_EMBOSS);
221                         
222                         /* name */
223                         but= uiDefButC(block, TEX, B_REDR, "Info:",     *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
224                         uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
225                         
226                         /* delete 'button' */
227                         uiBlockSetEmboss(block, UI_EMBOSSN);
228                         
229                         but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
230                         uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
231                         
232                         uiBlockSetEmboss(block, UI_EMBOSS);
233                 }
234                 
235                 /* draw backdrop */
236                 if (active) uiBlockSetCol(block, TH_BUT_ACTION);
237                         uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); 
238                 if (active) uiBlockSetCol(block, TH_AUTO);
239                 
240                 /* draw settings */
241                 {
242                         /* color */
243                         uiBlockBeginAlign(block);
244                                 uiDefButF(block, COL, B_REDR, "",               *xco, *yco-26, 150, 19, gpl->color, 0, 0, 0, 0, "Color to use for all strokes on this Grease Pencil Layer");
245                                 uiDefButF(block, NUMSLI, B_REDR, "Opacity: ",           *xco,*yco-45,150,19, &gpl->color[3], 0.3f, 1.0f, 0, 0, "Visibility of stroke (0.3 to 1.0)");
246                         uiBlockEndAlign(block);
247                         
248                         /* stroke thickness */
249                         uiDefButS(block, NUMSLI, B_REDR, "Thickness:",  *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
250                         
251                         /* debugging options */
252                         if (G.f & G_DEBUG) {
253                                 uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
254                         }
255                         
256                         /* onion-skinning */
257                         uiBlockBeginAlign(block);
258                                 uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
259                                 uiDefButS(block, NUMSLI, B_REDR, "GStep:",      *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
260                         uiBlockEndAlign(block);
261                         
262                         /* options */
263                         uiBlockBeginAlign(block);
264                                 if (curarea->spacetype == SPACE_VIEW3D) {
265                                         but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)");
266                                         uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl);
267                                 }
268                                 else {
269                                         but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
270                                         uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
271                                 }
272                                 
273                                 but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
274                                 uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
275                         uiBlockEndAlign(block);
276                 }
277         }
278         
279         /* adjust height for new to start */
280         (*yco) -= (height + 27); 
281
282 #endif
283 /* Draw the contents for a grease-pencil panel. This assumes several things:
284  *      - that panel has been created, is 318 x 204. max yco is 225
285  *      - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
286  *              which is basically the top left-hand corner
287  * It will return the amount of extra space to extend the panel by
288  */
289 short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
290 {
291 #if 0
292         uiBut *but;
293         bGPDlayer *gpl;
294         short xco= 10, yco= 170;
295         
296         /* draw gpd settings first */
297         {
298                 /* add new layer buttons */
299                 but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
300                 uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
301                 
302                 
303                 /* show override lmb-clicks button + painting lock */
304                 uiBlockBeginAlign(block);
305                         if ((gpd->flag & GP_DATA_EDITPAINT)==0) {
306                                 uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
307                                 
308                                 uiBlockSetCol(block, TH_BUT_SETTING);
309                                         uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED,       300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)");
310                                 uiBlockSetCol(block, TH_AUTO);
311                         }
312                         else
313                                 uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
314                 uiBlockEndAlign(block);
315                 
316                 /* 'view align' button (naming depends on context) */
317                 if (sa->spacetype == SPACE_VIEW3D)
318                         uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
319                 else
320                         uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
321         }
322         
323         /* draw for each layer */
324         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
325                 gp_drawui_layer(block, gpd, gpl, &xco, &yco);
326         }
327         
328         /* return new height if necessary */
329         return (yco < 0) ? (204 - yco) : 204;
330 #endif
331         return 0;
332 }       
333
334 /* ************************************************** */