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