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