Blender V5.0
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 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
132 if (!is_sequencer) {
133 t->scene = sce;
134 t->view_layer = view_layer;
135 }
136 else {
138 t->view_layer = t->scene ? BKE_view_layer_default_render(t->scene) : nullptr;
139 }
140
141 PropertyRNA *prop;
142
145
146 t->area = area;
147 t->region = region;
148 t->settings = ts;
149 t->reports = op ? op->reports : nullptr;
150
151 t->helpline = HLP_NONE;
152
153 t->flag = eTFlag(0);
154
155 if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) &&
157 {
158 t->obedit_type = obact->type;
159 }
160 else {
161 t->obedit_type = -1;
162 }
163
164 if (t->options & CTX_CURSOR) {
165 /* Cursor should always use the drag start as the combination of click-drag to place & move
166 * doesn't work well if the click location isn't used when transforming. */
168 }
169
170 /* Many kinds of transform only use a single handle. */
171 if (t->data_container == nullptr) {
172 t->data_container = static_cast<TransDataContainer *>(
173 MEM_callocN(sizeof(*t->data_container), __func__));
174 t->data_container_len = 1;
175 }
176
177 t->redraw = TREDRAW_HARD; /* Redraw first time. */
178
179 float2 mval;
180 if (event) {
181 if (t->flag & T_EVENT_DRAG_START) {
182 WM_event_drag_start_mval_fl(event, region, mval);
183 }
184 else {
185 mval = float2(event->mval);
186 }
187 }
188 else {
189 mval = float2(0, 0);
190 }
191
192 t->mval = mval;
193
194 /* Initialize this mouse variable in advance as it is required by
195 * `transform_convert_frame_side_dir_get` which is called before `initMouseInput`. */
196 t->mouse.imval = mval;
197
198 t->mode_info = nullptr;
199
200 t->data_len_all = 0;
201
203
204 unit_m3(t->mat);
205
206 /* Default to rotate on the Z axis. */
207 t->orient_axis = 2;
208 t->orient_axis_ortho = 1;
209
210 /* If there's an event, we're modal. */
211 if (event) {
212 t->flag |= T_MODAL;
213 }
214
215 /* Crease needs edge flag. */
218 }
219
220 t->remove_on_cancel = false;
221
222 if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) &&
223 RNA_property_is_set(op->ptr, prop))
224 {
225 if (RNA_property_boolean_get(op->ptr, prop)) {
226 t->remove_on_cancel = true;
227 }
228 }
229
230 /* Grease Pencil editing context. */
231 if (t->obedit_type == OB_GREASE_PENCIL && object_mode == OB_MODE_EDIT &&
232 ((area == nullptr) || (area->spacetype == SPACE_VIEW3D)))
233 {
235 }
236
237 /* Assign the space type, some exceptions for running in different mode. */
238 if (area == nullptr) {
239 /* Background mode. */
241 }
242 else if (((region == nullptr) || (region->regiondata == nullptr)) &&
243 (area->spacetype == SPACE_VIEW3D))
244 {
245 /* Running the operator through the text editor where e.g. `area.type` was
246 * set to 'VIEW_3D' but the viewport was not updated. */
248 }
249 else {
250 /* Normal operation. */
251 t->spacetype = area->spacetype;
252 }
253
254 /* Handle #T_ALT_TRANSFORM initialization, we may use for different operators. */
255 if (op) {
256 const char *prop_id = nullptr;
257 if (t->mode == TFM_SHRINKFATTEN) {
258 prop_id = "use_even_offset";
259 }
260
261 if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
263 }
264 }
265
266 if (t->spacetype == SPACE_VIEW3D) {
268
269 t->animtimer = (animscreen) ? animscreen->animtimer : nullptr;
270
272 t->flag |= T_V3D_ALIGN;
273 }
274
275 if ((object_mode & OB_MODE_ALL_PAINT) || (object_mode & OB_MODE_SCULPT_CURVES)) {
277 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
278 if (brush && (brush->flag & BRUSH_CURVE)) {
280 }
281 }
282
283 /* Initialize UV transform from. */
284 if (op && (prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
285 if (RNA_property_is_set(op->ptr, prop)) {
286 if (RNA_property_boolean_get(op->ptr, prop)) {
288 }
289 else {
291 }
292 }
293 else {
296 }
297 }
298 }
299 else if (t->spacetype == SPACE_IMAGE) {
300 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
303 /* UV transform. */
304 }
305 else if (sima->mode == SI_MODE_MASK) {
306 t->options |= CTX_MASK;
307 }
308 else if (sima->mode == SI_MODE_PAINT) {
309 Paint *paint = &sce->toolsettings->imapaint.paint;
310 Brush *brush = (paint) ? BKE_paint_brush(paint) : nullptr;
311 if (brush && (brush->flag & BRUSH_CURVE)) {
313 }
314 }
315 /* Image not in UV edit, nor in mask mode, can happen for some tools. */
316 }
317 else if (t->spacetype == SPACE_CLIP) {
318 SpaceClip *sclip = static_cast<SpaceClip *>(area->spacedata.first);
321 }
322 else if (ED_space_clip_check_show_maskedit(sclip)) {
323 t->options |= CTX_MASK;
324 }
325 }
326 else if (t->spacetype == SPACE_SEQ && region->regiontype == RGN_TYPE_PREVIEW) {
328
329 /* Needed for auto-keying transforms in preview during playback. */
331 t->animtimer = (animscreen) ? animscreen->animtimer : nullptr;
332 }
333
335
336 if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) &&
337 RNA_property_is_set(op->ptr, prop))
338 {
342 }
343
344 t->view = t_view_get(t);
345 t->around = t_around_get(t);
346
347 /* Exceptional case. */
350 const bool use_island = transdata_check_local_islands(t, t->around);
351
352 if ((t->obedit_type != -1) && !use_island) {
353 t->options |= CTX_NO_PET;
354 }
355 }
356 }
357
358 bool t_values_set_is_array = false;
359
360 if (op && (prop = RNA_struct_find_property(op->ptr, "value")) &&
361 RNA_property_is_set(op->ptr, prop))
362 {
363 float values[4] = {0}; /* In case value isn't length 4, avoid uninitialized memory. */
364 if (RNA_property_array_check(prop)) {
365 RNA_property_float_get_array(op->ptr, prop, values);
366 t_values_set_is_array = true;
367 }
368 else {
369 values[0] = RNA_property_float_get(op->ptr, prop);
370 }
371
372 if (t->flag & T_MODAL) {
373 /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */
375 }
376 else {
377 copy_v4_v4(t->values, values);
379 }
380 }
381
382 if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
383 bool constraint_axis[3] = {false, false, false};
384 if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) {
385 /* For operators whose `t->values` is array (as Move and Scale), set constraint so that the
386 * orientation is more intuitive in the Redo Panel. */
387 constraint_axis[0] = constraint_axis[1] = constraint_axis[2] = true;
388 }
389 else if (RNA_property_is_set(op->ptr, prop)) {
390 RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
391 }
392
393 if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
394 t->con.mode |= CON_APPLY;
395
396 if (constraint_axis[0]) {
397 t->con.mode |= CON_AXIS0;
398 }
399 if (constraint_axis[1]) {
400 t->con.mode |= CON_AXIS1;
401 }
402 if (constraint_axis[2]) {
403 t->con.mode |= CON_AXIS2;
404 }
405 }
406 }
407
408 {
409 eTOType orient_types[3];
410 eTOType orient_type_apply = O_DEFAULT;
411 float custom_matrix[3][3];
412
413 int orient_type_scene = V3D_ORIENT_GLOBAL;
414 int orient_type_default = -1;
415 int orient_type_set = -1;
416 int orient_type_matrix_set = -1;
417
418 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
420 orient_type_scene = orient_slot->type;
421 if (orient_type_scene == V3D_ORIENT_CUSTOM) {
422 const int index_custom = orient_slot->index_custom;
423 orient_type_scene += index_custom;
424 }
425 }
426
427 if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
428 RNA_property_is_set(op->ptr, prop)))
429 {
430 orient_type_set = RNA_property_enum_get(op->ptr, prop);
431 if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
432 orient_type_set = V3D_ORIENT_GLOBAL;
433 }
434 }
435
436 if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
437 t->orient_axis = RNA_property_enum_get(op->ptr, prop);
438 }
439
440 if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
442 }
443
444 /* The properties "orient_matrix" and "orient_matrix_type" are used to store the orientation
445 * calculated in the first operator call. This allows for reuse of the orientation during
446 * subsequent calls of the same operator. When making adjustments through the Redo panel
447 * (#OP_IS_REPEAT), reusing the orientation prevents unpredictable changes that can occur when
448 * using #V3D_ORIENT_VIEW. However, when activated by #SCREEN_OT_repeat_last
449 * (#OP_IS_REPEAT_LAST), it's best to avoid reusing the orientation to prevent unintended
450 * changes. */
451 if (op && !(op->flag & OP_IS_REPEAT_LAST) &&
452 ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
453 RNA_property_is_set(op->ptr, prop)))
454 {
455 RNA_property_float_get_array(op->ptr, prop, &custom_matrix[0][0]);
456
457 if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
458 RNA_property_is_set(op->ptr, prop))
459 {
460 orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop);
461 }
462 else if (orient_type_set == -1) {
463 orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
464 }
465 }
466
467 orient_type_default = orient_type_scene;
468
469 if (orient_type_set != -1) {
470 if (!(t->con.mode & CON_APPLY)) {
471 /* Only overwrite default if not constrained. */
472 orient_type_default = orient_type_set;
474 }
475 }
476 else if (orient_type_matrix_set != -1) {
477 orient_type_set = orient_type_matrix_set;
478 if (!(t->con.mode & CON_APPLY)) {
479 /* Only overwrite default if not constrained. */
480 orient_type_default = orient_type_set;
482 }
483 }
484
485 if (orient_type_set == -1) {
486 if (orient_type_scene == V3D_ORIENT_GLOBAL) {
487 orient_type_set = V3D_ORIENT_LOCAL;
488 }
489 else {
490 orient_type_set = V3D_ORIENT_GLOBAL;
491 }
492
493 if (t->con.mode & CON_APPLY) {
494 orient_type_apply = O_SCENE;
495 }
496 }
497 else {
498 orient_type_apply = O_SET;
499 }
500
501 BLI_assert(!ELEM(-1, orient_type_default, orient_type_set));
502 if (orient_type_matrix_set == orient_type_set) {
503 /* Constraints are forced to use the custom matrix when redoing. */
504 orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
505 }
506
507 orient_types[O_DEFAULT] = eTOType(orient_type_default);
508 orient_types[O_SCENE] = eTOType(orient_type_scene);
509 orient_types[O_SET] = eTOType(orient_type_set);
510
511 for (int i = 0; i < 3; i++) {
512 /* For efficiency, avoid calculating the same orientation twice. */
513 int j;
514 for (j = 0; j < i; j++) {
515 if (orient_types[j] == orient_types[i]) {
516 memcpy(&t->orient[i], &t->orient[j], sizeof(*t->orient));
517 break;
518 }
519 }
520 if (j == i) {
522 C, t, orient_types[i], custom_matrix, t->orient[i].matrix);
523 }
524 }
525
526 t->orient_type_mask = 0;
527 for (int i = 0; i < 3; i++) {
528 const int type = t->orient[i].type;
529 if (type < V3D_ORIENT_CUSTOM_MATRIX) {
530 BLI_assert(type < 32);
531 t->orient_type_mask |= (1 << type);
532 }
533 }
534
535 transform_orientations_current_set(t, orient_type_apply);
536 }
537
538 if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
539 RNA_property_is_set(op->ptr, prop)))
540 {
541 if (RNA_property_boolean_get(op->ptr, prop)) {
543 }
544 }
545 else {
546 /* Release confirms preference should not affect node editor (#69288, #70504). */
548 ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE)))
549 {
550 /* Global "release confirm" on mouse bindings. */
552 }
553 }
554
555 if (op &&
556 ((prop = RNA_struct_find_property(op->ptr, "mirror")) && RNA_property_is_set(op->ptr, prop)))
557 {
558 if (!RNA_property_boolean_get(op->ptr, prop)) {
559 t->flag |= T_NO_MIRROR;
560 }
561 }
562 else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
563 /* Pass. */
564 }
565 else {
566 /* Avoid mirroring for unsupported contexts. */
567 t->flag |= T_NO_MIRROR;
568 }
569
570 /* Setting proportional editing flag only if property exist in operator. Otherwise, assume it's
571 * not supported. */
572 if (op && (prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
573 if (RNA_property_is_set(op->ptr, prop)) {
574 if (RNA_property_boolean_get(op->ptr, prop)) {
575 t->flag |= T_PROP_EDIT;
576 if (RNA_boolean_get(op->ptr, "use_proportional_connected")) {
578 }
579 if (RNA_boolean_get(op->ptr, "use_proportional_projected")) {
581 }
582 }
583 }
584 else {
585 /* Use settings from scene only if modal. */
586 if (t->flag & T_MODAL) {
587 if ((t->options & CTX_NO_PET) == 0) {
588 bool use_prop_edit = false;
589 if (t->spacetype == SPACE_GRAPH) {
590 use_prop_edit = ts->proportional_fcurve;
591 }
592 else if (t->spacetype == SPACE_ACTION) {
593 use_prop_edit = ts->proportional_action;
594 }
595 else if (t->options & CTX_MASK) {
596 use_prop_edit = ts->proportional_mask;
597 }
598 else if (object_mode == OB_MODE_OBJECT) {
599 /* No active object means #TransConvertType_Object [see #convert_type_get()], so use
600 * toolsetting for *object*. */
601 use_prop_edit = ts->proportional_objects;
602 }
603 else {
604 use_prop_edit = (ts->proportional_edit & PROP_EDIT_USE) != 0;
605 }
606
607 if (use_prop_edit) {
608 t->flag |= T_PROP_EDIT;
611 }
614 }
615 }
616 }
617 }
618 }
619
620 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
621 RNA_property_is_set(op->ptr, prop)))
622 {
623 t->prop_size = RNA_property_float_get(op->ptr, prop);
624 }
625 else {
627 }
628
629 /* TRANSFORM_FIX_ME rna restrictions. */
630 if (t->prop_size <= 0.00001f) {
631 printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
632 t->prop_size = 1.0f;
633 }
634
635 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
636 RNA_property_is_set(op->ptr, prop)))
637 {
638 t->prop_mode = RNA_property_enum_get(op->ptr, prop);
639 }
640 else {
641 t->prop_mode = ts->prop_mode;
642 }
643 }
644 else { /* Add not pet option to context when not available. */
645 t->options |= CTX_NO_PET;
646 }
647
648 if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) &&
649 RNA_property_is_set(op->ptr, prop))
650 {
651 if (RNA_property_boolean_get(op->ptr, prop)) {
653 }
654 }
655 else if (t->obedit_type == OB_MESH) {
656 char automerge = t->scene->toolsettings->automerge;
657 if (automerge & AUTO_MERGE) {
658 t->flag |= T_AUTOMERGE;
659 if (automerge & AUTO_MERGE_AND_SPLIT) {
660 t->flag |= T_AUTOSPLIT;
661 }
662 }
663 }
664
665 if (op && (prop = RNA_struct_find_property(op->ptr, "use_duplicated_keyframes")) &&
666 RNA_property_is_set(op->ptr, prop))
667 {
668 if (RNA_property_boolean_get(op->ptr, prop)) {
670 }
671 }
672
673/* Mirror is not supported with proportional editing, turn it off. */
674#if 0
675 if (t->flag & T_PROP_EDIT) {
676 t->flag &= ~T_MIRROR;
677 }
678#endif
679
680 /* Disable cursor wrap when edge panning is enabled. */
681 if (t->options & CTX_VIEW2D_EDGE_PAN) {
683 }
684
685 if (op && (t->flag & T_MODAL) &&
686 ELEM(t->mode,
693 {
696 const wmKeyMapItem *kmi_passthrough = nullptr;
697 LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &keymap->items) {
698 if (kmi->flag & KMI_INACTIVE) {
699 continue;
700 }
701
702 if (kmi->propvalue == TFM_MODAL_PASSTHROUGH_NAVIGATE) {
703 kmi_passthrough = kmi;
704 break;
705 }
706 }
707 t->vod = ED_view3d_navigation_init(C, kmi_passthrough);
708 }
709
710 if (t->mode == TFM_TRANSLATION) {
711 if ((prop = RNA_struct_find_property(op->ptr, "translate_origin")) &&
712 RNA_property_is_set(op->ptr, prop))
713 {
714 if (RNA_property_boolean_get(op->ptr, prop)) {
715 t->flag |= T_ORIGIN;
716 }
717 }
718 }
719
723 initNumInput(&t->num);
724
726}
727
729{
730 if (custom_data->free_cb) {
731 /* Can take over freeing t->data and data_2d etc... */
732 custom_data->free_cb(t, tc, custom_data);
733 BLI_assert(custom_data->data == nullptr);
734 }
735 else if ((custom_data->data != nullptr) && custom_data->use_free) {
736 MEM_freeN(custom_data->data);
737 custom_data->data = nullptr;
738 }
739 /* In case modes are switched in the same transform session. */
740 custom_data->free_cb = nullptr;
741 custom_data->use_free = false;
742}
743
747{
748 TransCustomData *custom_data = &tcdc->first_elem;
749 for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
750 freeTransCustomData(t, tc, custom_data);
751 }
752}
753
755{
756 freeTransCustomData(t, nullptr, &t->custom.mode);
758 freeTransCustomData(t, tc, &tc->custom.mode);
759 }
760}
761
763{
764 if (t->draw_handle_view) {
766 }
767 if (t->draw_handle_pixel) {
769 }
770 if (t->draw_handle_cursor) {
772 }
773
774 if (t->flag & T_MODAL_CURSOR_SET) {
776 }
777
778 /* Free all custom-data. */
779 freeTransCustomDataContainer(t, nullptr, &t->custom);
782 }
783
784 /* #postTrans can be called when nothing is selected, so data is nullptr already. */
785 if (t->data_len_all != 0) {
787 /* Free data malloced per trans-data. */
789 TransData *td = tc->data;
790 for (int a = 0; a < tc->data_len; a++, td++) {
791 if (td->flag & TD_BEZTRIPLE) {
792 MEM_freeN(td->hdata);
793 }
794 }
795 }
796 MEM_freeN(tc->data);
797
798 MEM_SAFE_FREE(tc->data_mirror);
799 MEM_SAFE_FREE(tc->data_ext);
800 MEM_SAFE_FREE(tc->data_2d);
801 MEM_SAFE_FREE(tc->sorted_index_map);
802 }
803 }
804
806 t->data_container = nullptr;
807
809
810 if (t->spacetype == SPACE_IMAGE) {
811 if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
812 /* Pass. */
813 }
814 else {
815 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
816 if (sima->flag & SI_LIVE_UNWRAP) {
818 }
819 }
820 }
821
822 if (t->mouse.data) {
823 MEM_freeN(t->mouse.data);
824 }
825
826 if (t->rng != nullptr) {
827 BLI_rng_free(t->rng);
828 }
829
830 freeSnapping(t);
831
832 if (t->vod) {
834 }
835}
836
838{
839 if (td_basic->loc) {
840 copy_v3_v3(td_basic->loc, td_basic->iloc);
841 }
842
843 /* TODO(mano-wii): Only use 3D or larger vectors in `td->loc`.
844 * If `loc` and `val` point to the same address, it may indicate that `loc` is not 3D which is
845 * not safe for `copy_v3_v3`. */
846 if (td_basic->val && td_basic->val != td_basic->loc) {
847 *td_basic->val = td_basic->ival;
848 }
849}
850
851static void restoreElement(TransData *td)
852{
854
855 if (td->flag & TD_BEZTRIPLE) {
856 *(td->hdata->h1) = td->hdata->ih1;
857 *(td->hdata->h2) = td->hdata->ih2;
858 }
859}
860
862{
864
865 TransData *td;
866 TransData2D *td2d;
867 TransDataMirror *tdm;
868
869 for (td = tc->data; td < tc->data + tc->data_len; td++) {
870 restoreElement(td);
871 }
872
873 for (tdm = tc->data_mirror; tdm < tc->data_mirror + tc->data_mirror_len; tdm++) {
875 }
876
877 if (tc->data_ext) {
878 for (int i = 0; i < tc->data_len; i++) {
879 if (tc->data[i].flag & TD_NO_EXT) {
880 continue;
881 }
882
883 TransDataExtension *td_ext = &tc->data_ext[i];
884 if (td_ext->rot) {
885 copy_v3_v3(td_ext->rot, td_ext->irot);
886 }
887 if (td_ext->rotAngle) {
888 *td_ext->rotAngle = td_ext->irotAngle;
889 }
890 if (td_ext->rotAxis) {
891 copy_v3_v3(td_ext->rotAxis, td_ext->irotAxis);
892 }
893 /* XXX, `drotAngle` & `drotAxis` not used yet. */
894 if (td_ext->scale) {
895 copy_v3_v3(td_ext->scale, td_ext->iscale);
896 }
897 if (td_ext->quat) {
898 copy_qt_qt(td_ext->quat, td_ext->iquat);
899 }
900 }
901 }
902
903 for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
904 if (td2d->h1) {
905 td2d->h1[0] = td2d->ih1[0];
906 td2d->h1[1] = td2d->ih1[1];
907 }
908 if (td2d->h2) {
909 td2d->h2[0] = td2d->ih2[0];
910 td2d->h2[1] = td2d->ih2[1];
911 }
912 }
913
914 unit_m3(t->mat);
915 }
916
917 recalc_data(t);
918}
919
925
926void calculateCenterLocal(TransInfo *t, const float center_global[3])
927{
928 /* Setting constraint center. */
929 /* NOTE: init functions may over-ride `t->center`. */
931 if (tc->use_local_mat) {
932 mul_v3_m4v3(tc->center_local, tc->imat, center_global);
933 }
934 else {
935 copy_v3_v3(tc->center_local, center_global);
936 }
937 }
938}
939
940void calculateCenterCursor(TransInfo *t, float r_center[3])
941{
942 const float *cursor = t->scene->cursor.location;
943 copy_v3_v3(r_center, cursor);
944
945 /* If edit or pose mode, move cursor in local space. */
946 if (t->options & CTX_PAINT_CURVE) {
947 if (ED_view3d_project_float_global(t->region, cursor, r_center, V3D_PROJ_TEST_NOP) !=
949 {
951 }
952 r_center[2] = 0.0f;
953 }
954}
955
956void calculateCenterCursor2D(TransInfo *t, float r_center[2])
957{
958 float cursor_local_buf[2];
959 const float *cursor = nullptr;
960
961 if (t->spacetype == SPACE_IMAGE) {
963 cursor = sima->cursor;
964 }
965 if (t->spacetype == SPACE_SEQ) {
966 SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first;
967 const float2 cursor_pixel = seq::image_preview_unit_to_px(t->scene, sseq->cursor);
968 copy_v2_v2(cursor_local_buf, cursor_pixel);
969 cursor = cursor_local_buf;
970 }
971 else if (t->spacetype == SPACE_CLIP) {
972 SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
973 cursor = space_clip->cursor;
974 }
975
976 if (cursor) {
977 if (t->options & CTX_MASK) {
978 float co[2];
979
980 if (t->spacetype == SPACE_IMAGE) {
982 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
983 }
984 else if (t->spacetype == SPACE_CLIP) {
985 SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
986 BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
987 }
988 else {
989 BLI_assert_msg(0, "Shall not happen");
990 }
991
992 r_center[0] = co[0] * t->aspect[0];
993 r_center[1] = co[1] * t->aspect[1];
994 }
995 else if (t->options & CTX_PAINT_CURVE) {
996 if (t->spacetype == SPACE_IMAGE) {
997 r_center[0] = UI_view2d_view_to_region_x(&t->region->v2d, cursor[0]);
998 r_center[1] = UI_view2d_view_to_region_y(&t->region->v2d, cursor[1]);
999 }
1000 }
1001 else {
1002 r_center[0] = cursor[0] * t->aspect[0];
1003 r_center[1] = cursor[1] * t->aspect[1];
1004 }
1005 }
1006}
1007
1008void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
1009{
1010 SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
1011 Scene *scene = t->scene;
1012
1013 /* Cursor is combination of current frame, and graph-editor cursor value. */
1014 if (sipo->mode == SIPO_MODE_DRIVERS) {
1015 r_center[0] = sipo->cursorTime;
1016 r_center[1] = sipo->cursorVal;
1017 }
1018 else {
1019 r_center[0] = float(scene->r.cfra);
1020 r_center[1] = sipo->cursorVal;
1021 }
1022}
1023
1025 const TransDataBasic *td_basic,
1026 float r_vec[3])
1027{
1028 if (td_basic->flag & TD_SELECTED) {
1029 if (!(td_basic->flag & TD_NOCENTER)) {
1030 if (tc->use_local_mat) {
1031 mul_v3_m4v3(r_vec, tc->mat, td_basic->center);
1032 }
1033 else {
1034 copy_v3_v3(r_vec, td_basic->center);
1035 }
1036 return true;
1037 }
1038 }
1039 return false;
1040}
1041
1042void calculateCenterMedian(TransInfo *t, float r_center[3])
1043{
1044 float partial[3] = {0.0f, 0.0f, 0.0f};
1045 int total = 0;
1046
1048 float center[3];
1049 for (int i = 0; i < tc->data_len; i++) {
1050 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data[i], center)) {
1051 add_v3_v3(partial, center);
1052 total++;
1053 }
1054 }
1055 for (int i = 0; i < tc->data_mirror_len; i++) {
1056 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data_mirror[i], center)) {
1057 add_v3_v3(partial, center);
1058 total++;
1059 }
1060 }
1061 }
1062 if (total) {
1063 mul_v3_fl(partial, 1.0f / float(total));
1064 }
1065 copy_v3_v3(r_center, partial);
1066}
1067
1068void calculateCenterBound(TransInfo *t, float r_center[3])
1069{
1070 float max[3], min[3];
1071 bool changed = false;
1074 float center[3];
1075 for (int i = 0; i < tc->data_len; i++) {
1076 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data[i], center)) {
1077 minmax_v3v3_v3(min, max, center);
1078 changed = true;
1079 }
1080 }
1081 for (int i = 0; i < tc->data_mirror_len; i++) {
1082 if (transdata_center_global_get(tc, (TransDataBasic *)&tc->data_mirror[i], center)) {
1083 minmax_v3v3_v3(min, max, center);
1084 changed = true;
1085 }
1086 }
1087 }
1088 if (changed) {
1089 mid_v3_v3v3(r_center, min, max);
1090 }
1091}
1092
1093bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
1094{
1096
1097 if (t->spacetype != SPACE_VIEW3D) {
1098 return false;
1099 }
1100 if (tc->obedit) {
1101 if (object::calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
1102 mul_m4_v3(tc->obedit->object_to_world().ptr(), r_center);
1103 return true;
1104 }
1105 }
1106 else if (t->options & CTX_POSE_BONE) {
1109 if (object::calc_active_center_for_posemode(ob, select_only, r_center)) {
1110 mul_m4_v3(ob->object_to_world().ptr(), r_center);
1111 return true;
1112 }
1113 }
1114 else if (t->options & CTX_PAINT_CURVE) {
1115 Paint *paint = BKE_paint_get_active(t->scene, t->view_layer);
1116 Brush *br = BKE_paint_brush(paint);
1117 PaintCurve *pc = br->paint_curve;
1118 copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
1120 r_center[2] = 0.0f;
1121 return true;
1122 }
1123 else {
1124 /* Object mode. */
1127 if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
1128 copy_v3_v3(r_center, base->object->object_to_world().location());
1129 return true;
1130 }
1131 }
1132
1133 return false;
1134}
1135
1136static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
1137{
1138 switch (around) {
1140 calculateCenterBound(t, r_center);
1141 break;
1143 calculateCenterMedian(t, r_center);
1144 break;
1145 case V3D_AROUND_CURSOR:
1147 calculateCenterCursor2D(t, r_center);
1148 }
1149 else if (t->spacetype == SPACE_GRAPH) {
1150 calculateCenterCursorGraph2D(t, r_center);
1151 }
1152 else {
1153 calculateCenterCursor(t, r_center);
1154 }
1155 break;
1157 /* Individual element center uses median center for helpline and such. */
1158 calculateCenterMedian(t, r_center);
1159 break;
1160 case V3D_AROUND_ACTIVE: {
1161 if (calculateCenterActive(t, false, r_center)) {
1162 /* Pass. */
1163 }
1164 else {
1165 /* Fallback. */
1166 calculateCenterMedian(t, r_center);
1167 }
1168 break;
1169 }
1170 }
1171}
1172
1174{
1175 /* #ED_view3d_calc_zfac() defines a factor for perspective depth correction,
1176 * used in #ED_view3d_win_to_delta(). */
1177
1178 /* `zfac` is only used #convertViewVec only in cases operator was invoked in #RGN_TYPE_WINDOW
1179 * and never used in other cases.
1180 *
1181 * We need special case here as well, since #ED_view3d_calc_zfac will crash when called
1182 * for a region different from #RGN_TYPE_WINDOW.
1183 */
1184 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1185 t->zfac = ED_view3d_calc_zfac(static_cast<const RegionView3D *>(t->region->regiondata),
1186 t->center_global);
1187 }
1188 else if (t->spacetype == SPACE_IMAGE) {
1189 SpaceImage *sima = static_cast<SpaceImage *>(t->area->spacedata.first);
1190 t->zfac = 1.0f / sima->zoom;
1191 }
1192 else if (t->region) {
1193 View2D *v2d = &t->region->v2d;
1194 /* Get zoom factor the same way as in
1195 * #ui_view2d_curRect_validate_resize - better keep in sync! */
1196 const float zoomx = float(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
1197 t->zfac = 1.0f / zoomx;
1198 }
1199}
1200
1202{
1203 if ((t->flag & T_OVERRIDE_CENTER) == 0) {
1205 }
1207
1209
1210 /* For panning from the camera-view. */
1211 if ((t->options & CTX_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
1212 if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
1213
1214 if (t->options & CTX_CAMERA) {
1215 float axis[3];
1216 /* `persinv` is nasty, use `viewinv` instead, always right. */
1217 copy_v3_v3(axis, t->viewinv[2]);
1218 normalize_v3(axis);
1219
1220 /* 6.0 = 6 grid units. */
1221 axis[0] = t->center_global[0] - 6.0f * axis[0];
1222 axis[1] = t->center_global[1] - 6.0f * axis[1];
1223 axis[2] = t->center_global[2] - 6.0f * axis[2];
1224
1225 projectFloatView(t, axis, t->center2d);
1226
1227 /* Rotate only needs correct 2d center, grab needs #ED_view3d_calc_zfac() value. */
1228 if (t->mode == TFM_TRANSLATION) {
1229 copy_v3_v3(t->center_global, axis);
1230 }
1231 }
1232 }
1233 }
1234
1235 calculateZfac(t);
1236}
1237
1239{
1240 float zoom_prev = t->zfac;
1241 float zoom_new;
1242 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1243 if (!t->persp) {
1244 zoom_prev *= len_v3(t->persinv[0]);
1245 }
1246
1248 calculateZfac(t);
1249
1250 zoom_new = t->zfac;
1251 if (!t->persp) {
1252 zoom_new *= len_v3(t->persinv[0]);
1253 }
1254
1255 for (int i = 0; i < ARRAY_SIZE(t->orient); i++) {
1256 if (t->orient[i].type == V3D_ORIENT_VIEW) {
1257 copy_m3_m4(t->orient[i].matrix, t->viewinv);
1259 if (t->orient_curr == i) {
1262 }
1263 }
1264 }
1265 }
1266 else {
1267 calculateZfac(t);
1268 zoom_new = t->zfac;
1269 }
1270
1273 transform_input_update(t, zoom_prev / zoom_new);
1274}
1275
1277{
1278 int i;
1279 float dist;
1280 const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
1281
1282 t->proptext[0] = '\0';
1283
1284 if (t->flag & T_PROP_EDIT) {
1285 const char *pet_id = nullptr;
1287 TransData *td = tc->data;
1288 for (i = 0; i < tc->data_len; i++, td++) {
1289 if (td->flag & TD_SELECTED) {
1290 td->factor = 1.0f;
1291 }
1292 else if ((connected ? td->dist : td->rdist) > t->prop_size) {
1293 td->factor = 0.0f;
1294 restoreElement(td);
1295 }
1296 else {
1297 /* Use `rdist` for falloff calculations, it is the real distance. */
1298 if (connected) {
1299 dist = (t->prop_size - td->dist) / t->prop_size;
1300 }
1301 else {
1302 dist = (t->prop_size - td->rdist) / t->prop_size;
1303 }
1304
1305 /*
1306 * Clamp to positive numbers.
1307 * Certain corner cases with connectivity and individual centers
1308 * can give values of rdist larger than propsize.
1309 */
1310 dist = std::max(dist, 0.0f);
1311
1312 switch (t->prop_mode) {
1313 case PROP_SHARP:
1314 td->factor = dist * dist;
1315 break;
1316 case PROP_SMOOTH:
1317 /* Float imprecision can cause a `dist` approaching 1.0
1318 * to assign `td->factor` exceeding 1.0. See #147530. */
1319 td->factor = std::min(1.0f, 3.0f * dist * dist - 2.0f * dist * dist * dist);
1320 break;
1321 case PROP_ROOT:
1322 td->factor = sqrtf(dist);
1323 break;
1324 case PROP_LIN:
1325 td->factor = dist;
1326 break;
1327 case PROP_CONST:
1328 td->factor = 1.0f;
1329 break;
1330 case PROP_SPHERE:
1331 td->factor = sqrtf(2 * dist - dist * dist);
1332 break;
1333 case PROP_RANDOM:
1334 if (t->rng == nullptr) {
1335 /* Lazy initialization. */
1336 uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
1337 t->rng = BLI_rng_new(rng_seed);
1338 }
1339 td->factor = BLI_rng_get_float(t->rng) * dist;
1340 break;
1341 case PROP_INVSQUARE:
1342 td->factor = dist * (2.0f - dist);
1343 break;
1344 default:
1345 td->factor = 1;
1346 break;
1347 }
1348 /* An assert here likely means clamping is needed. */
1349 BLI_assert(td->factor <= 1.0f);
1350 }
1351 }
1352 }
1353
1354 switch (t->prop_mode) {
1355 case PROP_SHARP:
1356 pet_id = N_("(Sharp)");
1357 break;
1358 case PROP_SMOOTH:
1359 pet_id = N_("(Smooth)");
1360 break;
1361 case PROP_ROOT:
1362 pet_id = N_("(Root)");
1363 break;
1364 case PROP_LIN:
1365 pet_id = N_("(Linear)");
1366 break;
1367 case PROP_CONST:
1368 pet_id = N_("(Constant)");
1369 break;
1370 case PROP_SPHERE:
1371 pet_id = N_("(Sphere)");
1372 break;
1373 case PROP_RANDOM:
1374 pet_id = N_("(Random)");
1375 break;
1376 case PROP_INVSQUARE:
1377 pet_id = N_("(InvSquare)");
1378 break;
1379 default:
1380 break;
1381 }
1382
1383 if (pet_id) {
1384 STRNCPY_UTF8(t->proptext, IFACE_(pet_id));
1385 }
1386 }
1387 else {
1389 TransData *td = tc->data;
1390 for (i = 0; i < tc->data_len; i++, td++) {
1391 td->factor = 1.0;
1392 }
1393 }
1394 }
1395}
1396
1398 TransDataExtension *td_ext,
1399 float mat[3][3],
1400 bool use_drot)
1401{
1402 float totmat[3][3];
1403 float smat[3][3];
1404 float fmat[3][3];
1405 float obmat[3][3];
1406
1407 float dmat[3][3]; /* Delta rotation. */
1408 float dmat_inv[3][3];
1409
1410 mul_m3_m3m3(totmat, mat, td->mtx);
1411 mul_m3_m3m3(smat, td->smtx, mat);
1412
1413 /* Logic from #BKE_object_rot_to_mat3. */
1414 if (use_drot) {
1415 if (td_ext->rotOrder > 0) {
1416 eulO_to_mat3(dmat, td_ext->drot, td_ext->rotOrder);
1417 }
1418 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
1419#if 0
1420 axis_angle_to_mat3(dmat, td_ext->drotAxis, td_ext->drotAngle);
1421#else
1422 unit_m3(dmat);
1423#endif
1424 }
1425 else {
1426 float tquat[4];
1427 normalize_qt_qt(tquat, td_ext->dquat);
1428 quat_to_mat3(dmat, tquat);
1429 }
1430
1431 invert_m3_m3(dmat_inv, dmat);
1432 }
1433
1434 if (td_ext->rotOrder == ROT_MODE_QUAT) {
1435 float quat[4];
1436
1437 /* Calculate the total rotation. */
1438 quat_to_mat3(obmat, td_ext->iquat);
1439 if (use_drot) {
1440 mul_m3_m3m3(obmat, dmat, obmat);
1441 }
1442
1443 /* `mat = transform`, `obmat = object rotation`. */
1444 mul_m3_m3m3(fmat, smat, obmat);
1445
1446 if (use_drot) {
1447 mul_m3_m3m3(fmat, dmat_inv, fmat);
1448 }
1449
1450 mat3_to_quat(quat, fmat);
1451
1452 /* Apply. */
1453 copy_qt_qt(td_ext->quat, quat);
1454 }
1455 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
1456 float axis[3], angle;
1457
1458 /* Calculate the total rotation. */
1459 axis_angle_to_mat3(obmat, td_ext->irotAxis, td_ext->irotAngle);
1460 if (use_drot) {
1461 mul_m3_m3m3(obmat, dmat, obmat);
1462 }
1463
1464 /* `mat = transform`, `obmat = object rotation`. */
1465 mul_m3_m3m3(fmat, smat, obmat);
1466
1467 if (use_drot) {
1468 mul_m3_m3m3(fmat, dmat_inv, fmat);
1469 }
1470
1471 mat3_to_axis_angle(axis, &angle, fmat);
1472
1473 /* Apply. */
1474 copy_v3_v3(td_ext->rotAxis, axis);
1475 *td_ext->rotAngle = angle;
1476 }
1477 else {
1478 float eul[3];
1479
1480 /* Calculate the total rotation. */
1481 eulO_to_mat3(obmat, td_ext->irot, td_ext->rotOrder);
1482 if (use_drot) {
1483 mul_m3_m3m3(obmat, dmat, obmat);
1484 }
1485
1486 /* `mat = transform`, `obmat = object rotation`. */
1487 mul_m3_m3m3(fmat, smat, obmat);
1488
1489 if (use_drot) {
1490 mul_m3_m3m3(fmat, dmat_inv, fmat);
1491 }
1492
1493 mat3_to_compatible_eulO(eul, td_ext->rot, td_ext->rotOrder, fmat);
1494
1495 /* Apply. */
1496 copy_v3_v3(td_ext->rot, eul);
1497 }
1498}
1499
1501{
1502 if (!(ob->mode & OB_MODE_ALL_WEIGHT_PAINT)) {
1503 return nullptr;
1504 }
1505 /* Important that ob_armature can be set even when its not selected #23412.
1506 * Lines below just check is also visible. */
1508 if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
1510 Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
1511 if (base_arm) {
1512 View3D *v3d = static_cast<View3D *>(t->view);
1513 if (BASE_VISIBLE(v3d, base_arm)) {
1514 return ob_armature;
1515 }
1516 }
1517 }
1518 return nullptr;
1519}
1520
1521} // namespace blender::ed::transform
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:764
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)
SpaceSeq * CTX_wm_space_seq(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)
Scene * CTX_data_sequencer_scene(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)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
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:437
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:476
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:645
#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:123
#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
@ PROP_EDIT_PROJECTED
@ PROP_EDIT_USE
@ PROP_EDIT_CONNECTED
@ UVCALC_TRANSFORM_CORRECT_SLIDE
@ PROP_SMOOTH
@ PROP_ROOT
@ PROP_SHARP
@ PROP_RANDOM
@ PROP_LIN
@ PROP_CONST
@ PROP_INVSQUARE
@ PROP_SPHERE
@ SCE_XFORM_AXIS_ALIGN
@ AUTO_MERGE
@ AUTO_MERGE_AND_SPLIT
#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
@ 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:70
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 MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1696
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1691
#define U
BMesh const char void * data
nullptr float
#define printf(...)
#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 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 transform_data_ext_rotate(TransData *td, TransDataExtension *td_ext, float mat[3][3], bool use_drot)
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)
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:427
float2 image_preview_unit_to_px(const Scene *scene, const float2 co_src)
VecBase< float, 2 > float2
#define sqrtf
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:633
TransDataCurveHandleFlags * hdata
Definition transform.hh:520
TransCustomDataContainer custom
Definition transform.hh:974
struct blender::ed::transform::TransInfo::@342160341045112220003361360177273117120157367076 orient[3]
TransDataContainer * data_container
Definition transform.hh:802
int mval[2]
Definition WM_types.hh:763
wmKeyMap * modalkeymap
Definition WM_types.hh:1145
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
#define TRANS_CUSTOM_DATA_ELEM_MAX
Definition transform.hh:651
#define TRANS_DATA_CONTAINER_FIRST_OK(t)
Definition transform.hh:37
#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)