Skip to content

Instantly share code, notes, and snippets.

@pohy
Created Feb 21, 2020
Embed
What would you like to do?
Godot Subnode attribute
class Player : KinematicBody
{
[Subnode] private Spatial MyNode; // finds subnode called "MyNode" which is a Spatial, crash if not found
[Subnode("custom_name")] private Label MyLabel; // finds a Label called "custom_name"
public override void _Ready()
{
this.FindSubnodes(); // Must write `this.` because it's an extension class
}
}
using System;
using System.Reflection;
using Godot.Collections;
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
class SubnodeAttribute : System.Attribute
{
public string NodePath { get; private set; }
public SubnodeAttribute(string nodePath = null)
{
NodePath = nodePath;
}
}
public static class NodeExtensions
{
public static void FindSubnodes(this Godot.Node node)
{
foreach (PropertyInfo prop in node.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
SubnodeAttribute Subnode = (SubnodeAttribute)Attribute.GetCustomAttribute(prop, typeof(SubnodeAttribute));
if (Subnode != null)
{
string nodePath = Subnode.NodePath == null ? prop.Name : Subnode.NodePath;
var subnode = node.GetNode(nodePath);
prop.SetValue(node, subnode);
}
}
foreach (FieldInfo field in node.GetType().GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
SubnodeAttribute Subnode = (SubnodeAttribute)Attribute.GetCustomAttribute(field, typeof(SubnodeAttribute));
if (Subnode != null)
{
string nodePath = Subnode.NodePath == null ? field.Name : Subnode.NodePath;
var subnode = node.GetNode(nodePath);
field.SetValue(node, subnode);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment