Skip to content

Commit b261174

Browse files
committed
rework image import to handle different image counts in source folder
1 parent d360f18 commit b261174

File tree

3 files changed

+61
-53
lines changed

3 files changed

+61
-53
lines changed

Common/IEnumerableExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ namespace OpenLoco.Common
22
{
33
public static class IEnumerableExtensions
44
{
5-
public static IEnumerable<T?> Fill<T>(this IEnumerable<T?> source, int minLength, T? fillValue = default)
5+
public static IEnumerable<T> Fill<T>(this IEnumerable<T> source, int minLength, T fillValue)
66
{
77
var i = 0;
88
foreach (var item in source)

Gui/ViewModels/DatTypes/DatObjectEditorViewModel.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,14 @@ void SaveCore(string filename, SawyerEncoding? encodingToUse = null)
222222

223223
var saveDir = Path.GetDirectoryName(filename);
224224

225-
if (string.IsNullOrEmpty(saveDir) || !Directory.Exists(saveDir))
225+
if (string.IsNullOrEmpty(saveDir))
226226
{
227-
logger.Error("Cannot save - directory is invalid");
227+
logger.Error("Cannot save - directory is null or empty");
228+
return;
229+
}
230+
else if (!Directory.Exists(saveDir))
231+
{
232+
logger.Error($"Cannot save - directory does not exist: \"{saveDir}\"");
228233
return;
229234
}
230235

Gui/ViewModels/SubObjectTypes/ImageTableViewModel.cs

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Avalonia.Media.Imaging;
33
using Avalonia.Threading;
44
using DynamicData;
5+
using OpenLoco.Common;
56
using OpenLoco.Common.Logging;
67
using OpenLoco.Dat;
78
using OpenLoco.Dat.Types;
@@ -19,7 +20,6 @@
1920
using System.Reactive.Linq;
2021
using System.Text.Json;
2122
using System.Text.Json.Serialization;
22-
using System.Text.RegularExpressions;
2323
using System.Threading.Tasks;
2424
using System.Windows.Input;
2525
using Image = SixLabors.ImageSharp.Image;
@@ -55,7 +55,10 @@ public enum ColourSwatches
5555
public record SpriteOffset(
5656
[property: JsonPropertyName("path")] string Path,
5757
[property: JsonPropertyName("x")] int16_t X,
58-
[property: JsonPropertyName("y")] int16_t Y);
58+
[property: JsonPropertyName("y")] int16_t Y)
59+
{
60+
public static SpriteOffset Zero => new SpriteOffset(string.Empty, 0, 0);
61+
}
5962

6063
public class ImageTableViewModel : ReactiveObject, IExtraContentViewModel
6164
{
@@ -249,42 +252,55 @@ public async Task ImportImages()
249252

250253
try
251254
{
255+
Logger.Debug($"{G1Provider.G1Elements.Count} images in current object");
256+
257+
// count files in dir and check naming
258+
var files = Directory.GetFiles(dirPath, "*.png", SearchOption.AllDirectories);
259+
260+
Logger.Debug($"{files.Length} files in current directory");
261+
262+
IEnumerable<SpriteOffset> offsets;
263+
264+
// check for offsets file
252265
var offsetsFile = Path.Combine(dirPath, "sprites.json");
253266
if (File.Exists(offsetsFile))
254267
{
255-
// found blender folder
256-
var offsets = JsonSerializer.Deserialize<ICollection<SpriteOffset>>(File.ReadAllText(offsetsFile)); // sprites.json is an unnamed array so we need ICollection here, not IEnumerable
268+
offsets = JsonSerializer.Deserialize<ICollection<SpriteOffset>>(File.ReadAllText(offsetsFile)); // sprites.json is an unnamed array so we need ICollection here, not IEnumerable
257269
ArgumentNullException.ThrowIfNull(offsets);
258-
Logger.Debug("Found sprites.json file, using that");
259-
260-
if (offsets.Count != G1Provider.G1Elements.Count)
261-
{
262-
Logger.Warning($"Expected {G1Provider.G1Elements.Count} offsets, got {offsets.Count} offsets. Continue at your peril.");
263-
}
264-
265-
foreach (var offset in offsets)
266-
{
267-
var filename = Path.Combine(dirPath, offset.Path);
268-
LoadSprite(filename, offset);
269-
}
270+
Logger.Debug("Found sprites.json file; using that");
270271
}
271272
else
272273
{
273-
Logger.Debug("No sprites.json file found");
274-
var files = Directory.GetFiles(dirPath, "*", SearchOption.AllDirectories);
274+
offsets = G1Provider.G1Elements.Select((x, i) => new SpriteOffset($"{i}.png", x.XOffset, x.YOffset));
275+
Logger.Debug("Didn't find sprites.json; using existing G1Element32 offsets");
276+
}
277+
278+
offsets = offsets.Fill(files.Length, SpriteOffset.Zero);
279+
280+
// clear existing images
281+
Logger.Info("Clearing current G1Element32s and existing object images");
282+
G1Provider.G1Elements.Clear();
283+
Images.Clear();
284+
Bitmaps.Clear();
285+
286+
// load files
287+
var offsetList = offsets.ToList();
288+
for (var i = 0; i < files.Length; ++i)
289+
{
290+
var filename = Path.Combine(dirPath, $"{i}.png");
275291

276-
if (files.Length != G1Provider.G1Elements.Count)
292+
if (i < G1Provider.G1Elements.Count)
277293
{
278-
Logger.Warning($"Expected {G1Provider.G1Elements.Count} images, got {files.Length} images. Continue at your peril.");
294+
var g1 = G1Provider.G1Elements[i];
295+
LoadSprite(filename, 0, offsetList[i].X, offsetList[i].Y, g1.Flags, g1.ZoomOffset);
279296
}
280-
281-
foreach (var filename in files)
297+
else
282298
{
283-
LoadSprite(filename);
299+
LoadSprite(filename, 0, offsetList[i].X, offsetList[i].Y, G1ElementFlags.None, 0);
284300
}
285301
}
286302

287-
Logger.Debug("Import successful");
303+
Logger.Debug($"Imported {G1Provider.G1Elements.Count} images successfully");
288304
this.RaisePropertyChanged(nameof(Bitmaps));
289305
}
290306
catch (Exception ex)
@@ -294,38 +310,25 @@ public async Task ImportImages()
294310
}
295311

296312
animationTimer.Start();
297-
}
298-
299-
void LoadSprite(string filename, SpriteOffset? offset = null)
300-
{
301-
if (!Path.Exists(filename))
302-
{
303-
Logger.Error($"File doesn't exist: \"{filename}\"");
304-
return;
305-
}
306313

307-
var match = Regex.Match(Path.GetFileNameWithoutExtension(filename), @".*?(\d+).*?");
308-
if (!match.Success)
314+
void LoadSprite(string filename, uint imageOffset, short xOffset, short yOffset, G1ElementFlags flags, short zoomOffset)
309315
{
310-
Logger.Error($"Couldn't parse sprite index from filename: \"{filename}\"");
311-
return;
312-
}
316+
if (!Path.Exists(filename))
317+
{
318+
Logger.Error($"File doesn't exist: \"{filename}\"");
319+
return;
320+
}
313321

314-
var index = int.Parse(match.Groups[1].Value);
315-
var img = Image.Load<Rgba32>(filename);
322+
var img = Image.Load<Rgba32>(filename);
316323

317-
if (index >= G1Provider.G1Elements.Count)
318-
{
319-
var newElement = new G1Element32(0, (int16_t)img.Width, (int16_t)img.Height, 0, 0, G1ElementFlags.None, 0)
324+
var newElement = new G1Element32(imageOffset, (int16_t)img.Width, (int16_t)img.Height, xOffset, yOffset, flags, zoomOffset)
320325
{
321-
ImageData = PaletteMap.ConvertRgba32ImageToG1Data(img, G1ElementFlags.None)
326+
ImageData = PaletteMap.ConvertRgba32ImageToG1Data(img, flags)
322327
};
323-
G1Provider.G1Elements.Insert(index, newElement);
324-
Images.Insert(index, img); // update the UI
325-
}
326-
else
327-
{
328-
UpdateImage(img, index, offset);
328+
329+
G1Provider.G1Elements.Add(newElement);
330+
Images.Add(img);
331+
Bitmaps.Add(G1ImageConversion.CreateAvaloniaImage(img));
329332
}
330333
}
331334

0 commit comments

Comments
 (0)