using System; using System.Collections.Generic; using System.Linq; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; using Robust.Shared.ContentPack; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Timing; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using static Robust.UnitTesting.RobustIntegrationTest; namespace Content.MapRenderer.Painters { public sealed class TilePainter { public const int TileImageSize = EyeManager.PixelsPerMeter; private readonly ITileDefinitionManager _sTileDefinitionManager; private readonly SharedMapSystem _sMapSystem; private readonly IResourceManager _resManager; public TilePainter(ClientIntegrationInstance client, ServerIntegrationInstance server) { _sTileDefinitionManager = server.ResolveDependency(); _resManager = client.ResolveDependency(); var esm = server.ResolveDependency(); _sMapSystem = esm.GetEntitySystem(); } public void Run(Image gridCanvas, EntityUid gridUid, MapGridComponent grid) { var stopwatch = new Stopwatch(); stopwatch.Start(); var bounds = grid.LocalAABB; var xOffset = -bounds.Left; var yOffset = -bounds.Bottom; var tileSize = grid.TileSize * TileImageSize; var images = GetTileImages(_sTileDefinitionManager, _resManager, tileSize); var i = 0; _sMapSystem.GetAllTiles(gridUid, grid).AsParallel().ForAll(tile => { var path = _sTileDefinitionManager[tile.Tile.TypeId].Sprite.ToString(); if (string.IsNullOrWhiteSpace(path)) return; var x = (int) (tile.X + xOffset); var y = (int) (tile.Y + yOffset); var image = images[path][tile.Tile.Variant]; gridCanvas.Mutate(o => o.DrawImage(image, new Point(x * tileSize, y * tileSize), 1)); i++; }); Console.WriteLine($"{nameof(TilePainter)} painted {i} tiles on grid {gridUid} in {(int) stopwatch.Elapsed.TotalMilliseconds} ms"); } private Dictionary> GetTileImages( ITileDefinitionManager tileDefinitionManager, IResourceManager resManager, int tileSize) { var stopwatch = new Stopwatch(); stopwatch.Start(); var images = new Dictionary>(); foreach (var definition in tileDefinitionManager) { var path = definition.Sprite.ToString(); if (string.IsNullOrWhiteSpace(path)) continue; images[path] = new List(definition.Variants); using var stream = resManager.ContentFileRead(path); Image tileSheet = Image.Load(stream); if (tileSheet.Width != tileSize * definition.Variants || tileSheet.Height != tileSize) { throw new NotSupportedException($"Unable to use tiles with a dimension other than {tileSize}x{tileSize}."); } for (var i = 0; i < definition.Variants; i++) { var index = i; var tileImage = tileSheet.Clone(o => o.Crop(new Rectangle(tileSize * index, 0, 32, 32))); images[path].Add(tileImage); } } Console.WriteLine($"Indexed all tile images in {(int) stopwatch.Elapsed.TotalMilliseconds} ms"); return images; } } }