FTrack.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. using UnityEngine;
  2. using System;
  3. using System.Reflection;
  4. using System.Collections.Generic;
  5. namespace Flux
  6. {
  7. [System.Flags]
  8. public enum CacheMode
  9. {
  10. // None = 0,
  11. Editor = 1,
  12. RuntimeForward = 2,
  13. RuntimeBackwards = 4
  14. }
  15. /**
  16. * @brief FTrack holds events of a specific type. You cannot have a track with multiple types of events.
  17. * You can only have 2 events on the same frame per track, i.e. overlapping start and end.
  18. * @sa FSequence, FTimeline, FEvent
  19. */
  20. public class FTrack : FObject
  21. {
  22. // timeline it belongs to
  23. [SerializeField]
  24. [HideInInspector]
  25. private FTimeline _timeline;
  26. // string of the type of events it holds
  27. [SerializeField]
  28. [HideInInspector]
  29. private string _evtTypeStr;
  30. // event type, which unfortunately doesn't serialize
  31. private Type _evtType;
  32. // events it holds
  33. [SerializeField]
  34. [HideInInspector]
  35. private List<FEvent> _events = new List<FEvent>();
  36. /// @brief List of events it holds
  37. public List<FEvent> Events { get { return _events; } }
  38. public bool RequiresNoCache { get { return CacheMode == 0; } }
  39. public bool RequiresEditorCache { get { return (CacheMode & CacheMode.Editor) != 0; } }
  40. public bool RequiresForwardCache { get { return (CacheMode & CacheMode.RuntimeForward) != 0; } }
  41. public bool RequiresBackwardsCache { get { return (CacheMode & CacheMode.RuntimeBackwards) != 0; } }
  42. [SerializeField]
  43. [HideInInspector]
  44. private CacheMode _cacheMode = 0;
  45. public CacheMode CacheMode { get { return _cacheMode; } set { _cacheMode = value; } }
  46. public virtual CacheMode RequiredCacheMode { get { return 0; } }
  47. public virtual CacheMode AllowedCacheMode { get { return 0; } }
  48. // keep track of the current event we're updating
  49. private int _currentEvent = 0;
  50. /**
  51. * @brief Creates a FTrack.
  52. * @param T type of event this track will hold
  53. */
  54. public static FTrack Create<T>() where T : FEvent
  55. {
  56. Type evtType = typeof(T);
  57. string evtName = evtType.Name;
  58. GameObject trackGO = new GameObject( evtName );
  59. Type trackType = typeof(FTrack);
  60. #if NETFX_CORE
  61. System.Attribute[] customAttributes = new List<System.Attribute>(evtType.GetTypeInfo().GetCustomAttributes(typeof(FEventAttribute), false)).ToArray();
  62. #else
  63. object[] customAttributes = evtType.GetCustomAttributes(typeof(FEventAttribute), false);
  64. #endif
  65. if (customAttributes.Length > 0 )
  66. {
  67. trackType = ((FEventAttribute)customAttributes[0]).trackType;
  68. }
  69. FTrack track = (FTrack)trackGO.AddComponent(trackType);
  70. track.SetEventType( evtType );
  71. track.CacheMode = track.RequiredCacheMode;
  72. return track;
  73. }
  74. // sets the timeline it belongs to, only to be called by FTimeline to avoid errors
  75. internal void SetTimeline( FTimeline timeline )
  76. {
  77. _timeline = timeline;
  78. if( _timeline )
  79. {
  80. transform.parent = _timeline.transform;
  81. }
  82. else
  83. {
  84. transform.parent = null;
  85. }
  86. }
  87. public override FSequence Sequence { get { return _timeline.Sequence; } }
  88. public override Transform Owner { get { return _timeline.Owner; } }
  89. public override void Init()
  90. {
  91. _currentEvent = Sequence.IsPlayingForward ? 0 : _events.Count - 1;
  92. for( int i = 0; i != _events.Count; ++i )
  93. _events[i].Init();
  94. }
  95. /// @brief Pauses the timeline
  96. public virtual void Pause()
  97. {
  98. for( int i = 0; i != _events.Count; ++i )
  99. {
  100. if( _events[i].HasTriggered && !_events[i].HasFinished )
  101. _events[i].Pause();
  102. }
  103. }
  104. /// @brief Resumes the timeline
  105. public virtual void Resume()
  106. {
  107. for( int i = 0; i != _events.Count; ++i )
  108. {
  109. if( _events[i].HasTriggered && !_events[i].HasFinished )
  110. _events[i].Resume();
  111. }
  112. }
  113. public override void Stop()
  114. {
  115. for( int i = _events.Count-1; i >= 0; --i )
  116. {
  117. if( _events[i].HasTriggered )
  118. _events[i].Stop();
  119. }
  120. _currentEvent = Sequence.IsPlayingForward ? 0 : _events.Count - 1;
  121. }
  122. /// @brief Returns true if the track has no events
  123. public bool IsEmpty()
  124. {
  125. return _events.Count == 0;
  126. }
  127. /// @brief Returns to which timeline this track belongs
  128. public FTimeline Timeline { get { return _timeline; } }
  129. /// @brief Returns which type of event this track holds
  130. public Type GetEventType()
  131. {
  132. if( _evtType == null )
  133. {
  134. _evtType = Type.GetType( _evtTypeStr );
  135. }
  136. return _evtType;
  137. }
  138. /// @brief Sets the type of event this track holds
  139. /// @param evtType Has to inherit from FEvent
  140. private void SetEventType( Type evtType )
  141. {
  142. #if NETFX_CORE
  143. if (!evtType.GetTypeInfo().IsSubclassOf( typeof(FEvent) ) )
  144. #else
  145. if (!evtType.IsSubclassOf(typeof(FEvent)))
  146. #endif
  147. throw new ArgumentException( evtType.ToString() + " does not inherit from FEvent");
  148. _evtType = evtType;
  149. _evtTypeStr = evtType.ToString();
  150. }
  151. /// @brief Returns event on position \e index, they are ordered left to right.
  152. public FEvent GetEvent( int index )
  153. {
  154. return _events[index];
  155. }
  156. /// @brief Returns events at a specific frame.
  157. public int GetEventsAt( int t, FEvent[] evtBuffer )
  158. {
  159. int index = 0;
  160. for( int i = 0; i != _events.Count; ++i )
  161. {
  162. if( _events[i].Start <= t && _events[i].End >= t )
  163. evtBuffer[index++] = _events[i];
  164. else if( _events[i].Start > t ) // since they are ordered, no point in continuing
  165. break;
  166. }
  167. return index;
  168. }
  169. /// @brief Returns events at a given frame
  170. /// @param [in] t Frame
  171. /// @param [out] first First event, if there's 2 events it will be the one ending on that frame
  172. /// @param [out] second Second event, if there's 2 events it will be the one starting on that frame
  173. /// @return How many events are at frame \e t
  174. public int GetEventsAt( int t, out FEvent first, out FEvent second )
  175. {
  176. int index = 0;
  177. first = null;
  178. second = null;
  179. for( int i = 0; i != _events.Count; ++i )
  180. {
  181. if( _events[i].Start <= t && _events[i].End >= t )
  182. {
  183. if( index == 0 )
  184. first = _events[i];
  185. else
  186. second = _events[i];
  187. ++index;
  188. }
  189. else if( _events[i].Start > t ) // since they are ordered, no point in continuing
  190. break;
  191. }
  192. return index;
  193. }
  194. public FEvent GetEventBefore( int t )
  195. {
  196. for( int i = 0; i != _events.Count; ++i )
  197. {
  198. if( _events[i].Start >= t )
  199. {
  200. if( i > 0 )
  201. {
  202. return _events[i-1];
  203. }
  204. return null;
  205. }
  206. }
  207. return _events.Count > 0 ? _events[_events.Count-1] : null;
  208. }
  209. public FEvent GetEventAfter( int t )
  210. {
  211. for( int i = _events.Count-1; i >= 0; --i )
  212. {
  213. if( _events[i].End <= t )
  214. {
  215. if( i < _events.Count-1 )
  216. {
  217. return _events[i+1];
  218. }
  219. return null;
  220. }
  221. }
  222. return _events.Count > 0 ? _events[0] : null;
  223. }
  224. public bool CanAdd( FEvent evt )
  225. {
  226. foreach( FEvent e in _events )
  227. {
  228. // abort search, events are ordered!
  229. if( e.Start > evt.End )
  230. {
  231. break;
  232. }
  233. if( evt.Collides( e ) )
  234. {
  235. return false;
  236. }
  237. }
  238. return true;
  239. }
  240. public bool CanAdd( FEvent evt, FrameRange newRange )
  241. {
  242. for( int i = 0; i != _events.Count; ++i )
  243. {
  244. if( _events[i].Start > newRange.End )
  245. break;
  246. if( _events[i] == evt )
  247. continue;
  248. if( _events[i].FrameRange.Collides( newRange ) )
  249. return false;
  250. }
  251. return true;
  252. }
  253. public bool CanAddAt( int t )
  254. {
  255. foreach( FEvent e in _events )
  256. {
  257. if( e.Start < t + 1 && e.End > t )
  258. {
  259. return false;
  260. }
  261. }
  262. return true;
  263. }
  264. public bool CanAddAt( int t, out int maxLength )
  265. {
  266. maxLength = 0;
  267. if( t < 0 )
  268. {
  269. return false;
  270. }
  271. for( int i = 0; i != _events.Count; ++i )
  272. {
  273. if( _events[i].Start > t )
  274. {
  275. maxLength = _events[i].Start - t;
  276. return true;
  277. }
  278. else if( _events[i].Start <= t && _events[i].End > t )
  279. {
  280. return false;
  281. }
  282. }
  283. if( t >= Sequence.Length - 1 )
  284. {
  285. return false;
  286. }
  287. maxLength = Sequence.Length - t;
  288. return true;
  289. }
  290. public void Add( FEvent evt )
  291. {
  292. evt.SetTrack( this );
  293. for( int i = 0, limit = _events.Count; i != limit; ++i )
  294. {
  295. if( _events[i].Start > evt.End )
  296. {
  297. _events.Insert(i, evt);
  298. UpdateEventIds();
  299. return;
  300. }
  301. }
  302. // didn't find a spot, add at the end
  303. evt.SetId( _events.Count );
  304. _events.Add( evt );
  305. if( !Sequence.IsStopped )
  306. Init();
  307. }
  308. public void Remove( FEvent evt )
  309. {
  310. _events.Remove( evt );
  311. evt.SetTrack( null );
  312. UpdateEventIds();
  313. }
  314. public virtual void UpdateEvents( int frame, float time )
  315. {
  316. int limit = _events.Count;
  317. if( limit == 0 )
  318. return;
  319. int increment = 1;
  320. if( !Sequence.IsPlayingForward )
  321. {
  322. limit = -1;
  323. increment = -1;
  324. }
  325. for( int i = _currentEvent; i != limit; i += increment )
  326. {
  327. if( frame < _events[i].Start )
  328. {
  329. if( _events[i].HasTriggered )
  330. _events[i].Stop();
  331. if( Sequence.IsPlayingForward )
  332. break;
  333. else
  334. _currentEvent = Mathf.Clamp( i - 1, 0, _events.Count-1 );
  335. }
  336. else if( frame >= _events[i].Start && frame <= _events[i].End )
  337. {
  338. if( _events[i].HasFinished && Sequence.FrameChanged )
  339. _events[i].Stop();
  340. if( !_events[i].HasFinished )
  341. _events[i].UpdateEvent( frame - _events[i].Start, time-_events[i].StartTime );
  342. }
  343. else //if( frame > _events[_currentEvent].End ) // is it finished
  344. {
  345. if( !_events[i].HasFinished && (_events[i].HasTriggered || _events[i].TriggerOnSkip) )
  346. {
  347. _events[i].UpdateEvent( _events[i].Length, _events[i].LengthTime );
  348. }
  349. if( Sequence.IsPlayingForward )
  350. _currentEvent = Mathf.Clamp( i + 1, 0, _events.Count-1);
  351. else
  352. break;
  353. }
  354. }
  355. }
  356. public virtual void UpdateEventsEditor( int frame, float time )
  357. {
  358. _currentEvent = Sequence.IsPlayingForward ? 0 : _events.Count-1;
  359. UpdateEvents( frame, time );
  360. }
  361. private FTrackCache _cache = null;
  362. /** @brief Returns current Cache. */
  363. public FTrackCache Cache { get { return _cache; } set { _cache = value; }}
  364. /** @brief Does it have cache? */
  365. public bool HasCache { get { return _cache != null; } }
  366. /** @brief Create Cache, if it needs it. */
  367. public virtual void CreateCache(){ }
  368. /** @brief Clear Cache, if it needs it. */
  369. public virtual void ClearCache(){ }
  370. /** @brief Does this track have everything it needs to create the cache? */
  371. public virtual bool CanCreateCache()
  372. {
  373. return true;
  374. }
  375. public void Rebuild()
  376. {
  377. Transform t = transform;
  378. _events.Clear();
  379. for( int i = 0; i != t.childCount; ++i )
  380. {
  381. FEvent evt = t.GetChild(i).GetComponent<FEvent>();
  382. if( evt )
  383. {
  384. evt.SetTrack( this );
  385. _events.Add( evt );
  386. }
  387. }
  388. UpdateEventIds();
  389. }
  390. public void UpdateEventIds()
  391. {
  392. _events.Sort( delegate( FEvent c1, FEvent c2 ) { return c1.FrameRange.Start.CompareTo( c2.FrameRange.Start ); } );
  393. for(int i = 0, limit = _events.Count; i != limit; ++i )
  394. {
  395. _events[i].SetId( i );
  396. }
  397. }
  398. public FrameRange GetValidRange( FEvent evt )
  399. {
  400. int index = 0;
  401. for( ; index < _events.Count; ++index )
  402. {
  403. if( _events[index] == evt )
  404. {
  405. break;
  406. }
  407. }
  408. FrameRange range = new FrameRange( 0, Sequence.Length );
  409. if( index > 0 )
  410. {
  411. range.Start = _events[index - 1].End;
  412. }
  413. if( index < _events.Count - 1 )
  414. {
  415. range.End = _events[index + 1].Start;
  416. }
  417. if( range.Length > evt.GetMaxLength() )
  418. range.Length = evt.GetMaxLength();
  419. return range;
  420. }
  421. }
  422. }