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 | |
9 | namespace 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 | } |