Files
sbox-public/engine/Sandbox.System/SerializedObject/CustomEditorAttribute.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

111 lines
2.4 KiB
C#

using Facepunch.ActionGraphs;
namespace Sandbox;
[AttributeUsage( AttributeTargets.Class, AllowMultiple = true, Inherited = false )]
public class CustomEmbeddedEditorAttribute : Attribute
{
public Type TargetType { get; }
public CustomEmbeddedEditorAttribute( Type targetType = null )
{
TargetType = targetType;
}
}
[AttributeUsage( AttributeTargets.Class, AllowMultiple = true, Inherited = false )]
public class CustomEditorAttribute : Attribute
{
public Type TargetType { get; }
public Type[] WithAllAttributes { get; set; }
public bool ForMethod { get; set; }
public string NamedEditor { get; set; }
public bool ForInterface { get; set; }
public CustomEditorAttribute( Type targetType = null )
{
TargetType = targetType;
}
public float GetEditorScore( SerializedProperty property )
{
// This is a method, and it doesn't apply to it
if ( property.IsMethod != ForMethod )
return 0;
float score = 0;
if ( ForMethod )
score += 100;
if ( property.PropertyType.IsInterface && ForInterface )
score += 100;
var t = property.PropertyType;
if ( t is null ) return score;
if ( Either.IsEitherType( t ) )
{
t = typeof( Either );
}
if ( Nullable.GetUnderlyingType( t ) is { } elemType )
{
t = elemType;
}
//
// This attribute has a type set, look at that
//
if ( TargetType is not null && !ForMethod )
{
//
// Order by derived classes so we get the most relevent editor
//
Type baseType = TargetType;
while ( baseType.BaseType != null )
{
score += 10.0f;
baseType = baseType.BaseType;
}
if ( TargetType == t ) score += 1000.0f; // directly targets this class
else if ( t.IsGenericType && TargetType == t.GetGenericTypeDefinition() ) score += 500.0f; // generic type target
else if ( t.IsAssignableTo( TargetType ) ) score += 100.0f; // directly targets a base type
else return -100; // definitely not this!
}
//
// Properties can have [Editor( "NamedEditor" )]
//
if ( NamedEditor is not null )
{
if ( property.TryGetAttribute<EditorAttribute>( out var editorAttribute ) && string.Equals( editorAttribute.Value, NamedEditor ) )
{
score += 1000;
}
else
{
score -= 1000;
}
}
//
// Needs all of these attributes
//
if ( WithAllAttributes is not null )
{
foreach ( var a in WithAllAttributes )
{
if ( !property.HasAttribute( a ) )
return -100;
score += 1000;
}
}
return score;
}
}