FloSoft.AnimationTreeGen 1.0.0

dotnet add package FloSoft.AnimationTreeGen --version 1.0.0
                    
NuGet\Install-Package FloSoft.AnimationTreeGen -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FloSoft.AnimationTreeGen" Version="1.0.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FloSoft.AnimationTreeGen" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FloSoft.AnimationTreeGen">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FloSoft.AnimationTreeGen --version 1.0.0
                    
#r "nuget: FloSoft.AnimationTreeGen, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FloSoft.AnimationTreeGen@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FloSoft.AnimationTreeGen&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FloSoft.AnimationTreeGen&version=1.0.0
                    
Install as a Cake Tool

FloSoft.AnimationTreeGen

Roslyn source generator that emits typed StringName constants and state enums for Godot AnimationTree parameter paths.

Replaces brittle code like:

_tree.Set("parameters/StanceSelector/transition_request", $"{stance}_{weapon}");

with:

_tree.Set(Anim.StanceSelector.TransitionRequest, ...);

Typos in parameter paths or state names become compile errors instead of silent runtime failures.

Install

Published on nuget.org.

dotnet add package FloSoft.AnimationTreeGen

or in your .csproj:

<PackageReference Include="FloSoft.AnimationTreeGen" Version="1.0.0" />

The package is analyzer-only (no runtime DLL — the [AnimationTree] attribute is injected as internal source into your assembly by the generator itself, via RegisterPostInitializationOutput). Marked developmentDependency so it doesn't flow transitively to projects that depend on yours; no extra asset attributes are required.

For each .tres or .tscn you want to bind, register it as an AdditionalFile:

<ItemGroup>
  <AdditionalFiles Include="character/character_tree.tres" />
  <AdditionalFiles Include="scene/character_scene.tscn" />
</ItemGroup>

Minimal example

Note: you need to add the [TreeBind("res://some/path/to/tree.tres")] attribute AND make your class partial so the generator can extend it.

using Godot;
using FloSoft.AnimationTreeGen;

[TreeBind("res://character/character_tree.tres")]
public partial class Character : Node3D
{
    public void GoArmed()
    {
        var tree = GetNode<AnimationTree>("AnimationTree");
        tree.Set(
            Anim.ArmedToggle.TransitionRequest,
            Anim.ArmedToggle.StateNames.Armed);  // literal Godot value, typo-safe
    }
}

Binding an AnimationTree embedded in a .tscn

You can also point at a scene file directly:

[TreeBind("res://scene/character.tscn")]                          // auto-pick when there's one AnimationTree node
public partial class Character : Node3D { ... }

[TreeBind("res://scene/character.tscn", Node = "BodyTree")]       // disambiguate when there are several
public partial class BodyAnim { ... }

[TreeBind("res://scene/character.tscn", Node = "FaceTree")]
public partial class FaceAnim { ... }

If the scene contains exactly one [node type="AnimationTree" ...], the Node = "..." argument is optional. With multiple AnimationTree nodes, omitting it raises ATG006 and the generator lists the available names.

Generated shape

The generator emits a nested Anim static class — one nested type per named node in the BlendTree:

public static class Anim
{
    public static class ArmedToggle
    {
        public const string TransitionRequest = "parameters/ArmedToggle/transition_request";
        public const string CurrentState      = "parameters/ArmedToggle/current_state";
        public const string CurrentIndex      = "parameters/ArmedToggle/current_index";

        // Both shapes are emitted for Transition states — pick whichever fits the call site.
        public enum States { Unarmed, Armed }
        public static class StateNames
        {
            public const string Unarmed = "unarmed";
            public const string Armed   = "armed";
        }
    }
    // ... one nested class per named node
}

Generated members are const string rather than StringName fields — Godot's AnimationTree.Set(...) accepts either, and const string has zero runtime initialization (the compiler inlines the literal at every call site, and there's no Godot.* type referenced anywhere in the generated code). Trade-off: each call allocates a fresh StringName via implicit conversion — negligible for typical state-change calls; cache locally if you have a hot per-frame loop.

Use States (the enum) for typed method signatures, switch expressions, and anywhere C# can statically check the value. Use StateNames for tree.Set(...) / Get(...) calls that ultimately need the literal Godot string — the value matches what was declared in the .tres/.tscn input_<N>/name field exactly, including casing.

Supported nodes

Godot type Emitted members
AnimationNodeTransition TransitionRequest, CurrentState, CurrentIndex, plus States enum and StateNames const-string class from input_<N>/name
AnimationNodeBlend2, Blend3 BlendAmount
AnimationNodeAdd2, Add3 AddAmount
AnimationNodeOneShot Request, Active, InternalActive
AnimationNodeTimeScale Scale
AnimationNodeAnimation Animation — the node's design-time animation key (e.g. for AnimationPlayer.Play(...)), not a runtime parameter path

Tree shape supported in v1: AnimationTree.tree_root = AnimationNodeBlendTree with the children above. Nodes whose type isn't on this list are skipped with an ATG004 warning so the rest of the tree still generates.

Diagnostics

ID Severity Meaning
ATG001 Error Referenced .tres/.tscn is not in <AdditionalFiles>
ATG002 Error .tres/.tscn parse failure
ATG003 Error tree_root is missing or not an AnimationNodeBlendTree
ATG004 Warning Child node has unsupported AnimationNode type, skipped
ATG005 Warning Decorated class is not declared partial
ATG006 Error Scene contains multiple AnimationTree nodes; Node = "..." required
ATG007 Error Specified AnimationTree node not found in scene

Not yet supported in v1

Deferred (PRs welcome):

  • AnimationNodeStateMachine as tree_root
  • Nested BlendTrees
  • BlendSpace1D / BlendSpace2D
  • ExtResource (external) tree roots

Edge cases that currently fall through to a normal C# compile error:

  • Generic decorated classes
  • Nested decorated classes
  • Decorated class names that shadow C# keywords
  • Duplicate node-name or state-name collisions after identifier sanitization

Adding a new node type

The supported-nodes table is data, not code:

  1. Add a NodeTypeDescriptor entry to src/FloSoft.AnimationTreeGen/Mapping/NodeParameterMap.cs — Godot type name, parameter name pairs, and the HasStates flag.
  2. Add a hand-crafted .tres fixture under tests/FloSoft.AnimationTreeGen.Tests/Fixtures/ exercising the new type as a child of a BlendTree.
  3. Add an [InlineData] row to the existing [Theory] in NodeParameterMapTests, plus an emitter test if the output shape is novel.
  4. If you also added a new diagnostic, append it to src/FloSoft.AnimationTreeGen/AnalyzerReleases.Unshipped.md.

Then dotnet test.

Local development

# Unit tests
dotnet test tests/FloSoft.AnimationTreeGen.Tests

# End-to-end: verify the generator output compiles in real consumers
dotnet build samples/SampleConsumer       # .tres binding
dotnet build samples/SceneConsumer        # .tscn binding

# Produce a local nupkg, then verify it installs cleanly
dotnet pack src/FloSoft.AnimationTreeGen -c Release -o nupkgs
dotnet build samples/PackagedConsumer

samples/PackagedConsumer/ consumes the local nupkg from nupkgs/ via a project-local NuGet.config, so re-packing and rebuilding it is a fast end-to-end check. It's deliberately not part of solution-wide flows (dotnet build/dotnet test against the .sln would fail with NU1301 on a fresh clone, since nupkgs/ doesn't exist yet) — always invoke it explicitly after a dotnet pack.

Repo layout

src/FloSoft.AnimationTreeGen/             ← the source generator (netstandard2.0); also injects the [AnimationTree] attribute
tests/FloSoft.AnimationTreeGen.Tests/     ← parser + model + emitter + generator tests (net9.0)
samples/SampleConsumer/                 ← .tres binding via ProjectReference (fast iteration)
samples/SceneConsumer/                  ← .tscn binding with two AnimationTree nodes + Node = "..." disambiguation
samples/PackagedConsumer/               ← consumes the local nupkg (shipping verification)
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 131 5/31/2026