namespace GodotHelpers; using System; using System.Collections.Generic; using System.Linq; using Godot; using Godot.Collections; using Array = Godot.Collections.Array; /// /// Strong‑typed view of Godot's get_method_list / get_property_list output. /// public static class Reflector { /* ──────────── Typed records ──────────── */ public readonly record struct ArgInfo( string Name, Variant.Type Type, PropertyHint Hint, string HintString, Variant DefaultValue); public readonly record struct MethodInfoEx( string Name, IReadOnlyList Args, IReadOnlyList DefaultArgs, MethodFlags Flags, int Id, ArgInfo? ReturnValue); public readonly record struct PropertyInfoEx( string Name, string ClassName, Variant.Type Type, PropertyHint Hint, string HintString, PropertyUsageFlags Usage); /* ──────────── Public helpers ──────────── */ public static List GetMethodsListEx(this GodotObject godotObject) => GetMethods(godotObject); public static List GetMethods(GodotObject obj) { var raw = obj.GetMethodList(); var list = new List(raw.Count); foreach (Dictionary dict in raw) { // — Parse args — var argsRaw = (Array)dict["args"]; var args = new List(argsRaw.Count); foreach (Dictionary a in argsRaw) args.Add(ParseArg(a)); // — Parse return (may be empty) — ArgInfo? ret = null; if (dict.TryGetValue("return", out var retRaw) && retRaw.AsGodotDictionary() is Dictionary rd && rd.Count > 0) ret = ParseArg(rd); list.Add(new MethodInfoEx( Name: (string)dict["name"], Args: args, DefaultArgs: (Array)dict["default_args"], Flags: (MethodFlags)(int)dict["flags"], Id: (int)dict["id"], ReturnValue: ret )); } return list; } public static bool TryGetMethodInfo(this GodotObject godotObject, string property, out MethodInfoEx info) { foreach (var item in GetMethods(godotObject)) { if (item.Name == property) { info = item; return true; } } info = default; return false; } public static List GetPropertyListEx(this GodotObject godotObject) => GetProperties(godotObject); public static List GetProperties(GodotObject obj) { var raw = obj.GetPropertyList(); var list = new List(raw.Count); foreach (Dictionary dict in raw) { list.Add(new PropertyInfoEx( Name: (string)dict["name"], ClassName: (string)dict["class_name"], Type: (Variant.Type)(int)dict["type"], Hint: (PropertyHint)(int)dict["hint"], HintString: (string)dict["hint_string"], Usage: (PropertyUsageFlags)(int)dict["usage"] )); } return list; } public static PropertyInfoEx GetProperty(this IEnumerable properties, string name) => properties.FirstOrDefault(item => item.Name == name); public static bool TryGetPropertyInfo(this GodotObject godotObject, string property, out PropertyInfoEx info) { foreach (var item in GetProperties(godotObject)) { if (item.Name == property) { info = item; return true; } } info = default; return false; } /* ──────────── Internals ──────────── */ private static ArgInfo ParseArg(Dictionary d) => new( Name: (string)d["name"], Type: (Variant.Type)(int)d["type"], Hint: (PropertyHint)(int)d["hint"], HintString: (string)d["hint_string"], DefaultValue: d.TryGetValue("default_value", out var dv) ? dv : default); }