Skip to content

Instantly share code, notes, and snippets.

@cgbeutler
Last active June 3, 2020 23:46
Show Gist options
  • Save cgbeutler/8c85657bcaaa130aef45d14a677c981f to your computer and use it in GitHub Desktop.
Save cgbeutler/8c85657bcaaa130aef45d14a677c981f to your computer and use it in GitHub Desktop.
ExportAs Attribute for Godot CSharp Projects.
using System.Linq;
using Godot;
using Godot.Collections;
namespace Vial.Export {
[System.AttributeUsage(System.AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
public sealed class ExportAsAttribute : System.Attribute {
internal readonly string _name;
internal readonly int _type;
internal readonly int? _hint;
internal readonly string? _hintString;
public ExportAsAttribute( string name, Variant.Type type ) : this( name, type, null, null, null ) {}
public ExportAsAttribute( string name, Variant.Type type, PropertyHint hint ) : this(name, type, hint, null, null) {}
public ExportAsAttribute( string name, Variant.Type type, PropertyHint hint, string hintString ) : this (name, type, hint, hintString, null) {}
private ExportAsAttribute( string name, Variant.Type type, PropertyHint? hint, string? hintString, int? trigger ) {
_name = name;
_type = (int)type;
_hint = (int?)hint;
_hintString = hintString;
}
public Dictionary ToDict() {
var dict = new Dictionary(){ {"name", _name}, {"type", _type} };
if (_hint != null) dict.Add( "hint", _hint );
if (_hintString != null) dict.Add( "hint_string", _hintString );
return dict;
}
}
public static class ExportExt{
public static Dictionary[] GetPropertyListFromAttributes<T>( this T o ) where T : Object {
return typeof(T)
.GetProperties()
.Where( p => System.Attribute.IsDefined(p, typeof(ExportAsAttribute)) )
.SelectMany( p => p
.GetCustomAttributes( true )
.OfType<ExportAsAttribute>()
)
.Select( p => p.ToDict() )
.ToArray();
}
public static bool TryToSetPropertyWithAttribute<T>( this T o, string propertyStr, object value) where T : Object {
try {
var propertyInfo = typeof(T)
.GetProperties()
.Where( p => System.Attribute.IsDefined(p, typeof(ExportAsAttribute)) )
.FirstOrDefault( p => p
.GetCustomAttributes(true)
.Any( a => (a is ExportAsAttribute eaa) && eaa._name == propertyStr )
);
if ( propertyInfo == null ) return false;
propertyInfo.SetValue(o, value, System.Reflection.BindingFlags.SetProperty, null, null, null);
return true;
}
catch ( System.Exception e ) {
System.Console.WriteLine( $"Could not set property with attribute {e} {e.StackTrace}" );
return false;
}
}
public static object? TryToGetPropertyWithAttribute<T>( this T o, string propertyStr ) where T : Object {
try {
var propertyInfo = typeof(T)
.GetProperties()
.Where( p => System.Attribute.IsDefined(p, typeof(ExportAsAttribute)) )
.FirstOrDefault( p => p
.GetCustomAttributes(true)
.Any( a => (a is ExportAsAttribute eaa) && eaa._name == propertyStr )
);
if ( propertyInfo == null ) return null;
return propertyInfo.GetValue(o, System.Reflection.BindingFlags.GetProperty, null, null, null);
}
catch ( System.Exception e ) {
System.Console.WriteLine( $"Could not get property with attribute {e} {e.StackTrace}" );
return null;
}
}
}
}
// EXAMPLE USAGE:
// [ExportAs("display/style", Variant.Type.Object, PropertyHint.ResourceType, "StyleBox")]
// public StyleBox? Style {
// get => _style;
// set {
// _style = value;
// _updatePadding(); QueueSort();
// }
// }
// private StyleBox? _style;
//
// // NOTE: you will want to wrap code in a try-catch right now.
// // [Tool] mode will crash on exceptions otherwise.
// public override Godot.Collections.Array _GetPropertyList() {
// try {
// return new Godot.Collections.Array( this.GetPropertyListFromAttributes() );
// } catch ( Exception e ) {
// System.Console.WriteLine( $"[{nameof(MyClass)}] _GetPropertyList Exception: {e}\n{e.StackTrace}" );
// throw;
// }
// }
//
// public override bool _Set(string propertyStr, object value) {
// try {
// return this.TryToSetPropertyWithAttribute( propertyStr, value );
// } catch ( Exception e ) {
// Console.WriteLine( $"[{nameof(MyClass)}] _Set Exception: {e}\n{e.StackTrace}" );
// return false;
// }
// }
//
// public override object? _Get(string propertyStr) {
// try {
// return this.TryToGetPropertyWithAttribute( propertyStr );
// } catch ( Exception e ) {
// Console.WriteLine( $"[{nameof(MyClass)}] _Get Exception: {e}\n{e.StackTrace}" );
// return null;
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment