1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsCorePrerequisites.h" |
6 | #include "Animation/BsAnimationCurve.h" |
7 | |
8 | namespace bs |
9 | { |
10 | /** @addtogroup Animation |
11 | * @{ |
12 | */ |
13 | |
14 | /** Contains information and helper methods for various curve types. */ |
15 | template<class T> |
16 | struct TCurveProperties {}; |
17 | |
18 | template<> |
19 | struct TCurveProperties<float> |
20 | { |
21 | enum { NumComponents = 1 }; |
22 | static float getZero() { return 0.0f; } |
23 | static float getComponent(float val, UINT32 i) { return val; } |
24 | static void setComponent(float& val, UINT32 i, float newVal) { val = newVal; } |
25 | }; |
26 | |
27 | template<> |
28 | struct TCurveProperties<INT32> |
29 | { |
30 | enum { NumComponents = 1 }; |
31 | static INT32 getZero() { return 0; } |
32 | }; |
33 | |
34 | template<> |
35 | struct TCurveProperties<Vector2> |
36 | { |
37 | enum { NumComponents = 2 }; |
38 | static Vector2 getZero() { return Vector2::ZERO; } |
39 | static float getComponent(const Vector2& val, UINT32 i) { return val[i]; } |
40 | static void setComponent(Vector2& val, UINT32 i, float newVal) { val[i] = newVal; } |
41 | }; |
42 | |
43 | template<> |
44 | struct TCurveProperties<Vector3> |
45 | { |
46 | enum { NumComponents = 3 }; |
47 | static Vector3 getZero() { return Vector3::ZERO; } |
48 | static float getComponent(const Vector3& val, UINT32 i) { return val[i]; } |
49 | static void setComponent(Vector3& val, UINT32 i, float newVal) { val[i] = newVal; } |
50 | }; |
51 | |
52 | template<> |
53 | struct TCurveProperties<Quaternion> |
54 | { |
55 | enum { NumComponents = 4 }; |
56 | static Quaternion getZero() { return Quaternion::ZERO; } |
57 | static float getComponent(const Quaternion& val, UINT32 i) { return val[i]; } |
58 | static void setComponent(Quaternion& val, UINT32 i, float newVal) { val[i] = newVal; } |
59 | }; |
60 | |
61 | /** Helper class for dealing with animations, animation clips and curves. */ |
62 | class BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Animation) AnimationUtility |
63 | { |
64 | public: |
65 | /** |
66 | * Wraps or clamps the provided time value between the provided range. |
67 | * |
68 | * @param[in,out] time Time value to wrap/clamp. |
69 | * @param[in] start Start of the range. |
70 | * @param[in] end End of the range. |
71 | * @param[in] loop If true the value will be wrapped, otherwise clamped to range. |
72 | */ |
73 | static void wrapTime(float& time, float start, float end, bool loop); |
74 | |
75 | /** Converts a curve in euler angles (in degrees) into a curve using quaternions. */ |
76 | BS_SCRIPT_EXPORT() |
77 | static SPtr<TAnimationCurve<Quaternion>> eulerToQuaternionCurve(const SPtr<TAnimationCurve<Vector3>>& eulerCurve, |
78 | EulerAngleOrder order = EulerAngleOrder::YXZ); |
79 | |
80 | /** Converts a curve in quaternions into a curve using euler angles (in degrees). */ |
81 | BS_SCRIPT_EXPORT() |
82 | static SPtr<TAnimationCurve<Vector3>> quaternionToEulerCurve(const SPtr<TAnimationCurve<Quaternion>>& quatCurve); |
83 | |
84 | /** Splits a Vector3 curve into three individual curves, one for each component. */ |
85 | BS_SCRIPT_EXPORT() |
86 | static Vector<SPtr<TAnimationCurve<float>>> splitCurve3D(const SPtr<TAnimationCurve<Vector3>>& compoundCurve); |
87 | |
88 | /** Combines three single component curves into a Vector3 curve. */ |
89 | BS_SCRIPT_EXPORT() |
90 | static SPtr<TAnimationCurve<Vector3>> combineCurve3D(const Vector<SPtr<TAnimationCurve<float>>>& curveComponents); |
91 | |
92 | /** Splits a Vector2 curve into two individual curves, one for each component. */ |
93 | BS_SCRIPT_EXPORT() |
94 | static Vector<SPtr<TAnimationCurve<float>>> splitCurve2D(const SPtr<TAnimationCurve<Vector2>>& compoundCurve); |
95 | |
96 | /** Combines two single component curves into a Vector2 curve. */ |
97 | BS_SCRIPT_EXPORT() |
98 | static SPtr<TAnimationCurve<Vector2>> combineCurve2D(const Vector<SPtr<TAnimationCurve<float>>>& curveComponents); |
99 | |
100 | /** Splits a multi-component curve into multiple individual curves, one for each component. */ |
101 | template<class T> |
102 | static void splitCurve(const TAnimationCurve<T>& compoundCurve, |
103 | TAnimationCurve<float> (&output)[TCurveProperties<T>::NumComponents]); |
104 | |
105 | /** Combines multiple single component curves into a multi-component curve. */ |
106 | template<class T> |
107 | static void combineCurve(const TAnimationCurve<float> (&curveComponents)[TCurveProperties<T>::NumComponents], |
108 | TAnimationCurve<T>& output); |
109 | /** |
110 | * Calculates the total range covered by a set of curves. |
111 | * |
112 | * @param[in] curves Curves to calculate range for. |
113 | * @param[out] xMin Minimum time value present in the curves. |
114 | * @param[out] xMax Maximum time value present in the curves. |
115 | * @param[out] yMin Minimum curve value present in the curves. |
116 | * @param[out] yMax Maximum curve value present in the curves. |
117 | */ |
118 | static void calculateRange(const Vector<TAnimationCurve<float>>& curves, |
119 | float& xMin, float& xMax, float& yMin, float& yMax); |
120 | |
121 | /** @copydoc calculateRange(const Vector<TAnimationCurve<float>>&, float&, float&, float&, float&) */ |
122 | BS_SCRIPT_EXPORT() |
123 | static void calculateRange(const Vector<SPtr<TAnimationCurve<float>>>& curves, |
124 | float& xMin, float& xMax, float& yMin, float& yMax); |
125 | |
126 | /** Scales all curve values and tangents by the specified scale factor. */ |
127 | template<class T> |
128 | static TAnimationCurve<T> scaleCurve(const TAnimationCurve<T>& curve, float factor); |
129 | |
130 | /** Adds a time offset to all keyframes in the provided curve. */ |
131 | template<class T> |
132 | static TAnimationCurve<T> offsetCurve(const TAnimationCurve<T>& curve, float offset); |
133 | |
134 | /** Updates the provided list of keyframes by automatically calculating their tangents. */ |
135 | template<class T> |
136 | static void calculateTangents(Vector<TKeyframe<T>>& keyframes); |
137 | }; |
138 | |
139 | /** Type of tangent on a keyframe in an animation curve. */ |
140 | enum class BS_SCRIPT_EXPORT(m:Animation) TangentType |
141 | { |
142 | In = 1 << 0, |
143 | Out = 1 << 1 |
144 | }; |
145 | |
146 | /** |
147 | * Flags that are used for describing how are tangents calculated for a specific keyframe in an animation curve. |
148 | * Modes for "in" and "out" tangents can be combined. |
149 | */ |
150 | enum class BS_SCRIPT_EXPORT(m:Animation,n:TangentMode) TangentModeBits |
151 | { |
152 | /** Both tangents are calculated automatically based on the two surrounding keyframes. */ |
153 | Auto = 0, |
154 | /** Left tangent is calculated automatically based on the two surrounding keyframes. */ |
155 | InAuto = (int)TangentType::In | 1 << 2, |
156 | /** Left tangent is manually adjusted by the user. */ |
157 | InFree = (int)TangentType::In | 1 << 3, |
158 | /** Tangent is calculated automatically based on the previous keyframe. */ |
159 | InLinear = (int)TangentType::In | 1 << 4, |
160 | /** Tangent is infinite, ensuring there is a instantaneus jump between previous and current keyframe value. */ |
161 | InStep = (int)TangentType::In | 1 << 5, |
162 | /** Right tangents are calculated automatically based on the two surrounding keyframes. */ |
163 | OutAuto = (int)TangentType::Out | 1 << 6, |
164 | /** Right tangent is manually adjusted by the user. */ |
165 | OutFree = (int)TangentType::Out | 1 << 7, |
166 | /** Tangent is calculated automatically based on the next keyframe. */ |
167 | OutLinear = (int)TangentType::Out | 1 << 8, |
168 | /** Tangent is infinite, ensuring there is a instantaneus jump between current and next keyframe value. */ |
169 | OutStep = (int)TangentType::Out | 1 << 9, |
170 | /** Both tangents are manually adjusted by the user. */ |
171 | Free = 1 << 10, |
172 | }; |
173 | |
174 | typedef Flags<TangentModeBits> TangentMode; |
175 | BS_FLAGS_OPERATORS(TangentModeBits) |
176 | |
177 | /* Structure containing a reference to a keyframe as a curve index, and a keyframe index within that curve. */ |
178 | struct BS_SCRIPT_EXPORT(pl:true,m:Animation) KeyframeRef |
179 | { |
180 | KeyframeRef() = default; |
181 | KeyframeRef(INT32 curveIdx, INT32 keyIdx) |
182 | :curveIdx(curveIdx), keyIdx(keyIdx) |
183 | { } |
184 | |
185 | INT32 curveIdx = 0; |
186 | INT32 keyIdx = 0; |
187 | }; |
188 | |
189 | /** Structure containing a reference to a keyframe tangent, as a keyframe reference and type of the tangent. */ |
190 | struct BS_SCRIPT_EXPORT(pl:true,m:Animation) TangentRef |
191 | { |
192 | TangentRef() = default; |
193 | TangentRef(KeyframeRef keyframeRef, TangentType type) |
194 | :keyframeRef(keyframeRef), type(type) |
195 | { } |
196 | |
197 | KeyframeRef keyframeRef; |
198 | TangentType type = TangentType::In; |
199 | }; |
200 | |
201 | /** @} */ |
202 | } |