Blender V4.3
editors/transform/transform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BLI_math_matrix.h"
12
13#include "BKE_context.hh"
14#include "BKE_editmesh.hh"
15#include "BKE_layer.hh"
16#include "BKE_mask.h"
17#include "BKE_workspace.hh"
18
19#include "GPU_state.hh"
20
21#include "ED_clip.hh"
22#include "ED_gpencil_legacy.hh"
23#include "ED_image.hh"
24#include "ED_screen.hh"
25#include "ED_space_api.hh"
26#include "ED_uvedit.hh"
27
28#include "ANIM_keyframing.hh"
29
30#include "SEQ_transform.hh"
31
32#include "WM_api.hh"
33#include "WM_message.hh"
34
35#include "UI_interface_icons.hh"
36#include "UI_resources.hh"
37#include "UI_view2d.hh"
38
39#include "RNA_access.hh"
40
41#include "BLF_api.hh"
42#include "BLT_translation.hh"
43
44#include "transform.hh"
46#include "transform_convert.hh"
48#include "transform_gizmo.hh"
49#include "transform_mode.hh"
51#include "transform_snap.hh"
52
53/* Disabling, since when you type you know what you are doing,
54 * and being able to set it to zero is handy. */
55// #define USE_NUM_NO_ZERO.
56
57using namespace blender;
58
59/* -------------------------------------------------------------------- */
63void transform_view_vector_calc(const TransInfo *t, const float focus[3], float r_vec[3])
64{
65 if (t->persp != RV3D_ORTHO) {
66 sub_v3_v3v3(r_vec, t->viewinv[3], focus);
67 }
68 else {
69 copy_v3_v3(r_vec, t->viewinv[2]);
70 }
71 normalize_v3(r_vec);
72}
73
75{
77 return false;
78 }
79 return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
81}
82
85/* ************************** SPACE DEPENDENT CODE **************************** */
86
88{
89 if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && t->region &&
91 {
92 RegionView3D *rv3d = static_cast<RegionView3D *>(t->region->regiondata);
93
94 copy_m4_m4(t->viewmat, rv3d->viewmat);
95 copy_m4_m4(t->viewinv, rv3d->viewinv);
96 copy_m4_m4(t->persmat, rv3d->persmat);
97 copy_m4_m4(t->persinv, rv3d->persinv);
98 t->persp = rv3d->persp;
99 }
100 else {
101 unit_m4(t->viewmat);
102 unit_m4(t->viewinv);
103 unit_m4(t->persmat);
104 unit_m4(t->persinv);
105 t->persp = RV3D_ORTHO;
106 }
107}
108
109void setTransformViewAspect(TransInfo *t, float r_aspect[3])
110{
111 copy_v3_fl(r_aspect, 1.0f);
112
113 if (t->spacetype == SPACE_IMAGE) {
114 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
115
116 if (t->options & CTX_MASK) {
117 ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
118 }
119 else if (t->options & CTX_PAINT_CURVE) {
120 /* Pass. */
121 }
122 else {
123 ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
124 }
125 }
126 else if (t->spacetype == SPACE_SEQ) {
127 if (t->options & CTX_CURSOR) {
128 SEQ_image_preview_unit_to_px(t->scene, r_aspect, r_aspect);
129 }
130 }
131 else if (t->spacetype == SPACE_CLIP) {
132 SpaceClip *sclip = static_cast<SpaceClip *>(t->area->spacedata.first);
133
134 if (t->options & CTX_MOVIECLIP) {
135 ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
136 }
137 else {
138 ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]);
139 }
140 }
141 else if (t->spacetype == SPACE_GRAPH) {
142 /* Depends on context of usage. */
143 }
144}
145
146static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
147{
148 float divx = BLI_rcti_size_x(&v2d->mask);
149 float divy = BLI_rcti_size_y(&v2d->mask);
150
151 r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
152 r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
153 r_vec[2] = 0.0f;
154}
155
156static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
157{
158 float divx = BLI_rcti_size_x(&v2d->mask);
159 float divy = BLI_rcti_size_y(&v2d->mask);
160
161 float mulx = BLI_rctf_size_x(&v2d->cur);
162 float muly = BLI_rctf_size_y(&v2d->cur);
163
164 /* Difference with #convertViewVec2D. */
165 /* Clamp w/h, mask only. */
166 if (mulx / divx < muly / divy) {
167 divy = divx;
168 muly = mulx;
169 }
170 else {
171 divx = divy;
172 mulx = muly;
173 }
174 /* End difference. */
175
176 r_vec[0] = mulx * dx / divx;
177 r_vec[1] = muly * dy / divy;
178 r_vec[2] = 0.0f;
179}
180
181void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
182{
183 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
184 if (t->options & CTX_PAINT_CURVE) {
185 r_vec[0] = dx;
186 r_vec[1] = dy;
187 }
188 else {
189 const float xy_delta[2] = {float(dx), float(dy)};
190 ED_view3d_win_to_delta(t->region, xy_delta, t->zfac, r_vec);
191 }
192 }
193 else if (t->spacetype == SPACE_IMAGE) {
194 if (t->options & CTX_MASK) {
195 convertViewVec2D_mask(static_cast<View2D *>(t->view), r_vec, dx, dy);
196 }
197 else if (t->options & CTX_PAINT_CURVE) {
198 r_vec[0] = dx;
199 r_vec[1] = dy;
200 }
201 else {
202 convertViewVec2D(static_cast<View2D *>(t->view), r_vec, dx, dy);
203 }
204
205 r_vec[0] *= t->aspect[0];
206 r_vec[1] *= t->aspect[1];
207 }
208 else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
209 convertViewVec2D(static_cast<View2D *>(t->view), r_vec, dx, dy);
210 }
211 else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
212 convertViewVec2D(&t->region->v2d, r_vec, dx, dy);
213 }
214 else if (t->spacetype == SPACE_CLIP) {
215 if (t->options & CTX_MASK) {
216 convertViewVec2D_mask(static_cast<View2D *>(t->view), r_vec, dx, dy);
217 }
218 else {
219 convertViewVec2D(static_cast<View2D *>(t->view), r_vec, dx, dy);
220 }
221
222 r_vec[0] *= t->aspect[0];
223 r_vec[1] *= t->aspect[1];
224 }
225 else {
226 printf("%s: called in an invalid context\n", __func__);
227 zero_v3(r_vec);
228 }
229}
230
231void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag)
232{
233 if (t->spacetype == SPACE_VIEW3D) {
234 if (t->region->regiontype == RGN_TYPE_WINDOW) {
236 /* This is what was done in 2.64, perhaps we can be smarter? */
237 adr[0] = int(2140000000.0f);
238 adr[1] = int(2140000000.0f);
239 }
240 }
241 }
242 else if (t->spacetype == SPACE_IMAGE) {
243 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
244
245 if (t->options & CTX_MASK) {
246 float v[2];
247
248 v[0] = vec[0] / t->aspect[0];
249 v[1] = vec[1] / t->aspect[1];
250
251 BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
252
254
255 adr[0] = v[0];
256 adr[1] = v[1];
257 }
258 else if (t->options & CTX_PAINT_CURVE) {
259 adr[0] = vec[0];
260 adr[1] = vec[1];
261 }
262 else {
263 float v[2];
264
265 v[0] = vec[0] / t->aspect[0];
266 v[1] = vec[1] / t->aspect[1];
267
268 UI_view2d_view_to_region(static_cast<const View2D *>(t->view), v[0], v[1], &adr[0], &adr[1]);
269 }
270 }
271 else if (t->spacetype == SPACE_ACTION) {
272 int out[2] = {0, 0};
273#if 0
274 SpaceAction *sact = t->area->spacedata.first;
275
276 if (sact->flag & SACTION_DRAWTIME) {
277 // vec[0] = vec[0] / ((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
278 /* Same as below. */
279 UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
280 }
281 else
282#endif
283 {
284 UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
285 }
286
287 adr[0] = out[0];
288 adr[1] = out[1];
289 }
290 else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
291 int out[2] = {0, 0};
292
293 UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
294 adr[0] = out[0];
295 adr[1] = out[1];
296 }
297 else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work. */
298 int out[2] = {0, 0};
299
300 UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
301 adr[0] = out[0];
302 adr[1] = out[1];
303 }
304 else if (t->spacetype == SPACE_CLIP) {
305 SpaceClip *sc = static_cast<SpaceClip *>(t->area->spacedata.first);
306
307 if (t->options & CTX_MASK) {
309
310 if (clip) {
311 float v[2];
312
313 v[0] = vec[0] / t->aspect[0];
314 v[1] = vec[1] / t->aspect[1];
315
317
319
320 adr[0] = v[0];
321 adr[1] = v[1];
322 }
323 else {
324 adr[0] = 0;
325 adr[1] = 0;
326 }
327 }
328 else if (t->options & CTX_MOVIECLIP) {
329 float v[2];
330
331 v[0] = vec[0] / t->aspect[0];
332 v[1] = vec[1] / t->aspect[1];
333
334 UI_view2d_view_to_region(static_cast<const View2D *>(t->view), v[0], v[1], &adr[0], &adr[1]);
335 }
336 else {
337 BLI_assert(0);
338 }
339 }
340 else if (t->spacetype == SPACE_NODE) {
341 UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]);
342 }
343}
344void projectIntView(TransInfo *t, const float vec[3], int adr[2])
345{
347}
348
349void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag)
350{
351 switch (t->spacetype) {
352 case SPACE_VIEW3D: {
353 if (t->options & CTX_PAINT_CURVE) {
354 adr[0] = vec[0];
355 adr[1] = vec[1];
356 }
357 else if (t->region->regiontype == RGN_TYPE_WINDOW) {
358 /* Allow points behind the view #33643. */
360 /* XXX, 2.64 and prior did this, weak! */
361 adr[0] = t->region->winx / 2.0f;
362 adr[1] = t->region->winy / 2.0f;
363 }
364 return;
365 }
366 break;
367 }
368 default: {
369 int a[2] = {0, 0};
370 projectIntView(t, vec, a);
371 adr[0] = a[0];
372 adr[1] = a[1];
373 break;
374 }
375 }
376}
377void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
378{
380}
381
382void applyAspectRatio(TransInfo *t, float vec[2])
383{
384 if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) &&
385 !(t->options & CTX_PAINT_CURVE))
386 {
387 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
388
389 if ((sima->flag & SI_COORDFLOATS) == 0) {
390 int width, height;
391 ED_space_image_get_size(sima, &width, &height);
392
393 vec[0] *= width;
394 vec[1] *= height;
395 }
396
397 vec[0] /= t->aspect[0];
398 vec[1] /= t->aspect[1];
399 }
400 else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
401 if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
402 vec[0] /= t->aspect[0];
403 vec[1] /= t->aspect[1];
404 }
405 }
406}
407
408void removeAspectRatio(TransInfo *t, float vec[2])
409{
410 if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
411 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
412
413 if ((sima->flag & SI_COORDFLOATS) == 0) {
414 int width, height;
415 ED_space_image_get_size(sima, &width, &height);
416
417 vec[0] /= width;
418 vec[1] /= height;
419 }
420
421 vec[0] *= t->aspect[0];
422 vec[1] *= t->aspect[1];
423 }
424 else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
425 if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
426 vec[0] *= t->aspect[0];
427 vec[1] *= t->aspect[1];
428 }
429 }
430}
431
432static void viewRedrawForce(const bContext *C, TransInfo *t)
433{
434 if (t->options & CTX_GPENCIL_STROKES) {
435 if (t->obedit_type == OB_GREASE_PENCIL) {
437 }
438 else if (t->obedit_type == OB_GPENCIL_LEGACY) {
440 if (gpd) {
442 }
444 }
445 }
446 else if (t->spacetype == SPACE_VIEW3D) {
447 if (t->options & CTX_PAINT_CURVE) {
448 wmWindow *window = CTX_wm_window(C);
450 }
451 else {
452 /* Do we need more refined tags? */
453 if (t->options & CTX_POSE_BONE) {
455 }
456 else {
458 }
459
460 /* For real-time animation record - send notifiers recognized by animation editors. */
461 /* XXX: is this notifier a lame duck? */
464 }
465 }
466 }
467 else if (t->spacetype == SPACE_ACTION) {
468 // SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
470 }
471 else if (t->spacetype == SPACE_GRAPH) {
472 // SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
474 }
475 else if (t->spacetype == SPACE_NLA) {
477 }
478 else if (t->spacetype == SPACE_NODE) {
479 // ED_area_tag_redraw(t->area);
481 }
482 else if (t->spacetype == SPACE_SEQ) {
484 /* Key-frames on strips has been moved, so make sure related editors are informed. */
486 }
487 else if (t->spacetype == SPACE_IMAGE) {
488 if (t->options & CTX_MASK) {
489 Mask *mask = CTX_data_edit_mask(C);
490
492 }
493 else if (t->options & CTX_PAINT_CURVE) {
494 wmWindow *window = CTX_wm_window(C);
496 }
497 else if (t->options & CTX_CURSOR) {
499 }
500 else {
501 /* XXX how to deal with lock? */
503 if (sima->lock) {
507 }
508 else {
510 }
511 }
512 }
513 else if (t->spacetype == SPACE_CLIP) {
515
518
519 /* Objects could be parented to tracking data, so send this for viewport refresh. */
521
523 }
525 Mask *mask = CTX_data_edit_mask(C);
526
528 }
529 }
530}
531
533{
534 ED_area_status_text(t->area, nullptr);
535 WorkSpace *workspace = CTX_wm_workspace(C);
536 if (workspace) {
538 }
539
540 if (t->spacetype == SPACE_VIEW3D) {
541 /* If auto-keying is enabled, send notifiers that keyframes were added. */
544 }
545
546 /* Redraw UV editor. */
547 const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ?
550
551 if ((t->data_type == &TransConvertType_Mesh) &&
552 (t->settings->uvcalc_flag & uvcalc_correct_flag))
553 {
555 }
556 }
557}
558
559/* ************************************************* */
560
561static bool transform_modal_item_poll(const wmOperator *op, int value)
562{
563 const TransInfo *t = static_cast<const TransInfo *>(op->customdata);
565 if (value == TFM_MODAL_EDIT_SNAP_SOURCE_OFF) {
566 return true;
567 }
568 if (!ELEM(
570 {
571 return false;
572 }
573 }
574
575 switch (value) {
576 case TFM_MODAL_CANCEL: {
577 /* TODO: Canceling with LMB is not possible when the operator is activated
578 * through tweak and the LMB is pressed.
579 * Therefore, this item should not appear in the status bar. */
580 break;
581 }
585 if ((t->flag & T_PROP_EDIT) == 0) {
586 return false;
587 }
588 break;
589 }
592 if (t->spacetype != SPACE_VIEW3D) {
593 return false;
594 }
595 if ((t->tsnap.mode & ~(SCE_SNAP_TO_INCREMENT | SCE_SNAP_TO_GRID)) == 0) {
596 return false;
597 }
598 if (value == TFM_MODAL_ADD_SNAP) {
599 if (!(t->tsnap.status & SNAP_TARGET_FOUND)) {
600 return false;
601 }
602 }
603 else {
604 if (!t->tsnap.selectedPoint) {
605 return false;
606 }
607 }
608 break;
609 }
610 case TFM_MODAL_AXIS_Z:
615 if (t->flag & T_2D_EDIT) {
616 return false;
617 }
618 [[fallthrough]];
619 case TFM_MODAL_AXIS_X:
620 case TFM_MODAL_AXIS_Y:
622 if (t->flag & T_NO_CONSTRAINT) {
623 return false;
624 }
625 break;
626 case TFM_MODAL_CONS_OFF: {
627 if ((t->con.mode & CON_APPLY) == 0) {
628 return false;
629 }
630 break;
631 }
635 if (t->spacetype != SPACE_NODE) {
636 return false;
637 }
638 break;
639 }
642 if ((t->flag & T_AUTOIK) == 0) {
643 return false;
644 }
645 break;
646 }
648 case TFM_MODAL_ROTATE:
649 case TFM_MODAL_RESIZE:
654 return false;
655 }
656 if (value == TFM_MODAL_TRANSLATE && t->mode == TFM_TRANSLATION) {
657 /* The tracking transform in MovieClip has an alternate translate that modifies the offset
658 * of the tracks. */
660 }
661 if (value == TFM_MODAL_ROTATE && t->mode == TFM_ROTATION) {
662 return false;
663 }
664 if (value == TFM_MODAL_RESIZE && t->mode == TFM_RESIZE) {
665 /* The tracking transform in MovieClip has an alternate resize that only affects the
666 * tracker size and not the search area. */
668 }
669 if (value == TFM_MODAL_VERT_EDGE_SLIDE &&
671 /* WORKAROUND: Avoid repeated keys in status bar.
672 *
673 * Previously, `Vert/Edge Slide` and `Move` were triggered by the same modal key.
674 * But now, to fix #100129 (Status bar incorrectly shows "[G] Move"), `Vert/Edge Slide`
675 * has its own modal key. However by default it uses the same key as `Move` (G). So, to
676 * avoid displaying the same key twice (G and G), only display this modal key during the
677 * `Move` operation.
678 *
679 * Ideally we should check if it really uses the same key. */
680 t->mode != TFM_TRANSLATION))
681 {
682 return false;
683 }
684 if (value == TFM_MODAL_TRACKBALL &&
685 /* WORKAROUND: Avoid repeated keys in status bar.
686 *
687 * Previously, `Trackball` and `Rotate` were triggered by the same modal key.
688 * But to fix the status bar incorrectly showing "[R] Rotate", `Trackball` has now its
689 * own modal key. However by default it uses the same key as `Rotate` (R). So, to avoid
690 * displaying the same key twice (R and R), only display this modal key during the
691 * `Rotate` operation.
692 *
693 * Ideally we should check if it really uses the same key. */
694 t->mode != TFM_ROTATION)
695 {
696 return false;
697 }
698 if (value == TFM_MODAL_ROTATE_NORMALS) {
699 return t->mode == TFM_ROTATION && t->data_type == &TransConvertType_Mesh;
700 }
701 break;
702 }
704 return false;
707 return false;
708 }
709 if (!ELEM(
711 {
712 /* More modes can be added over time if this feature proves useful for them. */
713 return false;
714 }
715 if (t->options & CTX_CAMERA) {
716 /* Not supported. */
717 return false;
718 }
719 break;
720 }
723 /* Returning `false` will not prevent the navigation from working, it will just not display
724 * the shortcut in the header.
725 * Return `false` here to prevent this modal item from affecting the state with
726 * #T_ALT_TRANSFORM is used by the operator. */
727 return false;
728 }
729 return t->vod != nullptr;
730 }
731 return true;
732}
733
735{
736 static const EnumPropertyItem modal_items[] = {
737 {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
738 {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
739 {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X Axis", ""},
740 {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y Axis", ""},
741 {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z Axis", ""},
742 {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X Plane", ""},
743 {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y Plane", ""},
744 {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z Plane", ""},
745 {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
746 {TFM_MODAL_EDIT_SNAP_SOURCE_ON, "EDIT_SNAP_SOURCE_ON", 0, "Set Snap Base", ""},
747 {TFM_MODAL_EDIT_SNAP_SOURCE_OFF, "EDIT_SNAP_SOURCE_OFF", 0, "Set Snap Base (Off)", ""},
748 {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
749 {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
750 {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
751 {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
752 {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
753 {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
754 {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
755 {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
757 "PROPORTIONAL_SIZE_DOWN",
758 0,
759 "Decrease Proportional Influence",
760 ""},
761 {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
763 "AUTOIK_CHAIN_LEN_DOWN",
764 0,
765 "Decrease Max AutoIK Chain Length",
766 ""},
767 {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
769 "INSERTOFS_TOGGLE_DIR",
770 0,
771 "Toggle Direction for Node Auto-Offset",
772 ""},
773 {TFM_MODAL_NODE_ATTACH_ON, "NODE_ATTACH_ON", 0, "Node Attachment", ""},
774 {TFM_MODAL_NODE_ATTACH_OFF, "NODE_ATTACH_OFF", 0, "Node Attachment (Off)", ""},
775 {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""},
776 {TFM_MODAL_VERT_EDGE_SLIDE, "VERT_EDGE_SLIDE", 0, "Vert/Edge Slide", ""},
777 {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
778 {TFM_MODAL_TRACKBALL, "TRACKBALL", 0, "TrackBall", ""},
779 {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
780 {TFM_MODAL_ROTATE_NORMALS, "ROTATE_NORMALS", 0, "Rotate Normals", ""},
781 {TFM_MODAL_AUTOCONSTRAINT, "AUTOCONSTRAIN", 0, "Automatic Constraint", ""},
782 {TFM_MODAL_AUTOCONSTRAINTPLANE, "AUTOCONSTRAINPLANE", 0, "Automatic Constraint Plane", ""},
783 {TFM_MODAL_PRECISION, "PRECISION", 0, "Precision Mode", ""},
784 {TFM_MODAL_PASSTHROUGH_NAVIGATE, "PASSTHROUGH_NAVIGATE", 0, "Navigate", ""},
785 {0, nullptr, 0, nullptr, nullptr},
786 };
787
788 wmKeyMap *keymap = WM_modalkeymap_ensure(keyconf, "Transform Modal Map", modal_items);
790
791 /* Default modal map values:
792 *
793 * \code{.c}
794 * WM_modalkeymap_add_item(keymap,
795 * &(const KeyMapItem_Params){
796 * .type = EVT_RETKEY,
797 * .value = KM_PRESS,
798 * .modifier = KM_ANY,
799 * .direction = KM_ANY,
800 * },
801 * TFM_MODAL_CONFIRM);
802 * WM_modalkeymap_add_item(keymap,
803 * &(const KeyMapItem_Params){
804 * .type = EVT_ESCKEY,
805 * .value = KM_PRESS,
806 * .modifier = KM_ANY,
807 * .direction = KM_ANY,
808 * },
809 * TFM_MODAL_CANCEL);
810 * WM_modalkeymap_add_item(keymap,
811 * &(const KeyMapItem_Params){
812 * .type = EVT_PAGEUPKEY,
813 * .value = KM_PRESS,
814 * .modifier = KM_ANY,
815 * .direction = KM_ANY,
816 * },
817 * TFM_MODAL_AUTOIK_LEN_INC);
818 * WM_modalkeymap_add_item(keymap,
819 * &(const KeyMapItem_Params){
820 * .type = EVT_PAGEDOWNKEY,
821 * .value = KM_PRESS,
822 * .modifier = KM_ANY,
823 * .direction = KM_ANY,
824 * },
825 * TFM_MODAL_AUTOIK_LEN_DEC);
826 * WM_modalkeymap_add_item(keymap,
827 * &(const KeyMapItem_Params){
828 * .type = EVT_GKEY,
829 * .value = KM_PRESS,
830 * .modifier = KM_ANY,
831 * .direction = KM_ANY,
832 * },
833 * TFM_MODAL_TRANSLATE);
834 * WM_modalkeymap_add_item(keymap,
835 * &(const KeyMapItem_Params){
836 * .type = EVT_RKEY,
837 * .value = KM_PRESS,
838 * .modifier = KM_ANY,
839 * .direction = KM_ANY,
840 * },
841 * TFM_MODAL_ROTATE);
842 * WM_modalkeymap_add_item(keymap,
843 * &(const KeyMapItem_Params){
844 * .type = EVT_SKEY,
845 * .value = KM_PRESS,
846 * .modifier = KM_ANY,
847 * .direction = KM_ANY,
848 * },
849 * TFM_MODAL_RESIZE);
850 * WM_modalkeymap_add_item(keymap,
851 * &(const KeyMapItem_Params){
852 * .type = MIDDLEMOUSE,
853 * .value = KM_PRESS,
854 * .modifier = KM_ANY,
855 * .direction = KM_ANY,
856 * },
857 * TFM_MODAL_AUTOCONSTRAINT);
858 * WM_modalkeymap_add_item(keymap,
859 * &(const KeyMapItem_Params){
860 * .type = MIDDLEMOUSE,
861 * .value = KM_PRESS,
862 * .modifier = KM_SHIFT,
863 * .direction = KM_ANY,
864 * },
865 * TFM_MODAL_AUTOCONSTRAINTPLANE);
866 * \endcode
867 */
868
869 return keymap;
870}
871
872static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
873{
874 if (t->flag & T_NO_CONSTRAINT) {
875 return false;
876 }
877
878 if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) {
879 return false;
880 }
881
882 int constraint_curr = -1;
883
886
887 /* Avoid changing orientation in this case. */
888 constraint_curr = -2;
889 }
890 else if (t->con.mode & CON_APPLY) {
891 constraint_curr = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
892 }
893
894 int constraint_new;
895 const char *msg_2d = "", *msg_3d = "";
896
897 /* Initialize. */
898 switch (modal_type) {
899 case TFM_MODAL_AXIS_X:
900 msg_2d = IFACE_("along X");
901 msg_3d = IFACE_("along %s X");
902 constraint_new = CON_AXIS0;
903 break;
904 case TFM_MODAL_AXIS_Y:
905 msg_2d = IFACE_("along Y");
906 msg_3d = IFACE_("along %s Y");
907 constraint_new = CON_AXIS1;
908 break;
909 case TFM_MODAL_AXIS_Z:
910 msg_2d = IFACE_("along Z");
911 msg_3d = IFACE_("along %s Z");
912 constraint_new = CON_AXIS2;
913 break;
915 msg_3d = IFACE_("locking %s X");
916 constraint_new = CON_AXIS1 | CON_AXIS2;
917 break;
919 msg_3d = IFACE_("locking %s Y");
920 constraint_new = CON_AXIS0 | CON_AXIS2;
921 break;
923 msg_3d = IFACE_("locking %s Z");
924 constraint_new = CON_AXIS0 | CON_AXIS1;
925 break;
926 default:
927 /* Invalid key. */
928 return false;
929 }
930
931 if (t->flag & T_2D_EDIT) {
932 BLI_assert(modal_type < TFM_MODAL_PLANE_X);
933 if (constraint_new == CON_AXIS2) {
934 return false;
935 }
936
938 /* Setup the 2d msg string so it writes out the transform space. */
939 msg_2d = msg_3d;
940
941 short orient_index = 1;
942 if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) {
943 /* Successive presses on existing axis, cycle orientation modes. */
944 orient_index = short((t->orient_curr + 1) % int(ARRAY_SIZE(t->orient)));
945 }
946
947 transform_orientations_current_set(t, orient_index);
948 if (orient_index != 0) {
949 /* Make sure that we don't stop the constraint unless we are looped back around to
950 * "no constraint". */
951 constraint_curr = -1;
952 }
953 }
954
955 if (constraint_curr == constraint_new) {
957 }
958 else {
959 setUserConstraint(t, constraint_new, msg_2d);
960 }
961 }
962 else {
963 short orient_index = 1;
964 if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) {
965 /* Successive presses on existing axis, cycle orientation modes. */
966 orient_index = short((t->orient_curr + 1) % int(ARRAY_SIZE(t->orient)));
967 }
968
969 transform_orientations_current_set(t, orient_index);
970 if (orient_index == 0) {
972 }
973 else {
974 setUserConstraint(t, constraint_new, msg_3d);
975 }
976
977 /* Take the opportunity to update the gizmo. */
979 }
980 t->redraw |= TREDRAW_HARD;
981 return true;
982}
983
984int transformEvent(TransInfo *t, wmOperator *op, const wmEvent *event)
985{
986 bool handled = false;
987 bool is_navigating = t->vod ? ((RegionView3D *)t->region->regiondata)->rflag & RV3D_NAVIGATING :
988 false;
989
990 /* Handle modal numinput events first, if already activated. */
991 if (!is_navigating && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
992 hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event))
993 {
994 t->redraw |= TREDRAW_HARD;
995 handled = true;
996 }
997 else if (event->type == TIMER) {
998 if (ED_uvedit_live_unwrap_timer_check(static_cast<const wmTimer *>(event->customdata))) {
999 t->redraw |= TREDRAW_HARD;
1000 }
1001 }
1002 else if (!is_navigating && event->type == MOUSEMOVE) {
1003 t->mval = float2(event->mval);
1004
1005 /* Use this for soft redraw. Might cause flicker in object mode. */
1006 // t->redraw |= TREDRAW_SOFT;
1007 t->redraw |= TREDRAW_HARD;
1008
1009 if (t->state == TRANS_STARTING) {
1010 t->state = TRANS_RUNNING;
1011 }
1012
1013 applyMouseInput(t, &t->mouse, t->mval, t->values);
1014
1015 /* Snapping mouse move events. */
1016 t->redraw |= handleSnapping(t, event);
1017 handled = true;
1018 }
1019 /* Handle modal keymap first. */
1020 /* Enforce redraw of transform when modifiers are used. */
1021 else if (event->type == EVT_MODAL_MAP) {
1022 switch (event->val) {
1023 case TFM_MODAL_CANCEL:
1024 if (!(t->modifiers & MOD_EDIT_SNAP_SOURCE)) {
1025 t->state = TRANS_CANCEL;
1026 handled = true;
1027 }
1028 break;
1029 case TFM_MODAL_CONFIRM:
1030 if (!(t->modifiers & MOD_EDIT_SNAP_SOURCE)) {
1031 t->state = TRANS_CONFIRM;
1032 handled = true;
1033 }
1034 break;
1036 case TFM_MODAL_ROTATE:
1037 case TFM_MODAL_RESIZE:
1041 /* Only switch when. */
1043 break;
1044 }
1045
1046 if ((event->val == TFM_MODAL_TRANSLATE && t->mode == TFM_TRANSLATION) ||
1047 (event->val == TFM_MODAL_RESIZE && t->mode == TFM_RESIZE))
1048 {
1051
1052 t->flag ^= T_ALT_TRANSFORM;
1053 t->redraw |= TREDRAW_HARD;
1054 handled = true;
1055 }
1056 break;
1057 }
1058
1059 if ((event->val == TFM_MODAL_ROTATE && t->mode == TFM_ROTATION) ||
1060 (event->val == TFM_MODAL_TRACKBALL && t->mode == TFM_TRACKBALL) ||
1062 (event->val == TFM_MODAL_VERT_EDGE_SLIDE &&
1064 {
1065 break;
1066 }
1067
1069 break;
1070 }
1071
1073 resetTransModal(t);
1075
1076 if (event->val == TFM_MODAL_TRANSLATE) {
1078 }
1079 else if (event->val == TFM_MODAL_ROTATE) {
1080 transform_mode_init(t, nullptr, TFM_ROTATION);
1081 }
1082 else if (event->val == TFM_MODAL_TRACKBALL) {
1084 }
1085 else if (event->val == TFM_MODAL_ROTATE_NORMALS) {
1087 }
1088 else if (event->val == TFM_MODAL_RESIZE) {
1089 /* Scale isn't normally very useful after extrude along normals, see #39756 */
1090 if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) {
1091 stopConstraint(t);
1092 }
1093 transform_mode_init(t, nullptr, TFM_RESIZE);
1094 }
1095 else {
1096 /* First try Edge Slide. */
1098 /* If that fails, try Vertex Slide. */
1099 if (t->state == TRANS_CANCEL) {
1100 resetTransModal(t);
1101 t->state = TRANS_STARTING;
1103 }
1104 /* Vert Slide can fail on unconnected vertices (rare but possible). */
1105 if (t->state == TRANS_CANCEL) {
1106 resetTransModal(t);
1107 t->state = TRANS_STARTING;
1110 }
1111 }
1112
1113 /* Need to reinitialize after mode change. */
1114 initSnapping(t, nullptr);
1115 applyMouseInput(t, &t->mouse, t->mval, t->values);
1116 t->redraw |= TREDRAW_HARD;
1117 handled = true;
1118 break;
1119
1121 if (!(t->modifiers & MOD_SNAP_INVERT)) {
1124 t->redraw |= TREDRAW_HARD;
1125 }
1126 handled = true;
1127 break;
1129 if (t->modifiers & MOD_SNAP_INVERT) {
1130 t->modifiers &= ~MOD_SNAP_INVERT;
1132 t->redraw |= TREDRAW_HARD;
1133 handled = true;
1134 }
1135 break;
1137 t->modifiers ^= MOD_SNAP;
1139 t->redraw |= TREDRAW_HARD;
1140 handled = true;
1141 break;
1142 case TFM_MODAL_AXIS_X:
1143 case TFM_MODAL_AXIS_Y:
1144 case TFM_MODAL_AXIS_Z:
1145 case TFM_MODAL_PLANE_X:
1146 case TFM_MODAL_PLANE_Y:
1147 case TFM_MODAL_PLANE_Z:
1148 if (transform_event_modal_constraint(t, event->val)) {
1149 handled = true;
1150 }
1151 break;
1152 case TFM_MODAL_CONS_OFF:
1153 if ((t->flag & T_NO_CONSTRAINT) == 0) {
1154 stopConstraint(t);
1155 t->redraw |= TREDRAW_HARD;
1156 handled = true;
1157 }
1158 break;
1159 case TFM_MODAL_ADD_SNAP:
1160 addSnapPoint(t);
1161 t->redraw |= TREDRAW_HARD;
1162 handled = true;
1163 break;
1165 removeSnapPoint(t);
1166 t->redraw |= TREDRAW_HARD;
1167 handled = true;
1168 break;
1169 case TFM_MODAL_PROPSIZE:
1170 /* MOUSEPAN usage... */
1171 if (t->flag & T_PROP_EDIT) {
1172 float fac = 1.0f + 0.005f * (event->xy[1] - event->prev_xy[1]);
1173 t->prop_size *= fac;
1174 if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
1175 t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end),
1177 }
1178 else {
1180 }
1182 t->redraw |= TREDRAW_HARD;
1183 handled = true;
1184 }
1185 break;
1187 if (t->flag & T_PROP_EDIT) {
1188 t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
1189 if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
1190 t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
1191 }
1192 else {
1194 }
1196 t->redraw |= TREDRAW_HARD;
1197 handled = true;
1198 }
1199 break;
1201 if (t->flag & T_PROP_EDIT) {
1202 t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
1205 t->redraw |= TREDRAW_HARD;
1206 handled = true;
1207 }
1208 break;
1210 if (t->flag & T_AUTOIK) {
1212 t->redraw |= TREDRAW_HARD;
1213 handled = true;
1214 }
1215 break;
1217 if (t->flag & T_AUTOIK) {
1219 t->redraw |= TREDRAW_HARD;
1220 handled = true;
1221 }
1222 break;
1224 if (t->spacetype == SPACE_NODE) {
1225 SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
1226
1228
1231 }
1232 else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
1234 }
1235 else {
1236 BLI_assert(0);
1237 }
1238
1239 t->redraw |= TREDRAW_SOFT;
1240 }
1241 break;
1244 t->redraw |= TREDRAW_HARD;
1245 handled = true;
1246 break;
1248 t->modifiers &= ~MOD_NODE_ATTACH;
1249 t->redraw |= TREDRAW_HARD;
1250 handled = true;
1251 break;
1252
1255 if ((t->flag & T_RELEASE_CONFIRM) && (event->prev_val == KM_RELEASE) &&
1256 event->prev_type == t->launch_event)
1257 {
1258 /* Confirm transform if launch key is released after mouse move. */
1259 t->state = TRANS_CONFIRM;
1260 }
1261 else if ((t->flag & T_NO_CONSTRAINT) == 0) {
1263 /* Confirm. */
1266 t->redraw = TREDRAW_HARD;
1267 }
1268 else {
1269 if (t->options & CTX_CAMERA) {
1270 /* Exception for switching to dolly, or trackball, in camera view. */
1271 if (t->mode == TFM_TRANSLATION) {
1272 setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
1273 }
1274 else if (t->mode == TFM_ROTATION) {
1277 }
1278 t->redraw = TREDRAW_HARD;
1279 }
1280 else {
1281 t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ?
1284 if (t->con.mode & CON_APPLY) {
1285 stopConstraint(t);
1287
1288 /* In this case we might just want to remove the constraint,
1289 * so set #TREDRAW_SOFT to only select the constraint on the next mouse move event.
1290 * This way we can kind of "cancel" due to confirmation without constraint. */
1291 t->redraw = TREDRAW_SOFT;
1292 }
1293 else {
1295
1296 /* When first called, set #TREDRAW_HARD to select constraint immediately in
1297 * #selectConstraint. */
1299 }
1300 }
1301 }
1302 handled = true;
1303 }
1304 break;
1306 if (is_navigating) {
1307 /* WORKAROUND: During navigation, due to key conflicts, precision may be unintentionally
1308 * enabled. */
1309 }
1310 else if (event->prev_val == KM_PRESS) {
1312 /* Mouse position during Snap to Grid is not affected by precision. */
1313 if (!(validSnap(t) && t->tsnap.target_type == SCE_SNAP_TO_GRID)) {
1314 t->mouse.precision = true;
1315 }
1316
1317 t->redraw |= TREDRAW_HARD;
1318 }
1319 else if (event->prev_val == KM_RELEASE) {
1320 t->modifiers &= ~MOD_PRECISION;
1321 t->mouse.precision = false;
1322 t->redraw |= TREDRAW_HARD;
1323 }
1324 break;
1327 t->redraw |= TREDRAW_HARD;
1328 break;
1329 default:
1330 break;
1331 }
1332 }
1333 /* Else do non-mapped events. */
1334 else if (event->val == KM_PRESS) {
1335 switch (event->type) {
1336 case EVT_CKEY:
1337 if (event->flag & WM_EVENT_IS_REPEAT) {
1338 break;
1339 }
1340 if (event->modifier & KM_ALT) {
1341 if (!(t->options & CTX_NO_PET)) {
1342 t->flag ^= T_PROP_CONNECTED;
1345 t->redraw = TREDRAW_HARD;
1346 handled = true;
1347 }
1348 }
1349 break;
1350 case EVT_OKEY:
1351 if (event->flag & WM_EVENT_IS_REPEAT) {
1352 break;
1353 }
1354 if ((t->flag & T_PROP_EDIT) && (event->modifier & KM_SHIFT)) {
1355 t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
1357 t->redraw |= TREDRAW_HARD;
1358 handled = true;
1359 }
1360 break;
1361 case EVT_PADPLUSKEY:
1362 if ((event->modifier & KM_ALT) && (t->flag & T_PROP_EDIT)) {
1363 t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
1364 if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
1365 t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end);
1366 }
1368 t->redraw = TREDRAW_HARD;
1369 handled = true;
1370 }
1371 break;
1372 case EVT_PADMINUS:
1373 if ((event->modifier & KM_ALT) && (t->flag & T_PROP_EDIT)) {
1374 t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
1376 t->redraw = TREDRAW_HARD;
1377 handled = true;
1378 }
1379 break;
1380 case EVT_LEFTALTKEY:
1381 case EVT_RIGHTALTKEY:
1383 t->flag |= T_ALT_TRANSFORM;
1384 t->redraw |= TREDRAW_HARD;
1385 handled = true;
1386 }
1387 break;
1388 default:
1389 break;
1390 }
1391
1392 /* Snapping key events. */
1393 t->redraw |= handleSnapping(t, event);
1394 }
1395 else if (event->val == KM_RELEASE) {
1396 switch (event->type) {
1397 case EVT_LEFTALTKEY:
1398 case EVT_RIGHTALTKEY:
1399 /* TODO: Modal Map */
1401 t->flag &= ~T_ALT_TRANSFORM;
1402 t->redraw |= TREDRAW_HARD;
1403 handled = true;
1404 }
1405 break;
1406 }
1407
1408 /* Confirm transform if launch key is released after mouse move. */
1409 if ((t->flag & T_RELEASE_CONFIRM) && event->type == t->launch_event) {
1410 t->state = TRANS_CONFIRM;
1411 }
1412 }
1413
1414 /* Per transform event, if present. */
1415 if (t->mode_info && t->mode_info->handle_event_fn &&
1416 (!handled ||
1417 /* Needed for vertex slide, see #38756. */
1418 (event->type == MOUSEMOVE)))
1419 {
1420 t->redraw |= t->mode_info->handle_event_fn(t, event);
1421 }
1422
1423 /* Try to init modal numinput now, if possible. */
1424 if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
1425 handleNumInput(t->context, &(t->num), event))
1426 {
1427 t->redraw |= TREDRAW_HARD;
1428 handled = true;
1429 }
1430
1431 if (t->redraw && !ISMOUSE_MOTION(event->type)) {
1433 }
1434
1435 WorkSpace *workspace = CTX_wm_workspace(t->context);
1436 if (workspace) {
1437 BKE_workspace_status_clear(workspace);
1438 }
1439
1440 if (!is_navigating && (handled || t->redraw)) {
1441 return 0;
1442 }
1443 return OPERATOR_PASS_THROUGH;
1444}
1445
1446bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
1447{
1448 TransInfo *t = static_cast<TransInfo *>(MEM_callocN(sizeof(TransInfo), "TransInfo data"));
1449 bool success;
1450
1451 t->context = C;
1452
1453 t->state = TRANS_RUNNING;
1454
1455 /* Avoid calculating proportional editing. */
1456 t->options = CTX_NO_PET;
1457
1458 t->mode = TFM_DUMMY;
1459
1460 initTransInfo(C, t, nullptr, nullptr);
1461
1462 /* Avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set). */
1464
1465 create_trans_data(C, t); /* Make TransData structs from selection. */
1466
1467 t->around = centerMode; /* Override user-defined mode. */
1468
1469 if (t->data_len_all == 0) {
1470 success = false;
1471 }
1472 else {
1473 success = true;
1474
1475 calculateCenter(t);
1476
1477 if (cent2d) {
1478 copy_v2_v2(cent2d, t->center2d);
1479 }
1480
1481 if (cent3d) {
1482 /* Copy center from constraint center. Transform center can be local. */
1483 copy_v3_v3(cent3d, t->center_global);
1484 }
1485 }
1486
1487 /* Does insert keyframes, and clears base flags; doesn't read `transdata`. */
1489
1490 postTrans(C, t);
1491
1492 MEM_freeN(t);
1493
1494 return success;
1495}
1496
1498{
1499 /* Don't show overlays when not the active view and when overlay is disabled: #57139 */
1500 bool ok = false;
1501 if (region == t->region) {
1502 ok = true;
1503 }
1504 else {
1505 if (t->spacetype == SPACE_VIEW3D) {
1506 View3D *v3d = static_cast<View3D *>(t->view);
1507 if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
1508 ok = true;
1509 }
1510 }
1511 }
1512 return ok;
1513}
1514
1515static void drawTransformView(const bContext * /*C*/, ARegion *region, void *arg)
1516{
1517 TransInfo *t = static_cast<TransInfo *>(arg);
1518
1519 if (!transinfo_show_overlay(t, region)) {
1520 return;
1521 }
1522
1523 GPU_line_width(1.0f);
1524
1525 drawConstraint(t);
1526
1527 switch (t->spacetype) {
1528 case SPACE_GRAPH:
1529 case SPACE_ACTION:
1530 /* Different visualization because the proportional editing in these editors only looks at
1531 * the x-axis. */
1532 drawPropRange(t);
1533 break;
1534
1535 default:
1536 drawPropCircle(t);
1537 break;
1538 }
1539
1540 drawSnapping(t);
1541
1542 if (region == t->region && t->mode_info && t->mode_info->draw_fn) {
1543 t->mode_info->draw_fn(t);
1544 }
1545}
1546
1551static void drawAutoKeyWarning(TransInfo *t, ARegion *region)
1552{
1553 const char *printable = IFACE_("Auto Keying On");
1554 float printable_size[2];
1555 int xco, yco;
1556 int offset = 0;
1557
1558 const rcti *rect = ED_region_visible_rect(region);
1559
1560 View3D *v3d = nullptr;
1561 Scene *scene = nullptr;
1562 if (t->spacetype == SPACE_VIEW3D) {
1563 v3d = static_cast<View3D *>(t->view);
1564 scene = static_cast<Scene *>(t->scene);
1565 }
1566
1567 const int font_id = BLF_set_default();
1569 font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
1570
1571 /* Check to see if the Navigation Gizmo is enabled. */
1572 if ((t->spacetype != SPACE_VIEW3D) || (v3d == nullptr) ||
1574 {
1575 offset = 10;
1576 }
1577 else {
1578 /* Depending on user MINI_AXIS preference, pad accordingly. */
1579 switch ((eUserpref_MiniAxisType)U.mini_axis_type) {
1581 offset = U.gizmo_size_navigate_v3d;
1582 break;
1584 offset = U.rvisize * std::min((U.pixelsize / U.scale_factor), 1.0f) * 2.5f;
1585 break;
1587 offset = U.rvisize;
1588 break;
1589 }
1590 }
1591
1592 offset *= U.scale_factor;
1593
1594 xco = (rect->xmax - U.widget_unit) - int(printable_size[0]) - offset;
1595 yco = (rect->ymax - U.widget_unit);
1596
1597 /* Warning text (to clarify meaning of overlays)
1598 * - Original color was red to match the icon, but that clashes badly with a less nasty border.
1599 */
1600
1601 float text_color[4], shadow_color[4];
1602 if (v3d && scene) {
1603 ED_view3d_text_colors_get(scene, v3d, text_color, shadow_color);
1604 }
1605 else {
1606 UI_GetThemeColor4fv(TH_TEXT_HI, text_color);
1607 UI_GetThemeColor4fv(TH_BACK, text_color);
1608 }
1609 BLF_color4fv(BLF_default(), text_color);
1611 BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
1612
1613 /* Auto-key recording icon. */
1615
1616 xco -= U.widget_unit;
1617 yco -= int(printable_size[1]) / 2;
1618
1619 UI_icon_draw(xco, yco, ICON_REC);
1620
1622}
1623
1624static void drawTransformPixel(const bContext * /*C*/, ARegion *region, void *arg)
1625{
1626 TransInfo *t = static_cast<TransInfo *>(arg);
1627
1628 if (!transinfo_show_overlay(t, region)) {
1629 return;
1630 }
1631
1632 if (region == t->region) {
1633 Scene *scene = t->scene;
1634 ViewLayer *view_layer = t->view_layer;
1635 BKE_view_layer_synced_ensure(scene, view_layer);
1636 Object *ob = BKE_view_layer_active_object_get(view_layer);
1637
1638 /* Draw auto-key-framing hint in the corner
1639 * - only draw if enabled (advanced users may be distracted/annoyed),
1640 * for objects that will be auto-keyframed (no point otherwise),
1641 * AND only for the active region (as showing all is too overwhelming)
1642 */
1643 if ((U.keying_flag & AUTOKEY_FLAG_NOWARNING) == 0) {
1644 if (region == t->region) {
1645 if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) {
1646 if (ob && blender::animrig::autokeyframe_cfra_can_key(scene, &ob->id)) {
1647 drawAutoKeyWarning(t, region);
1648 }
1649 }
1650 }
1651 }
1652 }
1653}
1654
1656{
1658 PropertyRNA *prop;
1659
1660 bool use_prop_edit = false;
1661 int prop_edit_flag = 0;
1662
1663 /* Save proportional edit settings.
1664 * Skip saving proportional edit if it was not actually used.
1665 * Note that this value is being saved even if the operation is canceled. This is to maintain a
1666 * behavior already used by users. */
1667 if (!(t->options & CTX_NO_PET)) {
1668 if (t->flag & T_PROP_EDIT_ALL) {
1669 if (t->flag & T_PROP_EDIT) {
1670 use_prop_edit = true;
1671 }
1672 if (t->flag & T_PROP_CONNECTED) {
1673 prop_edit_flag |= PROP_EDIT_CONNECTED;
1674 }
1675 if (t->flag & T_PROP_PROJECTED) {
1676 prop_edit_flag |= PROP_EDIT_PROJECTED;
1677 }
1678 }
1679
1680 /* If modal, save settings back in scene if not set as operator argument. */
1681 if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
1682 /* Save settings if not set in operator. */
1683 if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) &&
1684 !RNA_property_is_set(op->ptr, prop))
1685 {
1688
1689 if (t->spacetype == SPACE_GRAPH) {
1690 ts->proportional_fcurve = use_prop_edit;
1691 }
1692 else if (t->spacetype == SPACE_ACTION) {
1693 ts->proportional_action = use_prop_edit;
1694 }
1695 else if (t->options & CTX_MASK) {
1696 ts->proportional_mask = use_prop_edit;
1697 }
1698 else if (obact && obact->mode == OB_MODE_OBJECT) {
1699 ts->proportional_objects = use_prop_edit;
1700 }
1701 else {
1702 if (use_prop_edit) {
1704 }
1705 else {
1706 ts->proportional_edit &= ~PROP_EDIT_USE;
1707 }
1708 }
1709 }
1710
1711 if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) {
1712 ts->proportional_size = RNA_property_is_set(op->ptr, prop) ?
1713 RNA_property_float_get(op->ptr, prop) :
1714 t->prop_size;
1715 }
1716
1717 if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
1718 !RNA_property_is_set(op->ptr, prop))
1719 {
1720 ts->prop_mode = t->prop_mode;
1721 }
1722 }
1723 }
1724
1725 if (t->state == TRANS_CANCEL) {
1726 /* No need to edit operator properties or tool settings if we are canceling the operation.
1727 * These properties must match the original ones. */
1728 return;
1729 }
1730
1731 if (!(t->options & CTX_NO_PET)) {
1732 if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
1733 RNA_property_boolean_set(op->ptr, prop, use_prop_edit);
1734 RNA_boolean_set(op->ptr, "use_proportional_connected", prop_edit_flag & PROP_EDIT_CONNECTED);
1735 RNA_boolean_set(op->ptr, "use_proportional_projected", prop_edit_flag & PROP_EDIT_PROJECTED);
1736 RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
1737 RNA_float_set(op->ptr, "proportional_size", t->prop_size);
1738 }
1739 }
1740
1741 /* Save back mode in case we're in the generic operator. */
1742 if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
1743 RNA_property_enum_set(op->ptr, prop, t->mode);
1744 }
1745
1746 if ((prop = RNA_struct_find_property(op->ptr, "value"))) {
1747 if (RNA_property_array_check(prop)) {
1749 }
1750 else {
1751 RNA_property_float_set(op->ptr, prop, t->values_final[0]);
1752 }
1753 }
1754
1755 /* Save snapping settings. */
1756 if ((prop = RNA_struct_find_property(op->ptr, "snap"))) {
1757 RNA_property_boolean_set(op->ptr, prop, (t->modifiers & MOD_SNAP) != 0);
1758
1759 if ((prop = RNA_struct_find_property(op->ptr, "snap_elements"))) {
1760 RNA_property_enum_set(op->ptr, prop, t->tsnap.mode);
1762 op->ptr, "use_snap_project", (t->tsnap.mode & SCE_SNAP_INDIVIDUAL_PROJECT) != 0);
1763 RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_operation);
1764
1766 RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0);
1767 RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0);
1768 RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0);
1770 op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0);
1771 }
1772
1773 /* Update `ToolSettings` for properties that change during modal. */
1774 if (t->flag & T_MODAL) {
1775 /* Do we check for parameter? */
1777 /* Type is #eSnapFlag, but type must match various snap attributes in #ToolSettings. */
1778 short *snap_flag_ptr;
1779
1780 wmMsgParams_RNA msg_key_params = {{nullptr}};
1781 msg_key_params.ptr = RNA_pointer_create(&t->scene->id, &RNA_ToolSettings, ts);
1782 if ((snap_flag_ptr = transform_snap_flag_from_spacetype_ptr(t, &msg_key_params.prop)) &&
1783 (bool(t->modifiers & MOD_SNAP) != bool(*snap_flag_ptr & SCE_SNAP)))
1784 {
1785 SET_FLAG_FROM_TEST(*snap_flag_ptr, t->modifiers & MOD_SNAP, SCE_SNAP);
1786 WM_msg_publish_rna_params(t->mbus, &msg_key_params);
1787 }
1788 }
1789 }
1790 }
1791
1792 if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
1793 RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
1794 }
1795
1796 if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
1797 if (t->flag & T_MODAL) {
1798 if (t->con.mode & CON_APPLY) {
1799 int orient_axis = constraintModeToIndex(t);
1800 if (orient_axis != -1) {
1801 RNA_property_enum_set(op->ptr, prop, orient_axis);
1802 }
1803 }
1804 else {
1805 RNA_property_enum_set(op->ptr, prop, t->orient_axis);
1806 }
1807 }
1808 }
1809 if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
1810 if (t->flag & T_MODAL) {
1812 }
1813 }
1814
1815 if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) {
1816 short orient_type_set, orient_type_curr;
1817 orient_type_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) :
1818 -1;
1819 orient_type_curr = t->orient[t->orient_curr].type;
1820
1821 if (!ELEM(orient_type_curr, orient_type_set, V3D_ORIENT_CUSTOM_MATRIX)) {
1822 RNA_property_enum_set(op->ptr, prop, orient_type_curr);
1823 orient_type_set = orient_type_curr;
1824 }
1825
1826 if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
1827 !RNA_property_is_set(op->ptr, prop))
1828 {
1829 /* Set the first time to register on redo. */
1830 RNA_property_enum_set(op->ptr, prop, orient_type_set);
1831 RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
1832 }
1833 }
1834
1835 if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
1836 bool constraint_axis[3] = {false, false, false};
1837 if (t->con.mode & CON_APPLY) {
1838 if (t->con.mode & CON_AXIS0) {
1839 constraint_axis[0] = true;
1840 }
1841 if (t->con.mode & CON_AXIS1) {
1842 constraint_axis[1] = true;
1843 }
1844 if (t->con.mode & CON_AXIS2) {
1845 constraint_axis[2] = true;
1846 }
1847 RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
1848 }
1849 else {
1850 RNA_property_unset(op->ptr, prop);
1851 }
1852 }
1853
1854 {
1855 const char *prop_id = nullptr;
1856 bool prop_state = true;
1857 if (t->mode == TFM_SHRINKFATTEN) {
1858 prop_id = "use_even_offset";
1859 prop_state = false;
1860 }
1861
1862 if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
1863 RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) == 0) == prop_state);
1864 }
1865 }
1866
1867 if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
1869 op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
1870 }
1871}
1872
1873bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
1874{
1875 int options = 0;
1876 PropertyRNA *prop;
1877
1878 mode = transform_mode_really_used(C, eTfmMode(mode));
1879
1880 t->context = C;
1881
1882 /* Added initialize, for external calls to set stuff in TransInfo, like undo string. */
1883
1884 t->state = TRANS_STARTING;
1885
1886 if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) &&
1887 RNA_property_is_set(op->ptr, prop))
1888 {
1889 if (RNA_property_boolean_get(op->ptr, prop)) {
1891 }
1892 }
1893
1894 if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) &&
1895 RNA_property_is_set(op->ptr, prop))
1896 {
1897 if (RNA_property_boolean_get(op->ptr, prop)) {
1899 }
1900 }
1901
1902 if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) &&
1903 RNA_property_is_set(op->ptr, prop))
1904 {
1905 if (RNA_property_boolean_get(op->ptr, prop)) {
1907 }
1908 }
1909
1910 if ((prop = RNA_struct_find_property(op->ptr, "view2d_edge_pan")) &&
1911 RNA_property_is_set(op->ptr, prop))
1912 {
1913 if (RNA_property_boolean_get(op->ptr, prop)) {
1915 }
1916 }
1917
1919
1920 t->mode = eTfmMode(mode);
1921
1922 /* Needed to translate tweak events to mouse buttons. */
1924 t->is_launch_event_drag = event ? (event->val == KM_CLICK_DRAG) : false;
1925
1926 unit_m3(t->spacemtx);
1927
1928 initTransInfo(C, t, op, event);
1929
1930 if (t->spacetype == SPACE_VIEW3D) {
1937 }
1938 else if (ELEM(t->spacetype,
1940 SPACE_CLIP,
1941 SPACE_NODE,
1944 SPACE_SEQ))
1945 {
1950 }
1951
1952 create_trans_data(C, t); /* Make #TransData structs from selection. */
1953
1954 if (t->data_len_all == 0) {
1955 postTrans(C, t);
1956 return false;
1957 }
1958
1959 /* When proportional editing is enabled, data_len_all can be non zero when
1960 * nothing is selected, if this is the case we can end the transform early.
1961 *
1962 * By definition transform-data has selected items in beginning,
1963 * so only the first item in each container needs to be checked
1964 * when looking for the presence of selected data. */
1965 if (t->flag & T_PROP_EDIT) {
1966 bool has_selected_any = false;
1968 if (tc->data->flag & TD_SELECTED) {
1969 has_selected_any = true;
1970 break;
1971 }
1972 }
1973
1974 if (!has_selected_any) {
1975 postTrans(C, t);
1976 return false;
1977 }
1978 }
1979
1980 if (event) {
1981 /* Keymap for shortcut header prints. */
1983
1984 /* Stupid code to have Ctrl-Click on gizmo work ok.
1985 *
1986 * Do this only for translation/rotation/resize because only these
1987 * modes are available from gizmo and doing such check could
1988 * lead to keymap conflicts for other modes (see #31584)
1989 */
1991 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &t->keymap->items) {
1992 if (kmi->flag & KMI_INACTIVE) {
1993 continue;
1994 }
1995
1996 if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) {
1997 if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) &&
1998 (event->modifier & KM_CTRL)) ||
1999 (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) &&
2000 (event->modifier & KM_SHIFT)) ||
2001 (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && (event->modifier & KM_ALT)) ||
2002 ((kmi->type == EVT_OSKEY) && (event->modifier & KM_OSKEY)))
2003 {
2005 }
2006 break;
2007 }
2008 }
2009 }
2010 if (t->data_type == &TransConvertType_Node) {
2011 /* Set the initial auto-attach flag based on whether the chosen keymap key is pressed at the
2012 * start of the operator. */
2014 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &t->keymap->items) {
2015 if (kmi->flag & KMI_INACTIVE) {
2016 continue;
2017 }
2018
2019 if (kmi->propvalue == TFM_MODAL_NODE_ATTACH_OFF && kmi->val == KM_PRESS) {
2020 if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) &&
2021 (event->modifier & KM_CTRL)) ||
2022 (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) &&
2023 (event->modifier & KM_SHIFT)) ||
2024 (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && (event->modifier & KM_ALT)) ||
2025 ((kmi->type == EVT_OSKEY) && (event->modifier & KM_OSKEY)))
2026 {
2027 t->modifiers &= ~MOD_NODE_ATTACH;
2028 }
2029 break;
2030 }
2031 }
2032 }
2033 }
2034
2035 initSnapping(t, op); /* Initialize snapping data AFTER mode flags. */
2036
2037 /* EVIL! pose-mode code can switch translation to rotate when 1 bone is selected.
2038 * will be removed (ton). */
2039
2040 /* EVIL2: we gave as argument also texture space context bit... was cleared. */
2041
2042 /* EVIL3: extend mode for animation editors also switches modes...
2043 * but is best way to avoid duplicate code. */
2044 mode = t->mode;
2045
2047 calculateCenter(t);
2048
2049 if (event) {
2050 /* Initialize accurate transform to settings requested by keymap. */
2051 bool use_accurate = false;
2052 if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) &&
2053 RNA_property_is_set(op->ptr, prop))
2054 {
2055 if (RNA_property_boolean_get(op->ptr, prop)) {
2056 use_accurate = true;
2057 }
2058 }
2059
2060 initMouseInput(t, &t->mouse, t->center2d, t->mval, use_accurate);
2061 }
2062
2063 transform_mode_init(t, op, mode);
2064
2065 if (t->state == TRANS_CANCEL) {
2066 postTrans(C, t);
2067 return false;
2068 }
2069
2070 /* Transformation axis from operator. */
2071 if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) &&
2072 RNA_property_is_set(op->ptr, prop))
2073 {
2074 t->orient_axis = RNA_property_enum_get(op->ptr, prop);
2075 }
2076 if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) &&
2077 RNA_property_is_set(op->ptr, prop))
2078 {
2080 }
2081
2082 /* Constraint init from operator. */
2083 if (t->con.mode & CON_APPLY) {
2084 setUserConstraint(t, t->con.mode, "%s");
2085 }
2086
2087 /* Don't write into the values when non-modal because they are already set from operator redo
2088 * values. */
2089 if (t->flag & T_MODAL) {
2090 /* Setup the mouse input with initial values. */
2091 applyMouseInput(t, &t->mouse, t->mouse.imval, t->values);
2092 }
2093
2094 if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
2095 if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
2096
2098 BMEditMesh *em = nullptr; /* BKE_editmesh_from_object(t->obedit); */
2099 bool do_skip = false;
2100
2101 /* Currently only used for two of three most frequent transform ops,
2102 * can include more ops.
2103 * Note that scaling cannot be included here,
2104 * non-uniform scaling will affect normals. */
2106 if (em->bm->totvertsel == em->bm->totvert) {
2107 /* No need to invalidate if whole mesh is selected. */
2108 do_skip = true;
2109 }
2110 }
2111
2112 if (t->flag & T_MODAL) {
2113 RNA_property_boolean_set(op->ptr, prop, false);
2114 }
2115 else if (!do_skip) {
2116 const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
2117 if (preserve_clnor) {
2119 t->flag |= T_CLNOR_REBUILD;
2120 }
2121 BM_lnorspace_invalidate(em->bm, true);
2122 }
2123 }
2124 }
2125 }
2126
2127 t->context = nullptr;
2128
2129 return true;
2130}
2131
2133{
2134 t->context = C;
2135
2136 if (t->redraw == TREDRAW_HARD) {
2138 if (t->mode_info) {
2139 t->mode_info->transform_fn(t); /* Calls #recalc_data(). */
2140 }
2141 }
2142
2143 if (t->redraw & TREDRAW_SOFT) {
2144 viewRedrawForce(C, t);
2145 }
2146
2148
2149 /* If auto confirm is on, break after one pass. */
2150 if (t->options & CTX_AUTOCONFIRM) {
2151 t->state = TRANS_CONFIRM;
2152 }
2153
2154 t->context = nullptr;
2155}
2156
2158{
2159 int exit_code = OPERATOR_RUNNING_MODAL;
2160
2161 t->context = C;
2162
2164 /* Handle restoring objects. */
2165 if (t->state == TRANS_CANCEL) {
2166 exit_code = OPERATOR_CANCELLED;
2167 restoreTransObjects(t); /* Calls #recalc_data(). */
2168 }
2169 else {
2170 if (t->flag & T_CLNOR_REBUILD) {
2172 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
2173 BM_lnorspace_rebuild(em->bm, true);
2174 }
2175 }
2176 exit_code = OPERATOR_FINISHED;
2177 }
2178
2179 /* Does insert keyframes, and clears base flags; doesn't read `transdata`. */
2181
2182 /* Free data, also handles overlap [in freeTransCustomData()]. */
2183 postTrans(C, t);
2184
2185 /* Send events out for redraws. */
2186 viewRedrawPost(C, t);
2187
2188 viewRedrawForce(C, t);
2189
2191 }
2192
2193 t->context = nullptr;
2194
2195 return exit_code;
2196}
2197
2199{
2200 /* Currently only checks for editmode. */
2201 if (t->flag & T_EDIT) {
2202 if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
2204 {
2205 /* Not all editmode supports axis-matrix. */
2206 return true;
2207 }
2208 }
2209
2210 return false;
2211}
2212
2213bool transform_apply_matrix(TransInfo *t, float mat[4][4])
2214{
2215 if (t->mode_info && t->mode_info->transform_matrix_fn) {
2216 t->mode_info->transform_matrix_fn(t, mat);
2217 return true;
2218 }
2219 return false;
2220}
2221
2222void transform_final_value_get(const TransInfo *t, float *value, const int value_num)
2223{
2224 memcpy(value, t->values_final, sizeof(float) * value_num);
2225}
Functions to insert, delete or modify keyframes.
WorkSpace * CTX_wm_workspace(const bContext *C)
Mask * CTX_data_edit_mask(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
void BKE_editmesh_lnorspace_update(BMEditMesh *em)
Definition editmesh.cc:208
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
void BKE_mask_coord_to_image(struct Image *image, struct ImageUser *iuser, float r_co[2], const float co[2])
void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2])
void BKE_workspace_status_clear(WorkSpace *workspace)
Definition workspace.cc:649
int BLF_set_default()
void BLF_shadow(int fontid, FontShadowType type, const float rgba[4]=nullptr)
Definition blf.cc:902
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:778
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:488
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:393
int BLF_default()
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL()
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void unit_m3(float m[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m4(float m1[4][4], const float m2[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
#define ARRAY_SIZE(arr)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ SACTION_DRAWTIME
@ OB_MODE_OBJECT
@ OB_MBALL
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ UVCALC_TRANSFORM_CORRECT_SLIDE
@ UVCALC_TRANSFORM_CORRECT
@ PROP_EDIT_PROJECTED
@ PROP_EDIT_USE
@ PROP_EDIT_CONNECTED
@ SCE_SNAP
@ PROP_MODE_MAX
eSnapTargetOP
@ SCE_SNAP_TARGET_NOT_ACTIVE
@ SCE_SNAP_TARGET_NOT_NONEDITED
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_NOT_EDITED
@ SCE_SNAP_INDIVIDUAL_PROJECT
@ SCE_SNAP_TO_INCREMENT
@ SCE_SNAP_TO_GRID
@ RGN_TYPE_WINDOW
#define RGN_TYPE_ANY
@ SI_COORDFLOATS
@ SNODE_INSERTOFS_DIR_RIGHT
@ SNODE_INSERTOFS_DIR_LEFT
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NODE
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
#define SPACE_TYPE_ANY
@ AUTOKEY_FLAG_NOWARNING
eUserpref_MiniAxisType
@ USER_MINI_AXIS_TYPE_GIZMO
@ USER_MINI_AXIS_TYPE_MINIMAL
@ USER_MINI_AXIS_TYPE_NONE
@ RV3D_NAVIGATING
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_GIZMO_HIDE
@ V3D_GIZMO_HIDE_NAVIGATE
@ RV3D_ORTHO
@ V3D_HIDE_OVERLAYS
@ V3D_ORIENT_NORMAL
@ V3D_ORIENT_CUSTOM_MATRIX
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
MovieClip * ED_space_clip_get_clip(const SpaceClip *sc)
bool ED_space_clip_check_show_trackedit(const SpaceClip *sc)
bool ED_space_clip_check_show_maskedit(const SpaceClip *sc)
void ED_space_clip_get_aspect(const SpaceClip *sc, float *r_aspx, float *r_aspy)
void ED_clip_point_stable_pos__reverse(const SpaceClip *sc, const ARegion *region, const float co[2], float r_co[2])
the reverse of ED_clip_point_stable_pos(), gets the marker region coords. better name here?...
void ED_space_clip_get_aspect_dimension_aware(const SpaceClip *sc, float *r_aspx, float *r_aspy)
void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height)
void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
void ED_image_point_pos__reverse(SpaceImage *sima, const ARegion *region, const float co[2], float r_co[2])
#define NUM_MODAL_INCREMENT_DOWN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:312
#define NUM_MODAL_INCREMENT_UP
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
const rcti * ED_region_visible_rect(ARegion *region)
Definition area.cc:4010
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
#define REGION_DRAW_POST_PIXEL
eTfmMode
@ TFM_RESIZE
@ TFM_EDGE_SLIDE
@ TFM_SHRINKFATTEN
@ TFM_VERT_SLIDE
@ TFM_ROTATION
@ TFM_TRANSLATION
@ TFM_NORMAL_ROTATION
@ TFM_DUMMY
@ TFM_TRACKBALL
bool ED_uvedit_live_unwrap_timer_check(const wmTimer *timer)
eV3DProjTest
Definition ED_view3d.hh:265
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:266
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:243
void ED_view3d_win_to_delta(const ARegion *region, const float xy_delta[2], float zfac, float r_out[3])
void ED_view3d_text_colors_get(const Scene *scene, const View3D *v3d, float r_text_color[4], float r_shadow_color[4])
eV3DProjStatus ED_view3d_project_int_global(const ARegion *region, const float co[3], int r_co[2], eV3DProjTest flag)
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:161
#define C
Definition RandGen.cpp:29
void UI_icon_draw(float x, float y, int icon_id)
@ TH_BACK
@ TH_TEXT_HI
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_view2d_view_to_region(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL()
Definition view2d.cc:1718
#define ND_SEQUENCER
Definition WM_types.hh:404
#define NC_GEOM
Definition WM_types.hh:360
@ WM_EVENT_IS_REPEAT
Definition WM_types.hh:650
#define ND_DATA
Definition WM_types.hh:475
#define NC_ANIMATION
Definition WM_types.hh:355
@ KM_PRESS
Definition WM_types.hh:284
@ KM_CLICK_DRAG
Definition WM_types.hh:292
@ KM_RELEASE
Definition WM_types.hh:285
#define NC_MOVIECLIP
Definition WM_types.hh:364
#define NC_SCENE
Definition WM_types.hh:345
#define ND_SPACE_NODE_VIEW
Definition WM_types.hh:502
#define ND_POSE
Definition WM_types.hh:425
#define NA_EDITED
Definition WM_types.hh:550
#define NC_GPENCIL
Definition WM_types.hh:366
#define ND_NLA
Definition WM_types.hh:464
#define ND_TRANSFORM
Definition WM_types.hh:423
#define NC_MASK
Definition WM_types.hh:365
#define ND_KEYS
Definition WM_types.hh:430
@ KM_CTRL
Definition WM_types.hh:256
@ KM_ALT
Definition WM_types.hh:257
@ KM_OSKEY
Definition WM_types.hh:259
@ KM_SHIFT
Definition WM_types.hh:255
#define ND_KEYFRAME
Definition WM_types.hh:461
#define NC_OBJECT
Definition WM_types.hh:346
#define NC_SPACE
Definition WM_types.hh:359
void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all)
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition btGjkEpa3.h:78
#define printf
CCL_NAMESPACE_BEGIN struct Options options
void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag)
bool checkUseAxisMatrix(TransInfo *t)
static bool transform_modal_item_poll(const wmOperator *op, int value)
void transformApply(bContext *C, TransInfo *t)
static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
static bool transinfo_show_overlay(TransInfo *t, ARegion *region)
static void drawTransformPixel(const bContext *, ARegion *region, void *arg)
void setTransformViewAspect(TransInfo *t, float r_aspect[3])
bool transdata_check_local_islands(TransInfo *t, short around)
void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag)
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
void removeAspectRatio(TransInfo *t, float vec[2])
wmKeyMap * transform_modal_keymap(wmKeyConfig *keyconf)
void transform_final_value_get(const TransInfo *t, float *value, const int value_num)
bool transform_apply_matrix(TransInfo *t, float mat[4][4])
static void viewRedrawPost(bContext *C, TransInfo *t)
static void viewRedrawForce(const bContext *C, TransInfo *t)
static void drawAutoKeyWarning(TransInfo *t, ARegion *region)
void setTransformViewMatrices(TransInfo *t)
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
void transform_view_vector_calc(const TransInfo *t, const float focus[3], float r_vec[3])
int transformEvent(TransInfo *t, wmOperator *op, const wmEvent *event)
void projectIntView(TransInfo *t, const float vec[3], int adr[2])
void applyAspectRatio(TransInfo *t, float vec[2])
int transformEnd(bContext *C, TransInfo *t)
static void drawTransformView(const bContext *, ARegion *region, void *arg)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
bGPdata * ED_gpencil_data_get_active(const bContext *C)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
bool is_autokey_on(const Scene *scene)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
VecBase< float, 2 > float2
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_array_check(PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
void * regiondata
struct ARegionType * type
int totvert
int totvertsel
void * first
blender::float2 imval
Definition transform.hh:383
bool precision
Definition transform.hh:387
float persmat[4][4]
float persinv[4][4]
float viewmat[4][4]
float viewinv[4][4]
ListBase spacedata
struct MovieClipUser user
struct MovieClip * clip
struct ImageUser iuser
struct Image * image
eTConstraint mode
Definition transform.hh:351
struct TransInfo::@565 orient[3]
eTfmMode mode
Definition transform.hh:517
short around
Definition transform.hh:580
TransModeInfo * mode_info
Definition transform.hh:518
wmMsgBus * mbus
Definition transform.hh:650
void * view
Definition transform.hh:647
char spacetype
Definition transform.hh:582
float viewinv[4][4]
Definition transform.hh:575
int orient_axis
Definition transform.hh:640
short persp
Definition transform.hh:579
ViewOpsData * vod
Definition transform.hh:673
eRedrawFlag redraw
Definition transform.hh:529
int data_len_all
Definition transform.hh:510
wmTimer * animtimer
Definition transform.hh:657
float prop_size
Definition transform.hh:546
void * draw_handle_cursor
Definition transform.hh:668
float center2d[2]
Definition transform.hh:557
float values[4]
Definition transform.hh:624
TransSnap tsnap
Definition transform.hh:537
float zfac
Definition transform.hh:665
eTState state
Definition transform.hh:527
ToolSettings * settings
Definition transform.hh:656
eTModifier modifiers
Definition transform.hh:525
NumInput num
Definition transform.hh:540
float aspect[3]
Definition transform.hh:553
short prop_mode
Definition transform.hh:621
Scene * scene
Definition transform.hh:654
eTOType orient_curr
Definition transform.hh:613
ViewLayer * view_layer
Definition transform.hh:655
eTFlag flag
Definition transform.hh:523
ARegion * region
Definition transform.hh:652
MouseInput mouse
Definition transform.hh:543
float persmat[4][4]
Definition transform.hh:577
short obedit_type
Definition transform.hh:584
float viewmat[4][4]
Definition transform.hh:573
void * draw_handle_pixel
Definition transform.hh:667
float values_final[4]
Definition transform.hh:632
TransCon con
Definition transform.hh:534
bContext * context
Definition transform.hh:649
bool is_launch_event_drag
Definition transform.hh:604
wmKeyMap * keymap
Definition transform.hh:659
short launch_event
Definition transform.hh:599
float center_global[3]
Definition transform.hh:555
blender::float2 mval
Definition transform.hh:663
float spacemtx[3][3]
Definition transform.hh:592
int orient_axis_ortho
Definition transform.hh:642
TransConvertTypeInfo * data_type
Definition transform.hh:513
eTContext options
Definition transform.hh:521
float persinv[4][4]
Definition transform.hh:578
ScrArea * area
Definition transform.hh:651
short type
Definition transform.hh:609
void * draw_handle_view
Definition transform.hh:666
void(* transform_matrix_fn)(TransInfo *, float[4][4])
void(* draw_fn)(TransInfo *)
void(* transform_fn)(TransInfo *)
enum eRedrawFlag(* handle_event_fn)(TransInfo *, const wmEvent *)
TransSnapPoint * selectedPoint
Definition transform.hh:331
eTSnap status
Definition transform.hh:318
eSnapSourceOP source_operation
Definition transform.hh:314
eSnapMode mode
Definition transform.hh:312
eSnapMode target_type
Definition transform.hh:321
eSnapTargetOP target_operation
Definition transform.hh:316
int ymax
int xmax
short val
Definition WM_types.hh:724
short prev_type
Definition WM_types.hh:777
int mval[2]
Definition WM_types.hh:728
uint8_t modifier
Definition WM_types.hh:739
eWM_EventFlag flag
Definition WM_types.hh:753
short prev_val
Definition WM_types.hh:779
short type
Definition WM_types.hh:722
void * customdata
Definition WM_types.hh:772
bool(* poll_modal_item)(const struct wmOperator *op, int value)
const PropertyRNA * prop
wmKeyMap * modalkeymap
Definition WM_types.hh:1098
struct wmOperatorType * type
struct PointerRNA * ptr
void calculateCenter(TransInfo *t)
void postTrans(bContext *C, TransInfo *t)
@ SNAP_TARGET_FOUND
Definition transform.hh:177
void applyMouseInput(TransInfo *t, MouseInput *mi, const blender::float2 &mval, float output[3])
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
@ CON_APPLY
Definition transform.hh:193
@ CON_AXIS1
Definition transform.hh:196
@ CON_AXIS0
Definition transform.hh:195
@ CON_AXIS2
Definition transform.hh:197
eTContext
Definition transform.hh:61
@ CTX_MOVIECLIP
Definition transform.hh:70
@ CTX_PAINT_CURVE
Definition transform.hh:72
@ CTX_AUTOCONFIRM
Definition transform.hh:78
@ CTX_CURSOR
Definition transform.hh:66
@ CTX_POSE_BONE
Definition transform.hh:73
@ CTX_OBJECT
Definition transform.hh:71
@ CTX_GPENCIL_STROKES
Definition transform.hh:68
@ CTX_MASK
Definition transform.hh:69
@ CTX_TEXTURE_SPACE
Definition transform.hh:74
@ CTX_VIEW2D_EDGE_PAN
Definition transform.hh:84
@ CTX_NO_PET
Definition transform.hh:77
@ CTX_CAMERA
Definition transform.hh:65
@ MOD_SNAP_INVERT
Definition transform.hh:164
@ MOD_EDIT_SNAP_SOURCE
Definition transform.hh:168
@ MOD_CONSTRAINT_SELECT_AXIS
Definition transform.hh:161
@ MOD_NODE_ATTACH
Definition transform.hh:166
@ MOD_PRECISION
Definition transform.hh:162
@ MOD_SNAP_FORCED
Definition transform.hh:167
@ MOD_CONSTRAINT_SELECT_PLANE
Definition transform.hh:165
@ MOD_SNAP
Definition transform.hh:163
void resetTransRestrictions(TransInfo *t)
void initMouseInput(TransInfo *t, MouseInput *mi, const blender::float2 &center, const blender::float2 &mval, bool precision)
@ TREDRAW_NOTHING
Definition transform.hh:215
@ TREDRAW_SOFT
Definition transform.hh:216
@ TREDRAW_HARD
Definition transform.hh:217
@ TFM_MODAL_EDIT_SNAP_SOURCE_OFF
Definition transform.hh:292
@ TFM_MODAL_AUTOIK_LEN_INC
Definition transform.hh:271
@ TFM_MODAL_PROPSIZE
Definition transform.hh:278
@ TFM_MODAL_AXIS_Y
Definition transform.hh:256
@ TFM_MODAL_RESIZE
Definition transform.hh:251
@ TFM_MODAL_AUTOCONSTRAINT
Definition transform.hh:282
@ TFM_MODAL_CONFIRM
Definition transform.hh:248
@ TFM_MODAL_ADD_SNAP
Definition transform.hh:262
@ TFM_MODAL_SNAP_TOGGLE
Definition transform.hh:254
@ TFM_MODAL_PLANE_X
Definition transform.hh:258
@ TFM_MODAL_TRACKBALL
Definition transform.hh:288
@ TFM_MODAL_REMOVE_SNAP
Definition transform.hh:263
@ TFM_MODAL_ROTATE_NORMALS
Definition transform.hh:289
@ TFM_MODAL_PASSTHROUGH_NAVIGATE
Definition transform.hh:294
@ TFM_MODAL_CONS_OFF
Definition transform.hh:261
@ TFM_MODAL_AUTOCONSTRAINTPLANE
Definition transform.hh:283
@ TFM_MODAL_VERT_EDGE_SLIDE
Definition transform.hh:287
@ TFM_MODAL_AXIS_X
Definition transform.hh:255
@ TFM_MODAL_ROTATE
Definition transform.hh:250
@ TFM_MODAL_AUTOIK_LEN_DEC
Definition transform.hh:272
@ TFM_MODAL_PROPSIZE_UP
Definition transform.hh:269
@ TFM_MODAL_PLANE_Y
Definition transform.hh:259
@ TFM_MODAL_SNAP_INV_ON
Definition transform.hh:252
@ TFM_MODAL_AXIS_Z
Definition transform.hh:257
@ TFM_MODAL_INSERTOFS_TOGGLE_DIR
Definition transform.hh:280
@ TFM_MODAL_PLANE_Z
Definition transform.hh:260
@ TFM_MODAL_NODE_ATTACH_OFF
Definition transform.hh:275
@ TFM_MODAL_CANCEL
Definition transform.hh:247
@ TFM_MODAL_NODE_ATTACH_ON
Definition transform.hh:274
@ TFM_MODAL_PROPSIZE_DOWN
Definition transform.hh:270
@ TFM_MODAL_PRECISION
Definition transform.hh:285
@ TFM_MODAL_TRANSLATE
Definition transform.hh:249
@ TFM_MODAL_SNAP_INV_OFF
Definition transform.hh:253
@ TFM_MODAL_EDIT_SNAP_SOURCE_ON
Definition transform.hh:291
@ O_DEFAULT
Definition transform.hh:233
@ T_RELEASE_CONFIRM
Definition transform.hh:123
@ T_CLNOR_REBUILD
Definition transform.hh:133
@ T_MODAL
Definition transform.hh:118
@ T_AUTOIK
Definition transform.hh:108
@ T_PROP_CONNECTED
Definition transform.hh:99
@ T_ALT_TRANSFORM
Definition transform.hh:126
@ T_NO_MIRROR
Definition transform.hh:111
@ T_PROP_EDIT
Definition transform.hh:98
@ T_2D_EDIT
Definition transform.hh:104
@ T_NO_CONSTRAINT
Definition transform.hh:95
@ T_EDIT
Definition transform.hh:91
@ T_PROP_PROJECTED
Definition transform.hh:100
void resetTransModal(TransInfo *t)
void restoreTransObjects(TransInfo *t)
@ TRANS_CONFIRM
Definition transform.hh:209
@ TRANS_STARTING
Definition transform.hh:207
@ TRANS_RUNNING
Definition transform.hh:208
@ TRANS_CANCEL
Definition transform.hh:210
void calculatePropRatio(TransInfo *t)
#define T_PROP_EDIT_ALL
Definition transform.hh:157
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void drawConstraint(TransInfo *t)
void drawPropCircle(TransInfo *t)
void setUserConstraint(TransInfo *t, int mode, const char text_[])
int constraintModeToIndex(const TransInfo *t)
void postSelectConstraint(TransInfo *t)
void stopConstraint(TransInfo *t)
void setLocalConstraint(TransInfo *t, int mode, const char text[])
void drawPropRange(TransInfo *t)
void initSelectConstraint(TransInfo *t)
void selectConstraint(TransInfo *t)
void transform_autoik_update(TransInfo *t, short mode)
void special_aftertrans_update(bContext *C, TransInfo *t)
void sort_trans_data_dist(TransInfo *t)
void create_trans_data(bContext *C, TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
TransConvertTypeInfo TransConvertType_MeshUV
TransConvertTypeInfo TransConvertType_Tracking
TransConvertTypeInfo TransConvertType_Node
TransConvertTypeInfo TransConvertType_SequencerImage
TransConvertTypeInfo TransConvertType_Mesh
@ TD_SELECTED
#define T_PROP_SIZE_MIN
#define T_PROP_SIZE_MAX
bool transform_draw_cursor_poll(bContext *C)
void transform_draw_cursor_draw(bContext *, int x, int y, void *customdata)
void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t)
void transform_gizmo_3d_model_from_constraint_and_mode_restore(TransInfo *t)
void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
bool transform_mode_is_changeable(const int mode)
eTfmMode transform_mode_really_used(bContext *C, eTfmMode mode)
transform modes used by different operators.
void transform_mode_snap_source_init(TransInfo *t, wmOperator *op)
void transform_orientations_current_set(TransInfo *t, const short orient_index)
bool transformModeUseSnap(const TransInfo *t)
void addSnapPoint(TransInfo *t)
bool validSnap(const TransInfo *t)
eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event)
void removeSnapPoint(TransInfo *t)
void transform_snap_flag_from_modifiers_set(TransInfo *t)
short * transform_snap_flag_from_spacetype_ptr(TransInfo *t, const PropertyRNA **r_prop=nullptr)
void initSnapping(TransInfo *t, wmOperator *op)
void drawSnapping(TransInfo *t)
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *)
Definition wm_draw.cc:1533
int WM_userdef_event_type_from_keymap_type(int kmitype)
void WM_window_status_area_tag_redraw(wmWindow *win)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
#define ISMOUSE_MOTION(event_type)
@ EVT_OKEY
@ TIMER
@ EVT_MODAL_MAP
@ EVT_RIGHTCTRLKEY
@ EVT_CKEY
@ EVT_OSKEY
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ EVT_RIGHTALTKEY
@ EVT_PADMINUS
@ EVT_LEFTALTKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_PADPLUSKEY
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:933
wmKeyMap * WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap)
void WM_msg_publish_rna_params(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
uint8_t flag
Definition wm_window.cc:138