using NativeEngine;
namespace Sandbox;
///
/// Anim param values contain any value for a limited set of types
///
public struct AnimParam
{
public string Name;
public T MinValue;
public T MaxValue;
public T DefaultValue;
public string[] OptionNames;
}
public sealed partial class AnimationGraph : Resource
{
internal HAnimationGraph native;
public override bool IsValid => native.IsValid;
///
/// Whether the animation graph is invalid, or has not yet loaded.
///
public bool IsError => native.IsNull || !native.IsStrongHandleValid();
///
/// Animation graph file name.
///
public string Name { get; internal set; }
///
/// Private constructor, use
///
private AnimationGraph( HAnimationGraph native, string name )
{
if ( native.IsNull ) throw new Exception( "Animation Graph pointer cannot be null!" );
this.native = native;
Name = name;
UpdateNameToIndexMapping();
SetIdFromResourcePath( Name );
}
internal override void OnReloaded()
{
base.OnReloaded();
UpdateNameToIndexMapping();
}
private void UpdateNameToIndexMapping()
{
_nameToIndex.Clear();
for ( var i = 0; i < ParamCount; i++ )
{
_nameToIndex[GetParameterFromList( i ).GetName()] = i;
}
}
~AnimationGraph()
{
var n = native;
native = default;
MainThread.Queue( () => n.DestroyStrongHandle() );
}
internal IAnimParameterList ParameterList => native.GetParameterList();
internal IAnimParameter GetParameterFromList( int index ) => ParameterList.GetParameter( index );
internal IAnimParameter GetParameterFromList( string name ) => ParameterList.GetParameter( name );
///
/// Number of parameters in this animgraph
///
public int ParamCount => ParameterList.Count();
private Dictionary _nameToIndex = new();
private static readonly Type[] _types =
[
null,
typeof( bool ),
typeof( byte ),
typeof( int ),
typeof( float ),
typeof( Vector3 ),
typeof( Rotation ),
];
///
/// Get value type of parameter at given index
///
public Type GetParameterType( int index )
{
return _types[(int)GetParameterFromList( index ).GetParameterType()];
}
///
/// Get value type of parameter with the given , or if not found.
///
public Type GetParameterType( string name )
{
if ( GetParameterFromList( name ) is not { IsValid: true } param )
{
return null;
}
var parameterType = param.GetParameterType();
return _types[(int)parameterType];
}
///
/// Get name of parameter at given index
///
public string GetParameterName( int index )
{
return GetParameterFromList( index ).GetName();
}
internal AnimParam GetParameterInternal( IAnimParameter param )
{
if ( !param.IsValid )
{
throw new ArgumentException( $"Invalid parameter" );
}
var parameterType = param.GetParameterType();
var type = _types[(int)parameterType];
if ( type != typeof( T ) )
{
throw new ArgumentException( $"Invalid parameter type {typeof( T )}, expected {type}" );
}
return new()
{
Name = param.GetName(),
MinValue = param.GetMinValue().GetValue(),
MaxValue = param.GetMaxValue().GetValue(),
DefaultValue = param.GetDefaultValue().GetValue(),
OptionNames = parameterType == AnimParamType.Enum ? Enumerable.Range( 0, param.GetNumOptionNames() )
.Select( param.GetOptionName )
.ToArray() : null
};
}
///
/// Try to get parameter index at given name
///
public bool TryGetParameterIndex( string name, out int index )
{
return _nameToIndex.TryGetValue( name, out index );
}
///
/// Get parameter at given name
///
public AnimParam GetParameter( string name )
{
return GetParameterInternal( GetParameterFromList( name ) );
}
///
/// Get parameter at given index
///
public AnimParam GetParameter( int index )
{
return GetParameterInternal( GetParameterFromList( index ) );
}
}