mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-07 22:08:34 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
395 lines
12 KiB
C#
395 lines
12 KiB
C#
using NativeEngine;
|
|
using Sandbox.Rendering;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// RenderAttributes are a set of values that are passed to the renderer.
|
|
/// They can be a variety of primitive types, textures, samplers or buffers.
|
|
/// You can access attributes in the shader by binding them to a variable:
|
|
/// <code>
|
|
/// float4 CornerRadius < Attribute( "BorderRadius" ); >;
|
|
/// Texture2D g_tColor < Attribute( "Texture" ); SrgbRead( false ); >;
|
|
/// </code>
|
|
/// <seealso cref="Renderer.Attributes"/>
|
|
/// <seealso cref="Graphics.DrawModel(Model, Transform, RenderAttributes)"/>
|
|
/// <seealso cref="ComputeShader.DispatchWithAttributes(RenderAttributes, int, int, int)"/>
|
|
/// </summary>
|
|
public partial class RenderAttributes
|
|
{
|
|
private CRenderAttributes attributes;
|
|
private bool manuallyAllocated;
|
|
|
|
internal static RenderAttributePool Pool = new();
|
|
|
|
internal CRenderAttributes Get()
|
|
{
|
|
return attributes;
|
|
}
|
|
|
|
internal void Set( CRenderAttributes a )
|
|
{
|
|
TryFree();
|
|
attributes = a;
|
|
manuallyAllocated = false;
|
|
}
|
|
|
|
public RenderAttributes()
|
|
{
|
|
manuallyAllocated = true;
|
|
attributes = CRenderAttributes.Create();
|
|
}
|
|
|
|
internal RenderAttributes( CRenderAttributes attr )
|
|
{
|
|
Set( attr );
|
|
}
|
|
|
|
~RenderAttributes()
|
|
{
|
|
TryFree();
|
|
}
|
|
|
|
private void TryFree()
|
|
{
|
|
if ( manuallyAllocated )
|
|
{
|
|
//
|
|
// garry: I'm deleting these on the main thread. I don't think there's actually
|
|
// any danger here because generally when you're using these you're passing them
|
|
// into something (like a render) and it's using it immediately and not holding on
|
|
// to it.
|
|
//
|
|
var a = attributes;
|
|
MainThread.Queue( () => a.DeleteThis() );
|
|
}
|
|
|
|
attributes = default;
|
|
|
|
ClearUsedTextures();
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.Clear( true, true );
|
|
ClearUsedTextures();
|
|
}
|
|
|
|
internal void Clear( bool freeMemory )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.Clear( freeMemory, true );
|
|
ClearUsedTextures();
|
|
}
|
|
|
|
public void SetCombo( in StringToken k, in int value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetComboValue( k, (byte)value );
|
|
}
|
|
|
|
[Obsolete( "Please use SetComboEnum" )]
|
|
public void SetCombo( in string k, in Enum value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetComboValue( k, (byte)(int)(object)value );
|
|
}
|
|
|
|
public void SetComboEnum<T>( in StringToken k, in T value ) where T : unmanaged, Enum
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetComboValue( k, (byte)value.AsInt() );
|
|
}
|
|
|
|
public void SetCombo( in StringToken k, in bool value )
|
|
{
|
|
SetCombo( k, value ? 1 : 0 );
|
|
}
|
|
|
|
public T GetComboEnum<T>( in StringToken k, in T defaultValue ) where T : Enum
|
|
{
|
|
if ( !attributes.IsValid )
|
|
return defaultValue;
|
|
|
|
return (T)(object)(int)attributes.GetComboValue( k, (byte)(int)(object)defaultValue );
|
|
}
|
|
|
|
public bool GetComboBool( in StringToken k, in bool defaultValue = false )
|
|
{
|
|
if ( !attributes.IsValid )
|
|
return defaultValue;
|
|
|
|
return attributes.GetComboValue( k, (byte)(defaultValue ? 1 : 0) ) == 1;
|
|
}
|
|
|
|
public int GetComboInt( in StringToken k, in int defaultValue = 0 )
|
|
{
|
|
if ( !attributes.IsValid )
|
|
return defaultValue;
|
|
|
|
return attributes.GetComboValue( k, (byte)defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal for a reason - don't expose!
|
|
/// </summary>
|
|
internal void SetPointer( in StringToken k, in IntPtr value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetPtrValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in int value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetIntValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Vector2Int value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetIntVector4DValue( k, value.x, value.y, 0, 0 );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Vector3Int value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetIntVector4DValue( k, value.x, value.y, value.z, 0 );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Texture value, in int mip = -1 )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
|
|
var native = value?.native ?? default;
|
|
Set( k, native, mip );
|
|
|
|
SetUsedTexture( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in SamplerState value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
|
|
attributes.SetSamplerValue( k, new( value ) );
|
|
}
|
|
|
|
internal void Set( in StringToken k, in ITexture value, in int mip = -1 )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetTextureValue( k, value, mip );
|
|
}
|
|
|
|
public void Set( in StringToken k, in float value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetFloatValue( k, value );
|
|
}
|
|
public void Set( in StringToken k, in double value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetFloatValue( k, (float)value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in string value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetStringValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in bool value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetBoolValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Vector4 value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetVector4DValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Angles value )
|
|
{
|
|
Set( k, new Vector3( value.pitch, value.yaw, value.roll ) );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Vector3 value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetVectorValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Vector2 value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetVector2DValue( k, value );
|
|
}
|
|
|
|
public void Set( in StringToken k, in GpuBuffer value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetBufferValue( k, value.native );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a constant buffer to a specific value
|
|
/// </summary>
|
|
public unsafe void SetData<T>( in StringToken k, Span<T> value ) where T : unmanaged
|
|
{
|
|
if ( !SandboxedUnsafe.IsAcceptablePod<T>() )
|
|
throw new ArgumentException( $"{nameof( T )} must be a POD type" );
|
|
|
|
int actualSize = value.Length * Unsafe.SizeOf<T>();
|
|
if ( actualSize <= 0 ) return;
|
|
fixed ( T* ptr = value )
|
|
RenderTools.SetDynamicConstantBufferData( attributes, k, Graphics.Context, (IntPtr)ptr, actualSize );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a constant buffer to a specific value
|
|
/// </summary>
|
|
public unsafe void SetData<T>( in StringToken k, T value ) where T : unmanaged
|
|
{
|
|
if ( !SandboxedUnsafe.IsAcceptablePod<T>() )
|
|
throw new ArgumentException( $"{nameof( T )} must be a POD type" );
|
|
|
|
if ( !attributes.IsValid ) return;
|
|
int actualSize = Unsafe.SizeOf<T>();
|
|
if ( actualSize <= 0 ) return;
|
|
RenderTools.SetDynamicConstantBufferData( attributes, k, Graphics.Context, (IntPtr)(&value), actualSize );
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Set a constant buffer to a specific value
|
|
/// </summary>
|
|
public unsafe void SetData<T>( in StringToken k, T[] value ) where T : unmanaged
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
SetData( k, value.AsSpan() );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a constant buffer to a specific value
|
|
/// </summary>
|
|
public unsafe void SetData<T>( in StringToken k, List<T> value ) where T : unmanaged
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
SetData( k, value.ToArray() );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a bool value - else defaultValue if missing
|
|
/// </summary>
|
|
public bool GetBool( in StringToken name, in bool defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetBoolValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a vector3 value - else defaultValue if missing
|
|
/// </summary>
|
|
public Vector3 GetVector( in StringToken name, in Vector3 defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetVectorValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a vector4 value - else defaultValue if missing
|
|
/// </summary>
|
|
public Vector4 GetVector4( in StringToken name, in Vector4 defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetVector4DValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a vector4 value - else defaultValue if missing
|
|
/// </summary>
|
|
public Angles GetAngles( in StringToken name, in Angles defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
|
|
var d = new Vector3( defaultValue.pitch, defaultValue.yaw, defaultValue.roll );
|
|
d = attributes.GetVectorValue( name, d );
|
|
|
|
return new Angles( d.x, d.y, d.z );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a float value - else defaultValue if missing
|
|
/// </summary>
|
|
public float GetFloat( in StringToken name, in float defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetFloatValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a int value - else defaultValue if missing
|
|
/// </summary>
|
|
public int GetInt( in StringToken name, in int defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetIntValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a matrix value - else defaultValue if missing
|
|
/// </summary>
|
|
public Matrix GetMatrix( in StringToken name, in Matrix defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
return attributes.GetVMatrixValue( name, defaultValue );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a texture value - else defaultValue if missing
|
|
/// </summary>
|
|
public Texture GetTexture( in StringToken name, in Texture defaultValue = default )
|
|
{
|
|
if ( !attributes.IsValid ) return defaultValue;
|
|
var texturePointer = attributes.GetTextureValue( name, default );
|
|
if ( texturePointer.IsNull ) return defaultValue;
|
|
|
|
return Texture.FromNative( texturePointer );
|
|
}
|
|
|
|
public void Set( in StringToken k, in Matrix value )
|
|
{
|
|
if ( !attributes.IsValid ) return;
|
|
attributes.SetVMatrixValue( k, value );
|
|
}
|
|
|
|
internal void MergeTo( RenderAttributes renderAttributes )
|
|
{
|
|
if ( renderAttributes is null ) throw new ArgumentNullException( nameof( renderAttributes ) );
|
|
if ( !attributes.IsValid || !renderAttributes.attributes.IsValid ) return;
|
|
attributes.MergeToPtr( renderAttributes.attributes );
|
|
}
|
|
|
|
// These are for backwards compatibility with compiled shit
|
|
public void SetCombo( [StringToken.Convert] in string k, in int value ) => SetCombo( (StringToken)k, value );
|
|
public void SetCombo( [StringToken.Convert] in string k, in bool value ) => SetCombo( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in bool value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in int value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Vector2Int value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Vector3Int value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Vector4 value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Vector3 value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Vector2 value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Matrix value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Angles value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in string value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in Texture value, in int mip = -1 ) => Set( (StringToken)k, value, mip );
|
|
public void Set( [StringToken.Convert] in string k, in float value ) => Set( (StringToken)k, value );
|
|
public void Set( [StringToken.Convert] in string k, in double value ) => Set( (StringToken)k, (float)value );
|
|
public Texture GetTexture( [StringToken.Convert] in string name, in Texture defaultValue = default ) => GetTexture( (StringToken)name, defaultValue );
|
|
|
|
}
|