Modern menu (#701)

* Start the framework.

* Start header bar.

* Header buttons now toggle. Sections show accordingly.
Basic audio section done. Needs subdividing for sane widget widths.

* Add fonts and multiple sizes.
Add graphics settings to menu.

* Finalized fonts, more sizes.

* Modularized the menu structure. Has an errant EndChild somewhere.

* Finished first step modularization.
Parameterized menu height.

* Some adaptive menu size.

* Moved all enhancements over and organized.
Tried to add button option for sidebar entries.

* Finished Enhancements Menu.
Sidebar window button still broken (can't reference window variables properly, not drawing in the right place).

* Developer Tools header started.
Menu now pops out with a checkbox in Developer Tools.
Menu sizing works for smaller game sizes.
Popout docking disabled.
Port bool added for disallowing popout regardless of cvar.

* Better auto-sizing. Columns collapse to 1 below 800 window width, and scroll.

* Move inside of HudEditorWindow::DrawElement to DrawContents, and call DrawContents from DrawElement.

* Menu resizability complete.
Menu popout complete.
Menu popout position/size is retained when popped in.
Apply HUD editor changes, draw contents in menu if window is closed.
All child sizes properly calculated.
SidebarEntry drawing separated into its own custom element.

* Split header entries into separate widget.
Header now dynamically sized and shows scrollbar when necessary.

* Modify EventLog to be drawable with the DrawContents setup.
Prevent menu from covering other windows (always in back).

* Add reset, close menu, and quit buttons to the header.

* Fix reset and quit button placement.

* Swap Actor Viewer, Collision Viewer, Save Editor to DrawContents concept.
Change reset icon to FA_ICON_UNDO (single arrow) and quit icon to FA_ICON_POWER_OFF.
Add button to close menu button tooltip, add parentheses to button for reset tooltip.

* Custom InputEditorWindow to work with menu.
Fix LUS references in Menu.cpp for Window backend changes.
Implement gamepad navigation and forced cursor visibility checkboxes.
Toggle cursor visibility according to menu status and forced visibility CVar.

* clang-format

* Swap std for fmt (runner build error).
Ensure cursor visibility is restored if started in full screen with the menu open.

* Oops, still had #include <format>

* Swap to LUS GetMenu() functionality.
Add option to hide "F1 to open enhancements menu" text at startup if menus aren't open.

* Remove last vestiges of pre-LUS-menu functionality.

* cleanup

* Adapt to GuiElement, GuiWindow changes on the menu support PR.

* LUS PR bump.
Adapt to cursor visibility changes in LUS.
Adapt to menu toggle changes in LUS.
Fix input editor not hiding in menu when popped out.

* Add new enhancements and cheats to Modern Menu from rebase.

* clang

* Apply Graphics Menu Lag Fix to Menu structure.

* Remove unnecessary window children to simplify controller navigation.

* clang

* Add `UpdateWindowBackendObjects()` call to backend combobox.

* Rebase to latest develop. Remove redundant window backend stuff that exists now in BenMenuBar.

* Search Enhancement (#2)

* 90% complete, Commit for review.

* Updated remaining Menu Entries, Reverted Backends and other Window Buttons for now.

Motion Blur copied to Search Menu.

* Did I mention I dislike this clang thing? lol

* Updating MotionBlur options and reverting soem things.

* Integrates .disabled and .disabledTooltip to the constructors. Allows for multiple qualifications to be checked against for disabling widgets and for setting the tooltip accordingly.

* Updated Disabled Reasoning

* Better Disabled State registration system

* Clean up from testing

* Expand WidgetOptions to be able to handle string and float values. bool and uint32_t are handled through int32_t.
Numerous renames.
Added several data structures to allow for dynamic updating of CVars for DisableOptions, as well as dynamic evaluation of status with enumerated conditions (less than, greater than, equal to).
Added menuThemeIndex variable to store state of menu theme selection instead of having all the individual calls to CVarGetInteger for it. Updated once per frame.

* Changed color vector to map with enum as key and UIWidget::Colors as the value.
More renames.
Moved float slider values into case block.

* Add Color_RGB8 and Color_RGBA8 to CVarVariant in preparation for adding color widgets to menu item system.
Not happy it required comparison operator overrides, but it is what it is.

* Changed disable conditions to lambdas.

* Convert Stats and Collision Viewer to menu item system.
Swap out DisableOption vector for activeDisables and a lambda function for evaluating disabled and hidden. Set the precedent to still use the DisableInfo system.

* Add DisableOption for both camera settings being off.
Put Debug Camera in Free Look column, disable common widgets for both cameras, hide widgets specific to either if off.

* Moved more widgets to MenuItem system. Some need proper initialization routines because of Ship::Context references.

* Convert menu items to nested vector setup.
Remove MenuItem enum.
Add menu item location display to search results.

* Partial removal of SidebarEntryIndex enum.

* Finish removing SidebarEntryIndex.
Rework drawing code to handle the change back to direct vector access.
Add tooltips to search.

* Fix Graphics enhancements section title.

* Copy added menu items to modern menu system.

* clang

* Add some documentation for the menu system components.

* Revert change to std::map

* `size_t` because GCC has to be happy

* Fixed HUD Editor Widescreen mode not displaying the sliders properly.
Changed all windows to full-section-width display.

* Revert changes to MotionBlur.cpp

* Add non-CVar variants of checkbox, combobox, and the sliders.
Fix motion blur functionality with new non-CVar widgets.

* Add non-CVar variants of checkbox, combobox, and the sliders.
Fix motion blur functionality with those non-CVar widgets.
Add size and labelPosition to widgetOptions, implemented on button and checkbox/combobox/sliders.
Change window popout buttons to inline size type.

* Rename SearchMenu.h to SearchableMenuItems.h and move to BenGui folder.

* Forgot to change the include XD

* Change `modifierFunc` to `preFunc`, updated documentation for that and including `postFunc`.

* Modify code to require variable for non-CVar widget initialization when necessary. Check for `valuePointer` being nullptr, and preventing widget drawing with a debug assert and error log entry.
Remove all `has_variant` calls and wrap entire widget type switch in `SearchMenuGetItem` with a try/catch on `std::bad_variant_access` with another error log and debug assert.

* More review changes.

* Implement `isPercentage`, `format`, and `showButtons` for sliders.
Pull values of those over from menubar.
Add documentation on `widgetOptions` for those and others added for previous review changes.
Move Fast Magic Arrow and Instant Fin Recall to Gameplay section.

* Modify header and sidebar "buttons" to match theming of regular buttons.

* Add precision clamping to SliderFloat value. At least 1.0 seems to be consistent at "100%".
Change IR slider to be percentage.

* Mention weirdness with SDL and pad menu button in controller nav tooltip.

* Move Menu files to 2s2h/BenGui.

* Add Warp Points to Developer Tools.
Make "Press F1" prompt show only when a menu isn't registered.

* clang

* Make search input take focus when search menu is open.

* Forgot include.

* Global search (#3)

* Restore Sidebar search entry, but lock it behind a checkbox in Settings. Dynamically adds or removes the sidebar entry, and header search is toggled inversely.

* Make menu toggle its visibility when using the button in the menu to close. Couldn't handle Alt+F4 without a hook I didn't want to add.
Remove unneeded commented code.

---------

Co-authored-by: Caladius <Caladius@users.noreply.github.com>
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
This commit is contained in:
Malkierian 2024-10-02 17:25:26 -07:00 committed by GitHub
parent 75bc685360
commit 71c2c94ece
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 4123 additions and 88 deletions

View File

@ -27,7 +27,6 @@ std::shared_ptr<BenMenuBar> mBenMenuBar;
std::shared_ptr<Ship::GuiWindow> mConsoleWindow;
std::shared_ptr<Ship::GuiWindow> mStatsWindow;
std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
@ -35,6 +34,8 @@ std::shared_ptr<HudEditorWindow> mHudEditorWindow;
std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
std::shared_ptr<CollisionViewerWindow> mCollisionViewerWindow;
std::shared_ptr<EventLogWindow> mEventLogWindow;
std::shared_ptr<BenMenu> mBenMenu;
std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
void SetupGuiElements() {
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
@ -47,7 +48,7 @@ void SetupGuiElements() {
mBenMenuBar = std::make_shared<BenMenuBar>(CVAR_MENU_BAR_OPEN, CVarGetInteger(CVAR_MENU_BAR_OPEN, 0));
gui->SetMenuBar(std::reinterpret_pointer_cast<Ship::GuiMenuBar>(mBenMenuBar));
if (gui->GetMenuBar() && !gui->GetMenuBar()->IsVisible()) {
if (!gui->GetMenuBar() && !CVarGetInteger("gSettings.DisableMenuShortcutNotify", 0)) {
#if defined(__SWITCH__) || defined(__WIIU__)
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
#else
@ -55,6 +56,9 @@ void SetupGuiElements() {
#endif
}
mBenMenu = std::make_shared<BenMenu>("gWindows.Menu", "Settings Menu");
gui->SetMenu(mBenMenu);
mStatsWindow = gui->GetGuiWindow("Stats");
if (mStatsWindow == nullptr) {
SPDLOG_ERROR("Could not find stats window");
@ -65,37 +69,38 @@ void SetupGuiElements() {
SPDLOG_ERROR("Could not find console window");
}
mInputEditorWindow = gui->GetGuiWindow("Input Editor");
if (mInputEditorWindow == nullptr) {
SPDLOG_ERROR("Could not find input editor window");
}
mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow");
if (mGfxDebuggerWindow == nullptr) {
SPDLOG_ERROR("Could not find input GfxDebuggerWindow");
}
mSaveEditorWindow = std::make_shared<SaveEditorWindow>("gWindows.SaveEditor", "Save Editor");
mBenInputEditorWindow = std::make_shared<BenInputEditorWindow>("gWindows.BenInputEditor", "2S2H Input Editor");
gui->AddGuiWindow(mBenInputEditorWindow);
mSaveEditorWindow = std::make_shared<SaveEditorWindow>("gWindows.SaveEditor", "Save Editor", ImVec2(480, 600));
gui->AddGuiWindow(mSaveEditorWindow);
mHudEditorWindow = std::make_shared<HudEditorWindow>("gWindows.HudEditor", "Hud Editor");
mHudEditorWindow = std::make_shared<HudEditorWindow>("gWindows.HudEditor", "HUD Editor", ImVec2(480, 600));
gui->AddGuiWindow(mHudEditorWindow);
mActorViewerWindow = std::make_shared<ActorViewerWindow>("gWindows.ActorViewer", "Actor Viewer");
mActorViewerWindow = std::make_shared<ActorViewerWindow>("gWindows.ActorViewer", "Actor Viewer", ImVec2(520, 600));
gui->AddGuiWindow(mActorViewerWindow);
mCollisionViewerWindow = std::make_shared<CollisionViewerWindow>("gWindows.CollisionViewer", "Collision Viewer");
mCollisionViewerWindow =
std::make_shared<CollisionViewerWindow>("gWindows.CollisionViewer", "Collision Viewer", ImVec2(390, 475));
gui->AddGuiWindow(mCollisionViewerWindow);
mEventLogWindow = std::make_shared<EventLogWindow>("gWindows.EventLog", "Event Log");
mEventLogWindow = std::make_shared<EventLogWindow>("gWindows.EventLog", "Event Log", ImVec2(520, 600));
gui->AddGuiWindow(mEventLogWindow);
gui->SetPadBtnTogglesMenu();
}
void Destroy() {
mBenMenuBar = nullptr;
mBenMenu = nullptr;
mStatsWindow = nullptr;
mConsoleWindow = nullptr;
mInputEditorWindow = nullptr;
mBenInputEditorWindow = nullptr;
mGfxDebuggerWindow = nullptr;
mCollisionViewerWindow = nullptr;
mEventLogWindow = nullptr;

View File

@ -7,6 +7,8 @@
#include "DeveloperTools/ActorViewer.h"
#include "DeveloperTools/CollisionViewer.h"
#include "DeveloperTools/EventLog.h"
#include "BenInputEditorWindow.h"
#include "Menu.h"
namespace BenGui {
void SetupHooks();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
#pragma once
#include "stdint.h"
#include "window/gui/GuiWindow.h"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <imgui.h>
#include <unordered_map>
#include <string>
#include <vector>
#include <set>
#include "controller/controldevice/controller/Controller.h"
class BenInputEditorWindow : public Ship::GuiWindow {
public:
using Ship::GuiWindow::GuiWindow;
~BenInputEditorWindow();
void DrawButton(const char* label, int32_t n64Btn, int32_t currentPort, int32_t* btnReading);
void DrawInputChip(const char* buttonName, ImVec4 color);
void DrawAnalogPreview(const char* label, ImVec2 stick, float deadzone = 0, bool gyro = false);
void DrawControllerSchema();
bool TestingRumble();
void DrawFullContents();
void DrawPortTabContents(uint8_t portIndex);
protected:
void InitElement() override;
void DrawElement() override;
void UpdateElement() override;
private:
void DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, Ship::Direction direction,
ImVec4 color);
void DrawButtonLine(const char* buttonName, uint8_t port, CONTROLLERBUTTONS_T bitmask, ImVec4 color);
void DrawButtonLineEditMappingButton(uint8_t port, CONTROLLERBUTTONS_T bitmask, std::string id);
void DrawButtonLineAddMappingButton(uint8_t port, CONTROLLERBUTTONS_T bitmask);
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction,
std::string id);
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction);
void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color);
void DrawRumbleSection(uint8_t port);
void DrawRemoveRumbleMappingButton(uint8_t port, std::string id);
void DrawAddRumbleMappingButton(uint8_t port);
void DrawLEDSection(uint8_t port);
void DrawRemoveLEDMappingButton(uint8_t port, std::string id);
void DrawAddLEDMappingButton(uint8_t port);
void DrawGyroSection(uint8_t port);
void DrawRemoveGyroMappingButton(uint8_t port, std::string id);
void DrawAddGyroMappingButton(uint8_t port);
int32_t mGameInputBlockTimer;
int32_t mMappingInputBlockTimer;
int32_t mRumbleTimer;
std::shared_ptr<Ship::ControllerRumbleMapping> mRumbleMappingToTest;
// mBitmaskToMappingIds[port][bitmask] = { id0, id1, ... }
std::unordered_map<uint8_t, std::unordered_map<CONTROLLERBUTTONS_T, std::vector<std::string>>> mBitmaskToMappingIds;
// mStickDirectionToMappingIds[port][stick][direction] = { id0, id1, ... }
std::unordered_map<uint8_t,
std::unordered_map<uint8_t, std::unordered_map<Ship::Direction, std::vector<std::string>>>>
mStickDirectionToMappingIds;
void UpdateBitmaskToMappingIds(uint8_t port);
void UpdateStickDirectionToMappingIds(uint8_t port);
void GetButtonColorsForShipDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor);
void DrawPortTab(uint8_t portIndex);
std::set<CONTROLLERBUTTONS_T> mButtonsBitmasks;
std::set<CONTROLLERBUTTONS_T> mDpadBitmasks;
void DrawButtonDeviceIcons(uint8_t portIndex, std::set<CONTROLLERBUTTONS_T> bitmasks);
void DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::Stick stick);
void DrawRumbleDeviceIcons(uint8_t portIndex);
void DrawGyroDeviceIcons(uint8_t portIndex);
void DrawLEDDeviceIcons(uint8_t portIndex);
bool mInputEditorPopupOpen;
void DrawSetDefaultsButton(uint8_t portIndex);
void DrawClearAllButton(uint8_t portIndex);
std::map<Ship::ShipDeviceIndex, bool> mDeviceIndexVisiblity;
void DrawDeviceVisibilityButtons();
};

View File

@ -153,7 +153,7 @@ void DrawBenMenu() {
}
}
extern std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
extern std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
void DrawSettingsMenu() {
if (UIWidgets::BeginMenu("Settings")) {
@ -312,8 +312,8 @@ void DrawSettingsMenu() {
// #region 2S2H [Todo] None of this works yet
/*
if (UIWidgets::BeginMenu("Controller")) { */
if (mInputEditorWindow) {
UIWidgets::WindowButton("Controller Mapping", "gWindows.InputEditor", mInputEditorWindow);
if (mBenInputEditorWindow) {
UIWidgets::WindowButton("Controller Mapping", "gWindows.InputEditor", mBenInputEditorWindow);
}
/*
#ifndef __SWITCH__

View File

@ -7,6 +7,7 @@
#include "DeveloperTools/ActorViewer.h"
#include "DeveloperTools/CollisionViewer.h"
#include "DeveloperTools/EventLog.h"
#include "BenInputEditorWindow.h"
namespace BenGui {
class BenMenuBar : public Ship::GuiMenuBar {

View File

@ -167,12 +167,6 @@ enum Presets {
};
void HudEditorWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(480, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Hud Editor", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
static HudEditor::Presets preset = HudEditor::Presets::VANILLA;
if (UIWidgets::Combobox("Preset", &preset, presetNames)) {
for (int i = HUD_EDITOR_ELEMENT_B; i < HUD_EDITOR_ELEMENT_MAX; i++) {
@ -252,7 +246,9 @@ void HudEditorWindow::DrawElement() {
}
if (CVarGetInteger(hudEditorElements[i].modeCvar, HUD_EDITOR_ELEMENT_MODE_VANILLA) >=
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43) {
if (ImGui::BeginTable("##table", 3, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoBordersInBody)) {
if (ImGui::BeginTable("##table", 3,
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoBordersInBody |
ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableNextColumn();
UIWidgets::CVarSliderInt("X", hudEditorElements[i].xCvar, -10, 330, hudEditorElements[i].defaultX,
{
@ -279,6 +275,4 @@ void HudEditorWindow::DrawElement() {
}
ImGui::PopID();
}
ImGui::End();
}

471
mm/2s2h/BenGui/Menu.cpp Normal file
View File

@ -0,0 +1,471 @@
#include "Menu.h"
#include "BenPort.h"
#include "BenGui.hpp"
#include "UIWidgets.hpp"
#include "graphic/Fast3D/gfx_rendering_api.h"
#include "2s2h/Enhancements/Enhancements.h"
#include "2s2h/Enhancements/Graphics/MotionBlur.h"
#include "2s2h/Enhancements/Graphics/PlayAsKafei.h"
#include "2s2h/DeveloperTools/DeveloperTools.h"
#include "window/gui/GuiMenuBar.h"
#include "window/gui/GuiElement.h"
#include "DeveloperTools/SaveEditor.h"
#include "DeveloperTools/ActorViewer.h"
#include "DeveloperTools/CollisionViewer.h"
#include "DeveloperTools/EventLog.h"
#include "HudEditor.h"
#include "SearchableMenuItems.h"
extern "C" {
#include "z64.h"
#include "functions.h"
extern PlayState* gPlayState;
}
std::vector<ImVec2> windowTypeSizes = { {} };
namespace BenGui {
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
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;
extern std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
extern std::shared_ptr<std::vector<Ship::WindowBackend>> availableWindowBackends;
extern std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
extern Ship::WindowBackend configWindowBackend;
extern void UpdateWindowBackendObjects();
// BENTODO: Not implemented yet
// UIWidgets::CVarCheckbox("Widescreen Actor Culling",
// "gEnhancements.Graphics.ActorCullingAccountsForWidescreen",
// { .tooltip = "Adjusts the culling planes to account for widescreen resolutions. "
// "This may have unintended side effects." });
// if (gPlayState != NULL) {
// ImGui::Separator();
// SearchMenuGetItem(MENU_ITEM_FRAME_ADVANCE_ENABLE);
// if (gPlayState->frameAdvCtx.enabled) {
// SearchMenuGetItem(MENU_ITEM_FRAME_ADVANCE_SINGLE);
// SearchMenuGetItem(MENU_ITEM_FRAME_ADVANCE_HOLD);
// if (ImGui::IsItemActive()) {
// CVarSetInteger("gDeveloperTools.FrameAdvanceTick", 1);
// }
// }
// }
// ImGui::PushStyleColor(ImGuiCol_Button, menuTheme[menuThemeIndex]);
// RenderWarpPointSection();
// ImGui::PopStyleColor(1);
//}
BenMenu::BenMenu(const std::string& consoleVariable, const std::string& name) : GuiWindow(consoleVariable, name) {
}
void BenMenu::InitElement() {
popped = CVarGetInteger("gSettings.Menu.Popout", 0);
poppedSize.x = CVarGetInteger("gSettings.Menu.PoppedWidth", 1280);
poppedSize.y = CVarGetInteger("gSettings.Menu.PoppedHeight", 800);
poppedPos.x = CVarGetInteger("gSettings.Menu.PoppedPos.x", 0);
poppedPos.y = CVarGetInteger("gSettings.Menu.PoppedPos.y", 0);
AddSettings();
AddEnhancements();
AddDevTools();
menuEntries = { { "Settings", settingsSidebar, "gSettings.Menu.SettingsSidebarIndex" },
{ "Enhancements", enhancementsSidebar, "gSettings.Menu.EnhancementsSidebarIndex" },
{ "Developer Tools", devToolsSidebar, "gSettings.Menu.DevToolsSidebarIndex" } };
UpdateWindowBackendObjects();
}
void BenMenu::UpdateElement() {
}
bool ModernMenuSidebarEntry(std::string label) {
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStyle& style = ImGui::GetStyle();
ImVec2 pos = window->DC.CursorPos;
const ImGuiID sidebarId = window->GetID(std::string(label + "##Sidebar").c_str());
ImVec2 labelSize = ImGui::CalcTextSize(label.c_str(), ImGui::FindRenderedTextEnd(label.c_str()), true);
pos.y += style.FramePadding.y;
pos.x = window->WorkRect.GetCenter().x - labelSize.x / 2;
ImRect bb = { pos - style.FramePadding, pos + labelSize + style.FramePadding };
ImGui::ItemSize(bb, style.FramePadding.y);
ImGui::ItemAdd(bb, sidebarId);
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, sidebarId, &hovered, &held);
if (pressed) {
ImGui::MarkItemEdited(sidebarId);
}
window->DrawList->AddRectFilled(pos - style.FramePadding, pos + labelSize + style.FramePadding,
ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive
: hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button),
3.0f);
UIWidgets::RenderText(pos, label.c_str(), ImGui::FindRenderedTextEnd(label.c_str()), true);
return pressed;
}
bool ModernMenuHeaderEntry(std::string label) {
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStyle& style = ImGui::GetStyle();
ImVec2 pos = window->DC.CursorPos;
const ImGuiID headerId = window->GetID(std::string(label + "##Header").c_str());
ImVec2 labelSize = ImGui::CalcTextSize(label.c_str(), ImGui::FindRenderedTextEnd(label.c_str()), true);
ImRect bb = { pos, pos + labelSize + style.FramePadding * 2 };
ImGui::ItemSize(bb, style.FramePadding.y);
ImGui::ItemAdd(bb, headerId);
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, headerId, &hovered, &held);
window->DrawList->AddRectFilled(bb.Min, bb.Max,
ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive
: hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button),
3.0f);
pos += style.FramePadding;
UIWidgets::RenderText(pos, label.c_str(), ImGui::FindRenderedTextEnd(label.c_str()), true);
return pressed;
}
void BenMenu::Draw() {
if (!IsVisible()) {
return;
}
DrawElement();
// Sync up the IsVisible flag if it was changed by ImGui
SyncVisibilityConsoleVariable();
}
void BenMenu::DrawElement() {
for (auto& [reason, info] : disabledMap) {
info.active = info.evaluation(info);
}
menuThemeIndex = static_cast<ColorOption>(CVarGetInteger("gSettings.MenuTheme", 3));
windowHeight = ImGui::GetMainViewport()->WorkSize.y;
windowWidth = ImGui::GetMainViewport()->WorkSize.x;
auto windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
bool popout = CVarGetInteger("gSettings.Menu.Popout", 0) && allowPopout;
if (popout) {
windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoDocking;
}
if (popout != popped) {
if (popout) {
windowHeight = poppedSize.y;
windowWidth = poppedSize.x;
ImGui::SetNextWindowSize({ static_cast<float>(windowWidth), static_cast<float>(windowHeight) },
ImGuiCond_Always);
ImGui::SetNextWindowPos(poppedPos, ImGuiCond_Always);
} else if (popped) {
CVarSetFloat("gSettings.Menu.PoppedWidth", poppedSize.x);
CVarSetFloat("gSettings.Menu.PoppedHeight", poppedSize.y);
CVarSave();
}
}
popped = popout;
auto windowCond = ImGuiCond_Always;
if (!popout) {
ImGui::SetNextWindowSize({ static_cast<float>(windowWidth), static_cast<float>(windowHeight) }, windowCond);
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), windowCond, { 0.5f, 0.5f });
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
}
if (!ImGui::Begin("Main Menu", NULL, windowFlags | ImGuiWindowFlags_NoBringToFrontOnFocus)) {
if (!popout) {
ImGui::PopStyleVar();
}
ImGui::End();
return;
}
if (popped != popout) {
if (!popout) {
ImGui::PopStyleVar();
}
CVarSetInteger("gSettings.Menu.Popout", popped);
CVarSetFloat("gSettings.Menu.PoppedWidth", poppedSize.x);
CVarSetFloat("gSettings.Menu.PoppedHeight", poppedSize.y);
CVarSetFloat("gSettings.Menu.PoppedPos.x", poppedSize.x);
CVarSetFloat("gSettings.Menu.PoppedPos.y", poppedSize.y);
CVarSave();
ImGui::End();
return;
}
ImGui::PushFont(OTRGlobals::Instance->fontStandardLargest);
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStyle& style = ImGui::GetStyle();
windowHeight = window->WorkRect.GetHeight();
windowWidth = window->WorkRect.GetWidth();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 8.0f));
auto sectionCount = menuEntries.size();
const char* headerCvar = "gSettings.Menu.SelectedHeader";
uint8_t headerIndex = CVarGetInteger(headerCvar, 0);
ImVec2 pos = window->DC.CursorPos;
float centerX = pos.x + windowWidth / 2 - (style.ItemSpacing.x * (sectionCount + 1));
std::vector<ImVec2> headerSizes;
float headerWidth = 200.0f + style.ItemSpacing.x;
for (int i = 0; i < sectionCount; i++) {
ImVec2 size = ImGui::CalcTextSize(menuEntries.at(i).label.c_str());
headerSizes.push_back(size);
headerWidth += size.x + style.FramePadding.x * 2;
if (i + 1 < sectionCount) {
headerWidth += style.ItemSpacing.x;
}
}
ImVec2 menuSize = { std::fminf(1280, windowWidth), std::fminf(800, windowHeight) };
pos += window->WorkRect.GetSize() / 2 - menuSize / 2;
ImGui::SetNextWindowPos(pos);
ImGui::BeginChild("Menu Block", menuSize,
ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar);
std::vector<SidebarEntry> sidebar;
float headerHeight = headerSizes.at(0).y + style.FramePadding.y * 2;
ImVec2 buttonSize = ImGui::CalcTextSize(ICON_FA_TIMES_CIRCLE) + style.FramePadding * 2;
bool scrollbar = false;
if (headerWidth > menuSize.x - buttonSize.x * 3 - style.ItemSpacing.x * 3) {
headerHeight += style.ScrollbarSize;
scrollbar = true;
}
if (UIWidgets::Button(ICON_FA_TIMES_CIRCLE, { .size = UIWidgets::Sizes::Inline, .tooltip = "Close Menu (Esc)" })) {
ToggleVisibility();
}
ImGui::SameLine();
ImGui::SetNextWindowSizeConstraints({ 0, headerHeight }, { headerWidth, headerHeight });
ImVec2 headerSelSize = { menuSize.x - buttonSize.x * 3 - style.ItemSpacing.x * 3, headerHeight };
if (scrollbar) {
headerSelSize.y += style.ScrollbarSize;
}
bool autoFocus = CVarGetInteger("gSettings.SearchAutofocus", 0);
bool headerSearch = !CVarGetInteger("gSettings.SidebarSearch", 0);
ImGui::BeginChild("Header Selection", headerSelSize,
ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_HorizontalScrollbar);
for (int i = 0; i < sectionCount; i++) {
auto entry = menuEntries.at(i);
uint8_t nextIndex = i;
UIWidgets::PushStyleButton(menuTheme[menuThemeIndex]);
if (headerIndex != i) {
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
}
if (ModernMenuHeaderEntry(entry.label)) {
if (autoFocus) {
menuSearch.Clear();
}
CVarSetInteger(headerCvar, i);
CVarSave();
nextIndex = i;
}
if (headerIndex != i) {
ImGui::PopStyleColor();
}
UIWidgets::PopStyleButton();
if (headerIndex == i) {
sidebar = entry.sidebarEntries;
}
if (i + 1 < sectionCount) {
ImGui::SameLine();
}
if (nextIndex != i) {
headerIndex = nextIndex;
}
}
std::string menuSearchText = "";
if (headerSearch) {
ImGui::SameLine();
if (autoFocus && ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() &&
!ImGui::IsMouseClicked(0)) {
ImGui::SetKeyboardFocusHere(0);
}
ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0, 0, 0, 0 });
menuSearch.Draw("##search", 200.0f);
menuSearchText = menuSearch.InputBuf;
if (menuSearchText.length() < 1) {
ImGui::SameLine(headerWidth - 200.0f + style.ItemSpacing.x);
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "Search...");
}
ImGui::PopStyleColor();
}
ImGui::EndChild();
ImGui::SameLine(menuSize.x - (buttonSize.x * 2) - style.ItemSpacing.x);
if (UIWidgets::Button(ICON_FA_UNDO, { .color = UIWidgets::Colors::Red,
.size = UIWidgets::Sizes::Inline,
.tooltip = "Reset"
#ifdef __APPLE__
" (Command-R)"
#elif !defined(__SWITCH__) && !defined(__WIIU__)
" (Ctrl+R)"
#else
""
#endif
})) {
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
->Dispatch("reset");
}
ImGui::SameLine();
if (UIWidgets::Button(
ICON_FA_POWER_OFF,
{ .color = UIWidgets::Colors::Red, .size = UIWidgets::Sizes::Inline, .tooltip = "Quit 2S2H" })) {
if (!popped) {
ToggleVisibility();
}
Ship::Context::GetInstance()->GetWindow()->Close();
}
ImGui::PopStyleVar();
pos.y += headerHeight + style.ItemSpacing.y;
pos.x = centerX - menuSize.x / 2 + (style.ItemSpacing.x * (sectionCount + 1));
window->DrawList->AddRectFilled(pos, pos + ImVec2{ menuSize.x, 4 }, ImGui::GetColorU32({ 255, 255, 255, 255 }),
true, style.WindowRounding);
pos.y += style.ItemSpacing.y;
float sectionHeight = menuSize.y - headerHeight - 4 - style.ItemSpacing.y * 2;
float columnHeight = sectionHeight - style.ItemSpacing.y * 4;
ImGui::SetNextWindowPos(pos + style.ItemSpacing * 2);
float sidebarWidth = 200 - style.ItemSpacing.x;
const char* sidebarCvar = menuEntries.at(headerIndex).sidebarCvar;
uint8_t sectionIndex = CVarGetInteger(sidebarCvar, 0);
if (sectionIndex > sidebar.size() - 1)
sectionIndex = sidebar.size() - 1;
if (sectionIndex < 0)
sectionIndex = 0;
float sectionCenterX = pos.x + (sidebarWidth / 2);
float topY = pos.y;
ImGui::SetNextWindowSizeConstraints({ sidebarWidth, 0 }, { sidebarWidth, columnHeight });
ImGui::BeginChild((menuEntries.at(headerIndex).label + " Section").c_str(), { sidebarWidth, columnHeight * 3 },
ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize, ImGuiWindowFlags_NoTitleBar);
for (size_t i = 0; i < sidebar.size(); i++) {
auto sidebarEntry = sidebar.at(i);
uint8_t nextIndex = i;
UIWidgets::PushStyleButton(menuTheme[menuThemeIndex]);
if (sectionIndex != i) {
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
}
if (ModernMenuSidebarEntry(sidebarEntry.label)) {
if (autoFocus) {
menuSearch.Clear();
}
CVarSetInteger(sidebarCvar, i);
CVarSave();
nextIndex = i;
}
if (sectionIndex != i) {
ImGui::PopStyleColor();
}
UIWidgets::PopStyleButton();
if (nextIndex != i) {
sectionIndex = i;
}
}
ImGui::EndChild();
ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger);
pos = ImVec2{ sectionCenterX + (sidebarWidth / 2), topY } + style.ItemSpacing * 2;
window->DrawList->AddRectFilled(pos, pos + ImVec2{ 4, sectionHeight - style.FramePadding.y * 2 },
ImGui::GetColorU32({ 255, 255, 255, 255 }), true, style.WindowRounding);
pos.x += 4 + style.ItemSpacing.x;
ImGui::SetNextWindowPos(pos + style.ItemSpacing);
float sectionWidth = menuSize.x - sidebarWidth - 4 - style.ItemSpacing.x * 4;
std::string sectionMenuId = sidebar.at(sectionIndex).label + " Settings";
int columns = sidebar.at(sectionIndex).columnCount;
size_t columnFuncs = sidebar.at(sectionIndex).columnWidgets.size();
if (windowWidth < 800) {
columns = 1;
}
float columnWidth = (sectionWidth - style.ItemSpacing.x * columns) / columns;
bool useColumns = columns > 1;
if (!useColumns || (headerSearch && menuSearchText.length() > 0)) {
ImGui::SameLine();
ImGui::SetNextWindowSizeConstraints({ sectionWidth, 0 }, { sectionWidth, columnHeight });
ImGui::BeginChild(sectionMenuId.c_str(), { sectionWidth, windowHeight * 4 }, ImGuiChildFlags_AutoResizeY,
ImGuiWindowFlags_NoTitleBar);
}
if (headerSearch && menuSearchText.length() > 0) {
ImGui::BeginChild("Search Results");
int searchCount = 0;
for (auto& [menuLabel, menuSidebar, cvar] : menuEntries) {
for (auto& sidebar : menuSidebar) {
for (auto& widgets : sidebar.columnWidgets) {
int column = 1;
for (auto& info : widgets) {
if (info.widgetType == WIDGET_SEPARATOR || info.widgetType == WIDGET_SEPARATOR_TEXT ||
info.isHidden) {
continue;
}
std::string widgetStr = std::string(info.widgetName) + std::string(info.widgetTooltip);
std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower);
menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '),
menuSearchText.end());
std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower);
widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end());
if (widgetStr.find(menuSearchText) != std::string::npos) {
SearchMenuGetItem(info);
searchCount++;
ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::Colors::Gray);
std::string origin = fmt::format(" ({} -> {}, Clmn {})", menuLabel, sidebar.label, column);
ImGui::Text("%s", origin.c_str());
ImGui::PopStyleColor();
}
}
column++;
}
}
}
if (searchCount == 0) {
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("No results found").x) / 2);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f);
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "No results found");
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("Clear Search").x) / 2 - 10.0f);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f);
if (UIWidgets::Button("Clear Search", { .size = UIWidgets::Sizes::Inline })) {
menuSearch.Clear();
}
}
ImGui::EndChild();
} else {
for (int i = 0; i < columnFuncs; i++) {
std::string sectionId = fmt::format("{} Column {}", sectionMenuId, i);
if (useColumns) {
ImGui::SetNextWindowSizeConstraints({ columnWidth, 0 }, { columnWidth, columnHeight });
ImGui::BeginChild(sectionId.c_str(), { columnWidth, windowHeight * 4 }, ImGuiChildFlags_AutoResizeY,
ImGuiWindowFlags_NoTitleBar);
}
for (auto& entry : sidebar.at(sectionIndex).columnWidgets.at(i)) {
SearchMenuGetItem(entry);
}
if (useColumns) {
ImGui::EndChild();
}
if (i < columns - 1) {
ImGui::SameLine();
}
}
}
if (!useColumns || menuSearchText.length() > 0) {
ImGui::EndChild();
}
ImGui::PopFont();
ImGui::PopFont();
if (!popout) {
ImGui::PopStyleVar();
}
ImGui::EndChild();
if (popout) {
poppedSize = ImGui::GetWindowSize();
poppedPos = ImGui::GetWindowPos();
}
ImGui::End();
}
} // namespace BenGui

31
mm/2s2h/BenGui/Menu.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include <libultraship/libultraship.h>
#include "UIWidgets.hpp"
namespace BenGui {
class BenMenu : public Ship::GuiWindow {
public:
using Ship::GuiWindow::GuiWindow;
BenMenu(const std::string& consoleVariable, const std::string& name);
void InitElement() override;
void DrawElement() override;
void UpdateElement() override;
void Draw() override;
protected:
ImVec2 mOriginalSize;
std::string mName;
uint32_t mWindowFlags;
private:
bool allowPopout = true; // PortNote: should be set to false on small screen ports
bool popped;
ImVec2 poppedSize;
ImVec2 poppedPos;
float windowHeight;
float windowWidth;
};
} // namespace BenGui

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
#include "UIWidgets.hpp"
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui_internal.h>
#include <sstream>
#include <libultraship/libultraship.h>
#include <string>
#include <unordered_map>
@ -389,6 +390,46 @@ bool CVarSliderInt(const char* label, const char* cvarName, int32_t min, int32_t
return dirty;
}
void ClampFloat(float* value, float min, float max, float step) {
int ticks = 0;
float increment = 1.0f;
if (step < 1.0f) {
ticks++;
increment = 0.1f;
}
if (step < 0.1f) {
ticks++;
increment = 0.01f;
}
if (step < 0.01f) {
ticks++;
increment = 0.001f;
}
if (step < 0.001f) {
ticks++;
increment = 0.0001f;
}
if (step < 0.0001f) {
ticks++;
increment = 0.00001f;
}
if (step < 0.00001f) {
ticks++;
increment = 0.000001f;
}
int factor = 1 * std::pow(10, ticks);
if (*value < min) {
*value = min;
} else if (*value > max) {
*value = max;
} else {
*value = std::round(*value * factor) / factor;
std::stringstream ss;
ss << std::setprecision(ticks) << std::setiosflags(std::ios_base::fixed) << *value;
*value = std::stof(ss.str());
}
}
bool SliderFloat(const char* label, float* value, float min, float max, const FloatSliderOptions& options) {
bool dirty = false;
std::string invisibleLabelStr = "##" + std::string(label);
@ -414,8 +455,7 @@ bool SliderFloat(const char* label, float* value, float min, float max, const Fl
if (options.showButtons) {
if (Button("-", { .color = options.color, .size = Sizes::Inline }) && *value > min) {
*value -= options.step;
if (*value < min)
*value = min;
ClampFloat(value, min, max, options.step);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
dirty = true;
}
@ -427,6 +467,7 @@ bool SliderFloat(const char* label, float* value, float min, float max, const Fl
if (ImGui::SliderScalar(invisibleLabel, ImGuiDataType_Float, &valueToDisplay, &minToDisplay, &maxToDisplay,
options.format, options.flags)) {
*value = options.isPercentage ? valueToDisplay / 100.0f : valueToDisplay;
ClampFloat(value, min, max, options.step);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
dirty = true;
}
@ -435,8 +476,7 @@ bool SliderFloat(const char* label, float* value, float min, float max, const Fl
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (Button("+", { .color = options.color, .size = Sizes::Inline }) && *value < max) {
*value += options.step;
if (*value > max)
*value = max;
ClampFloat(value, min, max, options.step);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
dirty = true;
}

View File

@ -12,6 +12,8 @@
namespace UIWidgets {
using SectionFunc = void(*)();
struct TextFilters {
static int FilterNumbers(ImGuiInputTextCallbackData* data) {
if (data->EventChar < 256 && strchr("1234567890", (char)data->EventChar)) {
@ -97,6 +99,7 @@ namespace UIWidgets {
void PushStyleCheckbox(const ImVec4& color = Colors::Indigo);
void PopStyleCheckbox();
void RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash);
bool Checkbox(const char* label, bool* v, const CheckboxOptions& options = {});
bool CVarCheckbox(const char* label, const char* cvarName, const CheckboxOptions& options = {});

View File

@ -15,6 +15,7 @@
#include "z64animation.h"
#include "z64bgcheck.h"
#include <libultraship/libultra/gbi.h>
#include <Fonts.h>
#ifdef _WIN32
#include <Windows.h>
#else
@ -95,6 +96,8 @@ CrowdControl* CrowdControl::Instance;
#include "2s2h/resource/importer/BackgroundFactory.h"
#include "2s2h/resource/importer/TextureAnimationFactory.h"
#include "2s2h/resource/importer/KeyFrameFactory.h"
#include "window/gui/resource/Font.h"
#include "window/gui/resource/FontFactory.h"
OTRGlobals* OTRGlobals::Instance;
GameInteractor* GameInteractor::Instance;
@ -279,6 +282,14 @@ OTRGlobals::OTRGlobals() {
}
}
#endif
fontMono = CreateFontWithSize(16.0f, "fonts/Inconsolata-Regular.ttf");
fontMonoLarger = CreateFontWithSize(20.0f, "fonts/Inconsolata-Regular.ttf");
fontMonoLargest = CreateFontWithSize(24.0f, "fonts/Inconsolata-Regular.ttf");
fontStandard = CreateFontWithSize(16.0f, "fonts/Montserrat-Regular.ttf");
fontStandardLarger = CreateFontWithSize(20.0f, "fonts/Montserrat-Regular.ttf");
fontStandardLargest = CreateFontWithSize(24.0f, "fonts/Montserrat-Regular.ttf");
ImGui::GetIO().FontDefault = fontMono;
}
OTRGlobals::~OTRGlobals() {
@ -310,6 +321,37 @@ struct ExtensionEntry {
std::string ext;
};
ImFont* OTRGlobals::CreateFontWithSize(float size, std::string fontPath) {
auto mImGuiIo = &ImGui::GetIO();
ImFont* font;
if (fontPath == "") {
ImFontConfig fontCfg = ImFontConfig();
fontCfg.OversampleH = fontCfg.OversampleV = 1;
fontCfg.PixelSnapH = true;
fontCfg.SizePixels = size;
font = mImGuiIo->Fonts->AddFontDefault(&fontCfg);
} else {
auto initData = std::make_shared<Ship::ResourceInitData>();
initData->Format = RESOURCE_FORMAT_BINARY;
initData->Type = static_cast<uint32_t>(RESOURCE_TYPE_FONT);
initData->ResourceVersion = 0;
initData->Path = fontPath;
std::shared_ptr<Ship::Font> fontData = std::static_pointer_cast<Ship::Font>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(fontPath, false, initData));
font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontData->Data, fontData->DataSize, size);
}
// FontAwesome fonts need to have their sizes reduced by 2.0f/3.0f in order to align correctly
float iconFontSize = size * 2.0f / 3.0f;
static const ImWchar sIconsRanges[] = { ICON_MIN_FA, ICON_MAX_16_FA, 0 };
ImFontConfig iconsConfig;
iconsConfig.MergeMode = true;
iconsConfig.PixelSnapH = true;
iconsConfig.GlyphMinAdvanceX = iconFontSize;
mImGuiIo->Fonts->AddFontFromMemoryCompressedBase85TTF(fontawesome_compressed_data_base85, iconFontSize,
&iconsConfig, sIconsRanges);
return font;
}
extern "C" void OTRMessage_Init();
extern "C" void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
@ -1475,9 +1517,9 @@ extern "C" void OTRControllerCallback(uint8_t rumble) {
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetLED()->SetLEDColor(
GetColorForControllerLED());
static std::shared_ptr<Ship::InputEditorWindow> controllerConfigWindow = nullptr;
static std::shared_ptr<BenInputEditorWindow> controllerConfigWindow = nullptr;
if (controllerConfigWindow == nullptr) {
controllerConfigWindow = std::dynamic_pointer_cast<Ship::InputEditorWindow>(
controllerConfigWindow = std::dynamic_pointer_cast<BenInputEditorWindow>(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Input Editor"));
// TODO: Add SoH Controller Config window rumble testing to upstream LUS config window
// note: the current implementation may not be desired in LUS, as "true" rumble support

View File

@ -24,6 +24,13 @@ class OTRGlobals {
public:
static OTRGlobals* Instance;
ImFont* fontStandard;
ImFont* fontStandardLarger;
ImFont* fontStandardLargest;
ImFont* fontMono;
ImFont* fontMonoLarger;
ImFont* fontMonoLargest;
std::shared_ptr<Ship::Context> context;
OTRGlobals();
@ -35,6 +42,7 @@ class OTRGlobals {
std::shared_ptr<std::vector<std::string>> ListFiles(std::string path);
private:
ImFont* CreateFontWithSize(float size, std::string fontPath = "");
void CheckSaveFile(size_t sramSize) const;
bool hasMasterQuest;
bool hasOriginal;

View File

@ -177,12 +177,6 @@ void ActorViewerWindow::UpdateElement() {
}
void ActorViewerWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Actor Viewer", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
if (gPlayState != nullptr) {
if (lastSceneId != gPlayState->sceneId) {
ResetVariables();
@ -442,7 +436,6 @@ void ActorViewerWindow::DrawElement() {
} else {
ImGui::Text("Playstate needed for actors!");
}
ImGui::End();
}
void ActorViewerWindow::InitElement() {

View File

@ -42,12 +42,6 @@ static std::vector<Vtx> sphereVtx;
// Draws the ImGui window for the collision viewer
void CollisionViewerWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(390, 475), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Collision Viewer", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
UIWidgets::CVarCheckbox("Enabled", "gCollisionViewer.Enabled");
ImGui::SameLine();
@ -113,8 +107,6 @@ void CollisionViewerWindow::DrawElement() {
{ 192, 0, 192, 255 });
ImGui::EndDisabled();
ImGui::End();
}
// Calculates the normal for a triangle at the 3 specified points

View File

@ -1,6 +1,8 @@
#ifndef DEVELOPER_TOOLS_H
#define DEVELOPER_TOOLS_H
#define WARP_POINT_CVAR "gDeveloperTools.WarpPoint."
enum DebugSaveInfo {
DEBUG_SAVE_INFO_NONE,
DEBUG_SAVE_INFO_VANILLA_DEBUG,

View File

@ -259,12 +259,6 @@ void RegisterEventLogHooks() {
}
void EventLogWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Event Log", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
if (UIWidgets::CVarCheckbox("Enable", "gEventLog.Enabled")) {
RegisterEventLogHooks();
}
@ -384,8 +378,6 @@ void EventLogWindow::DrawElement() {
ImGui::EndTable();
}
ImGui::End();
}
void EventLogWindow::InitElement() {

View File

@ -1949,12 +1949,6 @@ void DrawFlagsTab() {
}
void SaveEditorWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(480, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Save Editor", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
if (ImGui::BeginTabBar("SaveContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("General")) {
DrawGeneralTab();
@ -1998,8 +1992,6 @@ void SaveEditorWindow::DrawElement() {
ImGui::EndTabBar();
}
ImGui::End();
}
const char* textureLoad[8] = { gDungeonStrayFairyWoodfallIconTex,

View File

@ -2,6 +2,7 @@
#include "2s2h/BenGui/UIWidgets.hpp"
#include "window/gui/IconsFontAwesome4.h"
#include "2s2h/Enhancements/GameInteractor/GameInteractor.h"
#include "2s2h/DeveloperTools/DeveloperTools.h"
extern "C" {
#include "z64.h"
@ -13,8 +14,6 @@ extern SaveContext gSaveContext;
extern GameState* gGameState;
}
#define CV "gDeveloperTools.WarpPoint."
// 2S2H Added columns to scene table: entranceSceneId, betterMapSelectIndex, humanName
#define DEFINE_SCENE(_name, enumValue, _textId, _drawConfig, _restrictionFlags, _persistentCycleFlags, \
_entranceSceneId, _betterMapSelectIndex, humanName) \
@ -29,8 +28,9 @@ std::unordered_map<s16, const char*> warpPointSceneList = {
#undef DEFINE_SCENE_UNSET
void Warp() {
Vec3f pos = { CVarGetFloat(CV "X", 0.0f), CVarGetFloat(CV "Y", 0.0f), CVarGetFloat(CV "Z", 0.0f) };
s32 entrance = CVarGetInteger(CV "Entrance", ENTRANCE(SOUTH_CLOCK_TOWN, 0));
Vec3f pos = { CVarGetFloat(WARP_POINT_CVAR "X", 0.0f), CVarGetFloat(WARP_POINT_CVAR "Y", 0.0f),
CVarGetFloat(WARP_POINT_CVAR "Z", 0.0f) };
s32 entrance = CVarGetInteger(WARP_POINT_CVAR "Entrance", ENTRANCE(SOUTH_CLOCK_TOWN, 0));
if (gPlayState == NULL) {
// If gPlayState is NULL, it means the the user opted into BootToWarpPoint and the game is starting up. This is
@ -47,7 +47,7 @@ void Warp() {
gSaveContext.save.playerForm = PLAYER_FORM_HUMAN;
gSaveContext.save.linkAge = 0;
gSaveContext.fileNum = 0xFF;
MapSelect_LoadGame((MapSelectState*)gGameState, CVarGetInteger(CV "Entrance", 0), 0);
MapSelect_LoadGame((MapSelectState*)gGameState, CVarGetInteger(WARP_POINT_CVAR "Entrance", 0), 0);
} else {
// The else case, and the rest of this function is primarly relevant code copied from Play_SetRespawnData and
// func_80169EFC, minus the parts that copy scene flags to scene we are warping to (this is obviously
@ -57,9 +57,9 @@ void Warp() {
gPlayState->transitionType = TRANS_TYPE_INSTANT;
}
gSaveContext.respawn[RESPAWN_MODE_DOWN].entrance = Entrance_Create(entrance >> 9, 0, entrance & 0xF);
gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = CVarGetInteger(CV "Room", 0);
gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = CVarGetInteger(WARP_POINT_CVAR "Room", 0);
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = pos;
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = CVarGetFloat(CV "Rotation", 0.0f);
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = CVarGetFloat(WARP_POINT_CVAR "Rotation", 0.0f);
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = PLAYER_PARAMS(0xFF, PLAYER_INITMODE_D);
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
gSaveContext.respawnFlag = -8;
@ -67,8 +67,8 @@ void Warp() {
void RegisterWarpPoint() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnConsoleLogoUpdate>([]() {
if (!CVarGetInteger("gEnhancements.Cutscenes.SkipToFileSelect", 0) && CVarGetInteger(CV "BootToWarpPoint", 0) &&
CVarGetInteger(CV "Saved", 0)) {
if (!CVarGetInteger("gEnhancements.Cutscenes.SkipToFileSelect", 0) &&
CVarGetInteger(WARP_POINT_CVAR "BootToWarpPoint", 0) && CVarGetInteger(WARP_POINT_CVAR "Saved", 0)) {
// Normally called on console logo screen
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.ambienceId = AMBIENCE_ID_DISABLED;
@ -85,28 +85,29 @@ void RenderWarpPointSection() {
if (UIWidgets::Button("Set Warp Point")) {
Player* player = GET_PLAYER(gPlayState);
CVarSetInteger(CV "Entrance", gSaveContext.save.entrance);
CVarSetInteger(CV "Room", gPlayState->roomCtx.curRoom.num);
CVarSetFloat(CV "X", player->actor.world.pos.x);
CVarSetFloat(CV "Y", player->actor.world.pos.y);
CVarSetFloat(CV "Z", player->actor.world.pos.z);
CVarSetFloat(CV "Rotation", player->actor.shape.rot.y);
CVarSetInteger(CV "Saved", 1);
CVarSetInteger(WARP_POINT_CVAR "Entrance", gSaveContext.save.entrance);
CVarSetInteger(WARP_POINT_CVAR "Room", gPlayState->roomCtx.curRoom.num);
CVarSetFloat(WARP_POINT_CVAR "X", player->actor.world.pos.x);
CVarSetFloat(WARP_POINT_CVAR "Y", player->actor.world.pos.y);
CVarSetFloat(WARP_POINT_CVAR "Z", player->actor.world.pos.z);
CVarSetFloat(WARP_POINT_CVAR "Rotation", player->actor.shape.rot.y);
CVarSetInteger(WARP_POINT_CVAR "Saved", 1);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
if (CVarGetInteger(CV "Saved", 0)) {
u32 sceneId = Entrance_GetSceneIdAbsolute(CVarGetInteger(CV "Entrance", ENTRANCE(SOUTH_CLOCK_TOWN, 0)));
if (CVarGetInteger(WARP_POINT_CVAR "Saved", 0)) {
u32 sceneId =
Entrance_GetSceneIdAbsolute(CVarGetInteger(WARP_POINT_CVAR "Entrance", ENTRANCE(SOUTH_CLOCK_TOWN, 0)));
ImGui::AlignTextToFramePadding();
ImGui::Text("%s Room %d", warpPointSceneList[sceneId], CVarGetInteger(CV "Room", 0));
ImGui::Text("%s Room %d", warpPointSceneList[sceneId], CVarGetInteger(WARP_POINT_CVAR "Room", 0));
ImGui::SameLine();
if (UIWidgets::Button(ICON_FA_TIMES, { .size = UIWidgets::Sizes::Inline })) {
CVarClear(CV "Entrance");
CVarClear(CV "Room");
CVarClear(CV "X");
CVarClear(CV "Y");
CVarClear(CV "Z");
CVarClear(CV "Rotation");
CVarClear(CV "Saved");
CVarClear(WARP_POINT_CVAR "Entrance");
CVarClear(WARP_POINT_CVAR "Room");
CVarClear(WARP_POINT_CVAR "X");
CVarClear(WARP_POINT_CVAR "Y");
CVarClear(WARP_POINT_CVAR "Z");
CVarClear(WARP_POINT_CVAR "Rotation");
CVarClear(WARP_POINT_CVAR "Saved");
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();

Binary file not shown.

Binary file not shown.