AnimancerLayer.cs 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using UnityEngine;
  7. using UnityEngine.Animations;
  8. using UnityEngine.Playables;
  9. namespace Animancer
  10. {
  11. /// <summary>
  12. /// A layer on which animations can play with their states managed independantly of other layers while blending the
  13. /// output with those layers.
  14. /// </summary>
  15. ///
  16. /// <remarks>
  17. /// This class can be used as a custom yield instruction to wait until all animations finish playing.
  18. /// <para></para>
  19. /// <strong>Documentation:</strong>
  20. /// <see href="https://kybernetik.com.au/animancer/docs/manual/blending/layers">
  21. /// Layers</see>
  22. /// </remarks>
  23. /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerLayer
  24. ///
  25. public class AnimancerLayer : AnimancerNode,
  26. IAnimationClipCollection,
  27. ICopyable<AnimancerLayer>
  28. {
  29. /************************************************************************************************************************/
  30. #region Fields and Properties
  31. /************************************************************************************************************************/
  32. /// <summary>[Internal] Creates a new <see cref="AnimancerLayer"/>.</summary>
  33. protected internal AnimancerLayer(AnimancerGraph graph, int index)
  34. {
  35. Graph = graph;
  36. Parent = graph;
  37. Index = index;
  38. if (ApplyParentAnimatorIK)
  39. _ApplyAnimatorIK = graph.ApplyAnimatorIK;
  40. if (ApplyParentFootIK)
  41. _ApplyFootIK = graph.ApplyFootIK;
  42. CreatePlayable();
  43. ActiveStatesInternal = new(new(Graph, Playable));
  44. }
  45. /************************************************************************************************************************/
  46. /// <summary>Creates and assigns the <see cref="AnimationMixerPlayable"/> managed by this layer.</summary>
  47. protected override void CreatePlayable(out Playable playable)
  48. => playable = AnimationMixerPlayable.Create(Graph._PlayableGraph, _Capacity);
  49. /************************************************************************************************************************/
  50. /// <summary>A layer is its own root.</summary>
  51. public override AnimancerLayer Layer
  52. => this;
  53. /// <inheritdoc/>
  54. public override bool KeepChildrenConnected
  55. => Graph.KeepChildrenConnected;
  56. /************************************************************************************************************************/
  57. /// <summary>The animation states connected to this layer.</summary>
  58. private readonly List<AnimancerState>
  59. States = new();
  60. /************************************************************************************************************************/
  61. private readonly AnimancerState.ActiveList
  62. ActiveStatesInternal;
  63. /// <summary>The states connected to this layer which are <see cref="AnimancerState.IsActive"/>.</summary>
  64. public IReadOnlyIndexedList<AnimancerState> ActiveStates
  65. => ActiveStatesInternal;
  66. /************************************************************************************************************************/
  67. /// <summary>The default <see cref="Capacity"/> is 8 unless changed.</summary>
  68. /// <remarks>
  69. /// This value only affects newly created layers.
  70. /// <para></para>
  71. /// This value should be set high enough to include all states a layer is likely to have. It's generally not
  72. /// particularly important though since expanding the capacity is fairly fast.
  73. /// </remarks>
  74. public static int DefaultCapacity = 8;
  75. private int _Capacity = DefaultCapacity;
  76. /// <summary>
  77. /// The number of states that can be connected to this layer before its <see cref="Playable"/> needs to
  78. /// allocate more inputs.
  79. /// </summary>
  80. /// <remarks>Starts at the <see cref="DefaultCapacity"/> and doubles each time it needs to expand.</remarks>
  81. /// <exception cref="ArgumentException">This value cannot be set lower than the <see cref="ChildCount"/>.</exception>
  82. public int Capacity
  83. {
  84. get => _Capacity;
  85. set
  86. {
  87. if (value < ChildCount)
  88. throw new ArgumentException(
  89. $"{nameof(Capacity)} ({value}) cannot be smaller than {nameof(ChildCount)} ({ChildCount}).");
  90. _Capacity = value;
  91. _Playable.SetInputCount(value);
  92. }
  93. }
  94. /************************************************************************************************************************/
  95. private AnimancerState _CurrentState;
  96. /// <summary>The state of the animation currently being played.</summary>
  97. /// <remarks>
  98. /// Specifically, this is the state that was most recently started using any of the Play or CrossFade methods
  99. /// on this layer. States controlled individually via methods in the <see cref="AnimancerState"/> itself will
  100. /// not register in this property.
  101. /// <para></para>
  102. /// Each time this property changes, the <see cref="CommandCount"/> is incremented.
  103. /// </remarks>
  104. public AnimancerState CurrentState
  105. {
  106. get => _CurrentState;
  107. private set
  108. {
  109. _CurrentState = value;
  110. CommandCount++;
  111. }
  112. }
  113. /// <summary>
  114. /// The number of times the <see cref="CurrentState"/> has changed. By storing this value and later comparing
  115. /// the stored value to the current value, you can determine whether the state has been changed since then,
  116. /// even it has changed back to the same state.
  117. /// </summary>
  118. public int CommandCount { get; private set; }
  119. #if UNITY_EDITOR
  120. /// <summary>[Editor-Only] [Internal] Increases the <see cref="CommandCount"/> by 1.</summary>
  121. internal void IncrementCommandCount() => CommandCount++;
  122. #endif
  123. /************************************************************************************************************************/
  124. /// <summary>[Pro-Only]
  125. /// Determines whether this layer is set to additive blending. Otherwise it will override any earlier layers.
  126. /// </summary>
  127. public bool IsAdditive
  128. {
  129. get => Graph.Layers.IsAdditive(Index);
  130. set => Graph.Layers.SetAdditive(Index, value);
  131. }
  132. /************************************************************************************************************************/
  133. /// <summary>[Internal] [Pro-Only] The mask that determines which bones this layer will affect.</summary>
  134. internal AvatarMask _Mask;
  135. /// <summary>[Pro-Only] The mask that determines which bones this layer will affect.</summary>
  136. /// <remarks>
  137. /// Don't assign the same mask repeatedly unless you have modified it.
  138. /// This property doesn't check if the mask is the same
  139. /// so repeatedly assigning the same thing will simply waste performance.
  140. /// </remarks>
  141. public AvatarMask Mask
  142. {
  143. get => _Mask;
  144. set => Graph.Layers.SetMask(Index, value);
  145. }
  146. /************************************************************************************************************************/
  147. /// <summary>
  148. /// The average velocity of the root motion of all currently playing animations, taking their current
  149. /// <see cref="AnimancerNode.Weight"/> into account.
  150. /// </summary>
  151. public Vector3 AverageVelocity
  152. {
  153. get
  154. {
  155. var velocity = default(Vector3);
  156. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  157. {
  158. var state = ActiveStatesInternal[i];
  159. velocity += state.AverageVelocity * state.Weight;
  160. }
  161. return velocity;
  162. }
  163. }
  164. /************************************************************************************************************************/
  165. #endregion
  166. /************************************************************************************************************************/
  167. #region Child States
  168. /************************************************************************************************************************/
  169. /// <inheritdoc/>
  170. public override int ChildCount
  171. => States.Count;
  172. /// <summary>Returns the state connected to the specified `index` as a child of this layer.</summary>
  173. /// <remarks>This method is identical to <see cref="this[int]"/>.</remarks>
  174. public override AnimancerState GetChild(int index)
  175. => States[index];
  176. /// <summary>Returns the state connected to the specified `index` as a child of this layer.</summary>
  177. /// <remarks>This indexer is identical to <see cref="GetChild(int)"/>.</remarks>
  178. public AnimancerState this[int index]
  179. => States[index];
  180. /************************************************************************************************************************/
  181. /// <summary>Connects the `state` to this layer at its <see cref="AnimancerNode.Index"/>.</summary>
  182. protected internal override void OnAddChild(AnimancerState state)
  183. {
  184. Validate.AssertGraph(state, Graph);
  185. var index = States.Count;
  186. state.Index = index;
  187. States.Add(state);
  188. if (_Capacity <= index)
  189. {
  190. _Capacity *= 2;
  191. _Playable.SetInputCount(_Capacity);
  192. }
  193. // If the state should be active, deactivate and properly add it to the active list.
  194. if (state.TryDeactivate())
  195. ActiveStatesInternal.Add(state);
  196. if (Graph.KeepChildrenConnected)
  197. ConnectChildUnsafe(state.Index, state);
  198. }
  199. /************************************************************************************************************************/
  200. /// <summary>Disconnects the `state` from this layer at its <see cref="AnimancerNode.Index"/>.</summary>
  201. protected internal override void OnRemoveChild(AnimancerState state)
  202. {
  203. var index = state.Index;
  204. Validate.AssertCanRemoveChild(state, States, States.Count);
  205. if (ActiveStatesInternal.Remove(state))
  206. state._ActiveIndex = 0;
  207. if (Graph._PlayableGraph.IsValid() &&
  208. _Playable.GetInput(index).IsValid())
  209. Graph._PlayableGraph.Disconnect(_Playable, index);
  210. // Swap the last state into the place of the one that was just removed.
  211. var last = States.Count - 1;
  212. if (index < last)
  213. {
  214. state = States[last];
  215. DisconnectChildSafe(last);
  216. States[index] = state;
  217. state.Index = index;
  218. if (state.IsActive || Graph.KeepChildrenConnected)
  219. ConnectChildUnsafe(index, state);
  220. }
  221. States.RemoveAt(last);
  222. }
  223. /************************************************************************************************************************/
  224. /// <inheritdoc/>
  225. protected internal override void ApplyChildActive(AnimancerState state, bool setActive)
  226. {
  227. if (setActive)
  228. ActiveStatesInternal.Add(state);
  229. else
  230. ActiveStatesInternal.Remove(state);
  231. }
  232. /************************************************************************************************************************/
  233. /// <summary>[Internal] Connects all states in this layer.</summary>
  234. internal void ConnectAllStates()
  235. {
  236. for (int i = ChildCount - 1; i >= 0; i--)
  237. if (!_Playable.GetInput(i).IsValid())
  238. ConnectChildUnsafe(i, States[i]);
  239. }
  240. /// <summary>[Internal] Disconnects all states which are not <see cref="AnimancerState.IsActive"/>.</summary>
  241. internal void DisconnectInactiveStates()
  242. {
  243. for (int i = ChildCount - 1; i >= 0; i--)
  244. if (!States[i].IsActive)
  245. DisconnectChildSafe(i);
  246. }
  247. /************************************************************************************************************************/
  248. /// <summary>[Internal]
  249. /// Checks if any events should be invoked on any of the <see cref="ActiveStates"/>.
  250. /// </summary>
  251. internal void UpdateEvents()
  252. {
  253. if (Weight <= 0)
  254. return;
  255. if (FadeGroup != null &&
  256. FadeGroup.GetTargetWeight(this) == 0 &&
  257. !AnimancerState.RaiseEventsDuringFadeOut)
  258. return;
  259. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  260. ActiveStatesInternal[i].UpdateEvents();
  261. }
  262. /************************************************************************************************************************/
  263. /// <summary>[Internal] Cancels the current <see cref="FadeGroup"/> so it can be object pooled.</summary>
  264. internal void OnGraphDestroyed()
  265. {
  266. CurrentState?.FadeGroup?.Cancel();
  267. }
  268. /************************************************************************************************************************/
  269. /// <inheritdoc/>
  270. public override FastEnumerator<AnimancerState> GetEnumerator()
  271. => new(States);
  272. /************************************************************************************************************************/
  273. /// <inheritdoc/>
  274. public sealed override void CopyFrom(AnimancerNode copyFrom, CloneContext context)
  275. => this.CopyFromBase(copyFrom, context);
  276. /// <summary>Copies the details of `copyFrom` into this layer.</summary>
  277. /// <remarks>Call <see cref="CopyStatesFrom"/> (as well) if you want to copy the states.</remarks>
  278. public virtual void CopyFrom(AnimancerLayer copyFrom, CloneContext context)
  279. {
  280. base.CopyFrom(copyFrom, context);
  281. IsAdditive = copyFrom.IsAdditive;
  282. Mask = copyFrom.Mask;
  283. }
  284. /************************************************************************************************************************/
  285. /// <summary>Copies the details of all states in `copyFrom` to their equivalent states in this layer.</summary>
  286. /// <remarks>
  287. /// Any states which do not have an equivalent in this layer will be cloned into this layer.
  288. /// <para></para>
  289. /// Call <see cref="CopyFrom(AnimancerLayer, CloneContext)"/> (as well)
  290. /// if you want to copy the details of the layer itself.
  291. /// </remarks>
  292. public void CopyStatesFrom(AnimancerLayer copyFrom, CloneContext context, bool includeInactive = false)
  293. {
  294. if (copyFrom == this)
  295. return;
  296. Debug.Assert(context.TryGetValue(copyFrom.Graph, out var thisGraph));
  297. Debug.Assert(thisGraph == Graph);
  298. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  299. ActiveStatesInternal[i].Stop();
  300. CommandCount++;
  301. if (!includeInactive && Weight == 0)
  302. return;
  303. IReadOnlyList<AnimancerState> copyFromStates = includeInactive
  304. ? copyFrom.States
  305. : copyFrom.ActiveStatesInternal;
  306. var stateCount = copyFromStates.Count;
  307. for (int i = 0; i < stateCount; i++)
  308. {
  309. var state = copyFromStates[i];
  310. // If the clone already exists, copy over the state details.
  311. if (context.TryGetClone(state, out var clone))
  312. clone.CopyFrom(state, context);
  313. else// Otherwise, create a new clone.
  314. clone = context.Clone(state);
  315. if (clone.Parent != this)
  316. clone.SetParent(this);
  317. if (copyFrom.CurrentState == state)
  318. CurrentState = clone;
  319. // This should prevent the clones from being one frame behind after the next animation update
  320. // but it seems to only work for some states and not others.
  321. // clone.Time += clone.EffectiveSpeed * Time.deltaTime;
  322. }
  323. }
  324. /************************************************************************************************************************/
  325. #endregion
  326. /************************************************************************************************************************/
  327. #region Create State
  328. /************************************************************************************************************************/
  329. /// <summary>Creates and returns a new <see cref="ClipState"/> to play the `clip`.</summary>
  330. /// <remarks>
  331. /// <see cref="AnimancerGraph.GetKey"/> is used to determine the <see cref="AnimancerState.Key"/>.
  332. /// </remarks>
  333. public ClipState CreateState(AnimationClip clip)
  334. => CreateState(Graph.GetKey(clip), clip);
  335. /// <summary>
  336. /// Creates and returns a new <see cref="ClipState"/> to play the `clip` and registers it with the `key`.
  337. /// </summary>
  338. public ClipState CreateState(object key, AnimationClip clip)
  339. {
  340. var state = new ClipState(clip)
  341. {
  342. _Key = key,
  343. };
  344. state.SetParent(this);
  345. return state;
  346. }
  347. /************************************************************************************************************************/
  348. /// <summary>Returns a state registered with the `key` and attached to this layer or null if none exist.</summary>
  349. /// <exception cref="ArgumentNullException">The `key` is null.</exception>
  350. /// <remarks>
  351. /// If a state is registered with the `key` but on a different layer, this method will use that state as the
  352. /// key and try to look up another state with it. This allows it to associate multiple states with the same
  353. /// original key.
  354. /// </remarks>
  355. public AnimancerState GetState(ref object key)
  356. {
  357. if (key == null)
  358. throw new ArgumentNullException(nameof(key));
  359. // Check through any states backwards in the key chain.
  360. var earlierKey = key;
  361. while (earlierKey is AnimancerState keyState)
  362. {
  363. if (keyState.Parent == this)// If the state is on this layer, return it.
  364. {
  365. key = keyState.Key;
  366. return keyState;
  367. }
  368. else if (keyState.Parent == null)// If the state is on no layer, attach it to this one and return it.
  369. {
  370. key = keyState.Key;
  371. keyState.SetParent(this);
  372. return keyState;
  373. }
  374. else// Otherwise the state is on a different layer.
  375. {
  376. earlierKey = keyState.Key;
  377. }
  378. }
  379. while (true)
  380. {
  381. // If no state is registered with the key, return null.
  382. if (!Graph.States.TryGet(key, out var state))
  383. return null;
  384. if (state.Parent == this)// If the state is on this layer, return it.
  385. {
  386. return state;
  387. }
  388. else if (state.Parent == null)// If the state is on no layer, attach it to this one and return it.
  389. {
  390. state.SetParent(this);
  391. return state;
  392. }
  393. else// Otherwise the state is on a different layer.
  394. {
  395. // Use it as the key and try to look up the next state in a chain.
  396. key = state;
  397. }
  398. }
  399. }
  400. /************************************************************************************************************************/
  401. /// <summary>
  402. /// Calls <see cref="GetOrCreateState(AnimationClip, bool)"/> for each of the specified clips.
  403. /// <para></para>
  404. /// If you only want to create a single state, use <see cref="CreateState(AnimationClip)"/>.
  405. /// </summary>
  406. public void CreateIfNew(AnimationClip clip0, AnimationClip clip1)
  407. {
  408. GetOrCreateState(clip0);
  409. GetOrCreateState(clip1);
  410. }
  411. /// <summary>
  412. /// Calls <see cref="GetOrCreateState(AnimationClip, bool)"/> for each of the specified clips.
  413. /// <para></para>
  414. /// If you only want to create a single state, use <see cref="CreateState(AnimationClip)"/>.
  415. /// </summary>
  416. public void CreateIfNew(AnimationClip clip0, AnimationClip clip1, AnimationClip clip2)
  417. {
  418. GetOrCreateState(clip0);
  419. GetOrCreateState(clip1);
  420. GetOrCreateState(clip2);
  421. }
  422. /// <summary>
  423. /// Calls <see cref="GetOrCreateState(AnimationClip, bool)"/> for each of the specified clips.
  424. /// <para></para>
  425. /// If you only want to create a single state, use <see cref="CreateState(AnimationClip)"/>.
  426. /// </summary>
  427. public void CreateIfNew(AnimationClip clip0, AnimationClip clip1, AnimationClip clip2, AnimationClip clip3)
  428. {
  429. GetOrCreateState(clip0);
  430. GetOrCreateState(clip1);
  431. GetOrCreateState(clip2);
  432. GetOrCreateState(clip3);
  433. }
  434. /// <summary>
  435. /// Calls <see cref="GetOrCreateState(AnimationClip, bool)"/> for each of the specified clips.
  436. /// <para></para>
  437. /// If you only want to create a single state, use <see cref="CreateState(AnimationClip)"/>.
  438. /// </summary>
  439. public void CreateIfNew(params AnimationClip[] clips)
  440. {
  441. if (clips == null)
  442. return;
  443. var count = clips.Length;
  444. for (int i = 0; i < count; i++)
  445. {
  446. var clip = clips[i];
  447. if (clip != null)
  448. GetOrCreateState(clip);
  449. }
  450. }
  451. /************************************************************************************************************************/
  452. /// <summary>
  453. /// Calls <see cref="AnimancerGraph.GetKey"/> and returns the state registered with that key or
  454. /// creates one if it doesn't exist.
  455. /// <para></para>
  456. /// If the state already exists but has the wrong <see cref="AnimancerState.Clip"/>, the `allowSetClip`
  457. /// parameter determines what will happen. False causes it to throw an <see cref="ArgumentException"/> while
  458. /// true allows it to change the <see cref="AnimancerState.Clip"/>. Note that the change is somewhat costly to
  459. /// performance to use with caution.
  460. /// </summary>
  461. /// <exception cref="ArgumentException"/>
  462. public AnimancerState GetOrCreateState(AnimationClip clip, bool allowSetClip = false)
  463. {
  464. return GetOrCreateState(Graph.GetKey(clip), clip, allowSetClip);
  465. }
  466. /// <summary>
  467. /// Returns the state registered with the <see cref="IHasKey.Key"/> if there is one. Otherwise
  468. /// this method uses <see cref="ITransition.CreateState"/> to create a new one and registers it with
  469. /// that key before returning it.
  470. /// </summary>
  471. public AnimancerState GetOrCreateState(ITransition transition)
  472. {
  473. var key = transition.Key;
  474. var state = GetState(ref key);
  475. if (state == null)
  476. {
  477. state = transition.CreateState();
  478. state._Key = key;
  479. state.SetParent(this);
  480. }
  481. return state;
  482. }
  483. /// <summary>Returns the state registered with the `key` or creates one if it doesn't exist.</summary>
  484. /// <exception cref="ArgumentException"/>
  485. /// <exception cref="ArgumentNullException">The `key` is null.</exception>
  486. /// <remarks>
  487. /// If the state already exists but has the wrong <see cref="AnimancerState.Clip"/>, the `allowSetClip`
  488. /// parameter determines what will happen. False causes it to throw an <see cref="ArgumentException"/> while
  489. /// true allows it to change the <see cref="AnimancerState.Clip"/>. Note that the change is somewhat costly to
  490. /// performance to use with caution.
  491. /// <para></para>
  492. /// See also: <see cref="AnimancerStateDictionary.GetOrCreate(object, AnimationClip, bool)"/>.
  493. /// </remarks>
  494. public AnimancerState GetOrCreateState(object key, AnimationClip clip, bool allowSetClip = false)
  495. {
  496. var state = GetState(ref key);
  497. if (state == null)
  498. return CreateState(key, clip);
  499. // If a state exists but has the wrong clip, either change it or complain.
  500. if (!ReferenceEquals(state.Clip, clip))
  501. {
  502. if (allowSetClip)
  503. {
  504. state.Clip = clip;
  505. }
  506. else
  507. {
  508. throw new ArgumentException(
  509. AnimancerStateDictionary.GetClipMismatchError(key, state.Clip, clip));
  510. }
  511. }
  512. return state;
  513. }
  514. /// <summary>Returns the `state` if it's a child of this layer. Otherwise makes a clone of it.</summary>
  515. public AnimancerState GetOrCreateState(AnimancerState state)
  516. {
  517. var parent = state.Parent;
  518. if (parent == this)
  519. return state;
  520. if (parent == null)
  521. {
  522. state.SetParent(this);
  523. return state;
  524. }
  525. var key = state.Key;
  526. key ??= state;
  527. var stateOnThisLayer = GetState(ref key);
  528. if (stateOnThisLayer == null)
  529. {
  530. stateOnThisLayer = state.Clone();
  531. stateOnThisLayer._Weight = 0;
  532. stateOnThisLayer.SetParent(this);
  533. stateOnThisLayer.Key = key;
  534. }
  535. return stateOnThisLayer;
  536. }
  537. /************************************************************************************************************************/
  538. /// <summary>
  539. /// The maximum <see cref="AnimancerNode.Weight"/> that <see cref="GetOrCreateWeightlessState"/>
  540. /// will treat as being weightless. Default = 0.1.
  541. /// </summary>
  542. /// <remarks>This allows states with very small weights to be reused instead of needing to create new ones.</remarks>
  543. public static float WeightlessThreshold { get; set; } = 0.1f;
  544. /// <summary>
  545. /// The maximum number of duplicate states that can be created for a single clip when trying to get a
  546. /// weightless state. Exceeding this limit will cause it to just use the state with the lowest weight.
  547. /// Default = 3.
  548. /// </summary>
  549. public static int MaxCloneCount { get; set; } = 3;
  550. /// <summary>
  551. /// If the `state`'s <see cref="AnimancerNode.Weight"/> is not currently low,
  552. /// this method finds or creates a copy of it which is low.
  553. /// The returned <see cref="AnimancerState.Time"/> is also set to 0.
  554. /// </summary>
  555. /// <remarks>
  556. /// If this method would exceed the <see cref="MaxCloneCount"/>, it returns the clone with the lowest weight.
  557. /// <para></para>
  558. /// "Low" weight is defined as less than or equal to the <see cref="WeightlessThreshold"/>.
  559. /// <para></para>
  560. /// The <see href="https://kybernetik.com.au/animancer/docs/manual/blending/fading/modes">Fade Modes</see> page
  561. /// explains why clones are created.
  562. /// </remarks>
  563. public AnimancerState GetOrCreateWeightlessState(AnimancerState state)
  564. {
  565. if (state.Parent == null)
  566. {
  567. state.Weight = 0;
  568. goto GotState;
  569. }
  570. if (state.Parent == this &&
  571. state.Weight <= WeightlessThreshold)
  572. goto GotState;
  573. float lowestWeight = float.PositiveInfinity;
  574. AnimancerState lowestWeightState = null;
  575. int cloneCount = 0;
  576. // Use any earlier state that is weightless.
  577. var keyState = state;
  578. while (true)
  579. {
  580. keyState = keyState.Key as AnimancerState;
  581. if (keyState == null)
  582. {
  583. break;
  584. }
  585. else if (keyState.Parent == this)
  586. {
  587. if (keyState.Weight <= WeightlessThreshold)
  588. {
  589. state = keyState;
  590. goto GotState;
  591. }
  592. else if (lowestWeight > keyState.Weight)
  593. {
  594. lowestWeight = keyState.Weight;
  595. lowestWeightState = keyState;
  596. }
  597. }
  598. else if (keyState.Parent == null)
  599. {
  600. keyState.SetParent(this);
  601. goto GotState;
  602. }
  603. cloneCount++;
  604. }
  605. if (state.Parent == this)
  606. {
  607. lowestWeight = state.Weight;
  608. lowestWeightState = state;
  609. }
  610. keyState = state;
  611. // If that state is not at low weight,
  612. // get or create another state registered using the previous state as a key.
  613. // Keep going through states in this manner until you find one at low weight.
  614. while (true)
  615. {
  616. var key = (object)state;
  617. if (!Graph.States.TryGet(key, out state))
  618. {
  619. if (cloneCount >= MaxCloneCount && lowestWeightState != null)
  620. {
  621. state = lowestWeightState;
  622. goto GotState;
  623. }
  624. else
  625. {
  626. #if UNITY_ASSERTIONS
  627. var cloneTimer = OptionalWarning.CloneComplexState.IsEnabled() && keyState is not ClipState
  628. ? SimpleTimer.Start()
  629. : SimpleTimer.Default;
  630. #endif
  631. state = keyState.Clone();
  632. state.SetDebugName($"[{cloneCount + 1}] {keyState}");
  633. state.Weight = 0;
  634. state.Key = key;
  635. if (state.Parent != this)
  636. state.SetParent(this);
  637. #if UNITY_ASSERTIONS
  638. if (cloneTimer.Count() > 0)
  639. {
  640. var milliseconds = cloneTimer.TotalTimeSeconds * 1000;
  641. OptionalWarning.CloneComplexState.Log(
  642. $"A {keyState.GetType().Name} was cloned in {milliseconds} milliseconds." +
  643. $" This performance cost may be notable and complex states generally have parameters" +
  644. $" that need to be controlled which may result in undesired behaviour if your scripts" +
  645. $" are only expecting to have one state to control so you may wish to avoid cloning." +
  646. $"\n\nThe Fade Modes page explains why these clones are created:" +
  647. $" {Strings.DocsURLs.FadeModes}",
  648. Graph?.Component);
  649. }
  650. #endif
  651. goto GotState;
  652. }
  653. }
  654. else if (state.Parent == this)
  655. {
  656. if (state.Weight <= WeightlessThreshold)
  657. {
  658. goto GotState;
  659. }
  660. else if (lowestWeight > state.Weight)
  661. {
  662. lowestWeight = state.Weight;
  663. lowestWeightState = state;
  664. }
  665. }
  666. else if (state.Parent == null)
  667. {
  668. state.SetParent(this);
  669. goto GotState;
  670. }
  671. cloneCount++;
  672. }
  673. GotState:
  674. state.TimeD = 0;
  675. return state;
  676. }
  677. /************************************************************************************************************************/
  678. /// <summary>Destroys all states connected to this layer.</summary>
  679. /// <remarks>This operation cannot be undone.</remarks>
  680. public void DestroyStates()
  681. {
  682. CurrentState?.FadeGroup?.Cancel();
  683. for (int i = States.Count - 1; i >= 0; i--)
  684. States[i].Destroy();
  685. States.Clear();
  686. CurrentState = null;
  687. }
  688. /************************************************************************************************************************/
  689. #endregion
  690. /************************************************************************************************************************/
  691. #region Play Management
  692. /************************************************************************************************************************/
  693. /// <inheritdoc/>
  694. protected internal override void OnStartFade()
  695. {
  696. CommandCount++;
  697. }
  698. /************************************************************************************************************************/
  699. // Play Immediately.
  700. /************************************************************************************************************************/
  701. /// <summary>Stops all other animations on this layer, plays the `clip`, and returns its state.</summary>
  702. /// <remarks>
  703. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  704. /// To restart it from the beginning you can use <c>...Play(clip).Time = 0;</c>.
  705. /// <para></para>
  706. /// This method is safe to call repeatedly without checking whether the `clip` was already playing.
  707. /// </remarks>
  708. public AnimancerState Play(
  709. AnimationClip clip)
  710. => Play(GetOrCreateState(clip));
  711. /// <summary>Stops all other animations on the same layer, plays the `state`, and returns it.</summary>
  712. /// <remarks>
  713. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  714. /// To restart it from the beginning you can use <c>...Play(state).Time = 0;</c>.
  715. /// <para></para>
  716. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  717. /// </remarks>
  718. /// <exception cref="InvalidOperationException">
  719. /// The <see cref="AnimancerNodeBase.Parent"/> is another state (likely a <see cref="ManualMixerState"/>).
  720. /// It must be either null or a layer.
  721. /// </exception>
  722. public AnimancerState Play(
  723. AnimancerState state)
  724. {
  725. #if UNITY_ASSERTIONS
  726. AnimancerEvent.AssertEventPlayMismatch(Graph);
  727. AnimancerState.AssertNotExpectingFade(state);
  728. if (state.Parent is AnimancerState)
  729. throw new InvalidOperationException(
  730. $"A layer can't Play a state which is the child of another state." +
  731. $"\n• State: {state}" +
  732. $"\n• Parent: {state.Parent}" +
  733. $"\n• Layer: {this}");
  734. #endif
  735. // If the layer is at 0 weight and not fading, set it to 1.
  736. if (Weight == 0 && FadeGroup == null)
  737. Weight = 1;
  738. CurrentState?.FadeGroup?.Cancel();
  739. state = GetOrCreateState(state);
  740. CurrentState = state;
  741. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  742. {
  743. var otherState = ActiveStatesInternal[i];
  744. if (otherState != state)
  745. otherState.Stop();
  746. }
  747. // Similar to state.Play but more optimized.
  748. state.SetIsPlaying(true);
  749. state._Weight = 1;
  750. if (!state.IsActive)
  751. ActiveStatesInternal.Add(state);
  752. _Playable.ApplyChildWeight(state);
  753. return state;
  754. }
  755. /************************************************************************************************************************/
  756. // Cross Fade.
  757. /************************************************************************************************************************/
  758. /// <summary>
  759. /// Starts fading in the `clip` over the course of the `fadeDuration`
  760. /// while fading out all others in the same layer. Returns its state.
  761. /// </summary>
  762. /// <remarks>
  763. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`,
  764. /// this method will allow it to complete the existing fade rather than starting a slower one.
  765. /// <para></para>
  766. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>,
  767. /// this method will fade in the layer itself and simply <see cref="AnimancerState.Play"/> the `state`.
  768. /// <para></para>
  769. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  770. /// <para></para>
  771. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  772. /// </remarks>
  773. public AnimancerState Play(
  774. AnimationClip clip,
  775. float fadeDuration,
  776. FadeMode mode = default)
  777. {
  778. var key = Graph.GetKey(clip);
  779. var state = GetOrCreateState(key, clip);
  780. if (Graph.Transitions != null)
  781. fadeDuration = Graph.Transitions.GetFadeDuration(this, key, fadeDuration);
  782. return Play(state, fadeDuration, mode);
  783. }
  784. /// <summary>
  785. /// Starts fading in the `state` over the course of the `fadeDuration` while fading out all others in this
  786. /// layer. Returns the `state`.
  787. /// </summary>
  788. /// <remarks>
  789. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`, this
  790. /// method will allow it to complete the existing fade rather than starting a slower one.
  791. /// <para></para>
  792. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will fade in the layer itself
  793. /// and simply <see cref="AnimancerState.Play"/> the `state`.
  794. /// <para></para>
  795. /// This method is safe to call repeatedly without checking whether the `state` was already playing.
  796. /// <para></para>
  797. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  798. /// </remarks>
  799. public AnimancerState Play(
  800. AnimancerState state,
  801. float fadeDuration,
  802. FadeMode mode = default)
  803. {
  804. // Skip the fade if:
  805. if (fadeDuration <= 0 ||// There is no duration.
  806. (Graph.SkipFirstFade && Index == 0 && Weight == 0))// Or this is Layer 0 and it has no weight.
  807. {
  808. Weight = 1;
  809. AnimancerState.SkipNextExpectFade();
  810. state = Play(state);
  811. if (mode == FadeMode.FromStart ||
  812. mode == FadeMode.NormalizedFromStart)
  813. state.TimeD = 0;
  814. return state;
  815. }
  816. AnimancerEvent.AssertEventPlayMismatch(Graph);
  817. EvaluateFadeMode(mode, ref state, fadeDuration, out var stateFadeSpeed, out var layerFadeDuration);
  818. StartFade(1, layerFadeDuration);
  819. // If the layer has to fade in, play the state immediately.
  820. if (Weight == 0)
  821. {
  822. AnimancerState.SkipNextExpectFade();
  823. return Play(state);
  824. }
  825. state = GetOrCreateState(state);
  826. CurrentState = state;
  827. // If the state is already playing or will finish fading in faster than this new fade,
  828. // continue the existing fade.
  829. if (IsAlreadyFadingIn(state, fadeDuration))
  830. {
  831. CommandCount++;// Still pretend the fade was restarted.
  832. }
  833. else// Otherwise fade in the target state and fade out all others.
  834. {
  835. state.IsPlaying = true;
  836. var fade = GetFade();
  837. fade.SetNodes(this, state, ActiveStatesInternal, Graph.KeepChildrenConnected);
  838. fade.StartFade(1, stateFadeSpeed);
  839. }
  840. return state;
  841. }
  842. /************************************************************************************************************************/
  843. /// <summary>Is the `state` already faded in or fading in with shorter than the given `fadeDuration`?</summary>
  844. private static bool IsAlreadyFadingIn(
  845. AnimancerState state,
  846. float fadeDuration)
  847. {
  848. if (!state.IsPlaying)
  849. return false;
  850. var fadeGroup = state.FadeGroup;
  851. if (fadeGroup == null)
  852. return state.Weight == 1;
  853. return
  854. fadeGroup.FadeIn.Node == state &&
  855. fadeGroup.TargetWeight == 1 &&
  856. fadeGroup.RemainingFadeDuration <= fadeDuration;
  857. }
  858. /************************************************************************************************************************/
  859. /// <summary>Clears and reuses the existing fade if there is one. Otherwise gets one from the object pool.</summary>
  860. private FadeGroup GetFade()
  861. {
  862. if (CurrentState != null)
  863. {
  864. var fade = CurrentState.FadeGroup;
  865. if (fade != null)
  866. {
  867. fade.FadeOutInternal.Clear();
  868. fade.Easing = null;
  869. return fade;
  870. }
  871. }
  872. return FadeGroup.Pool.Instance.Acquire();
  873. }
  874. /************************************************************************************************************************/
  875. // Transition.
  876. /************************************************************************************************************************/
  877. /// <summary>
  878. /// Creates a state for the `transition` if it didn't already exist, then calls
  879. /// <see cref="Play(AnimancerState)"/> or <see cref="Play(AnimancerState, float, FadeMode)"/>
  880. /// depending on the <see cref="ITransition.FadeDuration"/>.
  881. /// </summary>
  882. /// <remarks>
  883. /// This method is safe to call repeatedly without checking whether the `transition` was already playing.
  884. /// </remarks>
  885. public AnimancerState Play(
  886. ITransition transition)
  887. => Graph.Transitions != null
  888. ? Graph.Transitions.Play(this, transition)
  889. : Play(transition, transition.FadeDuration, transition.FadeMode);
  890. /// <summary>
  891. /// Creates a state for the `transition` if it didn't already exist, then calls
  892. /// <see cref="Play(AnimancerState)"/> or <see cref="Play(AnimancerState, float, FadeMode)"/>
  893. /// depending on the <see cref="ITransition.FadeDuration"/>.
  894. /// </summary>
  895. /// <remarks>
  896. /// This method is safe to call repeatedly without checking whether the `transition` was already playing.
  897. /// </remarks>
  898. public AnimancerState Play(
  899. ITransition transition,
  900. float fadeDuration,
  901. FadeMode mode = default)
  902. {
  903. var state = GetOrCreateState(transition);
  904. state = Play(state, fadeDuration, mode);
  905. transition.Apply(state);
  906. return state;
  907. }
  908. /************************************************************************************************************************/
  909. // Try Play.
  910. /************************************************************************************************************************/
  911. /// <summary>
  912. /// Stops all other animations on this layer,
  913. /// plays the animation registered with the `key`,
  914. /// and returns the animation's state.
  915. /// </summary>
  916. /// <remarks>
  917. /// If no state is registered with the `key`, this method does nothing and returns null.
  918. /// <para></para>
  919. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  920. /// To restart it from the beginning you can simply set the returned state's time to 0.
  921. /// <para></para>
  922. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  923. /// </remarks>
  924. public AnimancerState TryPlay(
  925. object key)
  926. {
  927. if (Graph.Transitions != null)
  928. {
  929. var transitionState = Graph.Transitions.TryPlay(this, key);
  930. if (transitionState != null)
  931. return transitionState;
  932. }
  933. return Graph.States.TryGet(key, out var state)
  934. ? Play(state)
  935. : null;
  936. }
  937. /// <summary>
  938. /// Stops all other animations on this layer,
  939. /// plays the animation registered with the `key`,
  940. /// and returns the animation's state.
  941. /// </summary>
  942. /// <remarks>
  943. /// If no state is registered with the `key`, this method does nothing and returns null.
  944. /// <para></para>
  945. /// The animation will continue playing from its current <see cref="AnimancerState.Time"/>.
  946. /// To restart it from the beginning you can simply set the returned state's time to 0.
  947. /// <para></para>
  948. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  949. /// </remarks>
  950. public AnimancerState TryPlay(
  951. IHasKey hasKey)
  952. => TryPlay(hasKey.Key);
  953. /// <summary>
  954. /// Starts fading in the animation registered with the `key`
  955. /// while fading out all others in the same layer over the course of the `fadeDuration`
  956. /// and returns the animation's state.
  957. /// </summary>
  958. /// <remarks>
  959. /// If no state is registered with the `key`, this method does nothing and returns null.
  960. /// <para></para>
  961. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`,
  962. /// this method allows it to continue the existing fade rather than starting a slower one.
  963. /// <para></para>
  964. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will
  965. /// fade in the layer itself and simply <see cref="AnimancerState.Play"/> the `state`.
  966. /// <para></para>
  967. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  968. /// <para></para>
  969. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  970. /// </remarks>
  971. public AnimancerState TryPlay(
  972. object key,
  973. float fadeDuration,
  974. FadeMode mode = default)
  975. => Graph.States.TryGet(key, out var state)
  976. ? Play(state, fadeDuration, mode)
  977. : null;
  978. /// <summary>
  979. /// Starts fading in the animation registered with the `key`
  980. /// while fading out all others in the same layer over the course of the `fadeDuration`
  981. /// and returns the animation's state.
  982. /// </summary>
  983. /// <remarks>
  984. /// If no state is registered with the `key`, this method does nothing and returns null.
  985. /// <para></para>
  986. /// If the `state` was already playing and fading in with less time remaining than the `fadeDuration`,
  987. /// this method allows it to continue the existing fade rather than starting a slower one.
  988. /// <para></para>
  989. /// If the layer currently has 0 <see cref="AnimancerNode.Weight"/>, this method will
  990. /// fade in the layer itself and simply <see cref="AnimancerState.Play"/> the `state`.
  991. /// <para></para>
  992. /// This method is safe to call repeatedly without checking whether the animation was already playing.
  993. /// <para></para>
  994. /// <em>Animancer Lite only allows the default `fadeDuration` (0.25 seconds) in runtime builds.</em>
  995. /// </remarks>
  996. public AnimancerState TryPlay(
  997. IHasKey hasKey,
  998. float fadeDuration,
  999. FadeMode mode = default)
  1000. => TryPlay(hasKey.Key, fadeDuration, mode);
  1001. /************************************************************************************************************************/
  1002. /// <summary>Manipulates the other parameters according to the `mode`.</summary>
  1003. /// <exception cref="ArgumentException">
  1004. /// The <see cref="AnimancerState.Clip"/> is null when using <see cref="FadeMode.FromStart"/> or
  1005. /// <see cref="FadeMode.NormalizedFromStart"/>.
  1006. /// </exception>
  1007. private void EvaluateFadeMode(
  1008. FadeMode mode,
  1009. ref AnimancerState state,
  1010. float fadeDuration,
  1011. out float stateFadeSpeed,
  1012. out float layerFadeDuration)
  1013. {
  1014. layerFadeDuration = fadeDuration;
  1015. float fadeDistance;
  1016. switch (mode)
  1017. {
  1018. case FadeMode.FixedSpeed:
  1019. fadeDistance = 1;
  1020. layerFadeDuration *= Math.Abs(1 - Weight);
  1021. break;
  1022. case FadeMode.FixedDuration:
  1023. fadeDistance = Math.Abs(1 - state.Weight);
  1024. break;
  1025. case FadeMode.FromStart:
  1026. state = GetOrCreateWeightlessState(state);
  1027. fadeDistance = 1;
  1028. break;
  1029. case FadeMode.NormalizedSpeed:
  1030. {
  1031. var length = state.Length;
  1032. fadeDistance = 1;
  1033. fadeDuration *= length;
  1034. layerFadeDuration *= Math.Abs(1 - Weight) * length;
  1035. }
  1036. break;
  1037. case FadeMode.NormalizedDuration:
  1038. {
  1039. var length = state.Length;
  1040. fadeDistance = Math.Abs(1 - state.Weight);
  1041. fadeDuration *= length;
  1042. layerFadeDuration *= length;
  1043. }
  1044. break;
  1045. case FadeMode.NormalizedFromStart:
  1046. {
  1047. state = GetOrCreateWeightlessState(state);
  1048. var length = state.Length;
  1049. fadeDistance = 1;
  1050. fadeDuration *= length;
  1051. layerFadeDuration *= length;
  1052. }
  1053. break;
  1054. default:
  1055. throw AnimancerUtilities.CreateUnsupportedArgumentException(mode);
  1056. }
  1057. stateFadeSpeed = fadeDistance / fadeDuration;
  1058. }
  1059. /************************************************************************************************************************/
  1060. // Stopping
  1061. /************************************************************************************************************************/
  1062. /// <summary>
  1063. /// Sets <see cref="AnimancerNode.Weight"/> = 0 and calls <see cref="AnimancerNode.Stop"/>
  1064. /// on all animations to stop them from playing and rewind them to the start.
  1065. /// </summary>
  1066. protected internal override void StopWithoutWeight()
  1067. {
  1068. CurrentState = null;
  1069. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  1070. ActiveStatesInternal[i].Stop();
  1071. }
  1072. /************************************************************************************************************************/
  1073. // Checking
  1074. /************************************************************************************************************************/
  1075. /// <summary>
  1076. /// Returns true if the `clip` is currently being played by at least one state.
  1077. /// </summary>
  1078. public bool IsPlayingClip(AnimationClip clip)
  1079. {
  1080. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  1081. {
  1082. var state = ActiveStatesInternal[i];
  1083. if (state.Clip == clip && state.IsPlaying)
  1084. return true;
  1085. }
  1086. return false;
  1087. }
  1088. /// <summary>
  1089. /// Returns true if at least one animation is being played.
  1090. /// </summary>
  1091. public bool IsAnyStatePlaying()
  1092. {
  1093. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  1094. if (ActiveStatesInternal[i].IsPlaying)
  1095. return true;
  1096. return false;
  1097. }
  1098. /// <summary>
  1099. /// Returns true if the <see cref="CurrentState"/> is playing and hasn't yet reached its end.
  1100. /// <para></para>
  1101. /// This method is called by <see cref="IEnumerator.MoveNext"/> so this object can be used as a custom yield
  1102. /// instruction to wait until it finishes.
  1103. /// </summary>
  1104. public override bool IsPlayingAndNotEnding()
  1105. => _CurrentState != null && _CurrentState.IsPlayingAndNotEnding();
  1106. /************************************************************************************************************************/
  1107. /// <summary>
  1108. /// Calculates the total <see cref="AnimancerNode.Weight"/> of all states in this layer.
  1109. /// </summary>
  1110. public float GetTotalChildWeight()
  1111. {
  1112. float weight = 0;
  1113. for (int i = ActiveStatesInternal.Count - 1; i >= 0; i--)
  1114. {
  1115. weight += ActiveStatesInternal[i].Weight;
  1116. }
  1117. return weight;
  1118. }
  1119. /************************************************************************************************************************/
  1120. #endregion
  1121. /************************************************************************************************************************/
  1122. #region Inverse Kinematics
  1123. /************************************************************************************************************************/
  1124. private bool _ApplyAnimatorIK;
  1125. /// <inheritdoc/>
  1126. public override bool ApplyAnimatorIK
  1127. {
  1128. get => _ApplyAnimatorIK;
  1129. set => base.ApplyAnimatorIK = _ApplyAnimatorIK = value;
  1130. }
  1131. /************************************************************************************************************************/
  1132. private bool _ApplyFootIK;
  1133. /// <inheritdoc/>
  1134. public override bool ApplyFootIK
  1135. {
  1136. get => _ApplyFootIK;
  1137. set => base.ApplyFootIK = _ApplyFootIK = value;
  1138. }
  1139. /************************************************************************************************************************/
  1140. #endregion
  1141. /************************************************************************************************************************/
  1142. #region Other
  1143. /************************************************************************************************************************/
  1144. /// <summary>[<see cref="IAnimationClipCollection"/>]
  1145. /// Gathers all the animations in this layer.
  1146. /// </summary>
  1147. public void GatherAnimationClips(ICollection<AnimationClip> clips)
  1148. => clips.GatherFromSource(States);
  1149. /************************************************************************************************************************/
  1150. /// <summary>The Inspector display name of this layer.</summary>
  1151. public override string ToString()
  1152. {
  1153. #if UNITY_ASSERTIONS
  1154. if (DebugName == null)
  1155. {
  1156. if (_Mask != null)
  1157. return _Mask.GetCachedName();
  1158. SetDebugName(Index == 0
  1159. ? "Base Layer"
  1160. : "Layer " + Index);
  1161. }
  1162. return base.ToString();
  1163. #else
  1164. return "Layer " + Index;
  1165. #endif
  1166. }
  1167. /************************************************************************************************************************/
  1168. /// <inheritdoc/>
  1169. protected override void AppendDetails(StringBuilder text, string separator)
  1170. {
  1171. base.AppendDetails(text, separator);
  1172. text.AppendField(separator, nameof(CurrentState), CurrentState?.GetPath());
  1173. text.AppendField(separator, nameof(CommandCount), CommandCount);
  1174. text.AppendField(separator, nameof(IsAdditive), IsAdditive);
  1175. text.AppendField(separator, nameof(Mask), Mask);
  1176. }
  1177. /************************************************************************************************************************/
  1178. #endregion
  1179. /************************************************************************************************************************/
  1180. }
  1181. }