gd_core/addons/core/misc/POD.cs

301 lines
6.0 KiB
C#

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 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<T> : 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<PropertyInfo>? arguments,
List<Variant>? defaultArguments)
#endif
/*
static public List<gb.MethodInfo> GetGodotMethodList()
{
return PODEnergyCom.GetGodotMethodList();
}
*/
//*
static public List<gb.MethodInfo> GetGodotMethodList_bad()
{
List<gb.MethodInfo> methods = new();
var podType = typeof( POD<T> );
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<gb.PropertyInfo> 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<gb.PropertyInfo>? Arguments { get; init; }
public List<Variant>? 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<StringName, FieldInfo> _properties = ImmutableDictionary<StringName, FieldInfo>.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<Dictionary> _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();
}