Last active
June 3, 2020 23:46
-
-
Save cgbeutler/8c85657bcaaa130aef45d14a677c981f to your computer and use it in GitHub Desktop.
ExportAs Attribute for Godot CSharp Projects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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