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( 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; } }