Skip to content

Commit

Permalink
Add several quality of life enhancements (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonko0493 authored Apr 10, 2023
1 parent 1982173 commit d24aead
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/SerialLoops.Lib/IO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public static void CopyFiles(string sourceDirectory, string destinationDirectory
{
foreach (string file in Directory.GetFiles(sourceDirectory, filter))
{
File.Copy(file, Path.Combine(destinationDirectory, Path.GetFileName(file)));
File.Copy(file, Path.Combine(destinationDirectory, Path.GetFileName(file)), overwrite: true);
}
}

Expand Down
16 changes: 13 additions & 3 deletions src/SerialLoops.Lib/Items/ScriptItem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using HaruhiChokuretsuLib.Archive.Event;
using HaruhiChokuretsuLib.Util;
using QuikGraph;
using SerialLoops.Lib.Script;
using SerialLoops.Lib.Script.Parameters;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
Expand All @@ -17,16 +19,24 @@ public class ScriptItem : Item
public ScriptItem(string name) : base(name, ItemType.Script)
{
}
public ScriptItem(EventFile evt) : base(evt.Name[0..^1], ItemType.Script)
public ScriptItem(EventFile evt, ILogger log) : base(evt.Name[0..^1], ItemType.Script)
{
Event = evt;

Graph.AddVertexRange(Event.ScriptSections);

SearchableText = string.Join('\n', evt.ScriptSections.SelectMany(s => s.Objects.Select(c => c.Command.Mnemonic))
.Concat(evt.ConditionalsSection.Objects));
try
{
SearchableText = string.Join('\n', evt.ScriptSections.SelectMany(s => s.Objects.Select(c => c.Command.Mnemonic))
.Concat(evt.ConditionalsSection.Objects));
//.Concat(evt.LabelsSection.Objects.Select(l => l.Name))
//.Concat(evt.DialogueLines.Select(l => l.Text)));
}
catch (Exception ex)
{
log.LogError($"Exception encountered while creating searchable text for script {Name}: {ex.Message}");
log.Log(ex.StackTrace);
}
}

public Dictionary<ScriptSection, List<ScriptItemCommand>> GetScriptCommandTree(Project project)
Expand Down
138 changes: 126 additions & 12 deletions src/SerialLoops.Lib/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using HaruhiChokuretsuLib.Archive.Graphics;
using HaruhiChokuretsuLib.Font;
using HaruhiChokuretsuLib.Util;
using HaruhiChokuretsuLib.Util.Exceptions;
using SerialLoops.Lib.Items;
using SerialLoops.Lib.Util;
using SkiaSharp;
Expand Down Expand Up @@ -83,13 +84,46 @@ public Project(string name, string langCode, Config config, ILogger log)
log.LogError($"Exception occurred while attempting to create project directories.\n{exc.Message}\n\n{exc.StackTrace}");
}
}

public enum LoadProjectState
{
SUCCESS,
LOOSELEAF_FILES,
CORRUPTED_FILE,
NOT_FOUND,
FAILED,
}

public struct LoadProjectResult
{
public LoadProjectState State { get; set; }
public string BadArchive { get; set; }
public int BadFileIndex { get; set; }

public LoadProjectResult(LoadProjectState state, string badArchive, int badFileIndex)
{
State = state;
BadArchive = badArchive;
BadFileIndex = badFileIndex;
}
public LoadProjectResult(LoadProjectState state)
{
State = state;
BadArchive = string.Empty;
BadFileIndex = -1;
}
}

public void Load(Config config, ILogger log, IProgressTracker tracker)
public LoadProjectResult Load(Config config, ILogger log, IProgressTracker tracker)
{
Config = config;
LoadProjectSettings(log, tracker);
ClearOrCreateCaches(config.CachesDirectory, log);
LoadArchives(log, tracker);
if (Directory.GetFiles(Path.Combine(IterativeDirectory, "assets"), "*", SearchOption.AllDirectories).Length > 0)
{
return new(LoadProjectState.LOOSELEAF_FILES);
}
return LoadArchives(log, tracker);
}

public void LoadProjectSettings(ILogger log, IProgressTracker tracker)
Expand All @@ -100,18 +134,72 @@ public void LoadProjectSettings(ILogger log, IProgressTracker tracker)
tracker.Finished++;
}

public void LoadArchives(ILogger log, IProgressTracker tracker)
public LoadProjectResult LoadArchives(ILogger log, IProgressTracker tracker)
{
tracker.Focus("dat.bin", 3);
Dat = ArchiveFile<DataFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "dat.bin"), log);
try
{
Dat = ArchiveFile<DataFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "dat.bin"), log, false);
}
catch (ArchiveLoadException ex)
{
if (Directory.GetFiles(Path.Combine(BaseDirectory, "assets", "data")).Any(f => Path.GetFileNameWithoutExtension(f) == $"{ex.Index:X3}"))
{
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in dat.bin was detected as corrupt.");
return new(LoadProjectState.CORRUPTED_FILE, "dat.bin", ex.Index);
}
else
{
// If it's not a file they've modified, then they're using a bad base ROM
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in dat.bin was detected as corrupt. " +
$"Please use a different base ROM as this one is corrupted.");
return new(LoadProjectState.CORRUPTED_FILE, "dat.bin", -1);
}
}
tracker.Finished++;

tracker.CurrentlyLoading = "grp.bin";
Grp = ArchiveFile<GraphicsFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "grp.bin"), log);
try
{
Grp = ArchiveFile<GraphicsFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "grp.bin"), log);
}
catch (ArchiveLoadException ex)
{
if (Directory.GetFiles(Path.Combine(BaseDirectory, "assets", "graphics")).Any(f => Path.GetFileNameWithoutExtension(f) == $"{ex.Index:X3}"))
{
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in grp.bin was detected as corrupt.");
return new(LoadProjectState.CORRUPTED_FILE, "grp.bin", ex.Index);
}
else
{
// If it's not a file they've modified, then they're using a bad base ROM
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in grp.bin was detected as corrupt. " +
$"Please use a different base ROM as this one is corrupted.");
return new(LoadProjectState.CORRUPTED_FILE, "grp.bin", -1);
}
}
tracker.Finished++;

tracker.CurrentlyLoading = "evt.bin";
Evt = ArchiveFile<EventFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "evt.bin"), log);
try
{
Evt = ArchiveFile<EventFile>.FromFile(Path.Combine(IterativeDirectory, "original", "archives", "evt.bin"), log);
}
catch (ArchiveLoadException ex)
{
if (Directory.GetFiles(Path.Combine(BaseDirectory, "assets", "events")).Any(f => Path.GetFileNameWithoutExtension(f) == $"{ex.Index:X3}"))
{
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in evt.bin was detected as corrupt.");
return new(LoadProjectState.CORRUPTED_FILE, "evt.bin", ex.Index);
}
else
{
// If it's not a file they've modified, then they're using a bad base ROM
log.LogError($"File {ex.Index:4} (0x{ex.Index:X3}) '{ex.Filename}' in evt.bin was detected as corrupt. " +
$"Please use a different base ROM as this one is corrupted.");
return new(LoadProjectState.CORRUPTED_FILE, "evt.bin", -1);
}
}
tracker.Finished++;

tracker.Focus("Font", 5);
Expand Down Expand Up @@ -192,7 +280,7 @@ public void LoadArchives(ILogger log, IProgressTracker tracker)
tracker.Focus("Event Files", 1);
Items.AddRange(Evt.Files
.Where(e => !new string[] { "CHESSS", "EVTTBLS", "TOPICS", "SCENARIOS", "TUTORIALS", "VOICEMAPS" }.Contains(e.Name))
.Select(e => new ScriptItem(e)));
.Select(e => new ScriptItem(e, log)));
tracker.Finished++;

tracker.Focus("Maps", 1);
Expand Down Expand Up @@ -236,6 +324,23 @@ public void LoadArchives(ILogger log, IProgressTracker tracker)
Items.Add(new GroupSelectionItem(scenarioFile.Scenario.Selects[i], i, this));
tracker.Finished++;
}

return new(LoadProjectState.SUCCESS);
}

public void MigrateProject(string newRom, ILogger log, IProgressTracker tracker)
{
log.Log($"Attempting to migrate base ROM to {newRom}");

string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
NdsProjectFile.Create("temp", newRom, tempDir);
IO.CopyFiles(Path.Combine(tempDir, "data"), Path.Combine(BaseDirectory, "original", "archives"), "*.bin");
IO.CopyFiles(Path.Combine(tempDir, "data", "bgm"), Path.Combine(BaseDirectory, "original", "bgm"), "*.bin");
IO.CopyFiles(Path.Combine(tempDir, "data", "vce"), Path.Combine(BaseDirectory, "original", "vce"), "*.bin");
IO.CopyFiles(Path.Combine(tempDir, "overlay"), Path.Combine(BaseDirectory, "original", "overlay"), "*.bin");
IO.CopyFiles(Path.Combine(tempDir, "data", "movie"), Path.Combine(BaseDirectory, "rom", "data", "movie"), "*.mods");

Directory.Delete(tempDir, true);
}

public static void ClearOrCreateCaches(string cachesDirectory, ILogger log)
Expand All @@ -262,28 +367,37 @@ public ItemDescription FindItem(string name)
return Items.FirstOrDefault(i => i.Name == name.Split(" - ")[0]);
}

public static Project OpenProject(string projFile, Config config, ILogger log, IProgressTracker tracker)
public static (Project Project, LoadProjectResult Result) OpenProject(string projFile, Config config, ILogger log, IProgressTracker tracker)
{
log.Log($"Loading project from '{projFile}'...");
if (!File.Exists(projFile))
{
log.LogError($"Project file {projFile} not found -- has it been deleted?");
return null;
return (null, new(LoadProjectState.NOT_FOUND));
}
try
{
tracker.Focus($"{Path.GetFileNameWithoutExtension(projFile)} Project Data", 1);
Project project = JsonSerializer.Deserialize<Project>(File.ReadAllText(projFile));
tracker.Finished++;
project.Load(config, log, tracker);
return project;
LoadProjectResult result = project.Load(config, log, tracker);
if (result.State == LoadProjectState.LOOSELEAF_FILES)
{
log.LogWarning("Found looseleaf files in iterative directory; prompting user for build before loading archives...");
}
else if (result.State == LoadProjectState.CORRUPTED_FILE)
{
log.LogWarning("Found corrupted file in archive; prompting user for action before continuing...");
}
return (project, result);
}
catch (Exception exc)
{
log.LogError($"Error while loading project: {exc.Message}\n\n{exc.StackTrace}");
return null;
return (null, new(LoadProjectState.FAILED));
}
}

public List<ItemDescription> GetSearchResults(string searchTerm, bool titlesOnly = true)
{
if (titlesOnly)
Expand Down
4 changes: 2 additions & 2 deletions src/SerialLoops.Lib/SerialLoops.Lib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

<ItemGroup>
<PackageReference Include="BunLabs.NAudio.Flac" Version="2.0.1" />
<PackageReference Include="HaruhiChokuretsuLib" Version="0.24.10" />
<PackageReference Include="HaruhiChokuretsuLib" Version="0.25.0" />
<PackageReference Include="NAudio.Vorbis" Version="1.5.0" />
<PackageReference Include="NitroPacker.Core" Version="2.0.1" />
<PackageReference Include="NitroPacker.Core" Version="2.1.0" />
<PackageReference Include="NLayer" Version="1.14.0" />
<PackageReference Include="NLayer.NAudioSupport" Version="1.3.0" />
<PackageReference Include="QuikGraph" Version="2.5.0" />
Expand Down
3 changes: 2 additions & 1 deletion src/SerialLoops/Controls/HomePanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ private void InitializeComponents()
HorizontalContentAlignment = HorizontalAlignment.Center,
Items =
{
ControlGenerator.GetIcon("AppIcon", _log, 64),
// Doing this image manually bc otherwise it breaks on Gtk for some unknown reason
new ImageView { Image = Icon.FromResource($"SerialLoops.Icons.AppIcon.png"), Height = 64, Width = 64 },
ControlGenerator.GetTextHeader("Serial Loops", 18)
}
};
Expand Down
Loading

0 comments on commit d24aead

Please sign in to comment.