FAnimationTrackCache.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. //#define FLUX_DEBUG
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. namespace Flux
  5. {
  6. /// @brief Cache for FAnimationTrack
  7. public class FAnimationTrackCache : FTrackCache {
  8. private Animator _animator = null;
  9. public Animator Animator
  10. {
  11. get {
  12. if( _animator == null )
  13. _animator = Track.Owner.GetComponent<Animator>();
  14. return _animator;
  15. }
  16. }
  17. private bool _inPlayback = false;
  18. /// @brief Is the cache in playback?
  19. public bool InPlayback { get { return _inPlayback; } }
  20. // all the tracks it is caching
  21. private List<FAnimationTrack> _tracksCached = new List<FAnimationTrack>();
  22. /// @brief Number of tracks being cached
  23. public int NumberTracksCached { get { return _tracksCached.Count; } }
  24. // snapshot to revert GO state when in editor mode
  25. // private GameObjectSnapshot _snapshot;
  26. private List<FrameRange> _validFrameRanges = new List<FrameRange>();
  27. public FAnimationTrackCache( FTrack track )
  28. :base( track )
  29. {
  30. }
  31. protected override bool BuildInternal()
  32. {
  33. List<FTrack> tracksToUpdate = GetTracksToUpdate( out _tracksCached );
  34. // _tracksCached = GetAnimationTracks();
  35. _validFrameRanges.Clear();
  36. if( _tracksCached.Count == 0 || Animator == null || Animator.runtimeAnimatorController == null )
  37. return false;
  38. // build preview
  39. #if FLUX_DEBUG
  40. Debug.LogWarning("Creating Preview");
  41. #endif
  42. TransformSnapshot transformSnapshot = new TransformSnapshot(Track.Owner);
  43. FSequence sequence = Track.Sequence;
  44. if( _tracksCached[0].Snapshot != null )
  45. _tracksCached[0].Snapshot.Restore();
  46. // _snapshot = Application.isPlaying ? null : new GameObjectSnapshot( Track.Owner.gameObject );
  47. bool ownerIsActive = Track.Owner.gameObject.activeSelf;
  48. float speed = sequence.Speed;
  49. if( speed != 1 )
  50. sequence.Speed = 1f;
  51. Animator.speed = 1f;
  52. int currentFrame = sequence.CurrentFrame;
  53. bool isPlaying = sequence.IsPlaying;
  54. if( !sequence.IsStopped )
  55. sequence.Stop();
  56. if( !sequence.IsInit )
  57. sequence.Init();
  58. if( !ownerIsActive )
  59. {
  60. HideFlags hideFlags = Track.Owner.gameObject.hideFlags;
  61. Track.Owner.gameObject.hideFlags |= HideFlags.DontSave;
  62. Track.Owner.gameObject.SetActive( true );
  63. Track.Owner.gameObject.hideFlags = hideFlags;
  64. }
  65. FrameRange currentFrameRange = new FrameRange();
  66. foreach( FAnimationTrack animTrack in _tracksCached )
  67. {
  68. animTrack.Cache = null;
  69. animTrack.Stop(); // we need to force stop them to clear the currentEvent index
  70. }
  71. // set culling to get around Unity bug of recording at the start
  72. AnimatorCullingMode animatorCullingMode = Animator.cullingMode;
  73. Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
  74. Animator.enabled = true;
  75. for( int i = 0; i != Animator.layerCount; ++i )
  76. {
  77. Animator.SetLayerWeight(i, 0f);
  78. }
  79. Animator.StartRecording( -1 );
  80. bool success = Animator.recorderMode == AnimatorRecorderMode.Record;
  81. if( success )
  82. {
  83. Animator.enabled = false;
  84. float delta = 1f / sequence.FrameRate;
  85. int frame = 0;
  86. while( frame <= sequence.Length )
  87. {
  88. bool wasEnabled = Animator.enabled;
  89. foreach( FTrack track in tracksToUpdate )
  90. track.UpdateEvents( frame, frame * delta );
  91. if( wasEnabled )
  92. {
  93. currentFrameRange.End += 1;
  94. if( Animator.enabled )
  95. {
  96. Animator.Update( delta );
  97. }
  98. else
  99. {
  100. Animator.enabled = true;
  101. Animator.Update( delta );
  102. Animator.enabled = false;
  103. _validFrameRanges.Add( currentFrameRange );
  104. }
  105. }
  106. else if( Animator.enabled )
  107. {
  108. Animator.Update( 0 );
  109. currentFrameRange = new FrameRange( frame, frame );
  110. }
  111. ++frame;
  112. }
  113. foreach( FAnimationTrack animTrack in _tracksCached )
  114. {
  115. animTrack.Cache = this;
  116. }
  117. Track = _tracksCached[0];
  118. Animator.StopRecording();
  119. }
  120. if( !ownerIsActive )
  121. {
  122. HideFlags hideFlags = Track.Owner.gameObject.hideFlags;
  123. Track.Owner.gameObject.hideFlags |= HideFlags.DontSave;
  124. Track.Owner.gameObject.SetActive( false );
  125. Track.Owner.gameObject.hideFlags = hideFlags;
  126. }
  127. if( speed != 1 )
  128. sequence.Speed = speed;
  129. Animator.cullingMode = animatorCullingMode;
  130. sequence.Stop(true);
  131. if( currentFrame >= 0 )
  132. {
  133. if( isPlaying )
  134. sequence.Play( currentFrame );
  135. else
  136. sequence.SetCurrentFrame( currentFrame );
  137. transformSnapshot.Restore();
  138. }
  139. return success;
  140. }
  141. protected override bool ClearInternal()
  142. {
  143. #if FLUX_DEBUG
  144. Debug.LogWarning("Destroying Preview");
  145. #endif
  146. StopPlayback();
  147. foreach( FAnimationTrack animTrack in _tracksCached )
  148. {
  149. // animTrack.HasPreview = false;
  150. animTrack.Cache = null;
  151. }
  152. _tracksCached.Clear();
  153. return true;
  154. }
  155. /// @brief Starts playback
  156. public void StartPlayback()
  157. {
  158. if( _inPlayback )
  159. return;
  160. #if FLUX_DEBUG
  161. Debug.Log ("Start Playback");
  162. #endif
  163. // save transforms
  164. Animator.enabled = true;
  165. Animator.StartPlayback();
  166. _inPlayback = true;
  167. }
  168. /// @brief Stops playback
  169. public void StopPlayback()
  170. {
  171. if( !_inPlayback )
  172. return;
  173. #if FLUX_DEBUG
  174. Debug.Log ("Stop Playback");
  175. #endif
  176. Animator.StopPlayback();
  177. _inPlayback = false;
  178. }
  179. public override void GetPlaybackAt( float sequenceTime )
  180. {
  181. if( !InPlayback )
  182. StartPlayback();
  183. /// @TODO waiting for Unity crash bug to be fixed
  184. if( Track.Owner.gameObject.activeInHierarchy )
  185. {
  186. Animator.playbackTime = ConvertSequenceTime( sequenceTime );
  187. Animator.Update(0f);
  188. }
  189. }
  190. private float ConvertSequenceTime( float sequenceTime )
  191. {
  192. float playbackTime = 0;
  193. for( int i = 0; i != _validFrameRanges.Count; ++i )
  194. {
  195. float startTime = _validFrameRanges[i].Start * Track.Sequence.InverseFrameRate;
  196. if( startTime > sequenceTime )
  197. {
  198. // make sure we're still on the left of the preview
  199. playbackTime -= 0.0001f;
  200. break;
  201. }
  202. float endTime = _validFrameRanges[i].End * Track.Sequence.InverseFrameRate;
  203. if( endTime > sequenceTime )
  204. {
  205. // make sure we're on the right of the preview
  206. playbackTime += sequenceTime - startTime + 0.0001f;
  207. break;
  208. }
  209. else
  210. {
  211. playbackTime += endTime - startTime;
  212. }
  213. }
  214. // make sure we're just left to the end of the recorded data, because last frame will be with layer turned off
  215. return Mathf.Clamp( playbackTime, Animator.recorderStartTime, Animator.recorderStopTime - 0.0001f );
  216. }
  217. // private List<FAnimationTrack> GetAnimationTracks()
  218. private List<FTrack> GetTracksToUpdate( out List<FAnimationTrack> animTracks )
  219. {
  220. List<FTrack> tracksToUpdate = new List<FTrack>();
  221. animTracks = new List<FAnimationTrack>();
  222. Transform owner = Track.Owner;
  223. List<FContainer> containers = Track.Sequence.Containers;
  224. // bool isPlaying = Application.isPlaying;
  225. foreach( FContainer container in containers )
  226. {
  227. List<FTimeline> timelines = container.Timelines;
  228. foreach( FTimeline timeline in timelines )
  229. {
  230. if( timeline.Owner != owner )
  231. continue;
  232. List<FTrack> tracks = timeline.Tracks;
  233. foreach( FTrack track in tracks )
  234. {
  235. if( track != null && track.enabled /*&& (isPlaying || track is FTransformTrack)*/ )
  236. {
  237. if( track is FAnimationTrack )
  238. {
  239. animTracks.Add( (FAnimationTrack)track );
  240. tracksToUpdate.Add( track );
  241. }
  242. else if( track is FTransformTrack )
  243. tracksToUpdate.Add( track );
  244. }
  245. }
  246. }
  247. }
  248. return tracksToUpdate;
  249. }
  250. }
  251. #region GameObject Snapshot
  252. // /// @brief Takes a snapshot of a whole GameObject hierarchy
  253. // public class GameObjectSnapshot
  254. // {
  255. // // list of snapshots, i.e. internal Transform hierarchy
  256. // private List<TransformSnapshot> _snapshotList;
  257. // public List<TransformSnapshot> SnapshotList { get { return _snapshotList; } }
  258. //
  259. // // top Transform
  260. // private Transform _root;
  261. // public Transform Root { get { return _root; } }
  262. //
  263. // /**
  264. // * @brief Creates a snapshot
  265. // * @param go GameObject
  266. // */
  267. // public GameObjectSnapshot( GameObject go )
  268. // {
  269. // _root = go.transform;
  270. // _snapshotList = new List<TransformSnapshot>();
  271. //
  272. // TakeHierarchySnapshot( Root );
  273. // }
  274. //
  275. // /// @brief Restores the GameObject
  276. // public void Restore()
  277. // {
  278. // foreach( TransformSnapshot snapshot in _snapshotList )
  279. // {
  280. // snapshot.Restore();
  281. // }
  282. // }
  283. //
  284. // // Takes snapshot recursively
  285. // private void TakeHierarchySnapshot( Transform transform )
  286. // {
  287. // TransformSnapshot snapshot = new TransformSnapshot( transform );
  288. //
  289. // _snapshotList.Add( snapshot );
  290. //
  291. // for( int i = 0; i != transform.childCount; ++i )
  292. // {
  293. // TakeHierarchySnapshot( transform.GetChild(i) );
  294. // }
  295. // }
  296. // }
  297. //
  298. // /// @brief Saves the state of a transform
  299. // public class TransformSnapshot
  300. // {
  301. // // Transform saved
  302. // private Transform _transform = null;
  303. // public Transform Transform { get { return _transform; } }
  304. //
  305. // private Transform _parent = null;
  306. // public Transform Parent { get { return _parent; } }
  307. //
  308. // private Vector3 _localPosition;
  309. // public Vector3 LocalPosition { get { return _localPosition; } }
  310. //
  311. // private Quaternion _localRotation;
  312. // public Quaternion LocalRotation { get { return _localRotation; } }
  313. //
  314. // private Vector3 _localScale;
  315. // public Vector3 LocalScale { get { return _localScale; } }
  316. //
  317. // /**
  318. // * @brief Saves transform state
  319. // * @param transform Transform we want to save
  320. // */
  321. // public TransformSnapshot( Transform transform )
  322. // {
  323. // _transform = transform;
  324. // _parent = _transform.parent;
  325. // _localPosition = _transform.localPosition;
  326. // _localRotation = _transform.localRotation;
  327. // _localScale = _transform.localScale;
  328. // }
  329. //
  330. // /// @brief Restores the transform state.
  331. // public void Restore()
  332. // {
  333. // if( _parent != _transform.parent )
  334. // _transform.parent = _parent;
  335. // _transform.localRotation = _localRotation;
  336. // _transform.localPosition = _localPosition;
  337. // _transform.localScale = _localScale;
  338. // }
  339. // }
  340. #endregion
  341. }