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