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/BsAnimation.h"
7#include "Scene/BsComponent.h"
8
9namespace bs
10{
11 /** @addtogroup Components-Core
12 * @{
13 */
14
15 /**
16 * @copydoc Animation
17 *
18 * @note Wraps Animation as a Component.
19 */
20 class BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Animation,n:Animation) CAnimation : public Component
21 {
22 /** Information about scene objects bound to a specific animation curve. */
23 struct SceneObjectMappingInfo
24 {
25 HSceneObject sceneObject;
26 bool isMappedToBone;
27 HBone bone;
28 };
29
30 public:
31 CAnimation(const HSceneObject& parent);
32 virtual ~CAnimation() = default;
33
34 /**
35 * Determines the default clip to play as soon as the component is enabled. If more control over playing clips is needed
36 * use the play(), blend() and crossFade() methods to queue clips for playback manually, and setState() method for
37 * modify their states individually.
38 */
39 BS_SCRIPT_EXPORT(n:DefaultClip,pr:setter)
40 void setDefaultClip(const HAnimationClip& clip);
41
42 /** @copydoc setDefaultClip */
43 BS_SCRIPT_EXPORT(n:DefaultClip,pr:getter)
44 HAnimationClip getDefaultClip() const { return mDefaultClip; }
45
46 /** @copydoc Animation::setWrapMode */
47 BS_SCRIPT_EXPORT(n:WrapMode,pr:setter)
48 void setWrapMode(AnimWrapMode wrapMode);
49
50 /** @copydoc setWrapMode */
51 BS_SCRIPT_EXPORT(n:WrapMode,pr:getter)
52 AnimWrapMode getWrapMode() const { return mWrapMode; }
53
54 /** @copydoc Animation::setSpeed */
55 BS_SCRIPT_EXPORT(n:Speed,pr:setter)
56 void setSpeed(float speed);
57
58 /** @copydoc setSpeed */
59 BS_SCRIPT_EXPORT(n:Speed,pr:getter)
60 float getSpeed() const { return mSpeed; }
61
62 /** @copydoc Animation::play */
63 BS_SCRIPT_EXPORT(n:Play)
64 void play(const HAnimationClip& clip);
65
66 /** @copydoc Animation::blendAdditive */
67 BS_SCRIPT_EXPORT(n:BlendAdditive)
68 void blendAdditive(const HAnimationClip& clip, float weight, float fadeLength = 0.0f, UINT32 layer = 0);
69
70 /** @copydoc Animation::blend1D */
71 BS_SCRIPT_EXPORT(n:Blend1D)
72 void blend1D(const Blend1DInfo& info, float t);
73
74 /** @copydoc Animation::blend2D */
75 BS_SCRIPT_EXPORT(n:Blend2D)
76 void blend2D(const Blend2DInfo& info, const Vector2& t);
77
78 /** @copydoc Animation::crossFade */
79 BS_SCRIPT_EXPORT(n:CrossFade)
80 void crossFade(const HAnimationClip& clip, float fadeLength);
81
82 /** @copydoc Animation::sample */
83 BS_SCRIPT_EXPORT(n:Sample)
84 void sample(const HAnimationClip& clip, float time);
85
86 /** @copydoc Animation::stop */
87 BS_SCRIPT_EXPORT(n:Stop)
88 void stop(UINT32 layer);
89
90 /** @copydoc Animation::stopAll */
91 BS_SCRIPT_EXPORT(n:StopAll)
92 void stopAll();
93
94 /** @copydoc Animation::isPlaying */
95 BS_SCRIPT_EXPORT(n:IsPlaying,pr:getter)
96 bool isPlaying() const;
97
98 /** @copydoc Animation::getState */
99 BS_SCRIPT_EXPORT(n:GetState)
100 bool getState(const HAnimationClip& clip, AnimationClipState& state);
101
102 /** @copydoc Animation::setState */
103 BS_SCRIPT_EXPORT(n:SetState)
104 void setState(const HAnimationClip& clip, AnimationClipState state);
105
106 /**
107 * Changes a weight of a single morph channel, determining how much of it to apply on top of the base mesh.
108 *
109 * @param name Name of the morph channel to modify. This depends on the mesh the animation is currently
110 * animating.
111 * @param weight Weight that determines how much of the channel to apply to the mesh, in range [0, 1].
112 */
113 BS_SCRIPT_EXPORT(n:SetMorphChannelWeight)
114 void setMorphChannelWeight(const String& name, float weight);
115
116 /** Determines bounds that will be used for animation and mesh culling. Only relevant if setUseBounds() is set to true. */
117 BS_SCRIPT_EXPORT(n:Bounds,pr:setter)
118 void setBounds(const AABox& bounds);
119
120 /** @copydoc setBounds */
121 BS_SCRIPT_EXPORT(n:Bounds,pr:getter)
122 const AABox& getBounds() const { return mBounds; }
123
124 /**
125 * Determines should animation bounds be used for visibility determination (culling). If false the bounds of the
126 * mesh attached to the relevant CRenderable component will be used instead.
127 */
128 BS_SCRIPT_EXPORT(n:UseBounds,pr:setter)
129 void setUseBounds(bool enable);
130
131 /** @copydoc setUseBounds */
132 BS_SCRIPT_EXPORT(n:UseBounds,pr:getter)
133 bool getUseBounds() const { return mUseBounds; }
134
135 /** Enables or disables culling of the animation when out of view. Culled animation will not be evaluated. */
136 BS_SCRIPT_EXPORT(n:Cull,pr:setter)
137 void setEnableCull(bool enable);
138
139 /** Checks whether the animation will be evaluated when it is out of view. */
140 BS_SCRIPT_EXPORT(n:Cull,pr:getter)
141 bool getEnableCull() const { return mEnableCull; }
142
143 /** @copydoc Animation::getNumClips */
144 BS_SCRIPT_EXPORT(in:true)
145 UINT32 getNumClips() const;
146
147 /** @copydoc Animation::getClip */
148 BS_SCRIPT_EXPORT(in:true)
149 HAnimationClip getClip(UINT32 idx) const;
150
151 /** Triggered whenever an animation event is reached. */
152 Event<void(const HAnimationClip&, const String&)> onEventTriggered;
153
154 /** @name Internal
155 * @{
156 */
157
158 /** Returns the Animation implementation wrapped by this component. */
159 SPtr<Animation> _getInternal() const { return mInternal; }
160
161 /**
162 * Registers a new bone component, creating a new transform mapping from the bone name to the scene object the
163 * component is attached to.
164 */
165 void _addBone(HBone bone);
166
167 /** Unregisters a bone component, removing the bone -> scene object mapping. */
168 void _removeBone(const HBone& bone);
169
170 /** Called whenever the bone name the Bone component points to changes. */
171 void _notifyBoneChanged(const HBone& bone);
172
173 /**
174 * Registers a Renderable component with the animation, should be called whenever a Renderable component is added
175 * to the same scene object as this component.
176 */
177 void _registerRenderable(const HRenderable& renderable);
178
179 /**
180 * Removes renderable from the animation component. Should be called when a Renderable component is removed from
181 * this scene object.
182 */
183 void _unregisterRenderable();
184
185 /** Re-applies the bounds to the internal animation object, and the relevant renderable object if one exists. */
186 void _updateBounds(bool updateRenderable = true);
187
188 /**
189 * Rebuilds internal curve -> property mapping about the currently playing animation clip. This mapping allows the
190 * animation component to know which property to assign which values from an animation curve. This should be called
191 * whenever playback for a new clip starts, or when clip curves change.
192 */
193 BS_SCRIPT_EXPORT(in:true)
194 void _refreshClipMappings();
195
196 /** @copydoc Animation::getGenericCurveValue */
197 BS_SCRIPT_EXPORT(in:true)
198 bool _getGenericCurveValue(UINT32 curveIdx, float& value);
199
200 /**
201 * Preview mode allows certain operations on the component to be allowed (like basic animation playback),
202 * even when the component is not actively running. This is intended for use primarily by the animation editor.
203 * Preview mode ends automatically when the component is enabled (i.e. starts running normally), or when
204 * explicitly disabled. Returns true if the preview mode was enabled (which could fail if the component is
205 * currently running).
206 */
207 BS_SCRIPT_EXPORT(in:true)
208 bool _togglePreviewMode(bool enabled);
209
210 /** Triggered when the list of properties animated via generic animation curves needs to be recreated (script only). */
211 BS_SCRIPT_EXPORT(n:RebuildFloatProperties)
212 std::function<void(const HAnimationClip&)> _scriptRebuildFloatProperties;
213
214 /** Triggered when generic animation curves values need be applied to the properties they effect (script only). */
215 BS_SCRIPT_EXPORT(n:_UpdateFloatProperties)
216 std::function<void()> _scriptUpdateFloatProperties;
217
218 /** Triggers a callback in script code when animation event is triggered (script only). */
219 BS_SCRIPT_EXPORT(n:EventTriggered)
220 std::function<void(const HAnimationClip&, const String&)> _scriptOnEventTriggered;
221
222 /** @} */
223
224 /************************************************************************/
225 /* COMPONENT OVERRIDES */
226 /************************************************************************/
227 protected:
228 friend class SceneObject;
229
230 /** @copydoc Component::onInitialized() */
231 void onInitialized() override;
232
233 /** @copydoc Component::onDestroyed() */
234 void onDestroyed() override;
235
236 /** @copydoc Component::update() */
237 void update() override;
238
239 /** @copydoc Component::onDisabled() */
240 void onDisabled() override;
241
242 /** @copydoc Component::onEnabled() */
243 void onEnabled() override;
244
245 /** @copydoc Component::onTransformChanged() */
246 void onTransformChanged(TransformChangedFlags flags) override;
247 protected:
248 using Component::destroyInternal;
249
250 /** Creates the internal representation of the Animation and restores the values saved by the Component. */
251 void restoreInternal(bool previewMode);
252
253 /** Destroys the internal Animation representation. */
254 void destroyInternal();
255
256 /** Callback triggered whenever an animation event is triggered. */
257 void eventTriggered(const HAnimationClip& clip, const String& name);
258
259 /**
260 * Finds any scene objects that are mapped to bone transforms. Such object's transforms will be affected by
261 * skeleton bone animation.
262 */
263 void setBoneMappings();
264
265 /**
266 * Finds any curves that affect a transform of a specific scene object, and ensures that animation properly updates
267 * those transforms. This does not include curves referencing bones.
268 */
269 void updateSceneObjectMapping();
270
271 /** @copydoc Animation::mapCurveToSceneObject */
272 void mapCurveToSceneObject(const String& curve, const HSceneObject& so);
273
274 /** @copydoc Animation::unmapSceneObject */
275 void unmapSceneObject(const HSceneObject& so);
276
277 /** Searches child scene objects for Bone components and returns any found ones. */
278 Vector<HBone> findChildBones();
279
280 SPtr<Animation> mInternal;
281 HRenderable mAnimatedRenderable;
282
283 HAnimationClip mDefaultClip;
284 HAnimationClip mPrimaryPlayingClip;
285 AnimWrapMode mWrapMode = AnimWrapMode::Loop;
286 float mSpeed = 1.0f;
287 bool mEnableCull = true;
288 bool mUseBounds = false;
289 bool mPreviewMode = false;
290 AABox mBounds;
291
292 Vector<SceneObjectMappingInfo> mMappingInfos;
293
294 /************************************************************************/
295 /* RTTI */
296 /************************************************************************/
297 public:
298 friend class CAnimationRTTI;
299 static RTTITypeBase* getRTTIStatic();
300 RTTITypeBase* getRTTI() const override;
301
302 protected:
303 CAnimation(); // Serialization only
304 };
305
306 /** @} */
307}