Skip to content

Latest commit

 

History

History
232 lines (176 loc) · 5.34 KB

README.md

File metadata and controls

232 lines (176 loc) · 5.34 KB

GDMechanic

An API designed to streamline C# with Godot Engine without changing any fundamentals. It utilizes cached reflection for optimal performance, and provides power to easily extend the API with your own attributes.

Install Package from NuGet: NuGet

Status

NOTE: Abandoned since I do not use Godot actively anymore, and moved to other projects.

GDMechanic is functionally complete, but a few features are not fully tested.

Most documentation is provided, but extensions are not documented.

GDMechanic was created with Godot 3.1 alpha, and does not work in earlier versions due to namespace changes between 3.0.6 and 3.1 in GodotSharp.

Wiring

GDMechanic provides a set of core attributes for wiring fields, properties, and methods.

Activation

Call this.Wire() in the node's _Ready() method.

public override void _Ready()
{
	this.Wire();
	...
}

It is recommended to create a template for wired nodes, like the below.

using Godot;
using GDMechanic.Wiring;
using GDMechanic.Wiring.Attributes;

public class %CLASS% : %BASE%
{
	
	
	
	public override void _Ready()
	{
		this.Wire();
	}
}

You can place this template in Godot's "script_templates" folder in order for the IDE to pick it up.

Core Attributes

Node

Returns a reference to a node based on the provided node path.

[Node("UI/Score")] private RichTextLabel _scoreText;

Child

Returns a reference to a child based on match type.

[Child] private Player _player;
// or
[Child(Matchtypes.Name)] private Player _player;

[Child(MatchTypes.Type)] private RichTextLabel _score;

Sibling

Returns a reference to a sibling based on match type.

Parent

Returns a reference to the node's parent.

[Parent] private Mommy _mommy;

Group

Adds this node to the specified group.

[Group("Huggables")]
public class Teddy : Node2D
{
	...
}

SignalReceiver

Connects the specified signal from the specified source. The source can either be a node path or a reference from a field on the same node.

[Child] private Button _button2;

[SignalReceiver("Button", "pressed")]
public void OnButtonPressed()
{
	...
}

[SignalReceiver("_button2", "pressed", SourceTypes.Reference)]
public void OnButton2Pressed()
{
	...
}

Timer

Adds a child Timer node with the specified criteria, and assigns a reference to it to the field.

[Timer(nameof(OnTimerTimeout), waitTime: 1.5f, oneShot: true)]
private Timer _timer;
Starting Timer with Custom Wait Time

GDMechanic provides an extension method to Timer that makes it easy to start a timer with a different wait time, without overriding the default.

_timer.Start(6f);

Custom Attributes

You can create your own attributes quite easily. Create a class that extends Attribute and implement IStateWirer, IMethodWirer, or IClassWirer. Also, be sure to add the corresponding attribute targets to the attribute via AttributeUsage.

IStateWirer: AttributeTargets.Field | AttributeTargets.Property

IMethodWirer: AttributeTargets.Method

IClassWirer: AttributeTargets.Class

Then implement the necessary methods. GDMechanic will automatically be able to use it.

Example from NodeAttribute:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class NodeAttribute : MechanicAttribute, IStateWirer
{

	private readonly string _path;

	/// <summary>
	/// Returns a reference to a node based on the provided node path.
	/// </summary>
	/// <param name="path"></param>
	public NodeAttribute(string path) {
		_path = path;
	}

	public void Wire(Node node, CachedNodeStateInfo state)
	{
		state.SetValue(node, node.GetNode(_path));
	}
}

Extensions

GDMechanic provides extension methods for various nodes. Here are some examples.

public static T InstanceToParent<T>(this PackedScene packedScene, Node parent) where T: Node
public static IEnumerable<object> GetNodesOfType<T>(this SceneTree sceneTree) where T : Node
public static void TranslateX(this Node2D node, float xDisplacement)

Rng

Reimplementation of GDScript's "rand" functions. It uses System.Random under the hood, so it will not have the same output as GDScript's "rand" functions.

Rng.RandRange(0f, 6f);

Rng.Chance

Randomly returns true or false, based on the specified ratio.

if (Rng.Chance(0.05f))
{
	GD.Print("Critical hit!");
}

TimerSystem

Node that organizes a collection of timers for easy access through delegates. It is designed to be used with TimerSystemAttribute and TimerReceiverAttribute, although it is fully functional on its own.

[TimerSystem]
private TimerSystem _timerSystem;

public void StartTimer() {
	_timerSystem.Start(OnTimerTimeout);
}
[TimerReceiver(waitTime: 0.25f, oneShot: true)]
public void OnTimerTimeout()
{
	...
}

[TimerReceiver(waitTime: 3f, oneShot: true)]
public void OnDeathTimeout()
{
	...
}

Alternatively you can place TimerReceiverAttribute on the same field as the TimerSystem reference.

[TimerSystem]
[TimerReceiver(nameof(OnTimerTimeout), waitTime: 0.25f, oneShot: true)]
private TimerSystem _timerSystem;

public void StartTimer() {
	_timerSystem.Start(OnTimerTimeout);
}

public void OnTimerTimeout()
{
	...
}

[TimerReceiver(waitTime: 3f, oneShot: true)]
public void OnDeathTimeout()
{
	...
}