LokiCat.Godot.R3.ObservableSignals 1.0.60

There is a newer version of this package available.
See the version list below for details.
dotnet add package LokiCat.Godot.R3.ObservableSignals --version 1.0.60
                    
NuGet\Install-Package LokiCat.Godot.R3.ObservableSignals -Version 1.0.60
                    
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="LokiCat.Godot.R3.ObservableSignals" Version="1.0.60" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LokiCat.Godot.R3.ObservableSignals" Version="1.0.60" />
                    
Directory.Packages.props
<PackageReference Include="LokiCat.Godot.R3.ObservableSignals" />
                    
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 LokiCat.Godot.R3.ObservableSignals --version 1.0.60
                    
#r "nuget: LokiCat.Godot.R3.ObservableSignals, 1.0.60"
                    
#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 LokiCat.Godot.R3.ObservableSignals@1.0.60
                    
#: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=LokiCat.Godot.R3.ObservableSignals&version=1.0.60
                    
Install as a Cake Addin
#tool nuget:?package=LokiCat.Godot.R3.ObservableSignals&version=1.0.60
                    
Install as a Cake Tool

LokiCat.Godot.R3.ObservableSignals

A source generator that turns [Signal]-annotated delegates into fully reactive R3 Observable<T> properties. Supports zero to five signal arguments, [RxProperty] bindings, [InverseSignal] auto-generation, and full Godot editor compatibility.


✨ What It Does

This generator lets you define signals with [Signal] in combination with [RxObservable] or [RxProperty]:

[Signal]
[RxObservable]
public delegate void JumpEventHandler();

💥 And automatically provides:

  • ✅ A backing Subject<T> or RxVar<T>
  • ✅ A public observable or reactive property (OnJump, IsDead, etc.)
  • ✅ Lazy .Subscribe(...) wiring that calls EmitSignal(...) automatically

No need to write Connect(), EmitSignal(), or observable plumbing by hand.


🚀 Quick Start

✅ Define a signal:

[Signal]
[RxObservable]
public delegate void DamageTakenEventHandler(int amount);

✅ Emit it:

_onDamageTaken.OnNext(42);

✅ Observe it:

OnDamageTaken.Subscribe(amount => GD.Print($"Took {amount} damage!"));

🚫 [Signal] alone will not generate code. You must pair it with [RxObservable] or [RxProperty].


🔄 RxProperty Support

Use [RxProperty] to generate a reactive IRxProp<T> that syncs with a signal:

[Signal]
[RxProperty]
public delegate void IsDeadEventHandler(bool isDead);

Generates:

public IRxProp<bool> IsDead => _isDead;
private RxVar<bool> _isDead = new RxVar<bool>(false);
/* And wiring to the Godot signal */

🧠 Naming Rules

The generated property name:

  • Always starts with Is
  • Removes a leading Is only if it's a full word prefix (i.e. Is followed by an uppercase letter)
  • Does not remove Is from words like Island, Isotope, etc.
  • Strips the EventHandler suffix

Examples:

Delegate Name Generated Property Name
IsDeadEventHandler IsDead
DeadEventHandler IsDead
IslandEventHandler IsIsland
IsIslandEventHandler IsIsland
IslandTimeEventHandler IsIslandTime
IsIslandTimeEventHandler IsIslandTime
IsNotNotarizedEventHandler IsNotarized
IsNoteInverselyInverseEventHandler IsNoteInversely

🔁 Inverse Signal Support

Generate inverse signals from a single source:

🗒️ Godot does not support easy transformation of signals. This generator allows you to define a signal and automatically generate its inverse.

💡 TODO: Add more robust signal transformation support via [SignalTransform(<TBD Syntax>)] attribute.

[Signal]
[RxObservable]
public delegate void VisibleEventHandler(bool value);

// inferred from name
[Signal]
[InverseSignal]
public delegate void NotVisibleEventHandler(bool value);

// explicit source:
[Signal]
[InverseSignal(nameof(IsVisibleEventHandler))]
public delegate void HiddenEventHandler(bool value);

✅ Emits EmitSignal("Hidden", !value) when OnIsVisible is triggered. 🚫 Only valid for bool signals 🚫 Cannot be used with [RxProperty]

🔍 Inferred Naming Behavior

When no nameof(...) is used, the generator infers the target by removing the words Not or Inverse only when they are complete words — using word-boundary-aware matching. It does not remove them when embedded in words:

Inverse Name Inferred Target Name
NotVisibleEventHandler VisibleEventHandler
InverseHiddenEventHandler HiddenEventHandler
IsNotNotarizedEventHandler IsNotarizedEventHandler ✅ no strip inside word
IsNoteInverselyInverseEventHandler IsNoteInverselyEventHandler ✅ no strip
IsInvisible InvisibleEventHandler ❗ no automatic mapping to IsVisible

For symmetric relationships (e.g. IsVisible/IsInvisible), use [InverseSignal(nameof(...))] explicitly.


✅ Supported Signal Signatures

Delegate Type Observable Type Emission
delegate void JumpEventHandler() Observable<Unit> EmitSignal("Jump")
delegate void DamageEventHandler(int) Observable<int> EmitSignal("Damage", dmg)
delegate void HitEventHandler(Vector3, Node) Observable<(Vector3, Node)> EmitSignal("Hit", ...)
delegate void IsDeadEventHandler(bool) IRxProp<bool> ([RxProperty]) EmitSignal("IsDead", value)
Attribute Observable Type Parameter Count
[RxProperty] IRxProp<T>,RxVar<T> 0 or 1 (e.g. <Unit> or <T>)
[RxObservable] Observable<int>, Subject<T> 5 (e.g. <T1,T2,T3,T4,T5>
[InverseSignal] N/A 1 bool
delegate void IsDeadEventHandler(bool) IRxProp<bool> ([RxProperty]) EmitSignal("IsDead", value)

Up to 5 parameters are supported.


🚨 Generator Diagnostics

ID Reason
SIGOBS001 Missing R3.Unit for zero-arg signals
SIGOBS002 Signal delegate has more than 5 parameters
SIGOBS003 Manual EmitSignal("X") bypasses observable
SIGOBS004 [InverseSignal] used with [RxProperty] or [RxObservable]
SIGOBS005 More than one [InverseSignal] targets a single signal
SIGOBS009 [RxProperty] and [RxObservable] used together
SIGOBS010 Could not resolve nameof(...) in [InverseSignal]
SIGOBS011 Malformed attribute body in generated code
SOEG0001 Generator is running (informational)

💡 Best Practices

  • ✅ Use _onX.OnNext(...) to emit signals
  • ✅ Subscribe using OnX.Subscribe(...)
  • ⚠️ Do not call EmitSignal(...) manually — it will not notify observers
  • 🧠 Prefer [RxProperty] for stateful values
  • 🔁 Use [InverseSignal] for UI toggles, state flips, or binding inverses

📦 Installation

dotnet add package LokiCat.Godot.R3.ObservableSignals

Also define:

namespace R3 {
  public readonly struct Unit {} // required for 0-arg signals
}

📜 License

MIT License

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • net7.0

    • 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.70 236 7/2/2025
1.0.69 118 6/21/2025
1.0.68 105 6/21/2025
1.0.65 141 6/19/2025
1.0.64 140 6/19/2025
1.0.63 139 6/19/2025
1.0.62 137 6/19/2025
1.0.61 140 6/19/2025
1.0.60 141 6/19/2025
1.0.59 139 6/19/2025
1.0.58 142 6/19/2025
1.0.57 139 6/19/2025
1.0.56 144 6/19/2025
1.0.55 139 6/19/2025
1.0.54 139 6/18/2025
1.0.53 140 6/18/2025
1.0.52 137 6/18/2025
1.0.51 145 6/18/2025
1.0.47 153 6/14/2025
1.0.40 154 6/14/2025
1.0.38 163 6/14/2025
1.0.37 138 5/9/2025
1.0.36 81 5/9/2025
1.0.35 81 5/9/2025
1.0.34 82 5/9/2025
1.0.33 146 5/8/2025
1.0.32 146 5/8/2025
1.0.31 146 5/1/2025
1.0.30 152 5/1/2025
1.0.29 151 5/1/2025
1.0.28 150 4/30/2025
1.0.26 147 4/30/2025
1.0.25 146 4/30/2025
1.0.24 144 4/30/2025
1.0.23 152 4/30/2025
1.0.22 150 4/30/2025
1.0.21 142 4/30/2025
1.0.20 146 4/30/2025
1.0.19 142 4/29/2025
1.0.18 159 4/29/2025
1.0.17 156 4/28/2025
1.0.16 159 4/27/2025
1.0.15 166 4/27/2025
1.0.14 159 4/27/2025
1.0.13 157 4/27/2025
1.0.12 155 4/27/2025
1.0.11 152 4/27/2025
1.0.9 160 4/27/2025
1.0.7 161 4/27/2025
1.0.1 152 4/27/2025
1.0.0 159 4/27/2025
0.0.6 247 4/19/2025
0.0.5 169 4/19/2025