Blender V4.3
transform_generics.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_blenlib.h"
12#include "BLI_math_matrix.h"
13#include "BLI_math_rotation.h"
14#include "BLI_rand.h"
15#include "BLI_time.h"
16
17#include "BLT_translation.hh"
18
19#include "RNA_access.hh"
20
21#include "BKE_brush.hh"
22#include "BKE_context.hh"
23#include "BKE_layer.hh"
24#include "BKE_mask.h"
25#include "BKE_modifier.hh"
26#include "BKE_paint.hh"
27
28#include "SEQ_transform.hh"
29
30#include "ED_clip.hh"
31#include "ED_image.hh"
32#include "ED_object.hh"
33#include "ED_screen.hh"
34#include "ED_space_api.hh"
35#include "ED_uvedit.hh"
36
37#include "WM_api.hh"
38
39#include "UI_view2d.hh"
40
41#include "SEQ_sequencer.hh"
42
43#include "transform.hh"
44#include "transform_convert.hh"
45#include "transform_gizmo.hh"
47#include "transform_snap.hh"
48
49using namespace blender;
50
51/* ************************** GENERICS **************************** */
52
57
59{
60 t->flag &= ~T_ALL_RESTRICTIONS;
61}
62
63static void *t_view_get(TransInfo *t)
64{
65 if (t->spacetype == SPACE_VIEW3D) {
66 View3D *v3d = static_cast<View3D *>(t->area->spacedata.first);
67 return (void *)v3d;
68 }
69 if (t->region) {
70 return (void *)&t->region->v2d;
71 }
72 return nullptr;
73}
74
75static int t_around_get(TransInfo *t)
76{
77 if (t->flag & T_OVERRIDE_CENTER) {
78 /* Avoid initialization of individual origins (#V3D_AROUND_LOCAL_ORIGINS). */
80 }
81
82 ScrArea *area = t->area;
83 switch (t->spacetype) {
84 case SPACE_VIEW3D: {
85 if (t->mode == TFM_BEND) {
86 /* Bend always uses the cursor. */
87 return V3D_AROUND_CURSOR;
88 }
90 }
91 case SPACE_IMAGE: {
92 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
93 return sima->around;
94 }
95 case SPACE_GRAPH: {
96 SpaceGraph *sipo = static_cast<SpaceGraph *>(area->spacedata.first);
97 return sipo->around;
98 }
99 case SPACE_CLIP: {
100 SpaceClip *sclip = static_cast<SpaceClip *>(area->spacedata.first);
101 return sclip->around;
102 }
103 case SPACE_SEQ: {
106 }
107 break;
108 }
109 default:
110 break;
111 }
112
114}
115
116void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
117{
118 Scene *sce = CTX_data_scene(C);
119 ViewLayer *view_layer = CTX_data_view_layer(C);
120 BKE_view_layer_synced_ensure(sce, view_layer);
121 Object *obact = BKE_view_layer_active_object_get(view_layer);
122 const eObjectMode object_mode = eObjectMode(obact ? obact->mode : OB_MODE_OBJECT);
124 ARegion *region = CTX_wm_region(C);
125 ScrArea *area = CTX_wm_area(C);
126
127 PropertyRNA *prop;
128
129 t->mbus = CTX_wm_message_bus(C);
131 t->scene = sce;
132 t->view_layer = view_layer;
133 t->area = area;
134 t->region = region;
135 t->settings = ts;
136 t->reports = op ? op->reports : nullptr;
137
138 t->helpline = HLP_NONE;
139
140 t->flag = eTFlag(0);
141
142 if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) &&
144 {
145 t->obedit_type = obact->type;
146 }
147 else {
148 t->obedit_type = -1;
149 }
150
151 if (t->options & CTX_CURSOR) {
152 /* Cursor should always use the drag start as the combination of click-drag to place & move
153 * doesn't work well if the click location isn't used when transforming. */
155 }
156
157 /* Many kinds of transform only use a single handle. */
158 if (t->data_container == nullptr) {
159 t->data_container = static_cast<TransDataContainer *>(
160 MEM_callocN(sizeof(*t->data_container), __func__));
161 t->data_container_len = 1;
162 }
163
164 t->redraw = TREDRAW_HARD; /* Redraw first time. */
165
166 float2 mval;
167 if (event) {
168 if (t->flag & T_EVENT_DRAG_START) {
169 WM_event_drag_start_mval_fl(event, region, mval);
170 }
171 else {
172 mval = float2(event->mval);
173 }
174 }
175 else {
176 mval = float2(0, 0);
177 }
178
179 t->mval = mval;
180
181 /* Initialize this mouse variable in advance as it is required by
182 * `transform_convert_frame_side_dir_get` which is called before `initMouseInput`. */
183 t->mouse.imval = mval;
184
185 t->mode_info = nullptr;
186
187 t->data_len_all = 0;
188
190
191 unit_m3(t->mat);
192
193 /* Default to rotate on the Z axis. */
194 t->orient_axis = 2;
195 t->orient_axis_ortho = 1;
196
197 /* If there's an event, we're modal. */
198 if (event) {
199 t->flag |= T_MODAL;
200 }
201
202 /* Crease needs edge flag. */
205 }
206
207 t->remove_on_cancel = false;
208
209 if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) &&
210 RNA_property_is_set(op->ptr, prop))
211 {
212 if (RNA_property_boolean_get(op->ptr, prop)) {
213 t->remove_on_cancel = true;
214 }
215 }
216
217 /* Grease Pencil editing context. */
218 if (t->obedit_type == OB_GREASE_PENCIL && object_mode == OB_MODE_EDIT &&
219 (area->spacetype == SPACE_VIEW3D))
220 {
222 }
223
224 /* Assign the space type, some exceptions for running in different mode. */
225 if (area == nullptr) {
226 /* Background mode. */
228 }
229 else if (((region == nullptr) || (region->regiondata == nullptr)) &&
230 (area->spacetype == SPACE_VIEW3D))
231 {
232 /* Running the operator through the text editor where e.g. `area.type` was
233 * set to 'VIEW_3D' but the viewport was not updated. */
235 }
236 else {
237 /* Normal operation. */
238 t->spacetype = area->spacetype;
239 }
240
241 /* Handle #T_ALT_TRANSFORM initialization, we may use for different operators. */
242 if (op) {
243 const char *prop_id = nullptr;
244 if (t->mode == TFM_SHRINKFATTEN) {
245 prop_id = "use_even_offset";
246 }
247
248 if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
250 }
251 }
252
253 if (t->spacetype == SPACE_VIEW3D) {
255
256 t->animtimer = (animscreen) ? animscreen->animtimer : nullptr;
257
259 t->flag |= T_V3D_ALIGN;
260 }
261
262 if ((object_mode & OB_MODE_ALL_PAINT) || (object_mode & OB_MODE_SCULPT_CURVES)) {
264 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
265 if (brush && (brush->flag & BRUSH_CURVE)) {
267 }
268 }
269
270 /* Initialize UV transform from. */
271 if (op && (prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
272 if (RNA_property_is_set(op->ptr, prop)) {
273 if (RNA_property_boolean_get(op->ptr, prop)) {
275 }
276 else {
277 t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT_SLIDE;
278 }
279 }
280 else {
283 }
284 }
285 }
286 else if (t->spacetype == SPACE_IMAGE) {
287 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
290 /* UV transform. */
291 }
292 else if (sima->mode == SI_MODE_MASK) {
293 t->options |= CTX_MASK;
294 }
295 else if (sima->mode == SI_MODE_PAINT) {
296 Paint *paint = &sce->toolsettings->imapaint.paint;
297 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
298 if (brush && (brush->flag & BRUSH_CURVE)) {
300 }
301 }
302 /* Image not in UV edit, nor in mask mode, can happen for some tools. */
303 }
304 else if (t->spacetype == SPACE_CLIP) {
305 SpaceClip *sclip = static_cast<SpaceClip *>(area->spacedata.first);
308 }
309 else if (ED_space_clip_check_show_maskedit(sclip)) {
310 t->options |= CTX_MASK;
311 }
312 }
313 else if (t->spacetype == SPACE_SEQ && region->regiontype == RGN_TYPE_PREVIEW) {
315
316 /* Needed for auto-keying transforms in preview during playback. */
318 t->animtimer = (animscreen) ? animscreen->animtimer : nullptr;
319 }
320
322
323 if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) &&
324 RNA_property_is_set(op->ptr, prop))
325 {
329 }
330
331 t->view = t_view_get(t);
332 t->around = t_around_get(t);
333
334 /* Exceptional case. */
337 const bool use_island = transdata_check_local_islands(t, t->around);
338
339 if ((t->obedit_type != -1) && !use_island) {
340 t->options |= CTX_NO_PET;
341 }
342 }
343 }
344
345 bool t_values_set_is_array = false;
346
347 if (op && (prop = RNA_struct_find_property(op->ptr, "value")) &&
348 RNA_property_is_set(op->ptr, prop))
349 {
350 float values[4] = {0}; /* In case value isn't length 4, avoid uninitialized memory. */
351 if (RNA_property_array_check(prop)) {
352 RNA_property_float_get_array(op->ptr, prop, values);
353 t_values_set_is_array = true;
354 }
355 else {
356 values[0] = RNA_property_float_get(op->ptr, prop);
357 }
358
359 if (t->flag & T_MODAL) {
360 /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */
362 }
363 else {
364 copy_v4_v4(t->values, values);
366 }
367 }
368
369 if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
370 bool constraint_axis[3] = {false, false, false};
371 if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) {
372 /* For operators whose `t->values` is array (as Move and Scale), set constraint so that the
373 * orientation is more intuitive in the Redo Panel. */
374 constraint_axis[0] = constraint_axis[1] = constraint_axis[2] = true;
375 }
376 else if (RNA_property_is_set(op->ptr, prop)) {
377 RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
378 }
379
380 if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
381 t->con.mode |= CON_APPLY;
382
383 if (constraint_axis[0]) {
384 t->con.mode |= CON_AXIS0;
385 }
386 if (constraint_axis[1]) {
387 t->con.mode |= CON_AXIS1;
388 }
389 if (constraint_axis[2]) {
390 t->con.mode |= CON_AXIS2;
391 }
392 }
393 }
394
395 {
396 short orient_types[3];
397 short orient_type_apply = O_DEFAULT;
398 float custom_matrix[3][3];
399
400 int orient_type_scene = V3D_ORIENT_GLOBAL;
401 int orient_type_default = -1;
402 int orient_type_set = -1;
403 int orient_type_matrix_set = -1;
404
405 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
407 orient_type_scene = orient_slot->type;
408 if (orient_type_scene == V3D_ORIENT_CUSTOM) {
409 const int index_custom = orient_slot->index_custom;
410 orient_type_scene += index_custom;
411 }
412 }
413
414 if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
415 RNA_property_is_set(op->ptr, prop)))
416 {
417 orient_type_set = RNA_property_enum_get(op->ptr, prop);
418 if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
419 orient_type_set = V3D_ORIENT_GLOBAL;
420 }
421 }
422
423 if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
424 t->orient_axis = RNA_property_enum_get(op->ptr, prop);
425 }
426
427 if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
429 }
430
431 /* The properties "orient_matrix" and "orient_matrix_type" are used to store the orientation
432 * calculated in the first operator call. This allows for reuse of the orientation during
433 * subsequent calls of the same operator. When making adjustments through the Redo panel
434 * (#OP_IS_REPEAT), reusing the orientation prevents unpredictable changes that can occur when
435 * using #V3D_ORIENT_VIEW. However, when activated by #SCREEN_OT_repeat_last
436 * (#OP_IS_REPEAT_LAST), it's best to avoid reusing the orientation to prevent unintended
437 * changes. */
438 if (op && !(op->flag & OP_IS_REPEAT_LAST) &&
439 ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
440 RNA_property_is_set(op->ptr, prop)))
441 {
442 RNA_property_float_get_array(op->ptr, prop, &custom_matrix[0][0]);
443
444 if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
445 RNA_property_is_set(op->ptr, prop))
446 {
447 orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop);
448 }
449 else if (orient_type_set == -1) {
450 orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
451 }
452 }
453
454 orient_type_default = orient_type_scene;
455
456 if (orient_type_set != -1) {
457 if (!(t->con.mode & CON_APPLY)) {
458 /* Only overwrite default if not constrained. */
459 orient_type_default = orient_type_set;
461 }
462 }
463 else if (orient_type_matrix_set != -1) {
464 orient_type_set = orient_type_matrix_set;
465 if (!(t->con.mode & CON_APPLY)) {
466 /* Only overwrite default if not constrained. */
467 orient_type_default = orient_type_set;
469 }
470 }
471
472 if (orient_type_set == -1) {
473 if (orient_type_scene == V3D_ORIENT_GLOBAL) {
474 orient_type_set = V3D_ORIENT_LOCAL;
475 }
476 else {
477 orient_type_set = V3D_ORIENT_GLOBAL;
478 }
479
480 if (t->con.mode & CON_APPLY) {
481 orient_type_apply = O_SCENE;
482 }
483 }
484 else {
485 if (t->con.mode & CON_APPLY) {
486 orient_type_apply = O_SET;
487 }
488 }
489
490 BLI_assert(!ELEM(-1, orient_type_default, orient_type_set));
491 if (orient_type_matrix_set == orient_type_set) {
492 /* Constraints are forced to use the custom matrix when redoing. */
493 orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
494 }
495
496 orient_types[O_DEFAULT] = short(orient_type_default);
497 orient_types[O_SCENE] = short(orient_type_scene);
498 orient_types[O_SET] = short(orient_type_set);
499
500 for (int i = 0; i < 3; i++) {
501 /* For efficiency, avoid calculating the same orientation twice. */
502 int j;
503 for (j = 0; j < i; j++) {
504 if (orient_types[j] == orient_types[i]) {
505 memcpy(&t->orient[i], &t->orient[j], sizeof(*t->orient));
506 break;
507 }
508 }
509 if (j == i) {
511 C, t, orient_types[i], custom_matrix, t->orient[i].matrix);
512 }
513 }
514
515 t->orient_type_mask = 0;
516 for (int i = 0; i < 3; i++) {
517 const int type = t->orient[i].type;
518 if (type < V3D_ORIENT_CUSTOM_MATRIX) {
519 BLI_assert(type < 32);
520 t->orient_type_mask |= (1 << type);
521 }
522 }
523
524 transform_orientations_current_set(t, orient_type_apply);
525 }
526
527 if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
528 RNA_property_is_set(op->ptr, prop)))
529 {
530 if (RNA_property_boolean_get(op->ptr, prop)) {
532 }
533 }
534 else {
535 /* Release confirms preference should not affect node editor (#69288, #70504). */
537 ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE)))
538 {
539 /* Global "release confirm" on mouse bindings. */
541 }
542 }
543
544 if (op &&
545 ((prop = RNA_struct_find_property(op->ptr, "mirror")) && RNA_property_is_set(op->ptr, prop)))
546 {
547 if (!RNA_property_boolean_get(op->ptr, prop)) {
548 t->flag |= T_NO_MIRROR;
549 }
550 }
551 else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
552 /* Pass. */
553 }
554 else {
555 /* Avoid mirroring for unsupported contexts. */
556 t->flag |= T_NO_MIRROR;
557 }
558
559 /* Setting proportional editing flag only if property exist in operator. Otherwise, assume it's
560 * not supported. */
561 if (op && (prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
562 if (RNA_property_is_set(op->ptr, prop)) {
563 if (RNA_property_boolean_get(op->ptr, prop)) {
564 t->flag |= T_PROP_EDIT;
565 if (RNA_boolean_get(op->ptr, "use_proportional_connected")) {
567 }
568 if (RNA_boolean_get(op->ptr, "use_proportional_projected")) {
570 }
571 }
572 }
573 else {
574 /* Use settings from scene only if modal. */
575 if (t->flag & T_MODAL) {
576 if ((t->options & CTX_NO_PET) == 0) {
577 bool use_prop_edit = false;
578 if (t->spacetype == SPACE_GRAPH) {
579 use_prop_edit = ts->proportional_fcurve;
580 }
581 else if (t->spacetype == SPACE_ACTION) {
582 use_prop_edit = ts->proportional_action;
583 }
584 else if (t->options & CTX_MASK) {
585 use_prop_edit = ts->proportional_mask;
586 }
587 else if (obact && obact->mode == OB_MODE_OBJECT) {
588 use_prop_edit = ts->proportional_objects;
589 }
590 else {
591 use_prop_edit = (ts->proportional_edit & PROP_EDIT_USE) != 0;
592 }
593
594 if (use_prop_edit) {
595 t->flag |= T_PROP_EDIT;
596 if (ts->proportional_edit & PROP_EDIT_CONNECTED) {
598 }
599 if (ts->proportional_edit & PROP_EDIT_PROJECTED) {
601 }
602 }
603 }
604 }
605 }
606
607 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
608 RNA_property_is_set(op->ptr, prop)))
609 {
610 t->prop_size = RNA_property_float_get(op->ptr, prop);
611 }
612 else {
613 t->prop_size = ts->proportional_size;
614 }
615
616 /* TRANSFORM_FIX_ME rna restrictions. */
617 if (t->prop_size <= 0.00001f) {
618 printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
619 t->prop_size = 1.0f;
620 }
621
622 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
623 RNA_property_is_set(op->ptr, prop)))
624 {
625 t->prop_mode = RNA_property_enum_get(op->ptr, prop);
626 }
627 else {
628 t->prop_mode = ts->prop_mode;
629 }
630 }
631 else { /* Add not pet option to context when not available. */
632 t->options |= CTX_NO_PET;
633 }
634
635 if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) &&
636 RNA_property_is_set(op->ptr, prop))
637 {
638 if (RNA_property_boolean_get(op->ptr, prop)) {
640 }
641 }
642 else if (t->obedit_type == OB_MESH) {
643 char automerge = t->scene->toolsettings->automerge;
644 if (automerge & AUTO_MERGE) {
645 t->flag |= T_AUTOMERGE;
646 if (automerge & AUTO_MERGE_AND_SPLIT) {
647 t->flag |= T_AUTOSPLIT;
648 }
649 }
650 }
651
652 if (op && (prop = RNA_struct_find_property(op->ptr, "use_duplicated_keyframes")) &&
653 RNA_property_is_set(op->ptr, prop))
654 {
655 if (RNA_property_boolean_get(op->ptr, prop)) {
657 }
658 }
659
660/* Mirror is not supported with proportional editing, turn it off. */
661#if 0
662 if (t->flag & T_PROP_EDIT) {
663 t->flag &= ~T_MIRROR;
664 }
665#endif
666
667 /* Disable cursor wrap when edge panning is enabled. */
668 if (t->options & CTX_VIEW2D_EDGE_PAN) {
670 }
671
672 if (op && (t->flag & T_MODAL) &&
673 ELEM(t->mode,
680 {
682 wmKeyMap *keymap = WM_keymap_active(wm, op->type->modalkeymap);
683 const wmKeyMapItem *kmi_passthrough = nullptr;
684 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &keymap->items) {
685 if (kmi->flag & KMI_INACTIVE) {
686 continue;
687 }
688
689 if (kmi->propvalue == TFM_MODAL_PASSTHROUGH_NAVIGATE) {
690 kmi_passthrough = kmi;
691 break;
692 }
693 }
694 t->vod = ED_view3d_navigation_init(C, kmi_passthrough);
695 }
696
700 initNumInput(&t->num);
701
703}
704
706{
707 if (custom_data->free_cb) {
708 /* Can take over freeing t->data and data_2d etc... */
709 custom_data->free_cb(t, tc, custom_data);
710 BLI_assert(custom_data->data == nullptr);
711 }
712 else if ((custom_data->data != nullptr) && custom_data->use_free) {
713 MEM_freeN(custom_data->data);
714 custom_data->data = nullptr;
715 }
716 /* In case modes are switched in the same transform session. */
717 custom_data->free_cb = nullptr;
718 custom_data->use_free = false;
719}
720
724{
725 TransCustomData *custom_data = &tcdc->first_elem;
726 for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
727 freeTransCustomData(t, tc, custom_data);
728 }
729}
730
732{
733 freeTransCustomData(t, nullptr, &t->custom.mode);
735 freeTransCustomData(t, tc, &tc->custom.mode);
736 }
737}
738
740{
741 if (t->draw_handle_view) {
743 }
744 if (t->draw_handle_pixel) {
746 }
747 if (t->draw_handle_cursor) {
749 }
750
751 if (t->flag & T_MODAL_CURSOR_SET) {
753 }
754
755 /* Free all custom-data. */
756 freeTransCustomDataContainer(t, nullptr, &t->custom);
759 }
760
761 /* #postTrans can be called when nothing is selected, so data is nullptr already. */
762 if (t->data_len_all != 0) {
764 /* Free data malloced per trans-data. */
766 (t->spacetype == SPACE_GRAPH))
767 {
768 TransData *td = tc->data;
769 for (int a = 0; a < tc->data_len; a++, td++) {
770 if (td->flag & TD_BEZTRIPLE) {
771 MEM_freeN(td->hdata);
772 }
773 }
774 }
775 MEM_freeN(tc->data);
776
777 MEM_SAFE_FREE(tc->data_mirror);
778 MEM_SAFE_FREE(tc->data_ext);
779 MEM_SAFE_FREE(tc->data_2d);
780 }
781 }
782
784 t->data_container = nullptr;
785
787
788 if (t->spacetype == SPACE_IMAGE) {
789 if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
790 /* Pass. */
791 }
792 else {
793 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
794 if (sima->flag & SI_LIVE_UNWRAP) {
796 }
797 }
798 }
799
800 if (t->mouse.data) {
801 MEM_freeN(t->mouse.data);
802 }
803
804 if (t->rng != nullptr) {
805 BLI_rng_free(t->rng);
806 }
807
808 freeSnapping(t);
809
810 if (t->vod) {
812 }
813}
814
816{
818
819 TransData *td;
820
821 for (td = tc->data; td < tc->data + tc->data_len; td++) {
822 copy_v3_v3(td->iloc, td->loc);
823 if (td->ext->rot) {
824 copy_v3_v3(td->ext->irot, td->ext->rot);
825 }
826 if (td->ext->size) {
827 copy_v3_v3(td->ext->isize, td->ext->size);
828 }
829 }
830 recalc_data(t);
831}
832
834{
835 if (td_basic->loc) {
836 copy_v3_v3(td_basic->loc, td_basic->iloc);
837 }
838
839 /* TODO(mano-wii): Only use 3D or larger vectors in `td->loc`.
840 * If `loc` and `val` point to the same address, it may indicate that `loc` is not 3D which is
841 * not safe for `copy_v3_v3`. */
842 if (td_basic->val && td_basic->val != td_basic->loc) {
843 *td_basic->val = td_basic->ival;
844 }
845}
846
847static void restoreElement(TransData *td)
848{
850
851 if (td->ext && (td->flag & TD_NO_EXT) == 0) {
852 if (td->ext->rot) {
853 copy_v3_v3(td->ext->rot, td->ext->irot);
854 }
855 if (td->ext->rotAngle) {
856 *td->ext->rotAngle = td->ext->irotAngle;
857 }
858 if (td->ext->rotAxis) {
859 copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
860 }
861 /* XXX, `drotAngle` & `drotAxis` not used yet. */
862 if (td->ext->size) {
863 copy_v3_v3(td->ext->size, td->ext->isize);
864 }
865 if (td->ext->quat) {
866 copy_qt_qt(td->ext->quat, td->ext->iquat);
867 }
868 }
869
870 if (td->flag & TD_BEZTRIPLE) {
871 *(td->hdata->h1) = td->hdata->ih1;
872 *(td->hdata->h2) = td->hdata->ih2;
873 }
874}
875
877{
879
880 TransData *td;
881 TransData2D *td2d;
882 TransDataMirror *tdm;
883
884 for (td = tc->data; td < tc->data + tc->data_len; td++) {
885 restoreElement(td);
886 }
887
888 for (tdm = tc->data_mirror; tdm < tc->data_mirror + tc->data_mirror_len; tdm++) {
890 }
891
892 for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
893 if (td2d->h1) {
894 td2d->h1[0] = td2d->ih1[0];
895 td2d->h1[1] = td2d->ih1[1];
896 }
897 if (td2d->h2) {
898 td2d->h2[0] = td2d->ih2[0];
899 td2d->h2[1] = td2d->ih2[1];
900 }
901 }
902
903 unit_m3(t->mat);
904 }
905
906 recalc_data(t);
907}
908
914
915void calculateCenterLocal(TransInfo *t, const float center_global[3])
916{
917 /* Setting constraint center. */
918 /* NOTE: init functions may over-ride `t->center`. */
920 if (tc->use_local_mat) {
921 mul_v3_m4v3(tc->center_local, tc->imat, center_global);
922 }
923 else {
924 copy_v3_v3(tc->center_local, center_global);
925 }
926 }
927}
928
929void calculateCenterCursor(TransInfo *t, float r_center[3])
930{
931 const float *cursor = t->scene->cursor.location;
932 copy_v3_v3(r_center, cursor);
933
934 /* If edit or pose mode, move cursor in local space. */
935 if (t->options & CTX_PAINT_CURVE) {
936 if (ED_view3d_project_float_global(t->region, cursor, r_center, V3D_PROJ_TEST_NOP) !=
938 {
939 r_center[0] = t->region->winx / 2.0f;
940 r_center[1] = t->region->winy / 2.0f;
941 }
942 r_center[2] = 0.0f;
943 }
944}
945
946void calculateCenterCursor2D(TransInfo *t, float r_center[2])
947{
948 float cursor_local_buf[2];
949 const float *cursor = nullptr;
950
951 if (t->spacetype == SPACE_IMAGE) {
953 cursor = sima->cursor;
954 }
955 if (t->spacetype == SPACE_SEQ) {
956 SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first;
957 SEQ_image_preview_unit_to_px(t->scene, sseq->cursor, cursor_local_buf);
958 cursor = cursor_local_buf;
959 }
960 else if (t->spacetype == SPACE_CLIP) {
961 SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
962 cursor = space_clip->cursor;
963 }
964
965 if (cursor) {
966 if (t->options & CTX_MASK) {
967 float co[2];
968
969 if (t->spacetype == SPACE_IMAGE) {
971 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
972 }
973 else if (t->spacetype == SPACE_CLIP) {
974 SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
975 BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
976 }
977 else {
978 BLI_assert_msg(0, "Shall not happen");
979 }
980
981 r_center[0] = co[0] * t->aspect[0];
982 r_center[1] = co[1] * t->aspect[1];
983 }
984 else if (t->options & CTX_PAINT_CURVE) {
985 if (t->spacetype == SPACE_IMAGE) {
986 r_center[0] = UI_view2d_view_to_region_x(&t->region->v2d, cursor[0]);
987 r_center[1] = UI_view2d_view_to_region_y(&t->region->v2d, cursor[1]);
988 }
989 }
990 else {
991 r_center[0] = cursor[0] * t->aspect[0];
992 r_center[1] = cursor[1] * t->aspect[1];
993 }
994 }
995}
996
997void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
998{
1000 Scene *scene = t->scene;
1001
1002 /* Cursor is combination of current frame, and graph-editor cursor value. */
1003 if (sipo->mode == SIPO_MODE_DRIVERS) {
1004 r_center[0] = sipo->cursorTime;
1005 r_center[1] = sipo->cursorVal;
1006 }
1007 else {
1008 r_center[0] = float(scene->r.cfra);
1009 r_center[1] = sipo->cursorVal;
1010 }
1011}
1012
1014 const TransDataBasic *td_basic,
1015 float r_vec[3])
1016{
1017 if (td_basic->flag & TD_SELECTED) {
1018 if (!(td_basic->flag & TD_NOCENTER)) {
1019 if (tc->use_local_mat) {
1020 mul_v3_m4v3(r_vec, tc->mat, td_basic->center);
1021 }
1022 else {
1023 copy_v3_v3(r_vec, td_basic->center);
1024 }
1025 return true;
1026 }
1027 }
1028 return false;
1029}
1030
1031void calculateCenterMedian(TransInfo *t, float r_center[3])
1032{
1033 float partial[3] = {0.0f, 0.0f, 0.0f};
1034 int total = 0;
1035
1037 float center[3];
1038 for (int i = 0; i < tc->data_len; i++) {
1039 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data[i], center)) {
1040 add_v3_v3(partial, center);
1041 total++;
1042 }
1043 }
1044 for (int i = 0; i < tc->data_mirror_len; i++) {
1045 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data_mirror[i], center)) {
1046 add_v3_v3(partial, center);
1047 total++;
1048 }
1049 }
1050 }
1051 if (total) {
1052 mul_v3_fl(partial, 1.0f / float(total));
1053 }
1054 copy_v3_v3(r_center, partial);
1055}
1056
1057void calculateCenterBound(TransInfo *t, float r_center[3])
1058{
1059 float max[3], min[3];
1060 bool changed = false;
1061 INIT_MINMAX(min, max);
1063 float center[3];
1064 for (int i = 0; i < tc->data_len; i++) {
1065 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data[i], center)) {
1066 minmax_v3v3_v3(min, max, center);
1067 changed = true;
1068 }
1069 }
1070 for (int i = 0; i < tc->data_mirror_len; i++) {
1071 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data_mirror[i], center)) {
1072 minmax_v3v3_v3(min, max, center);
1073 changed = true;
1074 }
1075 }
1076 }
1077 if (changed) {
1078 mid_v3_v3v3(r_center, min, max);
1079 }
1080}
1081
1082bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
1083{
1085
1086 if (t->spacetype != SPACE_VIEW3D) {
1087 return false;
1088 }
1089 if (tc->obedit) {
1090 if (blender::ed::object::calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
1091 mul_m4_v3(tc->obedit->object_to_world().ptr(), r_center);
1092 return true;
1093 }
1094 }
1095 else if (t->options & CTX_POSE_BONE) {
1098 if (blender::ed::object::calc_active_center_for_posemode(ob, select_only, r_center)) {
1099 mul_m4_v3(ob->object_to_world().ptr(), r_center);
1100 return true;
1101 }
1102 }
1103 else if (t->options & CTX_PAINT_CURVE) {
1104 Paint *paint = BKE_paint_get_active(t->scene, t->view_layer);
1105 Brush *br = BKE_paint_brush(paint);
1106 PaintCurve *pc = br->paint_curve;
1107 copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
1109 r_center[2] = 0.0f;
1110 return true;
1111 }
1112 else {
1113 /* Object mode. */
1116 if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
1117 copy_v3_v3(r_center, base->object->object_to_world().location());
1118 return true;
1119 }
1120 }
1121
1122 return false;
1123}
1124
1125static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
1126{
1127 switch (around) {
1129 calculateCenterBound(t, r_center);
1130 break;
1132 calculateCenterMedian(t, r_center);
1133 break;
1134 case V3D_AROUND_CURSOR:
1136 calculateCenterCursor2D(t, r_center);
1137 }
1138 else if (t->spacetype == SPACE_GRAPH) {
1139 calculateCenterCursorGraph2D(t, r_center);
1140 }
1141 else {
1142 calculateCenterCursor(t, r_center);
1143 }
1144 break;
1146 /* Individual element center uses median center for helpline and such. */
1147 calculateCenterMedian(t, r_center);
1148 break;
1149 case V3D_AROUND_ACTIVE: {
1150 if (calculateCenterActive(t, false, r_center)) {
1151 /* Pass. */
1152 }
1153 else {
1154 /* Fallback. */
1155 calculateCenterMedian(t, r_center);
1156 }
1157 break;
1158 }
1159 }
1160}
1161
1163{
1164 /* #ED_view3d_calc_zfac() defines a factor for perspective depth correction,
1165 * used in #ED_view3d_win_to_delta(). */
1166
1167 /* `zfac` is only used #convertViewVec only in cases operator was invoked in #RGN_TYPE_WINDOW
1168 * and never used in other cases.
1169 *
1170 * We need special case here as well, since #ED_view3d_calc_zfac will crash when called
1171 * for a region different from #RGN_TYPE_WINDOW.
1172 */
1173 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1174 t->zfac = ED_view3d_calc_zfac(static_cast<const RegionView3D *>(t->region->regiondata),
1175 t->center_global);
1176 }
1177 else if (t->spacetype == SPACE_IMAGE) {
1178 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
1179 t->zfac = 1.0f / sima->zoom;
1180 }
1181 else if (t->region) {
1182 View2D *v2d = &t->region->v2d;
1183 /* Get zoom fac the same way as in
1184 * `ui_view2d_curRect_validate_resize` - better keep in sync! */
1185 const float zoomx = float(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
1186 t->zfac = 1.0f / zoomx;
1187 }
1188}
1189
1191{
1192 if ((t->flag & T_OVERRIDE_CENTER) == 0) {
1194 }
1196
1198
1199 /* For panning from the camera-view. */
1200 if ((t->options & CTX_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
1201 if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
1202
1203 if (t->options & CTX_CAMERA) {
1204 float axis[3];
1205 /* `persinv` is nasty, use `viewinv` instead, always right. */
1206 copy_v3_v3(axis, t->viewinv[2]);
1207 normalize_v3(axis);
1208
1209 /* 6.0 = 6 grid units. */
1210 axis[0] = t->center_global[0] - 6.0f * axis[0];
1211 axis[1] = t->center_global[1] - 6.0f * axis[1];
1212 axis[2] = t->center_global[2] - 6.0f * axis[2];
1213
1214 projectFloatView(t, axis, t->center2d);
1215
1216 /* Rotate only needs correct 2d center, grab needs #ED_view3d_calc_zfac() value. */
1217 if (t->mode == TFM_TRANSLATION) {
1218 copy_v3_v3(t->center_global, axis);
1219 }
1220 }
1221 }
1222 }
1223
1224 calculateZfac(t);
1225}
1226
1228{
1229 float zoom_prev = t->zfac;
1230 float zoom_new;
1231 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1232 if (!t->persp) {
1233 zoom_prev *= len_v3(t->persinv[0]);
1234 }
1235
1237 calculateZfac(t);
1238
1239 zoom_new = t->zfac;
1240 if (!t->persp) {
1241 zoom_new *= len_v3(t->persinv[0]);
1242 }
1243
1244 for (int i = 0; i < ARRAY_SIZE(t->orient); i++) {
1245 if (t->orient[i].type == V3D_ORIENT_VIEW) {
1246 copy_m3_m4(t->orient[i].matrix, t->viewinv);
1247 normalize_m3(t->orient[i].matrix);
1248 if (t->orient_curr == i) {
1249 copy_m3_m3(t->spacemtx, t->orient[i].matrix);
1251 }
1252 }
1253 }
1254 }
1255 else {
1256 calculateZfac(t);
1257 zoom_new = t->zfac;
1258 }
1259
1262 transform_input_update(t, zoom_prev / zoom_new);
1263}
1264
1266{
1267 int i;
1268 float dist;
1269 const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
1270
1271 t->proptext[0] = '\0';
1272
1273 if (t->flag & T_PROP_EDIT) {
1274 const char *pet_id = nullptr;
1276 TransData *td = tc->data;
1277 for (i = 0; i < tc->data_len; i++, td++) {
1278 if (td->flag & TD_SELECTED) {
1279 td->factor = 1.0f;
1280 }
1281 else if ((connected ? td->dist : td->rdist) > t->prop_size) {
1282 td->factor = 0.0f;
1283 restoreElement(td);
1284 }
1285 else {
1286 /* Use `rdist` for falloff calculations, it is the real distance. */
1287 if (connected) {
1288 dist = (t->prop_size - td->dist) / t->prop_size;
1289 }
1290 else {
1291 dist = (t->prop_size - td->rdist) / t->prop_size;
1292 }
1293
1294 /*
1295 * Clamp to positive numbers.
1296 * Certain corner cases with connectivity and individual centers
1297 * can give values of rdist larger than propsize.
1298 */
1299 if (dist < 0.0f) {
1300 dist = 0.0f;
1301 }
1302
1303 switch (t->prop_mode) {
1304 case PROP_SHARP:
1305 td->factor = dist * dist;
1306 break;
1307 case PROP_SMOOTH:
1308 td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
1309 break;
1310 case PROP_ROOT:
1311 td->factor = sqrtf(dist);
1312 break;
1313 case PROP_LIN:
1314 td->factor = dist;
1315 break;
1316 case PROP_CONST:
1317 td->factor = 1.0f;
1318 break;
1319 case PROP_SPHERE:
1320 td->factor = sqrtf(2 * dist - dist * dist);
1321 break;
1322 case PROP_RANDOM:
1323 if (t->rng == nullptr) {
1324 /* Lazy initialization. */
1325 uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
1326 t->rng = BLI_rng_new(rng_seed);
1327 }
1328 td->factor = BLI_rng_get_float(t->rng) * dist;
1329 break;
1330 case PROP_INVSQUARE:
1331 td->factor = dist * (2.0f - dist);
1332 break;
1333 default:
1334 td->factor = 1;
1335 break;
1336 }
1337 }
1338 }
1339 }
1340
1341 switch (t->prop_mode) {
1342 case PROP_SHARP:
1343 pet_id = N_("(Sharp)");
1344 break;
1345 case PROP_SMOOTH:
1346 pet_id = N_("(Smooth)");
1347 break;
1348 case PROP_ROOT:
1349 pet_id = N_("(Root)");
1350 break;
1351 case PROP_LIN:
1352 pet_id = N_("(Linear)");
1353 break;
1354 case PROP_CONST:
1355 pet_id = N_("(Constant)");
1356 break;
1357 case PROP_SPHERE:
1358 pet_id = N_("(Sphere)");
1359 break;
1360 case PROP_RANDOM:
1361 pet_id = N_("(Random)");
1362 break;
1363 case PROP_INVSQUARE:
1364 pet_id = N_("(InvSquare)");
1365 break;
1366 default:
1367 break;
1368 }
1369
1370 if (pet_id) {
1371 STRNCPY_UTF8(t->proptext, IFACE_(pet_id));
1372 }
1373 }
1374 else {
1376 TransData *td = tc->data;
1377 for (i = 0; i < tc->data_len; i++, td++) {
1378 td->factor = 1.0;
1379 }
1380 }
1381 }
1382}
1383
1384void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
1385{
1386 float totmat[3][3];
1387 float smat[3][3];
1388 float fmat[3][3];
1389 float obmat[3][3];
1390
1391 float dmat[3][3]; /* Delta rotation. */
1392 float dmat_inv[3][3];
1393
1394 mul_m3_m3m3(totmat, mat, td->mtx);
1395 mul_m3_m3m3(smat, td->smtx, mat);
1396
1397 /* Logic from #BKE_object_rot_to_mat3. */
1398 if (use_drot) {
1399 if (td->ext->rotOrder > 0) {
1400 eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
1401 }
1402 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
1403#if 0
1404 axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
1405#else
1406 unit_m3(dmat);
1407#endif
1408 }
1409 else {
1410 float tquat[4];
1411 normalize_qt_qt(tquat, td->ext->dquat);
1412 quat_to_mat3(dmat, tquat);
1413 }
1414
1415 invert_m3_m3(dmat_inv, dmat);
1416 }
1417
1418 if (td->ext->rotOrder == ROT_MODE_QUAT) {
1419 float quat[4];
1420
1421 /* Calculate the total rotation. */
1422 quat_to_mat3(obmat, td->ext->iquat);
1423 if (use_drot) {
1424 mul_m3_m3m3(obmat, dmat, obmat);
1425 }
1426
1427 /* `mat = transform`, `obmat = object rotation`. */
1428 mul_m3_m3m3(fmat, smat, obmat);
1429
1430 if (use_drot) {
1431 mul_m3_m3m3(fmat, dmat_inv, fmat);
1432 }
1433
1434 mat3_to_quat(quat, fmat);
1435
1436 /* Apply. */
1437 copy_qt_qt(td->ext->quat, quat);
1438 }
1439 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
1440 float axis[3], angle;
1441
1442 /* Calculate the total rotation. */
1443 axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
1444 if (use_drot) {
1445 mul_m3_m3m3(obmat, dmat, obmat);
1446 }
1447
1448 /* `mat = transform`, `obmat = object rotation`. */
1449 mul_m3_m3m3(fmat, smat, obmat);
1450
1451 if (use_drot) {
1452 mul_m3_m3m3(fmat, dmat_inv, fmat);
1453 }
1454
1455 mat3_to_axis_angle(axis, &angle, fmat);
1456
1457 /* Apply. */
1458 copy_v3_v3(td->ext->rotAxis, axis);
1459 *td->ext->rotAngle = angle;
1460 }
1461 else {
1462 float eul[3];
1463
1464 /* Calculate the total rotation. */
1465 eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
1466 if (use_drot) {
1467 mul_m3_m3m3(obmat, dmat, obmat);
1468 }
1469
1470 /* `mat = transform`, `obmat = object rotation`. */
1471 mul_m3_m3m3(fmat, smat, obmat);
1472
1473 if (use_drot) {
1474 mul_m3_m3m3(fmat, dmat_inv, fmat);
1475 }
1476
1477 mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
1478
1479 /* Apply. */
1480 copy_v3_v3(td->ext->rot, eul);
1481 }
1482}
1483
1485{
1486 if (!(ob->mode & OB_MODE_ALL_WEIGHT_PAINT)) {
1487 return nullptr;
1488 }
1489 /* Important that ob_armature can be set even when its not selected #23412.
1490 * Lines below just check is also visible. */
1492 if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
1494 Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
1495 if (base_arm) {
1496 View3D *v3d = static_cast<View3D *>(t->view);
1497 if (BASE_VISIBLE(v3d, base_arm)) {
1498 return ob_armature;
1499 }
1500 }
1501 }
1502 return nullptr;
1503}
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:621
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
wmMsgBus * CTX_wm_message_bus(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_mask_coord_from_image(struct Image *image, struct ImageUser *iuser, float r_co[2], const float co[2])
void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2])
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
Paint * BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
Definition paint.cc:438
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:649
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void mul_m4_v3(const float M[4][4], float r[3])
void invert_m3_m3_safe_ortho(float inverse[3][3], const float mat[3][3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void quat_to_mat3(float m[3][3], const float q[4])
void mat3_to_quat(float q[4], const float mat[3][3])
float normalize_qt_qt(float r[4], const float q[4])
void mat3_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[3][3])
void eulO_to_mat3(float M[3][3], const float e[3], short order)
void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
void copy_qt_qt(float q[4], const float a[4])
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
MINLINE void copy_v4_v4(float r[4], const float a[4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:93
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
#define STRNCPY_UTF8(dst, src)
unsigned int uint
Platform independent time functions.
long int BLI_time_now_seconds_i(void)
Definition time.c:75
#define INIT_MINMAX(min, max)
#define ARRAY_SIZE(arr)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define IFACE_(msgid)
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ BRUSH_CURVE
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_WEIGHT_PAINT
eObjectMode
@ OB_MODE_EDIT_GPENCIL_LEGACY
@ OB_MODE_EDIT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_SURF
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ SCE_ORIENT_DEFAULT
#define BASE_SELECTED(v3d, base)
@ SCE_XFORM_AXIS_ALIGN
@ UVCALC_TRANSFORM_CORRECT_SLIDE
@ PROP_EDIT_PROJECTED
@ PROP_EDIT_USE
@ PROP_EDIT_CONNECTED
@ AUTO_MERGE
@ AUTO_MERGE_AND_SPLIT
@ PROP_SMOOTH
@ PROP_ROOT
@ PROP_SHARP
@ PROP_RANDOM
@ PROP_LIN
@ PROP_CONST
@ PROP_INVSQUARE
@ PROP_SPHERE
#define BASE_VISIBLE(v3d, base)
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ SI_LIVE_UNWRAP
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ SIPO_MODE_DRIVERS
@ SI_MODE_PAINT
@ SI_MODE_MASK
@ USER_RELEASECONFIRM
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CURSOR
@ V3D_AROUND_CENTER_MEDIAN
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_ORIENT_CUSTOM
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_CUSTOM_MATRIX
@ V3D_ORIENT_LOCAL
@ V3D_ORIENT_VIEW
bool ED_space_clip_check_show_trackedit(const SpaceClip *sc)
bool ED_space_clip_check_show_maskedit(const SpaceClip *sc)
bool ED_space_image_show_uvedit(const SpaceImage *sima, Object *obedit)
void initNumInput(NumInput *n)
Definition numinput.cc:70
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
@ TFM_RESIZE
@ TFM_EDGE_SLIDE
@ TFM_SHRINKFATTEN
@ TFM_VERT_SLIDE
@ TFM_BEND
@ TFM_ROTATION
@ TFM_BWEIGHT
@ TFM_EDGE_CREASE
@ TFM_TRANSLATION
@ TFM_TRACKBALL
int BIF_countTransformOrientation(const bContext *C)
void ED_uvedit_live_unwrap_end(bool cancel)
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:266
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:243
void ED_view3d_navigation_free(bContext *C, ViewOpsData *vod)
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
ViewOpsData * ED_view3d_navigation_init(bContext *C, const wmKeyMapItem *kmi_merge)
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
#define MEM_SAFE_FREE(v)
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1691
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1686
unsigned int U
Definition btGjkEpa3.h:78
#define printf
#define sqrtf(x)
void setTransformViewAspect(TransInfo *t, float r_aspect[3])
bool transdata_check_local_islands(TransInfo *t, short around)
void setTransformViewMatrices(TransInfo *t)
void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
draw_view in_light_buf[] float
#define UINT_MAX
Definition hash_md5.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
bool calc_active_center_for_editmode(Object *obedit, bool select_only, float r_center[3])
bool calc_active_center_for_posemode(Object *ob, bool select_only, float r_center[3])
VecBase< float, 2 > float2
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_array_check(PropertyRNA *prop)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int SEQ_tool_settings_pivot_point_get(Scene *scene)
Definition sequencer.cc:410
#define min(a, b)
Definition sort.c:32
void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
void * regiondata
struct ARegionType * type
short flag
struct Object * object
float vec[3][3]
struct PaintCurve * paint_curve
void * first
blender::float2 imval
Definition transform.hh:383
void * data
Definition transform.hh:390
PaintCurvePoint * points
struct ToolSettings * toolsettings
View3DCursor cursor
TransformOrientationSlot orientation_slots[4]
ListBase spacedata
struct MovieClipUser user
float cursor[2]
struct MovieClip * clip
struct ImageUser iuser
struct Image * image
float cursor[2]
struct ImagePaintSettings imapaint
eTConstraint mode
Definition transform.hh:351
TransCustomData mode
Definition transform.hh:423
TransCustomData first_elem
Definition transform.hh:423
unsigned int use_free
Definition transform.hh:410
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
Definition transform.hh:409
float mat[4][4]
Definition transform.hh:462
TransData * data
Definition transform.hh:445
TransDataCurveHandleFlags * hdata
float smtx[3][3]
float mtx[3][3]
TransDataExtension * ext
float snap_spatial_precision
Definition transform.hh:568
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
float spacemtx_inv[3][3]
Definition transform.hh:593
wmTimer * animtimer
Definition transform.hh:657
float snap_spatial[3]
Definition transform.hh:563
float prop_size
Definition transform.hh:546
void * draw_handle_cursor
Definition transform.hh:668
float center2d[2]
Definition transform.hh:557
ReportList * reports
Definition transform.hh:661
float values[4]
Definition transform.hh:624
char proptext[20]
Definition transform.hh:548
TransSnap tsnap
Definition transform.hh:537
float zfac
Definition transform.hh:665
float values_modal_offset[4]
Definition transform.hh:627
eTState state
Definition transform.hh:527
ToolSettings * settings
Definition transform.hh:656
NumInput num
Definition transform.hh:540
TransCustomDataContainer custom
Definition transform.hh:676
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
eTHelpline helpline
Definition transform.hh:531
bool remove_on_cancel
Definition transform.hh:645
ViewLayer * view_layer
Definition transform.hh:655
int data_container_len
Definition transform.hh:506
eTFlag flag
Definition transform.hh:523
ARegion * region
Definition transform.hh:652
MouseInput mouse
Definition transform.hh:543
RNG * rng
Definition transform.hh:671
int orient_type_mask
Definition transform.hh:619
short obedit_type
Definition transform.hh:584
TransDataContainer * data_container
Definition transform.hh:505
void * draw_handle_pixel
Definition transform.hh:667
Depsgraph * depsgraph
Definition transform.hh:653
bool is_orient_default_overwrite
Definition transform.hh:606
float mat[3][3]
Definition transform.hh:589
float matrix[3][3]
Definition transform.hh:610
TransCon con
Definition transform.hh:534
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
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
ListBase points
Definition transform.hh:330
struct wmTimer * animtimer
int mval[2]
Definition WM_types.hh:728
wmKeyMap * modalkeymap
Definition WM_types.hh:1098
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
@ CON_APPLY
Definition transform.hh:193
@ CON_AXIS1
Definition transform.hh:196
@ CON_AXIS0
Definition transform.hh:195
@ CON_AXIS2
Definition transform.hh:197
#define TRANS_CUSTOM_DATA_ELEM_MAX
Definition transform.hh:427
@ CTX_MOVIECLIP
Definition transform.hh:70
@ CTX_PAINT_CURVE
Definition transform.hh:72
@ CTX_SEQUENCER_IMAGE
Definition transform.hh:75
@ CTX_CURSOR
Definition transform.hh:66
@ CTX_POSE_BONE
Definition transform.hh:73
@ CTX_OBJECT
Definition transform.hh:71
@ CTX_EDGE_DATA
Definition transform.hh:67
@ 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
#define TRANS_DATA_CONTAINER_FIRST_OK(t)
Definition transform.hh:849
@ TREDRAW_HARD
Definition transform.hh:217
@ TFM_MODAL_PASSTHROUGH_NAVIGATE
Definition transform.hh:294
void transform_input_update(TransInfo *t, const float fac)
@ O_DEFAULT
Definition transform.hh:233
@ O_SCENE
Definition transform.hh:234
@ O_SET
Definition transform.hh:235
eTFlag
Definition transform.hh:89
@ T_OVERRIDE_CENTER
Definition transform.hh:129
@ T_RELEASE_CONFIRM
Definition transform.hh:123
@ T_MODAL
Definition transform.hh:118
@ T_AUTOSPLIT
Definition transform.hh:138
@ T_PROP_CONNECTED
Definition transform.hh:99
@ T_ALT_TRANSFORM
Definition transform.hh:126
@ T_AUTOMERGE
Definition transform.hh:136
@ T_NO_MIRROR
Definition transform.hh:111
@ T_PROP_EDIT
Definition transform.hh:98
@ T_INPUT_IS_VALUES_FINAL
Definition transform.hh:115
@ T_V3D_ALIGN
Definition transform.hh:102
@ T_NO_CURSOR_WRAP
Definition transform.hh:144
@ T_EVENT_DRAG_START
Definition transform.hh:141
@ T_MODAL_CURSOR_SET
Definition transform.hh:131
@ T_PROP_PROJECTED
Definition transform.hh:100
@ T_DUPLICATED_KEYFRAMES
Definition transform.hh:152
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t)
Definition transform.hh:851
@ TRANS_CANCEL
Definition transform.hh:210
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
@ HLP_NONE
Definition transform.hh:223
void recalc_data(TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
@ TD_BEZTRIPLE
@ TD_NO_EXT
@ TD_SELECTED
@ TD_NOCENTER
static int t_around_get(TransInfo *t)
void calculateCenter(TransInfo *t)
void postTrans(bContext *C, TransInfo *t)
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
static void transdata_restore_basic(TransDataBasic *td_basic)
void resetTransRestrictions(TransInfo *t)
void calculateCenter2D(TransInfo *t)
void transformViewUpdate(TransInfo *t)
static void calculateZfac(TransInfo *t)
void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, TransCustomDataContainer *tcdc)
void calculateCenterMedian(TransInfo *t, float r_center[3])
static void restoreElement(TransData *td)
static void freeTransCustomData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
void calculateCenterCursor(TransInfo *t, float r_center[3])
Object * transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob)
void resetTransModal(TransInfo *t)
void restoreTransObjects(TransInfo *t)
static bool transdata_center_global_get(const TransDataContainer *tc, const TransDataBasic *td_basic, float r_vec[3])
static void * t_view_get(TransInfo *t)
void calculatePropRatio(TransInfo *t)
void applyTransObjects(TransInfo *t)
void calculateCenterLocal(TransInfo *t, const float center_global[3])
void freeTransCustomDataForMode(TransInfo *t)
void calculateCenterBound(TransInfo *t, float r_center[3])
void transform_gizmo_3d_model_from_constraint_and_mode_init(TransInfo *t)
void transform_orientations_current_set(TransInfo *t, const short orient_index)
short transform_orientation_matrix_get(bContext *C, TransInfo *t, short orient_index, const float custom[3][3], float r_spacemtx[3][3])
void freeSnapping(TransInfo *t)
void transform_snap_grid_init(const TransInfo *t, float r_snap[3], float *r_snap_precision)
#define N_(msgid)
void WM_cursor_modal_restore(wmWindow *win)
void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2])
#define ISMOUSE_BUTTON(event_type)
wmKeyMap * WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap)
bool WM_paint_cursor_end(wmPaintCursor *handle)