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