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