From 0bb5ad28319c512fa95ba2defe29317e15d0ad49 Mon Sep 17 00:00:00 2001 From: Arufonsu <17498701+Arufonsu@users.noreply.github.com> Date: Sat, 3 Jan 2026 21:10:01 -0300 Subject: [PATCH] Performance: Editor's Redundant Map Rendering [Editor] - We were iterating over the same 9 maps (3x3 grid) 6 separate times for different layers/attributes. This fix consolidates the whole thing into a single pass. - Also cleans up the mapgrid logic. Signed-off-by: Arufonsu <17498701+Arufonsu@users.noreply.github.com> --- Intersect.Editor/Core/Graphics.cs | 294 ++++++++---------------------- 1 file changed, 74 insertions(+), 220 deletions(-) diff --git a/Intersect.Editor/Core/Graphics.cs b/Intersect.Editor/Core/Graphics.cs index 03eacf9931..07ace12a8e 100644 --- a/Intersect.Editor/Core/Graphics.cs +++ b/Intersect.Editor/Core/Graphics.cs @@ -6,7 +6,6 @@ using Intersect.Editor.Forms.Helpers; using Intersect.Editor.General; using Intersect.Editor.Maps; -using Intersect.Enums; using Intersect.Framework.Core; using Intersect.Framework.Core.GameObjects.Animations; using Intersect.Framework.Core.GameObjects.Events; @@ -15,7 +14,6 @@ using Intersect.Framework.Core.GameObjects.Maps; using Intersect.Framework.Core.GameObjects.Maps.Attributes; using Intersect.Framework.Core.GameObjects.Resources; -using Intersect.GameObjects; using Intersect.Utilities; using Microsoft.Extensions.Logging; using Microsoft.Xna.Framework; @@ -60,8 +58,6 @@ public static partial class Graphics public static BlendState MultiplyState; //Overlay Stuff - public static System.Drawing.Color OverlayColor = System.Drawing.Color.Transparent; - private static BlendState sCurrentBlendmode = BlendState.NonPremultiplied; private static Effect sCurrentShader; @@ -147,6 +143,15 @@ public static void InitMonogame() } } + // New consolidated attribute drawing + private static void DrawAllMapAttributes(MapInstance map, int gridX, int gridY, bool screenShotting, RenderTarget2D target) + { + // Combine the 3 separate DrawMapAttributes calls + DrawMapAttributes(map, gridX, gridY, screenShotting, target, false, false); + DrawMapAttributes(map, gridX, gridY, screenShotting, target, false, true); + DrawMapAttributes(map, gridX, gridY, screenShotting, target, true, true); + } + public static GraphicsDevice GetGraphicsDevice() { return sGraphicsDevice; @@ -209,89 +214,7 @@ public static void Render() Globals.CurrentMap != null && Globals.MapGrid.Loaded) { - //Draw The lower maps - for (var y = Globals.CurrentMap.MapGridY - 1; y <= Globals.CurrentMap.MapGridY + 1; y++) - { - for (var x = Globals.CurrentMap.MapGridX - 1; x <= Globals.CurrentMap.MapGridX + 1; x++) - { - if (x >= 0 && x < Globals.MapGrid.GridWidth && y >= 0 && y < Globals.MapGrid.GridHeight) - { - MapInstance map = null; - try - { - map = MapInstance.Get(Globals.MapGrid.Grid[x, y].MapId); - } - catch (Exception exception) - { - Intersect.Core.ApplicationContext.Context.Value?.Logger.LogError( - exception, - $"{Globals.MapGrid.Grid.GetLength(0)}x{Globals.MapGrid.Grid.GetLength(1)} -- {x},{y}" - ); - } - - if (map != null) - { - lock (map.MapLock) - { - //Draw this map - DrawMap( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, 0, null - ); - } - } - else - { - DrawTransparentBorders( - x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY - ); - } - } - else - { - DrawTransparentBorders( - x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY - ); - } - } - } - - //Draw the lower resources/animations - for (var y = Globals.CurrentMap.MapGridY - 1; y <= Globals.CurrentMap.MapGridY + 1; y++) - { - for (var x = Globals.CurrentMap.MapGridX - 1; x <= Globals.CurrentMap.MapGridX + 1; x++) - { - if (x >= 0 && x < Globals.MapGrid.GridWidth && y >= 0 && y < Globals.MapGrid.GridHeight) - { - var mapGridItem = Globals.MapGrid.Grid[x, y]; - var map = MapInstance.Get(mapGridItem.MapId); - if (map == null) - { - continue; - } - - lock (map.MapLock) - { - DrawMapAttributes( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, null, false, false - ); - - DrawMapAttributes( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, null, false, true - ); - - DrawMapAttributes( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, null, true, true - ); - } - } - } - } - - // Draw events + // ONE optimized loop for (var y = Globals.CurrentMap.MapGridY - 1; y <= Globals.CurrentMap.MapGridY + 1; y++) { for (var x = Globals.CurrentMap.MapGridX - 1; x <= Globals.CurrentMap.MapGridX + 1; x++) @@ -301,57 +224,25 @@ public static void Render() var map = MapInstance.Get(Globals.MapGrid.Grid[x, y].MapId); if (map != null) { + var relX = x - Globals.CurrentMap.MapGridX; + var relY = y - Globals.CurrentMap.MapGridY; + lock (map.MapLock) { - DrawMapEvents( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, null - ); - } - } - } - } - } - - //Draw The upper maps - for (var y = Globals.CurrentMap.MapGridY - 1; y <= Globals.CurrentMap.MapGridY + 1; y++) - { - for (var x = Globals.CurrentMap.MapGridX - 1; x <= Globals.CurrentMap.MapGridX + 1; x++) - { - if (x >= 0 && x < Globals.MapGrid.GridWidth && y >= 0 && y < Globals.MapGrid.GridHeight) - { - var map = MapInstance.Get(Globals.MapGrid.Grid[x, y].MapId); - if (map != null) - { - lock (map.MapLock) - { - //Draw this map - DrawMap( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, 1, null - ); - } - } - } - } - } - - //Draw the upper resources/animations - for (var y = Globals.CurrentMap.MapGridY - 1; y <= Globals.CurrentMap.MapGridY + 1; y++) - { - for (var x = Globals.CurrentMap.MapGridX - 1; x <= Globals.CurrentMap.MapGridX + 1; x++) - { - if (x >= 0 && x < Globals.MapGrid.GridWidth && y >= 0 && y < Globals.MapGrid.GridHeight) - { - var map = MapInstance.Get(Globals.MapGrid.Grid[x, y].MapId); - if (map != null) - { - lock (map.MapLock) - { - DrawMapAttributes( - map, x - Globals.CurrentMap.MapGridX, y - Globals.CurrentMap.MapGridY, - false, null, true, false - ); + // Lower layers + DrawMap(map, relX, relY, false, 0, null); + + // Attributes - consolidate 3 calls into 1 + DrawAllMapAttributes(map, relX, relY, false, null); + + // Events + DrawMapEvents(map, relX, relY, false, null); + + // Upper layers + DrawMap(map, relX, relY, false, 1, null); + + // Upper attributes + DrawMapAttributes(map, relX, relY, false, null, true, false); } } } @@ -1092,108 +983,71 @@ public static void DrawMapGrid() EndSpriteBatch(); SetRenderTarget(sMapGridChain); sGraphicsDevice.Clear(Microsoft.Xna.Framework.Color.FromNonPremultiplied(60, 63, 65, 255)); - var rand = new Random(); + var grid = Globals.MapGrid; lock (Globals.MapGrid.GetMapGridLock()) { grid.Update(sMapGridChain.Bounds); + + // Pre-calculate colors and textures to avoid fetching them inside the loop + var whiteTex = GetWhiteTex(); + var emptySlotColor = System.Drawing.Color.Transparent; + var gridLineColor = System.Drawing.Color.White; + for (var x = 0; x < grid.GridWidth + 2; x++) { for (var y = 0; y < grid.GridHeight + 2; y++) { - var renderRect = new System.Drawing.Rectangle( - grid.ContentRect.X + x * grid.TileWidth, grid.ContentRect.Y + y * grid.TileHeight, - grid.TileWidth, grid.TileHeight - ); + // Calculate position ONCE + float drawX = grid.ContentRect.X + x * grid.TileWidth; + float drawY = grid.ContentRect.Y + y * grid.TileHeight; + var renderRect = new System.Drawing.Rectangle((int)drawX, (int)drawY, grid.TileWidth, grid.TileHeight); - if (grid.ViewRect.IntersectsWith(renderRect)) + // View Culling: Skip drawing if outside the visible area + if (!grid.ViewRect.IntersectsWith(renderRect)) { - if (x == 0 || - y == 0 || - x == grid.GridWidth + 1 || - y == grid.GridHeight + 1 || - grid.Grid[x - 1, y - 1].MapId == Guid.Empty) + continue; + } + + // We need a RectangleF for the drawing calls + var destRect = new RectangleF(drawX, drawY, grid.TileWidth, grid.TileHeight); + bool isPadding = x == 0 || y == 0 || x == grid.GridWidth + 1 || y == grid.GridHeight + 1; + + if (isPadding) + { + // Draw Border/Padding Background + DrawTexture(whiteTex, new RectangleF(0, 0, 1, 1), destRect, emptySlotColor, sMapGridChain); + } + else + { + var tile = grid.Grid[x - 1, y - 1]; + + if (tile.MapId == Guid.Empty || tile.Tex == null) { - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, grid.TileWidth, grid.TileHeight - ), System.Drawing.Color.FromArgb(45, 45, 48), sMapGridChain - ); + DrawTexture(whiteTex, new RectangleF(0, 0, 1, 1), destRect, emptySlotColor, sMapGridChain); } else { - if (grid.Grid[x - 1, y - 1].MapId != Guid.Empty) - { - if (grid.Grid[x - 1, y - 1].Tex != null && - grid.Grid[x - 1, y - 1].Tex.Width == grid.TileWidth && - grid.Grid[x - 1, y - 1].Tex.Height == grid.TileHeight) - { - DrawTexture( - grid.Grid[x - 1, y - 1].Tex, grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, sMapGridChain - ); - } - else - { - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, grid.TileWidth, - grid.TileHeight - ), System.Drawing.Color.Green, sMapGridChain - ); - } - } - else - { - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, grid.TileWidth, grid.TileHeight - ), System.Drawing.Color.Gray, sMapGridChain - ); - } + DrawTexture(tile.Tex, new RectangleF(0, 0, tile.Tex.Width, tile.Tex.Height), destRect, Color.White, sMapGridChain); } + } - if (Globals.MapGrid.ShowLines) - { - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, grid.TileWidth, 1 - ), System.Drawing.Color.DarkGray, sMapGridChain - ); - - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, 1, grid.TileHeight - ), System.Drawing.Color.DarkGray, sMapGridChain - ); + // Draw Grid Lines + if (!Globals.MapGrid.ShowLines) + { + continue; + } - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth + grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight, 1, grid.TileHeight - ), System.Drawing.Color.DarkGray, sMapGridChain - ); + var srcRect = new RectangleF(0, 0, 1, 1); + // Top + DrawTexture(whiteTex, srcRect, new RectangleF(drawX, drawY, grid.TileWidth, 1), gridLineColor, sMapGridChain); + // Bottom + DrawTexture(whiteTex, srcRect, new RectangleF(drawX, drawY + grid.TileHeight, grid.TileWidth, 1), gridLineColor, sMapGridChain); + // Left + DrawTexture(whiteTex, srcRect, new RectangleF(drawX, drawY, 1, grid.TileHeight), gridLineColor, sMapGridChain); + // Right + DrawTexture(whiteTex, srcRect, new RectangleF(drawX + grid.TileWidth, drawY, 1, grid.TileHeight), gridLineColor, sMapGridChain); - DrawTexture( - GetWhiteTex(), new RectangleF(0, 0, 1, 1), - new RectangleF( - grid.ContentRect.X + x * grid.TileWidth, - grid.ContentRect.Y + y * grid.TileHeight + grid.TileHeight, grid.TileWidth, 1 - ), System.Drawing.Color.DarkGray, sMapGridChain - ); - } - } } } }