Implement asymmetric and free handles type for masks
[blender.git] / source / blender / editors / mask / mask_edit.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) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/mask/mask_edit.c
29  *  \ingroup edmask
30  */
31
32
33 #include "BLI_math.h"
34
35 #include "BKE_context.h"
36 #include "BKE_mask.h"
37
38 #include "DNA_scene_types.h"
39
40 #include "WM_api.h"
41 #include "WM_types.h"
42
43 #include "ED_screen.h"
44 #include "ED_mask.h"  /* own include */
45 #include "ED_image.h"
46 #include "ED_object.h" /* ED_keymap_proportional_maskmode only */
47 #include "ED_clip.h"
48 #include "ED_sequencer.h"
49 #include "ED_transform.h"
50
51 #include "UI_view2d.h"
52
53 #include "RNA_access.h"
54
55 #include "mask_intern.h"  /* own include */
56
57 /********************** generic poll functions *********************/
58
59 int ED_maskedit_poll(bContext *C)
60 {
61         ScrArea *sa = CTX_wm_area(C);
62         if (sa) {
63                 switch (sa->spacetype) {
64                         case SPACE_CLIP:
65                                 return ED_space_clip_maskedit_poll(C);
66                         case SPACE_SEQ:
67                                 return ED_space_sequencer_maskedit_poll(C);
68                         case SPACE_IMAGE:
69                                 return ED_space_image_maskedit_poll(C);
70                 }
71         }
72         return FALSE;
73 }
74
75 int ED_maskedit_mask_poll(bContext *C)
76 {
77         ScrArea *sa = CTX_wm_area(C);
78         if (sa) {
79                 switch (sa->spacetype) {
80                         case SPACE_CLIP:
81                                 return ED_space_clip_maskedit_mask_poll(C);
82                         case SPACE_SEQ:
83                                 return ED_space_sequencer_maskedit_mask_poll(C);
84                         case SPACE_IMAGE:
85                                 return ED_space_image_maskedit_mask_poll(C);
86                 }
87         }
88         return FALSE;
89 }
90
91 /********************** registration *********************/
92
93 /* takes event->mval */
94 void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, const int mval[2], float co[2])
95 {
96         if (sa) {
97                 switch (sa->spacetype) {
98                         case SPACE_CLIP:
99                         {
100                                 SpaceClip *sc = sa->spacedata.first;
101                                 ED_clip_mouse_pos(sc, ar, mval, co);
102                                 BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
103                                 break;
104                         }
105                         case SPACE_SEQ:
106                         {
107                                 UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &co[0], &co[1]);
108                                 break;
109                         }
110                         case SPACE_IMAGE:
111                         {
112                                 SpaceImage *sima = sa->spacedata.first;
113                                 ED_image_mouse_pos(sima, ar, mval, co);
114                                 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
115                                 break;
116                         }
117                         default:
118                                 /* possible other spaces from which mask editing is available */
119                                 BLI_assert(0);
120                                 zero_v2(co);
121                                 break;
122                 }
123         }
124         else {
125                 BLI_assert(0);
126                 zero_v2(co);
127         }
128 }
129
130 /* input:  x/y   - mval space
131  * output: xr/yr - mask point space */
132 void ED_mask_point_pos(ScrArea *sa, ARegion *ar, float x, float y, float *xr, float *yr)
133 {
134         float co[2];
135
136         if (sa) {
137                 switch (sa->spacetype) {
138                         case SPACE_CLIP:
139                         {
140                                 SpaceClip *sc = sa->spacedata.first;
141                                 ED_clip_point_stable_pos(sc, ar, x, y, &co[0], &co[1]);
142                                 BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
143                                 break;
144                         }
145                         case SPACE_SEQ:
146                                 zero_v2(co); /* MASKTODO */
147                                 break;
148                         case SPACE_IMAGE:
149                         {
150                                 SpaceImage *sima = sa->spacedata.first;
151                                 ED_image_point_pos(sima, ar, x, y, &co[0], &co[1]);
152                                 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
153                                 break;
154                         }
155                         default:
156                                 /* possible other spaces from which mask editing is available */
157                                 BLI_assert(0);
158                                 zero_v2(co);
159                                 break;
160                 }
161         }
162         else {
163                 BLI_assert(0);
164                 zero_v2(co);
165         }
166
167         *xr = co[0];
168         *yr = co[1];
169 }
170
171 void ED_mask_point_pos__reverse(ScrArea *sa, ARegion *ar, float x, float y, float *xr, float *yr)
172 {
173         float co[2];
174
175         if (sa) {
176                 switch (sa->spacetype) {
177                         case SPACE_CLIP:
178                         {
179                                 SpaceClip *sc = sa->spacedata.first;
180                                 co[0] = x;
181                                 co[1] = y;
182                                 BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co);
183                                 ED_clip_point_stable_pos__reverse(sc, ar, co, co);
184                                 break;
185                         }
186                         case SPACE_SEQ:
187                                 zero_v2(co); /* MASKTODO */
188                                 break;
189                         case SPACE_IMAGE:
190                         {
191                                 SpaceImage *sima = sa->spacedata.first;
192                                 co[0] = x;
193                                 co[1] = y;
194                                 BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co);
195                                 ED_image_point_pos__reverse(sima, ar, co, co);
196                                 break;
197                         }
198                         default:
199                                 /* possible other spaces from which mask editing is available */
200                                 BLI_assert(0);
201                                 zero_v2(co);
202                                 break;
203                 }
204         }
205         else {
206                 BLI_assert(0);
207                 zero_v2(co);
208         }
209
210         *xr = co[0];
211         *yr = co[1];
212 }
213
214 void ED_mask_get_size(ScrArea *sa, int *width, int *height)
215 {
216         if (sa && sa->spacedata.first) {
217                 switch (sa->spacetype) {
218                         case SPACE_CLIP:
219                         {
220                                 SpaceClip *sc = sa->spacedata.first;
221                                 ED_space_clip_get_size(sc, width, height);
222                                 break;
223                         }
224                         case SPACE_SEQ:
225                         {
226 //                              Scene *scene = CTX_data_scene(C);
227 //                              *width = (scene->r.size * scene->r.xsch) / 100;
228 //                              *height = (scene->r.size * scene->r.ysch) / 100;
229                                 break;
230                         }
231                         case SPACE_IMAGE:
232                         {
233                                 SpaceImage *sima = sa->spacedata.first;
234                                 ED_space_image_get_size(sima, width, height);
235                                 break;
236                         }
237                         default:
238                                 /* possible other spaces from which mask editing is available */
239                                 BLI_assert(0);
240                                 *width = 0;
241                                 *height = 0;
242                                 break;
243                 }
244         }
245         else {
246                 BLI_assert(0);
247                 *width = 0;
248                 *height = 0;
249         }
250 }
251
252 void ED_mask_zoom(ScrArea *sa, ARegion *ar, float *zoomx, float *zoomy)
253 {
254         if (sa && sa->spacedata.first) {
255                 switch (sa->spacetype) {
256                         case SPACE_CLIP:
257                         {
258                                 SpaceClip *sc = sa->spacedata.first;
259                                 ED_space_clip_get_zoom(sc, ar, zoomx, zoomy);
260                                 break;
261                         }
262                         case SPACE_SEQ:
263                         {
264                                 *zoomx = *zoomy = 1.0f;
265                                 break;
266                         }
267                         case SPACE_IMAGE:
268                         {
269                                 SpaceImage *sima = sa->spacedata.first;
270                                 ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
271                                 break;
272                         }
273                         default:
274                                 /* possible other spaces from which mask editing is available */
275                                 BLI_assert(0);
276                                 *zoomx = *zoomy = 1.0f;
277                                 break;
278                 }
279         }
280         else {
281                 BLI_assert(0);
282                 *zoomx = *zoomy = 1.0f;
283         }
284 }
285
286 void ED_mask_get_aspect(ScrArea *sa, ARegion *UNUSED(ar), float *aspx, float *aspy)
287 {
288         if (sa && sa->spacedata.first) {
289                 switch (sa->spacetype) {
290                         case SPACE_CLIP:
291                         {
292                                 SpaceClip *sc = sa->spacedata.first;
293                                 ED_space_clip_get_aspect(sc, aspx, aspy);
294                                 break;
295                         }
296                         case SPACE_SEQ:
297                         {
298                                 *aspx = *aspy = 1.0f;  /* MASKTODO - render aspect? */
299                                 break;
300                         }
301                         case SPACE_IMAGE:
302                         {
303                                 SpaceImage *sima = sa->spacedata.first;
304                                 ED_space_image_get_aspect(sima, aspx, aspy);
305                                 break;
306                         }
307                         default:
308                                 /* possible other spaces from which mask editing is available */
309                                 BLI_assert(0);
310                                 *aspx = *aspy = 1.0f;
311                                 break;
312                 }
313         }
314         else {
315                 BLI_assert(0);
316                 *aspx = *aspy = 1.0f;
317         }
318 }
319
320 void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *scaley)
321 {
322         if (sa && sa->spacedata.first) {
323                 switch (sa->spacetype) {
324                         case SPACE_CLIP:
325                         {
326                                 SpaceClip *sc = sa->spacedata.first;
327                                 float aspx, aspy;
328
329                                 UI_view2d_getscale(&ar->v2d, scalex, scaley);
330                                 ED_space_clip_get_aspect(sc, &aspx, &aspy);
331
332                                 *scalex *= aspx;
333                                 *scaley *= aspy;
334                                 break;
335                         }
336                         case SPACE_SEQ:
337                         {
338                                 *scalex = *scaley = 1.0f;  /* MASKTODO? */
339                                 break;
340                         }
341                         case SPACE_IMAGE:
342                         {
343                                 SpaceImage *sima = sa->spacedata.first;
344                                 float aspx, aspy;
345
346                                 UI_view2d_getscale(&ar->v2d, scalex, scaley);
347                                 ED_space_image_get_aspect(sima, &aspx, &aspy);
348
349                                 *scalex *= aspx;
350                                 *scaley *= aspy;
351                                 break;
352                         }
353                         default:
354                                 /* possible other spaces from which mask editing is available */
355                                 BLI_assert(0);
356                                 *scalex = *scaley = 1.0f;
357                                 break;
358                 }
359         }
360         else {
361                 BLI_assert(0);
362                 *scalex = *scaley = 1.0f;
363         }
364 }
365
366 void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2])
367 {
368         if (sa) {
369                 switch (sa->spacetype) {
370                         case SPACE_CLIP:
371                         {
372                                 SpaceClip *space_clip = sa->spacedata.first;
373                                 copy_v2_v2(cursor, space_clip->cursor);
374                                 break;
375                         }
376                         case SPACE_SEQ:
377                         {
378                                 zero_v2(cursor);
379                                 break;
380                         }
381                         case SPACE_IMAGE:
382                         {
383                                 SpaceImage *space_image = sa->spacedata.first;
384                                 copy_v2_v2(cursor, space_image->cursor);
385                                 break;
386                         }
387                         default:
388                                 /* possible other spaces from which mask editing is available */
389                                 BLI_assert(0);
390                                 zero_v2(cursor);
391                                 break;
392                 }
393         }
394         else {
395                 BLI_assert(0);
396                 zero_v2(cursor);
397         }
398 }
399
400 /********************** registration *********************/
401
402 void ED_operatortypes_mask(void)
403 {
404         WM_operatortype_append(MASK_OT_new);
405
406         /* mask layers */
407         WM_operatortype_append(MASK_OT_layer_new);
408         WM_operatortype_append(MASK_OT_layer_remove);
409
410         /* add */
411         WM_operatortype_append(MASK_OT_add_vertex);
412         WM_operatortype_append(MASK_OT_add_feather_vertex);
413         WM_operatortype_append(MASK_OT_primitive_circle_add);
414         WM_operatortype_append(MASK_OT_primitive_square_add);
415
416         /* geometry */
417         WM_operatortype_append(MASK_OT_switch_direction);
418         WM_operatortype_append(MASK_OT_normals_make_consistent);
419         WM_operatortype_append(MASK_OT_delete);
420
421         /* select */
422         WM_operatortype_append(MASK_OT_select);
423         WM_operatortype_append(MASK_OT_select_all);
424         WM_operatortype_append(MASK_OT_select_border);
425         WM_operatortype_append(MASK_OT_select_lasso);
426         WM_operatortype_append(MASK_OT_select_circle);
427         WM_operatortype_append(MASK_OT_select_linked_pick);
428         WM_operatortype_append(MASK_OT_select_linked);
429         WM_operatortype_append(MASK_OT_select_more);
430         WM_operatortype_append(MASK_OT_select_less);
431
432         /* hide/reveal */
433         WM_operatortype_append(MASK_OT_hide_view_clear);
434         WM_operatortype_append(MASK_OT_hide_view_set);
435
436         /* feather */
437         WM_operatortype_append(MASK_OT_feather_weight_clear);
438
439         /* shape */
440         WM_operatortype_append(MASK_OT_slide_point);
441         WM_operatortype_append(MASK_OT_cyclic_toggle);
442         WM_operatortype_append(MASK_OT_handle_type_set);
443
444         /* relationships */
445         WM_operatortype_append(MASK_OT_parent_set);
446         WM_operatortype_append(MASK_OT_parent_clear);
447
448         /* shapekeys */
449         WM_operatortype_append(MASK_OT_shape_key_insert);
450         WM_operatortype_append(MASK_OT_shape_key_clear);
451         WM_operatortype_append(MASK_OT_shape_key_feather_reset);
452         WM_operatortype_append(MASK_OT_shape_key_rekey);
453
454         /* layers */
455         WM_operatortype_append(MASK_OT_layer_move);
456
457         /* duplicate */
458         WM_operatortype_append(MASK_OT_duplicate);
459
460         /* clipboard */
461         WM_operatortype_append(MASK_OT_copy_splines);
462         WM_operatortype_append(MASK_OT_paste_splines);
463 }
464
465 void ED_keymap_mask(wmKeyConfig *keyconf)
466 {
467         wmKeyMap *keymap;
468         wmKeyMapItem *kmi;
469
470         keymap = WM_keymap_find(keyconf, "Mask Editing", 0, 0);
471         keymap->poll = ED_maskedit_poll;
472
473         WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
474
475         /* add menu */
476         WM_keymap_add_menu(keymap, "MASK_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
477
478         /* mask mode supports PET now */
479         ED_keymap_proportional_cycle(keyconf, keymap);
480         ED_keymap_proportional_maskmode(keyconf, keymap);
481
482         /* geometry */
483         WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
484         WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
485         WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0);
486         WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0);
487
488         /* selection */
489         kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
490         RNA_boolean_set(kmi->ptr, "extend", FALSE);
491         RNA_boolean_set(kmi->ptr, "deselect", FALSE);
492         RNA_boolean_set(kmi->ptr, "toggle", FALSE);
493         kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
494         RNA_boolean_set(kmi->ptr, "extend", FALSE);
495         RNA_boolean_set(kmi->ptr, "deselect", FALSE);
496         RNA_boolean_set(kmi->ptr, "toggle", TRUE);
497
498         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", AKEY, KM_PRESS, 0, 0);
499         RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
500         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
501         RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
502
503         WM_keymap_add_item(keymap, "MASK_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
504         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
505         RNA_boolean_set(kmi->ptr, "deselect", FALSE);
506         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0);
507         RNA_boolean_set(kmi->ptr, "deselect", TRUE);
508
509         WM_keymap_add_item(keymap, "MASK_OT_select_border", BKEY, KM_PRESS, 0, 0);
510         WM_keymap_add_item(keymap, "MASK_OT_select_circle", CKEY, KM_PRESS, 0, 0);
511
512         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0);
513         RNA_boolean_set(kmi->ptr, "deselect", FALSE);
514         kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0);
515         RNA_boolean_set(kmi->ptr, "deselect", TRUE);
516
517         WM_keymap_add_item(keymap, "MASK_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
518         WM_keymap_add_item(keymap, "MASK_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
519
520         /* hide/reveal */
521         WM_keymap_add_item(keymap, "MASK_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
522         kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
523         RNA_boolean_set(kmi->ptr, "unselected", FALSE);
524
525         kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
526         RNA_boolean_set(kmi->ptr, "unselected", TRUE);
527
528         /* select clip while in maker view,
529          * this matches View3D functionality where you can select an
530          * object while in editmode to allow vertex parenting */
531         kmi = WM_keymap_add_item(keymap, "CLIP_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
532         RNA_boolean_set(kmi->ptr, "extend", FALSE);
533
534         /* shape */
535         WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0);
536         WM_keymap_add_item(keymap, "MASK_OT_slide_point", ACTIONMOUSE, KM_PRESS, 0, 0);
537         WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0);
538         WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
539         // WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0);
540         /* ... matches curve editmode */
541
542         /* relationships */
543         WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
544         WM_keymap_add_item(keymap, "MASK_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
545
546         WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0);
547         WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0);
548
549         /* duplicate */
550         WM_keymap_add_item(keymap, "MASK_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
551
552         /* for image editor only */
553         WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
554
555         /* Transform (don't use transform_keymap_for_space() since this maps to different spaces) */
556         WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
557         WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
558         WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
559         WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
560         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0);
561         RNA_enum_set(kmi->ptr, "mode", TFM_MASK_SHRINKFATTEN);
562 }
563
564 void ED_operatormacros_mask(void)
565 {
566         wmOperatorType *ot;
567         wmOperatorTypeMacro *otmacro;
568
569         ot = WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide",
570                                           "Add new vertex and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
571         ot->description = "Add new vertex and slide it";
572         WM_operatortype_macro_define(ot, "MASK_OT_add_vertex");
573         otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
574         RNA_boolean_set(otmacro->ptr, "is_new_point", TRUE);
575
576         ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide",
577                                           "Add new vertex to feather and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
578         ot->description = "Add new feather vertex and slide it";
579         WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex");
580         otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
581         RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE);
582
583         ot = WM_operatortype_append_macro("MASK_OT_duplicate_move", "Add Duplicate", "Duplicate mask and move",
584                                           OPTYPE_UNDO | OPTYPE_REGISTER);
585         WM_operatortype_macro_define(ot, "MASK_OT_duplicate");
586         otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
587         RNA_enum_set(otmacro->ptr, "proportional", 0);
588         RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
589 }