Blender V4.3
transform_input.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstdlib>
11
12#include "DNA_screen_types.h"
13#include "DNA_sequence_types.h"
14#include "DNA_space_types.h"
15
16#include "BKE_context.hh"
17
18#include "BLI_math_vector.h"
19#include "BLI_utildefines.h"
20
21#include "WM_api.hh"
22#include "WM_types.hh"
23
24#include "transform.hh"
25#include "transform_mode.hh"
26
27#include "ED_sequencer.hh"
28
29#include "SEQ_sequencer.hh"
30#include "SEQ_time.hh"
31
32#include "MEM_guardedalloc.h"
33
34using namespace blender;
35
36/* -------------------------------------------------------------------- */
41static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
42{
43 convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
44}
45
47static void InputSpring(TransInfo * /*t*/, MouseInput *mi, const double mval[2], float output[3])
48{
49 double dx, dy;
50 float ratio;
51
52 dx = double(mi->center[0]) - mval[0];
53 dy = double(mi->center[1]) - mval[1];
54 ratio = hypot(dx, dy) / double(mi->factor);
55
56 output[0] = ratio;
57}
58
60static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
61{
62 InputSpring(t, mi, mval, output);
63
64 /* Flip scale. */
65 /* Values can become really big when zoomed in so use longs #26598. */
66 if ((int64_t(int(mi->center[0]) - mval[0]) * int64_t(int(mi->center[0]) - mi->imval[0]) +
67 int64_t(int(mi->center[1]) - mval[1]) * int64_t(int(mi->center[1]) - mi->imval[1])) < 0)
68 {
69 output[0] *= -1.0f;
70 }
71}
72
74static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
75{
76 InputSpring(t, mi, mval, output);
77 output[0] -= 1.0f;
78}
79
81static void InputTrackBall(TransInfo * /*t*/,
82 MouseInput *mi,
83 const double mval[2],
84 float output[3])
85{
86 output[0] = float(mi->imval[1] - mval[1]);
87 output[1] = float(mval[0] - mi->imval[0]);
88
89 output[0] *= mi->factor;
90 output[1] *= mi->factor;
91}
92
95 MouseInput *mi,
96 const double mval[2],
97 float output[3])
98{
99 const int winx = t->region ? t->region->winx : 1;
100
101 output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
102}
103
106 MouseInput *mi,
107 const double mval[2],
108 float output[3])
109{
110 float vec[3];
111
112 InputVector(t, mi, mval, vec);
113 project_v3_v3v3(vec, vec, t->viewinv[0]);
114
115 output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
116}
117
118static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
119{
120 const int winy = t->region ? t->region->winy : 1;
121
122 /* Dragging up increases (matching viewport zoom). */
123 output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
124}
125
128 MouseInput *mi,
129 const double mval[2],
130 float output[3])
131{
132 float vec[3];
133
134 InputVector(t, mi, mval, vec);
135 project_v3_v3v3(vec, vec, t->viewinv[1]);
136
137 /* Dragging up increases (matching viewport zoom). */
138 output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f;
139}
140
142static void InputCustomRatioFlip(TransInfo * /*t*/,
143 MouseInput *mi,
144 const double mval[2],
145 float output[3])
146{
147 double length;
148 double distance;
149 double dx, dy;
150 const int *data = static_cast<const int *>(mi->data);
151
152 if (data) {
153 int mdx, mdy;
154 dx = data[2] - data[0];
155 dy = data[3] - data[1];
156
157 length = hypot(dx, dy);
158
159 mdx = mval[0] - data[2];
160 mdy = mval[1] - data[3];
161
162 distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
163
164 output[0] = (length != 0.0) ? double(distance / length) : 0.0;
165 }
166}
167
169static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
170{
171 InputCustomRatioFlip(t, mi, mval, output);
172 output[0] = -output[0];
173}
174
176 double angle;
177 double mval_prev[2];
178};
179
181static void InputAngle(TransInfo * /*t*/, MouseInput *mi, const double mval[2], float output[3])
182{
183 InputAngle_Data *data = static_cast<InputAngle_Data *>(mi->data);
184 float dir_prev[2], dir_curr[2], mi_center[2];
185 copy_v2_v2(mi_center, mi->center);
186
188 dir_prev, blender::float2{float(data->mval_prev[0]), float(data->mval_prev[1])}, mi_center);
189 sub_v2_v2v2(dir_curr, blender::float2{float(mval[0]), float(mval[1])}, mi_center);
190
191 if (normalize_v2(dir_prev) && normalize_v2(dir_curr)) {
192 float dphi = angle_normalized_v2v2(dir_prev, dir_curr);
193
194 if (cross_v2v2(dir_prev, dir_curr) > 0.0f) {
195 dphi = -dphi;
196 }
197
198 data->angle += double(dphi) * (mi->precision ? double(mi->precision_factor) : 1.0);
199
200 data->mval_prev[0] = mval[0];
201 data->mval_prev[1] = mval[1];
202 }
203
204 output[0] = data->angle;
205}
206
207static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
208{
209 float toutput[3];
210
211 InputAngle(t, mi, mval, output);
212 InputSpring(t, mi, mval, toutput);
213
214 output[1] = toutput[0];
215}
216
219/* -------------------------------------------------------------------- */
227 MouseInput *mi,
228 const int mval_start[2],
229 const int mval_end[2])
230{
231 int *data;
232
233 mi->data = MEM_reallocN(mi->data, sizeof(int[4]));
234
235 data = static_cast<int *>(mi->data);
236
237 data[0] = mval_start[0];
238 data[1] = mval_start[1];
239 data[2] = mval_end[0];
240 data[3] = mval_end[1];
241}
242
244{
246 const int win_axis =
247 t->region ? ((abs(int(t->region->winx * dir[0])) + abs(int(t->region->winy * dir[1]))) / 2) :
248 1;
249 const int2 mval_start = int2(mi->imval + dir * win_axis);
250 const int2 mval_end = int2(mi->imval);
251 setCustomPoints(t, mi, mval_start, mval_end);
252}
253
256/* -------------------------------------------------------------------- */
261{
262 MouseInput *mi = &t->mouse;
263
264 mi->imval = mval;
265
266 if (mi->data && ELEM(mi->apply, InputAngle, InputAngleSpring)) {
267 InputAngle_Data *data = static_cast<InputAngle_Data *>(mi->data);
268 data->mval_prev[0] = mi->imval[0];
269 data->mval_prev[1] = mi->imval[1];
270 data->angle = 0.0f;
271 }
272}
273
275 TransInfo *t, MouseInput *mi, const float2 &center, const float2 &mval, const bool precision)
276{
277 mi->factor = 0;
278 mi->precision = precision;
279
280 mi->center = center;
281
282 mi->post = nullptr;
283
284 transform_input_reset(t, mval);
285}
286
288{
289 float mdir[2] = {float(mi->center[1] - mi->imval[1]), float(mi->center[0] - mi->imval[0])};
290
291 mi->factor = len_v2(mdir);
292
293 if (mi->factor == 0.0f) {
294 mi->factor = 1.0f; /* Prevent inf. */
295 }
296}
297
299{
300 if ((seq->flag & SEQ_LEFTSEL) != 0) {
302 }
303 if ((seq->flag & SEQ_RIGHTSEL) != 0) {
305 }
307}
308
310{
311 if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
313 }
314
315 const Scene *scene = t->scene;
317
318 if (strips.size() == 1) {
319 return transform_seq_slide_strip_cursor_get(strips[0]);
320 }
321 if (strips.size() == 2) {
322 Sequence *seq1 = strips[0];
323 Sequence *seq2 = strips[1];
324
326 {
327 SWAP(Sequence *, seq1, seq2);
328 }
329
330 if (seq1->machine != seq2->machine) {
332 }
333
334 if (SEQ_time_right_handle_frame_get(scene, seq1) !=
336 {
338 }
339
340 const int cursor1 = transform_seq_slide_strip_cursor_get(seq1);
341 const int cursor2 = transform_seq_slide_strip_cursor_get(seq2);
342
343 if (cursor1 == WM_CURSOR_RIGHT_HANDLE && cursor2 == WM_CURSOR_LEFT_HANDLE) {
345 }
346 }
347
349}
350
352{
353 /* In case we allocate a new value. */
354 void *mi_data_prev = mi->data;
355
356 mi->use_virtual_mval = true;
357 mi->precision_factor = 1.0f / 10.0f;
358
359 switch (mode) {
360 case INPUT_VECTOR:
361 mi->apply = InputVector;
362 t->helpline = HLP_NONE;
363 break;
364 case INPUT_SPRING:
366 mi->apply = InputSpring;
367 t->helpline = HLP_SPRING;
368 break;
372 t->helpline = HLP_SPRING;
373 break;
377 t->helpline = HLP_SPRING;
378 break;
379 case INPUT_ANGLE:
380 case INPUT_ANGLE_SPRING: {
382 mi->use_virtual_mval = false;
383 mi->precision_factor = 1.0f / 30.0f;
384 data = static_cast<InputAngle_Data *>(
385 MEM_callocN(sizeof(InputAngle_Data), "angle accumulator"));
386 data->mval_prev[0] = mi->imval[0];
387 data->mval_prev[1] = mi->imval[1];
388 mi->data = data;
389 if (mode == INPUT_ANGLE) {
390 mi->apply = InputAngle;
391 }
392 else {
395 }
396 t->helpline = HLP_ANGLE;
397 break;
398 }
399 case INPUT_TRACKBALL:
400 mi->precision_factor = 1.0f / 30.0f;
401 /* Factor has to become setting or so. */
402 mi->factor = 0.01f;
403 mi->apply = InputTrackBall;
405 break;
408 t->helpline = HLP_HARROW;
409 break;
412 t->helpline = HLP_HARROW;
413 break;
416 t->helpline = HLP_VARROW;
417 break;
420 t->helpline = HLP_VARROW;
421 break;
424 t->helpline = HLP_CARROW;
425 break;
428 t->helpline = HLP_CARROW;
429 break;
430 case INPUT_NONE:
431 default:
432 mi->apply = nullptr;
433 break;
434 }
435
436 /* Setup for the mouse cursor: either set a custom one,
437 * or hide it if it will be drawn with the helpline. */
438 wmWindow *win = CTX_wm_window(t->context);
439 switch (t->helpline) {
440 case HLP_NONE:
441 /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP. */
442 if (t->flag & T_MODAL) {
445 }
446 /* Only use special cursor, when tweaking strips with mouse. */
447 if (t->mode == TFM_SEQ_SLIDE) {
450 }
451 else {
453 if (sseq != nullptr) {
454 sseq->flag &= ~SPACE_SEQ_DESELECT_STRIP_HANDLE;
455 }
456 }
457 }
458
459 break;
460 case HLP_SPRING:
461 case HLP_ANGLE:
462 case HLP_TRACKBALL:
463 case HLP_HARROW:
464 case HLP_VARROW:
465 case HLP_CARROW:
466 if (t->flag & T_MODAL) {
469 }
470 break;
471 default:
472 break;
473 }
474
475 /* If we've allocated new data, free the old data
476 * less hassle than checking before every alloc above. */
477 if (mi_data_prev && (mi_data_prev != mi->data)) {
478 MEM_freeN(mi_data_prev);
479 }
480}
481
482void setInputPostFct(MouseInput *mi, void (*post)(TransInfo *t, float values[3]))
483{
484 mi->post = post;
485}
486
487void applyMouseInput(TransInfo *t, MouseInput *mi, const float2 &mval, float output[3])
488{
489 double mval_db[2];
490
491 if (mi->use_virtual_mval) {
492 /* Update accumulator. */
493 double mval_delta[2];
494
495 mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
496 mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
497
498 mi->virtual_mval.prev[0] += mval_delta[0];
499 mi->virtual_mval.prev[1] += mval_delta[1];
500
501 if (mi->precision) {
502 mval_delta[0] *= double(mi->precision_factor);
503 mval_delta[1] *= double(mi->precision_factor);
504 }
505
506 mi->virtual_mval.accum[0] += mval_delta[0];
507 mi->virtual_mval.accum[1] += mval_delta[1];
508
509 mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
510 mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
511 }
512 else {
513 mval_db[0] = mval[0];
514 mval_db[1] = mval[1];
515 }
516
517 if (mi->apply != nullptr) {
518 mi->apply(t, mi, mval_db, output);
519 }
520
521 if (mi->post) {
522 mi->post(t, output);
523 }
524}
525
526void transform_input_update(TransInfo *t, const float fac)
527{
528 MouseInput *mi = &t->mouse;
529 float2 offset = fac * (mi->imval - mi->center);
530 mi->imval = t->center2d + offset;
531 mi->factor *= fac;
532
533 float center_old[2];
534 copy_v2_v2(center_old, mi->center);
535 copy_v2_v2(mi->center, t->center2d);
536
537 if (mi->use_virtual_mval) {
538 /* Update accumulator. */
539 double mval_delta[2];
540 sub_v2_v2v2_db(mval_delta, mi->virtual_mval.accum, mi->virtual_mval.prev);
541 mval_delta[0] *= fac;
542 mval_delta[1] *= fac;
544 add_v2_v2_db(mi->virtual_mval.accum, mval_delta);
545 }
546
548 float offset_center[2];
549 sub_v2_v2v2(offset_center, mi->center, center_old);
550 InputAngle_Data *data = static_cast<InputAngle_Data *>(mi->data);
551 data->mval_prev[0] += offset_center[0];
552 data->mval_prev[1] += offset_center[1];
553 }
554
555 if (t->mode == TFM_EDGE_SLIDE) {
557 }
558 else if (t->mode == TFM_VERT_SLIDE) {
560 }
561}
562
564{
565 MouseInput *mi = &t->mouse;
567 InputAngle_Data *data = static_cast<InputAngle_Data *>(mi->data);
568 data->angle = 0.0;
569 data->mval_prev[0] = mi->imval[0];
570 data->mval_prev[1] = mi->imval[1];
571 }
572 else {
573 memset(&mi->virtual_mval, 0, sizeof(mi->virtual_mval));
574 }
575}
576
wmWindow * CTX_wm_window(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
#define BLI_ASSERT_UNIT_V2(v)
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
float angle_normalized_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2_db(double r[2], const double a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
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 float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float normalize_v2(float n[2])
MINLINE void add_v2_v2_db(double r[2], const double a[2])
MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
#define SWAP(type, a, b)
#define ELEM(...)
typedef double(DMatrix)[4][4]
@ SEQ_RIGHTSEL
@ SEQ_LEFTSEL
@ USER_SEQ_ED_SIMPLE_TWEAKING
blender::VectorSet< Sequence * > ED_sequencer_selected_strips_from_context(bContext *C)
@ TFM_EDGE_SLIDE
@ TFM_VERT_SLIDE
@ TFM_SEQ_SLIDE
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
unsigned int U
Definition btGjkEpa3.h:78
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
int64_t size() const
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
VecBase< int32_t, 2 > int2
float distance(float a, float b)
__int64 int64_t
Definition stdint.h:89
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
blender::float2 imval
Definition transform.hh:383
bool use_virtual_mval
Definition transform.hh:400
double accum[2]
Definition transform.hh:403
void(* post)(TransInfo *t, float values[3])
Definition transform.hh:380
blender::float2 center
Definition transform.hh:384
double prev[2]
Definition transform.hh:402
struct MouseInput::@558 virtual_mval
void(* apply)(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
Definition transform.hh:379
float precision_factor
Definition transform.hh:386
float factor
Definition transform.hh:385
void * data
Definition transform.hh:390
bool precision
Definition transform.hh:387
eTfmMode mode
Definition transform.hh:517
float viewinv[4][4]
Definition transform.hh:575
float center2d[2]
Definition transform.hh:557
Scene * scene
Definition transform.hh:654
eTHelpline helpline
Definition transform.hh:531
eTFlag flag
Definition transform.hh:523
ARegion * region
Definition transform.hh:652
MouseInput mouse
Definition transform.hh:543
bContext * context
Definition transform.hh:649
MouseInputMode
Definition transform.hh:740
@ INPUT_TRACKBALL
Definition transform.hh:748
@ INPUT_VERTICAL_ABSOLUTE
Definition transform.hh:752
@ INPUT_SPRING
Definition transform.hh:743
@ INPUT_VECTOR
Definition transform.hh:742
@ INPUT_ANGLE_SPRING
Definition transform.hh:747
@ INPUT_CUSTOM_RATIO_FLIP
Definition transform.hh:754
@ INPUT_HORIZONTAL_RATIO
Definition transform.hh:749
@ INPUT_VERTICAL_RATIO
Definition transform.hh:751
@ INPUT_CUSTOM_RATIO
Definition transform.hh:753
@ INPUT_HORIZONTAL_ABSOLUTE
Definition transform.hh:750
@ INPUT_SPRING_DELTA
Definition transform.hh:745
@ INPUT_NONE
Definition transform.hh:741
@ INPUT_ANGLE
Definition transform.hh:746
@ INPUT_SPRING_FLIP
Definition transform.hh:744
@ T_MODAL
Definition transform.hh:118
@ T_MODAL_CURSOR_SET
Definition transform.hh:131
@ HLP_HARROW
Definition transform.hh:226
@ HLP_ANGLE
Definition transform.hh:225
@ HLP_SPRING
Definition transform.hh:224
@ HLP_CARROW
Definition transform.hh:228
@ HLP_TRACKBALL
Definition transform.hh:229
@ HLP_NONE
Definition transform.hh:223
@ HLP_VARROW
Definition transform.hh:227
static void InputCustomRatioFlip(TransInfo *, MouseInput *mi, const double mval[2], float output[3])
void transform_input_virtual_mval_reset(TransInfo *t)
void initMouseInput(TransInfo *t, MouseInput *mi, const float2 &center, const float2 &mval, const bool precision)
static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static int transform_seq_slide_strip_cursor_get(const Sequence *seq)
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputAngle(TransInfo *, MouseInput *mi, const double mval[2], float output[3])
static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
void transform_input_update(TransInfo *t, const float fac)
static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputSpring(TransInfo *, MouseInput *mi, const double mval[2], float output[3])
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float2 &dir)
static int transform_seq_slide_cursor_get(TransInfo *t)
void transform_input_reset(TransInfo *t, const float2 &mval)
void setCustomPoints(TransInfo *, MouseInput *mi, const int mval_start[2], const int mval_end[2])
void applyMouseInput(TransInfo *t, MouseInput *mi, const float2 &mval, float output[3])
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputTrackBall(TransInfo *, MouseInput *mi, const double mval[2], float output[3])
static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
void setInputPostFct(MouseInput *mi, void(*post)(TransInfo *t, float values[3]))
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
static void calcSpringFactor(MouseInput *mi)
transform modes used by different operators.
void transform_mode_edge_slide_reproject_input(TransInfo *t)
void transform_mode_vert_slide_reproject_input(TransInfo *t)
bool transform_mode_edge_seq_slide_use_restore_handle_selection(const TransInfo *t)
ccl_device_inline int abs(int x)
Definition util/math.h:120
void WM_cursor_modal_set(wmWindow *win, int val)
@ WM_CURSOR_NSEW_SCROLL
Definition wm_cursors.hh:51
@ WM_CURSOR_RIGHT_HANDLE
Definition wm_cursors.hh:64
@ WM_CURSOR_BOTH_HANDLES
Definition wm_cursors.hh:65
@ WM_CURSOR_LEFT_HANDLE
Definition wm_cursors.hh:63
@ WM_CURSOR_NONE
Definition wm_cursors.hh:58