commit 7d823aa78b838cfdf64f971a0f5ed028a495e6bc Author: Tony Bark <35226681+tonytins@users.noreply.github.com> Date: Tue Feb 3 03:00:54 2026 -0500 Initial source commit 🎉 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..aeff653 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,45 @@ +root = true + +# All files +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +indent_style = space + +# C# files +[*.cs] +# Nullable reference types +csharp_nullable_reference_types = enable + +# Naming conventions +dotnet_naming_rule.async_methods_end_in_async.severity = suggestion +dotnet_naming_rule.async_methods_end_in_async.symbols = async_methods +dotnet_naming_rule.async_methods_end_in_async.style = end_in_async + +dotnet_naming_symbols.async_methods.applicable_kinds = method +dotnet_naming_symbols.async_methods.required_modifiers = async + +dotnet_naming_style.end_in_async.required_suffix = Async +dotnet_naming_style.end_in_async.capitalization = pascal_case + +# Formatting +csharp_new_line_before_open_brace = all +csharp_indent_case_contents = true +csharp_space_after_cast = false + +# Project files +[*.{csproj,props,targets}] +indent_size = 4 + +# JSON files +[*.json] +indent_size = 2 + +# Godot files +[*.{tscn,tres,godot}] +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e306f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# .NET build outputs +bin/ +obj/ +*.dll +*.exe +*.pdb + +# User-specific files +*.user +*.suo +*.userprefs +.vs/ +.vscode/ +.idea/ + +# Godot-specific ignores +project/.godot/ +project/.import/ +project/export_presets.cfg + +# OS-specific +.DS_Store +Thumbs.db + +# NuGet packages +*.nupkg +packages/ diff --git a/Longhorn.Tests/BasicTests.cs b/Longhorn.Tests/BasicTests.cs new file mode 100644 index 0000000..be47b84 --- /dev/null +++ b/Longhorn.Tests/BasicTests.cs @@ -0,0 +1,52 @@ +using Godot; +using twodog.xunit; + +namespace Longhorn.Tests; + +[Collection("GodotHeadless")] +public class BasicTests(GodotHeadlessFixture godot) +{ + [Fact] + public void LoadMainScene_Succeeds() + { + // Arrange + var scene = GD.Load("res://main.tscn"); + + // Act + var instance = scene.Instantiate(); + godot.Tree.Root.AddChild(instance); + + // Assert + Assert.NotNull(instance); + Assert.NotNull(instance.GetParent()); + } + + [Fact] + public void PhysicsIteration_Succeeds() + { + // Arrange & Act + godot.Tree.Root.PhysicsInterpolationMode = Node.PhysicsInterpolationModeEnum.Off; + godot.GodotInstance.Iteration(); + + // Assert - if we get here without crashing, test passes + Assert.True(true); + } + + [Fact] + public void CreateNode_AddsToTree() + { + // Arrange + var node = new Node(); + node.Name = "TestNode"; + + // Act + godot.Tree.Root.AddChild(node); + + // Assert + Assert.True(godot.Tree.Root.HasNode("TestNode")); + Assert.Equal("TestNode", (string)godot.Tree.Root.GetNode("TestNode").Name); + + // Cleanup + node.QueueFree(); + } +} diff --git a/Longhorn.Tests/GodotHeadlessCollection.cs b/Longhorn.Tests/GodotHeadlessCollection.cs new file mode 100644 index 0000000..c024669 --- /dev/null +++ b/Longhorn.Tests/GodotHeadlessCollection.cs @@ -0,0 +1,7 @@ +using twodog.xunit; +using Xunit; + +namespace Longhorn.Tests; + +[CollectionDefinition("GodotHeadless", DisableParallelization = true)] +public class GodotHeadlessCollection : ICollectionFixture; diff --git a/Longhorn.Tests/Longhorn.Tests.csproj b/Longhorn.Tests/Longhorn.Tests.csproj new file mode 100644 index 0000000..6b21a84 --- /dev/null +++ b/Longhorn.Tests/Longhorn.Tests.csproj @@ -0,0 +1,51 @@ + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ../Longhorn/project + + + + + + + + + diff --git a/Longhorn.slnx b/Longhorn.slnx new file mode 100644 index 0000000..16a130d --- /dev/null +++ b/Longhorn.slnx @@ -0,0 +1,4 @@ + + + + diff --git a/Longhorn/Longhorn.csproj b/Longhorn/Longhorn.csproj new file mode 100644 index 0000000..2e4dcd3 --- /dev/null +++ b/Longhorn/Longhorn.csproj @@ -0,0 +1,18 @@ + + + net10.0 + Exe + enable + enable + false + + + + + + + + + ./project + + diff --git a/Longhorn/Program.cs b/Longhorn/Program.cs new file mode 100644 index 0000000..3b1991a --- /dev/null +++ b/Longhorn/Program.cs @@ -0,0 +1,24 @@ +using Godot; +using Engine = twodog.Engine; + +// Create and start the Godot engine with your project +using var engine = new Engine("Longhorn", Engine.ResolveProjectDir()); +using var godot = engine.Start(); + +// Load your main scene +var scene = GD.Load("res://main.tscn"); +engine.Tree.Root.AddChild(scene.Instantiate()); + +GD.Print("2dog is running! Close window or press 'Q' to quit."); +Console.WriteLine("Press 'Q' to quit."); + +// Main game loop - runs until window closes or 'Q' is pressed +while (!godot.Iteration()) +{ + if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Q) + break; + + // Your per-frame logic here +} + +Console.WriteLine("Shutting down..."); diff --git a/Longhorn/project/main.tscn b/Longhorn/project/main.tscn new file mode 100644 index 0000000..36e156c --- /dev/null +++ b/Longhorn/project/main.tscn @@ -0,0 +1,22 @@ +[gd_scene format=3] + +[node name="Main" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="CenterContainer" type="CenterContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="CenterContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Hello from 2dog!" diff --git a/Longhorn/project/project.godot b/Longhorn/project/project.godot new file mode 100644 index 0000000..52a337e --- /dev/null +++ b/Longhorn/project/project.godot @@ -0,0 +1,26 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +custom_features="dotnet" + +[application] + +config/name="Longhorn" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.6", "C#") + +[dotnet] + +project/assembly_name="Longhorn" + +[display] + +window/size/viewport_width=1280 +window/size/viewport_height=720 diff --git a/README.md b/README.md new file mode 100644 index 0000000..98ccda9 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Longhorn + +This is a long term experimental project for testing [2dog](https://2dog.dev/), a C# library that embeds LibGodot and leverages the existing GDSharp APIs. + +## License + +I hereby waive this project under the public domain - see [UNLICENSE](LICENSE) for details. \ No newline at end of file diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..ee6c639 --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,22 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute +this software, either in source code form or as a compiled binary, for any +purpose, commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and +to the detriment of our heirs and + +successors. We intend this dedication to be an overt act of relinquishment +in perpetuity of all present and future rights to this software under copyright +law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, +please refer to