BsAnimationClip.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "Resources/BsResource.h"
  6. #include "Math/BsVector3.h"
  7. #include "Math/BsQuaternion.h"
  8. #include "Animation/BsAnimationCurve.h"
  9. namespace bs
  10. {
  11. /** @addtogroup Animation
  12. * @{
  13. */
  14. struct AnimationCurveMapping;
  15. /** A set of animation curves representing translation/rotation/scale and generic animation. */
  16. struct BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Animation) AnimationCurves
  17. {
  18. BS_SCRIPT_EXPORT()
  19. AnimationCurves() {}
  20. /**
  21. * Registers a new curve used for animating position.
  22. *
  23. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  24. * in a skeleton, if any.
  25. * @param[in] curve Curve to add to the clip.
  26. */
  27. BS_SCRIPT_EXPORT(n:AddPositionCurve)
  28. void addPositionCurve(const String& name, const TAnimationCurve<Vector3>& curve);
  29. /**
  30. * Registers a new curve used for animating rotation.
  31. *
  32. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  33. * in a skeleton, if any.
  34. * @param[in] curve Curve to add to the clip.
  35. */
  36. BS_SCRIPT_EXPORT(n:AddRotationCurve)
  37. void addRotationCurve(const String& name, const TAnimationCurve<Quaternion>& curve);
  38. /**
  39. * Registers a new curve used for animating scale.
  40. *
  41. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  42. * in a skeleton, if any.
  43. * @param[in] curve Curve to add to the clip.
  44. */
  45. BS_SCRIPT_EXPORT(n:AddScaleCurve)
  46. void addScaleCurve(const String& name, const TAnimationCurve<Vector3>& curve);
  47. /**
  48. * Registers a new curve used for generic animation.
  49. *
  50. * @param[in] name Unique name of the curve. This can be used for retrieving the value of the curve
  51. * from animation.
  52. * @param[in] curve Curve to add to the clip.
  53. */
  54. BS_SCRIPT_EXPORT(n:AddGenericCurve)
  55. void addGenericCurve(const String& name, const TAnimationCurve<float>& curve);
  56. /** Removes an existing curve from the clip. */
  57. BS_SCRIPT_EXPORT(n:RemovePositionCurve)
  58. void removePositionCurve(const String& name);
  59. /** Removes an existing curve from the clip. */
  60. BS_SCRIPT_EXPORT(n:RemoveRotationCurve)
  61. void removeRotationCurve(const String& name);
  62. /** Removes an existing curve from the clip. */
  63. BS_SCRIPT_EXPORT(n:RemoveScaleCurve)
  64. void removeScaleCurve(const String& name);
  65. /** Removes an existing curve from the clip. */
  66. BS_SCRIPT_EXPORT(n:RemoveGenericCurve)
  67. void removeGenericCurve(const String& name);
  68. /** Curves for animating scene object's position. */
  69. Vector<TNamedAnimationCurve<Vector3>> position;
  70. /** Curves for animating scene object's rotation. */
  71. Vector<TNamedAnimationCurve<Quaternion>> rotation;
  72. /** Curves for animating scene object's scale. */
  73. Vector<TNamedAnimationCurve<Vector3>> scale;
  74. /** Curves for animating generic component properties. */
  75. Vector<TNamedAnimationCurve<float>> generic;
  76. };
  77. /** Contains a set of animation curves used for moving and rotating the root bone. */
  78. struct BS_SCRIPT_EXPORT(m:Animation) RootMotion
  79. {
  80. RootMotion() { }
  81. RootMotion(const TAnimationCurve<Vector3>& position, const TAnimationCurve<Quaternion>& rotation)
  82. :position(position), rotation(rotation)
  83. { }
  84. /** Animation curve representing the movement of the root bone. */
  85. TAnimationCurve<Vector3> position;
  86. /** Animation curve representing the rotation of the root bone. */
  87. TAnimationCurve<Quaternion> rotation;
  88. };
  89. /** Event that is triggered when animation reaches a certain point. */
  90. struct BS_SCRIPT_EXPORT(m:Animation,pl:true) AnimationEvent
  91. {
  92. AnimationEvent()
  93. :time(0.0f)
  94. { }
  95. /**
  96. * Constructs a new animation event.
  97. *
  98. * @param[in] name Name used to identify the event when triggered.
  99. * @param[in] time Time at which to trigger the event, in seconds.
  100. */
  101. AnimationEvent(const String& name, float time)
  102. :name(name), time(time)
  103. { }
  104. /** Name used to identify the event when triggered. */
  105. String name;
  106. /** Time at which to trigger the event, in seconds. */
  107. float time;
  108. };
  109. /** Types of curves in an AnimationClip. */
  110. enum class CurveType
  111. {
  112. Position,
  113. Rotation,
  114. Scale,
  115. Generic,
  116. MorphFrame,
  117. MorphWeight,
  118. Count // Keep at end
  119. };
  120. /**
  121. * Contains animation curves for translation/rotation/scale of scene objects/skeleton bones, as well as curves for
  122. * generic property animation.
  123. */
  124. class BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Animation) AnimationClip : public Resource
  125. {
  126. public:
  127. virtual ~AnimationClip() { }
  128. /** @copydoc setCurves() */
  129. BS_SCRIPT_EXPORT(n:Curves,pr:getter)
  130. SPtr<AnimationCurves> getCurves() const { return mCurves; }
  131. /**
  132. * A set of all curves stored in the animation. Returned value will not be updated if the animation clip curves are
  133. * added or removed, as it is a copy of clip's internal values.
  134. */
  135. BS_SCRIPT_EXPORT(n:Curves,pr:setter)
  136. void setCurves(const AnimationCurves& curves);
  137. /** @copydoc setEvents() */
  138. BS_SCRIPT_EXPORT(n:Events,pr:getter)
  139. const Vector<AnimationEvent>& getEvents() const { return mEvents; }
  140. /** A set of all events to be triggered as the animation is playing. */
  141. BS_SCRIPT_EXPORT(n:Events,pr:setter)
  142. void setEvents(const Vector<AnimationEvent>& events) { mEvents = events; }
  143. /**
  144. * Returns a set of curves containing motion of the root bone. This allows the user to evaluate the root bone
  145. * animation curves manually, instead of through the normal animation process. This property is only available
  146. * if animation clip was imported with root motion import enabled.
  147. */
  148. BS_SCRIPT_EXPORT(n:RootMotion,pr:getter)
  149. SPtr<RootMotion> getRootMotion() const { return mRootMotion; }
  150. /** Checks if animation clip has root motion curves separate from the normal animation curves. */
  151. BS_SCRIPT_EXPORT(n:HasRootMotion,pr:getter)
  152. bool hasRootMotion() const;
  153. /**
  154. * Maps skeleton bone names to animation curve names, and returns a set of indices that can be easily used for
  155. * locating an animation curve based on the bone index.
  156. *
  157. * @param[in] skeleton Skeleton to create the mapping for.
  158. * @param[out] mapping Pre-allocated array that will receive output animation clip indices. The array must
  159. * be large enough to store an index for every bone in the @p skeleton. Bones that have
  160. * no related animation curves will be assigned value -1.
  161. */
  162. void getBoneMapping(const Skeleton& skeleton, AnimationCurveMapping* mapping) const;
  163. /**
  164. * Attempts to find translation/rotation/scale curves with the specified name and fills the mapping structure with
  165. * their indices, which can then be used for quick lookup.
  166. *
  167. * @param[in] name Name of the curves to look up.
  168. * @param[out] mapping Triple containing the translation/rotation/scale indices of the found curves. Indices
  169. * will be -1 for curves that haven't been found.
  170. */
  171. void getCurveMapping(const String& name, AnimationCurveMapping& mapping) const;
  172. /**
  173. * Attempts to find a generic curve with the specified name and fills output with found index, which can then be
  174. * used for quick lookup.
  175. *
  176. * @param[in] name Name of the curve to look up.
  177. * @param[out] frameIdx Index of the curve animating the morph shape frames, or -1 if not found.
  178. * @param[out] weightIdx Index of the curve animating the channel weight, or -1 if not found.
  179. */
  180. void getMorphMapping(const String& name, UINT32& frameIdx, UINT32& weightIdx) const;
  181. /**
  182. * Checks are the curves contained within the clip additive. Additive clips are intended to be added on top of
  183. * other clips.
  184. */
  185. BS_SCRIPT_EXPORT(n:IsAddtive,pr:getter)
  186. bool isAdditive() const { return mIsAdditive; }
  187. /** Returns the length of the animation clip, in seconds. */
  188. BS_SCRIPT_EXPORT(n:Length,pr:getter)
  189. float getLength() const { return mLength; }
  190. /** @copydoc setSampleRate() */
  191. BS_SCRIPT_EXPORT(n:SampleRate,pr:getter)
  192. UINT32 getSampleRate() const { return mSampleRate; }
  193. /**
  194. * Number of samples per second the animation clip curves were sampled at. This value is not used by the animation
  195. * clip or curves directly since unevenly spaced keyframes are supported. But it can be of value when determining
  196. * the original sample rate of an imported animation or similar.
  197. */
  198. BS_SCRIPT_EXPORT(n:SampleRate,pr:setter)
  199. void setSampleRate(UINT32 sampleRate) { mSampleRate = sampleRate; }
  200. /**
  201. * Returns a version that can be used for detecting modifications on the clip by external systems. Whenever the clip
  202. * is modified the version is increased by one.
  203. */
  204. UINT64 getVersion() const { return mVersion; }
  205. /**
  206. * Creates an animation clip with no curves. After creation make sure to register some animation curves before
  207. * using it.
  208. */
  209. BS_SCRIPT_EXPORT(ec:AnimationClip)
  210. static HAnimationClip create(bool isAdditive = false);
  211. /**
  212. * Creates an animation clip with specified curves.
  213. *
  214. * @param[in] curves Curves to initialize the animation with.
  215. * @param[in] isAdditive Determines does the clip contain additive curve data. This will change the behaviour
  216. * how is the clip blended with other animations.
  217. * @param[in] sampleRate If animation uses evenly spaced keyframes, number of samples per second. Not relevant
  218. * if keyframes are unevenly spaced.
  219. * @param[in] rootMotion Optional set of curves that can be used for animating the root bone. Not used by the
  220. * animation system directly but is instead provided to the user for manual evaluation.
  221. */
  222. BS_SCRIPT_EXPORT(ec:AnimationClip)
  223. static HAnimationClip create(const SPtr<AnimationCurves>& curves, bool isAdditive = false, UINT32 sampleRate = 1,
  224. const SPtr<RootMotion>& rootMotion = nullptr);
  225. public: // ***** INTERNAL ******
  226. /** @name Internal
  227. * @{
  228. */
  229. /** Creates a new AnimationClip without initializing it. Use create() for normal use. */
  230. static SPtr<AnimationClip> _createPtr(const SPtr<AnimationCurves>& curves, bool isAdditive = false,
  231. UINT32 sampleRate = 1, const SPtr<RootMotion>& rootMotion = nullptr);
  232. /** @} */
  233. protected:
  234. AnimationClip();
  235. AnimationClip(const SPtr<AnimationCurves>& curves, bool isAdditive, UINT32 sampleRate,
  236. const SPtr<RootMotion>& rootMotion);
  237. /** @copydoc Resource::initialize() */
  238. void initialize() override;
  239. /** Creates a name -> curve index mapping for quicker curve lookup by name. */
  240. void buildNameMapping();
  241. /** Calculate the length of the clip based on assigned curves. */
  242. void calculateLength();
  243. UINT64 mVersion;
  244. /**
  245. * Contains all the animation curves in the clip. It's important this field is immutable so it may be used on other
  246. * threads. This means any modifications to the field will require a brand new data structure to be generated and
  247. * all existing data copied (plus the modification).
  248. */
  249. SPtr<AnimationCurves> mCurves;
  250. /**
  251. * A set of curves containing motion of the root bone. If this is non-empty it should be true that mCurves does not
  252. * contain animation curves for the root bone. Root motion will not be evaluated through normal animation process
  253. * but is instead provided for the user for manual evaluation.
  254. */
  255. SPtr<RootMotion> mRootMotion;
  256. /**
  257. * Contains a map from curve name to curve index. Indices are stored as specified in CurveType enum.
  258. */
  259. UnorderedMap<String, UINT32[(int)CurveType::Count]> mNameMapping;
  260. Vector<AnimationEvent> mEvents;
  261. bool mIsAdditive;
  262. float mLength;
  263. UINT32 mSampleRate;
  264. /************************************************************************/
  265. /* SERIALIZATION */
  266. /************************************************************************/
  267. public:
  268. friend class AnimationClipRTTI;
  269. static RTTITypeBase* getRTTIStatic();
  270. RTTITypeBase* getRTTI() const override;
  271. /**
  272. * Creates an AnimationClip with no data. You must populate its data manually followed by a call to initialize().
  273. *
  274. * @note For serialization use only.
  275. */
  276. static SPtr<AnimationClip> createEmpty();
  277. };
  278. /** @} */
  279. }