Skip to content

Commit 5185f5b

Browse files
committed
Optimize rendering of waypoints and base nodes
1 parent a7068e0 commit 5185f5b

File tree

1 file changed

+138
-65
lines changed

1 file changed

+138
-65
lines changed

src/TSMapEditor/Rendering/MapView.cs

Lines changed: 138 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ public interface IMapView
3636
/// </summary>
3737
public class MapView : IMapView
3838
{
39+
struct WaypointDrawStruct
40+
{
41+
public Waypoint Waypoint;
42+
public Color Color;
43+
public Rectangle DrawRectangle;
44+
45+
public WaypointDrawStruct(Waypoint waypoint, Color color, Rectangle drawRectangle)
46+
{
47+
Waypoint = waypoint;
48+
Color = color;
49+
DrawRectangle = drawRectangle;
50+
}
51+
}
52+
3953
private static Color[] MarbleMadnessTileHeightLevelColors = new Color[]
4054
{
4155
new Color(165, 28, 68),
@@ -126,6 +140,8 @@ public MapView(WindowManager windowManager, Map map, TheaterGraphics theaterGrap
126140
private List<AlphaImageRenderStruct> alphaImagesToRender = new List<AlphaImageRenderStruct>();
127141
private ObjectSpriteRecord objectSpriteRecord = new ObjectSpriteRecord();
128142

143+
private List<WaypointDrawStruct> waypointsToRender = new List<WaypointDrawStruct>();
144+
129145
private Stopwatch refreshStopwatch;
130146

131147
private ulong refreshIndex;
@@ -756,9 +772,105 @@ public void DrawTerrainTile(MapTile tile)
756772
}
757773
}
758774

775+
/// <summary>
776+
/// Draws all waypoints visible on the screen, utilizing batching as much as possible.
777+
/// </summary>
759778
private void DrawWaypoints()
760779
{
761-
Map.Waypoints.ForEach(DrawWaypoint);
780+
waypointsToRender.Clear();
781+
782+
// Instead of drawing one waypoint at a time, we draw the same-texture element of
783+
// all waypoints at once, and iterate through the waypoints multiple times.
784+
// While it seems heavier, this approach allows MonoGame's SpriteBatch to batch
785+
// the draw calls, making the process much lighter in practice.
786+
787+
// Gather waypoints to draw
788+
for (int i = 0; i < Map.Waypoints.Count; i++)
789+
{
790+
var waypoint = Map.Waypoints[i];
791+
792+
Point2D drawPoint = CellMath.CellTopLeftPointFromCellCoords(waypoint.Position, Map);
793+
794+
var cell = Map.GetTile(waypoint.Position);
795+
if (cell != null && !EditorState.Is2DMode)
796+
drawPoint -= new Point2D(0, cell.Level * Constants.CellHeight);
797+
798+
if (MinimapUsers.Count == 0 &&
799+
(Camera.TopLeftPoint.X > drawPoint.X + EditorGraphics.TileBorderTexture.Width ||
800+
Camera.TopLeftPoint.Y > drawPoint.Y + EditorGraphics.TileBorderTexture.Height ||
801+
GetCameraRightXCoord() < drawPoint.X ||
802+
GetCameraBottomYCoord() < drawPoint.Y))
803+
{
804+
// This waypoint is outside the camera
805+
continue;
806+
}
807+
808+
Color waypointColor = string.IsNullOrEmpty(waypoint.EditorColor) ? Color.Fuchsia : waypoint.XNAColor;
809+
var drawRectangle = new Rectangle(drawPoint.X, drawPoint.Y, EditorGraphics.GenericTileTexture.Width, EditorGraphics.GenericTileTexture.Height);
810+
811+
waypointsToRender.Add(new WaypointDrawStruct(waypoint, waypointColor, drawRectangle));
812+
}
813+
814+
// Draw darkened background for all waypoints
815+
for (int i = 0; i < waypointsToRender.Count; i++)
816+
{
817+
var waypoint = waypointsToRender[i];
818+
819+
Renderer.DrawTexture(EditorGraphics.GenericTileTexture, waypoint.DrawRectangle, new Color(0, 0, 0, 128));
820+
}
821+
822+
// Draw tile border for all waypoints
823+
for (int i = 0; i < waypointsToRender.Count; i++)
824+
{
825+
var waypoint = waypointsToRender[i];
826+
827+
Renderer.DrawTexture(EditorGraphics.TileBorderTexture, waypoint.DrawRectangle, waypoint.Color);
828+
}
829+
830+
// Draw text for all waypoints
831+
for (int i = 0; i < waypointsToRender.Count; i++)
832+
{
833+
int fontIndex = Constants.UIBoldFont;
834+
string waypointIdentifier = waypointsToRender[i].Waypoint.Identifier.ToString();
835+
var textDimensions = Renderer.GetTextDimensions(waypointIdentifier, fontIndex);
836+
Renderer.DrawStringWithShadow(waypointIdentifier, fontIndex,
837+
new Vector2(waypointsToRender[i].DrawRectangle.X + ((Constants.CellSizeX - textDimensions.X) / 2),
838+
waypointsToRender[i].DrawRectangle.Y + ((Constants.CellSizeY - textDimensions.Y) / 2)),
839+
waypointsToRender[i].Color);
840+
}
841+
}
842+
843+
private void DrawWaypoint(Waypoint waypoint)
844+
{
845+
Point2D drawPoint = CellMath.CellTopLeftPointFromCellCoords(waypoint.Position, Map);
846+
847+
var cell = Map.GetTile(waypoint.Position);
848+
if (cell != null && !EditorState.Is2DMode)
849+
drawPoint -= new Point2D(0, cell.Level * Constants.CellHeight);
850+
851+
if (MinimapUsers.Count == 0 &&
852+
(Camera.TopLeftPoint.X > drawPoint.X + EditorGraphics.TileBorderTexture.Width ||
853+
Camera.TopLeftPoint.Y > drawPoint.Y + EditorGraphics.TileBorderTexture.Height ||
854+
GetCameraRightXCoord() < drawPoint.X ||
855+
GetCameraBottomYCoord() < drawPoint.Y))
856+
{
857+
// This waypoint is outside the camera
858+
return;
859+
}
860+
861+
Color waypointColor = string.IsNullOrEmpty(waypoint.EditorColor) ? Color.Fuchsia : waypoint.XNAColor;
862+
var drawRectangle = new Rectangle(drawPoint.X, drawPoint.Y, EditorGraphics.GenericTileTexture.Width, EditorGraphics.GenericTileTexture.Height);
863+
864+
Renderer.DrawTexture(EditorGraphics.GenericTileTexture, drawRectangle, new Color(0, 0, 0, 128));
865+
Renderer.DrawTexture(EditorGraphics.TileBorderTexture, drawRectangle, waypointColor);
866+
867+
int fontIndex = Constants.UIBoldFont;
868+
string waypointIdentifier = waypoint.Identifier.ToString();
869+
var textDimensions = Renderer.GetTextDimensions(waypointIdentifier, fontIndex);
870+
Renderer.DrawStringWithShadow(waypointIdentifier,
871+
fontIndex,
872+
new Vector2(drawPoint.X + ((Constants.CellSizeX - textDimensions.X) / 2), drawPoint.Y + ((Constants.CellSizeY - textDimensions.Y) / 2)),
873+
waypointColor);
762874
}
763875

764876
private void DrawCellTags()
@@ -864,6 +976,7 @@ private void DrawGameObjects()
864976
}
865977

866978
ProcessObjectSpriteRecord(false, true, false);
979+
objectSpriteRecord.Clear(false);
867980
}
868981

869982
private void DrawObject(GameObject gameObject)
@@ -989,15 +1102,19 @@ private void ProcessObjectSpriteRecord(bool complexDepth, bool processShadows, b
9891102

9901103
private void DrawBaseNodes()
9911104
{
992-
Renderer.PushSettings(new SpriteBatchSettings(SpriteSortMode.Immediate, BlendState.Opaque, null, null, null, palettedColorDrawEffect));
993-
foreach (var baseNode in Map.GraphicalBaseNodes)
1105+
if (Map.GraphicalBaseNodes.Count > 0)
9941106
{
995-
DrawBaseNode(baseNode);
1107+
foreach (var baseNode in Map.GraphicalBaseNodes)
1108+
{
1109+
RecordBaseNode(baseNode);
1110+
}
1111+
1112+
ProcessObjectSpriteRecord(false, false, false);
1113+
objectSpriteRecord.Clear(false);
9961114
}
997-
Renderer.PopSettings();
9981115
}
9991116

1000-
private void DrawBaseNode(GraphicalBaseNode graphicalBaseNode)
1117+
private void RecordBaseNode(GraphicalBaseNode graphicalBaseNode)
10011118
{
10021119
// TODO add base nodes to the regular rendering code
10031120

@@ -1015,7 +1132,7 @@ private void DrawBaseNode(GraphicalBaseNode graphicalBaseNode)
10151132
return;
10161133
}
10171134

1018-
const float opacity = 0.25f;
1135+
const float opacity = 0.35f;
10191136

10201137
ShapeImage bibGraphics = TheaterGraphics.BuildingBibTextures[graphicalBaseNode.BuildingType.Index];
10211138
ShapeImage graphics = TheaterGraphics.BuildingTextures[graphicalBaseNode.BuildingType.Index];
@@ -1028,9 +1145,8 @@ private void DrawBaseNode(GraphicalBaseNode graphicalBaseNode)
10281145

10291146
if ((graphics == null || graphics.GetFrame(frameIndex) == null) && (bibGraphics == null || bibGraphics.GetFrame(0) == null))
10301147
{
1031-
SetPaletteEffectParams(palettedColorDrawEffect, null, false, false, false);
1032-
Renderer.DrawStringWithShadow(iniName, Constants.UIBoldFont, drawPoint.ToXNAVector(), replacementColor, 1.0f);
1033-
Renderer.DrawStringWithShadow("#" + baseNodeIndex, Constants.UIBoldFont, drawPoint.ToXNAVector() + new Vector2(0f, 20f), baseNodeIndexColor);
1148+
objectSpriteRecord.AddTextEntry(new TextEntry(iniName, replacementColor, drawPoint));
1149+
objectSpriteRecord.AddTextEntry(new TextEntry("# " + baseNodeIndex, baseNodeIndexColor, drawPoint + new Point2D(0, 20)));
10341150
return;
10351151
}
10361152

@@ -1050,33 +1166,25 @@ private void DrawBaseNode(GraphicalBaseNode graphicalBaseNode)
10501166
int bibFinalDrawPointX = drawPoint.X - bibFrame.ShapeWidth / 2 + bibFrame.OffsetX + Constants.CellSizeX / 2;
10511167
int bibFinalDrawPointY = drawPoint.Y - bibFrame.ShapeHeight / 2 + bibFrame.OffsetY + Constants.CellSizeY / 2 + yDrawOffset;
10521168

1053-
SetPaletteEffectParams(palettedColorDrawEffect, bibGraphics.GetPaletteTexture(), true, true, false);
1054-
1055-
Renderer.DrawTexture(texture, new Rectangle(
1056-
bibFinalDrawPointX, bibFinalDrawPointY,
1169+
objectSpriteRecord.AddGraphicsEntry(new ObjectSpriteEntry(bibGraphics.GetPaletteTexture(), bibFrame,
1170+
new Rectangle(bibFinalDrawPointX, bibFinalDrawPointY,
10571171
bibFrame.SourceRectangle.Width, bibFrame.SourceRectangle.Height),
1058-
bibFrame.SourceRectangle, remapColor,
1059-
0f, Vector2.Zero, SpriteEffects.None, 0f);
1172+
remapColor, false, false, new DepthRectangle(1f, 1f)));
10601173

10611174
if (bibGraphics.HasRemapFrames())
10621175
{
1063-
Renderer.DrawTexture(bibGraphics.GetRemapFrame(0).Texture,
1064-
new Rectangle(bibFinalDrawPointX, bibFinalDrawPointY, bibFrame.SourceRectangle.Width, bibFrame.SourceRectangle.Height),
1065-
bibGraphics.GetRemapFrame(0).SourceRectangle,
1066-
remapColor,
1067-
0f,
1068-
Vector2.Zero,
1069-
SpriteEffects.None,
1070-
0f);
1176+
objectSpriteRecord.AddGraphicsEntry(new ObjectSpriteEntry(bibGraphics.GetPaletteTexture(), bibGraphics.GetRemapFrame(0),
1177+
new Rectangle(bibFinalDrawPointX, bibFinalDrawPointY,
1178+
bibFrame.SourceRectangle.Width, bibFrame.SourceRectangle.Height),
1179+
remapColor, true, false, new DepthRectangle(1f, 1f)));
10711180
}
10721181
}
10731182
}
10741183

10751184
var frame = graphics.GetFrame(frameIndex);
10761185
if (frame == null)
10771186
{
1078-
SetPaletteEffectParams(palettedColorDrawEffect, null, false, false, false);
1079-
Renderer.DrawStringWithShadow("#" + baseNodeIndex, Constants.UIBoldFont, drawPoint.ToXNAVector(), baseNodeIndexColor);
1187+
objectSpriteRecord.AddTextEntry(new TextEntry("#" + baseNodeIndex, baseNodeIndexColor, drawPoint));
10801188
return;
10811189
}
10821190

@@ -1086,50 +1194,15 @@ private void DrawBaseNode(GraphicalBaseNode graphicalBaseNode)
10861194
int y = drawPoint.Y - frame.ShapeHeight / 2 + frame.OffsetY + Constants.CellSizeY / 2 + yDrawOffset;
10871195
Rectangle drawRectangle = new Rectangle(x, y, frame.SourceRectangle.Width, frame.SourceRectangle.Height);
10881196

1089-
SetPaletteEffectParams(palettedColorDrawEffect, graphics.GetPaletteTexture(), true, true, false);
1090-
1091-
Renderer.DrawTexture(texture, frame.SourceRectangle, drawRectangle, remapColor);
1197+
objectSpriteRecord.AddGraphicsEntry(new ObjectSpriteEntry(graphics.GetPaletteTexture(), texture, frame.SourceRectangle, drawRectangle, remapColor, false, false, new DepthRectangle(1f, 1f)));
10921198

10931199
if (graphics.HasRemapFrames())
10941200
{
1095-
Renderer.DrawTexture(graphics.GetRemapFrame(frameIndex).Texture, graphics.GetRemapFrame(frameIndex).SourceRectangle, drawRectangle, remapColor);
1201+
objectSpriteRecord.AddGraphicsEntry(new ObjectSpriteEntry(graphics.GetPaletteTexture(), graphics.GetRemapFrame(frameIndex).Texture,
1202+
graphics.GetRemapFrame(frameIndex).SourceRectangle, drawRectangle, remapColor, true, false, new DepthRectangle(1f, 1f)));
10961203
}
10971204

1098-
SetPaletteEffectParams(palettedColorDrawEffect, null, false, false, false);
1099-
Renderer.DrawStringWithShadow("#" + baseNodeIndex, Constants.UIBoldFont, drawPoint.ToXNAVector(), baseNodeIndexColor);
1100-
}
1101-
1102-
private void DrawWaypoint(Waypoint waypoint)
1103-
{
1104-
Point2D drawPoint = CellMath.CellTopLeftPointFromCellCoords(waypoint.Position, Map);
1105-
1106-
var cell = Map.GetTile(waypoint.Position);
1107-
if (cell != null && !EditorState.Is2DMode)
1108-
drawPoint -= new Point2D(0, cell.Level * Constants.CellHeight);
1109-
1110-
if (MinimapUsers.Count == 0 &&
1111-
(Camera.TopLeftPoint.X > drawPoint.X + EditorGraphics.TileBorderTexture.Width ||
1112-
Camera.TopLeftPoint.Y > drawPoint.Y + EditorGraphics.TileBorderTexture.Height ||
1113-
GetCameraRightXCoord() < drawPoint.X ||
1114-
GetCameraBottomYCoord() < drawPoint.Y))
1115-
{
1116-
// This waypoint is outside the camera
1117-
return;
1118-
}
1119-
1120-
Color waypointColor = string.IsNullOrEmpty(waypoint.EditorColor) ? Color.Fuchsia : waypoint.XNAColor;
1121-
var drawRectangle = new Rectangle(drawPoint.X, drawPoint.Y, EditorGraphics.GenericTileTexture.Width, EditorGraphics.GenericTileTexture.Height);
1122-
1123-
Renderer.DrawTexture(EditorGraphics.GenericTileTexture, drawRectangle, new Color(0, 0, 0, 128));
1124-
Renderer.DrawTexture(EditorGraphics.TileBorderTexture, drawRectangle, waypointColor);
1125-
1126-
int fontIndex = Constants.UIBoldFont;
1127-
string waypointIdentifier = waypoint.Identifier.ToString();
1128-
var textDimensions = Renderer.GetTextDimensions(waypointIdentifier, fontIndex);
1129-
Renderer.DrawStringWithShadow(waypointIdentifier,
1130-
fontIndex,
1131-
new Vector2(drawPoint.X + ((Constants.CellSizeX - textDimensions.X) / 2), drawPoint.Y + ((Constants.CellSizeY - textDimensions.Y) / 2)),
1132-
waypointColor);
1205+
objectSpriteRecord.AddTextEntry(new TextEntry("#" + baseNodeIndex, baseNodeIndexColor, drawPoint));
11331206
}
11341207

11351208
private void DrawCellTag(CellTag cellTag)

0 commit comments

Comments
 (0)