GPencil: Added operators to select first and last points of strokes
[blender-staging.git] / source / blender / editors / gpencil / gpencil_ops.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) 2009, 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_ops.c
27  *  \ingroup edgpencil
28  */
29
30
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <stdio.h>
34
35 #include "BLI_sys_types.h"
36
37 #include "BKE_context.h"
38
39 #include "DNA_gpencil_types.h"
40
41 #include "WM_api.h"
42 #include "WM_types.h"
43
44 #include "RNA_access.h"
45
46 #include "ED_gpencil.h"
47 #include "ED_object.h"
48 #include "ED_transform.h"
49
50 #include "gpencil_intern.h"
51
52 /* ****************************************** */
53 /* Grease Pencil Keymaps */
54
55 /* Generic Drawing Keymap */
56 static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
57 {
58         wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0);
59         wmKeyMapItem *kmi;
60         
61         /* Draw  --------------------------------------- */
62         /* draw */
63         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY);
64         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
65         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
66         
67         /* draw - straight lines */
68         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY);
69         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
70         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
71         
72         /* draw - poly lines */
73         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY);
74         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
75         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
76         
77         /* erase */
78         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
79         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
80         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
81         
82         
83         /* Tablet Mappings for Drawing ------------------ */
84         /* For now, only support direct drawing using the eraser, as most users using a tablet
85          * may still want to use that as their primary pointing device!
86          */
87 #if 0
88         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_STYLUS, KM_PRESS, 0, 0);
89         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW);
90         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
91 #endif
92         
93         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0);
94         RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
95         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
96         
97         /* Viewport Tools ------------------------------- */
98         
99         /* Enter EditMode */
100         WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, DKEY);
101         
102         /* Pie Menu - For standard tools */
103         WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_tool_palette", QKEY, KM_PRESS, 0, DKEY);
104         WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_settings_palette", WKEY, KM_PRESS, 0, DKEY);
105 }
106
107 /* ==================== */
108
109 /* Poll callback for stroke editing mode */
110 static int gp_stroke_editmode_poll(bContext *C)
111 {
112         bGPdata *gpd = CTX_data_gpencil_data(C);
113         return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
114 }
115
116 /* Stroke Editing Keymap - Only when editmode is enabled */
117 static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
118 {
119         wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
120         wmKeyMapItem *kmi;
121         
122         /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
123         keymap->poll = gp_stroke_editmode_poll;
124         
125         /* ----------------------------------------------- */
126         
127         /* Exit EditMode */
128         WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0);
129         
130         /* Pie Menu - For settings/tools easy access */
131         WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_sculpt", EKEY, KM_PRESS, 0, DKEY);
132         
133         /* Brush Settings */
134         /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys
135          *       in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain
136          *       that the only data being edited is that of the Grease Pencil strokes
137          */
138         
139         /* FKEY = Eraser Radius */
140         kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
141         RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius");
142         
143         /* Selection ------------------------------------- */
144         /* select all */
145         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0);
146         RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
147         
148         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
149         RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
150         
151         /* circle select */
152         WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, 0);
153         
154         /* border select */
155         WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0);
156         
157         /* lasso select */
158         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
159         RNA_boolean_set(kmi->ptr, "deselect", false);
160         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0);
161         RNA_boolean_set(kmi->ptr, "deselect", true);
162         
163         /* In the Node Editor, lasso select needs ALT modifier too (as somehow CTRL+LMB drag gets taken for "cut" quite early)
164          * There probably isn't too much harm adding this for other editors too as part of standard GP editing keymap. This hotkey
165          * combo doesn't seem to see much use under standard scenarios?
166          */
167         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
168         RNA_boolean_set(kmi->ptr, "deselect", false);
169         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL | KM_ALT, 0);
170         RNA_boolean_set(kmi->ptr, "deselect", true);
171         
172         /* normal select */
173         WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
174         
175         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
176         RNA_boolean_set(kmi->ptr, "extend", true);
177         RNA_boolean_set(kmi->ptr, "toggle", true);
178         
179         /* whole stroke select */
180         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
181         RNA_boolean_set(kmi->ptr, "entire_strokes", true);
182         
183         /* select linked */
184         /* NOTE: While LKEY is redundant, not having it breaks the mode illusion too much */
185         WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, 0, 0);
186         WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
187         
188         /* select grouped */
189         WM_keymap_add_item(keymap, "GPENCIL_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
190                 
191         /* select more/less */
192         WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
193         WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
194         
195         /* Editing ----------------------------------------- */
196         
197         /* duplicate and move selected points */
198         WM_keymap_add_item(keymap, "GPENCIL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
199         
200         /* delete */
201         WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", XKEY, KM_PRESS, 0, 0);
202         WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", DELKEY, KM_PRESS, 0, 0);
203
204         WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
205         WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", DELKEY, KM_PRESS, KM_CTRL, 0);
206         
207         /* copy + paste */
208         WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
209         WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
210         
211 #ifdef __APPLE__
212         WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
213         WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
214 #endif
215
216         /* snap */
217         WM_keymap_add_menu(keymap, "GPENCIL_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
218         
219         
220         /* convert to geometry */
221         WM_keymap_add_item(keymap, "GPENCIL_OT_convert", CKEY, KM_PRESS, KM_ALT, 0);
222         
223         
224         /* Show/Hide */
225         /* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */
226         WM_keymap_add_item(keymap, "GPENCIL_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
227         
228         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 0, 0);
229         RNA_boolean_set(kmi->ptr, "unselected", false);
230         
231         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
232         RNA_boolean_set(kmi->ptr, "unselected", true);
233         
234         /* Isolate Layer */
235         WM_keymap_add_item(keymap, "GPENCIL_OT_layer_isolate", PADASTERKEY, KM_PRESS, 0, 0);
236         
237         /* Move to Layer */
238         WM_keymap_add_item(keymap, "GPENCIL_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
239         
240         
241         
242         /* Brush-Based Editing:
243          *   EKEY + LMB                          = Single stroke, draw immediately 
244          *        + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc.
245          *
246          * For the modal version, use D+E -> Sculpt
247          */
248         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, EKEY);
249         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
250         
251         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, EKEY);
252         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
253         /*RNA_boolean_set(kmi->ptr, "use_invert", true);*/
254         
255         kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, EKEY);
256         RNA_boolean_set(kmi->ptr, "wait_for_input", false);
257         /*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/
258         
259         
260         /* Shift-FKEY = Sculpt Strength */
261         kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
262         RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.strength");
263         
264         /* Ctrl-FKEY = Sculpt Brush Size */
265         kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
266         RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.size");
267         
268         
269         
270         
271         /* Transform Tools */
272         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
273         
274         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
275         
276         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
277         
278         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
279         
280         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
281         
282         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0);
283         
284         WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
285         
286         WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
287         
288         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0);
289         RNA_enum_set(kmi->ptr, "mode", TFM_GPENCIL_SHRINKFATTEN);
290         
291         /* Proportional Editing */
292         ED_keymap_proportional_cycle(keyconf, keymap);
293         ED_keymap_proportional_editmode(keyconf, keymap, true);
294 }
295
296 /* ==================== */
297
298 void ED_keymap_gpencil(wmKeyConfig *keyconf)
299 {
300         ed_keymap_gpencil_general(keyconf);
301         ed_keymap_gpencil_editing(keyconf);
302 }
303
304 /* ****************************************** */
305
306 void ED_operatortypes_gpencil(void)
307 {
308         /* Drawing ----------------------- */
309         
310         WM_operatortype_append(GPENCIL_OT_draw);
311         
312         /* Editing (Strokes) ------------ */
313         
314         WM_operatortype_append(GPENCIL_OT_editmode_toggle);
315         
316         WM_operatortype_append(GPENCIL_OT_select);
317         WM_operatortype_append(GPENCIL_OT_select_all);
318         WM_operatortype_append(GPENCIL_OT_select_circle);
319         WM_operatortype_append(GPENCIL_OT_select_border);
320         WM_operatortype_append(GPENCIL_OT_select_lasso);
321         
322         WM_operatortype_append(GPENCIL_OT_select_linked);
323         WM_operatortype_append(GPENCIL_OT_select_grouped);
324         WM_operatortype_append(GPENCIL_OT_select_more);
325         WM_operatortype_append(GPENCIL_OT_select_less);
326         WM_operatortype_append(GPENCIL_OT_select_first);
327         WM_operatortype_append(GPENCIL_OT_select_last);
328         
329         WM_operatortype_append(GPENCIL_OT_duplicate);
330         WM_operatortype_append(GPENCIL_OT_delete);
331         WM_operatortype_append(GPENCIL_OT_dissolve);
332         WM_operatortype_append(GPENCIL_OT_copy);
333         WM_operatortype_append(GPENCIL_OT_paste);
334         
335         WM_operatortype_append(GPENCIL_OT_move_to_layer);
336         WM_operatortype_append(GPENCIL_OT_layer_change);
337         
338         WM_operatortype_append(GPENCIL_OT_snap_to_grid);
339         WM_operatortype_append(GPENCIL_OT_snap_to_cursor);
340         WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected);
341         
342         WM_operatortype_append(GPENCIL_OT_brush_paint);
343         
344         /* Editing (Buttons) ------------ */
345         
346         WM_operatortype_append(GPENCIL_OT_data_add);
347         WM_operatortype_append(GPENCIL_OT_data_unlink);
348         
349         WM_operatortype_append(GPENCIL_OT_layer_add);
350         WM_operatortype_append(GPENCIL_OT_layer_remove);
351         WM_operatortype_append(GPENCIL_OT_layer_move);
352         WM_operatortype_append(GPENCIL_OT_layer_duplicate);
353         
354         WM_operatortype_append(GPENCIL_OT_hide);
355         WM_operatortype_append(GPENCIL_OT_reveal);
356         WM_operatortype_append(GPENCIL_OT_lock_all);
357         WM_operatortype_append(GPENCIL_OT_unlock_all);
358         WM_operatortype_append(GPENCIL_OT_layer_isolate);
359         
360         WM_operatortype_append(GPENCIL_OT_active_frame_delete);
361         
362         WM_operatortype_append(GPENCIL_OT_convert);
363
364         /* Editing (Time) --------------- */
365 }
366
367 void ED_operatormacros_gpencil(void)
368 {
369         wmOperatorType *ot;
370         wmOperatorTypeMacro *otmacro;
371         
372         /* Duplicate + Move = Interactively place newly duplicated strokes */
373         ot = WM_operatortype_append_macro("GPENCIL_OT_duplicate_move", "Duplicate Strokes",
374                                           "Make copies of the selected Grease Pencil strokes and move them",
375                                           OPTYPE_UNDO | OPTYPE_REGISTER);
376         WM_operatortype_macro_define(ot, "GPENCIL_OT_duplicate");
377         otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
378         RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
379
380 }
381
382 /* ****************************************** */