///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // D E R E L I C T // /// // (c) 2003..2024 #nullable enable using Godot; //using Microsoft.CodeAnalysis.CSharp.Syntax; using Godot.Collections; using System; using System.Collections.Generic; using sr = System.Reflection; using gb = Godot.Bridge; using System.Collections.Immutable; using System.Reflection; using System.Collections; public readonly struct PropertyInfo_Test { public Variant.Type Type { get; init; } public StringName Name { get; init; } public PropertyHint Hint { get; init; } public string HintString { get; init; } public PropertyUsageFlags Usage { get; init; } public StringName? ClassName { get; init; } public bool Exported { get; init; } } //[GlobalClass] public partial class POD : GodotObject where T : io.Obj, new() { static public gb.PropertyInfo GetPropertyInfo( Type type, string name ) { var gt = Util.CSTypeCodeToGodotVariantType( Type.GetTypeCode( type ) ); var propHint = type.IsEnum ? PropertyHint.Enum : PropertyHint.None; var propString = type.IsEnum ? U.EnumHintString( type ) : ""; gb.PropertyInfo info = new( gt, name, propHint, propString, PropertyUsageFlags.Default, true ); return info; } #if DOCUMENTATION public MethodInfo( StringName name, PropertyInfo returnVal, MethodFlags flags, List? arguments, List? defaultArguments) #endif /* static public List GetGodotMethodList() { return PODEnergyCom.GetGodotMethodList(); } */ //* static public List GetGodotMethodList_bad() { List methods = new(); var podType = typeof( POD ); var methodsArr = podType.GetMethods( sr.BindingFlags.DeclaredOnly | sr.BindingFlags.Public | sr.BindingFlags.NonPublic ); foreach( var mi in methodsArr ) { var retInfo = GetPropertyInfo( mi.ReturnType, "return" ); List argsInfo = new(); foreach( var pi in mi.GetParameters() ) { //sr.ParameterInfo; GetPropertyInfo( pi.ParameterType, pi.Name! ); } gb.MethodInfo gmi = new() { Name = mi.Name, Flags = MethodFlags.Default, ReturnVal = retInfo, Arguments = argsInfo }; methods.Add( gmi ); } //methods.AddRange( methodsArr ); return methods; } // */ /* public gb.PropertyInfo ReturnVal { get; init; } public MethodFlags Flags { get; init; } public int Id { get; init; } public List? Arguments { get; init; } public List? DefaultArguments { get; init; } */ private T _pod; public T Pod { get => _pod; set { _pod = value; } } #nullable disable public POD() { Pod = new T(); } #nullable enable public POD( T in_pod ) { _pod = in_pod; } public Type GetPODType() { return typeof( T ); } ImmutableDictionary _properties = ImmutableDictionary.Empty; //* public override Variant _Get( StringName property ) { var dbgName = property.ToString(); var prop = base._Get( property ); log.info( cat: "pod", msg: $"{GetType().Name}._Get: {dbgName} = {prop}" ); if( property == "script" && prop.VariantType == Variant.Type.Nil ) { prop = Variant.CreateFrom( new StringName( $"{log.thisFilePath()}" ) ); } else { //Skip this } if( _properties.TryGetValue( property, out var fi ) ) { var val = fi.GetValue( _pod ); var variant = Util.Convert( val?.GetType(), val ); return variant; } return prop; } //*/ public override void _Notification( int what ) => base._Notification( what ); //* public override Array _GetPropertyList() { var other = base._GetPropertyList(); if( other == null ) { other = new(); } log.info( cat: "pod", msg: $"{GetType().Name} _GetPropertyList" ); var type = GetPODType(); var fields = refl.GetAllFields( type ); foreach( var fi in fields ) { var tc = Type.GetTypeCode( fi.FieldType ); var gt = Util.CSTypeCodeToGodotVariantType( tc ); var isEnumerable = fi.FieldType.IsAssignableTo( typeof( IEnumerable ) ); var genericCount = fi.FieldType.GenericTypeArguments.Length; if( isEnumerable && genericCount != 1 ) continue; var sn = new StringName( $"{refl.PrettyName( fi )}" ); var usage = PropertyUsageFlags.Default; var hint = !fi.FieldType.IsEnum ? PropertyHint.None : PropertyHint.Enum; var hintStr = !fi.FieldType.IsEnum ? "" : U.EnumHintString( fi.FieldType ); if( typeof( T ).Name == "Com" ) { if( fi.FieldType.Name == "ComType" ) usage |= PropertyUsageFlags.ReadOnly; } if( isEnumerable ) { hint = PropertyHint.ArrayType; hintStr = "Object"; gt = Util.ConvertMarshalTypeToVariantType( typeof( IEnumerable ) ); } if( gt == Variant.Type.Nil ) continue; //usage |= PropertyUsageFlags.ReadOnly; var dict = U.MakeProperty( this.GetType(), sn, gt, hint: hint, hintString: hintStr ); /* (new Godot.Collections.Dictionary() { { "name", sn }, { "type", (int)gt }, { "usage", (int)usage }, //{ "hint", } //{ "hint_string", $"Version {pod.Meta.Version} Reason {pod.Meta.Reason}" }, }); */ _properties = _properties.Add( sn, fi ); //dict[sn] = (long)gt; log.info( cat: "pod", msg: $"{GetType().Name} PropList: Add {sn} type {gt} tc {tc}" ); other.Add( dict ); } return other; } //*/ public override bool _PropertyCanRevert( StringName property ) => base._PropertyCanRevert( property ); public override Variant _PropertyGetRevert( StringName property ) => base._PropertyGetRevert( property ); public override bool _Set( StringName property, Variant value ) { return base._Set( property, value ); } public override void _ValidateProperty( Dictionary property ) => base._ValidateProperty( property ); public override bool Equals( object? obj ) => base.Equals( obj ); public override int GetHashCode() => base.GetHashCode(); public override string ToString() => base.ToString(); }