66 * PROGRAMMER: Peter Geinitz (Wayfarer)
77 */
88
9+ using ExtendedSystemObjects ;
10+ using Imaging ;
11+ using System ;
912using System . Collections . Concurrent ;
1013using System . Collections . Generic ;
1114using System . Drawing ;
1215using System . Linq ;
1316using System . Threading . Tasks ;
1417using System . Windows . Media ;
15- using ExtendedSystemObjects ;
16- using Imaging ;
1718using Brushes = System . Drawing . Brushes ;
1819
1920namespace Solaris
@@ -46,48 +47,83 @@ internal static Bitmap GenerateImage(
4647 {
4748 var background = new Bitmap ( width * textureSize , height * textureSize ) ;
4849
49- if ( map == null )
50+ if ( map == null || textures == null )
5051 {
5152 return background ;
5253 }
5354
54- // Using ConcurrentBag removes the need for thread blocking (locking)
55+ // 1. Safe Sequential Cache Hydration Pass (File I/O)
56+ foreach ( var texture in textures . Values )
57+ {
58+ if ( string . IsNullOrWhiteSpace ( texture . Path ) ) continue ;
59+
60+ if ( ! ImageCache . ContainsKey ( texture . Path ) )
61+ {
62+ try
63+ {
64+ var loadedBmp = Render . GetBitmapFile ( texture . Path ) ;
65+ if ( loadedBmp != null )
66+ {
67+ ImageCache [ texture . Path ] = loadedBmp ;
68+ }
69+ }
70+ catch ( Exception ex )
71+ {
72+ System . Diagnostics . Trace . WriteLine ( $ "[CRITICAL] Failed to decode asset { texture . Path } : { ex . Message } ") ;
73+ }
74+ }
75+ }
76+
77+ // 2. High-Speed Memory Map Translation Pass
5578 var tiles = new ConcurrentBag < Box > ( ) ;
5679
5780 Parallel . ForEach ( map , tile =>
5881 {
5982 if ( tile . Value is not { Count : > 0 } ) return ;
6083
61- var x = tile . Key % width * textureSize ;
62- var y = tile . Key / width * textureSize ;
84+ var x = ( tile . Key % width ) * textureSize ;
85+ var y = ( tile . Key / width ) * textureSize ;
6386
6487 foreach ( var textureId in tile . Value )
6588 {
66- var texture = textures [ textureId ] ;
67- var image = ImageCache . GetOrAdd ( texture . Path , path => Render . GetBitmapFile ( path ) ) ;
68- tiles . Add ( new Box { X = x , Y = y , Layer = texture . Layer , Image = image } ) ;
89+ if ( ! textures . TryGetValue ( textureId , out var texture ) ) continue ;
90+
91+ if ( ImageCache . TryGetValue ( texture . Path , out var cachedImage ) )
92+ {
93+ tiles . Add ( new Box { X = x , Y = y , Layer = texture . Layer , Image = cachedImage } ) ;
94+ }
6995 }
7096 } ) ;
7197
72- // Convert to a list to sort by layer (so top layers render last)
7398 var sortedTiles = tiles . ToList ( ) ;
7499 sortedTiles . Sort ( ( a , b ) => a . Layer . CompareTo ( b . Layer ) ) ;
75100
76- foreach ( var slice in sortedTiles )
101+ // 3. THE GRAPHICS FIX: Open the graphics envelope ONCE for the whole map sheet
102+ using ( var graph = Graphics . FromImage ( background ) )
77103 {
78- Render . CombineBitmap ( background , slice . Image , slice . X , slice . Y ) ;
79- }
104+ // Optional: Ensure a clean alpha base line across the canvas space
105+ graph . Clear ( System . Drawing . Color . Transparent ) ;
106+
107+ // Blit all 100 tiles rapidly into the open graphics pipeline context
108+ foreach ( var slice in sortedTiles )
109+ {
110+ if ( slice . Image != null )
111+ {
112+ graph . DrawImage ( slice . Image ,
113+ new Rectangle ( slice . X , slice . Y , slice . Image . Width , slice . Image . Height ) ) ;
114+ }
115+ }
116+ } // GDI+ flushes all operations to system memory and closes cleanly here ONCE
80117
81118 return background ;
82119 }
83-
84120 /// <summary>
85121 /// Generates a grid overlay.
86122 /// </summary>
87123 /// <param name="width">The width.</param>
88124 /// <param name="height">The height.</param>
89125 /// <param name="textureSize">Size of the texture.</param>
90- /// <returns></returns>
126+ /// <returns>ImageSource representing the grid overlay. </returns>
91127 internal static ImageSource GenerateGrid ( int width , int height , int textureSize )
92128 {
93129 using var bitmap = new Bitmap ( width * textureSize , height * textureSize ) ;
@@ -109,7 +145,7 @@ internal static ImageSource GenerateGrid(int width, int height, int textureSize)
109145 /// <param name="height">The height.</param>
110146 /// <param name="textureSize">Size of the texture.</param>
111147 /// <param name="padding">The padding.</param>
112- /// <returns></returns>
148+ /// <returns>ImageSource representing the number overlay. </returns>
113149 internal static ImageSource GenerateNumbers ( int width , int height , int textureSize , int padding = 2 )
114150 {
115151 using var bitmap = new Bitmap ( width * textureSize , height * textureSize ) ;
@@ -139,7 +175,7 @@ internal static ImageSource GenerateNumbers(int width, int height, int textureSi
139175 /// </summary>
140176 /// <param name="map">The map.</param>
141177 /// <param name="idTexture">The identifier texture.</param>
142- /// <returns></returns>
178+ /// <returns>MapChangeResult representing the result of the operation. </returns>
143179 internal static MapChangeResult AddTile (
144180 Dictionary < int , List < int > > ? map , KeyValuePair < int , int > idTexture )
145181 {
@@ -155,7 +191,7 @@ internal static MapChangeResult AddTile(
155191 /// <param name="map">The map.</param>
156192 /// <param name="textures">The textures.</param>
157193 /// <param name="idLayer">The identifier layer.</param>
158- /// <returns></returns>
194+ /// <returns>MapChangeResult representing the result of the operation. </returns>
159195 internal static MapChangeResult RemoveTile (
160196 Dictionary < int , List < int > > ? map , Dictionary < int , Texture > textures , KeyValuePair < int , int > idLayer )
161197 {
@@ -194,7 +230,7 @@ internal static MapChangeResult RemoveTile(
194230 /// <param name="layer">The layer.</param>
195231 /// <param name="idTile">The identifier tile.</param>
196232 /// <returns>Image on screen</returns>
197- public static Bitmap ? AddDisplay (
233+ public static Bitmap AddDisplay (
198234 int width , int textureSize , Dictionary < int , Texture > textures , Bitmap ? layer ,
199235 KeyValuePair < int , int > idTile )
200236 {
@@ -231,7 +267,7 @@ public static Bitmap RemoveDisplay(int width, int textureSize, Bitmap? layer, in
231267 /// <param name="width">The width.</param>
232268 /// <param name="height">The height.</param>
233269 /// <param name="textureSize">Size of the texture.</param>
234- /// <returns>Movement animation </returns>
270+ /// <returns>Task representing the asynchronous operation. </returns>
235271 internal static async Task DisplayMovement ( Aurora aurora , IEnumerable < int > steps , Bitmap ? avatar ,
236272 int width , int height , int textureSize )
237273 {
0 commit comments