Skip to content

Commit

Permalink
make more stuff async and show tasks/progress in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
jupahe64 committed Dec 6, 2023
1 parent 9d9dabd commit 9351fd2
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 125 deletions.
3 changes: 3 additions & 0 deletions Fushigi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Fushigi.param;
using Fushigi.ui;
using System.Runtime.InteropServices;
using Fushigi.windowing;


FileStream outputStream = new FileStream("output.log", FileMode.Create);
Expand Down Expand Up @@ -39,9 +40,11 @@
};

MainWindow window = new MainWindow();
WindowManager.Run();

outputStream.Close();


void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
Exception? ex = e.ExceptionObject as Exception;
Expand Down
15 changes: 10 additions & 5 deletions Fushigi/param/ParamDB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,26 @@ public static bool TryGetRailPointComponent(string railName, [NotNullWhen(true)]

public static string[] GetActors() => sActors.Keys.ToArray();

public static void Load()
public static void Load(IProgress<(string operationName, float? progress)> progress)
{
/* if we have already been initialized, we skip this process */
if (sIsInit)
{
return;
}

progress.Report(("Gathering Actor packs", null));
/* the files in /Pack/Actor in the RomFS contain the PACK files that contain our parameters */
// string[] files = RomFS.GetFiles("/Pack/Actor");
string[] files = RomFS.GetFiles(Path.Combine("Pack", "Actor"));


/* iterate through each file */
foreach (string file in files)
for (int i = 0; i < files.Length; i++)
{
string file = files[i];

progress.Report(("Loading Parameters from Actor packs", i / (float)files.Length));

/* the actor name in question is at the beginning of the file name */
string actorName = Path.GetFileNameWithoutExtension(file).Split(".pack")[0];
ParamList param = new ParamList();
Expand Down Expand Up @@ -193,14 +198,14 @@ public static void Load()
sIsInit = true;
}

public static void Reload()
public static void Reload(IProgress<(string operationName, float? progress)> progress)
{
sActors.Clear();
sComponents.Clear();
sRails.Clear();
sRailParamList.Clear();
sIsInit = false;
Load();
Load(progress);
}

static Component ReadByml(Byml.Byml byml)
Expand Down
150 changes: 95 additions & 55 deletions Fushigi/ui/MainWindow.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Fushigi.course;
using Fushigi.param;
using Fushigi.ui.modal;
using Fushigi.ui.widgets;
Expand All @@ -19,11 +20,14 @@ public class MainWindow : IPopupModalHost
private ImFontPtr mDefaultFont;
private ImFontPtr mIconFont;

private (Course course, TaskCompletionSource promise)? mCourseLoadRequest = null;

public MainWindow()
{
WindowManager.CreateWindow(out mWindow,
onConfigureIO: () =>
{
Console.WriteLine("Initializing Window");
unsafe
{
var io = ImGui.GetIO();
Expand Down Expand Up @@ -87,8 +91,6 @@ public MainWindow()
});
mWindow.Load += () => WindowManager.RegisterRenderDelegate(mWindow, Render);
mWindow.Closing += Close;
mWindow.Run();
mWindow.Dispose();
}

public async Task<bool> TryCloseCourse()
Expand Down Expand Up @@ -135,8 +137,27 @@ public void Close()
}).ConfigureAwait(false); //fire and forget
}

void LoadFromSettings(GL gl)
//TODO put this somewhere else
public static Task LoadParamDBWithProgressBar(IPopupModalHost modalHost)
{
return ProgressBarDialog.ShowDialogForAsyncAction(modalHost,
"Loading ParamDB",
async (p) =>
{
p.Report(("Creating task", 0));
await modalHost.WaitTick();
var task = ParamDB.sIsInit ?
Task.Run(() => ParamDB.Reload(p)) :
Task.Run(() => ParamDB.Load(p));
await task;
});
}

async Task StartupRoutine(GL gl)
{
await WaitTick();
bool shouldShowPreferenceWindow = true;
bool shouldShowWelcomeDialog = true;
string romFSPath = UserSettings.GetRomFSPath();
if (RomFS.IsValidRoot(romFSPath))
{
Expand All @@ -146,16 +167,21 @@ void LoadFromSettings(GL gl)
if (!ParamDB.sIsInit)
{
Console.WriteLine("Parameter database needs to be initialized...");
mIsGeneratingParamDB = true;

await LoadParamDBWithProgressBar(this);
await Task.Delay(500);

}

string? latestCourse = UserSettings.GetLatestCourse();
if (latestCourse != null && ParamDB.sIsInit)
{
mCurrentCourseName = latestCourse;
mSelectedCourseScene = new(new(mCurrentCourseName), gl, this);
mIsChoosingPreferences = false;
mIsWelcome = false;
//wait for other pending dialogs to close
await mModalHost.WaitTick();

await LoadCourseWithProgressBar(latestCourse);
shouldShowPreferenceWindow = false;
shouldShowWelcomeDialog = false;
}
}

Expand All @@ -164,11 +190,33 @@ void LoadFromSettings(GL gl)
if (!string.IsNullOrEmpty(RomFS.GetRoot()) &&
!string.IsNullOrEmpty(UserSettings.GetModRomFSPath()))
{
mIsChoosingPreferences = false;
mIsWelcome = false;
shouldShowPreferenceWindow = false;
shouldShowWelcomeDialog = false;
}


if(shouldShowPreferenceWindow)
mIsShowPreferenceWindow = true;

if(shouldShowWelcomeDialog)
await WelcomeMessage.ShowDialog(this);
}

Task LoadCourseWithProgressBar(string name)
{
return ProgressBarDialog.ShowDialogForAsyncAction(this,
$"Loading {name}",
async (p) =>
{
var promise = new TaskCompletionSource();
p.Report(("Loading course files", null));
await mModalHost.WaitTick();
var course = new Course(name);
p.Report(("Loading other resources (this temporarily freezes the app)", null));
await mModalHost.WaitTick();

mCourseLoadRequest = (course, promise);
await promise.Task;
});
}

void DrawMainMenu(GL gl)
Expand All @@ -194,7 +242,7 @@ void DrawMainMenu(GL gl)
{
mCurrentCourseName = selectedCourse;
Console.WriteLine($"Selected course {mCurrentCourseName}!");
mSelectedCourseScene = new(new(mCurrentCourseName), gl, this);
await LoadCourseWithProgressBar(mCurrentCourseName);
UserSettings.AppendRecentCourse(mCurrentCourseName);
}
}).ConfigureAwait(false); //fire and forget
Expand Down Expand Up @@ -265,12 +313,12 @@ void DrawMainMenu(GL gl)
{
if (ImGui.MenuItem("Preferences"))
{
mIsChoosingPreferences = true;
mIsShowPreferenceWindow = true;
}

if (ImGui.MenuItem("Regenerate Parameter Database", ParamDB.sIsInit))
{
mIsGeneratingParamDB = true;
_ = LoadParamDBWithProgressBar(this);
}

if (ImGui.MenuItem("Undo"))
Expand All @@ -292,26 +340,17 @@ void DrawMainMenu(GL gl)
}
}

void DrawWelcome()
public void Render(GL gl, double delta, ImGuiController controller)
{
if (!ImGui.Begin("Welcome"))
//for now (makes sure we have atleast one frame rendered before the course get's loaded)
if(mCourseLoadRequest.TryGetValue(out var request))
{
return;
}

ImGui.Text("Welcome to Fushigi! Set the RomFS game path and save directory to get started.");

if (ImGui.Button("Close"))
{
mIsWelcome = false;
mSelectedCourseScene = new(request.course, gl, this);
mCurrentCourseName = request.course.GetName();
request.promise.SetResult();
mCourseLoadRequest = null;
}

ImGui.End();
}

public void Render(GL gl, double delta, ImGuiController controller)
{

/* keep OpenGLs viewport size in sync with the window's size */
gl.Viewport(mWindow.FramebufferSize);

Expand All @@ -325,34 +364,21 @@ public void Render(GL gl, double delta, ImGuiController controller)
if (ImGui.GetFrameCount() == 2)
{
ImGui.LoadIniSettingsFromDisk("imgui.ini");
LoadFromSettings(gl);
_ = StartupRoutine(gl);
}

DrawMainMenu(gl);

// ImGui settings are available frame 3
if (ImGui.GetFrameCount() > 2)

if (!string.IsNullOrEmpty(RomFS.GetRoot()) &&
!string.IsNullOrEmpty(UserSettings.GetModRomFSPath()))
{
if (!string.IsNullOrEmpty(RomFS.GetRoot()) &&
!string.IsNullOrEmpty(UserSettings.GetModRomFSPath()))
{
mSelectedCourseScene?.DrawUI(gl, delta);
}

if (mIsChoosingPreferences)
{
Preferences.Draw(ref mIsChoosingPreferences, gl);
}

if (mIsWelcome)
{
DrawWelcome();
}
mSelectedCourseScene?.DrawUI(gl, delta);
}

if (mIsGeneratingParamDB)
{
ParamDBDialog.Draw(ref mIsGeneratingParamDB);
}
if (mIsShowPreferenceWindow)
{
Preferences.Draw(ref mIsShowPreferenceWindow, gl, this);
}

mModalHost.DrawHostedModals();
Expand All @@ -372,11 +398,25 @@ public void Render(GL gl, double delta, ImGuiController controller)
return mModalHost.ShowPopUp(modal, title, windowFlags, minWindowSize);
}

public Task WaitTick()
{
return ((IPopupModalHost)mModalHost).WaitTick();
}

readonly IWindow mWindow;
string? mCurrentCourseName;
CourseScene? mSelectedCourseScene;
bool mIsChoosingPreferences = true;
bool mIsWelcome = true;
bool mIsGeneratingParamDB = false;
bool mIsShowPreferenceWindow = false;


class WelcomeMessage : OkDialog<WelcomeMessage>
{
protected override string Title => "Welcome";

protected override void DrawBody()
{
ImGui.Text("Welcome to Fushigi! Set the RomFS game path and save directory to get started.");
}
}
}
}
37 changes: 37 additions & 0 deletions Fushigi/ui/modal/OkDialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Fushigi.util;
using ImGuiNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Fushigi.ui.modal
{
public abstract class OkDialog<TDialog> : IPopupModal<OkDialog<TDialog>.Void>
where TDialog : OkDialog<TDialog>, new()
{
private struct Void { }

protected abstract string Title { get; }

public static async Task ShowDialog(IPopupModalHost modalHost)
{
var dialog = new TDialog();
await modalHost.ShowPopUp(dialog, dialog.Title,
ImGuiWindowFlags.AlwaysAutoResize);
}

protected abstract void DrawBody();

void IPopupModal<Void>.DrawModalContent(Promise<Void> promise)
{
DrawBody();

if (ImGui.Button("OK"))
{
promise.SetResult(new Void());
}
}
}
}
Loading

0 comments on commit 9351fd2

Please sign in to comment.