@@ -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