Bootstrap Stride-hosted engine shell
This commit is contained in:
parent
8cf38fed87
commit
97c697b638
11 changed files with 229 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
bin/
|
||||
obj/
|
||||
artifacts/
|
||||
*.user
|
||||
*.suo
|
||||
.vs/
|
||||
.idea/
|
||||
5
Aquarium.Engine.slnx
Normal file
5
Aquarium.Engine.slnx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<Solution>
|
||||
<Folder Name="/src/">
|
||||
<Project Path="src/Aquarium.Engine/Aquarium.Engine.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
17
README.md
17
README.md
|
|
@ -30,3 +30,20 @@ Aquarium-first rather than framework-first.
|
|||
Create the smallest C# executable that opens a window, owns the camera/Grid
|
||||
invariant, and renders one sun plus orbiting planets with diegetic labels.
|
||||
Everything else earns its way back in.
|
||||
|
||||
## Run
|
||||
|
||||
```powershell
|
||||
dotnet build Aquarium.Engine.slnx
|
||||
dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj
|
||||
```
|
||||
|
||||
Headless smoke:
|
||||
|
||||
```powershell
|
||||
dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj -- --headless
|
||||
```
|
||||
|
||||
The first cut uses Stride as a NuGet-hosted shell through
|
||||
`Stride.CommunityToolkit.Windows`. Stride is scaffolding; the Aquarium owns the
|
||||
camera/Grid invariant and the renderer direction. See `docs/stride-boundary.md`.
|
||||
|
|
|
|||
38
docs/stride-boundary.md
Normal file
38
docs/stride-boundary.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Stride Boundary
|
||||
|
||||
Stride enters Aquarium as a package dependency, not as vendored engine source.
|
||||
|
||||
## What Stride Provides
|
||||
|
||||
- Window/device/input scaffolding.
|
||||
- Game loop hosting.
|
||||
- Asset and graphics infrastructure where it helps.
|
||||
- A place to insert Aquarium-owned renderer passes.
|
||||
|
||||
## What Aquarium Owns
|
||||
|
||||
- Camera/Grid invariants.
|
||||
- World model and simulation state.
|
||||
- CultNet and CultCache boundaries.
|
||||
- Renderer architecture and field ownership.
|
||||
- Diegetic UI grammar.
|
||||
- Debug command surface.
|
||||
|
||||
## First Invariant
|
||||
|
||||
The camera target is a point on global XY. The Grid center is that same point.
|
||||
Grid radius is derived from camera zoom distance, not from camera pitch/yaw or
|
||||
screen projection. Orbiting the camera must not resize the Grid.
|
||||
|
||||
Current code expresses this through `OrbitCameraRig` and `GridFrame`.
|
||||
|
||||
## Current Warnings
|
||||
|
||||
`Stride.CommunityToolkit.Windows` brings Stride's asset/compiler toolchain into
|
||||
the restore graph. The first restore/build currently reports transitive NuGet
|
||||
advisories for `Microsoft.Build.Tasks.Core`, `NuGet.Packaging`, and
|
||||
`NuGet.Protocol`, plus Stride's default missing `GameSettings` warning. These
|
||||
are dependency/tooling warnings, not Aquarium code warnings.
|
||||
|
||||
Do not hide them globally yet. Track whether newer Stride/Toolkit packages clear
|
||||
the advisories before adding warning suppressions.
|
||||
6
global.json
Normal file
6
global.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "10.0.202",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
14
src/Aquarium.Engine/Aquarium.Engine.csproj
Normal file
14
src/Aquarium.Engine/Aquarium.Engine.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Stride.CommunityToolkit.Windows" Version="1.0.0-preview.62" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
src/Aquarium.Engine/AquariumHost.cs
Normal file
26
src/Aquarium.Engine/AquariumHost.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using Stride.CommunityToolkit.Engine;
|
||||
using Stride.Engine;
|
||||
using Stride.Games;
|
||||
|
||||
namespace Aquarium.Engine;
|
||||
|
||||
public static class AquariumHost
|
||||
{
|
||||
public static int Run(string[] args)
|
||||
{
|
||||
using var game = new Game();
|
||||
var runtime = new AquariumRuntime(new AquariumRuntimeOptions(ParseHeadless(args)));
|
||||
|
||||
game.Run(
|
||||
context: null,
|
||||
start: runtime.Start,
|
||||
update: runtime.Update);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static bool ParseHeadless(IEnumerable<string> args)
|
||||
{
|
||||
return args.Any(arg => string.Equals(arg, "--headless", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
49
src/Aquarium.Engine/AquariumRuntime.cs
Normal file
49
src/Aquarium.Engine/AquariumRuntime.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using Stride.Core.Mathematics;
|
||||
using Stride.Engine;
|
||||
using Stride.Games;
|
||||
|
||||
namespace Aquarium.Engine;
|
||||
|
||||
public sealed class AquariumRuntime
|
||||
{
|
||||
private readonly AquariumRuntimeOptions options;
|
||||
private readonly OrbitCameraRig cameraRig;
|
||||
|
||||
private GridFrame gridFrame;
|
||||
|
||||
public AquariumRuntime(AquariumRuntimeOptions options)
|
||||
{
|
||||
this.options = options;
|
||||
cameraRig = new OrbitCameraRig(
|
||||
target: Vector2.Zero,
|
||||
yawRadians: MathUtil.DegreesToRadians(35.0f),
|
||||
pitchRadians: MathUtil.DegreesToRadians(42.0f),
|
||||
distance: 24.0f);
|
||||
gridFrame = GridFrame.FromCamera(cameraRig);
|
||||
}
|
||||
|
||||
public void Start(Scene rootScene)
|
||||
{
|
||||
_ = rootScene;
|
||||
Console.WriteLine("Aquarium Engine booted.");
|
||||
Console.WriteLine($"Grid center: {gridFrame.Center}, radius: {gridFrame.Radius:0.00}");
|
||||
Console.WriteLine("Stride is present as the host shell; Aquarium owns the invariants.");
|
||||
}
|
||||
|
||||
public void Update(Scene rootScene, GameTime gameTime)
|
||||
{
|
||||
_ = rootScene;
|
||||
_ = gameTime;
|
||||
|
||||
gridFrame = GridFrame.FromCamera(cameraRig);
|
||||
|
||||
if (options.Headless)
|
||||
{
|
||||
Console.WriteLine("Headless smoke reached first update.");
|
||||
Environment.ExitCode = 0;
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly record struct AquariumRuntimeOptions(bool Headless);
|
||||
3
src/Aquarium.Engine/Program.cs
Normal file
3
src/Aquarium.Engine/Program.cs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
using Aquarium.Engine;
|
||||
|
||||
return AquariumHost.Run(args);
|
||||
11
src/Aquarium.Engine/World/GridFrame.cs
Normal file
11
src/Aquarium.Engine/World/GridFrame.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using Stride.Core.Mathematics;
|
||||
|
||||
namespace Aquarium.Engine;
|
||||
|
||||
public readonly record struct GridFrame(Vector2 Center, float Radius)
|
||||
{
|
||||
public static GridFrame FromCamera(OrbitCameraRig camera)
|
||||
{
|
||||
return new GridFrame(camera.Target, camera.Distance);
|
||||
}
|
||||
}
|
||||
53
src/Aquarium.Engine/World/OrbitCameraRig.cs
Normal file
53
src/Aquarium.Engine/World/OrbitCameraRig.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using Stride.Core.Mathematics;
|
||||
|
||||
namespace Aquarium.Engine;
|
||||
|
||||
public sealed class OrbitCameraRig
|
||||
{
|
||||
public OrbitCameraRig(Vector2 target, float yawRadians, float pitchRadians, float distance)
|
||||
{
|
||||
Target = target;
|
||||
YawRadians = yawRadians;
|
||||
PitchRadians = pitchRadians;
|
||||
Distance = MathF.Max(1.0f, distance);
|
||||
}
|
||||
|
||||
public Vector2 Target { get; private set; }
|
||||
|
||||
public float YawRadians { get; private set; }
|
||||
|
||||
public float PitchRadians { get; private set; }
|
||||
|
||||
public float Distance { get; private set; }
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get
|
||||
{
|
||||
var horizontal = Distance * MathF.Cos(PitchRadians);
|
||||
var x = Target.X + horizontal * MathF.Cos(YawRadians);
|
||||
var y = Target.Y + horizontal * MathF.Sin(YawRadians);
|
||||
var z = Distance * MathF.Sin(PitchRadians);
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
public void Orbit(float yawDeltaRadians, float pitchDeltaRadians)
|
||||
{
|
||||
YawRadians += yawDeltaRadians;
|
||||
PitchRadians = MathUtil.Clamp(
|
||||
PitchRadians + pitchDeltaRadians,
|
||||
MathUtil.DegreesToRadians(5.0f),
|
||||
MathUtil.DegreesToRadians(85.0f));
|
||||
}
|
||||
|
||||
public void Zoom(float wheelSteps)
|
||||
{
|
||||
Distance = MathF.Max(1.0f, Distance * MathF.Pow(0.92f, wheelSteps));
|
||||
}
|
||||
|
||||
public void Pan(Vector2 gridDelta)
|
||||
{
|
||||
Target += gridDelta;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue