using System.Collections.Generic; using UnityEngine; namespace Invector.vEventSystems { public interface vIAnimatorStateInfoController { vAnimatorStateInfos animatorStateInfos { get; } } public static class vIAnimatorStateInfoHelper { /// /// Register all listener to listener /// /// public static void Register(this vIAnimatorStateInfoController animatorStateInfos) { if (animatorStateInfos.isValid()) { animatorStateInfos.animatorStateInfos.RegisterListener(); } } /// /// Remove all listener from /// /// public static void UnRegister(this vIAnimatorStateInfoController animatorStateInfos) { if (animatorStateInfos.isValid()) { animatorStateInfos.animatorStateInfos.RemoveListener(); } } /// /// Check if is valid /// /// /// public static bool isValid(this vIAnimatorStateInfoController animatorStateInfos) { return animatorStateInfos != null && animatorStateInfos.animatorStateInfos != null && animatorStateInfos.animatorStateInfos.animator != null; } } [System.Serializable] public class vAnimatorStateInfos { public bool debug; public Animator animator; public vAnimatorStateInfos(Animator animator) { this.animator = animator; Init(); } public void Init() { if (animator) { stateInfos = new vStateInfo[animator.layerCount]; for (int i = 0; i < stateInfos.Length; i++) { stateInfos[i] = new vStateInfo(i); } } } public void RegisterListener() { var bhv = animator.GetBehaviours(); for (int i = 0; i < bhv.Length; i++) { bhv[i].RemoveStateInfoListener(this); bhv[i].AddStateInfoListener(this); } if (debug) { Debug.Log($"Listeners Registered", animator); } } public void RemoveListener() { if (animator) { var bhv = animator.GetBehaviours(); for (int i = 0; i < bhv.Length; i++) { bhv[i].RemoveStateInfoListener(this); } if (debug) { Debug.Log($"Listeners Removed", animator); } } } public vStateInfo[] stateInfos = new vStateInfo[0]; [System.Serializable] public class vStateInfo { public int layer; public int shortPathHash; public float normalizedTime; public List tags = new List(); public vStateInfo(int layer) { this.layer = layer; } } /// /// Add tag to the layer /// /// Tag /// Animator layer public void AddStateInfo(string tag, int layer) { if (stateInfos.Length > 0 && layer < stateInfos.Length) { vStateInfo info = stateInfos[layer]; info.tags.Add(tag); info.shortPathHash = 0; info.normalizedTime = 0; } if (debug) { Debug.Log($"Add tag : {tag},in the animator layer :{layer}", animator); } } /// /// Uptade State info /// /// state layer /// state normalizedTime /// state fullPathHash public void UpdateStateInfo(int layer, float normalizedTime, int fullPathHash) { if (stateInfos.Length > 0 && layer < stateInfos.Length) { vStateInfo info = stateInfos[layer]; info.normalizedTime = normalizedTime; info.shortPathHash = fullPathHash; } } /// /// Remove Tag of the layer /// /// Tag /// Animator layer public void RemoveStateInfo(string tag, int layer) { if (stateInfos.Length > 0 && layer < stateInfos.Length) { vStateInfo info = stateInfos[layer]; if (info.tags.Contains(tag)) { info.tags.Remove(tag); if (info.tags.Count == 0) { info.shortPathHash = 0; info.normalizedTime = 0; } if (debug) { Debug.Log($"Remove tag : {tag}, in the animator layer :{layer}", animator); } } } } /// /// Check If StateInfo list contains tag /// /// tag to check /// public bool HasTag(string tag) { return System.Array.Exists(stateInfos, info => info.tags.Contains(tag)); } /// /// Check if All tags in in StateInfo List /// /// tags to check /// public bool HasAllTags(params string[] tags) { var has = tags.Length > 0 ? true : false; for (int i = 0; i < tags.Length; i++) { if (!HasTag(tags[i])) { has = false; break; } } return has; } /// /// Check if StateInfo List Contains any tag /// /// tags to check /// public bool HasAnyTag(params string[] tags) { var has = false; for (int i = 0; i < tags.Length; i++) { if (HasTag(tags[i])) { has = true; break; } } return has; } /// /// Get current animator state info using tag /// /// tag /// if tag exit return AnimatorStateInfo? else return null public vStateInfo GetStateInfoUsingTag(string tag) { return System.Array.Find(stateInfos, info => info.tags.Contains(tag)); } public float GetCurrentNormalizedTime(int layer) { if (stateInfos.Length > 0 && layer < stateInfos.Length) { vStateInfo info = stateInfos[layer]; return info.normalizedTime; } return 0; } } }