|
1 |
| -using System; |
2 |
| -using System.Text; |
3 |
| -using DALib.Data; |
| 1 | +using DALib.Data; |
4 | 2 | using DALib.Definitions;
|
5 | 3 | using DALib.Extensions;
|
6 | 4 | using DALib.Memory;
|
7 | 5 | using DALib.Utility;
|
8 | 6 | using SkiaSharp;
|
| 7 | +using System; |
| 8 | +using System.Text; |
9 | 9 |
|
10 | 10 | namespace DALib.Drawing;
|
11 | 11 |
|
@@ -179,146 +179,171 @@ public static SKImage RenderImage(EfaFrame efa, EfaBlendingType efaBlendingType
|
179 | 179 | /// <param name="iaDat">
|
180 | 180 | /// The IA archive.
|
181 | 181 | /// </param>
|
182 |
| - public static SKImage RenderMap(MapFile map, DataArchive seoDat, DataArchive iaDat) |
| 182 | + /// <param name="foregroundPadding"> |
| 183 | + /// The amount of padding to add to the height of the file and beginning rendering position |
| 184 | + /// </param> |
| 185 | + /// <param name="cache"> |
| 186 | + /// A <see cref="MapImageCache"/> that can be reused to share <see cref="SKImageCache{TKey}"/> caches between multiple map renderings. |
| 187 | + /// </param> |
| 188 | + |
| 189 | + public static SKImage RenderMap(MapFile map, DataArchive seoDat, DataArchive iaDat, int foregroundPadding = 512, |
| 190 | + MapImageCache? cache = null, bool dotGuides = false) |
183 | 191 | => RenderMap(
|
184 | 192 | map,
|
185 | 193 | Tileset.FromArchive("tilea", seoDat),
|
186 | 194 | PaletteLookup.FromArchive("mpt", seoDat)
|
187 |
| - .Freeze(), |
| 195 | + .Freeze(), |
188 | 196 | PaletteLookup.FromArchive("stc", iaDat)
|
189 |
| - .Freeze(), |
190 |
| - iaDat); |
| 197 | + .Freeze(), |
| 198 | + iaDat, foregroundPadding, cache, dotGuides); |
191 | 199 |
|
192 | 200 | /// <summary>
|
193 | 201 | /// Renders a MapFile, given already extracted information
|
194 | 202 | /// </summary>
|
195 | 203 | /// <param name="map">
|
196 |
| - /// The MapFile to render |
| 204 | + /// The <see cref="MapFile"/> to render |
197 | 205 | /// </param>
|
198 | 206 | /// <param name="tiles">
|
199 |
| - /// A collection of background tiles |
| 207 | + /// A <see cref="Tileset"/> representing a collection of background tiles |
200 | 208 | /// </param>
|
201 | 209 | /// <param name="bgPaletteLookup">
|
202 |
| - /// PaletteLookup for background tiles |
| 210 | + /// <see cref="PaletteLookup"/> for background tiles |
203 | 211 | /// </param>
|
204 | 212 | /// <param name="fgPaletteLookup">
|
205 |
| - /// PaletteLookup for foreground tiles |
| 213 | + /// <see cref="PaletteLookup"/> for foreground tiles |
206 | 214 | /// </param>
|
207 | 215 | /// <param name="iaDat">
|
208 |
| - /// IA archive for reading foreground tile files |
| 216 | + /// IA <see cref="DataArchive"/> for reading foreground tile files |
| 217 | + /// </param> |
| 218 | + /// <param name="foregroundPadding"> |
| 219 | + /// The amount of padding to add to the height of the file and beginning rendering position |
| 220 | + /// </param> |
| 221 | + /// <param name="cache"> |
| 222 | + /// A <see cref="MapImageCache"/> that can be reused to share <see cref="SKImageCache{TKey}"/> caches between multiple map renderings. |
209 | 223 | /// </param>
|
210 | 224 | public static SKImage RenderMap(
|
211 | 225 | MapFile map,
|
212 | 226 | Tileset tiles,
|
213 | 227 | PaletteLookup bgPaletteLookup,
|
214 | 228 | PaletteLookup fgPaletteLookup,
|
215 |
| - DataArchive iaDat) |
| 229 | + DataArchive iaDat, |
| 230 | + int foregroundPadding = 512, |
| 231 | + MapImageCache? cache = null) |
216 | 232 | {
|
217 |
| - const int FOREGROUND_PADDING = 512; |
| 233 | + var dispose = cache is null; |
| 234 | + cache ??= new MapImageCache(); |
218 | 235 |
|
219 | 236 | //create lookups so we only render each tile piece once
|
220 | 237 | using var bgCache = new SKImageCache<int>();
|
221 | 238 | using var lfgCache = new SKImageCache<int>();
|
222 | 239 | using var rfgCache = new SKImageCache<int>();
|
223 | 240 |
|
224 |
| - //calculate width and height based on isometric view |
225 |
| - var width = map.Width * CONSTANTS.TILE_WIDTH; |
226 |
| - var height = map.Height * (CONSTANTS.TILE_HEIGHT + 1) + FOREGROUND_PADDING; |
| 241 | + //calculate width and height |
| 242 | + var width = (map.Width + map.Height + 1) * CONSTANTS.HALF_TILE_WIDTH; |
| 243 | + var height = (map.Width + map.Height +1 ) * CONSTANTS.HALF_TILE_HEIGHT + foregroundPadding; |
227 | 244 | using var bitmap = new SKBitmap(width, height);
|
228 | 245 | using var canvas = new SKCanvas(bitmap);
|
229 | 246 |
|
230 | 247 | //the first tile drawn is the center tile at the top (0, 0)
|
231 |
| - var bgInitialDrawX = width / 2 - CONSTANTS.HALF_TILE_WIDTH; |
232 |
| - var bgInitialDrawY = FOREGROUND_PADDING; |
233 |
| - |
234 |
| - //render background tiles and draw them to the canvas |
235 |
| - for (var y = 0; y < map.Height; y++) |
| 248 | + var bgInitialDrawX = map.Height - 1 * CONSTANTS.HALF_TILE_WIDTH; |
| 249 | + var bgInitialDrawY = foregroundPadding; |
| 250 | + try |
236 | 251 | {
|
237 |
| - for (var x = 0; x < map.Width; x++) |
| 252 | + //render background tiles and draw them to the canvas |
| 253 | + for (var y = 0; y < map.Height; y++) |
238 | 254 | {
|
239 |
| - var bgIndex = map.Tiles[x, y].Background; |
| 255 | + for (var x = 0; x < map.Width; x++) |
| 256 | + { |
| 257 | + var bgIndex = map.Tiles[x, y].Background; |
240 | 258 |
|
241 |
| - if (bgIndex > 0) |
242 |
| - --bgIndex; |
| 259 | + if (bgIndex > 0) |
| 260 | + --bgIndex; |
243 | 261 |
|
244 |
| - var bgImage = bgCache.GetOrCreate( |
245 |
| - bgIndex, |
246 |
| - index => |
247 |
| - { |
248 |
| - var palette = bgPaletteLookup.GetPaletteForId(index + 2); |
| 262 | + var bgImage = cache.BackgroundCache.GetOrCreate( |
| 263 | + bgIndex, |
| 264 | + index => |
| 265 | + { |
| 266 | + var palette = bgPaletteLookup.GetPaletteForId(index + 2); |
249 | 267 |
|
250 |
| - return RenderTile(tiles[index], palette); |
251 |
| - }); |
| 268 | + return RenderTile(tiles[index], palette); |
| 269 | + }); |
252 | 270 |
|
253 |
| - //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
254 |
| - var drawX = bgInitialDrawX + x * CONSTANTS.HALF_TILE_WIDTH; |
255 |
| - var drawY = bgInitialDrawY + x * CONSTANTS.HALF_TILE_HEIGHT; |
| 271 | + //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
| 272 | + var drawX = bgInitialDrawX + x * CONSTANTS.HALF_TILE_WIDTH; |
| 273 | + var drawY = bgInitialDrawY + x * CONSTANTS.HALF_TILE_HEIGHT; |
| 274 | + canvas.DrawImage(bgImage, drawX, drawY); |
| 275 | + } |
256 | 276 |
|
257 |
| - canvas.DrawImage(bgImage, drawX, drawY); |
| 277 | + //for each Y axis iteration, we want to move the draw position half a tile to the left and down from the initial draw position |
| 278 | + bgInitialDrawX -= CONSTANTS.HALF_TILE_WIDTH; |
| 279 | + bgInitialDrawY += CONSTANTS.HALF_TILE_HEIGHT; |
258 | 280 | }
|
259 | 281 |
|
260 |
| - //for each Y axis iteration, we want to move the draw position half a tile to the left and down from the initial draw position |
261 |
| - bgInitialDrawX -= CONSTANTS.HALF_TILE_WIDTH; |
262 |
| - bgInitialDrawY += CONSTANTS.HALF_TILE_HEIGHT; |
263 |
| - } |
264 |
| - |
265 |
| - //render left and right foreground tiles and draw them to the canvas |
266 |
| - var fgInitialDrawX = width / 2 - CONSTANTS.HALF_TILE_WIDTH; |
267 |
| - var fgInitialDrawY = FOREGROUND_PADDING; |
| 282 | + //render left and right foreground tiles and draw them to the canvas |
| 283 | + var fgInitialDrawX = map.Height * CONSTANTS.HALF_TILE_WIDTH; |
| 284 | + var fgInitialDrawY = foregroundPadding; |
268 | 285 |
|
269 |
| - for (var y = 0; y < map.Height; y++) |
270 |
| - { |
271 |
| - for (var x = 0; x < map.Width; x++) |
| 286 | + for (var y = 0; y < map.Height; y++) |
272 | 287 | {
|
273 |
| - var tile = map.Tiles[x, y]; |
274 |
| - var lfgIndex = tile.LeftForeground; |
275 |
| - var rfgIndex = tile.RightForeground; |
276 |
| - |
277 |
| - //render left foreground |
278 |
| - var lfgImage = lfgCache.GetOrCreate( |
279 |
| - lfgIndex, |
280 |
| - index => |
281 |
| - { |
282 |
| - var hpf = HpfFile.FromArchive($"stc{index:D5}.hpf", iaDat); |
283 |
| - var palette = fgPaletteLookup.GetPaletteForId(index + 1); |
284 |
| - |
285 |
| - return RenderImage(hpf, palette); |
286 |
| - }); |
287 |
| - |
288 |
| - //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
289 |
| - var lfgDrawX = fgInitialDrawX + x * CONSTANTS.HALF_TILE_WIDTH; |
290 |
| - |
291 |
| - var lfgDrawY = fgInitialDrawY + (x + 1) * CONSTANTS.HALF_TILE_HEIGHT - lfgImage.Height + CONSTANTS.HALF_TILE_HEIGHT; |
292 |
| - |
293 |
| - if ((lfgIndex % 10000) > 1) |
294 |
| - canvas.DrawImage(lfgImage, lfgDrawX, lfgDrawY); |
295 |
| - |
296 |
| - //render right foreground |
297 |
| - var rfgImage = rfgCache.GetOrCreate( |
298 |
| - rfgIndex, |
299 |
| - index => |
300 |
| - { |
301 |
| - var hpf = HpfFile.FromArchive($"stc{index:D5}.hpf", iaDat); |
302 |
| - var palette = fgPaletteLookup.GetPaletteForId(index + 1); |
303 |
| - |
304 |
| - return RenderImage(hpf, palette); |
305 |
| - }); |
306 |
| - |
307 |
| - //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
308 |
| - var rfgDrawX = fgInitialDrawX + (x + 1) * CONSTANTS.HALF_TILE_WIDTH; |
309 |
| - |
310 |
| - var rfgDrawY = fgInitialDrawY + (x + 1) * CONSTANTS.HALF_TILE_HEIGHT - rfgImage.Height + CONSTANTS.HALF_TILE_HEIGHT; |
311 |
| - |
312 |
| - if ((rfgIndex % 10000) > 1) |
313 |
| - canvas.DrawImage(rfgImage, rfgDrawX, rfgDrawY); |
| 288 | + for (var x = 0; x < map.Width; x++) |
| 289 | + { |
| 290 | + var tile = map.Tiles[x, y]; |
| 291 | + var lfgIndex = tile.LeftForeground; |
| 292 | + var rfgIndex = tile.RightForeground; |
| 293 | + |
| 294 | + //render left foreground |
| 295 | + var lfgImage = cache.LeftForegroundCache.GetOrCreate( |
| 296 | + lfgIndex, |
| 297 | + index => |
| 298 | + { |
| 299 | + var hpf = HpfFile.FromArchive($"stc{index:D5}.hpf", iaDat); |
| 300 | + var palette = fgPaletteLookup.GetPaletteForId(index + 1); |
| 301 | + |
| 302 | + return RenderImage(hpf, palette); |
| 303 | + }); |
| 304 | + |
| 305 | + //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
| 306 | + var lfgDrawX = fgInitialDrawX + x * CONSTANTS.HALF_TILE_WIDTH; |
| 307 | + |
| 308 | + var lfgDrawY = fgInitialDrawY + (x + 1) * CONSTANTS.HALF_TILE_HEIGHT - lfgImage.Height + |
| 309 | + CONSTANTS.HALF_TILE_HEIGHT; |
| 310 | + |
| 311 | + if ((lfgIndex % 10000) > 1) |
| 312 | + canvas.DrawImage(lfgImage, lfgDrawX, lfgDrawY); |
| 313 | + |
| 314 | + //render right foreground |
| 315 | + var rfgImage = cache.RightForegroundCache.GetOrCreate( |
| 316 | + rfgIndex, |
| 317 | + index => |
| 318 | + { |
| 319 | + var hpf = HpfFile.FromArchive($"stc{index:D5}.hpf", iaDat); |
| 320 | + var palette = fgPaletteLookup.GetPaletteForId(index + 1); |
| 321 | + |
| 322 | + return RenderImage(hpf, palette); |
| 323 | + }); |
| 324 | + |
| 325 | + //for each X axis iteration, we want to move the draw position half a tile to the right and down from the initial draw position |
| 326 | + var rfgDrawX = fgInitialDrawX + (x + 1) * CONSTANTS.HALF_TILE_WIDTH; |
| 327 | + |
| 328 | + var rfgDrawY = fgInitialDrawY + (x + 1) * CONSTANTS.HALF_TILE_HEIGHT - rfgImage.Height + |
| 329 | + CONSTANTS.HALF_TILE_HEIGHT; |
| 330 | + |
| 331 | + if ((rfgIndex % 10000) > 1) |
| 332 | + canvas.DrawImage(rfgImage, rfgDrawX, rfgDrawY); |
| 333 | + } |
| 334 | + |
| 335 | + //for each Y axis iteration, we want to move the draw position half a tile to the left and down from the initial draw position |
| 336 | + fgInitialDrawX -= CONSTANTS.HALF_TILE_WIDTH; |
| 337 | + fgInitialDrawY += CONSTANTS.HALF_TILE_HEIGHT; |
314 | 338 | }
|
315 |
| - |
316 |
| - //for each Y axis iteration, we want to move the draw position half a tile to the left and down from the initial draw position |
317 |
| - fgInitialDrawX -= CONSTANTS.HALF_TILE_WIDTH; |
318 |
| - fgInitialDrawY += CONSTANTS.HALF_TILE_HEIGHT; |
| 339 | + return SKImage.FromBitmap(bitmap); |
| 340 | + } |
| 341 | + finally |
| 342 | + { |
| 343 | + if (dispose) |
| 344 | + cache.Dispose(); |
319 | 345 | }
|
320 | 346 |
|
321 |
| - return SKImage.FromBitmap(bitmap); |
322 | 347 | }
|
323 | 348 |
|
324 | 349 | /// <summary>
|
|
0 commit comments