Blender V4.3
transform_constraints.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
9#include <cmath>
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
13
14#include "DNA_object_types.h"
15#include "DNA_scene_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
18#include "DNA_view3d_types.h"
19
20#include "GPU_immediate.hh"
21#include "GPU_matrix.hh"
22#include "GPU_state.hh"
23
24#include "BLI_math_matrix.h"
25#include "BLI_math_rotation.h"
26#include "BLI_rect.h"
27#include "BLI_string.h"
28#include "BLI_utildefines.h"
29
30#include "ED_view3d.hh"
31
32#include "BLT_translation.hh"
33
34#include "UI_resources.hh"
35#include "UI_view2d.hh"
36
37#include "transform.hh"
38#include "transform_gizmo.hh"
40#include "transform_snap.hh"
41
42/* Own include. */
44
45using namespace blender;
46
47static void drawObjectConstraint(TransInfo *t);
48
49/* -------------------------------------------------------------------- */
53static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3])
54{
55 unit_m3(r_pmtx);
56
57 if (!(t->con.mode & CON_AXIS0)) {
58 zero_v3(r_pmtx[0]);
59 }
60
61 if (!(t->con.mode & CON_AXIS1)) {
62 zero_v3(r_pmtx[1]);
63 }
64
65 if (!(t->con.mode & CON_AXIS2)) {
66 zero_v3(r_pmtx[2]);
67 }
68
69 float mat[3][3];
70 mul_m3_m3m3(mat, r_pmtx, t->spacemtx_inv);
71 mul_m3_m3m3(r_pmtx, t->spacemtx, mat);
72}
73
74static void view_vector_calc(const TransInfo *t, const float focus[3], float r_vec[3])
75{
76 if (t->persp != RV3D_ORTHO) {
77 sub_v3_v3v3(r_vec, t->viewinv[3], focus);
78 }
79 else {
80 copy_v3_v3(r_vec, t->viewinv[2]);
81 }
82 normalize_v3(r_vec);
83}
84
85/* ************************** CONSTRAINTS ************************* */
86#define CONSTRAIN_EPSILON 0.0001f
87
88static void constraint_plane_normal_calc(const TransInfo *t, float r_plane_no[3])
89{
90 const float *constraint_vector[2];
91 int n = 0;
92 for (int i = 0; i < 3; i++) {
93 if (t->con.mode & (CON_AXIS0 << i)) {
94 constraint_vector[n++] = t->spacemtx[i];
95 if (n == 2) {
96 break;
97 }
98 }
99 }
100 BLI_assert(n == 2);
101
102 cross_v3_v3v3(r_plane_no, constraint_vector[0], constraint_vector[1]);
103 normalize_v3(r_plane_no);
104}
105
106void constraintNumInput(TransInfo *t, float vec[3])
107{
108 int mode = t->con.mode;
109 if (mode & CON_APPLY) {
110 float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
111
112 const int dims = getConstraintSpaceDimension(t);
113 if (dims == 2) {
114 int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
115 if (axis == (CON_AXIS0 | CON_AXIS1)) {
116 // vec[0] = vec[0]; /* Same. */
117 // vec[1] = vec[1]; /* Same. */
118 vec[2] = nval;
119 }
120 else if (axis == (CON_AXIS1 | CON_AXIS2)) {
121 vec[2] = vec[1];
122 vec[1] = vec[0];
123 vec[0] = nval;
124 }
125 else if (axis == (CON_AXIS0 | CON_AXIS2)) {
126 // vec[0] = vec[0]; /* Same. */
127 vec[2] = vec[1];
128 vec[1] = nval;
129 }
130 }
131 else if (dims == 1) {
132 if (mode & CON_AXIS0) {
133 // vec[0] = vec[0]; /* Same. */
134 vec[1] = nval;
135 vec[2] = nval;
136 }
137 else if (mode & CON_AXIS1) {
138 vec[1] = vec[0];
139 vec[0] = nval;
140 vec[2] = nval;
141 }
142 else if (mode & CON_AXIS2) {
143 vec[2] = vec[0];
144 vec[0] = nval;
145 vec[1] = nval;
146 }
147 }
148 }
149}
150
151static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
152{
153 if (t->spacetype == SPACE_VIEW3D) {
154 // View3D *v3d = t->area->spacedata.first;
155 const float min_dist = 1.0f; /* `v3d->clip_start`. */
156 float dir[3];
157 float l;
158
159 sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
160 if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
161 negate_v3(dir);
162 }
163 project_v3_v3v3(dir, dir, t->viewinv[2]);
164
165 l = len_v3(dir);
166
167 if (l < min_dist) {
168 float diff[3];
169 normalize_v3_v3_length(diff, t->viewinv[2], min_dist - l);
170 sub_v3_v3(t_con_center, diff);
171 }
172 }
173}
174
178static void axisProjection(const TransInfo *t,
179 const float axis[3],
180 const float in[3],
181 float out[3])
182{
183 float vec[3], factor, angle;
184 float t_con_center[3];
185
186 if (is_zero_v3(in)) {
187 return;
188 }
189
190 copy_v3_v3(t_con_center, t->center_global);
191
192 /* Checks for center being too close to the view center. */
193 viewAxisCorrectCenter(t, t_con_center);
194
195 angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
196 if (angle > float(M_PI_2)) {
197 angle = float(M_PI) - angle;
198 }
199
200 /* For when view is parallel to constraint... will cause NaNs otherwise
201 * So we take vertical motion in 3D space and apply it to the
202 * constraint axis. Nice for camera grab + MMB. */
203 if (angle < DEG2RADF(5.0f)) {
204 project_v3_v3v3(vec, in, t->viewinv[1]);
205 factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
206 /* Since camera distance is quite relative, use quadratic relationship.
207 * holding shift can compensate. */
208 if (factor < 0.0f) {
209 factor *= -factor;
210 }
211 else {
212 factor *= factor;
213 }
214
215 /* -factor makes move down going backwards. */
216 normalize_v3_v3_length(out, axis, -factor);
217 }
218 else {
219 float v[3];
220 float norm[3], norm_center[3];
221 float plane[3];
222
223 view_vector_calc(t, t_con_center, norm_center);
224 cross_v3_v3v3(plane, norm_center, axis);
225
226 project_v3_v3v3(vec, in, plane);
227 sub_v3_v3v3(vec, in, vec);
228
229 add_v3_v3v3(v, vec, t_con_center);
231
232 /* Give arbitrary large value if projection is impossible. */
233 factor = dot_v3v3(axis, norm);
234 if (1.0f - fabsf(factor) < 0.0002f) {
235 copy_v3_v3(out, axis);
236 if (factor > 0) {
237 mul_v3_fl(out, 1000000000.0f);
238 }
239 else {
240 mul_v3_fl(out, -1000000000.0f);
241 }
242 }
243 else {
244 /* Use ray-ray intersection instead of line-line because this gave
245 * precision issues adding small values to large numbers. */
246 float mul;
247 if (isect_ray_ray_v3(t_con_center, axis, v, norm, &mul, nullptr)) {
248 mul_v3_v3fl(out, axis, mul);
249 }
250 else {
251 /* In practice this should never fail. */
252 BLI_assert(0);
253 }
254
255 /* Possible some values become nan when viewpoint and object are both zero. */
256 if (!isfinite(out[0])) {
257 out[0] = 0.0f;
258 }
259 if (!isfinite(out[1])) {
260 out[1] = 0.0f;
261 }
262 if (!isfinite(out[2])) {
263 out[2] = 0.0f;
264 }
265 }
266 }
267}
268
273 const float plane_no[3],
274 float r_out[3])
275{
276 float lambda;
277 const float *edge_snap_point = t->tsnap.snap_target;
278 const float *edge_dir = t->tsnap.snapNormal;
279 bool is_aligned = fabsf(dot_v3v3(edge_dir, plane_no)) < CONSTRAIN_EPSILON;
280 if (!is_aligned && isect_ray_plane_v3_factor(
281 edge_snap_point, edge_dir, t->tsnap.snap_source, plane_no, &lambda))
282 {
283 madd_v3_v3v3fl(r_out, edge_snap_point, edge_dir, lambda);
284 sub_v3_v3(r_out, t->tsnap.snap_source);
285 }
286}
287
288static void UNUSED_FUNCTION(constraint_snap_plane_to_face(const TransInfo *t,
289 const float plane[4],
290 float r_out[3]))
291{
292 float face_plane[4], isect_orig[3], isect_dir[3];
293 const float *face_snap_point = t->tsnap.snap_target;
294 const float *face_normal = t->tsnap.snapNormal;
295 plane_from_point_normal_v3(face_plane, face_snap_point, face_normal);
296 bool is_aligned = fabsf(dot_v3v3(plane, face_plane)) > (1.0f - CONSTRAIN_EPSILON);
297 if (!is_aligned && isect_plane_plane_v3(plane, face_plane, isect_orig, isect_dir)) {
298 closest_to_ray_v3(r_out, face_snap_point, isect_orig, isect_dir);
299 sub_v3_v3(r_out, t->tsnap.snap_source);
300 }
301}
302
304 const float axis[3],
305 float r_out[3])
306{
307 float lambda;
308 const float *edge_snap_point = t->tsnap.snap_target;
309 const float *edge_dir = t->tsnap.snapNormal;
310 bool is_aligned = fabsf(dot_v3v3(axis, edge_dir)) > (1.0f - CONSTRAIN_EPSILON);
311 if (!is_aligned &&
312 isect_ray_ray_v3(t->tsnap.snap_source, axis, edge_snap_point, edge_dir, &lambda, nullptr))
313 {
314 mul_v3_v3fl(r_out, axis, lambda);
315 }
316}
317
319 const float axis[3],
320 float r_out[3])
321{
322 float lambda;
323 const float *face_snap_point = t->tsnap.snap_target;
324 const float *face_normal = t->tsnap.snapNormal;
325 bool is_aligned = fabsf(dot_v3v3(axis, face_normal)) < CONSTRAIN_EPSILON;
326 if (!is_aligned &&
327 isect_ray_plane_v3_factor(t->tsnap.snap_source, axis, face_snap_point, face_normal, &lambda))
328 {
329 mul_v3_v3fl(r_out, axis, lambda);
330 }
331}
332
337static bool isPlaneProjectionViewAligned(const TransInfo *t, const float plane_no[3])
338{
339 const float eps = 0.001f;
340 float view_to_plane[3];
341 view_vector_calc(t, t->center_global, view_to_plane);
342
343 float factor = dot_v3v3(plane_no, view_to_plane);
344 return fabsf(factor) < eps;
345}
346
347static void planeProjection(const TransInfo *t,
348 const float plane_no[3],
349 const float in[3],
350 float out[3])
351{
352
353 float pos[3], view_vec[3], factor;
354
356 view_vector_calc(t, pos, view_vec);
357
358 if (isect_ray_plane_v3_factor(pos, view_vec, t->center_global, plane_no, &factor)) {
359 madd_v3_v3v3fl(out, in, view_vec, factor);
360 }
361}
362
364{
365 short orientation = t->orient[t->orient_curr].type;
366 if (orientation == V3D_ORIENT_CUSTOM_MATRIX) {
367 /* Use the real value of the "orient_type". */
368 orientation = t->orient[O_DEFAULT].type;
369 }
370 return orientation;
371}
372
374 const TransDataContainer * /*tc*/,
375 const TransData *td))[3]
376{
378 BLI_assert(t->orient_type_mask & (1 << V3D_ORIENT_GIMBAL));
379 if (t->options & (CTX_POSE_BONE | CTX_OBJECT)) {
380 return td->ext->axismtx_gimbal;
381 }
382 }
383 return td->axismtx;
384}
385
386void transform_constraint_get_nearest(const TransInfo *t, const float3 &vec, float r_vec[3])
387{
388 bool is_snap_to_point = false, is_snap_to_edge = false, is_snap_to_face = false;
389
391 if (validSnap(t)) {
392 is_snap_to_edge = (t->tsnap.target_type & SCE_SNAP_TO_EDGE) != 0;
393 is_snap_to_face = (t->tsnap.target_type & SCE_SNAP_TO_FACE) != 0;
394 is_snap_to_point = !is_snap_to_edge && !is_snap_to_face;
395 }
396 }
397
398 /* Fallback for when axes are aligned. */
399 mul_v3_m3v3(r_vec, t->con.pmtx, vec);
400
401 if (is_snap_to_point) {
402 /* Pass. With snap points, a projection is alright, no adjustments needed. */
403 }
404 else {
405 const int dims = getConstraintSpaceDimension(t);
406 if (dims == 2) {
407 if (!is_zero_v3(r_vec)) {
408 float plane_no[3];
409 constraint_plane_normal_calc(t, plane_no);
410
411 if (is_snap_to_edge) {
412 constraint_snap_plane_to_edge(t, plane_no, r_vec);
413 }
414 else if (is_snap_to_face) {
415 /* Disabled, as it has not proven to be really useful. (See #82386). */
416 // constraint_snap_plane_to_face(t, plane, out);
417 }
418 else if (!isPlaneProjectionViewAligned(t, plane_no)) {
419 /* View alignment correction. */
420 planeProjection(t, plane_no, vec, r_vec);
421 }
422 }
423 }
424 else if (dims == 1) {
425 float c[3];
426
427 if (t->con.mode & CON_AXIS0) {
428 copy_v3_v3(c, t->spacemtx[0]);
429 }
430 else if (t->con.mode & CON_AXIS1) {
431 copy_v3_v3(c, t->spacemtx[1]);
432 }
433 else {
435 copy_v3_v3(c, t->spacemtx[2]);
436 }
437
438 if (is_snap_to_edge) {
440 }
441 else if (is_snap_to_face) {
443 }
444 else {
445 /* View alignment correction. */
446 axisProjection(t, c, vec, r_vec);
447 }
448 }
449 }
450}
451
460 const TransDataContainer * /*tc*/,
461 const TransData *td,
462 const float in[3],
463 float out[3])
464{
465 if (td || !(t->con.mode & CON_APPLY)) {
466 copy_v3_v3(out, in);
467 return;
468 }
469
471}
472
484 const TransDataContainer *tc,
485 const TransData *td,
486 const float in[3],
487 float out[3])
488{
489 if (!td) {
490 applyAxisConstraintVec(t, tc, td, in, out);
491 }
492 else {
493 /* Specific TransData's space. */
494 copy_v3_v3(out, in);
495 if (t->con.mode & CON_APPLY) {
496 mul_m3_v3(t->spacemtx_inv, out);
497 const float(*axismtx)[3] = transform_object_axismtx_get(t, tc, td);
498 mul_m3_v3(axismtx, out);
499 if (t->flag & T_EDIT) {
500 mul_m3_v3(tc->mat3_unit, out);
501 }
502 }
503 }
504}
505
510 const TransDataContainer * /*tc*/,
511 const TransData *td,
512 float r_smat[3][3])
513{
514 if (!td && t->con.mode & CON_APPLY) {
515 float tmat[3][3];
516
517 if (!(t->con.mode & CON_AXIS0)) {
518 r_smat[0][0] = 1.0f;
519 }
520 if (!(t->con.mode & CON_AXIS1)) {
521 r_smat[1][1] = 1.0f;
522 }
523 if (!(t->con.mode & CON_AXIS2)) {
524 r_smat[2][2] = 1.0f;
525 }
526
527 mul_m3_m3m3(tmat, r_smat, t->spacemtx_inv);
528 mul_m3_m3m3(r_smat, t->spacemtx, tmat);
529 }
530}
531
536 const TransDataContainer *tc,
537 const TransData *td,
538 float r_smat[3][3])
539{
540 if (td && t->con.mode & CON_APPLY) {
541 float tmat[3][3];
542 float imat[3][3];
543
544 const float(*axismtx)[3] = transform_object_axismtx_get(t, tc, td);
545 invert_m3_m3(imat, axismtx);
546
547 if (!(t->con.mode & CON_AXIS0)) {
548 r_smat[0][0] = 1.0f;
549 }
550 if (!(t->con.mode & CON_AXIS1)) {
551 r_smat[1][1] = 1.0f;
552 }
553 if (!(t->con.mode & CON_AXIS2)) {
554 r_smat[2][2] = 1.0f;
555 }
556
557 mul_m3_m3m3(tmat, r_smat, imat);
558 if (t->flag & T_EDIT) {
559 mul_m3_m3m3(r_smat, tc->mat3_unit, r_smat);
560 }
561 mul_m3_m3m3(r_smat, axismtx, tmat);
562 }
563}
564
566 const float axismtx[3][3],
567 float r_axis[3],
568 float *r_angle)
569{
571 int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
572
573 switch (mode) {
574 case CON_AXIS0:
575 case (CON_AXIS1 | CON_AXIS2):
576 copy_v3_v3(r_axis, axismtx[0]);
577 break;
578 case CON_AXIS1:
579 case (CON_AXIS0 | CON_AXIS2):
580 copy_v3_v3(r_axis, axismtx[1]);
581 break;
582 case CON_AXIS2:
583 case (CON_AXIS0 | CON_AXIS1):
584 copy_v3_v3(r_axis, axismtx[2]);
585 break;
586 }
587 /* Don't flip axis if asked to or if num input. */
588 if (r_angle &&
589 !((mode & CON_NOFLIP) || hasNumInput(&t->num) || (t->flag & T_INPUT_IS_VALUES_FINAL)))
590 {
591 float view_vector[3];
592 view_vector_calc(t, t->center_global, view_vector);
593 if (dot_v3v3(r_axis, view_vector) > 0.0f) {
594 *r_angle = -(*r_angle);
595 }
596 }
597}
598
613 const TransDataContainer * /*tc*/,
614 const TransData *td,
615 float r_axis[3],
616 float *r_angle)
617{
618 if (!td && t->con.mode & CON_APPLY) {
619 constraints_rotation_impl(t, t->spacemtx, r_axis, r_angle);
620 }
621}
622
637 const TransDataContainer *tc,
638 const TransData *td,
639 float r_axis[3],
640 float *r_angle)
641{
642 if (t->con.mode & CON_APPLY) {
643 float tmp_axismtx[3][3];
644 const float(*axismtx)[3];
645
646 /* On setup call, use first object. */
647 if (td == nullptr) {
648 BLI_assert(tc == nullptr);
650 td = tc->data;
651 }
652
653 if (t->flag & T_EDIT) {
654 mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
655 axismtx = tmp_axismtx;
656 }
657 else {
658 axismtx = transform_object_axismtx_get(t, tc, td);
659 }
660
661 constraints_rotation_impl(t, axismtx, r_axis, r_angle);
662 }
663}
664
667/* -------------------------------------------------------------------- */
671void setConstraint(TransInfo *t, int mode, const char text[])
672{
673 BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
674 t->con.mode = eTConstraint(mode);
676
678
679 t->con.drawExtra = nullptr;
683 t->redraw = TREDRAW_HARD;
684}
685
686void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
687{
688 BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
689 t->con.mode = eTConstraint(mode);
691
693
698 t->redraw = TREDRAW_HARD;
699}
700
701void setLocalConstraint(TransInfo *t, int mode, const char text[])
702{
703 if ((t->flag & T_EDIT) || t->data_len_all == 1) {
704 /* Although in edit-mode each object has its local space, use the
705 * orientation of the active object. */
706 setConstraint(t, mode, text);
707 }
708 else {
709 setAxisMatrixConstraint(t, mode, text);
710 }
711}
712
713void setUserConstraint(TransInfo *t, int mode, const char text_[])
714{
715 char text[256];
716 const short orientation = transform_orientation_or_default(t);
717 const char *spacename = transform_orientations_spacename_get(t, orientation);
718 SNPRINTF(text, text_, spacename);
719
720 switch (orientation) {
721 case V3D_ORIENT_LOCAL:
723 setLocalConstraint(t, mode, text);
724 break;
726 if (checkUseAxisMatrix(t)) {
727 setAxisMatrixConstraint(t, mode, text);
728 break;
729 }
732 case V3D_ORIENT_VIEW:
736 default: {
737 setConstraint(t, mode, text);
738 break;
739 }
740 }
741 t->con.mode |= CON_USER;
742}
743
746/* -------------------------------------------------------------------- */
750static void drawLine(
751 TransInfo *t, const float center[3], const float dir[3], char axis, short options)
752{
754 return;
755 }
756
757 float v1[3], v2[3], v3[3];
758 uchar col[3], col2[3];
759
760 if (t->spacetype == SPACE_VIEW3D) {
761 View3D *v3d = static_cast<View3D *>(t->view);
762
763 copy_v3_v3(v3, dir);
764 mul_v3_fl(v3, v3d->clip_end);
765
766 sub_v3_v3v3(v2, center, v3);
767 add_v3_v3v3(v1, center, v3);
768 }
769 else if (t->spacetype == SPACE_SEQ) {
770 View2D *v2d = static_cast<View2D *>(t->view);
771
772 copy_v3_v3(v3, dir);
773 float max_dist = max_ff(BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur));
774 mul_v3_fl(v3, max_dist);
775
776 sub_v3_v3v3(v2, center, v3);
777 add_v3_v3v3(v1, center, v3);
778 }
779
781
782 if (options & DRAWLIGHT) {
783 col[0] = col[1] = col[2] = 220;
784 }
785 else {
787 }
788 UI_make_axis_color(col, axis, col2);
789
791
792 float viewport[4];
793 GPU_viewport_size_get_f(viewport);
795
797 immUniform2fv("viewportSize", &viewport[2]);
798 immUniform1f("lineWidth", U.pixelsize * 2.0f);
799
801
803 immVertex3fv(pos, v1);
805 immEnd();
806
808
810}
811
813{
814 TransCon *tc = &(t->con);
815
817 return;
818 }
819 if (!(tc->mode & CON_APPLY)) {
820 return;
821 }
822 if (t->flag & T_NO_CONSTRAINT) {
823 return;
824 }
825
826 if (tc->drawExtra) {
827 tc->drawExtra(t);
828 }
829 else {
830 if (tc->mode & CON_SELECT) {
831 float vec[3];
832
833 convertViewVec(t, vec, (t->mval[0] - t->mouse.imval[0]), (t->mval[1] - t->mouse.imval[1]));
834 add_v3_v3(vec, t->center_global);
835
836 drawLine(t, t->center_global, t->spacemtx[0], 'X', 0);
837 drawLine(t, t->center_global, t->spacemtx[1], 'Y', 0);
838 drawLine(t, t->center_global, t->spacemtx[2], 'Z', 0);
839
840 eGPUDepthTest depth_test_enabled = GPU_depth_test_get();
841 if (depth_test_enabled) {
843 }
844
845 const uint shdr_pos = GPU_vertformat_attr_add(
847
849
850 float viewport_size[4];
851 GPU_viewport_size_get_f(viewport_size);
852 immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
853
854 immUniform1i("colors_len", 0); /* "simple" mode. */
855 immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
856 immUniform1f("dash_width", 2.0f);
857 immUniform1f("udash_factor", 0.5f);
858
860 immVertex3fv(shdr_pos, t->center_global);
861 immVertex3fv(shdr_pos, vec);
862 immEnd();
863
865
866 if (depth_test_enabled) {
868 }
869 }
870
871 if (tc->mode & CON_AXIS0) {
872 drawLine(t, t->center_global, t->spacemtx[0], 'X', DRAWLIGHT);
873 }
874 if (tc->mode & CON_AXIS1) {
875 drawLine(t, t->center_global, t->spacemtx[1], 'Y', DRAWLIGHT);
876 }
877 if (tc->mode & CON_AXIS2) {
878 drawLine(t, t->center_global, t->spacemtx[2], 'Z', DRAWLIGHT);
879 }
880 }
881}
882
884{
885 if (t->flag & T_PROP_EDIT) {
886 const RegionView3D *rv3d = nullptr;
887 float tmat[4][4], imat[4][4];
888
889 if (t->spacetype == SPACE_VIEW3D) {
890 if (t->region && (t->region->regiontype == RGN_TYPE_WINDOW)) {
891 rv3d = static_cast<const RegionView3D *>(t->region->regiondata);
892 }
893 }
894
895 if (rv3d != nullptr) {
896 copy_m4_m4(tmat, rv3d->viewmat);
897 invert_m4_m4(imat, tmat);
898 }
899 else {
900 unit_m4(tmat);
901 unit_m4(imat);
902 }
903
905
906 if (t->spacetype == SPACE_VIEW3D) {
907 /* Pass. */
908 }
909 else if (t->spacetype == SPACE_IMAGE) {
910 GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
911 }
912
913 eGPUDepthTest depth_test_enabled = GPU_depth_test_get();
914 if (depth_test_enabled) {
916 }
917
919
921
922 float viewport[4];
923 GPU_viewport_size_get_f(viewport);
925
926 immUniform2fv("viewportSize", &viewport[2]);
927 immUniform1f("lineWidth", 3.0f * U.pixelsize);
928
931
932 immUniform1f("lineWidth", 1.0f * U.pixelsize);
935
937
938 if (depth_test_enabled) {
940 }
941
943 }
944}
945
947{
948 if ((t->flag & T_PROP_EDIT) == 0) {
949 return;
950 }
951
953
955
956 float viewport[4];
957 GPU_viewport_size_get_f(viewport);
959
960 immUniform2fv("viewportSize", &viewport[2]);
961
962 View2D *v2d = &t->region->v2d;
963 const float x1 = t->center_global[0] - t->prop_size;
964 const float y1 = v2d->cur.ymin;
965 const float x2 = t->center_global[0] + t->prop_size;
966 const float y2 = v2d->cur.ymax;
967
968 immUniform1f("lineWidth", 3.0f * U.pixelsize);
970 imm_draw_box_wire_3d(pos, x1, y1, x2, y2);
971
972 immUniform1f("lineWidth", 1.0f * U.pixelsize);
974 imm_draw_box_wire_3d(pos, x1, y1, x2, y2);
975
978}
979
981{
982 /* Draw the first one lighter because that's the one who controls the others.
983 * Meaning the transformation is projected on that one and just copied on the others
984 * constraint space.
985 * In a nutshell, the object with light axis is controlled by the user and the others follow.
986 * Without drawing the first light, users have little clue what they are doing.
987 */
988 short options = DRAWLIGHT;
989 float tmp_axismtx[3][3];
990
992 TransData *td = tc->data;
993 for (int i = 0; i < tc->data_len; i++, td++) {
994 float co[3];
995 const float(*axismtx)[3];
996
997 if (t->flag & T_PROP_EDIT) {
998 /* We're sorted, so skip the rest. */
999 if (td->factor == 0.0f) {
1000 break;
1001 }
1002 }
1003
1004 if (t->options & CTX_GPENCIL_STROKES) {
1005 /* Only draw a constraint line for one point, otherwise we can't see anything. */
1006 if ((options & DRAWLIGHT) == 0) {
1007 break;
1008 }
1009 }
1010
1011 if (t->options & CTX_SEQUENCER_IMAGE) {
1012 /* Because we construct an "L" shape to deform the sequence, we should skip
1013 * all points except the first vertex. Otherwise we will draw the same axis constraint line
1014 * 3 times for each strip.
1015 */
1016 if (i % 3 != 0) {
1017 continue;
1018 }
1019 }
1020
1021 if (t->flag & T_EDIT) {
1022 mul_v3_m4v3(co, tc->mat, td->center);
1023
1024 mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
1025 axismtx = tmp_axismtx;
1026 }
1027 else {
1028 if (t->options & CTX_POSE_BONE) {
1029 mul_v3_m4v3(co, tc->mat, td->center);
1030 }
1031 else {
1032 copy_v3_v3(co, td->center);
1033 }
1034 axismtx = transform_object_axismtx_get(t, tc, td);
1035 }
1036
1037 if (t->con.mode & CON_AXIS0) {
1038 drawLine(t, co, axismtx[0], 'X', options);
1039 }
1040 if (t->con.mode & CON_AXIS1) {
1041 drawLine(t, co, axismtx[1], 'Y', options);
1042 }
1043 if (t->con.mode & CON_AXIS2) {
1044 drawLine(t, co, axismtx[2], 'Z', options);
1045 }
1046 options &= ~DRAWLIGHT;
1047 }
1048 }
1049}
1050
1053/* -------------------------------------------------------------------- */
1058{
1059 t->con.mode |= CON_APPLY;
1060 *t->con.text = ' ';
1062}
1063
1065{
1066 if (t->orient_curr != O_DEFAULT) {
1068 }
1069
1070 t->con.mode &= ~(CON_APPLY | CON_SELECT);
1071 *t->con.text = '\0';
1072 t->num.idx_max = t->idx_max;
1073}
1074
1077/* -------------------------------------------------------------------- */
1082{
1083 if (t->orient_curr == O_DEFAULT) {
1085 }
1086
1088}
1089
1091{
1092 if (t->con.mode & CON_SELECT) {
1093 setNearestAxis(t);
1094 startConstraint(t);
1095 }
1096}
1097
1099{
1100 t->con.mode &= ~CON_SELECT;
1101 if (!(t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2))) {
1102 t->con.mode &= ~CON_APPLY;
1103 }
1104}
1105
1107{
1108 /* Clear any prior constraint flags. */
1109 t->con.mode &= ~(CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
1110
1111 /* No correction needed... just use whichever one is lower. */
1112 blender::float2 dvec = t->mval - t->mouse.imval;
1113 if (abs(dvec.x) < abs(dvec.y)) {
1114 t->con.mode |= CON_AXIS1;
1115 STRNCPY(t->con.text, IFACE_(" along Y axis"));
1116 }
1117 else {
1118 t->con.mode |= CON_AXIS0;
1119 STRNCPY(t->con.text, IFACE_(" along X axis"));
1120 }
1121}
1122
1124{
1125 /* Clear any prior constraint flags. */
1126 t->con.mode &= ~(CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
1127
1128 float zfac;
1129 float mvec[3], proj[3];
1130 float len[3];
1131 int i;
1132
1133 /* Calculate mouse movement. */
1134 mvec[0] = t->mval[0] - t->mouse.imval[0];
1135 mvec[1] = t->mval[1] - t->mouse.imval[1];
1136 mvec[2] = 0.0f;
1137
1138 /* We need to correct axis length for the current zoom-level of view,
1139 * this to prevent projected values to be clipped behind the camera
1140 * and to overflow the short integers.
1141 * The formula used is a bit stupid, just a simplification of the subtraction
1142 * of two 2D points 30 pixels apart (that's the last factor in the formula) after
1143 * projecting them with #ED_view3d_win_to_delta and then get the length of that vector. */
1145 zfac = len_v3(t->persinv[0]) * 2.0f / t->region->winx * zfac * 30.0f;
1146
1147 for (i = 0; i < 3; i++) {
1148 float axis[3], axis_2d[2];
1149
1150 copy_v3_v3(axis, t->spacemtx[i]);
1151
1152 mul_v3_fl(axis, zfac);
1153 /* Now we can project to get window coordinate. */
1154 add_v3_v3(axis, t->center_global);
1155 projectFloatView(t, axis, axis_2d);
1156
1157 sub_v2_v2v2(axis, axis_2d, t->center2d);
1158 axis[2] = 0.0f;
1159
1160 if (normalize_v3(axis) > 1e-3f) {
1161 project_v3_v3v3(proj, mvec, axis);
1162 sub_v3_v3v3(axis, mvec, proj);
1163 len[i] = normalize_v3(axis);
1164 }
1165 else {
1166 len[i] = 1e10f;
1167 }
1168 }
1169
1170 if (len[0] <= len[1] && len[0] <= len[2]) {
1172 t->con.mode |= (CON_AXIS1 | CON_AXIS2);
1173 SNPRINTF(t->con.text, IFACE_(" locking %s X axis"), t->spacename);
1174 }
1175 else {
1176 t->con.mode |= CON_AXIS0;
1177 SNPRINTF(t->con.text, IFACE_(" along %s X axis"), t->spacename);
1178 }
1179 }
1180 else if (len[1] <= len[0] && len[1] <= len[2]) {
1182 t->con.mode |= (CON_AXIS0 | CON_AXIS2);
1183 SNPRINTF(t->con.text, IFACE_(" locking %s Y axis"), t->spacename);
1184 }
1185 else {
1186 t->con.mode |= CON_AXIS1;
1187 SNPRINTF(t->con.text, IFACE_(" along %s Y axis"), t->spacename);
1188 }
1189 }
1190 else if (len[2] <= len[1] && len[2] <= len[0]) {
1192 t->con.mode |= (CON_AXIS0 | CON_AXIS1);
1193 SNPRINTF(t->con.text, IFACE_(" locking %s Z axis"), t->spacename);
1194 }
1195 else {
1196 t->con.mode |= CON_AXIS2;
1197 SNPRINTF(t->con.text, IFACE_(" along %s Z axis"), t->spacename);
1198 }
1199 }
1200}
1201
1203{
1204 eTConstraint mode_prev = t->con.mode;
1205
1206 /* Constraint setting - depends on spacetype. */
1207 if (t->spacetype == SPACE_VIEW3D) {
1208 /* 3d-view. */
1210 }
1211 else {
1212 /* Assume that this means a 2D-Editor. */
1214 }
1215
1216 if (mode_prev != t->con.mode) {
1219 }
1220}
1221
1224/* -------------------------------------------------------------------- */
1229{
1230 if ((t->con.mode & CON_APPLY) == 0) {
1231 return -1;
1232 }
1233 switch (int(t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2))) {
1234 case (CON_AXIS0):
1235 case (CON_AXIS1 | CON_AXIS2):
1236 return 0;
1237 case (CON_AXIS1):
1238 case (CON_AXIS0 | CON_AXIS2):
1239 return 1;
1240 case (CON_AXIS2):
1241 case (CON_AXIS0 | CON_AXIS1):
1242 return 2;
1243 default:
1244 return -1;
1245 }
1246}
1247
1249{
1250 int mode = t->con.mode;
1251
1252 if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1)) {
1253 return true;
1254 }
1255
1256 if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2)) {
1257 return true;
1258 }
1259
1260 if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2)) {
1261 return true;
1262 }
1263
1264 return false;
1265}
1266
1268{
1269 int n = 0;
1270
1271 if (t->con.mode & CON_AXIS0) {
1272 n++;
1273 }
1274
1275 if (t->con.mode & CON_AXIS1) {
1276 n++;
1277 }
1278
1279 if (t->con.mode & CON_AXIS2) {
1280 n++;
1281 }
1282
1283 return n;
1284 /* Someone willing to do it cryptically could do the following instead:
1285 *
1286 * `return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);`
1287 *
1288 * Based on the assumptions that the axis flags are one after the other and start at 1
1289 */
1290}
1291
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ATTR_FALLTHROUGH
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
#define M_PI_2
#define M_PI
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
bool isect_ray_ray_v3(const float ray_origin_a[3], const float ray_direction_a[3], const float ray_origin_b[3], const float ray_direction_b[3], float *r_lambda_a, float *r_lambda_b)
float closest_to_ray_v3(float r_close[3], const float p[3], const float ray_orig[3], const float ray_dir[3])
bool isect_plane_plane_v3(const float plane_a[4], const float plane_b[4], float r_isect_co[3], float r_isect_no[3]) ATTR_WARN_UNUSED_RESULT
bool isect_ray_plane_v3_factor(const float ray_origin[3], const float ray_direction[3], const float plane_co[3], const float plane_no[3], float *r_lambda)
void mul_m3_v3(const float M[3][3], float r[3])
void unit_m3(float m[3][3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
#define DEG2RADF(_deg)
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3_length(float r[3], const float a[3], float unit_length)
MINLINE void negate_v3(float r[3])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
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
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned char uchar
unsigned int uint
#define UNUSED_FUNCTION(x)
#define ELEM(...)
#define IFACE_(msgid)
Object is a sort of wrapper for general info.
@ SCE_SNAP_TO_EDGE
@ SCE_SNAP_TO_FACE
@ RGN_TYPE_WINDOW
@ SPACE_NODE
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ RV3D_ORTHO
@ V3D_ORIENT_NORMAL
@ V3D_ORIENT_CUSTOM
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_CUSTOM_MATRIX
@ V3D_ORIENT_LOCAL
@ V3D_ORIENT_VIEW
@ V3D_ORIENT_CURSOR
@ V3D_ORIENT_GIMBAL
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void immEnd()
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram()
void immUniform2f(const char *name, float x, float y)
void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
void immUniformColor4f(float r, float g, float b, float a)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformColor3ubv(const unsigned char rgb[3])
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void imm_drawcircball(const float cent[3], float radius, const float tmat[4][4], uint pos)
void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_pop()
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
eGPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:239
eGPUDepthTest
Definition GPU_state.hh:107
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
@ TH_GRID
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
void UI_make_axis_color(const unsigned char col[3], char axis, unsigned char r_col[3])
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition btGjkEpa3.h:78
static void mul(btAlignedObjectArray< T > &items, const Q &value)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
CCL_NAMESPACE_BEGIN struct Options options
#define fabsf(x)
int len
bool checkUseAxisMatrix(TransInfo *t)
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
draw_view in_light_buf[] float
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
uint col
const btScalar eps
Definition poly34.cpp:11
void * regiondata
blender::float2 imval
Definition transform.hh:383
short idx_max
float viewmat[4][4]
void(* applySize)(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_smat[3][3])
Definition transform.hh:366
char text[50]
Definition transform.hh:347
void(* applyRot)(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_axis[3], float *r_angle)
Definition transform.hh:371
float pmtx[3][3]
Definition transform.hh:349
void(* applyVec)(const TransInfo *t, const TransDataContainer *tc, const TransData *td, const float in[3], float r_out[3])
Definition transform.hh:360
eTConstraint mode
Definition transform.hh:351
void(* drawExtra)(TransInfo *t)
Definition transform.hh:352
float mat3_unit[3][3]
Definition transform.hh:469
TransData * data
Definition transform.hh:445
float axismtx[3][3]
struct TransInfo::@565 orient[3]
void * view
Definition transform.hh:647
char spacetype
Definition transform.hh:582
float viewinv[4][4]
Definition transform.hh:575
short persp
Definition transform.hh:579
eRedrawFlag redraw
Definition transform.hh:529
int data_len_all
Definition transform.hh:510
float spacemtx_inv[3][3]
Definition transform.hh:593
float prop_size
Definition transform.hh:546
float center2d[2]
Definition transform.hh:557
TransSnap tsnap
Definition transform.hh:537
short idx_max
Definition transform.hh:559
eTModifier modifiers
Definition transform.hh:525
NumInput num
Definition transform.hh:540
float aspect[3]
Definition transform.hh:553
eTOType orient_curr
Definition transform.hh:613
eTFlag flag
Definition transform.hh:523
ARegion * region
Definition transform.hh:652
MouseInput mouse
Definition transform.hh:543
float persmat[4][4]
Definition transform.hh:577
char spacename[64]
Definition transform.hh:595
TransCon con
Definition transform.hh:534
float center_global[3]
Definition transform.hh:555
blender::float2 mval
Definition transform.hh:663
float spacemtx[3][3]
Definition transform.hh:592
eTContext options
Definition transform.hh:521
float persinv[4][4]
Definition transform.hh:578
short type
Definition transform.hh:609
float snapNormal[3]
Definition transform.hh:328
float snap_target[3]
Definition transform.hh:327
float snap_source[3]
Definition transform.hh:325
eSnapMode target_type
Definition transform.hh:321
float ymax
float ymin
#define DRAWLIGHT
Definition transform.hh:802
eTConstraint
Definition transform.hh:191
@ CON_NOFLIP
Definition transform.hh:200
@ CON_APPLY
Definition transform.hh:193
@ CON_SELECT
Definition transform.hh:198
@ CON_AXIS1
Definition transform.hh:196
@ CON_USER
Definition transform.hh:201
@ CON_AXIS0
Definition transform.hh:195
@ CON_AXIS2
Definition transform.hh:197
@ CTX_SEQUENCER_IMAGE
Definition transform.hh:75
@ CTX_POSE_BONE
Definition transform.hh:73
@ CTX_OBJECT
Definition transform.hh:71
@ CTX_GPENCIL_STROKES
Definition transform.hh:68
@ MOD_CONSTRAINT_SELECT_PLANE
Definition transform.hh:165
#define TRANS_DATA_CONTAINER_FIRST_OK(t)
Definition transform.hh:849
@ TREDRAW_HARD
Definition transform.hh:217
@ O_DEFAULT
Definition transform.hh:233
@ O_SCENE
Definition transform.hh:234
@ T_PROP_EDIT
Definition transform.hh:98
@ T_INPUT_IS_VALUES_FINAL
Definition transform.hh:115
@ T_NO_CONSTRAINT
Definition transform.hh:95
@ T_NULL_ONE
Definition transform.hh:96
@ T_EDIT
Definition transform.hh:91
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
static void drawObjectConstraint(TransInfo *t)
static void constraints_rotation_impl(const TransInfo *t, const float axismtx[3][3], float r_axis[3], float *r_angle)
bool isLockConstraint(const TransInfo *t)
#define CONSTRAIN_EPSILON
void drawConstraint(TransInfo *t)
void drawPropCircle(TransInfo *t)
void setUserConstraint(TransInfo *t, int mode, const char text_[])
static void applyAxisConstraintSize(const TransInfo *t, const TransDataContainer *, const TransData *td, float r_smat[3][3])
static void planeProjection(const TransInfo *t, const float plane_no[3], const float in[3], float out[3])
void startConstraint(TransInfo *t)
static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3])
void setConstraint(TransInfo *t, int mode, const char text[])
static bool isPlaneProjectionViewAligned(const TransInfo *t, const float plane_no[3])
static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
int constraintModeToIndex(const TransInfo *t)
static void constraint_plane_normal_calc(const TransInfo *t, float r_plane_no[3])
static const float(* transform_object_axismtx_get(const TransInfo *t, const TransDataContainer *, const TransData *td))[3]
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
static void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
void setNearestAxis(TransInfo *t)
void transform_constraint_snap_axis_to_face(const TransInfo *t, const float axis[3], float r_out[3])
static void setNearestAxis3d(TransInfo *t)
void postSelectConstraint(TransInfo *t)
static void constraint_snap_plane_to_edge(const TransInfo *t, const float plane_no[3], float r_out[3])
void stopConstraint(TransInfo *t)
static void applyAxisConstraintVec(const TransInfo *t, const TransDataContainer *, const TransData *td, const float in[3], float out[3])
void constraintNumInput(TransInfo *t, float vec[3])
void setLocalConstraint(TransInfo *t, int mode, const char text[])
void transform_constraint_get_nearest(const TransInfo *t, const float3 &vec, float r_vec[3])
void transform_constraint_snap_axis_to_edge(const TransInfo *t, const float axis[3], float r_out[3])
static void applyAxisConstraintRot(const TransInfo *t, const TransDataContainer *, const TransData *td, float r_axis[3], float *r_angle)
static void applyObjectConstraintRot(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_axis[3], float *r_angle)
int getConstraintSpaceDimension(const TransInfo *t)
static void applyObjectConstraintSize(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_smat[3][3])
void drawPropRange(TransInfo *t)
void initSelectConstraint(TransInfo *t)
static void setNearestAxis2d(TransInfo *t)
static short transform_orientation_or_default(const TransInfo *t)
void selectConstraint(TransInfo *t)
static void view_vector_calc(const TransInfo *t, const float focus[3], float r_vec[3])
static void applyObjectConstraintVec(const TransInfo *t, const TransDataContainer *tc, const TransData *td, const float in[3], float out[3])
static void axisProjection(const TransInfo *t, const float axis[3], const float in[3], float out[3])
void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t)
void transform_orientations_current_set(TransInfo *t, const short orient_index)
const char * transform_orientations_spacename_get(TransInfo *t, const short orient_type)
bool validSnap(const TransInfo *t)
bool transform_snap_is_active(const TransInfo *t)
ccl_device_inline int abs(int x)
Definition util/math.h:120