Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.

Commit e75d6e8

Browse files
committed
Support nested directories for extra input
1 parent bc609b4 commit e75d6e8

File tree

1 file changed

+126
-58
lines changed

1 file changed

+126
-58
lines changed

Src/UI/P9SongTool/Apps/Project2MiloApp.cs

Lines changed: 126 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@ public void Parse(Project2MiloOptions op)
5454
? Directory.GetFiles(lipsyncDir, "*.lipsync")
5555
: Array.Empty<string>();
5656

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-
6357
// Enforce files exist
6458
if (!File.Exists(songMetaPath))
6559
throw new MiloBuildException("Can't find \"song.json\" file");
@@ -77,7 +71,7 @@ public void Parse(Project2MiloOptions op)
7771
var state = new AppState(inputDir);
7872
state.UpdateSystemInfo(GetSystemInfo(op));
7973

80-
var miloDir = CreateRootDirectory(p9song.Name?.ToLower());
74+
var miloDir = CreateRootDirectory(p9song.Name?.ToLower() ?? "song");
8175
var miloDirEntry = miloDir.Extras["DirectoryEntry"] as MiloObjectDirEntry;
8276

8377
// Add lipsync files
@@ -96,62 +90,46 @@ public void Parse(Project2MiloOptions op)
9690
miloDir.Entries.Add(lyricConfigAnim);
9791
}
9892

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+
}
12499

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();
127106

128-
// Add extra milo entries and parse prop anim files
129-
foreach (var extra in extras)
107+
foreach (var animEntry in animEntries)
130108
{
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;
137110

138111
try
139112
{
113+
// Try parsing as prop anim
140114
var extraAnim = state
141115
.GetSerializer()
142116
.ReadFromMiloObjectBytes<PropAnim>(mob);
143117

144118
if (extraAnim.AnimName is "song_anim")
145119
{
146120
MergePropAnims(anim, extraAnim);
121+
122+
// Remove old entry
123+
miloDir.Entries.Remove(animEntry);
147124
continue;
148125
}
149126
}
150127
catch { }
151-
152-
miloDir.Entries.Add(extra);
153128
}
154129

130+
var serializer = state.GetSerializer();
131+
var outputMiloPath = Path.GetFullPath(op.OutputPath);
132+
155133
var miloFile = new MiloFile
156134
{
157135
Data = serializer.WriteToBytes(miloDir)
@@ -165,6 +143,89 @@ public void Parse(Project2MiloOptions op)
165143
Console.WriteLine($"Successfully created milo at \"{outputMiloPath}\"");
166144
}
167145

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+
168229
protected string GetMiloType(string path)
169230
=> SupportedExtraTypes
170231
.Where(x => path.EndsWith(x.extension, StringComparison.CurrentCultureIgnoreCase))
@@ -428,25 +489,15 @@ protected MiloObjectDir CreateRootDirectory(string name)
428489

429490
var miloDir = new MiloObjectDir()
430491
{
431-
Name = name
492+
Name = name ?? ""
432493
};
433494

434495
miloDir.Extras.Add("DirectoryEntry", miloDirEntry);
435496
return miloDir;
436497
}
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-
};
449498

499+
protected MiloObjectDir CreateMiloDir(string name)
500+
{
450501
var miloDirEntry = new MiloObjectDirEntry()
451502
{
452503
Name = name,
@@ -462,9 +513,26 @@ protected MiloObjectDir GetCharSubDirectory(string lipPath)
462513
Name = name
463514
};
464515

465-
miloDir.Entries.Add(lipsync);
466516
miloDir.Extras.Add("DirectoryEntry", miloDirEntry);
467517
return miloDir;
468518
}
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+
}
469537
}
470538
}

0 commit comments

Comments
 (0)