mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-08-02 08:50:18 -04:00
* Remove unnecessary static singletons in MainMenu code * Empty SceneWorld delete queues during shutdown * Dresser cancel async load operation on destroy * Use reflection to null references to static native resources on shutdown This way we don't have to remember doing this manually. * Fix SoundOcclusionSystem using static lists to reference resources * Sound System: Use weak references to refer to scenes * Cleanup static logging listeners that kept strong refs to panels * UISystem Cleanup, make sure all panel/stylesheet refs are released * RenderTarget and RenderAttributes shutdown cleanup * Rework AvatarLoader, ThumbLoader & HTTPImageLoader Cache First try to go through ResourceLibrary.WeakIndex which might already hold the texture. If there is no hit, go through a second cache that caches HTTP & Steam API response bytes instead of textures. We want to cache the response bytes rather than the actual Texture, so stuff cached sits in RAM not VRAM. Before avatars and thumbs would reside in VRAM. * Fix rendertarget leak in CommandList.Attr.SetValue GetDepthTarget() / GetColorTarget() return a new strong handle (ref count +1). We need to DestroyStrongHandle() that ref. So handles don't leak. * Call EngineLoop.DrainFrameEndDisposables before shutdown * NativeResourceCache now report leaks on shutdown * Override Resource.Destroy for native resources, kill stronghandles * Deregister SceneWorld from SceneWorld.All during destruction * Ensure async texture loading cancels on shutdown * SkinnedModelRender bonemergetarget deregister from target OnDisabled * Clear shaderMaterials cache during shutdown * Refactor Shutdown code Mostly renaming methods from Clear() -> Shutdown() Adding separate GlobalContext.Shutdown function (more aggressive than GlobalContext.Reset). Clear some static input state. * Deregister surfaces from Surface.All in OnDestroy * RunAllStaticConstructors when loading a mount * Advanced managed resource leak tracker enabled via `resource_leak_tracking 1` Works by never pruning the WeakTable in NativeResourceCache. So we can check for all resources if they are still being held on to and log a callstack.
181 lines
4.2 KiB
C#
181 lines
4.2 KiB
C#
using NativeEngine;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Anim param values contain any value for a limited set of types
|
|
/// </summary>
|
|
public struct AnimParam<T>
|
|
{
|
|
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;
|
|
|
|
/// <summary>
|
|
/// Whether the animation graph is invalid, or has not yet loaded.
|
|
/// </summary>
|
|
public bool IsError => native.IsNull || !native.IsStrongHandleValid();
|
|
|
|
/// <summary>
|
|
/// Animation graph file name.
|
|
/// </summary>
|
|
public string Name { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// Private constructor, use <see cref="FromNative(HAnimationGraph, string)"/>
|
|
/// </summary>
|
|
private AnimationGraph( HAnimationGraph native, string name )
|
|
{
|
|
if ( native.IsNull ) throw new Exception( "Animation Graph pointer cannot be null!" );
|
|
|
|
this.native = native;
|
|
Name = name;
|
|
|
|
UpdateNameToIndexMapping();
|
|
RegisterWeakResourceId( 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;
|
|
}
|
|
}
|
|
|
|
internal override void Destroy()
|
|
{
|
|
if ( !native.IsNull )
|
|
{
|
|
var n = native;
|
|
native = default;
|
|
|
|
MainThread.Queue( () => n.DestroyStrongHandle() );
|
|
}
|
|
|
|
base.Destroy();
|
|
}
|
|
|
|
internal IAnimParameterList ParameterList => native.GetParameterList();
|
|
internal IAnimParameter GetParameterFromList( int index ) => ParameterList.GetParameter( index );
|
|
internal IAnimParameter GetParameterFromList( string name ) => ParameterList.GetParameter( name );
|
|
|
|
/// <summary>
|
|
/// Number of parameters in this animgraph
|
|
/// </summary>
|
|
public int ParamCount => ParameterList.Count();
|
|
|
|
private Dictionary<string, int> _nameToIndex = new();
|
|
|
|
private static readonly Type[] _types =
|
|
[
|
|
null,
|
|
typeof( bool ),
|
|
typeof( byte ),
|
|
typeof( int ),
|
|
typeof( float ),
|
|
typeof( Vector3 ),
|
|
typeof( Rotation ),
|
|
];
|
|
|
|
/// <summary>
|
|
/// Get value type of parameter at given index
|
|
/// </summary>
|
|
public Type GetParameterType( int index )
|
|
{
|
|
return _types[(int)GetParameterFromList( index ).GetParameterType()];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get value type of parameter with the given <paramref name="name"/>, or <see langword="null"/> if not found.
|
|
/// </summary>
|
|
public Type GetParameterType( string name )
|
|
{
|
|
if ( GetParameterFromList( name ) is not { IsValid: true } param )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var parameterType = param.GetParameterType();
|
|
|
|
return _types[(int)parameterType];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get name of parameter at given index
|
|
/// </summary>
|
|
public string GetParameterName( int index )
|
|
{
|
|
return GetParameterFromList( index ).GetName();
|
|
}
|
|
|
|
internal AnimParam<T> GetParameterInternal<T>( 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<T>(),
|
|
MaxValue = param.GetMaxValue().GetValue<T>(),
|
|
DefaultValue = param.GetDefaultValue().GetValue<T>(),
|
|
OptionNames = parameterType == AnimParamType.Enum ? Enumerable.Range( 0, param.GetNumOptionNames() )
|
|
.Select( param.GetOptionName )
|
|
.ToArray() : null
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to get parameter index at given name
|
|
/// </summary>
|
|
public bool TryGetParameterIndex( string name, out int index )
|
|
{
|
|
return _nameToIndex.TryGetValue( name, out index );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get parameter at given name
|
|
/// </summary>
|
|
public AnimParam<T> GetParameter<T>( string name )
|
|
{
|
|
return GetParameterInternal<T>( GetParameterFromList( name ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get parameter at given index
|
|
/// </summary>
|
|
public AnimParam<T> GetParameter<T>( int index )
|
|
{
|
|
return GetParameterInternal<T>( GetParameterFromList( index ) );
|
|
}
|
|
}
|