diff --git a/src/ReactorMaintenance.Win2D/Images/tilemap.png b/src/ReactorMaintenance.Win2D/Images/tilemap.png new file mode 100644 index 0000000..9ca784c Binary files /dev/null and b/src/ReactorMaintenance.Win2D/Images/tilemap.png differ diff --git a/src/ReactorMaintenance.Win2D/MainWindow.xaml b/src/ReactorMaintenance.Win2D/MainWindow.xaml index 44e307f..843ef19 100644 --- a/src/ReactorMaintenance.Win2D/MainWindow.xaml +++ b/src/ReactorMaintenance.Win2D/MainWindow.xaml @@ -41,6 +41,7 @@ - \ No newline at end of file + diff --git a/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs b/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs index 5b7161e..299f372 100644 --- a/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs +++ b/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs @@ -4,8 +4,8 @@ using Windows.Storage; using Windows.Storage.Pickers; using Windows.UI; using Microsoft.Graphics.Canvas; -using Microsoft.Graphics.Canvas.Geometry; using Microsoft.Graphics.Canvas.Text; +using Microsoft.Graphics.Canvas.UI; using Microsoft.Graphics.Canvas.UI.Xaml; using Microsoft.UI; using Microsoft.UI.Xaml; @@ -43,6 +43,16 @@ public sealed partial class MainWindow RefreshInspector(); } + private void LevelCanvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args) + { + args.TrackAsyncAction(LoadTilemapAsync(sender).AsAsyncAction()); + } + + private async Task LoadTilemapAsync(CanvasControl sender) + { + m_TerrainTilemap = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///Images/tilemap.png")); + } + private void ToolPicker_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ToolPicker.SelectedItem is EEditorTool tool) @@ -213,99 +223,41 @@ public sealed partial class MainWindow private void DrawDualTerrainTile(CanvasDrawingSession drawing, Rect rect, int floorMask) { - var wallColor = ColorHelper.FromArgb(255, 54, 61, 68); - var floorColor = ColorHelper.FromArgb(255, 31, 36, 40); + if (m_TerrainTilemap is null) + return; + var wallMask = c_AllCorners ^ floorMask; - - drawing.FillRectangle(rect, floorColor); - DrawDualTerrainTile(drawing, rect, wallColor, floorColor, GetDualTerrainTileId(wallMask)); + var sourceRect = TilemapSourceRect(wallMask); + drawing.DrawImage(m_TerrainTilemap, rect, sourceRect); } - private static int GetDualTerrainTileId(int wallMask) + private static Rect TilemapSourceRect(int wallMask) { - return wallMask; - } - - private static void DrawDualTerrainTile(CanvasDrawingSession drawing, Rect rect, Color wallColor, Color floorColor, int tileId) - { - if (tileId == 0) - return; - - if (tileId == c_AllCorners) - { - drawing.FillRectangle(rect, wallColor); - return; - } - - switch (tileId) - { - case c_TopLeftCorner: - case c_TopRightCorner: - case c_BottomLeftCorner: - case c_BottomRightCorner: - DrawTerrainCorner(drawing, rect, wallColor, tileId); - break; - case c_TopLeftCorner | c_TopRightCorner: - drawing.FillRectangle(new(rect.X, rect.Y, rect.Width, rect.Height / 2), wallColor); - break; - case c_BottomLeftCorner | c_BottomRightCorner: - drawing.FillRectangle(new(rect.X, rect.Y + rect.Height / 2, rect.Width, rect.Height / 2), wallColor); - break; - case c_TopLeftCorner | c_BottomLeftCorner: - drawing.FillRectangle(new(rect.X, rect.Y, rect.Width / 2, rect.Height), wallColor); - break; - case c_TopRightCorner | c_BottomRightCorner: - drawing.FillRectangle(new(rect.X + rect.Width / 2, rect.Y, rect.Width / 2, rect.Height), wallColor); - break; - case c_TopLeftCorner | c_BottomRightCorner: - DrawTerrainCorner(drawing, rect, wallColor, c_TopLeftCorner); - DrawTerrainCorner(drawing, rect, wallColor, c_BottomRightCorner); - break; - case c_TopRightCorner | c_BottomLeftCorner: - DrawTerrainCorner(drawing, rect, wallColor, c_TopRightCorner); - DrawTerrainCorner(drawing, rect, wallColor, c_BottomLeftCorner); - break; - default: - drawing.FillRectangle(rect, wallColor); - DrawTerrainCorner(drawing, rect, floorColor, c_AllCorners ^ tileId); - break; - } - } - - private static void DrawTerrainCorner(CanvasDrawingSession drawing, Rect rect, Color color, int corner) - { - var radiusX = (float)rect.Width / 2; - var radiusY = (float)rect.Height / 2; - var center = corner switch { - c_TopLeftCorner => new Vector2((float)rect.X, (float)rect.Y), - c_TopRightCorner => new Vector2((float)(rect.X + rect.Width), (float)rect.Y), - c_BottomRightCorner => new Vector2((float)(rect.X + rect.Width), (float)(rect.Y + rect.Height)), - c_BottomLeftCorner => new Vector2((float)rect.X, (float)(rect.Y + rect.Height)), - _ => new Vector2((float)(rect.X + rect.Width / 2), (float)(rect.Y + rect.Height / 2)) - }; - var start = corner switch { - c_TopLeftCorner => new Vector2(center.X + radiusX, center.Y), - c_TopRightCorner => new Vector2(center.X, center.Y + radiusY), - c_BottomRightCorner => new Vector2(center.X - radiusX, center.Y), - c_BottomLeftCorner => new Vector2(center.X, center.Y - radiusY), - _ => center - }; - var end = corner switch { - c_TopLeftCorner => new Vector2(center.X, center.Y + radiusY), - c_TopRightCorner => new Vector2(center.X - radiusX, center.Y), - c_BottomRightCorner => new Vector2(center.X, center.Y - radiusY), - c_BottomLeftCorner => new Vector2(center.X + radiusX, center.Y), - _ => center + var tilePosition = wallMask switch { + c_BottomLeftCorner => new GridPosition(0, 0), + c_TopRightCorner | c_BottomRightCorner => new GridPosition(1, 0), + c_TopLeftCorner | c_BottomLeftCorner | c_BottomRightCorner => new GridPosition(2, 0), + c_BottomLeftCorner | c_BottomRightCorner => new GridPosition(3, 0), + c_TopLeftCorner | c_BottomRightCorner => new GridPosition(0, 1), + c_BottomLeftCorner | c_TopRightCorner | c_BottomRightCorner => new GridPosition(1, 1), + c_AllCorners => new GridPosition(2, 1), + c_TopLeftCorner | c_BottomLeftCorner | c_TopRightCorner => new GridPosition(3, 1), + c_TopRightCorner => new GridPosition(0, 2), + c_TopLeftCorner | c_TopRightCorner => new GridPosition(1, 2), + c_TopLeftCorner | c_TopRightCorner | c_BottomRightCorner => new GridPosition(2, 2), + c_BottomLeftCorner | c_TopLeftCorner => new GridPosition(3, 2), + 0 => new GridPosition(0, 3), + c_BottomRightCorner => new GridPosition(1, 3), + c_BottomLeftCorner | c_TopRightCorner => new GridPosition(2, 3), + c_TopLeftCorner => new GridPosition(3, 3), + _ => throw new ArgumentOutOfRangeException(nameof(wallMask), wallMask, "Unsupported tile mask.") }; - using var builder = new CanvasPathBuilder(drawing); - builder.BeginFigure(center); - builder.AddLine(start); - builder.AddArc(end, radiusX, radiusY, 0, CanvasSweepDirection.Clockwise, CanvasArcSize.Small); - builder.EndFigure(CanvasFigureLoop.Closed); - - using var geometry = CanvasGeometry.CreatePath(builder); - drawing.FillGeometry(geometry, color); + return new( + tilePosition.X * c_TilemapTileSize, + tilePosition.Y * c_TilemapTileSize, + c_TilemapTileSize, + c_TilemapTileSize); } private int GetDualTileMask(int x, int y) @@ -486,11 +438,13 @@ public sealed partial class MainWindow } private readonly SimulationEngine m_Simulation = new(); + private const int c_TilemapTileSize = 512; private const int c_TopLeftCorner = 1; private const int c_TopRightCorner = 2; private const int c_BottomLeftCorner = 4; private const int c_BottomRightCorner = 8; private const int c_AllCorners = c_TopLeftCorner | c_TopRightCorner | c_BottomLeftCorner | c_BottomRightCorner; + private CanvasBitmap? m_TerrainTilemap; private StorageFile? m_CurrentFile; private LevelState m_Level; private bool m_Painting; diff --git a/src/ReactorMaintenance.Win2D/ReactorMaintenance.Win2D.csproj b/src/ReactorMaintenance.Win2D/ReactorMaintenance.Win2D.csproj index 7d3910e..abd0757 100644 --- a/src/ReactorMaintenance.Win2D/ReactorMaintenance.Win2D.csproj +++ b/src/ReactorMaintenance.Win2D/ReactorMaintenance.Win2D.csproj @@ -24,4 +24,8 @@ - \ No newline at end of file + + + + +