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