Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / transform / transform_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  * Contributor(s): none yet.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/transform/transform_ops.c
24  *  \ingroup edtransform
25  */
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_mesh_types.h"
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32
33 #include "BLI_math.h"
34 #include "BLI_utildefines.h"
35
36 #include "BLT_translation.h"
37
38 #include "BKE_context.h"
39 #include "BKE_global.h"
40 #include "BKE_report.h"
41 #include "BKE_editmesh.h"
42
43 #include "RNA_access.h"
44 #include "RNA_define.h"
45 #include "RNA_enum_types.h"
46
47 #include "WM_api.h"
48 #include "WM_types.h"
49
50 #include "UI_interface.h"
51 #include "UI_resources.h"
52
53 #include "ED_screen.h"
54 /* for USE_LOOPSLIDE_HACK only */
55 #include "ED_mesh.h"
56
57 #include "transform.h"
58
59 typedef struct TransformModeItem {
60         const char *idname;
61         int mode;
62         void (*opfunc)(wmOperatorType *);
63 } TransformModeItem;
64
65 static const float VecOne[3] = {1, 1, 1};
66
67 static const char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
68 static const char OP_ROTATION[] = "TRANSFORM_OT_rotate";
69 static const char OP_TOSPHERE[] = "TRANSFORM_OT_tosphere";
70 static const char OP_RESIZE[] = "TRANSFORM_OT_resize";
71 static const char OP_SKIN_RESIZE[] = "TRANSFORM_OT_skin_resize";
72 static const char OP_SHEAR[] = "TRANSFORM_OT_shear";
73 static const char OP_BEND[] = "TRANSFORM_OT_bend";
74 static const char OP_SHRINK_FATTEN[] = "TRANSFORM_OT_shrink_fatten";
75 static const char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
76 static const char OP_TILT[] = "TRANSFORM_OT_tilt";
77 static const char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
78 static const char OP_MIRROR[] = "TRANSFORM_OT_mirror";
79 static const char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
80 static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
81 static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
82 static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
83 static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
84
85 static void TRANSFORM_OT_translate(struct wmOperatorType *ot);
86 static void TRANSFORM_OT_rotate(struct wmOperatorType *ot);
87 static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot);
88 static void TRANSFORM_OT_resize(struct wmOperatorType *ot);
89 static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot);
90 static void TRANSFORM_OT_shear(struct wmOperatorType *ot);
91 static void TRANSFORM_OT_bend(struct wmOperatorType *ot);
92 static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot);
93 static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot);
94 static void TRANSFORM_OT_tilt(struct wmOperatorType *ot);
95 static void TRANSFORM_OT_trackball(struct wmOperatorType *ot);
96 static void TRANSFORM_OT_mirror(struct wmOperatorType *ot);
97 static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot);
98 static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot);
99 static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot);
100 static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot);
101 static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot);
102
103 static TransformModeItem transform_modes[] =
104 {
105         {OP_TRANSLATION, TFM_TRANSLATION, TRANSFORM_OT_translate},
106         {OP_ROTATION, TFM_ROTATION, TRANSFORM_OT_rotate},
107         {OP_TOSPHERE, TFM_TOSPHERE, TRANSFORM_OT_tosphere},
108         {OP_RESIZE, TFM_RESIZE, TRANSFORM_OT_resize},
109         {OP_SKIN_RESIZE, TFM_SKIN_RESIZE, TRANSFORM_OT_skin_resize},
110         {OP_SHEAR, TFM_SHEAR, TRANSFORM_OT_shear},
111         {OP_BEND, TFM_BEND, TRANSFORM_OT_bend},
112         {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN, TRANSFORM_OT_shrink_fatten},
113         {OP_PUSH_PULL, TFM_PUSHPULL, TRANSFORM_OT_push_pull},
114         {OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
115         {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
116         {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
117         {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide},
118         {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide},
119         {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
120         {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
121         {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
122         {NULL, 0}
123 };
124
125 const EnumPropertyItem rna_enum_transform_mode_types[] =
126 {
127         {TFM_INIT, "INIT", 0, "Init", ""},
128         {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
129         {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
130         {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
131         {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
132         {TFM_SKIN_RESIZE, "SKIN_RESIZE", 0, "Skin Resize", ""},
133         {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
134         {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
135         {TFM_BEND, "BEND", 0, "Bend", ""},
136         {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
137         {TFM_TILT, "TILT", 0, "Tilt", ""},
138         {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
139         {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
140         {TFM_CREASE, "CREASE", 0, "Crease", ""},
141         {TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
142         {TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
143         {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
144         {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
145         {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
146         {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
147         {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
148         {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
149         {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
150         {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
151         {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
152         {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
153         {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
154         {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
155         {TFM_ALIGN, "ALIGN", 0, "Align", ""},
156         {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
157         {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
158         {0, NULL, 0, NULL, NULL}
159 };
160
161 static int select_orientation_exec(bContext *C, wmOperator *op)
162 {
163         Scene *scene = CTX_data_scene(C);
164         int orientation = RNA_enum_get(op->ptr, "orientation");
165
166         BIF_selectTransformOrientationValue(scene, orientation);
167
168         WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
169
170         return OPERATOR_FINISHED;
171 }
172
173 static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
174 {
175         uiPopupMenu *pup;
176         uiLayout *layout;
177
178         pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
179         layout = UI_popup_menu_layout(pup);
180         uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
181         UI_popup_menu_end(C, pup);
182
183         return OPERATOR_INTERFACE;
184 }
185
186 static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
187 {
188         PropertyRNA *prop;
189
190         /* identifiers */
191         ot->name   = "Select Orientation";
192         ot->description = "Select transformation orientation";
193         ot->idname = "TRANSFORM_OT_select_orientation";
194         ot->flag   = OPTYPE_UNDO;
195
196         /* api callbacks */
197         ot->invoke = select_orientation_invoke;
198         ot->exec   = select_orientation_exec;
199         ot->poll   = ED_operator_view3d_active;
200
201         prop = RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
202         RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
203         RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
204 }
205
206
207 static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
208 {
209         Scene *scene = CTX_data_scene(C);
210         BIF_removeTransformOrientationIndex(C, scene->orientation_index_custom);
211
212         WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
213
214         return OPERATOR_FINISHED;
215 }
216
217 static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
218 {
219         return delete_orientation_exec(C, op);
220 }
221
222 static int delete_orientation_poll(bContext *C)
223 {
224         Scene *scene = CTX_data_scene(C);
225
226         if (ED_operator_areaactive(C) == 0)
227                 return 0;
228
229         return (scene->orientation_type >= V3D_MANIP_CUSTOM) && (scene->orientation_index_custom != -1);
230 }
231
232 static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot)
233 {
234         /* identifiers */
235         ot->name   = "Delete Orientation";
236         ot->description = "Delete transformation orientation";
237         ot->idname = "TRANSFORM_OT_delete_orientation";
238         ot->flag   = OPTYPE_UNDO;
239
240         /* api callbacks */
241         ot->invoke = delete_orientation_invoke;
242         ot->exec   = delete_orientation_exec;
243         ot->poll   = delete_orientation_poll;
244 }
245
246 static int create_orientation_exec(bContext *C, wmOperator *op)
247 {
248         char name[MAX_NAME];
249         const bool use = RNA_boolean_get(op->ptr, "use");
250         const bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
251         const bool use_view = RNA_boolean_get(op->ptr, "use_view");
252         View3D *v3d = CTX_wm_view3d(C);
253
254         RNA_string_get(op->ptr, "name", name);
255
256         if (use && !v3d) {
257                 BKE_report(op->reports, RPT_ERROR, "Create Orientation's 'use' parameter only valid in a 3DView context");
258                 return OPERATOR_CANCELLED;
259         }
260
261         BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
262
263         WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
264         WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
265
266         return OPERATOR_FINISHED;
267 }
268
269 static void TRANSFORM_OT_create_orientation(struct wmOperatorType *ot)
270 {
271         /* identifiers */
272         ot->name   = "Create Orientation";
273         ot->description = "Create transformation orientation from selection";
274         ot->idname = "TRANSFORM_OT_create_orientation";
275         ot->flag   = OPTYPE_REGISTER | OPTYPE_UNDO;
276
277         /* api callbacks */
278         ot->exec   = create_orientation_exec;
279         ot->poll   = ED_operator_areaactive;
280
281         RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
282         RNA_def_boolean(ot->srna, "use_view", false, "Use View",
283                         "Use the current view instead of the active object to create the new orientation");
284
285         WM_operatortype_props_advanced_begin(ot);
286
287         RNA_def_boolean(ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
288         RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite previous",
289                         "Overwrite previously created orientation with same name");
290 }
291
292
293 #ifdef USE_LOOPSLIDE_HACK
294 /**
295  * Special hack for MESH_OT_loopcut_slide so we get back to the selection mode
296  */
297 static void transformops_loopsel_hack(bContext *C, wmOperator *op)
298 {
299         if (op->type->idname == OP_EDGE_SLIDE) {
300                 if (op->opm && op->opm->opm && op->opm->opm->prev) {
301                         wmOperator *op_prev = op->opm->opm->prev;
302                         Scene *scene = CTX_data_scene(C);
303                         int mesh_select_mode[3];
304                         PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
305
306                         if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
307                                 ToolSettings *ts = scene->toolsettings;
308                                 short selectmode_orig;
309
310                                 RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
311                                 selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
312                                                    (mesh_select_mode[1] ? SCE_SELECT_EDGE   : 0) |
313                                                    (mesh_select_mode[2] ? SCE_SELECT_FACE   : 0));
314
315                                 /* still switch if we were originally in face select mode */
316                                 if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
317                                         Object *obedit = CTX_data_edit_object(C);
318                                         BMEditMesh *em = BKE_editmesh_from_object(obedit);
319                                         em->selectmode = ts->selectmode = selectmode_orig;
320                                         EDBM_selectmode_set(em);
321                                 }
322                         }
323                 }
324         }
325 }
326 #else
327 /* prevent removal by cleanup */
328 #  error "loopslide hack removed!"
329 #endif  /* USE_LOOPSLIDE_HACK */
330
331
332 static void transformops_exit(bContext *C, wmOperator *op)
333 {
334 #ifdef USE_LOOPSLIDE_HACK
335         transformops_loopsel_hack(C, op);
336 #endif
337
338         saveTransform(C, op->customdata, op);
339         MEM_freeN(op->customdata);
340         op->customdata = NULL;
341         G.moving = 0;
342 }
343
344 static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event)
345 {
346         int retval = 1;
347         if (op->customdata == NULL) {
348                 TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
349                 TransformModeItem *tmode;
350                 int mode = -1;
351
352                 for (tmode = transform_modes; tmode->idname; tmode++) {
353                         if (op->type->idname == tmode->idname) {
354                                 mode = tmode->mode;
355                                 break;
356                         }
357                 }
358
359                 if (mode == -1) {
360                         mode = RNA_enum_get(op->ptr, "mode");
361                 }
362
363                 retval = initTransform(C, t, op, event, mode);
364
365                 /* store data */
366                 if (retval) {
367                         G.moving = special_transform_moving(t);
368                         op->customdata = t;
369                 }
370                 else {
371                         MEM_freeN(t);
372                 }
373         }
374
375         return retval; /* return 0 on error */
376 }
377
378 static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
379 {
380         int exit_code;
381
382         TransInfo *t = op->customdata;
383         const enum TfmMode mode_prev = t->mode;
384
385 #if defined(WITH_INPUT_NDOF) && 0
386         // stable 2D mouse coords map to different 3D coords while the 3D mouse is active
387         // in other words, 2D deltas are no longer good enough!
388         // disable until individual 'transformers' behave better
389
390         if (event->type == NDOF_MOTION)
391                 return OPERATOR_PASS_THROUGH;
392 #endif
393
394         /* XXX insert keys are called here, and require context */
395         t->context = C;
396         exit_code = transformEvent(t, event);
397         t->context = NULL;
398
399         /* XXX, workaround: active needs to be calculated before transforming,
400          * since we're not reading from 'td->center' in this case. see: T40241 */
401         if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) {
402                 /* In camera view, tsnap callback is not set (see initSnappingMode() in transfrom_snap.c, and T40348). */
403                 if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) {
404                         t->tsnap.targetSnap(t);
405                 }
406         }
407
408         transformApply(C, t);
409
410         exit_code |= transformEnd(C, t);
411
412         if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
413                 transformops_exit(C, op);
414                 exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */
415         }
416         else {
417                 if (mode_prev != t->mode) {
418                         /* WARNING: this is not normal to switch operator types
419                          * normally it would not be supported but transform happens
420                          * to share callbacks between different operators. */
421                         wmOperatorType *ot_new = NULL;
422                         TransformModeItem *item = transform_modes;
423                         while (item->idname) {
424                                 if (item->mode == t->mode) {
425                                         ot_new = WM_operatortype_find(item->idname, false);
426                                         break;
427                                 }
428                                 item++;
429                         }
430
431                         BLI_assert(ot_new != NULL);
432                         if (ot_new) {
433                                 WM_operator_type_set(op, ot_new);
434                         }
435                         /* end suspicious code */
436                 }
437         }
438
439         return exit_code;
440 }
441
442 static void transform_cancel(bContext *C, wmOperator *op)
443 {
444         TransInfo *t = op->customdata;
445
446         t->state = TRANS_CANCEL;
447         transformEnd(C, t);
448         transformops_exit(C, op);
449 }
450
451 static int transform_exec(bContext *C, wmOperator *op)
452 {
453         TransInfo *t;
454
455         if (!transformops_data(C, op, NULL)) {
456                 G.moving = 0;
457                 return OPERATOR_CANCELLED;
458         }
459
460         t = op->customdata;
461
462         t->options |= CTX_AUTOCONFIRM;
463
464         transformApply(C, t);
465
466         transformEnd(C, t);
467
468         transformops_exit(C, op);
469
470         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
471
472         return OPERATOR_FINISHED;
473 }
474
475 static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
476 {
477         if (!transformops_data(C, op, event)) {
478                 G.moving = 0;
479                 return OPERATOR_CANCELLED;
480         }
481
482         /* When modal, allow 'value' to set initial offset. */
483         if ((event == NULL) &&
484             RNA_struct_property_is_set(op->ptr, "value"))
485         {
486                 return transform_exec(C, op);
487         }
488         else {
489                 /* add temp handler */
490                 WM_event_add_modal_handler(C, op);
491
492                 op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only?
493
494                 /* Use when modal input has some transformation to begin with. */
495                 {
496                         TransInfo *t = op->customdata;
497                         if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) {
498                                 transformApply(C, t);
499                         }
500                 }
501
502                 return OPERATOR_RUNNING_MODAL;
503         }
504 }
505
506 void Transform_Properties(struct wmOperatorType *ot, int flags)
507 {
508         PropertyRNA *prop;
509
510         if (flags & P_AXIS) {
511                 prop = RNA_def_property(ot->srna, "axis", PROP_FLOAT, PROP_DIRECTION);
512                 RNA_def_property_array(prop, 3);
513                 /* Make this not hidden when there's a nice axis selection widget */
514                 RNA_def_property_flag(prop, PROP_HIDDEN);
515                 RNA_def_property_ui_text(prop, "Axis", "The axis around which the transformation occurs");
516         }
517
518         if (flags & P_CONSTRAINT) {
519                 RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
520                 prop = RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE);
521                 RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
522                 RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
523         }
524
525         if (flags & P_MIRROR) {
526                 prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
527                 if (flags & P_MIRROR_DUMMY) {
528                         /* only used so macros can disable this option */
529                         RNA_def_property_flag(prop, PROP_HIDDEN);
530                 }
531         }
532
533
534         if (flags & P_PROPORTIONAL) {
535                 RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", "");
536                 prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0,
537                                     "Proportional Editing Falloff", "Falloff type for proportional editing mode");
538                 RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
539                 RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
540                               "Proportional Size", "", 0.001f, 100.0f);
541         }
542
543         if (flags & P_SNAP) {
544                 prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
545                 RNA_def_property_flag(prop, PROP_HIDDEN);
546
547                 if (flags & P_GEO_SNAP) {
548                         prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
549                         RNA_def_property_flag(prop, PROP_HIDDEN);
550                         prop = RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
551                         RNA_def_property_flag(prop, PROP_HIDDEN);
552
553                         if (flags & P_ALIGN_SNAP) {
554                                 prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
555                                 RNA_def_property_flag(prop, PROP_HIDDEN);
556                                 prop = RNA_def_float_vector(ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
557                                 RNA_def_property_flag(prop, PROP_HIDDEN);
558                         }
559                 }
560         }
561
562         if (flags & P_GPENCIL_EDIT) {
563                 RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
564         }
565
566         if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
567                 RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
568                 prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
569                 RNA_def_property_flag(prop, PROP_HIDDEN);
570         }
571
572         if (flags & P_CORRECT_UV) {
573                 RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UVs", "Correct UV coordinates when transforming");
574         }
575
576         if (flags & P_CENTER) {
577                 /* For manipulators that define their own center. */
578                 prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
579                 RNA_def_property_array(prop, 3);
580                 RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
581                 RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
582         }
583
584         if ((flags & P_NO_DEFAULTS) == 0) {
585                 prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button");
586                 RNA_def_property_flag(prop, PROP_HIDDEN);
587
588                 prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
589                 RNA_def_property_flag(prop, PROP_HIDDEN);
590         }
591 }
592
593 static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
594 {
595         /* identifiers */
596         ot->name   = "Translate";
597         ot->description = "Translate (move) selected items";
598         ot->idname = OP_TRANSLATION;
599         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
600
601         /* api callbacks */
602         ot->invoke = transform_invoke;
603         ot->exec   = transform_exec;
604         ot->modal  = transform_modal;
605         ot->cancel = transform_cancel;
606         ot->poll   = ED_operator_screenactive;
607
608         RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
609
610         WM_operatortype_props_advanced_begin(ot);
611
612         Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
613 }
614
615 static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
616 {
617         /* identifiers */
618         ot->name   = "Resize";
619         ot->description = "Scale (resize) selected items";
620         ot->idname = OP_RESIZE;
621         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
622
623         /* api callbacks */
624         ot->invoke = transform_invoke;
625         ot->exec   = transform_exec;
626         ot->modal  = transform_modal;
627         ot->cancel = transform_cancel;
628         ot->poll   = ED_operator_screenactive;
629
630         RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
631
632         WM_operatortype_props_advanced_begin(ot);
633
634         Transform_Properties(
635                 ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
636 }
637
638 static int skin_resize_poll(bContext *C)
639 {
640         struct Object *obedit = CTX_data_edit_object(C);
641         if (obedit && obedit->type == OB_MESH) {
642                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
643                 return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
644         }
645         return 0;
646 }
647
648 static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
649 {
650         /* identifiers */
651         ot->name   = "Skin Resize";
652         ot->description = "Scale selected vertices' skin radii";
653         ot->idname = OP_SKIN_RESIZE;
654         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
655
656         /* api callbacks */
657         ot->invoke = transform_invoke;
658         ot->exec   = transform_exec;
659         ot->modal  = transform_modal;
660         ot->cancel = transform_cancel;
661         ot->poll   = skin_resize_poll;
662
663         RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
664
665         WM_operatortype_props_advanced_begin(ot);
666
667         Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_NO_TEXSPACE);
668 }
669
670 static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
671 {
672         /* identifiers */
673         ot->name   = "Trackball";
674         ot->description = "Trackball style rotation of selected items";
675         ot->idname = OP_TRACKBALL;
676         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
677
678         /* api callbacks */
679         ot->invoke = transform_invoke;
680         ot->exec   = transform_exec;
681         ot->modal  = transform_modal;
682         ot->cancel = transform_cancel;
683         ot->poll   = ED_operator_screenactive;
684
685         /* Maybe we could use float_vector_xyz here too? */
686         RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
687
688         WM_operatortype_props_advanced_begin(ot);
689
690         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
691 }
692
693 static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
694 {
695         /* identifiers */
696         ot->name = "Rotate";
697         ot->description = "Rotate selected items";
698         ot->idname = OP_ROTATION;
699         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
700
701         /* api callbacks */
702         ot->invoke = transform_invoke;
703         ot->exec   = transform_exec;
704         ot->modal  = transform_modal;
705         ot->cancel = transform_cancel;
706         ot->poll   = ED_operator_screenactive;
707
708         RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
709
710         WM_operatortype_props_advanced_begin(ot);
711
712         Transform_Properties(
713                 ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
714 }
715
716 static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
717 {
718         /* identifiers */
719         ot->name = "Tilt";
720         /* optional -
721          * "Tilt selected vertices"
722          * "Specify an extra axis rotation for selected vertices of 3D curve" */
723         ot->description = "Tilt selected control vertices of 3D curve";
724         ot->idname = OP_TILT;
725         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
726
727         /* api callbacks */
728         ot->invoke = transform_invoke;
729         ot->exec   = transform_exec;
730         ot->modal  = transform_modal;
731         ot->cancel = transform_cancel;
732         ot->poll   = ED_operator_editcurve_3d;
733
734         RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
735
736         WM_operatortype_props_advanced_begin(ot);
737
738         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
739 }
740
741 static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
742 {
743         /* identifiers */
744         ot->name   = "Bend";
745         ot->description = "Bend selected items between the 3D cursor and the mouse";
746         ot->idname = OP_BEND;
747         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
748
749         /* api callbacks */
750         ot->invoke = transform_invoke;
751         // ot->exec   = transform_exec;  // unsupported
752         ot->modal  = transform_modal;
753         ot->cancel = transform_cancel;
754         ot->poll   = ED_operator_region_view3d_active;
755
756         RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
757
758         WM_operatortype_props_advanced_begin(ot);
759
760         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
761 }
762
763 static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
764 {
765         /* identifiers */
766         ot->name   = "Shear";
767         ot->description = "Shear selected items along the horizontal screen axis";
768         ot->idname = OP_SHEAR;
769         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
770
771         /* api callbacks */
772         ot->invoke = transform_invoke;
773         ot->exec   = transform_exec;
774         ot->modal  = transform_modal;
775         ot->cancel = transform_cancel;
776         ot->poll   = ED_operator_screenactive;
777
778         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
779
780         WM_operatortype_props_advanced_begin(ot);
781
782         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
783         // XXX Shear axis?
784 }
785
786 static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
787 {
788         /* identifiers */
789         ot->name   = "Push/Pull";
790         ot->description = "Push/Pull selected items";
791         ot->idname = OP_PUSH_PULL;
792         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
793
794         /* api callbacks */
795         ot->invoke = transform_invoke;
796         ot->exec   = transform_exec;
797         ot->modal  = transform_modal;
798         ot->cancel = transform_cancel;
799         ot->poll   = ED_operator_screenactive;
800
801         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
802
803         WM_operatortype_props_advanced_begin(ot);
804
805         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
806 }
807
808 static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
809 {
810         /* identifiers */
811         ot->name   = "Shrink/Fatten";
812         ot->description = "Shrink/fatten selected vertices along normals";
813         ot->idname = OP_SHRINK_FATTEN;
814         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
815
816         /* api callbacks */
817         ot->invoke = transform_invoke;
818         ot->exec   = transform_exec;
819         ot->modal  = transform_modal;
820         ot->cancel = transform_cancel;
821         ot->poll   = ED_operator_editmesh;
822
823         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
824
825         RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
826
827         WM_operatortype_props_advanced_begin(ot);
828
829         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
830 }
831
832 static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
833 {
834         /* identifiers */
835         ot->name   = "To Sphere";
836         //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
837         ot->description = "Move selected vertices outward in a spherical shape around mesh center";
838         ot->idname = OP_TOSPHERE;
839         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
840
841         /* api callbacks */
842         ot->invoke = transform_invoke;
843         ot->exec   = transform_exec;
844         ot->modal  = transform_modal;
845         ot->cancel = transform_cancel;
846         ot->poll   = ED_operator_screenactive;
847
848         RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
849
850         WM_operatortype_props_advanced_begin(ot);
851
852         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
853 }
854
855 static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
856 {
857         /* identifiers */
858         ot->name   = "Mirror";
859         ot->description = "Mirror selected items around one or more axes";
860         ot->idname = OP_MIRROR;
861         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
862
863         /* api callbacks */
864         ot->invoke = transform_invoke;
865         ot->exec   = transform_exec;
866         ot->modal  = transform_modal;
867         ot->cancel = transform_cancel;
868         ot->poll   = ED_operator_screenactive;
869
870         Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
871 }
872
873 static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
874 {
875         PropertyRNA *prop;
876
877         /* identifiers */
878         ot->name   = "Edge Slide";
879         ot->description = "Slide an edge loop along a mesh";
880         ot->idname = OP_EDGE_SLIDE;
881         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
882
883         /* api callbacks */
884         ot->invoke = transform_invoke;
885         ot->exec   = transform_exec;
886         ot->modal  = transform_modal;
887         ot->cancel = transform_cancel;
888         ot->poll   = ED_operator_editmesh_region_view3d;
889
890         RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
891
892         prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
893         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
894         RNA_def_boolean(ot->srna, "use_even", false, "Even",
895                         "Make the edge loop match the shape of the adjacent edge loop");
896
897         WM_operatortype_props_advanced_begin(ot);
898
899         RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
900                         "When Even mode is active, flips between the two adjacent edge loops");
901         RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
902                         "Clamp within the edge extents");
903
904         Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
905 }
906
907 static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
908 {
909         /* identifiers */
910         ot->name   = "Vertex Slide";
911         ot->description = "Slide a vertex along a mesh";
912         ot->idname = OP_VERT_SLIDE;
913         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
914
915         /* api callbacks */
916         ot->invoke = transform_invoke;
917         ot->exec   = transform_exec;
918         ot->modal  = transform_modal;
919         ot->cancel = transform_cancel;
920         ot->poll   = ED_operator_editmesh_region_view3d;
921
922         RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
923         RNA_def_boolean(ot->srna, "use_even", false, "Even",
924                         "Make the edge loop match the shape of the adjacent edge loop");
925
926         WM_operatortype_props_advanced_begin(ot);
927
928         RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
929                         "When Even mode is active, flips between the two adjacent edge loops");
930         RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
931                         "Clamp within the edge extents");
932
933         Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
934 }
935
936 static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
937 {
938         /* identifiers */
939         ot->name   = "Edge Crease";
940         ot->description = "Change the crease of edges";
941         ot->idname = OP_EDGE_CREASE;
942         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
943
944         /* api callbacks */
945         ot->invoke = transform_invoke;
946         ot->exec   = transform_exec;
947         ot->modal  = transform_modal;
948         ot->cancel = transform_cancel;
949         ot->poll   = ED_operator_editmesh;
950
951         RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
952
953         WM_operatortype_props_advanced_begin(ot);
954
955         Transform_Properties(ot, P_SNAP);
956 }
957
958 static int edge_bevelweight_exec(bContext *C, wmOperator *op)
959 {
960         Mesh *me = (Mesh *)CTX_data_edit_object(C)->data;
961
962         /* auto-enable bevel edge weight drawing, then chain to common transform code */
963         me->drawflag |= ME_DRAWBWEIGHTS;
964
965         return transform_exec(C, op);
966 }
967
968 static int edge_bevelweight_invoke(bContext *C, wmOperator *op, const wmEvent *event)
969 {
970         Mesh *me = (Mesh *)CTX_data_edit_object(C)->data;
971
972         /* auto-enable bevel edge weight drawing, then chain to common transform code */
973         me->drawflag |= ME_DRAWBWEIGHTS;
974
975         return transform_invoke(C, op, event);
976 }
977
978
979 static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
980 {
981         /* identifiers */
982         ot->name   = "Edge Bevel Weight";
983         ot->description = "Change the bevel weight of edges";
984         ot->idname = OP_EDGE_BWEIGHT;
985         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
986
987         /* api callbacks */
988         ot->invoke = edge_bevelweight_invoke;
989         ot->exec   = edge_bevelweight_exec;
990         ot->modal  = transform_modal;
991         ot->cancel = transform_cancel;
992         ot->poll   = ED_operator_editmesh;
993
994         RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
995
996         WM_operatortype_props_advanced_begin(ot);
997
998         Transform_Properties(ot, P_SNAP);
999 }
1000
1001 static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
1002 {
1003         /* identifiers */
1004         ot->name   = "Sequence Slide";
1005         ot->description = "Slide a sequence strip in time";
1006         ot->idname = OP_SEQ_SLIDE;
1007         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1008
1009         /* api callbacks */
1010         ot->invoke = transform_invoke;
1011         ot->exec   = transform_exec;
1012         ot->modal  = transform_modal;
1013         ot->cancel = transform_cancel;
1014         ot->poll   = ED_operator_sequencer_active;
1015
1016         RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
1017
1018         WM_operatortype_props_advanced_begin(ot);
1019
1020         Transform_Properties(ot, P_SNAP);
1021 }
1022
1023 static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
1024 {
1025         PropertyRNA *prop;
1026
1027         /* identifiers */
1028         ot->name   = "Transform";
1029         ot->description = "Transform selected items by mode type";
1030         ot->idname = "TRANSFORM_OT_transform";
1031         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1032
1033         /* api callbacks */
1034         ot->invoke = transform_invoke;
1035         ot->exec   = transform_exec;
1036         ot->modal  = transform_modal;
1037         ot->cancel = transform_cancel;
1038         ot->poll   = ED_operator_screenactive;
1039
1040         prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
1041         RNA_def_property_flag(prop, PROP_HIDDEN);
1042
1043         RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
1044
1045         WM_operatortype_props_advanced_begin(ot);
1046
1047         Transform_Properties(
1048                 ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
1049 }
1050
1051 void transform_operatortypes(void)
1052 {
1053         TransformModeItem *tmode;
1054
1055         for (tmode = transform_modes; tmode->idname; tmode++) {
1056                 WM_operatortype_append(tmode->opfunc);
1057         }
1058
1059         WM_operatortype_append(TRANSFORM_OT_transform);
1060
1061         WM_operatortype_append(TRANSFORM_OT_select_orientation);
1062         WM_operatortype_append(TRANSFORM_OT_create_orientation);
1063         WM_operatortype_append(TRANSFORM_OT_delete_orientation);
1064 }
1065
1066 void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spaceid)
1067 {
1068         wmKeyMapItem *kmi;
1069         wmKeyMap *modalmap;
1070
1071         /* transform.c, only adds modal map once, checks if it's there */
1072         modalmap = transform_modal_keymap(keyconf);
1073
1074         /* assign map to operators only the first time */
1075         if (modalmap) {
1076                 TransformModeItem *tmode;
1077
1078                 for (tmode = transform_modes; tmode->idname; tmode++) {
1079                         WM_modalkeymap_assign(modalmap, tmode->idname);
1080                 }
1081                 WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
1082         }
1083
1084         switch (spaceid) {
1085                 case SPACE_VIEW3D:
1086                         WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0);
1087
1088                         WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0);
1089
1090                         WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0);
1091
1092                         WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0);
1093
1094                         WM_keymap_add_item(keymap, OP_BEND, WKEY, KM_PRESS, KM_SHIFT, 0);
1095
1096                         WM_keymap_add_item(keymap, OP_TOSPHERE, SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
1097
1098                         WM_keymap_add_item(keymap, OP_SHEAR, SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
1099
1100                         WM_keymap_add_item(keymap, "TRANSFORM_OT_select_orientation", SPACEKEY, KM_PRESS, KM_ALT, 0);
1101
1102                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_create_orientation", SPACEKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
1103                         RNA_boolean_set(kmi->ptr, "use", true);
1104
1105                         WM_keymap_add_item(keymap, OP_MIRROR, MKEY, KM_PRESS, KM_CTRL, 0);
1106
1107                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
1108                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
1109
1110                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
1111                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element");
1112
1113                         /* Will fall-through to texture-space transform. */
1114                         kmi = WM_keymap_add_item(keymap, "OBJECT_OT_transform_axis_target", TKEY, KM_PRESS, KM_SHIFT, 0);
1115
1116                         kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0);
1117                         RNA_boolean_set(kmi->ptr, "texture_space", true);
1118
1119                         kmi = WM_keymap_add_item(keymap, OP_RESIZE, TKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
1120                         RNA_boolean_set(kmi->ptr, "texture_space", true);
1121
1122                         WM_keymap_add_item(keymap, OP_SKIN_RESIZE, AKEY, KM_PRESS, KM_CTRL, 0);
1123
1124                         break;
1125                 case SPACE_ACTION:
1126                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", GKEY, KM_PRESS, 0, 0);
1127                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_TRANSLATE);
1128
1129                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
1130                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_TRANSLATE);
1131
1132                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EKEY, KM_PRESS, 0, 0);
1133                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_EXTEND);
1134
1135                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, 0, 0);
1136                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_SCALE);
1137
1138                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", TKEY, KM_PRESS, KM_SHIFT, 0);
1139                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_SLIDE);
1140                         break;
1141                 case SPACE_IPO:
1142                         WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0);
1143
1144                         WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0);
1145
1146                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EKEY, KM_PRESS, 0, 0);
1147                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_EXTEND);
1148
1149                         WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0);
1150
1151                         WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0);
1152                         break;
1153                 case SPACE_NLA:
1154                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", GKEY, KM_PRESS, 0, 0);
1155                         RNA_enum_set(kmi->ptr, "mode", TFM_TRANSLATION);
1156
1157                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
1158                         RNA_enum_set(kmi->ptr, "mode", TFM_TRANSLATION);
1159
1160                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EKEY, KM_PRESS, 0, 0);
1161                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_EXTEND);
1162
1163                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, 0, 0);
1164                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_SCALE);
1165                         break;
1166                 case SPACE_NODE:
1167                         WM_keymap_add_item(keymap, "NODE_OT_translate_attach", GKEY, KM_PRESS, 0, 0);
1168                         WM_keymap_add_item(keymap, "NODE_OT_translate_attach", EVT_TWEAK_A, KM_ANY, 0, 0);
1169                         WM_keymap_add_item(keymap, "NODE_OT_translate_attach", EVT_TWEAK_S, KM_ANY, 0, 0);
1170                         /* NB: small trick: macro operator poll may fail due to library data edit,
1171                          * in that case the secondary regular operators are called with same keymap.
1172                          */
1173                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
1174                         RNA_boolean_set(kmi->ptr, "release_confirm", true);
1175                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_A, KM_ANY, 0, 0);
1176                         RNA_boolean_set(kmi->ptr, "release_confirm", true);
1177                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
1178                         RNA_boolean_set(kmi->ptr, "release_confirm", true);
1179
1180                         WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0);
1181
1182                         WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0);
1183
1184                         /* detach and translate */
1185                         WM_keymap_add_item(keymap, "NODE_OT_move_detach_links", DKEY, KM_PRESS, KM_ALT, 0);
1186                         /* XXX release_confirm is set in the macro operator definition */
1187                         WM_keymap_add_item(keymap, "NODE_OT_move_detach_links_release", EVT_TWEAK_A, KM_ANY, KM_ALT, 0);
1188                         WM_keymap_add_item(keymap, "NODE_OT_move_detach_links", EVT_TWEAK_S, KM_ANY, KM_ALT, 0);
1189
1190                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
1191                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
1192                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
1193                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_node_element");
1194                         break;
1195                 case SPACE_SEQ:
1196                         WM_keymap_add_item(keymap, OP_SEQ_SLIDE, GKEY, KM_PRESS, 0, 0);
1197
1198                         WM_keymap_add_item(keymap, OP_SEQ_SLIDE, EVT_TWEAK_S, KM_ANY, 0, 0);
1199
1200                         kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", EKEY, KM_PRESS, 0, 0);
1201                         RNA_enum_set(kmi->ptr, "mode", TFM_TIME_EXTEND);
1202                         break;
1203                 case SPACE_IMAGE:
1204                         WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0);
1205
1206                         WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0);
1207
1208                         WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0);
1209
1210                         WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0);
1211
1212                         WM_keymap_add_item(keymap, OP_SHEAR, SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
1213
1214                         WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
1215
1216                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
1217                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
1218
1219                         kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
1220                         RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_uv_element");
1221                         break;
1222                 case SPACE_CLIP:
1223                         WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0);
1224                         WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0);
1225                         WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0);
1226                         WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0);
1227                         break;
1228                 default:
1229                         break;
1230         }
1231 }
1232