11
11
using SixLabors . ImageSharp . PixelFormats ;
12
12
using System ;
13
13
using System . Collections . Generic ;
14
- using System . Collections . Immutable ;
15
14
using System . IO ;
16
15
using System . Linq ;
17
16
using System . Reactive . Linq ;
17
+ using System . Text . Json ;
18
+ using System . Text . Json . Serialization ;
18
19
using System . Text . RegularExpressions ;
19
20
using System . Threading . Tasks ;
20
21
using System . Windows . Input ;
21
22
using Image = SixLabors . ImageSharp . Image ;
22
23
23
24
namespace AvaGui . ViewModels
24
25
{
26
+ public record SpriteOffset (
27
+ [ property: JsonPropertyName ( "path" ) ] string Path ,
28
+ [ property: JsonPropertyName ( "x" ) ] int16_t X ,
29
+ [ property: JsonPropertyName ( "y" ) ] int16_t Y ) ;
30
+
25
31
public class ImageTableViewModel : ReactiveObject , IExtraContentViewModel , ILocoFileViewModel
26
32
{
27
33
readonly IHasG1Elements G1Provider ;
@@ -186,6 +192,8 @@ public UIG1Element32? SelectedG1Element
186
192
//todo: second half should be model
187
193
public async Task ImportImages ( )
188
194
{
195
+ animationTimer . Stop ( ) ;
196
+
189
197
var folders = await PlatformSpecific . OpenFolderPicker ( ) ;
190
198
var dir = folders . FirstOrDefault ( ) ;
191
199
if ( dir == null )
@@ -199,48 +207,71 @@ public async Task ImportImages()
199
207
return ;
200
208
}
201
209
202
- var files = Directory . GetFiles ( dirPath ) ;
203
- if ( files . Length == 0 )
204
- {
205
- return ;
206
- }
207
-
208
210
try
209
211
{
210
- var sorted = files . OrderBy ( static f =>
212
+ var offsetsFile = Path . Combine ( dirPath , "sprites.json" ) ;
213
+ if ( File . Exists ( offsetsFile ) )
211
214
{
212
- var match = Regex . Match ( Path . GetFileNameWithoutExtension ( f ) , @".*?(\d+).*?" ) ;
213
- return match . Success
214
- ? int . Parse ( match . Groups [ 1 ] . Value )
215
- : throw new InvalidDataException ( $ "Directory contains file that doesn't contain a number={ f } ") ;
216
- } ) ;
217
-
218
- var sortedH = sorted . ToImmutableHashSet ( ) ;
215
+ // found blender folder
216
+ var offsets = JsonSerializer . Deserialize < ICollection < SpriteOffset > > ( File . ReadAllText ( offsetsFile ) ) ; // sprites.json is an unnamed array so we need ICollection here, not IEnumerable
217
+ Logger . Debug ( "Found sprites.json file, using that" ) ;
219
218
220
- var g1Elements = new List < G1Element32 > ( ) ;
221
- var i = 0 ;
222
- foreach ( var file in sorted )
219
+ foreach ( var offset in offsets )
220
+ {
221
+ var filename = Path . Combine ( dirPath , offset . Path ) ;
222
+ LoadSprite ( filename , offset ) ;
223
+ }
224
+ }
225
+ else
223
226
{
224
- var img = Image . Load < Rgba32 > ( file ) ;
225
- Images [ i ] = img ;
226
- var currG1 = G1Provider . G1Elements [ i ] ;
227
- currG1 = currG1 with
227
+ Logger . Debug ( "No sprites.json file found" ) ;
228
+ foreach ( var filename in Directory . GetFiles ( dirPath , "*" , SearchOption . AllDirectories ) )
228
229
{
229
- Width = ( int16_t ) img . Width ,
230
- Height = ( int16_t ) img . Height ,
231
- Flags = currG1 . Flags & ~ G1ElementFlags . IsRLECompressed , // SawyerStreamWriter::SaveImageTable does this anyways
232
- ImageData = PaletteMap . ConvertRgba32ImageToG1Data ( img , currG1 . Flags )
233
- } ;
234
- G1Provider . G1Elements [ i ] = currG1 ;
235
- i ++ ;
230
+ LoadSprite ( filename ) ;
231
+ }
236
232
}
237
233
234
+ Logger . Debug ( "Import successful" ) ;
238
235
this . RaisePropertyChanged ( nameof ( Bitmaps ) ) ;
239
236
}
240
237
catch ( Exception ex )
241
238
{
242
239
Logger . Error ( ex ) ;
243
240
}
241
+
242
+ animationTimer . Start ( ) ;
243
+ }
244
+
245
+ void LoadSprite ( string filename , SpriteOffset ? offset = null )
246
+ {
247
+ if ( ! Path . Exists ( filename ) )
248
+ {
249
+ Logger . Error ( $ "File doesn't exist: \" { filename } \" ") ;
250
+ return ;
251
+ }
252
+
253
+ var match = Regex . Match ( Path . GetFileNameWithoutExtension ( filename ) , @".*?(\d+).*?" ) ;
254
+ if ( ! match . Success )
255
+ {
256
+ Logger . Warning ( $ "Couldn't parse sprite index from filename: \" { filename } \" ") ;
257
+ return ;
258
+ }
259
+
260
+ var index = int . Parse ( match . Groups [ 1 ] . Value ) ;
261
+ var img = Image . Load < Rgba32 > ( filename ) ;
262
+ Images [ index ] = img ;
263
+
264
+ var currG1 = G1Provider . G1Elements [ index ] ;
265
+ currG1 = currG1 with
266
+ {
267
+ Width = ( int16_t ) img . Width ,
268
+ Height = ( int16_t ) img . Height ,
269
+ Flags = currG1 . Flags & ~ G1ElementFlags . IsRLECompressed , // SawyerStreamWriter::SaveImageTable does this anyways
270
+ ImageData = PaletteMap . ConvertRgba32ImageToG1Data ( img , currG1 . Flags ) ,
271
+ XOffset = offset ? . X ?? currG1 . XOffset ,
272
+ YOffset = offset ? . Y ?? currG1 . YOffset
273
+ } ;
274
+ G1Provider . G1Elements [ index ] = currG1 ;
244
275
}
245
276
246
277
// todo: second half should be in model
0 commit comments