@@ -54,12 +54,6 @@ public void Parse(Project2MiloOptions op)
54
54
? Directory . GetFiles ( lipsyncDir , "*.lipsync" )
55
55
: Array . Empty < string > ( ) ;
56
56
57
- // Get extra files
58
- var extrasDir = Path . Combine ( inputDir , "extra" ) ;
59
- var extrasPaths = Directory . Exists ( extrasDir )
60
- ? Directory . GetFiles ( extrasDir )
61
- : Array . Empty < string > ( ) ;
62
-
63
57
// Enforce files exist
64
58
if ( ! File . Exists ( songMetaPath ) )
65
59
throw new MiloBuildException ( "Can't find \" song.json\" file" ) ;
@@ -77,7 +71,7 @@ public void Parse(Project2MiloOptions op)
77
71
var state = new AppState ( inputDir ) ;
78
72
state . UpdateSystemInfo ( GetSystemInfo ( op ) ) ;
79
73
80
- var miloDir = CreateRootDirectory ( p9song . Name ? . ToLower ( ) ) ;
74
+ var miloDir = CreateRootDirectory ( p9song . Name ? . ToLower ( ) ?? "song" ) ;
81
75
var miloDirEntry = miloDir . Extras [ "DirectoryEntry" ] as MiloObjectDirEntry ;
82
76
83
77
// Add lipsync files
@@ -96,62 +90,46 @@ public void Parse(Project2MiloOptions op)
96
90
miloDir . Entries . Add ( lyricConfigAnim ) ;
97
91
}
98
92
99
- // Iterate over extra milo objects
100
- var extras = new List < MiloObject > ( ) ;
101
- Parallel . ForEach ( extrasPaths ,
102
- path =>
103
- {
104
- // Get milo type
105
- var miloType = GetMiloType ( path ) ;
106
-
107
- // Ignore unsupported files and filter out lyric_config if in json
108
- if ( miloType is null
109
- || ( ! ( lyricConfigAnim is null ) && path . EndsWith ( lyricConfigAnim . Name , StringComparison . CurrentCultureIgnoreCase ) ) )
110
- return ;
111
-
112
- var miloObj = miloType switch
113
- {
114
- "PNG" => CreateTex ( path , state . SystemInfo ) ,
115
- _ => CreateObject ( path , miloType )
116
- } ;
117
-
118
- // Add milo object to directory
119
- lock ( extras )
120
- {
121
- extras . Add ( miloObj ) ;
122
- }
123
- } ) ;
93
+ // Process extra files
94
+ var extrasDir = Path . Combine ( inputDir , "extra" ) ;
95
+ if ( Directory . Exists ( extrasDir ) )
96
+ {
97
+ ProcessExtraFiles ( extrasDir , miloDir , state ) ;
98
+ }
124
99
125
- var serializer = state . GetSerializer ( ) ;
126
- var outputMiloPath = Path . GetFullPath ( op . OutputPath ) ;
100
+ // Merge anim entries in root directory
101
+ var animEntries = miloDir
102
+ . Entries
103
+ . Where ( x => x . Name != "song.anim"
104
+ && x . Type == "PropAnim" )
105
+ . ToList ( ) ;
127
106
128
- // Add extra milo entries and parse prop anim files
129
- foreach ( var extra in extras )
107
+ foreach ( var animEntry in animEntries )
130
108
{
131
- if ( ! ( extra is MiloObjectBytes mob )
132
- || ! ( extra . Type is "PropAnim" ) )
133
- {
134
- miloDir . Entries . Add ( extra ) ;
135
- continue ;
136
- }
109
+ if ( ! ( animEntry is MiloObjectBytes mob ) ) continue ;
137
110
138
111
try
139
112
{
113
+ // Try parsing as prop anim
140
114
var extraAnim = state
141
115
. GetSerializer ( )
142
116
. ReadFromMiloObjectBytes < PropAnim > ( mob ) ;
143
117
144
118
if ( extraAnim . AnimName is "song_anim" )
145
119
{
146
120
MergePropAnims ( anim , extraAnim ) ;
121
+
122
+ // Remove old entry
123
+ miloDir . Entries . Remove ( animEntry ) ;
147
124
continue ;
148
125
}
149
126
}
150
127
catch { }
151
-
152
- miloDir . Entries . Add ( extra ) ;
153
128
}
154
129
130
+ var serializer = state . GetSerializer ( ) ;
131
+ var outputMiloPath = Path . GetFullPath ( op . OutputPath ) ;
132
+
155
133
var miloFile = new MiloFile
156
134
{
157
135
Data = serializer . WriteToBytes ( miloDir )
@@ -165,6 +143,89 @@ public void Parse(Project2MiloOptions op)
165
143
Console . WriteLine ( $ "Successfully created milo at \" { outputMiloPath } \" ") ;
166
144
}
167
145
146
+ protected void ProcessExtraFiles ( string extrasDir , MiloObjectDir miloDir , AppState state )
147
+ {
148
+ var existingEntries = miloDir
149
+ . Entries
150
+ . Select ( x => x . Name . ToLower ( ) )
151
+ . ToHashSet ( ) ;
152
+
153
+ // Get extra files
154
+ var extraFiles = GetExtraFilesToProcess ( extrasDir , miloDir ) ;
155
+
156
+ // Iterate over extra milo objects
157
+ Parallel . ForEach ( extraFiles ,
158
+ extraFile =>
159
+ {
160
+ var ( miloDir , miloType , path ) = extraFile ;
161
+
162
+ var miloObj = miloType switch
163
+ {
164
+ "PNG" => CreateTex ( path , state . SystemInfo ) ,
165
+ _ => CreateObject ( path , miloType )
166
+ } ;
167
+
168
+ // Add milo object to directory
169
+ lock ( miloDir )
170
+ {
171
+ miloDir . Entries . Add ( miloObj ) ;
172
+ }
173
+ } ) ;
174
+ }
175
+
176
+ protected List < ( MiloObjectDir , string , string ) > GetExtraFilesToProcess ( string extraPath , MiloObjectDir miloDir )
177
+ {
178
+ var filesToProcess = new List < ( MiloObjectDir , string , string ) > ( ) ; // (Dir, type, path)
179
+
180
+ var existingEntries = miloDir
181
+ . Entries
182
+ . Select ( x => x . Name . ToLower ( ) )
183
+ . ToHashSet ( ) ;
184
+
185
+ // Process entries
186
+ foreach ( var filePath in Directory . GetFiles ( extraPath ) )
187
+ {
188
+ // Get milo type
189
+ var miloType = GetMiloType ( filePath ) ;
190
+
191
+ // Ignore unsupported files and existing entries
192
+ if ( miloType is null
193
+ || ( existingEntries . Contains ( Path . GetFileName ( filePath ) . ToLower ( ) ) ) )
194
+ continue ;
195
+
196
+ filesToProcess . Add ( ( miloDir , miloType , filePath ) ) ;
197
+ }
198
+
199
+ var miloDirEntry = miloDir . Extras [ "DirectoryEntry" ] as MiloObjectDirEntry ;
200
+
201
+ var existingDirs = miloDirEntry
202
+ . SubDirectories
203
+ . ToDictionary ( x => x . Name . ToLower ( ) , y => y ) ;
204
+
205
+ // Process directories
206
+ foreach ( var dirPath in Directory . GetDirectories ( extraPath ) )
207
+ {
208
+ var dirName = Path . GetFileName ( dirPath ) ;
209
+ var isNewDir = false ;
210
+
211
+ if ( ! existingDirs . TryGetValue ( dirName . ToLower ( ) , out var subDir ) )
212
+ {
213
+ // Create sub dir
214
+ subDir = CreateMiloDir ( dirName ) ;
215
+ isNewDir = true ;
216
+ }
217
+
218
+ var subFiles = GetExtraFilesToProcess ( dirPath , subDir ) ;
219
+ if ( ! subFiles . Any ( ) ) continue ;
220
+
221
+ // Add files to process
222
+ filesToProcess . AddRange ( subFiles ) ;
223
+ if ( isNewDir ) miloDirEntry . SubDirectories . Add ( subDir ) ;
224
+ }
225
+
226
+ return filesToProcess ;
227
+ }
228
+
168
229
protected string GetMiloType ( string path )
169
230
=> SupportedExtraTypes
170
231
. Where ( x => path . EndsWith ( x . extension , StringComparison . CurrentCultureIgnoreCase ) )
@@ -428,25 +489,15 @@ protected MiloObjectDir CreateRootDirectory(string name)
428
489
429
490
var miloDir = new MiloObjectDir ( )
430
491
{
431
- Name = name
492
+ Name = name ?? ""
432
493
} ;
433
494
434
495
miloDir . Extras . Add ( "DirectoryEntry" , miloDirEntry ) ;
435
496
return miloDir ;
436
497
}
437
-
438
- protected MiloObjectDir GetCharSubDirectory ( string lipPath )
439
- {
440
- var name = Path . GetFileNameWithoutExtension ( lipPath ) . ToLower ( ) ;
441
- var fileName = Path . GetFileName ( lipPath ) . ToLower ( ) ;
442
- var data = File . ReadAllBytes ( lipPath ) ;
443
-
444
- var lipsync = new MiloObjectBytes ( "CharLipSync" )
445
- {
446
- Name = fileName ,
447
- Data = data
448
- } ;
449
498
499
+ protected MiloObjectDir CreateMiloDir ( string name )
500
+ {
450
501
var miloDirEntry = new MiloObjectDirEntry ( )
451
502
{
452
503
Name = name ,
@@ -462,9 +513,26 @@ protected MiloObjectDir GetCharSubDirectory(string lipPath)
462
513
Name = name
463
514
} ;
464
515
465
- miloDir . Entries . Add ( lipsync ) ;
466
516
miloDir . Extras . Add ( "DirectoryEntry" , miloDirEntry ) ;
467
517
return miloDir ;
468
518
}
519
+
520
+ protected MiloObjectDir GetCharSubDirectory ( string lipPath )
521
+ {
522
+ var name = Path . GetFileNameWithoutExtension ( lipPath ) . ToLower ( ) ;
523
+ var fileName = Path . GetFileName ( lipPath ) . ToLower ( ) ;
524
+ var data = File . ReadAllBytes ( lipPath ) ;
525
+
526
+ var lipsync = new MiloObjectBytes ( "CharLipSync" )
527
+ {
528
+ Name = fileName ,
529
+ Data = data
530
+ } ;
531
+
532
+ var miloDir = CreateMiloDir ( name ) ;
533
+
534
+ miloDir . Entries . Add ( lipsync ) ;
535
+ return miloDir ;
536
+ }
469
537
}
470
538
}
0 commit comments