Normal UI: for all ops needing autosmooth on, enable it if needed.
[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, "use_proportional_edit");
551     if (prop_pet && (prop_pet != prop) && (RNA_property_boolean_get(op->ptr, prop_pet) == false)) {
552       if (STRPREFIX(prop_id, "proportional") || STRPREFIX(prop_id, "use_proportional")) {
553         return false;
554       }
555     }
556   }
557
558   return true;
559 }
560
561 void Transform_Properties(struct wmOperatorType *ot, int flags)
562 {
563   PropertyRNA *prop;
564
565   if (flags & P_ORIENT_AXIS) {
566     prop = RNA_def_property(ot->srna, "orient_axis", PROP_ENUM, PROP_NONE);
567     RNA_def_property_ui_text(prop, "Axis", "");
568     RNA_def_property_enum_default(prop, 2);
569     RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
570     RNA_def_property_flag(prop, PROP_SKIP_SAVE);
571   }
572   if (flags & P_ORIENT_AXIS_ORTHO) {
573     prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
574     RNA_def_property_ui_text(prop, "Axis Ortho", "");
575     RNA_def_property_enum_default(prop, 1);
576     RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
577     RNA_def_property_flag(prop, PROP_SKIP_SAVE);
578   }
579
580   if (flags & P_ORIENT_MATRIX) {
581     prop = RNA_def_property(ot->srna, "orient_type", PROP_ENUM, PROP_NONE);
582     RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
583     RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
584
585     /* Set by 'orient_type' or gizmo which acts on non-standard orientation. */
586     prop = RNA_def_float_matrix(
587         ot->srna, "orient_matrix", 3, 3, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
588     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
589
590     /* Only use 'orient_matrix' when 'orient_matrix_type == orient_type',
591      * this allows us to reuse the orientation set by a gizmo for eg, without disabling the ability
592      * to switch over to other orientations. */
593     prop = RNA_def_property(ot->srna, "orient_matrix_type", PROP_ENUM, PROP_NONE);
594     RNA_def_property_ui_text(prop, "Matrix Orientation", "");
595     RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
596     RNA_def_property_flag(prop, PROP_HIDDEN);
597   }
598
599   if (flags & P_CONSTRAINT) {
600     RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
601   }
602
603   if (flags & P_MIRROR) {
604     prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
605     if (flags & P_MIRROR_DUMMY) {
606       /* only used so macros can disable this option */
607       RNA_def_property_flag(prop, PROP_HIDDEN);
608     }
609   }
610
611   if (flags & P_PROPORTIONAL) {
612     RNA_def_boolean(ot->srna, "use_proportional_edit", 0, "Proportional Editing", "");
613     prop = RNA_def_enum(ot->srna,
614                         "proportional_edit_falloff",
615                         rna_enum_proportional_falloff_items,
616                         0,
617                         "Proportional Falloff",
618                         "Falloff type for proportional editing mode");
619     /* Abusing id_curve :/ */
620     RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
621     RNA_def_float(ot->srna,
622                   "proportional_size",
623                   1,
624                   T_PROP_SIZE_MIN,
625                   T_PROP_SIZE_MAX,
626                   "Proportional Size",
627                   "",
628                   0.001f,
629                   100.0f);
630
631     RNA_def_boolean(ot->srna, "use_proportional_connected", 0, "Connected", "");
632     RNA_def_boolean(ot->srna, "use_proportional_projected", 0, "Projected (2D)", "");
633   }
634
635   if (flags & P_SNAP) {
636     prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
637     RNA_def_property_flag(prop, PROP_HIDDEN);
638
639     if (flags & P_GEO_SNAP) {
640       prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
641       RNA_def_property_flag(prop, PROP_HIDDEN);
642       prop = RNA_def_float_vector(
643           ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
644       RNA_def_property_flag(prop, PROP_HIDDEN);
645
646       if (flags & P_ALIGN_SNAP) {
647         prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
648         RNA_def_property_flag(prop, PROP_HIDDEN);
649         prop = RNA_def_float_vector(
650             ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
651         RNA_def_property_flag(prop, PROP_HIDDEN);
652       }
653     }
654   }
655
656   if (flags & P_GPENCIL_EDIT) {
657     prop = RNA_def_boolean(ot->srna,
658                            "gpencil_strokes",
659                            0,
660                            "Edit Grease Pencil",
661                            "Edit selected Grease Pencil strokes");
662     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
663   }
664
665   if (flags & P_CURSOR_EDIT) {
666     prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
667     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
668   }
669
670   if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
671     prop = RNA_def_boolean(
672         ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
673     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
674     prop = RNA_def_boolean(
675         ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
676     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
677   }
678
679   if (flags & P_CORRECT_UV) {
680     RNA_def_boolean(
681         ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
682   }
683
684   if (flags & P_CENTER) {
685     /* For gizmos that define their own center. */
686     prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
687     RNA_def_property_array(prop, 3);
688     RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
689     RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
690   }
691
692   if ((flags & P_NO_DEFAULTS) == 0) {
693     prop = RNA_def_boolean(ot->srna,
694                            "release_confirm",
695                            0,
696                            "Confirm on Release",
697                            "Always confirm operation when releasing button");
698     RNA_def_property_flag(prop, PROP_HIDDEN);
699
700     prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
701     RNA_def_property_flag(prop, PROP_HIDDEN);
702   }
703 }
704
705 static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
706 {
707   /* identifiers */
708   ot->name = "Move";
709   ot->description = "Move selected items";
710   ot->idname = OP_TRANSLATION;
711   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
712
713   /* api callbacks */
714   ot->invoke = transform_invoke;
715   ot->exec = transform_exec;
716   ot->modal = transform_modal;
717   ot->cancel = transform_cancel;
718   ot->poll = ED_operator_screenactive;
719   ot->poll_property = transform_poll_property;
720
721   RNA_def_float_vector_xyz(
722       ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX);
723
724   WM_operatortype_props_advanced_begin(ot);
725
726   Transform_Properties(ot,
727                        P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
728                            P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT);
729 }
730
731 static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
732 {
733   /* identifiers */
734   ot->name = "Resize";
735   ot->description = "Scale (resize) selected items";
736   ot->idname = OP_RESIZE;
737   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
738
739   /* api callbacks */
740   ot->invoke = transform_invoke;
741   ot->exec = transform_exec;
742   ot->modal = transform_modal;
743   ot->cancel = transform_cancel;
744   ot->poll = ED_operator_screenactive;
745   ot->poll_property = transform_poll_property;
746
747   RNA_def_float_vector(
748       ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
749
750   WM_operatortype_props_advanced_begin(ot);
751
752   Transform_Properties(ot,
753                        P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
754                            P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
755 }
756
757 static bool skin_resize_poll(bContext *C)
758 {
759   struct Object *obedit = CTX_data_edit_object(C);
760   if (obedit && obedit->type == OB_MESH) {
761     BMEditMesh *em = BKE_editmesh_from_object(obedit);
762     return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
763   }
764   return 0;
765 }
766
767 static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
768 {
769   /* identifiers */
770   ot->name = "Skin Resize";
771   ot->description = "Scale selected vertices' skin radii";
772   ot->idname = OP_SKIN_RESIZE;
773   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
774
775   /* api callbacks */
776   ot->invoke = transform_invoke;
777   ot->exec = transform_exec;
778   ot->modal = transform_modal;
779   ot->cancel = transform_cancel;
780   ot->poll = skin_resize_poll;
781   ot->poll_property = transform_poll_property;
782
783   RNA_def_float_vector(
784       ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
785
786   WM_operatortype_props_advanced_begin(ot);
787
788   Transform_Properties(ot,
789                        P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
790                            P_OPTIONS | P_NO_TEXSPACE);
791 }
792
793 static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
794 {
795   /* identifiers */
796   ot->name = "Trackball";
797   ot->description = "Trackball style rotation of selected items";
798   ot->idname = OP_TRACKBALL;
799   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
800
801   /* api callbacks */
802   ot->invoke = transform_invoke;
803   ot->exec = transform_exec;
804   ot->modal = transform_modal;
805   ot->cancel = transform_cancel;
806   ot->poll = ED_operator_screenactive;
807   ot->poll_property = transform_poll_property;
808
809   /* Maybe we could use float_vector_xyz here too? */
810   RNA_def_float_rotation(
811       ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
812
813   WM_operatortype_props_advanced_begin(ot);
814
815   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
816 }
817
818 static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
819 {
820   /* identifiers */
821   ot->name = "Rotate";
822   ot->description = "Rotate selected items";
823   ot->idname = OP_ROTATION;
824   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
825
826   /* api callbacks */
827   ot->invoke = transform_invoke;
828   ot->exec = transform_exec;
829   ot->modal = transform_modal;
830   ot->cancel = transform_cancel;
831   ot->poll = ED_operator_screenactive;
832   ot->poll_property = transform_poll_property;
833
834   RNA_def_float_rotation(
835       ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
836
837   WM_operatortype_props_advanced_begin(ot);
838
839   Transform_Properties(ot,
840                        P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
841                            P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
842 }
843
844 static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
845 {
846   /* identifiers */
847   ot->name = "Tilt";
848   /* optional -
849    * "Tilt selected vertices"
850    * "Specify an extra axis rotation for selected vertices of 3D curve" */
851   ot->description = "Tilt selected control vertices of 3D curve";
852   ot->idname = OP_TILT;
853   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
854
855   /* api callbacks */
856   ot->invoke = transform_invoke;
857   ot->exec = transform_exec;
858   ot->modal = transform_modal;
859   ot->cancel = transform_cancel;
860   ot->poll = ED_operator_editcurve_3d;
861   ot->poll_property = transform_poll_property;
862
863   RNA_def_float_rotation(
864       ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
865
866   WM_operatortype_props_advanced_begin(ot);
867
868   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
869 }
870
871 static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
872 {
873   /* identifiers */
874   ot->name = "Bend";
875   ot->description = "Bend selected items between the 3D cursor and the mouse";
876   ot->idname = OP_BEND;
877   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
878
879   /* api callbacks */
880   ot->invoke = transform_invoke;
881   // ot->exec   = transform_exec;  // unsupported
882   ot->modal = transform_modal;
883   ot->cancel = transform_cancel;
884   ot->poll = ED_operator_region_view3d_active;
885   ot->poll_property = transform_poll_property;
886
887   RNA_def_float_rotation(
888       ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
889
890   WM_operatortype_props_advanced_begin(ot);
891
892   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
893 }
894
895 static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
896 {
897   /* identifiers */
898   ot->name = "Shear";
899   ot->description = "Shear selected items along the horizontal screen axis";
900   ot->idname = OP_SHEAR;
901   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
902
903   /* api callbacks */
904   ot->invoke = transform_invoke;
905   ot->exec = transform_exec;
906   ot->modal = transform_modal;
907   ot->cancel = transform_cancel;
908   ot->poll = ED_operator_screenactive;
909   ot->poll_property = transform_poll_property;
910
911   RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
912   RNA_def_enum(ot->srna, "shear_axis", rna_enum_axis_xy_items, 0, "Shear Axis", "");
913
914   WM_operatortype_props_advanced_begin(ot);
915
916   Transform_Properties(ot,
917                        P_ORIENT_AXIS | P_ORIENT_AXIS_ORTHO | P_ORIENT_MATRIX | P_PROPORTIONAL |
918                            P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
919 }
920
921 static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
922 {
923   /* identifiers */
924   ot->name = "Push/Pull";
925   ot->description = "Push/Pull selected items";
926   ot->idname = OP_PUSH_PULL;
927   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
928
929   /* api callbacks */
930   ot->invoke = transform_invoke;
931   ot->exec = transform_exec;
932   ot->modal = transform_modal;
933   ot->cancel = transform_cancel;
934   ot->poll = ED_operator_screenactive;
935   ot->poll_property = transform_poll_property;
936
937   RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
938
939   WM_operatortype_props_advanced_begin(ot);
940
941   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
942 }
943
944 static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
945 {
946   /* identifiers */
947   ot->name = "Shrink/Fatten";
948   ot->description = "Shrink/fatten selected vertices along normals";
949   ot->idname = OP_SHRINK_FATTEN;
950   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
951
952   /* api callbacks */
953   ot->invoke = transform_invoke;
954   ot->exec = transform_exec;
955   ot->modal = transform_modal;
956   ot->cancel = transform_cancel;
957   ot->poll = ED_operator_editmesh;
958   ot->poll_property = transform_poll_property;
959
960   RNA_def_float_distance(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
961
962   RNA_def_boolean(ot->srna,
963                   "use_even_offset",
964                   false,
965                   "Offset Even",
966                   "Scale the offset to give more even thickness");
967
968   WM_operatortype_props_advanced_begin(ot);
969
970   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
971 }
972
973 static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
974 {
975   /* identifiers */
976   ot->name = "To Sphere";
977   // added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
978   ot->description = "Move selected vertices outward in a spherical shape around mesh center";
979   ot->idname = OP_TOSPHERE;
980   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
981
982   /* api callbacks */
983   ot->invoke = transform_invoke;
984   ot->exec = transform_exec;
985   ot->modal = transform_modal;
986   ot->cancel = transform_cancel;
987   ot->poll = ED_operator_screenactive;
988   ot->poll_property = transform_poll_property;
989
990   RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
991
992   WM_operatortype_props_advanced_begin(ot);
993
994   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
995 }
996
997 static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
998 {
999   /* identifiers */
1000   ot->name = "Mirror";
1001   ot->description = "Mirror selected items around one or more axes";
1002   ot->idname = OP_MIRROR;
1003   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1004
1005   /* api callbacks */
1006   ot->invoke = transform_invoke;
1007   ot->exec = transform_exec;
1008   ot->modal = transform_modal;
1009   ot->cancel = transform_cancel;
1010   ot->poll = ED_operator_screenactive;
1011   ot->poll_property = transform_poll_property;
1012
1013   Transform_Properties(
1014       ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
1015 }
1016
1017 static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
1018 {
1019   PropertyRNA *prop;
1020
1021   /* identifiers */
1022   ot->name = "Edge Slide";
1023   ot->description = "Slide an edge loop along a mesh";
1024   ot->idname = OP_EDGE_SLIDE;
1025   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1026
1027   /* api callbacks */
1028   ot->invoke = transform_invoke;
1029   ot->exec = transform_exec;
1030   ot->modal = transform_modal;
1031   ot->cancel = transform_cancel;
1032   ot->poll = ED_operator_editmesh_region_view3d;
1033   ot->poll_property = transform_poll_property;
1034
1035   RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
1036
1037   prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
1038   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1039   RNA_def_boolean(ot->srna,
1040                   "use_even",
1041                   false,
1042                   "Even",
1043                   "Make the edge loop match the shape of the adjacent edge loop");
1044
1045   WM_operatortype_props_advanced_begin(ot);
1046
1047   RNA_def_boolean(ot->srna,
1048                   "flipped",
1049                   false,
1050                   "Flipped",
1051                   "When Even mode is active, flips between the two adjacent edge loops");
1052   RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
1053
1054   Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
1055 }
1056
1057 static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
1058 {
1059   /* identifiers */
1060   ot->name = "Vertex Slide";
1061   ot->description = "Slide a vertex along a mesh";
1062   ot->idname = OP_VERT_SLIDE;
1063   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1064
1065   /* api callbacks */
1066   ot->invoke = transform_invoke;
1067   ot->exec = transform_exec;
1068   ot->modal = transform_modal;
1069   ot->cancel = transform_cancel;
1070   ot->poll = ED_operator_editmesh_region_view3d;
1071   ot->poll_property = transform_poll_property;
1072
1073   RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
1074   RNA_def_boolean(ot->srna,
1075                   "use_even",
1076                   false,
1077                   "Even",
1078                   "Make the edge loop match the shape of the adjacent edge loop");
1079
1080   WM_operatortype_props_advanced_begin(ot);
1081
1082   RNA_def_boolean(ot->srna,
1083                   "flipped",
1084                   false,
1085                   "Flipped",
1086                   "When Even mode is active, flips between the two adjacent edge loops");
1087   RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
1088
1089   Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
1090 }
1091
1092 static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
1093 {
1094   /* identifiers */
1095   ot->name = "Edge Crease";
1096   ot->description = "Change the crease of edges";
1097   ot->idname = OP_EDGE_CREASE;
1098   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1099
1100   /* api callbacks */
1101   ot->invoke = transform_invoke;
1102   ot->exec = transform_exec;
1103   ot->modal = transform_modal;
1104   ot->cancel = transform_cancel;
1105   ot->poll = ED_operator_editmesh;
1106   ot->poll_property = transform_poll_property;
1107
1108   RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
1109
1110   WM_operatortype_props_advanced_begin(ot);
1111
1112   Transform_Properties(ot, P_SNAP);
1113 }
1114
1115 static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
1116 {
1117   /* identifiers */
1118   ot->name = "Edge Bevel Weight";
1119   ot->description = "Change the bevel weight of edges";
1120   ot->idname = OP_EDGE_BWEIGHT;
1121   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1122
1123   /* api callbacks */
1124   ot->invoke = transform_invoke;
1125   ot->exec = transform_exec;
1126   ot->modal = transform_modal;
1127   ot->cancel = transform_cancel;
1128   ot->poll = ED_operator_editmesh;
1129
1130   RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
1131
1132   WM_operatortype_props_advanced_begin(ot);
1133
1134   Transform_Properties(ot, P_SNAP);
1135 }
1136
1137 static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
1138 {
1139   /* identifiers */
1140   ot->name = "Sequence Slide";
1141   ot->description = "Slide a sequence strip in time";
1142   ot->idname = OP_SEQ_SLIDE;
1143   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1144
1145   /* api callbacks */
1146   ot->invoke = transform_invoke;
1147   ot->exec = transform_exec;
1148   ot->modal = transform_modal;
1149   ot->cancel = transform_cancel;
1150   ot->poll = ED_operator_sequencer_active;
1151
1152   RNA_def_float_vector_xyz(
1153       ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
1154
1155   WM_operatortype_props_advanced_begin(ot);
1156
1157   Transform_Properties(ot, P_SNAP);
1158 }
1159
1160 static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot)
1161 {
1162   /* identifiers */
1163   ot->name = "Rotate Normals";
1164   ot->description = "Rotate split normal of selected items";
1165   ot->idname = OP_NORMAL_ROTATION;
1166   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1167
1168   /* api callbacks */
1169   ot->invoke = transform_invoke;
1170   ot->exec = transform_exec;
1171   ot->modal = transform_modal;
1172   ot->cancel = transform_cancel;
1173   ot->poll = ED_operator_editmesh;
1174
1175   RNA_def_float_rotation(
1176       ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
1177
1178   Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
1179 }
1180
1181 static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
1182 {
1183   PropertyRNA *prop;
1184
1185   /* identifiers */
1186   ot->name = "Transform";
1187   ot->description = "Transform selected items by mode type";
1188   ot->idname = "TRANSFORM_OT_transform";
1189   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1190
1191   /* api callbacks */
1192   ot->invoke = transform_invoke;
1193   ot->exec = transform_exec;
1194   ot->modal = transform_modal;
1195   ot->cancel = transform_cancel;
1196   ot->poll = ED_operator_screenactive;
1197   ot->poll_property = transform_poll_property;
1198
1199   prop = RNA_def_enum(
1200       ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
1201   RNA_def_property_flag(prop, PROP_HIDDEN);
1202
1203   RNA_def_float_vector(
1204       ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
1205
1206   WM_operatortype_props_advanced_begin(ot);
1207
1208   Transform_Properties(ot,
1209                        P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
1210                            P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
1211 }
1212
1213 void transform_operatortypes(void)
1214 {
1215   TransformModeItem *tmode;
1216
1217   for (tmode = transform_modes; tmode->idname; tmode++) {
1218     WM_operatortype_append(tmode->opfunc);
1219   }
1220
1221   WM_operatortype_append(TRANSFORM_OT_transform);
1222
1223   WM_operatortype_append(TRANSFORM_OT_select_orientation);
1224   WM_operatortype_append(TRANSFORM_OT_create_orientation);
1225   WM_operatortype_append(TRANSFORM_OT_delete_orientation);
1226 }
1227
1228 void ED_keymap_transform(wmKeyConfig *keyconf)
1229 {
1230   wmKeyMap *modalmap = transform_modal_keymap(keyconf);
1231
1232   TransformModeItem *tmode;
1233
1234   for (tmode = transform_modes; tmode->idname; tmode++) {
1235     WM_modalkeymap_assign(modalmap, tmode->idname);
1236   }
1237   WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
1238 }