mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
752 lines
39 KiB
C++
752 lines
39 KiB
C++
#include "BenMenuBar.h"
|
|
#include "BenPort.h"
|
|
#include <imgui.h>
|
|
#include "public/bridge/consolevariablebridge.h"
|
|
#include <libultraship/libultraship.h>
|
|
#include "graphic/Fast3D/gfx_rendering_api.h"
|
|
#include "UIWidgets.hpp"
|
|
#include <unordered_map>
|
|
#include <string>
|
|
#include "2s2h/Enhancements/Enhancements.h"
|
|
#include "2s2h/Enhancements/Graphics/MotionBlur.h"
|
|
#include "2s2h/Enhancements/Graphics/PlayAsKafei.h"
|
|
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
|
#include "2s2h/DeveloperTools/WarpPoint.h"
|
|
#include "HudEditor.h"
|
|
|
|
extern bool ShouldClearTextureCacheAtEndOfFrame;
|
|
|
|
extern "C" {
|
|
#include "z64.h"
|
|
#include "functions.h"
|
|
extern PlayState* gPlayState;
|
|
}
|
|
|
|
static const std::unordered_map<int32_t, const char*> textureFilteringMap = {
|
|
{ FILTER_THREE_POINT, "Three-Point" },
|
|
{ FILTER_LINEAR, "Linear" },
|
|
{ FILTER_NONE, "None" },
|
|
};
|
|
|
|
static const std::unordered_map<int32_t, const char*> debugSaveOptions = {
|
|
{ DEBUG_SAVE_INFO_COMPLETE, "100\% save" },
|
|
{ DEBUG_SAVE_INFO_VANILLA_DEBUG, "Vanilla debug save" },
|
|
{ DEBUG_SAVE_INFO_NONE, "Empty save" },
|
|
};
|
|
|
|
static const std::unordered_map<Ship::AudioBackend, const char*> audioBackendsMap = {
|
|
{ Ship::AudioBackend::WASAPI, "Windows Audio Session API" },
|
|
{ Ship::AudioBackend::SDL, "SDL" },
|
|
};
|
|
|
|
static std::unordered_map<Ship::WindowBackend, const char*> windowBackendsMap = {
|
|
{ Ship::WindowBackend::DX11, "DirectX" },
|
|
{ Ship::WindowBackend::SDL_OPENGL, "OpenGL" },
|
|
{ Ship::WindowBackend::SDL_METAL, "Metal" },
|
|
{ Ship::WindowBackend::GX2, "GX2" }
|
|
};
|
|
|
|
static const std::unordered_map<int32_t, const char*> clockTypeOptions = {
|
|
{ CLOCK_TYPE_ORIGINAL, "Original" },
|
|
{ CLOCK_TYPE_TEXT_BASED, "Text only" },
|
|
};
|
|
|
|
static const std::unordered_map<int32_t, const char*> alwaysWinDoggyraceOptions = {
|
|
{ ALWAYS_WIN_DOGGY_RACE_OFF, "Off" },
|
|
{ ALWAYS_WIN_DOGGY_RACE_MASKOFTRUTH, "When owning Mask of Truth" },
|
|
{ ALWAYS_WIN_DOGGY_RACE_ALWAYS, "Always" },
|
|
};
|
|
|
|
namespace BenGui {
|
|
|
|
void DrawMenuBarIcon() {
|
|
static bool gameIconLoaded = false;
|
|
if (!gameIconLoaded) {
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Game_Icon",
|
|
"textures/icons/g2ShipIcon.png");
|
|
gameIconLoaded = true;
|
|
}
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetGui()->HasTextureByName("Game_Icon")) {
|
|
#ifdef __SWITCH__
|
|
ImVec2 iconSize = ImVec2(20.0f, 20.0f);
|
|
float posScale = 1.0f;
|
|
#elif defined(__WIIU__)
|
|
ImVec2 iconSize = ImVec2(16.0f * 2, 16.0f * 2);
|
|
float posScale = 2.0f;
|
|
#elif defined(__ANDROID__)
|
|
ImVec2 iconSize = ImVec2(16.0f * 2, 16.0f * 2);
|
|
float posScale = 2.0f;
|
|
#else
|
|
ImVec2 iconSize = ImVec2(16.0f, 16.0f);
|
|
float posScale = 1.0f;
|
|
#endif
|
|
ImGui::SetCursorPos(ImVec2(5, 5) * posScale);
|
|
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), iconSize);
|
|
ImGui::SameLine();
|
|
ImGui::SetCursorPos(ImVec2(25, 0) * posScale);
|
|
}
|
|
}
|
|
|
|
void DrawBenMenu() {
|
|
if (UIWidgets::BeginMenu("2Ship")) {
|
|
if (UIWidgets::MenuItem("Hide Menu Bar",
|
|
#if !defined(__SWITCH__) && !defined(__WIIU__) && !defined(__ANDROID__)
|
|
"F1"
|
|
#else
|
|
"[-]"
|
|
#endif
|
|
)) {
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetMenuBar()->ToggleVisibility();
|
|
}
|
|
#if !defined(__SWITCH__) && !defined(__WIIU__) && !defined(__ANDROID__)
|
|
if (UIWidgets::MenuItem("Toggle Fullscreen", "F11")) {
|
|
Ship::Context::GetInstance()->GetWindow()->ToggleFullscreen();
|
|
}
|
|
#endif
|
|
if (UIWidgets::MenuItem("Reset",
|
|
#ifdef __APPLE__
|
|
"Command-R"
|
|
#elif !defined(__SWITCH__) && !defined(__WIIU__) && !defined(__ANDROID__)
|
|
"Ctrl+R"
|
|
#else
|
|
""
|
|
#endif
|
|
)) {
|
|
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
|
|
->Dispatch("reset");
|
|
}
|
|
#if !defined(__SWITCH__) && !defined(__WIIU__) && !defined(__ANDROID__)
|
|
if (UIWidgets::MenuItem("Open App Files Folder")) {
|
|
std::string filesPath = Ship::Context::GetInstance()->GetAppDirectoryPath();
|
|
SDL_OpenURL(std::string("file:///" + std::filesystem::absolute(filesPath).string()).c_str());
|
|
}
|
|
|
|
if (UIWidgets::MenuItem("Quit")) {
|
|
Ship::Context::GetInstance()->GetWindow()->Close();
|
|
}
|
|
#endif
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
|
|
extern std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
|
|
|
void DrawSettingsMenu() {
|
|
if (UIWidgets::BeginMenu("Settings")) {
|
|
if (UIWidgets::BeginMenu("Audio")) {
|
|
UIWidgets::CVarSliderFloat("Master Volume: %.0f %%", "gSettings.Audio.MasterVolume", 0.0f, 1.0f, 1.0f,
|
|
{ .showButtons = false, .format = "", .isPercentage = true });
|
|
|
|
if (UIWidgets::CVarSliderFloat("Main Music Volume: %.0f %%", "gSettings.Audio.MainMusicVolume", 0.0f, 1.0f,
|
|
1.0f, { .showButtons = false, .format = "", .isPercentage = true })) {
|
|
AudioSeq_SetPortVolumeScale(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gSettings.Audio.MainMusicVolume", 1.0f));
|
|
}
|
|
if (UIWidgets::CVarSliderFloat("Sub Music Volume: %.0f %%", "gSettings.Audio.SubMusicVolume", 0.0f, 1.0f,
|
|
1.0f, { .showButtons = false, .format = "", .isPercentage = true })) {
|
|
AudioSeq_SetPortVolumeScale(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSettings.Audio.SubMusicVolume", 1.0f));
|
|
}
|
|
if (UIWidgets::CVarSliderFloat("Sound Effects Volume: %.0f %%", "gSettings.Audio.SoundEffectsVolume", 0.0f,
|
|
1.0f, 1.0f, { .showButtons = false, .format = "", .isPercentage = true })) {
|
|
AudioSeq_SetPortVolumeScale(SEQ_PLAYER_SFX, CVarGetFloat("gSettings.Audio.SoundEffectsVolume", 1.0f));
|
|
}
|
|
if (UIWidgets::CVarSliderFloat("Fanfare Volume: %.0f %%", "gSettings.Audio.FanfareVolume", 0.0f, 1.0f, 1.0f,
|
|
{ .showButtons = false, .format = "", .isPercentage = true })) {
|
|
AudioSeq_SetPortVolumeScale(SEQ_PLAYER_FANFARE, CVarGetFloat("gSettings.Audio.FanfareVolume", 1.0f));
|
|
}
|
|
if (UIWidgets::CVarSliderFloat("Ambience Volume: %.0f %%", "gSettings.Audio.AmbienceVolume", 0.0f, 1.0f,
|
|
1.0f, { .showButtons = false, .format = "", .isPercentage = true })) {
|
|
AudioSeq_SetPortVolumeScale(SEQ_PLAYER_AMBIENCE, CVarGetFloat("gSettings.Audio.AmbienceVolume", 1.0f));
|
|
}
|
|
|
|
auto currentAudioBackend = Ship::Context::GetInstance()->GetAudio()->GetAudioBackend();
|
|
if (UIWidgets::Combobox(
|
|
"Audio API", ¤tAudioBackend, audioBackendsMap,
|
|
{ .tooltip = "Sets the audio API used by the game. Requires a relaunch to take effect.",
|
|
.disabled = Ship::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1,
|
|
.disabledTooltip = "Only one audio API is available on this platform." })) {
|
|
Ship::Context::GetInstance()->GetAudio()->SetAudioBackend(currentAudioBackend);
|
|
}
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Graphics")) {
|
|
|
|
#ifndef __APPLE__
|
|
if (UIWidgets::CVarSliderFloat("Internal Resolution: %f %%", CVAR_INTERNAL_RESOLUTION, 0.5f, 2.0f, 1.0f)) {
|
|
Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(
|
|
CVarGetFloat(CVAR_INTERNAL_RESOLUTION, 1));
|
|
};
|
|
UIWidgets::Tooltip(
|
|
"Multiplies your output resolution by the value inputted, as a more intensive but effective "
|
|
"form of anti-aliasing");
|
|
#endif
|
|
#ifndef __WIIU__
|
|
if (UIWidgets::CVarSliderInt("MSAA: %d", CVAR_MSAA_VALUE, 1, 8, 1)) {
|
|
Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger(CVAR_MSAA_VALUE, 1));
|
|
};
|
|
UIWidgets::Tooltip(
|
|
"Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel");
|
|
#endif
|
|
|
|
{ // FPS Slider
|
|
constexpr unsigned int minFps = 20;
|
|
static unsigned int maxFps;
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
|
maxFps = 360;
|
|
} else {
|
|
maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
|
}
|
|
unsigned int currentFps =
|
|
std::max(std::min(OTRGlobals::Instance->GetInterpolationFPS(), maxFps), minFps);
|
|
bool matchingRefreshRate =
|
|
CVarGetInteger("gMatchRefreshRate", 0) &&
|
|
Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11;
|
|
UIWidgets::CVarSliderInt((currentFps == 20) ? "FPS: Original (20)" : "FPS: %d", "gInterpolationFPS",
|
|
minFps, maxFps, 20, { .disabled = matchingRefreshRate });
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
|
UIWidgets::Tooltip(
|
|
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is "
|
|
"purely visual and does not impact game logic, execution of glitches etc.\n\n A higher target "
|
|
"FPS than your monitor's refresh rate will waste resources, and might give a worse result.");
|
|
} else {
|
|
UIWidgets::Tooltip(
|
|
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is "
|
|
"purely visual and does not impact game logic, execution of glitches etc.");
|
|
}
|
|
} // END FPS Slider
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
|
// UIWidgets::Spacer(0);
|
|
if (ImGui::Button("Match Refresh Rate")) {
|
|
int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
|
if (hz >= 20 && hz <= 360) {
|
|
CVarSetInteger("gInterpolationFPS", hz);
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
|
}
|
|
}
|
|
} else {
|
|
UIWidgets::CVarCheckbox("Match Refresh Rate", "gMatchRefreshRate");
|
|
}
|
|
UIWidgets::Tooltip("Matches interpolation value to the current game's window refresh rate");
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
|
UIWidgets::CVarSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off"
|
|
: "Jitter fix: >= %d FPS",
|
|
"gExtraLatencyThreshold", 0, 360, 80);
|
|
UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input "
|
|
"lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the "
|
|
"CPU to work on one frame while GPU works on the previous frame.\nThis setting "
|
|
"should be used when your computer is too slow to do CPU + GPU work in time.");
|
|
}
|
|
|
|
// UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
|
|
// #endregion */
|
|
|
|
Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
|
Ship::WindowBackend configWindowBackend;
|
|
int32_t configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
|
if (configWindowBackendId != -1 &&
|
|
configWindowBackendId < static_cast<int>(Ship::WindowBackend::BACKEND_COUNT)) {
|
|
configWindowBackend = static_cast<Ship::WindowBackend>(configWindowBackendId);
|
|
} else {
|
|
configWindowBackend = runningWindowBackend;
|
|
}
|
|
|
|
auto availableWindowBackends = Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends();
|
|
std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
|
|
for (auto& backend : *availableWindowBackends) {
|
|
availableWindowBackendsMap[backend] = windowBackendsMap[backend];
|
|
}
|
|
|
|
if (UIWidgets::Combobox(
|
|
"Renderer API (Needs reload)", &configWindowBackend, availableWindowBackendsMap,
|
|
{ .tooltip = "Sets the renderer API used by the game. Requires a relaunch to take effect.",
|
|
.disabled = Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1,
|
|
.disabledTooltip = "Only one renderer API is available on this platform." })) {
|
|
Ship::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id",
|
|
static_cast<int32_t>(configWindowBackend));
|
|
Ship::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name",
|
|
windowBackendsMap.at(configWindowBackend));
|
|
Ship::Context::GetInstance()->GetConfig()->Save();
|
|
}
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) {
|
|
UIWidgets::CVarCheckbox("Enable Vsync", CVAR_VSYNC_ENABLED);
|
|
}
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) {
|
|
UIWidgets::CVarCheckbox("Windowed fullscreen", CVAR_SDL_WINDOWED_FULLSCREEN);
|
|
}
|
|
|
|
if (Ship::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) {
|
|
UIWidgets::CVarCheckbox(
|
|
"Allow multi-windows", CVAR_ENABLE_MULTI_VIEWPORTS,
|
|
{ .tooltip = "Allows multiple windows to be opened at once. Requires a reload to take effect." });
|
|
}
|
|
|
|
UIWidgets::CVarCombobox("Texture Filter (Needs reload)", CVAR_TEXTURE_FILTER, textureFilteringMap);
|
|
|
|
// Currently this only has "Overlays Text Font", it doesn't use our new UIWidgets so it stands out
|
|
// Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings();
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
// #region 2S2H [Todo] None of this works yet
|
|
/*
|
|
if (UIWidgets::BeginMenu("Controller")) { */
|
|
if (mInputEditorWindow) {
|
|
UIWidgets::WindowButton("Controller Mapping", "gWindows.InputEditor", mInputEditorWindow);
|
|
}
|
|
/*
|
|
#ifndef __SWITCH__
|
|
UIWidgets::CVarCheckbox("Menubar Controller Navigation", CVAR_IMGUI_CONTROLLER_NAV, {
|
|
.tooltip = "Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: "
|
|
"This will disable game inputs while the menubar is visible.\n\nD-pad to move between "
|
|
"items, A to select, and X to grab focus on the menu bar"
|
|
});
|
|
#endif
|
|
UIWidgets::CVarCheckbox("Show Inputs", "gInputEnabled", {
|
|
.tooltip = "Shows currently pressed inputs on the bottom right of the screen"
|
|
});
|
|
UIWidgets::CVarSliderFloat("Input Scale: %.1f", "gInputScale", 1.0f, 3.0f, 1.0f, {
|
|
.tooltip = "Sets the on screen size of the displayed inputs from the Show Inputs setting",
|
|
.showButtons = false,
|
|
.format = ""
|
|
});
|
|
UIWidgets::CVarSliderInt("Simulated Input Lag: %d frames", CVAR_SIMULATED_INPUT_LAG, 0, 6, 0, {
|
|
.tooltip = "Buffers your inputs to be executed a specified amount of frames later"
|
|
});
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::EndMenu();
|
|
*/
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
|
|
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
|
|
|
void DrawEnhancementsMenu() {
|
|
if (UIWidgets::BeginMenu("Enhancements")) {
|
|
|
|
if (UIWidgets::BeginMenu("Camera")) {
|
|
ImGui::SeparatorText("Fixes");
|
|
UIWidgets::CVarCheckbox(
|
|
"Fix Targetting Camera Snap", "gEnhancements.Camera.FixTargettingCameraSnap",
|
|
{ .tooltip =
|
|
"Fixes the camera snap that occurs when you are moving and press the targetting button." });
|
|
|
|
ImGui::SeparatorText("Free Look");
|
|
if (UIWidgets::CVarCheckbox(
|
|
"Free Look", "gEnhancements.Camera.FreeLook.Enable",
|
|
{ .tooltip = "Enables free look camera control\nNote: You must remap C buttons off of the right "
|
|
"stick in the controller config menu, and map the camera stick to the right stick.",
|
|
.disabled = CVarGetInteger("gEnhancements.Camera.DebugCam.Enable", 0) != 0 })) {
|
|
RegisterCameraFreeLook();
|
|
}
|
|
|
|
if (CVarGetInteger("gEnhancements.Camera.FreeLook.Enable", 0)) {
|
|
UIWidgets::CVarCheckbox("Invert Camera X Axis", "gEnhancements.Camera.RightStick.InvertXAxis",
|
|
{ .tooltip = "Inverts the Camera X Axis" });
|
|
UIWidgets::CVarCheckbox("Invert Camera Y Axis", "gEnhancements.Camera.RightStick.InvertYAxis",
|
|
{ .tooltip = "Inverts the Camera Y Axis", .defaultValue = true });
|
|
UIWidgets::CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f",
|
|
"gEnhancements.Camera.RightStick.CameraSensitivity.X", 0.01f, 5.0f, 1.0f);
|
|
UIWidgets::CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f",
|
|
"gEnhancements.Camera.RightStick.CameraSensitivity.Y", 0.01f, 5.0f, 1.0f);
|
|
|
|
UIWidgets::CVarSliderInt("Camera Distance: %d", "gEnhancements.Camera.FreeLook.MaxCameraDistance", 100,
|
|
900, 185);
|
|
UIWidgets::CVarSliderInt("Camera Transition Speed: %d", "gEnhancements.Camera.FreeLook.TransitionSpeed",
|
|
1, 900, 25);
|
|
UIWidgets::CVarSliderFloat("Max Camera Height Angle: %.0f°", "gEnhancements.Camera.FreeLook.MaxPitch",
|
|
-89.0f, 89.0f, 72.0f);
|
|
UIWidgets::CVarSliderFloat("Min Camera Height Angle: %.0f°", "gEnhancements.Camera.FreeLook.MinPitch",
|
|
-89.0f, 89.0f, -49.0f);
|
|
f32 maxY = CVarGetFloat("gEnhancements.Camera.FreeLook.MaxPitch", 72.0f);
|
|
f32 minY = CVarGetFloat("gEnhancements.Camera.FreeLook.MinPitch", -49.0f);
|
|
CVarSetFloat("gEnhancements.Camera.FreeLook.MaxPitch", std::max(maxY, minY));
|
|
CVarSetFloat("gEnhancements.Camera.FreeLook.MinPitch", std::min(maxY, minY));
|
|
}
|
|
|
|
ImGui::SeparatorText("'Debug' Camera");
|
|
if (UIWidgets::CVarCheckbox(
|
|
"Debug Camera", "gEnhancements.Camera.DebugCam.Enable",
|
|
{ .tooltip = "Enables free camera control.",
|
|
.disabled = CVarGetInteger("gEnhancements.Camera.FreeLook.Enable", 0) != 0 })) {
|
|
RegisterDebugCam();
|
|
}
|
|
|
|
if (CVarGetInteger("gEnhancements.Camera.DebugCam.Enable", 0)) {
|
|
UIWidgets::CVarCheckbox("Invert Camera X Axis", "gEnhancements.Camera.RightStick.InvertXAxis",
|
|
{ .tooltip = "Inverts the Camera X Axis" });
|
|
UIWidgets::CVarCheckbox("Invert Camera Y Axis", "gEnhancements.Camera.RightStick.InvertYAxis",
|
|
{ .tooltip = "Inverts the Camera Y Axis", .defaultValue = true });
|
|
UIWidgets::CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f",
|
|
"gEnhancements.Camera.RightStick.CameraSensitivity.X", 0.01f, 5.0f, 1.0f);
|
|
UIWidgets::CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f",
|
|
"gEnhancements.Camera.RightStick.CameraSensitivity.Y", 0.01f, 5.0f, 1.0f);
|
|
|
|
UIWidgets::CVarCheckbox(
|
|
"Enable Roll (Six Degrees Of Freedom)", "gEnhancements.Camera.DebugCam.6DOF",
|
|
{ .tooltip = "This allows for all six degrees of movement with the camera, NOTE: Yaw will work "
|
|
"differently in "
|
|
"this system, instead rotating around the focal point, rather than a polar axis." });
|
|
UIWidgets::CVarSliderFloat("Camera Speed: %.0f", "gEnhancements.Camera.DebugCam.CameraSpeed", 0.1f,
|
|
3.0f, 0.5f);
|
|
}
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Cutscenes")) {
|
|
UIWidgets::CVarCheckbox("Hide Title Cards", "gEnhancements.Cutscenes.HideTitleCards");
|
|
UIWidgets::CVarCheckbox("Skip Entrance Cutscenes", "gEnhancements.Cutscenes.SkipEntranceCutscenes");
|
|
UIWidgets::CVarCheckbox(
|
|
"Skip to File Select", "gEnhancements.Cutscenes.SkipToFileSelect",
|
|
{ .tooltip = "Skip the opening title sequence and go straight to the file select menu after boot" });
|
|
UIWidgets::CVarCheckbox(
|
|
"Skip Intro Sequence", "gEnhancements.Cutscenes.SkipIntroSequence",
|
|
{
|
|
.tooltip = "When starting a game you will be taken straight to South Clock Town as Deku Link.",
|
|
});
|
|
UIWidgets::CVarCheckbox(
|
|
"Skip Story Cutscenes", "gEnhancements.Cutscenes.SkipStoryCutscenes",
|
|
{
|
|
.tooltip =
|
|
"Disclaimer: This doesn't do much yet, we will be progressively adding more skips over time",
|
|
});
|
|
UIWidgets::CVarCheckbox(
|
|
"Skip Misc Interactions", "gEnhancements.Cutscenes.SkipMiscInteractions",
|
|
{
|
|
.tooltip =
|
|
"Disclaimer: This doesn't do much yet, we will be progressively adding more skips over time",
|
|
});
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Saving / Time Cycle")) {
|
|
|
|
ImGui::SeparatorText("Saving");
|
|
UIWidgets::CVarCheckbox("Persistent Owl Saves", "gEnhancements.Saving.PersistentOwlSaves",
|
|
{ .tooltip = "Continuing a save will not remove the owl save. Playing Song of "
|
|
"Time, allowing the moon to crash or finishing the "
|
|
"game will remove the owl save and become the new last save." });
|
|
UIWidgets::CVarCheckbox(
|
|
"Pause Menu Save", "gEnhancements.Saving.PauseSave",
|
|
{ .tooltip = "Re-introduce the pause menu save system. Pressing B in the pause menu will give you the "
|
|
"option to create an Owl Save from your current location.\n\nWhen loading back into the "
|
|
"game, you will be placed either at the entrance of the dungeon you saved in, or in South "
|
|
"Clock Town." });
|
|
if (UIWidgets::CVarCheckbox(
|
|
"Autosave", "gEnhancements.Saving.Autosave",
|
|
{ .tooltip = "Automatically create owl saves on the chosen interval.\n\nWhen loading back into the "
|
|
"game, you will be placed either at the entrance of the dungeon you saved in, or in "
|
|
"South Clock Town." })) {
|
|
RegisterAutosave();
|
|
}
|
|
UIWidgets::CVarSliderInt("Autosave Interval (minutes): %d", "gEnhancements.Saving.AutosaveInterval", 1, 60,
|
|
5, { .disabled = !CVarGetInteger("gEnhancements.Saving.Autosave", 0) });
|
|
|
|
ImGui::SeparatorText("Time Cycle");
|
|
UIWidgets::CVarCheckbox("Do not reset Bottle content", "gEnhancements.Cycle.DoNotResetBottleContent",
|
|
{ .tooltip = "Playing the Song Of Time will not reset the bottles' content." });
|
|
UIWidgets::CVarCheckbox("Do not reset Consumables", "gEnhancements.Cycle.DoNotResetConsumables",
|
|
{ .tooltip = "Playing the Song Of Time will not reset the consumables." });
|
|
UIWidgets::CVarCheckbox(
|
|
"Do not reset Razor Sword", "gEnhancements.Cycle.DoNotResetRazorSword",
|
|
{ .tooltip = "Playing the Song Of Time will not reset the Sword back to Kokiri Sword." });
|
|
UIWidgets::CVarCheckbox("Do not reset Rupees", "gEnhancements.Cycle.DoNotResetRupees",
|
|
{ .tooltip = "Playing the Song Of Time will not reset the your rupees." });
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255));
|
|
ImGui::SeparatorText("Unstable");
|
|
ImGui::PopStyleColor();
|
|
UIWidgets::CVarCheckbox(
|
|
"Disable Save Delay", "gEnhancements.Saving.DisableSaveDelay",
|
|
{ .tooltip = "Removes the arbitrary 2 second timer for saving from the original game. This is known to "
|
|
"cause issues when attempting the 0th Day Glitch" });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Dialogues")) {
|
|
UIWidgets::CVarCheckbox(
|
|
"Fast Text", "gEnhancements.Dialogue.FastText",
|
|
{ .tooltip = "Speeds up text rendering, and enables holding of B progress to next message" });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Dpad")) {
|
|
UIWidgets::CVarCheckbox("Dpad Equips", "gEnhancements.Dpad.DpadEquips",
|
|
{ .tooltip = "Allows you to equip items to your d-pad" });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Fixes")) {
|
|
UIWidgets::CVarCheckbox("Fix Ammo Count Color", "gFixes.FixAmmoCountEnvColor",
|
|
{ .tooltip = "Fixes a missing gDPSetEnvColor, which causes the ammo count to be "
|
|
"the wrong color prior to obtaining magic or other conditions." });
|
|
|
|
UIWidgets::CVarCheckbox("Fix Hess and Weirdshot Crash", "gEnhancements.Fixes.HessCrash",
|
|
{ .tooltip = "Fixes a crash that can occur when performing a HESS or Weirdshot.",
|
|
.defaultValue = true });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Graphics")) {
|
|
ImGui::SeparatorText("Clock");
|
|
UIWidgets::CVarCombobox("Clock Type", "gEnhancements.Graphics.ClockType", clockTypeOptions);
|
|
UIWidgets::CVarCheckbox("24 Hours Clock", "gEnhancements.Graphics.24HoursClock");
|
|
MotionBlur_RenderMenuOptions();
|
|
ImGui::SeparatorText("Other");
|
|
UIWidgets::CVarCheckbox("Authentic logo", "gEnhancements.Graphics.AuthenticLogo",
|
|
{ .tooltip = "Hide the game version and build details and display the authentic "
|
|
"model and texture on the boot logo start screen" });
|
|
UIWidgets::CVarCheckbox("Bow Reticle", "gEnhancements.Graphics.BowReticle",
|
|
{ .tooltip = "Gives the bow a reticle when you draw an arrow" });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Masks")) {
|
|
UIWidgets::CVarCheckbox("Fast Transformation", "gEnhancements.Masks.FastTransformation");
|
|
UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere",
|
|
{ .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." });
|
|
UIWidgets::CVarCheckbox("No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", {});
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Minigames")) {
|
|
UIWidgets::CVarCombobox("Always Win Doggy Race", "gEnhancements.Minigames.AlwaysWinDoggyRace",
|
|
alwaysWinDoggyraceOptions);
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Modes")) {
|
|
if (UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei",
|
|
{ .tooltip = "Requires scene reload to take effect." })) {
|
|
UpdatePlayAsKafeiSkeletons();
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
if (UIWidgets::BeginMenu("Player Movement")) {
|
|
UIWidgets::CVarSliderInt("Climb speed", "gEnhancements.PlayerMovement.ClimbSpeed", 1, 5, 1,
|
|
{ .tooltip = "Increases the speed at which Link climbs vines and ladders." });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Restorations")) {
|
|
UIWidgets::CVarCheckbox(
|
|
"Constant Distance Backflips and Sidehops", "gEnhancements.Restorations.ConstantFlipsHops",
|
|
{ .tooltip = "Backflips and Sidehops travel a constant distance as they did in OOT." });
|
|
UIWidgets::CVarCheckbox(
|
|
"Power Crouch Stab", "gEnhancements.Restorations.PowerCrouchStab",
|
|
{ .tooltip =
|
|
"Crouch stabs will use the power of Link's previous melee attack, as is in MM JP 1.0 and OOT." });
|
|
UIWidgets::CVarCheckbox("Side Rolls", "gEnhancements.Restorations.SideRoll",
|
|
{ .tooltip = "Restores side rolling from OOT." });
|
|
UIWidgets::CVarCheckbox("Tatl ISG", "gEnhancements.Restorations.TatlISG",
|
|
{ .tooltip = "Restores Navi ISG from OOT, but now with Tatl." });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (UIWidgets::BeginMenu("Songs/Playback")) {
|
|
UIWidgets::CVarCheckbox(
|
|
"Enable Sun's Song", "gEnhancements.Songs.EnableSunsSong",
|
|
{ .tooltip = "Enables the partially implemented Sun's Song. RIGHT-DOWN-UP-RIGHT-DOWN-UP to play it. "
|
|
"This song will make time move very fast until either Link moves to a different scene, "
|
|
"or when the time switches to a new time period." });
|
|
UIWidgets::CVarCheckbox("Dpad Ocarina", "gEnhancements.Playback.DpadOcarina",
|
|
{ .tooltip = "Enables using the Dpad for Ocarina playback." });
|
|
UIWidgets::CVarCheckbox("Prevent Dropped Ocarina Inputs", "gEnhancements.Playback.NoDropOcarinaInput",
|
|
{ .tooltip = "Prevent dropping inputs when playing the ocarina quickly" });
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (mHudEditorWindow) {
|
|
UIWidgets::WindowButton("Hud Editor", "gWindows.HudEditor", mHudEditorWindow,
|
|
{ .tooltip = "Enables the Hud Editor window, allowing you to edit your hud" });
|
|
}
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
|
|
void DrawCheatsMenu() {
|
|
if (UIWidgets::BeginMenu("Cheats")) {
|
|
UIWidgets::CVarCheckbox("Infinite Health", "gCheats.InfiniteHealth");
|
|
UIWidgets::CVarCheckbox("Infinite Magic", "gCheats.InfiniteMagic");
|
|
UIWidgets::CVarCheckbox("Infinite Rupees", "gCheats.InfiniteRupees");
|
|
UIWidgets::CVarCheckbox("Infinite Consumables", "gCheats.InfiniteConsumables");
|
|
UIWidgets::CVarCheckbox("Unbreakable Razor Sword", "gCheats.UnbreakableRazorSword");
|
|
UIWidgets::CVarCheckbox("Unrestricted Items", "gCheats.UnrestrictedItems");
|
|
if (UIWidgets::CVarCheckbox("Moon Jump on L", "gCheats.MoonJumpOnL",
|
|
{ .tooltip = "Holding L makes you float into the air" })) {
|
|
RegisterMoonJumpOnL();
|
|
}
|
|
UIWidgets::CVarCheckbox("No Clip", "gCheats.NoClip");
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
|
|
extern std::shared_ptr<Ship::GuiWindow> mStatsWindow;
|
|
extern std::shared_ptr<Ship::GuiWindow> mConsoleWindow;
|
|
extern std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
|
|
extern std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
|
|
extern std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
|
|
extern std::shared_ptr<CollisionViewerWindow> mCollisionViewerWindow;
|
|
extern std::shared_ptr<EventLogWindow> mEventLogWindow;
|
|
|
|
const char* logLevels[] = {
|
|
"trace", "debug", "info", "warn", "error", "critical", "off",
|
|
};
|
|
|
|
void DrawDeveloperToolsMenu() {
|
|
if (UIWidgets::BeginMenu("Developer Tools", UIWidgets::Colors::Yellow)) {
|
|
UIWidgets::CVarCheckbox("Debug Mode", "gDeveloperTools.DebugEnabled",
|
|
{ .tooltip = "Enables Debug Mode, allowing you to select maps with L + R + Z." });
|
|
|
|
if (CVarGetInteger("gDeveloperTools.DebugEnabled", 0)) {
|
|
UIWidgets::CVarCheckbox(
|
|
"Better Map Select", "gDeveloperTools.BetterMapSelect.Enabled",
|
|
{ .tooltip = "Overrides the original map select with a translated, more user-friendly version." });
|
|
|
|
if (UIWidgets::CVarCombobox(
|
|
"Debug Save File Mode", "gDeveloperTools.DebugSaveFileMode", debugSaveOptions,
|
|
{ .tooltip =
|
|
"Change the behavior of creating saves while debug mode is enabled:\n\n"
|
|
"- Empty Save: The default 3 heart save file in first cycle\n"
|
|
"- Vanilla Debug Save: Uses the title screen save info (8 hearts, all items and masks)\n"
|
|
"- 100\% Save: All items, equipment, mask, quast status and bombers notebook complete" })) {
|
|
RegisterDebugSaveCreate();
|
|
}
|
|
}
|
|
|
|
if (UIWidgets::CVarCheckbox("Prevent Actor Update", "gDeveloperTools.PreventActorUpdate")) {
|
|
RegisterPreventActorUpdateHooks();
|
|
}
|
|
if (UIWidgets::CVarCheckbox("Prevent Actor Draw", "gDeveloperTools.PreventActorDraw")) {
|
|
RegisterPreventActorDrawHooks();
|
|
}
|
|
if (UIWidgets::CVarCheckbox("Prevent Actor Init", "gDeveloperTools.PreventActorInit")) {
|
|
RegisterPreventActorInitHooks();
|
|
}
|
|
if (UIWidgets::CVarCombobox("Log Level", "gDeveloperTools.LogLevel", logLevels,
|
|
{
|
|
.tooltip = "The log level determines which messages are printed to the "
|
|
"console. This does not affect the log file output",
|
|
.defaultIndex = 1,
|
|
})) {
|
|
Ship::Context::GetInstance()->GetLogger()->set_level(
|
|
(spdlog::level::level_enum)CVarGetInteger("gDeveloperTools.LogLevel", 1));
|
|
}
|
|
|
|
if (gPlayState != NULL) {
|
|
ImGui::Separator();
|
|
UIWidgets::Checkbox(
|
|
"Frame Advance", (bool*)&gPlayState->frameAdvCtx.enabled,
|
|
{ .tooltip = "This allows you to advance through the game one frame at a time on command. "
|
|
"To advance a frame, hold Z and tap R on the second controller. Holding Z "
|
|
"and R will advance a frame every half second. You can also use the buttons below." });
|
|
if (gPlayState->frameAdvCtx.enabled) {
|
|
if (UIWidgets::Button("Advance 1", { .size = UIWidgets::Sizes::Inline })) {
|
|
CVarSetInteger("gDeveloperTools.FrameAdvanceTick", 1);
|
|
}
|
|
ImGui::SameLine();
|
|
UIWidgets::Button("Advance (Hold)", { .size = UIWidgets::Sizes::Inline });
|
|
if (ImGui::IsItemActive()) {
|
|
CVarSetInteger("gDeveloperTools.FrameAdvanceTick", 1);
|
|
}
|
|
}
|
|
}
|
|
RenderWarpPointSection();
|
|
ImGui::Separator();
|
|
if (mCollisionViewerWindow) {
|
|
UIWidgets::WindowButton("Collision Viewer", "gWindows.CollisionViewer", mCollisionViewerWindow,
|
|
{ .tooltip = "Draws collision to the screen" });
|
|
}
|
|
if (mStatsWindow) {
|
|
UIWidgets::WindowButton(
|
|
"Stats", "gWindows.Stats", mStatsWindow,
|
|
{ .tooltip = "Shows the stats window, with your FPS and frametimes, and the OS you're playing on" });
|
|
}
|
|
if (mConsoleWindow) {
|
|
UIWidgets::WindowButton(
|
|
"Console", "gWindows.Console", mConsoleWindow,
|
|
{ .tooltip =
|
|
"Enables the console window, allowing you to input commands, type help for some examples" });
|
|
}
|
|
if (mGfxDebuggerWindow) {
|
|
UIWidgets::WindowButton(
|
|
"Gfx Debugger", "gWindows.GfxDebugger", mGfxDebuggerWindow,
|
|
{ .tooltip =
|
|
"Enables the Gfx Debugger window, allowing you to input commands, type help for some examples" });
|
|
}
|
|
if (mSaveEditorWindow) {
|
|
UIWidgets::WindowButton(
|
|
"Save Editor", "gWindows.SaveEditor", mSaveEditorWindow,
|
|
{ .tooltip = "Enables the Save Editor window, allowing you to edit your save file" });
|
|
}
|
|
if (mActorViewerWindow) {
|
|
UIWidgets::WindowButton(
|
|
"Actor Viewer", "gWindows.ActorViewer", mActorViewerWindow,
|
|
{ .tooltip = "Enables the Actor Viewer window, allowing you to view actors in the world." });
|
|
}
|
|
if (mEventLogWindow) {
|
|
UIWidgets::WindowButton("Event Log", "gWindows.EventLog", mEventLogWindow);
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
|
|
void BenMenuBar::DrawElement() {
|
|
if (ImGui::BeginMenuBar()) {
|
|
DrawMenuBarIcon();
|
|
|
|
static ImVec2 sWindowPadding(8.0f, 8.0f);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, sWindowPadding);
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
DrawBenMenu();
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
DrawSettingsMenu();
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
DrawEnhancementsMenu();
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
DrawCheatsMenu();
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
DrawDeveloperToolsMenu();
|
|
|
|
ImGui::SetCursorPosY(0.0f);
|
|
|
|
ImGui::PopStyleVar(1);
|
|
ImGui::EndMenuBar();
|
|
}
|
|
}
|
|
} // namespace BenGui
|
|
// namespace BenGui
|