using NHSE.Core; using System; using System.Drawing; namespace NHSE.Sprites; /// /// Produces bitmaps for viewing map acres and full maps. /// public sealed class MapRenderer : IDisposable { /// /// Data source for map rendering. /// private readonly MapEditor Map; /// Scale factor for full map rendering. private int MapScale => Map.MapScale; /// Scale factor for acre viewport rendering. private int ViewScale => Map.ViewScale; // Cached acre view objects to remove allocation/GC /// 1px scale viewport item layer pixel data. private readonly int[] ViewportItems1; /// Upscaled viewport item layer pixel data. private readonly int[] ViewportItemsX; /// Upscaled viewport item layer image. private readonly Bitmap ViewportItemsImage; /// Upscaled map item layer pixel data with reticle. private readonly int[] MapItemsReticleX; /// Upscaled map item layer image with reticle. private readonly Bitmap MapItemsReticleImage; /// 1px scale viewport terrain layer pixel data. private readonly int[] ViewportTerrain1; /// Upscaled viewport terrain layer pixel data. private readonly int[] ViewportTerrainX; /// Upscaled viewport terrain layer image. private readonly Bitmap ViewportTerrainImage; /// 1px scale map terrain layer pixel data. private readonly int[] MapTerrain1; /// Upscaled map terrain layer pixel data. private readonly int[] MapTerrainX; /// Upscaled map terrain layer image. private readonly Bitmap MapTerrainImage; public MapRenderer(MapEditor m) { Map = m; // Initialize cached objects based on map size // Get tile info from layer 0 (item layer is the tiniest cell we can render) var l1 = m.Mutator.Manager.FieldItems.Layer0; var info = l1.TileInfo; MapItemsReticleX = new int[info.TotalWidth * info.TotalHeight * MapScale * MapScale]; MapItemsReticleImage = new Bitmap(info.TotalWidth * MapScale, info.TotalHeight * MapScale); MapTerrain1 = new int[MapItemsReticleX.Length / (MapScale * MapScale)]; MapTerrainX = new int[MapItemsReticleX.Length]; MapTerrainImage = new Bitmap(MapItemsReticleImage.Width, MapItemsReticleImage.Height); ViewportItems1 = new int[info.ViewWidth * info.ViewHeight]; ViewportItemsX = new int[ViewportItems1.Length * ViewScale * ViewScale]; ViewportItemsImage = new Bitmap(info.ViewWidth * ViewScale, info.ViewHeight * ViewScale); ViewportTerrain1 = new int[16*16 * 16*16]; // each terrain tile is drawn as 16px, then we upscale ViewportTerrainX = new int[ViewportItemsX.Length]; // 2x upscale ViewportTerrainImage = new Bitmap(ViewportItemsImage.Width, ViewportItemsImage.Height); } public void Dispose() { MapItemsReticleImage.Dispose(); MapTerrainImage.Dispose(); ViewportItemsImage.Dispose(); ViewportTerrainImage.Dispose(); } /// /// Updates the map items reticle bitmap for the current layer and view position. /// /// Transparency of items (not including reticle). /// Option to draw the reticle. /// Updated bitmap with reticle. public Bitmap UpdateMapItemsReticle(int transparency, bool drawReticle = true) => UpdateMapItemsReticle(Map.Mutator.CurrentLayer, Map.Mutator.View.X, Map.Mutator.View.Y, transparency, drawReticle); /// /// Updates the map terrain bitmap. /// /// Index of building to highlight, or -1 for none. /// Updated map terrain bitmap. public Bitmap UpdateMapTerrain(int selectedBuildingIndex = -1) => TerrainSprite.GetMapWithBuildings(MapTerrainImage, Map, null, MapTerrain1, MapTerrainX, selectedBuildingIndex); /// /// Updates the viewport items bitmap for the current layer and view position. /// /// Transparency of items. public Bitmap UpdateViewportItems(int transparency) => UpdateViewportItems(Map.Mutator.View.X, Map.Mutator.View.Y, transparency); /// /// Updates the viewport terrain bitmap. /// /// Font to use for building labels. /// Transparency for building shapes drawn on terrain. /// Transparency for terrain layer. /// Index of building to highlight, or -1 for none. /// public Bitmap UpdateViewportTerrain(Font f, byte transparencyBuilding, byte transparencyTerrain, int selectedBuildingIndex = -1) { TerrainSprite.LoadViewport(ViewportTerrainImage, Map, f, ViewportTerrain1, ViewportTerrainX, selectedBuildingIndex, transparencyBuilding, transparencyTerrain); return ViewportTerrainImage; } private Bitmap UpdateMapItemsReticle(LayerFieldItem layer, int absX, int absY, int transparency, bool drawReticle = true) { var cfg = Map.Mutator.Manager.ConfigItems; ItemLayerSprite.LoadItemLayerDrawReticle(cfg, layer, MapItemsReticleX, transparency); MapItemsReticleImage.SetBitmapData(MapItemsReticleX); if (drawReticle) ItemLayerSprite.DrawViewReticle(MapItemsReticleImage, layer.TileInfo, absX, absY); return MapItemsReticleImage; } private Bitmap UpdateViewportItems(int absX, int absY, int transparency) { var cfg = Map.Mutator.Manager.ConfigItems; var layer = Map.Mutator.CurrentLayer; ItemLayerSprite.LoadViewport(ViewportItemsImage, layer, cfg, absX, absY, ViewportItems1, ViewportItemsX, ViewScale, transparency); return ViewportItemsImage; } }