Initial source commit 🎉

This commit is contained in:
Tony Bark 2026-02-03 03:00:54 -05:00
commit 7d823aa78b
12 changed files with 305 additions and 0 deletions

45
.editorconfig Normal file
View file

@ -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

27
.gitignore vendored Normal file
View file

@ -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/

View file

@ -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<PackedScene>("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();
}
}

View file

@ -0,0 +1,7 @@
using twodog.xunit;
using Xunit;
namespace Longhorn.Tests;
[CollectionDefinition("GodotHeadless", DisableParallelization = true)]
public class GodotHeadlessCollection : ICollectionFixture<GodotHeadlessFixture>;

View file

@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<!-- 2dog packages -->
<ItemGroup>
<PackageReference Include="2dog" Version="0.1.10-pre"/>
<PackageReference Include="2dog.xunit" Version="0.1.10-pre"/>
<PackageReference Include="GodotSharp" Version="4.6.0"/>
</ItemGroup>
<!-- Platform-specific native library packages -->
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<PackageReference Include="2dog.win-x64" Version="0.1.10-pre"/>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Linux'))">
<PackageReference Include="2dog.linux-x64" Version="0.1.10-pre"/>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('OSX'))">
<PackageReference Include="2dog.osx-arm64" Version="0.1.10-pre"/>
</ItemGroup>
<!-- Test framework packages -->
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageReference Include="xunit" Version="2.9.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2"/>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>
<!-- Godot project location -->
<PropertyGroup>
<GodotProjectDir>../Longhorn/project</GodotProjectDir>
</PropertyGroup>
<!-- Remove duplicate Godot.SourceGenerators that come from GodotSharp package
(2dog package already embeds them) -->
<Target Name="RemoveDuplicateGodotAnalyzers" BeforeTargets="CoreCompile">
<ItemGroup>
<Analyzer Remove="@(Analyzer)" Condition="$([System.String]::Copy('%(Analyzer.Identity)').Contains('Godot.SourceGenerators'))" />
</ItemGroup>
</Target>
</Project>

4
Longhorn.slnx Normal file
View file

@ -0,0 +1,4 @@
<Solution>
<Project Path="Longhorn.Tests/Longhorn.Tests.csproj" />
<Project Path="Longhorn/Longhorn.csproj" />
</Solution>

18
Longhorn/Longhorn.csproj Normal file
View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="2dog" Version="0.1.10-pre"/>
</ItemGroup>
<!-- Godot project location -->
<PropertyGroup>
<GodotProjectDir>./project</GodotProjectDir>
</PropertyGroup>
</Project>

24
Longhorn/Program.cs Normal file
View file

@ -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<PackedScene>("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...");

View file

@ -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!"

View file

@ -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

7
README.md Normal file
View file

@ -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.

22
UNLICENSE Normal file
View file

@ -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 <https://unlicense.org/>