CustomAvatarAnimationPlayer.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // CustomAvatarAnimationPlayer.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Collections.ObjectModel;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.GamerServices;
  15. #endregion
  16. namespace CustomAvatarAnimation
  17. {
  18. /// <summary>
  19. /// This type implements an animation at runtime, including the
  20. /// current state and updating that state for time.
  21. /// </summary>
  22. public class CustomAvatarAnimationPlayer : CustomAvatarAnimationData, IAvatarAnimation
  23. {
  24. #region Current Animation State
  25. /// <summary>
  26. /// The current keyframe in the animation.
  27. /// </summary>
  28. private int currentKeyframe = 0;
  29. /// <summary>
  30. /// The current expression keyframe in the animation
  31. /// </summary>
  32. private int currentExpressionKeyframe = 0;
  33. /// <summary>
  34. /// The current temporal position in the animation.
  35. /// </summary>
  36. private TimeSpan currentPosition = TimeSpan.Zero;
  37. /// <summary>
  38. /// The current temporal position in the animation.
  39. /// </summary>
  40. public TimeSpan CurrentPosition
  41. {
  42. get
  43. {
  44. return currentPosition;
  45. }
  46. set
  47. {
  48. currentPosition = value;
  49. // Set the current keyframe to 0 since we don't know where we are
  50. // in the list of keyframes. The next update will set the correct
  51. // keyframe.
  52. currentKeyframe = 0;
  53. currentExpressionKeyframe = 0;
  54. // update the animation for the new position,
  55. // elapsing zero additional time
  56. Update(TimeSpan.Zero, false);
  57. }
  58. }
  59. /// <summary>
  60. /// The current position of the bones as the current time in the animation.
  61. /// </summary>
  62. Matrix[] avatarBoneTransforms = new Matrix[AvatarRenderer.BoneCount];
  63. /// <summary>
  64. /// The current position of the bones as the current time in the animation.
  65. /// </summary>
  66. public ReadOnlyCollection<Matrix> BoneTransforms
  67. {
  68. get { return boneTransforms; }
  69. }
  70. private ReadOnlyCollection<Matrix> boneTransforms;
  71. /// <summary>
  72. /// Returns the avatars current expression
  73. /// </summary>
  74. public AvatarExpression Expression
  75. {
  76. get
  77. {
  78. return avatarExpression;
  79. }
  80. }
  81. AvatarExpression avatarExpression = new AvatarExpression();
  82. #endregion
  83. #region Initialization
  84. /// <summary>
  85. /// Constructs a new CustomAvatarAnimationPlayer object.
  86. /// </summary>
  87. /// <param name="name">The name of the animation.</param>
  88. /// <param name="length">The length of the animation.</param>
  89. /// <param name="keyframes">The keyframes in the animation.</param>
  90. public CustomAvatarAnimationPlayer(string name, TimeSpan length,
  91. List<AvatarKeyFrame> keyframes,
  92. List<AvatarExpressionKeyFrame> expressionKeyframes) :
  93. base(name, length, keyframes, expressionKeyframes)
  94. {
  95. // Reset the current bone transforms
  96. for (int i = 0; i < AvatarRenderer.BoneCount; i++)
  97. {
  98. avatarBoneTransforms[i] = Matrix.Identity;
  99. }
  100. boneTransforms = new ReadOnlyCollection<Matrix>(avatarBoneTransforms);
  101. // Update the current bone transforms to the first position in the animation
  102. Update(TimeSpan.Zero, false);
  103. }
  104. #endregion
  105. #region Updating
  106. /// <summary>
  107. /// Updates the current position of the animation.
  108. /// </summary>
  109. /// <param name="timeSpan">The elapsed time since the last update.</param>
  110. /// <param name="loop">If true, the animation will loop.</param>
  111. public void Update(TimeSpan timeSpan, bool loop)
  112. {
  113. // Add the elapsed time to the current time.
  114. currentPosition += timeSpan;
  115. // Check current time against the length
  116. if (currentPosition > Length)
  117. {
  118. if (loop)
  119. {
  120. // Find the right time in the new loop iteration
  121. while (currentPosition > Length)
  122. {
  123. currentPosition -= Length;
  124. }
  125. // Set the keyframe to 0.
  126. currentKeyframe = 0;
  127. currentExpressionKeyframe = 0;
  128. }
  129. else
  130. {
  131. // If the animation is not looping,
  132. // then set the time to the end of the animation.
  133. currentPosition = Length;
  134. }
  135. }
  136. // Check to see if we are less than zero
  137. else if (currentPosition < TimeSpan.Zero)
  138. {
  139. if (loop)
  140. {
  141. // If the animation is looping,
  142. // then find the right time in the new loop iteration
  143. while (currentPosition < TimeSpan.Zero)
  144. {
  145. currentPosition += Length;
  146. }
  147. // Set the keyframe to the last keyframe
  148. currentKeyframe = Keyframes.Count - 1;
  149. currentExpressionKeyframe = ExpressionKeyframes.Count - 1;
  150. }
  151. else
  152. {
  153. // If the animation is not looping,
  154. // then set the time to the beginning of the animation.
  155. currentPosition = TimeSpan.Zero;
  156. }
  157. }
  158. // Update the bone transforms based on the current time.
  159. UpdateBoneTransforms(timeSpan >= TimeSpan.Zero);
  160. // Update the expression
  161. UpdateAvatarExpression(timeSpan >= TimeSpan.Zero);
  162. }
  163. /// <summary>
  164. /// Updates the transforms with the correct keyframes based on the current time.
  165. /// </summary>
  166. /// <param name="playingForward">
  167. /// If true, the animation is playing forward; otherwise, it is playing backwards
  168. /// </param>
  169. private void UpdateBoneTransforms(bool playingForward)
  170. {
  171. if (playingForward)
  172. {
  173. while (currentKeyframe < Keyframes.Count)
  174. {
  175. // Get the current keyframe
  176. AvatarKeyFrame keyframe = Keyframes[currentKeyframe];
  177. // Stop when we've read up to the current time.
  178. if (keyframe.Time >= currentPosition)
  179. break;
  180. // Apply the current keyframe's transform to the bone array.
  181. avatarBoneTransforms[keyframe.Bone] = keyframe.Transform;
  182. // Move the current keyframe forward.
  183. currentKeyframe++;
  184. }
  185. }
  186. else
  187. {
  188. while (currentKeyframe >= 0)
  189. {
  190. // Get the current keyframe
  191. AvatarKeyFrame keyframe = Keyframes[currentKeyframe];
  192. // Stop when we've read back to the current time.
  193. if (keyframe.Time <= currentPosition)
  194. break;
  195. // Apply the current keyframe's transform to the bone array.
  196. avatarBoneTransforms[keyframe.Bone] = keyframe.Transform;
  197. // Move the current keyframe backwards.
  198. currentKeyframe--;
  199. }
  200. }
  201. }
  202. /// <summary>
  203. /// Updates the expression with the correct keyframes based on the current time.
  204. /// </summary>
  205. /// <param name="playingForward">
  206. /// If true, the animation is playing forward; otherwise, it is playing backwards
  207. /// </param>
  208. private void UpdateAvatarExpression(bool playingForward)
  209. {
  210. // Check to see if we have an expression animation
  211. if (ExpressionKeyframes == null || ExpressionKeyframes.Count == 0)
  212. return;
  213. if (playingForward)
  214. {
  215. while (currentExpressionKeyframe < ExpressionKeyframes.Count)
  216. {
  217. // Get the current keyframe
  218. AvatarExpressionKeyFrame keyframe = ExpressionKeyframes[currentExpressionKeyframe];
  219. // Stop when we've read up to the current time.
  220. if (keyframe.Time >= currentPosition)
  221. break;
  222. // Set the current expression
  223. avatarExpression = keyframe.Expression;
  224. // Move the current keyframe forward.
  225. currentExpressionKeyframe++;
  226. }
  227. }
  228. else
  229. {
  230. while (currentExpressionKeyframe >= 0)
  231. {
  232. // Get the current keyframe
  233. AvatarExpressionKeyFrame keyframe = ExpressionKeyframes[currentExpressionKeyframe];
  234. // Stop when we've read back to the current time.
  235. if (keyframe.Time <= currentPosition)
  236. break;
  237. // Set the current expression
  238. avatarExpression = keyframe.Expression;
  239. // Move the current keyframe backwards.
  240. currentExpressionKeyframe--;
  241. }
  242. }
  243. }
  244. #endregion
  245. }
  246. }