diff --git a/Core/Attributes/NodeBindAttribute.cs b/Core/Attributes/NodeBindAttribute.cs
new file mode 100644
index 0000000..5970653
--- /dev/null
+++ b/Core/Attributes/NodeBindAttribute.cs
@@ -0,0 +1,6 @@
+namespace Godot.Sharp.Extended.Attributes;
+
+[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)]
+public class NodeBindAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Core/Attributes/NodeBindPropAttribute.cs b/Core/Attributes/NodeBindPropAttribute.cs
new file mode 100644
index 0000000..c215cce
--- /dev/null
+++ b/Core/Attributes/NodeBindPropAttribute.cs
@@ -0,0 +1,14 @@
+namespace Godot.Sharp.Extended.Attributes;
+
+[System.AttributeUsage(System.AttributeTargets.Field)]
+public class NodePropBindAttribute : System.Attribute
+{
+ public string TargetNodeName { get; private set; }
+ public string GodotPropertyName { get; private set; }
+
+ public NodePropBindAttribute(string targetNodeName, string godotPropertyName)
+ {
+ TargetNodeName = targetNodeName;
+ GodotPropertyName = godotPropertyName;
+ }
+}
\ No newline at end of file
diff --git a/Core/Attributes/ResourcePathAttribute.cs b/Core/Attributes/ResourcePathAttribute.cs
new file mode 100644
index 0000000..347dc67
--- /dev/null
+++ b/Core/Attributes/ResourcePathAttribute.cs
@@ -0,0 +1,11 @@
+namespace Godot.Sharp.Extended.Attributes;
+
+[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)]
+public class ResourcePathAttribute : System.Attribute
+{
+ public string Path { get; private set; }
+
+ public ResourcePathAttribute(string path) {
+ Path = path;
+ }
+}
\ No newline at end of file
diff --git a/Core/Godot.Sharp.Extended.csproj b/Core/Godot.Sharp.Extended.csproj
new file mode 100644
index 0000000..29df43d
--- /dev/null
+++ b/Core/Godot.Sharp.Extended.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net8.0
+ enable
+ enable
+ Godot.Sharp.Extended
+
+
+
+
+
+
+
diff --git a/Core/Tools/MathFunctionExtensions.cs b/Core/Tools/MathFunctionExtensions.cs
new file mode 100644
index 0000000..9fd8cf4
--- /dev/null
+++ b/Core/Tools/MathFunctionExtensions.cs
@@ -0,0 +1,22 @@
+namespace Godot.Sharp.Extended.Tools;
+
+public static partial class MathFunctionExtensions
+{
+ public static bool InRange(this int @this, int min, int max) => @this >= min && @this <= max;
+ public static bool InRange(this float @this, float min, float max) => @this >= min && @this <= max;
+ public static bool InRange(this double @this, double min, double max) => @this >= min && @this <= max;
+ public static bool InRange(this Vector2 @this, Vector2 min, Vector2 max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y);
+ public static bool InRange(this Vector2I @this, Vector2I min, Vector2I max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y);
+ public static bool InRange(this Vector3 @this, Vector3 min, Vector3 max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y) && @this.Z.InRange(min.Z, max.Z);
+ public static bool InRange(this Vector3I @this, Vector3I min, Vector3I max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y) && @this.Z.InRange(min.Z, max.Z);
+ public static bool InRange(this Vector4 @this, Vector4 min, Vector4 max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y) && @this.Z.InRange(min.Z, max.Z) && @this.W.InRange(min.W, max.W);
+ public static bool InRange(this Vector4I @this, Vector4I min, Vector4I max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y) && @this.Z.InRange(min.Z, max.Z) && @this.W.InRange(min.W, max.W);
+ public static bool InRange(this Quaternion @this, Quaternion min, Quaternion max) =>
+ @this.X.InRange(min.X, max.X) && @this.Y.InRange(min.Y, max.Y) && @this.Z.InRange(min.Z, max.Z) && @this.W.InRange(min.W, max.W);
+}
\ No newline at end of file
diff --git a/Core/Tools/NodeExtensions.cs b/Core/Tools/NodeExtensions.cs
new file mode 100644
index 0000000..4ede49d
--- /dev/null
+++ b/Core/Tools/NodeExtensions.cs
@@ -0,0 +1,65 @@
+using Godot.Collections;
+
+namespace Godot.Sharp.Extended.Tools;
+
+public static class NodeExtensions
+{
+ public static void AddToGroup(this Node node) => node.AddToGroup(node.GetType().Name);
+ public static T GetNode(this Node node) where T : Node => node.GetNode(typeof(T).Name);
+ public static Array GetChildrenOfType(this Node node) where T : Node
+ {
+ var children = node.GetChildren();
+
+ return new Array(children.OfType().ToArray());
+ }
+ public static T? GetFirstChildOfType(this Node node) where T : Node => GetChildrenOfType(node).FirstOrDefault();
+
+ public static void RemoveAllChildren(this Node node)
+ {
+ foreach (var child in node.GetChildren())
+ node.RemoveChild(child);
+ }
+
+ public static void RemoveAndQueueFreeChildren(this Node node)
+ {
+ foreach (var child in node.GetChildren())
+ {
+ node.RemoveChild(child);
+ child.QueueFree();
+ }
+ }
+
+ public static void QueueFreeChildren(this Node node)
+ {
+ foreach (var child in node.GetChildren())
+ node.QueueFree();
+ }
+
+ public static T? GetAncestor(this Node node) where T : Node
+ {
+ Node current = node;
+ Node root = node.GetTree().Root;
+ while (current != root && !(current is T))
+ current = current.GetParent();
+
+ return current as T;
+ }
+
+ public static Node? GetLastChild(this Node node)
+ {
+ var count = node.GetChildCount();
+ if (count == 0) return null;
+ return node.GetChild(count - 1);
+ }
+
+ public static T? GetLastChild(this Node node) where T : Node
+ {
+ Node? last = null;
+ foreach (var child in node.GetChildren())
+ {
+ if (child is T) last = child;
+ }
+
+ return last as T;
+ }
+}
\ No newline at end of file