1 | /**************************************************************************/ |
2 | /* animation.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef ANIMATION_H |
32 | #define ANIMATION_H |
33 | |
34 | #include "core/io/resource.h" |
35 | #include "core/templates/local_vector.h" |
36 | |
37 | #define ANIM_MIN_LENGTH 0.001 |
38 | |
39 | class Animation : public Resource { |
40 | GDCLASS(Animation, Resource); |
41 | RES_BASE_EXTENSION("anim" ); |
42 | |
43 | public: |
44 | enum TrackType { |
45 | TYPE_VALUE, ///< Set a value in a property, can be interpolated. |
46 | TYPE_POSITION_3D, ///< Position 3D track |
47 | TYPE_ROTATION_3D, ///< Rotation 3D track |
48 | TYPE_SCALE_3D, ///< Scale 3D track |
49 | TYPE_BLEND_SHAPE, ///< Blend Shape track |
50 | TYPE_METHOD, ///< Call any method on a specific node. |
51 | TYPE_BEZIER, ///< Bezier curve |
52 | TYPE_AUDIO, |
53 | TYPE_ANIMATION, |
54 | }; |
55 | |
56 | enum InterpolationType { |
57 | INTERPOLATION_NEAREST, |
58 | INTERPOLATION_LINEAR, |
59 | INTERPOLATION_CUBIC, |
60 | INTERPOLATION_LINEAR_ANGLE, |
61 | INTERPOLATION_CUBIC_ANGLE, |
62 | }; |
63 | |
64 | enum UpdateMode { |
65 | UPDATE_CONTINUOUS, |
66 | UPDATE_DISCRETE, |
67 | UPDATE_CAPTURE, |
68 | }; |
69 | |
70 | enum LoopMode { |
71 | LOOP_NONE, |
72 | LOOP_LINEAR, |
73 | LOOP_PINGPONG, |
74 | }; |
75 | |
76 | enum LoopedFlag { |
77 | LOOPED_FLAG_NONE, |
78 | LOOPED_FLAG_END, |
79 | LOOPED_FLAG_START, |
80 | }; |
81 | |
82 | enum FindMode { |
83 | FIND_MODE_NEAREST, |
84 | FIND_MODE_APPROX, |
85 | FIND_MODE_EXACT, |
86 | }; |
87 | |
88 | #ifdef TOOLS_ENABLED |
89 | enum HandleMode { |
90 | HANDLE_MODE_FREE, |
91 | HANDLE_MODE_LINEAR, |
92 | HANDLE_MODE_BALANCED, |
93 | HANDLE_MODE_MIRRORED, |
94 | }; |
95 | enum HandleSetMode { |
96 | HANDLE_SET_MODE_NONE, |
97 | HANDLE_SET_MODE_RESET, |
98 | HANDLE_SET_MODE_AUTO, |
99 | }; |
100 | #endif // TOOLS_ENABLED |
101 | |
102 | private: |
103 | struct Track { |
104 | TrackType type = TrackType::TYPE_ANIMATION; |
105 | InterpolationType interpolation = INTERPOLATION_LINEAR; |
106 | bool loop_wrap = true; |
107 | NodePath path; // path to something |
108 | bool imported = false; |
109 | bool enabled = true; |
110 | Track() {} |
111 | virtual ~Track() {} |
112 | }; |
113 | |
114 | struct Key { |
115 | real_t transition = 1.0; |
116 | double time = 0.0; // time in secs |
117 | }; |
118 | |
119 | // transform key holds either Vector3 or Quaternion |
120 | template <class T> |
121 | struct TKey : public Key { |
122 | T value; |
123 | }; |
124 | |
125 | const int32_t POSITION_TRACK_SIZE = 5; |
126 | const int32_t ROTATION_TRACK_SIZE = 6; |
127 | const int32_t SCALE_TRACK_SIZE = 5; |
128 | const int32_t BLEND_SHAPE_TRACK_SIZE = 3; |
129 | |
130 | /* POSITION TRACK */ |
131 | |
132 | struct PositionTrack : public Track { |
133 | Vector<TKey<Vector3>> positions; |
134 | int32_t compressed_track = -1; |
135 | PositionTrack() { type = TYPE_POSITION_3D; } |
136 | }; |
137 | |
138 | /* ROTATION TRACK */ |
139 | |
140 | struct RotationTrack : public Track { |
141 | Vector<TKey<Quaternion>> rotations; |
142 | int32_t compressed_track = -1; |
143 | RotationTrack() { type = TYPE_ROTATION_3D; } |
144 | }; |
145 | |
146 | /* SCALE TRACK */ |
147 | |
148 | struct ScaleTrack : public Track { |
149 | Vector<TKey<Vector3>> scales; |
150 | int32_t compressed_track = -1; |
151 | ScaleTrack() { type = TYPE_SCALE_3D; } |
152 | }; |
153 | |
154 | /* BLEND SHAPE TRACK */ |
155 | |
156 | struct BlendShapeTrack : public Track { |
157 | Vector<TKey<float>> blend_shapes; |
158 | int32_t compressed_track = -1; |
159 | BlendShapeTrack() { type = TYPE_BLEND_SHAPE; } |
160 | }; |
161 | |
162 | /* PROPERTY VALUE TRACK */ |
163 | |
164 | struct ValueTrack : public Track { |
165 | UpdateMode update_mode = UPDATE_CONTINUOUS; |
166 | bool update_on_seek = false; |
167 | Vector<TKey<Variant>> values; |
168 | |
169 | ValueTrack() { |
170 | type = TYPE_VALUE; |
171 | } |
172 | }; |
173 | |
174 | /* METHOD TRACK */ |
175 | |
176 | struct MethodKey : public Key { |
177 | StringName method; |
178 | Vector<Variant> params; |
179 | }; |
180 | |
181 | struct MethodTrack : public Track { |
182 | Vector<MethodKey> methods; |
183 | MethodTrack() { type = TYPE_METHOD; } |
184 | }; |
185 | |
186 | /* BEZIER TRACK */ |
187 | struct BezierKey { |
188 | Vector2 in_handle; //relative (x always <0) |
189 | Vector2 out_handle; //relative (x always >0) |
190 | real_t value = 0.0; |
191 | #ifdef TOOLS_ENABLED |
192 | HandleMode handle_mode = HANDLE_MODE_FREE; |
193 | #endif // TOOLS_ENABLED |
194 | }; |
195 | |
196 | struct BezierTrack : public Track { |
197 | Vector<TKey<BezierKey>> values; |
198 | |
199 | BezierTrack() { |
200 | type = TYPE_BEZIER; |
201 | } |
202 | }; |
203 | |
204 | /* AUDIO TRACK */ |
205 | |
206 | struct AudioKey { |
207 | Ref<Resource> stream; |
208 | real_t start_offset = 0.0; //offset from start |
209 | real_t end_offset = 0.0; //offset from end, if 0 then full length or infinite |
210 | AudioKey() { |
211 | } |
212 | }; |
213 | |
214 | struct AudioTrack : public Track { |
215 | Vector<TKey<AudioKey>> values; |
216 | bool use_blend = true; |
217 | |
218 | AudioTrack() { |
219 | type = TYPE_AUDIO; |
220 | } |
221 | }; |
222 | |
223 | /* AUDIO TRACK */ |
224 | |
225 | struct AnimationTrack : public Track { |
226 | Vector<TKey<StringName>> values; |
227 | |
228 | AnimationTrack() { |
229 | type = TYPE_ANIMATION; |
230 | } |
231 | }; |
232 | |
233 | Vector<Track *> tracks; |
234 | |
235 | /* |
236 | template<class T> |
237 | int _insert_pos(double p_time, T& p_keys);*/ |
238 | |
239 | template <class T> |
240 | void _clear(T &p_keys); |
241 | |
242 | template <class T, class V> |
243 | int _insert(double p_time, T &p_keys, const V &p_value); |
244 | |
245 | template <class K> |
246 | |
247 | inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false) const; |
248 | |
249 | _FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const; |
250 | _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const; |
251 | _FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const; |
252 | _FORCE_INLINE_ real_t _interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const; |
253 | _FORCE_INLINE_ Variant _interpolate_angle(const Variant &p_a, const Variant &p_b, real_t p_c) const; |
254 | |
255 | _FORCE_INLINE_ Vector3 _cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; |
256 | _FORCE_INLINE_ Quaternion _cubic_interpolate_in_time(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; |
257 | _FORCE_INLINE_ Variant _cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; |
258 | _FORCE_INLINE_ real_t _cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; |
259 | _FORCE_INLINE_ Variant _cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; |
260 | |
261 | template <class T> |
262 | _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; |
263 | |
264 | template <class T> |
265 | _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const; |
266 | |
267 | double length = 1.0; |
268 | real_t step = 0.1; |
269 | LoopMode loop_mode = LOOP_NONE; |
270 | |
271 | /* Animation compression page format (version 1): |
272 | * |
273 | * Animation uses bitwidth based compression separated into small pages. The intention is that pages fit easily in the cache, so decoding is cache efficient. |
274 | * The page-based nature also makes future animation streaming from disk possible. |
275 | * |
276 | * Actual format: |
277 | * |
278 | * num_compressed_tracks = bounds.size() |
279 | * header : (x num_compressed_tracks) |
280 | * ------- |
281 | * timeline_keys_offset : uint32_t - offset to time keys |
282 | * timeline_size : uint32_t - amount of time keys |
283 | * data_keys_offset : uint32_t offset to key data |
284 | * |
285 | * time key (uint32_t): |
286 | * ------------------ |
287 | * frame : bits 0-15 - time offset of key, computed as: page.time_offset + frame * (1.0/fps) |
288 | * data_key_offset : bits 16-27 - offset to key data, computed as: data_keys_offset * 4 + data_key_offset |
289 | * data_key_count : bits 28-31 - amount of data keys pointed to, computed as: data_key_count+1 (max 16) |
290 | * |
291 | * data key: |
292 | * --------- |
293 | * X / Blend Shape : uint16_t - X coordinate of XYZ vector key, or Blend Shape value. If Blend shape, Y and Z are not present and can be ignored. |
294 | * Y : uint16_t |
295 | * Z : uint16_t |
296 | * If data_key_count+1 > 1 (if more than 1 key is stored): |
297 | * data_bitwidth : uint16_t - This is only present if data_key_count > 1. Contains delta bitwidth information. |
298 | * X / Blend Shape delta bitwidth: bits 0-3 - |
299 | * if 0, nothing is present for X (use the first key-value for subsequent keys), |
300 | * else assume the number of bits present for each element (+ 1 for sign). Assumed always 16 bits, delta max signed 15 bits, with underflow and overflow supported. |
301 | * Y delta bitwidth : bits 4-7 |
302 | * Z delta bitwidth : bits 8-11 |
303 | * FRAME delta bitwidth : 12-15 bits - always present (obviously), actual bitwidth is FRAME+1 |
304 | * Data key is 4 bytes long for Blend Shapes, 8 bytes long for pos/rot/scale. |
305 | * |
306 | * delta keys: |
307 | * ----------- |
308 | * Compressed format is packed in the following format after the data key, containing delta keys one after the next in a tightly bit packed fashion. |
309 | * FRAME bits -> X / Blend Shape Bits (if bitwidth > 0) -> Y Bits (if not Blend Shape and Y Bitwidth > 0) -> Z Bits (if not Blend Shape and Z Bitwidth > 0) |
310 | * |
311 | * data key format: |
312 | * ---------------- |
313 | * Decoding keys means starting from the base key and going key by key applying deltas until the proper position is reached needed for interpolation. |
314 | * Resulting values are uint32_t |
315 | * data for X / Blend Shape, Y and Z must be normalized first: unorm = float(data) / 65535.0 |
316 | * **Blend Shape**: (unorm * 2.0 - 1.0) * Compression::BLEND_SHAPE_RANGE |
317 | * **Pos/Scale**: unorm_vec3 * bounds[track].size + bounds[track].position |
318 | * **Rotation**: Quaternion(Vector3::octahedron_decode(unorm_vec3.xy),unorm_vec3.z * Math_PI * 2.0) |
319 | * **Frame**: page.time_offset + frame * (1.0/fps) |
320 | */ |
321 | |
322 | struct Compression { |
323 | enum { |
324 | MAX_DATA_TRACK_SIZE = 16384, |
325 | BLEND_SHAPE_RANGE = 8, // - 8.0 to 8.0 |
326 | FORMAT_VERSION = 1 |
327 | }; |
328 | struct Page { |
329 | Vector<uint8_t> data; |
330 | double time_offset; |
331 | }; |
332 | |
333 | uint32_t fps = 120; |
334 | LocalVector<Page> pages; |
335 | LocalVector<AABB> bounds; //used by position and scale tracks (which contain index to track and index to bounds). |
336 | bool enabled = false; |
337 | } compression; |
338 | |
339 | Vector3i _compress_key(uint32_t p_track, const AABB &p_bounds, int32_t p_key = -1, float p_time = 0.0); |
340 | bool _rotation_interpolate_compressed(uint32_t p_compressed_track, double p_time, Quaternion &r_ret) const; |
341 | bool _pos_scale_interpolate_compressed(uint32_t p_compressed_track, double p_time, Vector3 &r_ret) const; |
342 | bool _blend_shape_interpolate_compressed(uint32_t p_compressed_track, double p_time, float &r_ret) const; |
343 | template <uint32_t COMPONENTS> |
344 | bool _fetch_compressed(uint32_t p_compressed_track, double p_time, Vector3i &r_current_value, double &r_current_time, Vector3i &r_next_value, double &r_next_time, uint32_t *key_index = nullptr) const; |
345 | template <uint32_t COMPONENTS> |
346 | bool _fetch_compressed_by_index(uint32_t p_compressed_track, int p_index, Vector3i &r_value, double &r_time) const; |
347 | int _get_compressed_key_count(uint32_t p_compressed_track) const; |
348 | template <uint32_t COMPONENTS> |
349 | void _get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, List<int> *r_indices) const; |
350 | _FORCE_INLINE_ Quaternion _uncompress_quaternion(const Vector3i &p_value) const; |
351 | _FORCE_INLINE_ Vector3 _uncompress_pos_scale(uint32_t p_compressed_track, const Vector3i &p_value) const; |
352 | _FORCE_INLINE_ float _uncompress_blend_shape(const Vector3i &p_value) const; |
353 | |
354 | // bind helpers |
355 | private: |
356 | bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); |
357 | bool _vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); |
358 | bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); |
359 | bool _quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); |
360 | |
361 | void _position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); |
362 | void _rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); |
363 | void _scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); |
364 | void _blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); |
365 | void _value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); |
366 | |
367 | protected: |
368 | bool _set(const StringName &p_name, const Variant &p_value); |
369 | bool _get(const StringName &p_name, Variant &r_ret) const; |
370 | void _get_property_list(List<PropertyInfo> *p_list) const; |
371 | |
372 | virtual void reset_state() override; |
373 | |
374 | static void _bind_methods(); |
375 | |
376 | public: |
377 | int add_track(TrackType p_type, int p_at_pos = -1); |
378 | void remove_track(int p_track); |
379 | |
380 | int get_track_count() const; |
381 | TrackType track_get_type(int p_track) const; |
382 | |
383 | void track_set_path(int p_track, const NodePath &p_path); |
384 | NodePath track_get_path(int p_track) const; |
385 | int find_track(const NodePath &p_path, const TrackType p_type) const; |
386 | |
387 | void track_move_up(int p_track); |
388 | void track_move_down(int p_track); |
389 | void track_move_to(int p_track, int p_to_index); |
390 | void track_swap(int p_track, int p_with_track); |
391 | |
392 | void track_set_imported(int p_track, bool p_imported); |
393 | bool track_is_imported(int p_track) const; |
394 | |
395 | void track_set_enabled(int p_track, bool p_enabled); |
396 | bool track_is_enabled(int p_track) const; |
397 | |
398 | int track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1); |
399 | void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition); |
400 | void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); |
401 | void track_set_key_time(int p_track, int p_key_idx, double p_time); |
402 | int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const; |
403 | void track_remove_key(int p_track, int p_idx); |
404 | void track_remove_key_at_time(int p_track, double p_time); |
405 | int track_get_key_count(int p_track) const; |
406 | Variant track_get_key_value(int p_track, int p_key_idx) const; |
407 | double track_get_key_time(int p_track, int p_key_idx) const; |
408 | real_t track_get_key_transition(int p_track, int p_key_idx) const; |
409 | bool track_is_compressed(int p_track) const; |
410 | |
411 | int position_track_insert_key(int p_track, double p_time, const Vector3 &p_position); |
412 | Error position_track_get_key(int p_track, int p_key, Vector3 *r_position) const; |
413 | Error try_position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const; |
414 | Vector3 position_track_interpolate(int p_track, double p_time) const; |
415 | |
416 | int rotation_track_insert_key(int p_track, double p_time, const Quaternion &p_rotation); |
417 | Error rotation_track_get_key(int p_track, int p_key, Quaternion *r_rotation) const; |
418 | Error try_rotation_track_interpolate(int p_track, double p_time, Quaternion *r_interpolation) const; |
419 | Quaternion rotation_track_interpolate(int p_track, double p_time) const; |
420 | |
421 | int scale_track_insert_key(int p_track, double p_time, const Vector3 &p_scale); |
422 | Error scale_track_get_key(int p_track, int p_key, Vector3 *r_scale) const; |
423 | Error try_scale_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const; |
424 | Vector3 scale_track_interpolate(int p_track, double p_time) const; |
425 | |
426 | int blend_shape_track_insert_key(int p_track, double p_time, float p_blend); |
427 | Error blend_shape_track_get_key(int p_track, int p_key, float *r_blend) const; |
428 | Error try_blend_shape_track_interpolate(int p_track, double p_time, float *r_blend) const; |
429 | float blend_shape_track_interpolate(int p_track, double p_time) const; |
430 | |
431 | void track_set_interpolation_type(int p_track, InterpolationType p_interp); |
432 | InterpolationType track_get_interpolation_type(int p_track) const; |
433 | |
434 | int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle); |
435 | void bezier_track_set_key_value(int p_track, int p_index, real_t p_value); |
436 | void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio = 1.0); |
437 | void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio = 1.0); |
438 | real_t bezier_track_get_key_value(int p_track, int p_index) const; |
439 | Vector2 bezier_track_get_key_in_handle(int p_track, int p_index) const; |
440 | Vector2 bezier_track_get_key_out_handle(int p_track, int p_index) const; |
441 | #ifdef TOOLS_ENABLED |
442 | void bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, HandleSetMode p_set_mode = HANDLE_SET_MODE_NONE); |
443 | HandleMode bezier_track_get_key_handle_mode(int p_track, int p_index) const; |
444 | #endif // TOOLS_ENABLED |
445 | |
446 | real_t bezier_track_interpolate(int p_track, double p_time) const; |
447 | |
448 | int audio_track_insert_key(int p_track, double p_time, const Ref<Resource> &p_stream, real_t p_start_offset = 0, real_t p_end_offset = 0); |
449 | void audio_track_set_key_stream(int p_track, int p_key, const Ref<Resource> &p_stream); |
450 | void audio_track_set_key_start_offset(int p_track, int p_key, real_t p_offset); |
451 | void audio_track_set_key_end_offset(int p_track, int p_key, real_t p_offset); |
452 | Ref<Resource> audio_track_get_key_stream(int p_track, int p_key) const; |
453 | real_t audio_track_get_key_start_offset(int p_track, int p_key) const; |
454 | real_t audio_track_get_key_end_offset(int p_track, int p_key) const; |
455 | void audio_track_set_use_blend(int p_track, bool p_enable); |
456 | bool audio_track_is_use_blend(int p_track) const; |
457 | |
458 | int animation_track_insert_key(int p_track, double p_time, const StringName &p_animation); |
459 | void animation_track_set_key_animation(int p_track, int p_key, const StringName &p_animation); |
460 | StringName animation_track_get_key_animation(int p_track, int p_key) const; |
461 | |
462 | void track_set_interpolation_loop_wrap(int p_track, bool p_enable); |
463 | bool track_get_interpolation_loop_wrap(int p_track) const; |
464 | |
465 | Variant value_track_interpolate(int p_track, double p_time) const; |
466 | void value_track_set_update_mode(int p_track, UpdateMode p_mode); |
467 | UpdateMode value_track_get_update_mode(int p_track) const; |
468 | |
469 | Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const; |
470 | StringName method_track_get_name(int p_track, int p_key_idx) const; |
471 | |
472 | void copy_track(int p_track, Ref<Animation> p_to_animation); |
473 | |
474 | void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const; |
475 | |
476 | void set_length(real_t p_length); |
477 | real_t get_length() const; |
478 | |
479 | void set_loop_mode(LoopMode p_loop_mode); |
480 | LoopMode get_loop_mode() const; |
481 | |
482 | void set_step(real_t p_step); |
483 | real_t get_step() const; |
484 | |
485 | void clear(); |
486 | |
487 | void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3); |
488 | void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests |
489 | |
490 | // Helper math functions for Variant. |
491 | static Variant add_variant(const Variant &a, const Variant &b); |
492 | static Variant subtract_variant(const Variant &a, const Variant &b); |
493 | static Variant blend_variant(const Variant &a, const Variant &b, float c); |
494 | static Variant interpolate_variant(const Variant &a, const Variant &b, float c); |
495 | |
496 | Animation(); |
497 | ~Animation(); |
498 | }; |
499 | |
500 | VARIANT_ENUM_CAST(Animation::TrackType); |
501 | VARIANT_ENUM_CAST(Animation::InterpolationType); |
502 | VARIANT_ENUM_CAST(Animation::UpdateMode); |
503 | VARIANT_ENUM_CAST(Animation::LoopMode); |
504 | VARIANT_ENUM_CAST(Animation::LoopedFlag); |
505 | VARIANT_ENUM_CAST(Animation::FindMode); |
506 | #ifdef TOOLS_ENABLED |
507 | VARIANT_ENUM_CAST(Animation::HandleMode); |
508 | VARIANT_ENUM_CAST(Animation::HandleSetMode); |
509 | #endif // TOOLS_ENABLED |
510 | |
511 | #endif // ANIMATION_H |
512 | |