GodotSharp.SourceGenerators

repository·main·Indexed 43 days ago

https://github.com/cat-lips/godotsharp.sourcegenerators

A collection of C# Source Generators for the Godot Engine designed to reduce boilerplate and provide strongly typed access to SceneTrees, InputMaps, AudioBuses, Shaders, and other engine features. Supports Godot 3 and 4 depending on the version (1.x for Godot 3, 2.x for both, 3.x for Godot 4). Features include attributes like [SceneTree] for node hierarchy access, [AutoEnum] for string conversions, and [Notify] for property change events.

Tokens
7.4K
Snippets
23
Records
25
Agent score
6%

What's inside GodotSharp.SourceGenerators

  1. Overview of GodotSharp.SourceGenerators features

    main

    GodotSharp.SourceGenerators provides a wide array of attributes to automate boilerplate and provide strongly typed access to Godot engine features.

    Core Feature Categories:

    Scene & Node Management

    • [SceneTree]: Strongly typed access to the scene hierarchy and uniquely named nodes.
    • [Instantiable]: Generates static methods to instantiate scenes (GD4).
    • [OnInstantiate]: Generates a static Instantiate method that calls an attributed method during instantiation (Note: being replaced by [Instantiable]).
    • [Singleton]: Provides single instance access to data or scene objects (GD4).

    Engine Configuration Access (GD4 focus)

    • [AnimNames]: Strongly typed access to animation names in .tres and .tscn files.
    • [AudioBus]: Strongly typed access to audio bus names and IDs.
    • [Autoload]: Strongly typed access to autoload nodes defined in godot.project.
    • [GlobalGroups]: Strongly typed access to global groups defined in godot.project.
    • [InputMap]: Strongly typed access to input actions defined in godot.project.
    • [LayerNames]: Strongly typed access to layer names defined in godot.project.
    • [ShaderGlobals]: Strongly typed access to global shader uniforms.
    • [TR]: Strongly typed access to translation locales and keys from CSV files.

    Data & Logic Automation

    • [AutoEnum]: Generates efficient Str/Parse for enums or enums for static data classes.
    • [CodeComments]: Provides a nested static class to access property comments (useful for tooltips).
    • [Notify]: Generates boilerplate to trigger logic only when property values change.
    • [GodotOverride]: Allows using On* methods instead of virtual _* overrides (requires partial methods in GD4).
    • [Rpc]: Provides strongly typed access to Rpc and RpcId methods.
    • [Shader]: Strongly typed access to shader uniforms or visual shader parameters.
    • [ResourceTree]: Strongly typed access to the resource hierarchy (GD4).
  2. Use `SceneTree` for strongly typed scene hierarchy access

    main

    The [SceneTree] attribute provides strongly typed access to your scene's node hierarchy. It generates properties for uniquely named nodes and allows you to navigate the tree using the _ operator. Nodes are cached on first access to minimize interop overhead.

    Key Features:

    • _ Operator: Use _ to start a path traversal (e.g., _.Node1.Node2).
    • Unique Names: Nodes marked with a unique name in the Godot editor can be accessed directly as class properties.
    • Leaf Nodes: Only leaf nodes are returned as Godot types. For branch nodes, call .Get() to retrieve the node or use implicit conversion.
    • GD4 Interfaces: Generates ISceneTree.TscnFilePath for static path retrieval and IInstantiable for easy instantiation.

    Attribute Options:

    • tscnRelativeToClassPath: Specify the .tscn path relative to the class (default: null).
    • traverseInstancedScenes: Include instanced scenes in the generated hierarchy (default: false).
    • root: Provide an alternative to the _ operator (e.g., [SceneTree(root: "ME")]).
    • uqScope: Specify the default scope for uniquely named nodes (default: Scope.Public).
    [SceneTree]
    public partial class MyScene : Node
    {
        private partial MyNodeType MyNodeWithUniqueName { get; }
    
        public override void _Ready() 
        {
            // Access via '_' operator
            GD.Print(_.Node1.Node11.Node12);
    
            // Direct access to unique nodes
            GD.Print(MyNodeWithUniqueName);
            
            // Accessing branch nodes via .Get()
            GD.Print(_.Node1.Get().Name);
        }
    }
  3. Install GodotSharp.SourceGenerators via NuGet

    main

    To use these C# Source Generators in your Godot project, install the package via NuGet.

    Compatibility Note:

    • Version 1.x: Supports Godot 3 only.
    • Version 2.x: Supports Godot 3 & 4.
    • Version 3.x: Will support Godot 4 only.
    # Install via NuGet
    nuget install GodotSharp.SourceGenerators
  4. Use CodeComments for localized string translation

    main

    The CodeComments feature allows you to generate type-safe, localized string accessors based on your translation keys. You can manage the active locale globally for different translation contexts (like TrKeys, TrPlurals, or custom TrContext classes) to ensure the correct language is returned at runtime.

    To use it, set the Locale property on the relevant static class before calling the generated translation methods.

    // Set the locale for general keys
    TrKeys.Locale = TrKeys.Loc.Ja;
    var greet = TrKeys.TrGreet(); // Returns Japanese greeting
    
    // Set the locale for pluralized strings
    TrPlurals.Locale = TrPlurals.Loc.Ja;
    var apples = TrPlurals.TrThereAreApples(0); // Returns Japanese plural string
    
    // Set the locale for a custom translation context
    TrContext.Locale = TrContext.Loc.Ja;
    var msgLetter = TrContext.TrMessageLetter(); // Returns Japanese translation
    var alpLetter = TrContext.TrAlphabetLetter(); // Returns Japanese translation
  5. Breaking changes in version 2.7.0

    main

    If you are upgrading to version 2.7.0, be aware of the following breaking changes:

    1. Scope Strings: Scope strings have been replaced with a more definitive enum set.
    2. Autoloads: The Autoload class must now be explicitly decorated instead of being implicitly generated.
    3. Unicode Identifiers: Identifiers comprised of unicode characters no longer require a _ prefix. Other invalid characters are now removed instead of being replaced with _.
  6. Instantiate scenes safely with `[Instantiate]`

    main

    The [Instantiate] class attribute generates static methods to instantiate scenes and ensures they are initialized correctly via a constructor or an init method.

    Options:

    • init: (default 'Init') The name of the initialization function to call after instantiation.
    • name: (default 'New') The name of the static instantiation function.
    • ctor: (default 'Protected') The scope of the generated constructor ('None' to skip generation).

    This is the recommended way to handle scene instantiation when your scenes require specific setup parameters.

    // Simple instantiation
    [Instantiate]
    public partial class Scene1 : Node {}
    
    // Instantiation with a custom init method
    [Instantiate]
    public partial class Scene2 : Node
    {
        private void Init(int arg) {}
    }
    
    // Full customization
    [Instantiate(nameof(Initialise), "Instantiate", "private")]
    public partial class Scene3 : Node
    {
        private void Initialise(int arg1, string arg2, object arg3 = null) {}
    }
  7. Use the [Shader] attribute for strongly typed ShaderMaterials

    main

    Decorate a ShaderMaterial class with the [Shader] attribute to generate strongly typed access to shader uniforms. This eliminates the need for manual GetShaderParameter and SetShaderParameter calls using StringName keys.

    Key Features:

    • Automatic Loading: Generates a LoadShader() method and handles shader assignment in the constructor.
    • Default Values: Generates a Default static class containing the default values for all uniforms.
    • Typed Properties: Converts shader uniforms into C# properties with appropriate types (e.g., int, float, Color).
    • Reset Method: Provides a Reset() method to revert all parameters to their default values.
    [Shader]
    //[Shader("Shaders/my_shader")] // Optional: specify relative or absolute path
    public partial class MyShader : ShaderMaterial;
  8. Generate enums and conversions with `AutoEnum`

    main

    The [AutoEnum] attribute automates the creation of string parsing and enum conversions for both standard enums and data-carrying classes.

    1. For Enums: Decorating an enum generates extension methods for string conversion:

    • e.Str(): Converts an enum value to its string name.
    • MapTypeStr.Parse(string): Parses a string back into the enum type.

    2. For Classes: Decorating a partial class (used as a data container) generates:

    • An internal enum Enum representing the static members.
    • instance.ToEnum(): Converts the class instance to its corresponding enum.
    • MapData.FromEnum(e): Converts an enum back to the class instance.
    • instance.ToStr(): Converts the instance to a string.
    • MapData.FromStr(string): Parses a string into the class instance.
    // Enum usage
    [AutoEnum]
    public enum MapType { City, Corridor }
    var s = MapType.City.Str();
    var e = MapTypeStr.Parse(s);
    
    // Class usage
    [AutoEnum]
    public partial class MapData {
        public static readonly MapData City = new();
    }
    var e = MapData.City.ToEnum();
    var d = MapData.FromEnum(e);
  9. Instantiate scenes using `IInstantiable` (GD4 only)

    main

    In Godot 4, classes decorated with [SceneTree] can implement IInstantiable to provide a streamlined way to instantiate scenes using their TscnFilePath.

    Available Methods:

    • Instantiator.Instantiate<T>(): A static helper that works for any type implementing ISceneTree.
    • IInstantiable.Instantiate<T>(): Non-generic interface method to instantiate any ISceneTree type.
    • IInstantiable<T>.Instantiate(): Generic interface method that can only instantiate its own type T.
    [SceneTree]
    public partial class Scene1 : Node;
    
    [SceneTree]
    public partial class Scene2 : Node, IInstantiable;
    
    [SceneTree]
    public partial class Scene3 : Node, IInstantiable<Scene3>;
    
    // Usage
    var s1 = Instantiator.Instantiate<Scene1>();
    var s2 = Instantiator.Instantiate<Scene2>();
    var s3 = IInstantiable<Scene3>.Instantiate();
  10. Generate property events with `[Notify]`

    main

    The [Notify] property attribute automatically generates ValueChanging and ValueChanged events for a property.

    Key Features:

    • Automatic Triggering: Events are only triggered if the new value is different from the current value.
    • Nested Changes: Automatically triggers nested changes for Resource and Resource[].
    • Event Control: You can pause events using PauseValueEvents = true.
    • Initialization: You can set initial values in a constructor using an InitValue method to avoid triggering events during setup.

    Performance Note: To avoid heap allocations when using custom struct types, ensure your struct implements IEquatable<T>. If it does not, the struct will be boxed to object? during the equality check, causing a memory allocation every time the property is set.

    public partial class NotifyTest : Node
    {
        // Recommended: Requires C# 14 and <LangVersion>14</LangVersion>
        [Notify] public partial int Value { get; set; } = 7;
    
        public override void _Ready()
        {
            ValueChanging += () => GD.Print($"Value is about to change from {Value}");
            ValueChanged += () => GD.Print($"Value has been changed to {Value}");
    
            Value = 1; // Raises events
            Value = 1; // No events raised (value is same)
        }
    }
  11. Use `[OnInstantiate]` for method-based instantiation

    main

    The [OnInstantiate] method attribute generates a static Instantiate method that calls the attributed method as part of the instantiation process. This is useful for specific method-based initialization.

    Note: This is a more granular alternative to the [Instantiate] class attribute. If you want to control the constructor scope or use a more robust pattern, use [Instantiate] on the class instead.

    Options:

    • ctor: (default 'Protected') The scope of the generated constructor.
    • bool (passed as a flag): If you pass a boolean instead of a scope, it acts as a flag to use all overrides.
    public partial class MyScene : Node
    {
        [OnInstantiate]
        private void Initialise(string myArg1, int myArg2)
            => GD.PrintS("Init", myArg1, myArg2);
    }
  12. Use the [Singleton] attribute for easy access to data or scenes

    main

    The [Singleton] attribute provides a static Instance property for accessing a single instance of a class or a scene object. The instance is created statically on first use.

    Patterns:

    • Pure Data/Logic: Use [Singleton] on a class (e.g., public partial class MyData;).
    • Node Singletons: Use [Singleton] on a Node class. If you have an Init() method, the generator will automatically call it during instantiation.
    • Scene Singletons: Use [Singleton] on a class representing a .tscn file. The generator will look for a .tscn file with the same name in the same folder and instantiate it.

    Advanced Options:

    • init: Override the name of the initialization function (defaults to 'Init').

    Example with custom Init and Scene:

    [Singleton(nameof(InitScene))] // Looks for InitScene() and a matching .tscn
    public partial class MyScene : Node
    {
        private void InitScene() { /* ... */ }
    }
    [Singleton]
    public partial class MyData;
    
    [Singleton]
    public partial class MyNode : Node
    {
        private void Init() { }
    }
    
    [Singleton(nameof(InitScene))]
    public partial class MyScene : Node
    {
        private void InitScene() { }
    }