Blender V4.3
transform_mode_timeslide.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 <algorithm>
10#include <cstdlib>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_math_vector.h"
15#include "BLI_string.h"
16
17#include "BKE_nla.hh"
18#include "BKE_unit.hh"
19
20#include "ED_screen.hh"
21
22#include "UI_interface.hh"
23#include "UI_view2d.hh"
24
25#include "BLT_translation.hh"
26
27#include "transform.hh"
28#include "transform_convert.hh"
29
30#include "transform_mode.hh"
31
32/* -------------------------------------------------------------------- */
36static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR])
37{
38 char tvec[NUM_STR_REP_LEN * 3];
39
40 if (hasNumInput(&t->num)) {
41 outputNumInput(&(t->num), tvec, &t->scene->unit);
42 }
43 else {
44 const float *range = static_cast<const float *>(t->custom.mode.data);
45 float minx = range[0];
46 float maxx = range[1];
47 float cval = t->values_final[0];
48 float val;
49
50 val = 2.0f * (cval - sval) / (maxx - minx);
51 CLAMP(val, -1.0f, 1.0f);
52
53 BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
54 }
55
56 BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]);
57}
58
59static void applyTimeSlideValue(TransInfo *t, float sval, float cval)
60{
61 int i;
62 const float *range = static_cast<const float *>(t->custom.mode.data);
63 float minx = range[0];
64 float maxx = range[1];
65
66 /* Set value for drawing black line. */
67 if (t->spacetype == SPACE_ACTION) {
68 SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
69 saction->timeslide = cval;
70 }
71
72 /* It doesn't matter whether we apply to t->data or
73 * t->data2d, but t->data2d is more convenient. */
75 TransData *td = tc->data;
76 for (i = 0; i < tc->data_len; i++, td++) {
77 /* It is assumed that td->extra is a pointer to the AnimData,
78 * whose active action is where this keyframe comes from
79 * (this is only valid when not in NLA). */
80 AnimData *adt = static_cast<AnimData *>((t->spacetype != SPACE_NLA) ? td->extra : nullptr);
81
82 /* Only apply to data if in range. */
83 if ((sval > minx) && (sval < maxx)) {
84 float cvalc = std::clamp(cval, minx, maxx);
85 float timefac;
86 float *dst;
87 float ival;
88
89 if (td->val) {
90 dst = td->val;
91 ival = td->ival;
92 }
93 else {
94 dst = &td->loc[0];
95 ival = td->iloc[0];
96 }
97
98 /* NLA mapping magic here works as follows:
99 * - `ival` goes from strip time to global time.
100 * - Calculation is performed into `td->val` in global time
101 * (since `sval` and min/max are all in global time).
102 * - `td->val` then gets put back into strip time.
103 */
104 if (adt) {
105 /* Strip to global. */
107 }
108
109 /* Left half? */
110 if (ival < sval) {
111 timefac = (sval - ival) / (sval - minx);
112 *dst = cvalc - timefac * (cvalc - minx);
113 }
114 else {
115 timefac = (ival - sval) / (maxx - sval);
116 *dst = cvalc + timefac * (maxx - cvalc);
117 }
118
119 if (adt) {
120 /* Global to strip. */
122 }
123 }
124 }
125 }
126}
127
129{
130 View2D *v2d = (View2D *)t->view;
131 float cval[2], sval[2];
132 const float *range = static_cast<const float *>(t->custom.mode.data);
133 float minx = range[0];
134 float maxx = range[1];
135 char str[UI_MAX_DRAW_STR];
136
137 /* Calculate mouse co-ordinates. */
138 UI_view2d_region_to_view(v2d, t->mval[0], t->mval[1], &cval[0], &cval[1]);
139 UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]);
140
141 /* `t->values_final[0]` stores `cval[0]`,
142 * which is the current mouse-pointer location (in frames). */
143 /* XXX Need to be able to repeat this. */
144 // t->values_final[0] = cval[0]; /* UNUSED (reset again later). */
145
146 /* Handle numeric-input stuff. */
147 t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
148 applyNumInput(&t->num, &t->vec[0]);
149 t->values_final[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
150
151 headerTimeSlide(t, sval[0], str);
152 applyTimeSlideValue(t, sval[0], t->values_final[0]);
153
154 recalc_data(t);
155
157}
158
159static void initTimeSlide(TransInfo *t, wmOperator * /*op*/)
160{
161 /* This tool is only really available in the Action Editor. */
162 if (t->spacetype == SPACE_ACTION) {
163 SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
164
165 /* Set flag for drawing stuff. */
166 saction->flag |= SACTION_MOVING;
167 }
168 else {
169 t->state = TRANS_CANCEL;
170 }
171
172 t->mode = TFM_TIME_SLIDE;
173
175
176 {
177 Scene *scene = t->scene;
178 float *range;
179 t->custom.mode.data = range = static_cast<float *>(
180 MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max"));
181 t->custom.mode.use_free = true;
182
183 float min = 999999999.0f, max = -999999999.0f;
184 int i;
186 TransData *td = tc->data;
187 for (i = 0; i < tc->data_len; i++, td++) {
188 AnimData *adt = static_cast<AnimData *>((t->spacetype != SPACE_NLA) ? td->extra : nullptr);
189 float val = *(td->val);
190
191 /* Strip/action time to global (mapped) time. */
192 if (adt) {
194 }
195
196 if (min > val) {
197 min = val;
198 }
199 if (max < val) {
200 max = val;
201 }
202 }
203 }
204
205 if (min == max) {
206 /* Just use the current frame ranges. */
207 min = float(PSFRA);
208 max = float(PEFRA);
209 }
210
211 range[0] = min;
212 range[1] = max;
213 }
214
215 /* Numeric-input has max of (n-1). */
216 t->idx_max = 0;
217 t->num.flag = 0;
218 t->num.idx_max = t->idx_max;
219
220 /* Initialize snap like for everything else. */
221 t->snap[0] = t->snap[1] = 1.0f;
222
223 copy_v3_fl(t->num.val_inc, t->snap[0]);
224 t->num.unit_sys = t->scene->unit.system;
225 /* No time unit supporting frames currently. */
226 t->num.unit_type[0] = B_UNIT_NONE;
227}
228
232 /*flags*/ T_NULL_ONE,
233 /*init_fn*/ initTimeSlide,
234 /*transform_fn*/ applyTimeSlide,
235 /*transform_matrix_fn*/ nullptr,
236 /*handle_event_fn*/ nullptr,
237 /*snap_distance_fn*/ nullptr,
238 /*snap_apply_fn*/ nullptr,
239 /*draw_fn*/ nullptr,
240};
float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
@ NLATIME_CONVERT_MAP
Definition BKE_nla.hh:516
@ NLATIME_CONVERT_UNMAP
Definition BKE_nla.hh:513
@ B_UNIT_NONE
Definition BKE_unit.hh:106
MINLINE void copy_v3_fl(float r[3], float f)
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define CLAMP(a, b, c)
#define IFACE_(msgid)
@ SACTION_MOVING
#define PSFRA
#define PEFRA
@ SPACE_ACTION
@ SPACE_NLA
#define NUM_STR_REP_LEN
void outputNumInput(NumInput *n, char *str, const UnitSettings *unit_settings)
Definition numinput.cc:88
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
@ TFM_TIME_SLIDE
Read Guarded memory(de)allocation.
#define UI_MAX_DRAW_STR
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1663
draw_view in_light_buf[] float
#define str(s)
IndexRange range
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
#define min(a, b)
Definition sort.c:32
void * first
blender::float2 imval
Definition transform.hh:383
short idx_max
float val_inc[NUM_MAX_ELEMENTS]
int unit_type[NUM_MAX_ELEMENTS]
short flag
struct UnitSettings unit
ListBase spacedata
TransCustomData mode
Definition transform.hh:423
unsigned int use_free
Definition transform.hh:410
eTfmMode mode
Definition transform.hh:517
void * view
Definition transform.hh:647
char spacetype
Definition transform.hh:582
float snap[2]
Definition transform.hh:561
short idx_max
Definition transform.hh:559
eTState state
Definition transform.hh:527
NumInput num
Definition transform.hh:540
TransCustomDataContainer custom
Definition transform.hh:676
Scene * scene
Definition transform.hh:654
float vec[3]
Definition transform.hh:587
MouseInput mouse
Definition transform.hh:543
float values_final[4]
Definition transform.hh:632
blender::float2 mval
Definition transform.hh:663
ScrArea * area
Definition transform.hh:651
@ INPUT_NONE
Definition transform.hh:741
@ T_NULL_ONE
Definition transform.hh:96
@ TRANS_CANCEL
Definition transform.hh:210
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void recalc_data(TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
float max
transform modes used by different operators.
static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR])
static void applyTimeSlideValue(TransInfo *t, float sval, float cval)
static void initTimeSlide(TransInfo *t, wmOperator *)
TransModeInfo TransMode_timeslide
static void applyTimeSlide(TransInfo *t)