// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik // using System; using System.Runtime.CompilerServices; using UnityEngine; using Object = UnityEngine.Object; namespace Animancer { /// [Pro-Only] An object that can be updated during Animancer's animation updates. /// /// /// Example: /// Register to receive updates using or /// and stop /// receiving updates using or /// . /// /// 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. /// } /// } /// /// /// https://kybernetik.com.au/animancer/api/Animancer/IUpdatable /// public interface IUpdatable { /************************************************************************************************************************/ /// The index of this object in its . /// Should be initialized to -1 to indicate that this object is not yet in a list. int UpdatableIndex { get; set; } /// Updates this object. void Update(); /************************************************************************************************************************/ /// An for . public readonly struct Indexer : IIndexer { /************************************************************************************************************************/ /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly int GetIndex(IUpdatable item) => item.UpdatableIndex; /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void SetIndex(IUpdatable item, int index) => item.UpdatableIndex = index; /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void ClearIndex(IUpdatable item) => item.UpdatableIndex = -1; /************************************************************************************************************************/ } /************************************************************************************************************************/ /// An of . public class List : IndexedList { /************************************************************************************************************************/ /// The default for newly created lists. /// Default value is 4. public static new int DefaultCapacity { get; set; } = 4; /************************************************************************************************************************/ /// Creates a new with the . public List() : base(DefaultCapacity, new()) { } /************************************************************************************************************************/ /// Calls on all items in this list. /// /// Uses to handle exceptions and continues executing /// the remaining items if any occur. /// public void UpdateAll() { BeginEnumeraton(); ContinueEnumeration: try { while (TryEnumerateNext()) { Current.Update(); } } catch (Exception exception) { Debug.LogException(exception, AnimancerGraph.Current?.Component as Object); goto ContinueEnumeration; } } /************************************************************************************************************************/ /// Clones any items. public void CloneFrom( List copyFrom, CloneContext context) { var count = copyFrom.Count; for (int i = 0; i < count; i++) if (copyFrom[i] is ICloneable cloneable && context.GetOrCreateClone(cloneable) is IUpdatable clone) Add(clone); } /************************************************************************************************************************/ } /************************************************************************************************************************/ } /// https://kybernetik.com.au/animancer/api/Animancer/AnimancerUtilities public static partial class AnimancerUtilities { /************************************************************************************************************************/ /// Is the `updatable` currently in a list? public static bool IsInList(this IUpdatable updatable) => updatable.UpdatableIndex >= 0; /************************************************************************************************************************/ } }