mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-07 09:45:33 -04:00
ui: initial file select gate implementation
This commit is contained in:
@@ -85,6 +85,7 @@ set(RANDOMIZER_SOURCES
|
||||
src/verify_item_functions.cpp
|
||||
src/paths.cpp
|
||||
src/session.cpp
|
||||
src/hooks.cpp
|
||||
src/ui/config_store.cpp
|
||||
src/ui/rando_seed_generation.cpp
|
||||
src/ui/rando_config.cpp
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "hooks.hpp"
|
||||
#include "session.hpp"
|
||||
#include "randomizer_context.hpp"
|
||||
#include "ui/rando_config.hpp"
|
||||
|
||||
#include <mods/svc/hook.hpp>
|
||||
#include <mods/svc/log.hpp>
|
||||
|
||||
#include "d/d_file_select.h"
|
||||
|
||||
DEFINE_HOOK(&dFile_select_c::selectDataNameMove, dFile_select_c__selectDataNameMove);
|
||||
DEFINE_HOOK(&dFile_select_c::dataSelect, dFile_select_c__dataSelect);
|
||||
|
||||
namespace randomizer::ui {
|
||||
dialogSelectModeState g_dialogSelectModeState = SelectReady;
|
||||
}
|
||||
|
||||
namespace randomizer::hooks {
|
||||
namespace {
|
||||
UiDialogHandle playModeDialog{0};
|
||||
|
||||
HookAction hookPreDataSelect(ModContext*, void* args, void* retval, void* userdata) {
|
||||
ui::g_dialogSelectModeState = ui::SelectReady;
|
||||
ui::g_file_select_window_ctx.is_proceed = false;
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
HookAction hookPreSelectDataNameMove(ModContext*, void* args, void* retval, void* userdata) {
|
||||
dFile_select_c* i_this = mods::arg<dFile_select_c*>(args, 0);
|
||||
|
||||
// if coming from "start randomizer" button, let transition occur as normal
|
||||
if (ui::g_file_select_window_ctx.is_proceed) {
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
bool isHeaderTxtChange = i_this->headerTxtChangeAnm();
|
||||
bool isFileRecScale = i_this->fileRecScaleAnm2();
|
||||
bool isModoruTxtDisp = i_this->modoruTxtDispAnm();
|
||||
|
||||
// if selected vanilla mode, let transition occur as normal
|
||||
if (ui::g_dialogSelectModeState == ui::SelectVanilla) {
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
if (ui::g_dialogSelectModeState == ui::SelectReady && isHeaderTxtChange == true && isFileRecScale == true && isModoruTxtDisp == true) {
|
||||
ui::g_dialogSelectModeState = ui::SelectWait;
|
||||
|
||||
auto buildDialog = [i_this]() {
|
||||
UiDialogDesc desc = UI_DIALOG_DESC_INIT;
|
||||
desc.title = "Play Type";
|
||||
desc.body_rml = "What mode would you like to play?";
|
||||
desc.icon = "question-mark";
|
||||
desc.variant = UI_DIALOG_NORMAL;
|
||||
|
||||
UiDialogAction actions[2];
|
||||
actions[0] = {
|
||||
.label = "Vanilla",
|
||||
.on_pressed = [](ModContext* ctx, UiDialogHandle dialogHandle, void*) {
|
||||
mDoAud_seStartMenu(Z2SE_SY_CURSOR_OK);
|
||||
randomizer_GetContext() = RandomizerContext();
|
||||
ui::g_dialogSelectModeState = ui::SelectVanilla;
|
||||
session::svc_mng.ui->dialog_close(ctx, dialogHandle);
|
||||
},
|
||||
.user_data = nullptr,
|
||||
.keep_open = false,
|
||||
};
|
||||
actions[1] = {
|
||||
.label = "Randomizer",
|
||||
.on_pressed = [](ModContext* ctx, UiDialogHandle dialogHandle, void* userdata) {
|
||||
mDoAud_seStartMenu(Z2SE_SY_CURSOR_OK);
|
||||
ui::g_dialogSelectModeState = ui::SelectRandomizer;
|
||||
ui::buildFileSelectGateMenu(static_cast<dFile_select_c*>(userdata));
|
||||
session::svc_mng.ui->dialog_close(ctx, dialogHandle);
|
||||
},
|
||||
.user_data = i_this,
|
||||
.keep_open = false,
|
||||
};
|
||||
desc.actions = actions;
|
||||
desc.action_count = 2;
|
||||
|
||||
if (session::svc_mng.ui->dialog_push(session::svc_mng.mod_ctx, &desc, &playModeDialog) != MOD_OK) {
|
||||
mods::log::error("Failed to push dialog");
|
||||
return MOD_ERROR;
|
||||
}
|
||||
|
||||
return MOD_OK;
|
||||
};
|
||||
|
||||
if (buildDialog() != MOD_OK) {
|
||||
mods::log::error("Failed to build dialog");
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
return HOOK_SKIP_ORIGINAL;
|
||||
}
|
||||
}
|
||||
|
||||
ModResult initialize() {
|
||||
#define ADD_HOOK_PRE(originalFn, hookFn) \
|
||||
if (mods::hook::add_pre<originalFn>(hookFn) != MOD_OK) { \
|
||||
mods::log::error("Failed to add pre-hook for " #originalFn); \
|
||||
return MOD_ERROR; \
|
||||
}
|
||||
|
||||
ADD_HOOK_PRE(dFile_select_c__selectDataNameMove, hookPreSelectDataNameMove);
|
||||
ADD_HOOK_PRE(dFile_select_c__dataSelect, hookPreDataSelect);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mods/api.h>
|
||||
|
||||
namespace randomizer::hooks {
|
||||
ModResult initialize();
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "session.hpp"
|
||||
#include "ui/ui.hpp"
|
||||
#include "hooks.hpp"
|
||||
|
||||
DEFINE_MOD();
|
||||
IMPORT_SERVICE(HostService, svc_host);
|
||||
@@ -32,6 +33,11 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
||||
return mods::set_error(error, result, "failed to initialize session");
|
||||
}
|
||||
|
||||
result = randomizer::hooks::initialize();
|
||||
if (result != MOD_OK) {
|
||||
return mods::set_error(error, result, "failed to initialize hooks");
|
||||
}
|
||||
|
||||
result = randomizer::ui::initialize();
|
||||
if (result != MOD_OK) {
|
||||
return mods::set_error(error, result, "failed to initialize ui");
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <thread>
|
||||
#include <map>
|
||||
|
||||
#include "d/d_file_select.h"
|
||||
|
||||
namespace randomizer::ui {
|
||||
|
||||
seedgen::settings::Setting* FindSetting(const std::string& key) {
|
||||
@@ -95,16 +97,21 @@ const std::vector<std::pair<std::string, std::string>>& GetStartingInventoryLayo
|
||||
return layoutOrder;
|
||||
}
|
||||
|
||||
UiMenuTabHandle g_menu_tab{};
|
||||
|
||||
FileSelectGateWindowCtx g_file_select_window_ctx{};
|
||||
|
||||
namespace {
|
||||
// Control Helpers
|
||||
void add_button(UiElementHandle pane, const char* label, const char* help_rml,
|
||||
UiPressedFn on_pressed, UiElementHandle* out_handle = nullptr)
|
||||
UiPressedFn on_pressed, void* userdata = nullptr, UiElementHandle* out_handle = nullptr)
|
||||
{
|
||||
UiControlDesc desc = UI_CONTROL_DESC_INIT;
|
||||
desc.kind = UI_CONTROL_BUTTON;
|
||||
desc.label = label;
|
||||
desc.help_rml = help_rml;
|
||||
desc.on_pressed = on_pressed;
|
||||
desc.user_data = userdata;
|
||||
session::svc_mng.ui->pane_add_control(session::svc_mng.mod_ctx, pane, &desc, out_handle);
|
||||
}
|
||||
|
||||
@@ -452,9 +459,31 @@ void OnMenuTabSelected(ModContext* ctx, void*) {
|
||||
UiWindowHandle window{};
|
||||
session::svc_mng.ui->window_push(ctx, &desc, &window);
|
||||
}
|
||||
}
|
||||
|
||||
UiMenuTabHandle g_menu_tab{};
|
||||
// Play Tab
|
||||
ModResult buildPlayTab(ModContext* ctx, UiWindowHandle, UiElementHandle leftPane,
|
||||
UiElementHandle rightPane, void*, ModError*)
|
||||
{
|
||||
add_button(leftPane,
|
||||
"Selected Seed",
|
||||
"",
|
||||
[](ModContext*, void*) {
|
||||
// TODO
|
||||
});
|
||||
|
||||
add_button(leftPane,
|
||||
"Start Randomizer",
|
||||
"",
|
||||
[](ModContext*, void* userdata) {
|
||||
// set flag to move to name screen after window close
|
||||
g_file_select_window_ctx.is_proceed = true;
|
||||
session::svc_mng.ui->window_close(session::svc_mng.mod_ctx, *static_cast<UiWindowHandle*>(userdata));
|
||||
},
|
||||
&g_file_select_window_ctx.window_handle);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ModResult buildMenuTab() {
|
||||
UiMenuTabDesc desc = UI_MENU_TAB_DESC_INIT;
|
||||
@@ -464,6 +493,56 @@ ModResult buildMenuTab() {
|
||||
return session::svc_mng.ui->register_menu_tab(session::svc_mng.mod_ctx, &desc, &g_menu_tab);
|
||||
}
|
||||
|
||||
ModResult buildFileSelectGateMenu(dFile_select_c* fileSelect) {
|
||||
UiTabDesc tabs[6]{};
|
||||
|
||||
tabs[0].struct_size = sizeof(UiTabDesc);
|
||||
tabs[0].title = "Play";
|
||||
tabs[0].build = buildPlayTab;
|
||||
|
||||
tabs[1].struct_size = sizeof(UiTabDesc);
|
||||
tabs[1].title = "Seed Management";
|
||||
tabs[1].build = buildSeedManagementTab;
|
||||
tabs[1].update = updateSeedManagementTab;
|
||||
|
||||
tabs[2].struct_size = sizeof(UiTabDesc);
|
||||
tabs[2].title = "Seed Options";
|
||||
tabs[2].build = buildSeedOptionsTab;
|
||||
|
||||
tabs[3].struct_size = sizeof(UiTabDesc);
|
||||
tabs[3].title = "Hints";
|
||||
tabs[3].build = buildHintsTab;
|
||||
|
||||
tabs[4].struct_size = sizeof(UiTabDesc);
|
||||
tabs[4].title = "Starting Inventory";
|
||||
tabs[4].build = buildStartingInventoryTab;
|
||||
|
||||
tabs[5].struct_size = sizeof(UiTabDesc);
|
||||
tabs[5].title = "Excluded Locations";
|
||||
tabs[5].build = buildExcludedLocationsTab;
|
||||
|
||||
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
|
||||
desc.tabs = tabs;
|
||||
desc.tab_count = 6;
|
||||
desc.user_data = fileSelect;
|
||||
desc.on_closed = [](ModContext*, UiWindowHandle, void* userdata) {
|
||||
dFile_select_c* i_this = static_cast<dFile_select_c*>(userdata);
|
||||
|
||||
// if closing the window through backing out, return to file select
|
||||
if (!g_file_select_window_ctx.is_proceed) {
|
||||
i_this->headerTxtSet(0x43, 1, 0);
|
||||
i_this->fileRecScaleAnmInitSet2(0.0f, 1.0f);
|
||||
i_this->nameMoveAnmInitSet(0xd29, 0xd1f);
|
||||
i_this->modoruTxtDispAnmInit(0);
|
||||
i_this->mDataSelProc = dFile_select_c::DATASELPROC_NAME_TO_DATA_SELECT_MOVE;
|
||||
}
|
||||
|
||||
g_dialogSelectModeState = SelectReady;
|
||||
};
|
||||
|
||||
session::svc_mng.ui->window_push(session::svc_mng.mod_ctx, &desc, &g_file_select_window_ctx.window_handle);
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPath() {
|
||||
return paths::GetRandomizerPath() / "randomizer";
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include <mods/api.h>
|
||||
#include "mods/svc/ui.h"
|
||||
|
||||
// Forward declaration
|
||||
namespace randomizer::seedgen::config {
|
||||
@@ -12,12 +13,27 @@ class dFile_select_c;
|
||||
|
||||
namespace randomizer::ui {
|
||||
|
||||
enum dialogSelectModeState : uint8_t {
|
||||
SelectReady,
|
||||
SelectWait,
|
||||
SelectVanilla,
|
||||
SelectRandomizer
|
||||
};
|
||||
extern dialogSelectModeState g_dialogSelectModeState;
|
||||
|
||||
struct FileSelectGateWindowCtx {
|
||||
UiWindowHandle window_handle{};
|
||||
bool is_proceed{false};
|
||||
};
|
||||
extern FileSelectGateWindowCtx g_file_select_window_ctx;
|
||||
|
||||
void SaveNewRandomizerPreset(const std::string& presetName, bool overwriteExisting = false);
|
||||
void ApplyExistingRandomizerPreset(const std::filesystem::path& presetFilePath);
|
||||
void CopyPermalinkToClipboard();
|
||||
void PastePermalinkFromClipboard();
|
||||
|
||||
ModResult buildMenuTab();
|
||||
ModResult buildFileSelectGateMenu(dFile_select_c*);
|
||||
|
||||
std::filesystem::path GetRandomizerPath();
|
||||
std::filesystem::path GetRandomizerSettingsPath();
|
||||
|
||||
Reference in New Issue
Block a user