WM: refactor gestures for use as tools
[blender.git] / source / blender / windowmanager / intern / wm_operator_props.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) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  */
23
24 /** \file blender/windowmanager/intern/wm_operator_props.c
25  *  \ingroup wm
26  *
27  * Generic re-usable property definitions and accessors for operators to share.
28  * (`WM_operator_properties_*` functions).
29  */
30
31 #include "DNA_space_types.h"
32
33 #include "BLI_rect.h"
34 #include "BLI_math_base.h"
35
36 #include "UI_resources.h"
37
38 #include "RNA_access.h"
39 #include "RNA_define.h"
40 #include "RNA_enum_types.h"
41
42 #include "WM_api.h"
43 #include "WM_types.h"
44
45 /* default properties for fileselect */
46 void WM_operator_properties_filesel(
47         wmOperatorType *ot, int filter, short type, short action,
48         short flag, short display, short sort)
49 {
50         PropertyRNA *prop;
51
52         static EnumPropertyItem file_display_items[] = {
53                 {FILE_DEFAULTDISPLAY, "DEFAULT", 0, "Default", "Automatically determine display type for files"},
54                 {FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
55                 {FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
56                 {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
57                 {0, NULL, 0, NULL, NULL}
58         };
59
60         if (flag & WM_FILESEL_FILEPATH)
61                 RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file");
62
63         if (flag & WM_FILESEL_DIRECTORY)
64                 RNA_def_string_dir_path(ot->srna, "directory", NULL, FILE_MAX, "Directory", "Directory of the file");
65
66         if (flag & WM_FILESEL_FILENAME)
67                 RNA_def_string_file_name(ot->srna, "filename", NULL, FILE_MAX, "File Name", "Name of the file");
68
69         if (flag & WM_FILESEL_FILES)
70                 RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
71
72         if (action == FILE_SAVE) {
73                 /* note, this is only used to check if we should highlight the filename area red when the
74                  * filepath is an existing file. */
75                 prop = RNA_def_boolean(ot->srna, "check_existing", true, "Check Existing",
76                                        "Check and warn on overwriting existing files");
77                 RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
78         }
79
80         prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", "");
81         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
82         prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & FILE_TYPE_BLENDER_BACKUP) != 0, "Filter .blend files", "");
83         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
84         prop = RNA_def_boolean(ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", "");
85         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
86         prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", "");
87         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
88         prop = RNA_def_boolean(ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", "");
89         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
90         prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", "");
91         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
92         prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", "");
93         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
94         prop = RNA_def_boolean(ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", "");
95         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
96         prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", "");
97         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
98         prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", "");
99         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
100         prop = RNA_def_boolean(ot->srna, "filter_alembic", (filter & FILE_TYPE_ALEMBIC) != 0, "Filter Alembic files", "");
101         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
102         prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", "");
103         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
104         prop = RNA_def_boolean(ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", "");
105         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
106
107         prop = RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL,
108                            "File Browser Mode", "The setting for the file browser mode to load a .blend file, a library or a special file",
109                            FILE_LOADLIB, FILE_SPECIAL);
110         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
111
112         if (flag & WM_FILESEL_RELPATH)
113                 RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
114
115         if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) {
116                 prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", "");
117                 RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
118                 prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", "");
119                 RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
120         }
121
122         prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", "");
123         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
124
125         prop = RNA_def_enum(ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", "");
126         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
127
128 }
129
130 static void wm_operator_properties_select_action_ex(wmOperatorType *ot, int default_action,
131                                                     const EnumPropertyItem *select_actions)
132 {
133         RNA_def_enum(ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute");
134 }
135
136 void WM_operator_properties_select_action(wmOperatorType *ot, int default_action)
137 {
138         static EnumPropertyItem select_actions[] = {
139                 {SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"},
140                 {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"},
141                 {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"},
142                 {SEL_INVERT, "INVERT", 0, "Invert", "Invert selection of all elements"},
143                 {0, NULL, 0, NULL, NULL}
144         };
145
146         wm_operator_properties_select_action_ex(ot, default_action, select_actions);
147 }
148
149 /**
150  * only SELECT/DESELECT
151  */
152 void WM_operator_properties_select_action_simple(wmOperatorType *ot, int default_action)
153 {
154         static EnumPropertyItem select_actions[] = {
155                 {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"},
156                 {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"},
157                 {0, NULL, 0, NULL, NULL}
158         };
159
160         wm_operator_properties_select_action_ex(ot, default_action, select_actions);
161 }
162
163 /**
164  * Use for all select random operators.
165  * Adds properties: percent, seed, action.
166  */
167 void WM_operator_properties_select_random(wmOperatorType *ot)
168 {
169         RNA_def_float_percentage(
170                 ot->srna, "percent", 50.f, 0.0f, 100.0f,
171                 "Percent", "Percentage of objects to select randomly", 0.f, 100.0f);
172         RNA_def_int(
173                 ot->srna, "seed", 0, 0, INT_MAX,
174                 "Random Seed", "Seed for the random number generator", 0, 255);
175
176         WM_operator_properties_select_action_simple(ot, SEL_SELECT);
177 }
178
179 int WM_operator_properties_select_random_seed_increment_get(wmOperator *op)
180 {
181         PropertyRNA *prop = RNA_struct_find_property(op->ptr, "seed");
182         int value = RNA_property_int_get(op->ptr, prop);
183
184         if (op->flag & OP_IS_INVOKE) {
185                 if (!RNA_property_is_set(op->ptr, prop)) {
186                         value += 1;
187                         RNA_property_int_set(op->ptr, prop, value);
188                 }
189         }
190         return value;
191 }
192
193 void WM_operator_properties_select_all(wmOperatorType *ot)
194 {
195         WM_operator_properties_select_action(ot, SEL_TOGGLE);
196 }
197
198 void WM_operator_properties_border(wmOperatorType *ot)
199 {
200         PropertyRNA *prop;
201
202         prop = RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
203         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
204         prop = RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
205         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
206         prop = RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
207         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
208         prop = RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
209         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
210 }
211
212 void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
213 {
214         rect->xmin = RNA_int_get(op->ptr, "xmin");
215         rect->ymin = RNA_int_get(op->ptr, "ymin");
216         rect->xmax = RNA_int_get(op->ptr, "xmax");
217         rect->ymax = RNA_int_get(op->ptr, "ymax");
218 }
219
220 void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect)
221 {
222         rcti rect_i;
223         WM_operator_properties_border_to_rcti(op, &rect_i);
224         BLI_rctf_rcti_copy(rect, &rect_i);
225 }
226
227 /**
228  * Use with #WM_gesture_border_invoke
229  */
230 void WM_operator_properties_gesture_border_ex(wmOperatorType *ot, bool deselect, bool extend)
231 {
232         WM_operator_properties_border(ot);
233
234         if (deselect) {
235                 RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
236         }
237         if (extend) {
238                 RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
239         }
240 }
241
242 void WM_operator_properties_gesture_border_select(wmOperatorType *ot)
243 {
244         WM_operator_properties_gesture_border_ex(ot, true, true);
245 }
246 void WM_operator_properties_gesture_border(wmOperatorType *ot)
247 {
248         WM_operator_properties_gesture_border_ex(ot, false, false);
249 }
250
251 void WM_operator_properties_gesture_border_zoom(wmOperatorType *ot)
252 {
253         WM_operator_properties_border(ot);
254
255         PropertyRNA *prop;
256         prop = RNA_def_boolean(ot->srna, "zoom_out", false, "Zoom Out", "");
257         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
258 }
259
260 /**
261  * Use with #WM_gesture_lasso_invoke
262  */
263 void WM_operator_properties_gesture_lasso_ex(wmOperatorType *ot, bool deselect, bool extend)
264 {
265         PropertyRNA *prop;
266         prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
267         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
268
269         if (deselect) {
270                 RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
271         }
272         if (extend) {
273                 RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
274         }
275 }
276
277 void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
278 {
279         WM_operator_properties_gesture_lasso_ex(ot, false, false);
280 }
281
282 void WM_operator_properties_gesture_lasso_select(wmOperatorType *ot)
283 {
284         WM_operator_properties_gesture_lasso_ex(ot, true, true);
285 }
286
287 /**
288  * Use with #WM_gesture_straightline_invoke
289  */
290 void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
291 {
292         PropertyRNA *prop;
293
294         prop = RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX);
295         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
296         prop = RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX);
297         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
298         prop = RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX);
299         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
300         prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX);
301         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
302
303         if (cursor) {
304                 prop = RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX,
305                                    "Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX);
306                 RNA_def_property_flag(prop, PROP_HIDDEN);
307         }
308 }
309
310 /**
311  * Use with #WM_gesture_circle_invoke
312  */
313 void WM_operator_properties_gesture_circle_ex(wmOperatorType *ot, bool deselect)
314 {
315         PropertyRNA *prop;
316         const int radius_default = 25;
317
318         prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
319         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
320         prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
321         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
322         RNA_def_int(ot->srna, "radius", radius_default, 1, INT_MAX, "Radius", "", 1, INT_MAX);
323
324         if (deselect) {
325                 RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
326         }
327 }
328
329 void WM_operator_properties_gesture_circle(wmOperatorType *ot)
330 {
331         WM_operator_properties_gesture_circle_ex(ot, false);
332 }
333
334 void WM_operator_properties_gesture_circle_select(wmOperatorType *ot)
335 {
336         WM_operator_properties_gesture_circle_ex(ot, true);
337 }
338
339 void WM_operator_properties_mouse_select(wmOperatorType *ot)
340 {
341         PropertyRNA *prop;
342
343         prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
344                                "Extend selection instead of deselecting everything first");
345         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
346         prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection");
347         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
348         prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection");
349         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
350 }
351
352 /**
353  * \param nth_can_disable: Enable if we want to be able to select no interval at all.
354  */
355 void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_disable)
356 {
357         const int nth_default = nth_can_disable ? 1 : 2;
358         const int nth_min =  min_ii(nth_default, 2);
359         RNA_def_int(ot->srna, "nth", nth_default, nth_min, INT_MAX, "Nth Selection", "", nth_min, 100);
360         RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
361         RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
362 }
363
364 void WM_operator_properties_checker_interval_from_op(
365         struct wmOperator *op, struct CheckerIntervalParams *op_params)
366 {
367         const int nth = RNA_int_get(op->ptr, "nth") - 1;
368         const int skip = RNA_int_get(op->ptr, "skip");
369         int offset = RNA_int_get(op->ptr, "offset");
370
371         op_params->nth = nth;
372         op_params->skip = skip;
373         op_params->offset = mod_i(offset, nth + skip);  /* so input of offset zero ends up being (nth - 1) */
374 }
375
376 bool WM_operator_properties_checker_interval_test(
377         const struct CheckerIntervalParams *op_params, int depth)
378 {
379         return ((op_params->nth == 0) ||
380                 ((op_params->offset + depth) % (op_params->skip + op_params->nth) >= op_params->skip));
381 }