Godot.Sharp.Extended/SceneGenerator.cs
2025-09-26 03:13:44 -05:00

64 lines
No EOL
2.2 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
namespace Godot.Sharp.Extended.Generators;
[Generator]
public class SceneGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var scenes = context.AdditionalTextsProvider
.Where(text => text.Path.EndsWith(".tscn"));
context.RegisterSourceOutput(
context.CompilationProvider.Combine(scenes.Collect()).Combine(context.AnalyzerConfigOptionsProvider),
(ctx, t) => GenerateCode(ctx, t.Left.Left, t.Left.Right, t.Right));
}
private void GenerateCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<AdditionalText> scenes,
AnalyzerConfigOptionsProvider optionsProvider)
{
optionsProvider.GlobalOptions.TryGetValue("build_property.projectdir", out var projectDirectory);
var allMethods = new StringBuilder();
foreach (var scene in scenes)
{
var directory = Path.GetDirectoryName(scene.Path);
var name = Path.GetFileNameWithoutExtension(scene.Path);
var relativePath = scene.Path.Replace(projectDirectory ?? "", "").Replace("\\", "/");
allMethods.AppendLine(
$$"""
public static T New{{name.ToPascalCase()}}<T>() where T : Node {
var packedScene = GD.Load<PackedScene>("res://{{relativePath}}");
return packedScene.Instance<T>();
}
""");
var code =
$$"""
// <auto-generated />
using System;
using Godot;
namespace Godot.Sharp.Extended;
public class Scenes
{
{{allMethods}}
}
""";
context.AddSource("Godot.Sharp.Extended.Scenes.g.cs", SourceText.From(code, Encoding.UTF8));
}
}
}