// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // using System; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor.Animations; #endif namespace Animancer { /// https://kybernetik.com.au/animancer/api/Animancer/ControllerState partial class ControllerState { /************************************************************************************************************************/ /// A wrapper for the name and hash of an . public readonly struct ParameterID { /************************************************************************************************************************/ /// The name of this parameter. public readonly string Name; /// The name hash of this parameter. public readonly int Hash; /************************************************************************************************************************/ /// /// Creates a new with the specified and uses /// to calculate the . /// public ParameterID(string name) { Name = name; Hash = Animator.StringToHash(name); } /// /// Creates a new with the specified and leaves the /// null. /// public ParameterID(int hash) { Name = null; Hash = hash; } /// Creates a new with the specified and . /// This constructor does not verify that the `hash` actually corresponds to the `name`. public ParameterID(string name, int hash) { Name = name; Hash = hash; } /************************************************************************************************************************/ /// /// Creates a new with the specified and uses /// to calculate the . /// public static implicit operator ParameterID(string name) => new ParameterID(name); /// /// Creates a new with the specified and leaves the /// null. /// public static implicit operator ParameterID(int hash) => new ParameterID(hash); /************************************************************************************************************************/ /// Returns the . public static implicit operator int(ParameterID parameter) => parameter.Hash; /************************************************************************************************************************/ /// [Editor-Conditional] /// Throws if the `controller` doesn't have a parameter with the specified /// and `type`. /// /// [System.Diagnostics.Conditional(Strings.UnityEditor)] public void ValidateHasParameter(RuntimeAnimatorController controller, AnimatorControllerParameterType type) { #if UNITY_EDITOR var parameterDetails = GetParameterDetails(controller); if (parameterDetails == null) return; // Check that there is a parameter with the correct hash and type. if (!parameterDetails.TryGetValue(Hash, out var parameterType)) { throw new ArgumentException($"{controller} has no {type} parameter matching {this}"); } if (type != parameterType) { throw new ArgumentException($"{controller} has a parameter matching {this}, but it is not a {type}"); } #endif } /************************************************************************************************************************/ #if UNITY_EDITOR private static Dictionary> _ControllerToParameterHashAndType; /// [Editor-Only] Returns the hash mapped to the type of all parameters in the `controller`. /// This doesn't work for if the `controller` was loaded from an Asset Bundle. private static Dictionary GetParameterDetails( RuntimeAnimatorController controller) { Editor.AnimancerEditorUtilities.InitializeCleanDictionary(ref _ControllerToParameterHashAndType); if (_ControllerToParameterHashAndType.TryGetValue(controller, out var parameterDetails)) return parameterDetails; if (controller is AnimatorController editorController) { var parameters = editorController.parameters; var count = parameters.Length; if (count != 0 || editorController.layers.Length != 0) { parameterDetails = new Dictionary(); for (int i = 0; i < count; i++) { var parameter = parameters[i]; parameterDetails.Add(parameter.nameHash, parameter.type); } _ControllerToParameterHashAndType.Add(controller, parameterDetails); return parameterDetails; } } _ControllerToParameterHashAndType.Add(controller, null); return null; } #endif /************************************************************************************************************************/ /// Returns a string containing the and . public override string ToString() { return $"{nameof(ControllerState)}.{nameof(ParameterID)}" + $"({nameof(Name)}: '{Name}'" + $", {nameof(Hash)}: {Hash})"; } /************************************************************************************************************************/ } /************************************************************************************************************************/ } }