123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- using System;
- using System.Runtime.CompilerServices;
- using UnityEngine;
- using Object = UnityEngine.Object;
- namespace Animancer
- {
- /// <summary>[Pro-Only] An object that can be updated during Animancer's animation updates.</summary>
- ///
- /// <remarks>
- /// <strong>Example:</strong>
- /// Register to receive updates using <see cref="AnimancerGraph.RequirePreUpdate"/> or
- /// <see cref="AnimancerGraph.RequirePostUpdate"/> and stop
- /// receiving updates using <see cref="AnimancerGraph.CancelPreUpdate"/> or
- /// <see cref="AnimancerGraph.CancelPostUpdate"/>.
- /// <para></para><code>
- /// public sealed class MyUpdatable : IUpdatable
- /// {
- /// // Implement IUpdatable.
- /// // You can avoid this by inheriting from Updatable instead.
- /// int IUpdatable.UpdatableIndex { get; set; } = IUpdatable.List.NotInList;
- ///
- /// private AnimancerComponent _Animancer;
- ///
- /// public void StartUpdating(AnimancerComponent animancer)
- /// {
- /// _Animancer = animancer;
- ///
- /// // If you want Update to be called before the playables get updated.
- /// _Animancer.Graph.RequirePreUpdate(this);
- ///
- /// // If you want Update to be called after the playables get updated.
- /// _Animancer.Graph.RequirePostUpdate(this);
- /// }
- ///
- /// public void StopUpdating()
- /// {
- /// // If you used RequirePreUpdate.
- /// _Animancer.Graph.CancelPreUpdate(this);
- ///
- /// // If you used RequirePostUpdate.
- /// _Animancer.Graph.CancelPostUpdate(this);
- /// }
- ///
- /// void IUpdatable.Update()
- /// {
- /// // Called during every animation update.
- ///
- /// // AnimancerGraph.Current can be used to access the system it is being updated by.
- /// }
- /// }
- /// </code></remarks>
- ///
- /// https://kybernetik.com.au/animancer/api/Animancer/IUpdatable
- ///
- public interface IUpdatable
- {
- /************************************************************************************************************************/
- /// <summary>The index of this object in its <see cref="IndexedList{TItem, TIndexer}"/>.</summary>
- /// <remarks>Should be initialized to -1 to indicate that this object is not yet in a list.</remarks>
- int UpdatableIndex { get; set; }
- /// <summary>Updates this object.</summary>
- void Update();
- /************************************************************************************************************************/
- /// <summary>An <see cref="IIndexer{T}"/> for <see cref="IUpdatable"/>.</summary>
- public readonly struct Indexer : IIndexer<IUpdatable>
- {
- /************************************************************************************************************************/
- /// <inheritdoc/>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public readonly int GetIndex(IUpdatable item)
- => item.UpdatableIndex;
- /// <inheritdoc/>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public readonly void SetIndex(IUpdatable item, int index)
- => item.UpdatableIndex = index;
- /// <inheritdoc/>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public readonly void ClearIndex(IUpdatable item)
- => item.UpdatableIndex = -1;
- /************************************************************************************************************************/
- }
- /************************************************************************************************************************/
- /// <summary>An <see cref="IndexedList{TItem, TAccessor}"/> of <see cref="IUpdatable"/>.</summary>
- public class List : IndexedList<IUpdatable, Indexer>
- {
- /************************************************************************************************************************/
- /// <summary>The default <see cref="IndexedList{TItem, TIndexer}.Capacity"/> for newly created lists.</summary>
- /// <remarks>Default value is 4.</remarks>
- public static new int DefaultCapacity { get; set; } = 4;
- /************************************************************************************************************************/
- /// <summary>Creates a new <see cref="List"/> with the <see cref="DefaultCapacity"/>.</summary>
- public List()
- : base(DefaultCapacity, new())
- { }
- /************************************************************************************************************************/
- /// <summary>Calls <see cref="Update"/> on all items in this list.</summary>
- /// <remarks>
- /// Uses <see cref="Debug.LogException(Exception, Object)"/> to handle exceptions and continues executing
- /// the remaining items if any occur.
- /// </remarks>
- public void UpdateAll()
- {
- BeginEnumeraton();
- ContinueEnumeration:
- try
- {
- while (TryEnumerateNext())
- {
- Current.Update();
- }
- }
- catch (Exception exception)
- {
- Debug.LogException(exception, AnimancerGraph.Current?.Component as Object);
- goto ContinueEnumeration;
- }
- }
- /************************************************************************************************************************/
- /// <summary>Clones any <see cref="ICloneable{T}"/> items.</summary>
- public void CloneFrom(
- List copyFrom,
- CloneContext context)
- {
- var count = copyFrom.Count;
- for (int i = 0; i < count; i++)
- if (copyFrom[i] is ICloneable<object> cloneable &&
- context.GetOrCreateClone(cloneable) is IUpdatable clone)
- Add(clone);
- }
- /************************************************************************************************************************/
- }
- /************************************************************************************************************************/
- }
- /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerUtilities
- public static partial class AnimancerUtilities
- {
- /************************************************************************************************************************/
- /// <summary>Is the `updatable` currently in a list?</summary>
- public static bool IsInList(this IUpdatable updatable)
- => updatable.UpdatableIndex >= 0;
- /************************************************************************************************************************/
- }
- }
|