Net.Like.Xue.Tokyo/Assets/Plugins/Animancer/Internal/Controller States/ControllerState.ParameterID.cs

165 lines
7.2 KiB
C#

// 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
{
/************************************************************************************************************************/
/// <summary>A wrapper for the name and hash of an <see cref="AnimatorControllerParameter"/>.</summary>
public readonly struct ParameterID
{
/************************************************************************************************************************/
/// <summary>The name of this parameter.</summary>
public readonly string Name;
/// <summary>The name hash of this parameter.</summary>
public readonly int Hash;
/************************************************************************************************************************/
/// <summary>
/// Creates a new <see cref="ParameterID"/> with the specified <see cref="Name"/> and uses
/// <see cref="Animator.StringToHash"/> to calculate the <see cref="Hash"/>.
/// </summary>
public ParameterID(string name)
{
Name = name;
Hash = Animator.StringToHash(name);
}
/// <summary>
/// Creates a new <see cref="ParameterID"/> with the specified <see cref="Hash"/> and leaves the
/// <see cref="Name"/> null.
/// </summary>
public ParameterID(int hash)
{
Name = null;
Hash = hash;
}
/// <summary>Creates a new <see cref="ParameterID"/> with the specified <see cref="Name"/> and <see cref="Hash"/>.</summary>
/// <remarks>This constructor does not verify that the `hash` actually corresponds to the `name`.</remarks>
public ParameterID(string name, int hash)
{
Name = name;
Hash = hash;
}
/************************************************************************************************************************/
/// <summary>
/// Creates a new <see cref="ParameterID"/> with the specified <see cref="Name"/> and uses
/// <see cref="Animator.StringToHash"/> to calculate the <see cref="Hash"/>.
/// </summary>
public static implicit operator ParameterID(string name) => new ParameterID(name);
/// <summary>
/// Creates a new <see cref="ParameterID"/> with the specified <see cref="Hash"/> and leaves the
/// <see cref="Name"/> null.
/// </summary>
public static implicit operator ParameterID(int hash) => new ParameterID(hash);
/************************************************************************************************************************/
/// <summary>Returns the <see cref="Hash"/>.</summary>
public static implicit operator int(ParameterID parameter) => parameter.Hash;
/************************************************************************************************************************/
/// <summary>[Editor-Conditional]
/// Throws if the `controller` doesn't have a parameter with the specified <see cref="Hash"/>
/// and `type`.
/// </summary>
/// <exception cref="ArgumentException"/>
[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<RuntimeAnimatorController, Dictionary<int, AnimatorControllerParameterType>>
_ControllerToParameterHashAndType;
/// <summary>[Editor-Only] Returns the hash mapped to the type of all parameters in the `controller`.</summary>
/// <remarks>This doesn't work for if the `controller` was loaded from an Asset Bundle.</remarks>
private static Dictionary<int, AnimatorControllerParameterType> 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<int, AnimatorControllerParameterType>();
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
/************************************************************************************************************************/
/// <summary>Returns a string containing the <see cref="Name"/> and <see cref="Hash"/>.</summary>
public override string ToString()
{
return $"{nameof(ControllerState)}.{nameof(ParameterID)}" +
$"({nameof(Name)}: '{Name}'" +
$", {nameof(Hash)}: {Hash})";
}
/************************************************************************************************************************/
}
/************************************************************************************************************************/
}
}