Skip to content

Commit 07b0eb3

Browse files
authored
Merge pull request #197 from Perksey/silk-backend
2 parents dabb5ae + 00f1329 commit 07b0eb3

File tree

4 files changed

+212
-0
lines changed

4 files changed

+212
-0
lines changed

Trains.NET.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinTrains", "src\WinTrains\
4545
EndProject
4646
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazingTrains", "src\BlazingTrains\BlazingTrains.csproj", "{79D851AC-3713-4582-A20A-5E6C24FEAE6B}"
4747
EndProject
48+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilkTrains", "src\SilkTrains\SilkTrains.csproj", "{D5624473-B557-42F4-B907-C9922CAA8075}"
49+
EndProject
4850
Global
4951
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5052
Debug|Any CPU = Debug|Any CPU
@@ -95,6 +97,10 @@ Global
9597
{79D851AC-3713-4582-A20A-5E6C24FEAE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
9698
{79D851AC-3713-4582-A20A-5E6C24FEAE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
9799
{79D851AC-3713-4582-A20A-5E6C24FEAE6B}.Release|Any CPU.Build.0 = Release|Any CPU
100+
{D5624473-B557-42F4-B907-C9922CAA8075}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
101+
{D5624473-B557-42F4-B907-C9922CAA8075}.Debug|Any CPU.Build.0 = Debug|Any CPU
102+
{D5624473-B557-42F4-B907-C9922CAA8075}.Release|Any CPU.ActiveCfg = Release|Any CPU
103+
{D5624473-B557-42F4-B907-C9922CAA8075}.Release|Any CPU.Build.0 = Release|Any CPU
98104
EndGlobalSection
99105
GlobalSection(SolutionProperties) = preSolution
100106
HideSolutionNode = FALSE
@@ -111,6 +117,7 @@ Global
111117
{10E5BE95-85C2-456C-A32B-A77E7EB702A1} = {6D7A257F-24F9-43A2-870A-14DFCA32DDD2}
112118
{894082D5-C407-476F-9EAA-B412411E6E1F} = {77E57704-D3D8-4228-A195-1F90FD62539A}
113119
{79D851AC-3713-4582-A20A-5E6C24FEAE6B} = {77E57704-D3D8-4228-A195-1F90FD62539A}
120+
{D5624473-B557-42F4-B907-C9922CAA8075} = {77E57704-D3D8-4228-A195-1F90FD62539A}
114121
EndGlobalSection
115122
GlobalSection(ExtensibilityGlobals) = postSolution
116123
SolutionGuid = {8834C621-39E4-4AD6-85D0-97F46ADC88D6}

src/SilkTrains/Hacks.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Silk.NET.Maths;
2+
using Silk.NET.Windowing;
3+
4+
namespace SilkTrains;
5+
6+
internal static class Hacks
7+
{
8+
// TODO: Replace this with the real IView.PointToFramebuffer when 2.12 is released without the divide by zero bug :O
9+
public static Vector2D<int> NotBuggedPointToFramebuffer(this IView view, Vector2D<int> point)
10+
=> point * (view.FramebufferSize / view.Size);
11+
}

src/SilkTrains/Program.cs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
using Silk.NET.Core;
4+
using Silk.NET.Input;
5+
using Silk.NET.Maths;
6+
using Silk.NET.OpenGL;
7+
using Silk.NET.Windowing;
8+
using SilkTrains;
9+
using SixLabors.ImageSharp;
10+
using SixLabors.ImageSharp.PixelFormats;
11+
using SkiaSharp;
12+
using Trains.NET.Rendering;
13+
using Trains.NET.Rendering.Skia;
14+
using Trains.Storage;
15+
16+
// Game stuff
17+
string windowSizeFileName = FileSystemStorage.GetFilePath("WindowSize.txt");
18+
IGame game = DI.ServiceLocator.GetService<IGame>();
19+
IInteractionManager interactionManager = DI.ServiceLocator.GetService<IInteractionManager>();
20+
21+
// Get size from file
22+
Vector2D<int> size = new(1280, 720);
23+
if (File.Exists(windowSizeFileName))
24+
{
25+
string sizeString = File.ReadAllText(windowSizeFileName);
26+
string[] bits = sizeString.Split(',');
27+
if (bits.Length == 2)
28+
{
29+
if (double.TryParse(bits[0], out double width) && double.TryParse(bits[1], out double height))
30+
{
31+
size = new((int)width, (int)height);
32+
}
33+
}
34+
}
35+
36+
// Create the Silk.NET window
37+
var options = WindowOptions.Default with
38+
{
39+
Size = size,
40+
Title = "Trains - @davidwengier - " + ThisAssembly.AssemblyInformationalVersion,
41+
PreferredStencilBufferBits = 8,
42+
PreferredBitDepth = new(8)
43+
};
44+
45+
var window = Window.Create(options);
46+
47+
// Silk.NET-Skia interop variables
48+
GRGlInterface grGlInterface = null!;
49+
GRContext grContext = null!;
50+
GRBackendRenderTarget renderTarget = null!;
51+
SKSurface surface = null!;
52+
SKCanvas canvas = null!;
53+
SKCanvasWrapper canvasWrapper = null!;
54+
55+
// Other Silk.NET variables
56+
IInputContext inputContext = null!;
57+
58+
// Input handling
59+
void BindMouse(IMouse mouse)
60+
{
61+
mouse.Scroll += (_, deltaPos) =>
62+
{
63+
var mousePos = window.NotBuggedPointToFramebuffer((Vector2D<int>)mouse.Position.ToGeneric());
64+
if (deltaPos.Y > 0)
65+
{
66+
interactionManager.PointerZoomIn(mousePos.X, mousePos.Y);
67+
}
68+
else
69+
{
70+
interactionManager.PointerZoomOut(mousePos.X, mousePos.Y);
71+
}
72+
};
73+
mouse.MouseMove += (_, newPosFloat) =>
74+
{
75+
var mousePos = window.NotBuggedPointToFramebuffer((Vector2D<int>)newPosFloat.ToGeneric());
76+
if (mouse.IsButtonPressed(MouseButton.Left))
77+
{
78+
interactionManager.PointerDrag(mousePos.X, mousePos.Y);
79+
}
80+
else if (mouse.IsButtonPressed(MouseButton.Right))
81+
{
82+
interactionManager.PointerAlternateDrag(mousePos.X, mousePos.Y);
83+
}
84+
else
85+
{
86+
interactionManager.PointerMove(mousePos.X, mousePos.Y);
87+
}
88+
};
89+
mouse.MouseDown += (_, button) =>
90+
{
91+
var mousePos = window.NotBuggedPointToFramebuffer((Vector2D<int>)mouse.Position.ToGeneric());
92+
if (button == MouseButton.Left)
93+
{
94+
interactionManager.PointerClick(mousePos.X, mousePos.Y);
95+
}
96+
else if (button == MouseButton.Right)
97+
{
98+
interactionManager.PointerAlternateClick(mousePos.X, mousePos.Y);
99+
}
100+
};
101+
mouse.MouseUp += (_, button) =>
102+
{
103+
if (button != MouseButton.Left)
104+
{
105+
return;
106+
}
107+
108+
var mousePos = window.NotBuggedPointToFramebuffer((Vector2D<int>)mouse.Position.ToGeneric());
109+
interactionManager.PointerRelease(mousePos.X, mousePos.Y);
110+
};
111+
}
112+
113+
// Create the Skia-OpenGL link
114+
void HandleSize(Vector2D<int> fbSize)
115+
{
116+
renderTarget = new(window.FramebufferSize.X, window.FramebufferSize.Y, 0, 8, new(0, (int)InternalFormat.Rgba8));
117+
surface = SKSurface.Create(grContext, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
118+
canvas = surface.Canvas;
119+
canvasWrapper = new(canvas);
120+
game.SetSize(fbSize.X, fbSize.Y);
121+
}
122+
123+
// Bind window events
124+
window.Load += () =>
125+
{
126+
grGlInterface = GRGlInterface.Create(name => window.GLContext!.TryGetProcAddress(name, out var addr) ? addr : 0);
127+
grGlInterface.Validate();
128+
grContext = GRContext.CreateGl(grGlInterface);
129+
game.InitializeAsync(200, 200).GetAwaiter().GetResult();
130+
HandleSize(window.FramebufferSize);
131+
inputContext = window.CreateInput();
132+
if (inputContext.Mice.Count > 0)
133+
{
134+
BindMouse(inputContext.Mice[0]);
135+
}
136+
137+
using var ers = Assembly.GetExecutingAssembly().GetManifestResourceStream("SilkTrains.RedTrain.png");
138+
if (ers is null)
139+
{
140+
return;
141+
}
142+
143+
using var img = Image.Load<Rgba32>(ers);
144+
var rowByteLen = img.Width * 4;
145+
var bytes = new byte[rowByteLen * img.Height];
146+
for (int i = 0; i < img.Height; i++)
147+
{
148+
MemoryMarshal.Cast<Rgba32, byte>(img.GetPixelRowSpan(i)).CopyTo(bytes.AsSpan(i * rowByteLen, rowByteLen));
149+
}
150+
var rawImage = new RawImage(img.Width, img.Height, bytes);
151+
window.SetWindowIcon(ref rawImage);
152+
};
153+
154+
window.FramebufferResize += HandleSize;
155+
window.Render += deltaSeconds =>
156+
{
157+
grContext.ResetContext();
158+
game.Render(canvasWrapper);
159+
canvas.Flush();
160+
};
161+
162+
window.Closing += () =>
163+
{
164+
game.Dispose();
165+
File.WriteAllText(windowSizeFileName, $"{window.Size.X},{window.Size.Y}");
166+
};
167+
168+
// Open the window!
169+
window.Run();

src/SilkTrains/SilkTrains.csproj

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<PackageReference Include="Silk.NET.Input" Version="2.11.0" />
10+
<PackageReference Include="Silk.NET.OpenGL" Version="2.11.0" />
11+
<PackageReference Include="Silk.NET.Windowing" Version="2.11.0" />
12+
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<ProjectReference Include="..\Trains.NET.Engine\Trains.NET.Engine.csproj" />
16+
<ProjectReference Include="..\Trains.NET.Instrumentation\Trains.NET.Instrumentation.csproj" />
17+
<ProjectReference Include="..\Trains.NET.Rendering.Skia\Trains.NET.Rendering.Skia.csproj" />
18+
<ProjectReference Include="..\Trains.NET.Rendering\Trains.NET.Rendering.csproj" />
19+
<ProjectReference Include="..\Trains.NET.SourceGenerator\Trains.NET.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
20+
</ItemGroup>
21+
<ItemGroup>
22+
<Compile Include="..\Trains\Storage\FileSystemStorage.cs" Link="Storage\FileSystemStorage.cs" />
23+
<EmbeddedResource Include="..\Trains\RedTrain.png" Link="RedTrain.png" />
24+
</ItemGroup>
25+
</Project>

0 commit comments

Comments
 (0)