From ed1b01f052b6473a05bf239505799bc929bce121 Mon Sep 17 00:00:00 2001 From: hzhang Date: Wed, 5 Feb 2025 15:01:43 +0000 Subject: [PATCH] add: Scene --- AssetRegisterGenerator.cs | 54 +++++++++++++++++++++++++++++++++ GlobalRegistryGenerator.cs | 57 +++++++++++++++++++++++------------ Hangman.SDK.Generators.csproj | 5 ++- 3 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 AssetRegisterGenerator.cs diff --git a/AssetRegisterGenerator.cs b/AssetRegisterGenerator.cs new file mode 100644 index 0000000..c29bf21 --- /dev/null +++ b/AssetRegisterGenerator.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Hangman.SDK.Generators; +[Generator] +public class AssetRegisterGenerator : AssetProcessGenerator +{ + public override void Execute(GeneratorExecutionContext context) + { + if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver)) + return; + Compilation compilation = context.Compilation; + StringBuilder sb = new(); + + sb + .AppendLine("using System;") + .AppendLine("using Godot;") + .AppendLine("using Hangman.SDK.Attributes;") + .AppendLine("[AutoRegister]") + .AppendLine("public static class AssetRegister") + .AppendLine("{") + .AppendLine(" public static void Register()") + .AppendLine(" {"); + foreach (var derivedClassDeclaration in receiver.Classes) + { + SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree); + INamedTypeSymbol? symbol = model.GetDeclaredSymbol(derivedClassDeclaration) as INamedTypeSymbol; + string filePath = derivedClassDeclaration.SyntaxTree.FilePath.Replace(".cs", ".tscn"); + if(!filePath.Contains("Assets") || symbol == null) + continue; + ImmutableArray additionalFiles = context.AdditionalFiles; + if (additionalFiles.Select(y => y.Path).Contains(filePath)) + { + string rs = filePath.Replace("\\", "/").Replace(" ", "%20"); + rs = rs.Substring(rs.IndexOf("Assets", StringComparison.Ordinal)); + string gdPath = "res://" + rs; + string className = Path.GetFileNameWithoutExtension(filePath); + sb + .AppendLine( + $" GlobalRegistry.Asset<{className}>.Scene = ResourceLoader.Load(\"{gdPath}\");" + ); + } + } + + sb + .AppendLine(" }") + .AppendLine("}"); + context.AddSource("AssetRegistry.g.cs", sb.ToString()); + } +} \ No newline at end of file diff --git a/GlobalRegistryGenerator.cs b/GlobalRegistryGenerator.cs index 7417bc6..30b9106 100644 --- a/GlobalRegistryGenerator.cs +++ b/GlobalRegistryGenerator.cs @@ -12,26 +12,43 @@ public class GlobalRegistryGenerator : ISourceGenerator public void Execute(GeneratorExecutionContext context) { StringBuilder sb = new(); - sb.AppendLine("using System;"); - sb.AppendLine("using System.Collections.Generic;"); - sb.AppendLine("using System.Linq;"); - sb.AppendLine("using System.Reflection;"); - sb.AppendLine("using Hangman.SDK.Attributes;"); - sb.AppendLine("public static partial class GlobalRegistry"); - sb.AppendLine("{"); - sb.AppendLine(" public static void Register()"); - sb.AppendLine(" {"); - sb.AppendLine(" Assembly assembly = Assembly.GetEntryAssembly();"); - sb.AppendLine(" IEnumerable registerTypes = assembly.GetTypes()"); - sb.AppendLine(" .Where(t => t.IsClass && t.GetCustomAttributes(typeof(AutoRegister), false).Any());"); - sb.AppendLine(" foreach(Type t in registerTypes)"); - sb.AppendLine(" {"); - sb.AppendLine(" MethodInfo registerMethod = t.GetMethod(\"Register\", BindingFlags.Static | BindingFlags.Public);"); - sb.AppendLine(" if (registerMethod != null)"); - sb.AppendLine(" registerMethod.Invoke(null, null);"); - sb.AppendLine(" }"); - sb.AppendLine(" }"); - sb.AppendLine("}"); + sb + .AppendLine("using Godot;") + .AppendLine("using System;") + .AppendLine("using System.Collections.Generic;") + .AppendLine("using System.Linq;") + .AppendLine("using System.Reflection;") + .AppendLine("using Hangman.SDK.Attributes;") + .AppendLine("using Hangman.SDK;") + .AppendLine("public static partial class GlobalRegistry") + .AppendLine("{") + .AppendLine(" public static void Register()") + .AppendLine(" {") + .AppendLine(" Assembly assembly = Assembly.GetExecutingAssembly();") + .AppendLine(" IEnumerable registerTypes = Utils.GetLoadableTypes(assembly);") + .AppendLine(" registerTypes = registerTypes.Where(t => t.IsClass && t.GetCustomAttributes(typeof(AutoRegister), false).Any());") + .AppendLine(" foreach(Type t in registerTypes)") + .AppendLine(" {") + .AppendLine(" MethodInfo registerMethod = t.GetMethod(\"Register\", BindingFlags.Static | BindingFlags.Public);") + .AppendLine(" if (registerMethod != null)") + .AppendLine(" registerMethod.Invoke(null, null);") + .AppendLine(" }") + .AppendLine(" }") + .AppendLine(" public static class Asset where T : Node") + .AppendLine(" {") + .AppendLine(" private static readonly Queue Pool = new();") + .AppendLine(" public static PackedScene Scene { get; set; }") + .AppendLine(" public static T Instance => Scene.Instantiate();") + .AppendLine(" public static T Get() => Pool.Count > 0 ? Pool.Dequeue() : Instance;") + .AppendLine(" public static void Return(T obj)") + .AppendLine(" {") + .AppendLine(" if(Pool.Count < 10)") + .AppendLine(" Pool.Enqueue(obj);") + .AppendLine(" else") + .AppendLine(" obj.QueueFree();") + .AppendLine(" }") + .AppendLine(" }") + .AppendLine("}"); context.AddSource("GlobalRegistry.g.cs", sb.ToString()); } } \ No newline at end of file diff --git a/Hangman.SDK.Generators.csproj b/Hangman.SDK.Generators.csproj index adec8f8..446af74 100644 --- a/Hangman.SDK.Generators.csproj +++ b/Hangman.SDK.Generators.csproj @@ -2,7 +2,7 @@ netstandard2.0 - false + true enable latest @@ -11,6 +11,9 @@ Hangman.SDK.Generators Hangman.SDK.Generators + true + 0.0.1 + Hangman