mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cadb5923d | ||
|
|
f51b428de4 | ||
|
|
7fb49b5e01 | ||
|
|
5a735395da | ||
|
|
dda4e4b5c9 | ||
|
|
6d76ce9f5e | ||
|
|
e0ed28543b | ||
|
|
1afe496fed | ||
|
|
31685557d2 | ||
|
|
cf92349436 | ||
|
|
8a74695a74 | ||
|
|
ebb9e3fc8e | ||
|
|
01b127b7f3 | ||
|
|
422839dea4 | ||
|
|
a2e93687f6 | ||
|
|
fab4340461 | ||
|
|
b7a607b765 | ||
|
|
4669337a3f | ||
|
|
7b11b129f7 | ||
|
|
b18eb6b649 | ||
|
|
0879154432 | ||
|
|
f1698ae721 | ||
|
|
ad50070aba | ||
|
|
449a2ebc70 | ||
|
|
be70a5a123 | ||
|
|
d1bbba626d | ||
|
|
2141922ee3 | ||
|
|
c2ec2f2cc3 | ||
|
|
207df24ffd | ||
|
|
0966633d2a | ||
|
|
50bc007d46 | ||
|
|
941b48b802 | ||
|
|
cbc89b8af4 | ||
|
|
9cd2f6e784 | ||
|
|
64ebfa222e | ||
|
|
0129959d7b | ||
|
|
3ebfdb3928 | ||
|
|
bb386e25a0 | ||
|
|
4d3c39224c | ||
|
|
0b16bced84 | ||
|
|
b7d7a2d9bf | ||
|
|
fa702ed90c | ||
|
|
7e10b1315e | ||
|
|
cae9c27c62 | ||
|
|
cd4ee56d48 | ||
|
|
790d36bfbc | ||
|
|
da793a5bf2 | ||
|
|
69edc89292 | ||
|
|
a93f011253 | ||
|
|
4c670ad342 | ||
|
|
d9d6dbdf51 | ||
|
|
da04b7f859 | ||
|
|
8e0b482b23 | ||
|
|
d3933591b5 | ||
|
|
f31674a12e | ||
|
|
c474a82a94 | ||
|
|
71c2c94ece | ||
|
|
75bc685360 | ||
|
|
200aaf7be8 | ||
|
|
f33f994adc | ||
|
|
b1eea9ca76 | ||
|
|
1475e6af7b | ||
|
|
25887952c9 | ||
|
|
137ca0de12 | ||
|
|
a5059beaeb | ||
|
|
4d1ddff798 | ||
|
|
bbfa903a99 | ||
|
|
6ff3be97de | ||
|
|
466a716222 | ||
|
|
185e761f78 | ||
|
|
ea8809ddd0 | ||
|
|
13035d72a4 | ||
|
|
136a928883 | ||
|
|
0c2a51c9f4 | ||
|
|
d74699740e | ||
|
|
542feb038e | ||
|
|
b0ca99f18c | ||
|
|
53faf37dc1 | ||
|
|
63ffddb67b | ||
|
|
4a57bdbc5f | ||
|
|
0ec23b34ba | ||
|
|
d0caa0f78c | ||
|
|
51af06463f | ||
|
|
57cb5d2b51 | ||
|
|
24d8d47ab2 | ||
|
|
aa1b0108f4 | ||
|
|
2e4710c6c2 | ||
|
|
3ef3e7a239 | ||
|
|
a38b9daa6d | ||
|
|
120562952c | ||
|
|
fc309f5eaa | ||
|
|
e87d7c6954 | ||
|
|
8b2b12dbe8 | ||
|
|
e60ca15ae6 | ||
|
|
6fd7fc3a9d | ||
|
|
51a6d9d926 | ||
|
|
5e17828cc4 | ||
|
|
d2a11f1476 | ||
|
|
f8f00e6d9b | ||
|
|
2d8bc175fe | ||
|
|
5de6a9ac8f | ||
|
|
03a597d44c | ||
|
|
139a240ed3 | ||
|
|
26321c9a17 | ||
|
|
888b8fe24a | ||
|
|
53e76c5aeb | ||
|
|
04e5ac449d | ||
|
|
e484e0ba82 | ||
|
|
291973fffe | ||
|
|
01ae001de5 | ||
|
|
711b02be55 | ||
|
|
513e89c073 |
@@ -192,15 +192,17 @@ jobs:
|
||||
key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-14-macports-
|
||||
# Updated PATH applies to the next step and onwards
|
||||
- name: Install MacPorts (if necessary)
|
||||
run: |
|
||||
if [ command -v port &>/dev/null ]; then
|
||||
if command -v /opt/local/bin/port 2>&1 >/dev/null; then
|
||||
echo "MacPorts already installed"
|
||||
else
|
||||
echo "Installing MacPorts"
|
||||
wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg
|
||||
sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target /
|
||||
fi
|
||||
echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
|
||||
echo "/opt/local/bin:/opt/local/sbin" >> "$GITHUB_PATH"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew uninstall --ignore-dependencies libpng
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||
steps:
|
||||
- id: 'pr-number'
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
@@ -20,8 +20,9 @@ jobs:
|
||||
const pullHeadSHA = '${{github.event.workflow_run.head_sha}}';
|
||||
const pullUserId = ${{github.event.sender.id}};
|
||||
const prNumber = await (async () => {
|
||||
const pulls = await github.rest.pulls.list({owner, repo});
|
||||
for await (const {data} of github.paginate.iterator(pulls)) {
|
||||
for await (const { data } of github.paginate.iterator(
|
||||
github.rest.pulls.list, { owner, repo }
|
||||
)) {
|
||||
for (const pull of data) {
|
||||
if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) {
|
||||
return pull.number;
|
||||
@@ -36,7 +37,7 @@ jobs:
|
||||
|
||||
return prNumber;
|
||||
- id: 'artifacts-text'
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
@@ -54,7 +55,7 @@ jobs:
|
||||
return acc;
|
||||
}, '### Build Artifacts');
|
||||
- id: 'add-to-pr'
|
||||
uses: garrettjoecox/pr-section@3.1.0
|
||||
uses: garrettjoecox/pr-section@4.0.0
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
pr-number: ${{ steps.pr-number.outputs.result }}
|
||||
|
||||
@@ -16,8 +16,8 @@ android {
|
||||
}
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 31
|
||||
versionCode 3
|
||||
versionName "1.0.2"
|
||||
versionCode 4
|
||||
versionName "1.1.1"
|
||||
externalNativeBuild {
|
||||
//ndkBuild {
|
||||
// arguments "APP_PLATFORM=android-23"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.dishii.mm"
|
||||
android:versionCode="3"
|
||||
android:versionName="1.0.2"
|
||||
android:versionCode="4"
|
||||
android:versionName="1.1.1"
|
||||
android:installLocation="auto">
|
||||
|
||||
<!-- OpenGL ES 3.0 -->
|
||||
|
||||
+3
-3
@@ -5,10 +5,10 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
project(2s2h VERSION 1.0.2 LANGUAGES C CXX)
|
||||
project(2s2h VERSION 1.1.1 LANGUAGES C CXX)
|
||||
include(CMake/2ship-cvars.cmake)
|
||||
include(CMake/lus-cvars.cmake)
|
||||
set(PROJECT_BUILD_NAME "Rika Charlie" CACHE STRING "" FORCE)
|
||||
set(PROJECT_BUILD_NAME "Satoko Bravo" CACHE STRING "" FORCE)
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE)
|
||||
|
||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT 2ship)
|
||||
@@ -32,7 +32,7 @@ endif()
|
||||
set(GFX_DEBUG_DISASSEMBLER ON)
|
||||
|
||||
# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd)
|
||||
set(USE_F3DEX2 ON)
|
||||
set(GBI_UCODE F3DEX_GBI_2)
|
||||
|
||||
################################################################################
|
||||
# Set target arch type if empty. Visual studio solution generator provides it.
|
||||
|
||||
+1
-1
Submodule OTRExporter updated: e8f93ff692...1cbb1b65dd
@@ -0,0 +1,239 @@
|
||||
# Building 2 Ship 2 Harkinian
|
||||
|
||||
## Windows
|
||||
|
||||
Requires:
|
||||
* At least 8GB of RAM (machines with 4GB have seen complier failures)
|
||||
* Visual Studio 2022 Community Edition with the C++ feature set
|
||||
* One of the Windows SDKs that comes with Visual Studio, for example the current Windows 10 version 10.0.19041.0
|
||||
* The `MSVC v143 - VS 2022 C++ build tools` component of Visual Studio
|
||||
* Python 3 (can be installed manually or as part of Visual Studio)
|
||||
* Git (can be installed manually or as part of Visual Studio)
|
||||
* Cmake (can be installed via chocolatey or manually)
|
||||
|
||||
During installation, check the "Desktop development with C++" feature set:
|
||||
|
||||

|
||||
Doing so should also check one of the Windows SDKs by default. Then, in the installation details in the right-hand column, make sure you also check the v143 toolset. This is often done by default.
|
||||
|
||||
It is recommended that you install Python and Git standalone, the install process in VS Installer has given some issues in the past.
|
||||
|
||||
1. Clone the 2 Ship 2 Harkinian repository
|
||||
|
||||
_Note: Be sure to either clone with the ``--recursive`` flag or do ``git submodule update --init`` after cloning to pull in the libultraship submodule!_
|
||||
|
||||
2. After setup and initial build, use the built-in O2R extraction to make your mm.o2r file.
|
||||
|
||||
_Note: Instructions assume using powershell_
|
||||
```powershell
|
||||
# Navigate to the 2ship2harkinian repo within powershell. ie: cd "C:\yourpath\2ship2harkinian"
|
||||
cd 2ship2harkinian
|
||||
|
||||
# Setup cmake project
|
||||
# Add `-DCMAKE_BUILD_TYPE:STRING=Release` if you're packaging
|
||||
& 'C:\Program Files\CMake\bin\cmake' -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64
|
||||
|
||||
# Generate 2ship.o2r
|
||||
& 'C:\Program Files\CMake\bin\cmake.exe' --build .\build\x64 --target Generate2ShipOtr
|
||||
|
||||
# Compile project
|
||||
# Add `--config Release` if you're packaging
|
||||
& 'C:\Program Files\CMake\bin\cmake.exe' --build .\build\x64
|
||||
|
||||
# Now you can run the executable in .\build\x64 or run in Visual Studio
|
||||
```
|
||||
|
||||
### Developing 2S2H
|
||||
With the cmake build system you have two options for working on the project:
|
||||
|
||||
#### Visual Studio
|
||||
To develop using Visual Studio you only need to use cmake to generate the solution file:
|
||||
```powershell
|
||||
# Generates 2s2h.sln at `build/x64` for Visual Studio 2022
|
||||
& 'C:\Program Files\CMake\bin\cmake' -S . -B "build/x64" -G "Visual Studio 17 2022" -T v143 -A x64
|
||||
```
|
||||
|
||||
#### Visual Studio Code or another editor
|
||||
To develop using Visual Studio Code or another editor you only need to open the repository in it.
|
||||
To build you'll need to follow the instructions from the building section.
|
||||
|
||||
_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
|
||||
|
||||
_Experimental: You can also use another build system entirely rather than MSVC like [Ninja](https://ninja-build.org/) for possibly better performance._
|
||||
|
||||
|
||||
### Generating the distributable
|
||||
After compiling the project you can generate the distributable by running:
|
||||
```powershell
|
||||
# Go to build folder
|
||||
cd "build/x64"
|
||||
# Generate
|
||||
& 'C:\Program Files\CMake\bin\cpack.exe' -G ZIP
|
||||
```
|
||||
|
||||
### Additional CMake Targets
|
||||
#### Clean
|
||||
```powershell
|
||||
# If you need to clean the project you can run
|
||||
C:\Program Files\CMake\bin\cmake.exe --build build-cmake --target clean
|
||||
```
|
||||
|
||||
#### Regenerate Asset Headers
|
||||
```powershell
|
||||
# If you need to regenerate the asset headers to check them into source
|
||||
C:\Program Files\CMake\bin\cmake.exe --build build-cmake --target ExtractAssetHeaders
|
||||
```
|
||||
|
||||
## Linux
|
||||
### Install dependencies
|
||||
#### Debian/Ubuntu
|
||||
```sh
|
||||
# using gcc
|
||||
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
|
||||
|
||||
# or using clang
|
||||
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev
|
||||
```
|
||||
#### Arch
|
||||
```sh
|
||||
# using gcc
|
||||
pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
|
||||
|
||||
# or using clang
|
||||
pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost
|
||||
```
|
||||
#### Fedora
|
||||
```sh
|
||||
# using gcc
|
||||
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel
|
||||
|
||||
# or using clang
|
||||
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel
|
||||
```
|
||||
#### openSUSE
|
||||
```sh
|
||||
# using gcc
|
||||
zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel
|
||||
|
||||
# or using clang
|
||||
zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
|
||||
|
||||
```bash
|
||||
# Clone the repo and enter the directory
|
||||
git clone https://github.com/HarbourMasters/2ship2harkinian.git
|
||||
cd 2ship2harkinian
|
||||
|
||||
# Clone the submodules
|
||||
git submodule update --init
|
||||
|
||||
# Generate Ninja project
|
||||
# Add `-DCMAKE_BUILD_TYPE:STRING=Release` if you're packaging
|
||||
# Add `-DPython3_EXECUTABLE=$(which python3)` if you are using non-standard Python installations such as PyEnv
|
||||
cmake -H. -Bbuild-cmake -GNinja
|
||||
|
||||
# Generate 2ship.o2r
|
||||
cmake --build build-cmake --target Generate2ShipOtr
|
||||
|
||||
# Compile the project
|
||||
# Add `--config Release` if you're packaging
|
||||
cmake --build build-cmake
|
||||
|
||||
# Now you can run the executable in ./build-cmake/mm/2s2h.elf
|
||||
# To develop the project open the repository in VSCode (or your preferred editor)
|
||||
```
|
||||
|
||||
### Generate a distributable
|
||||
After compiling the project you can generate a distributable by running of the following:
|
||||
```bash
|
||||
# Go to build folder
|
||||
cd build-cmake
|
||||
# Generate
|
||||
cpack -G DEB
|
||||
cpack -G ZIP
|
||||
cpack -G External (creates appimage)
|
||||
```
|
||||
|
||||
### Additional CMake Targets
|
||||
#### Clean
|
||||
```bash
|
||||
# If you need to clean the project you can run
|
||||
cmake --build build-cmake --target clean
|
||||
```
|
||||
|
||||
#### Regenerate Asset Headers
|
||||
```bash
|
||||
# If you need to regenerate the asset headers to check them into source
|
||||
cmake --build build-cmake --target ExtractAssetHeaders
|
||||
```
|
||||
|
||||
## macOS
|
||||
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake, nlohmann-json, libzip` (can be installed via homebrew, macports, etc)
|
||||
|
||||
**Important: For maximum performance make sure you have ninja build tools installed!**
|
||||
|
||||
_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
git clone https://github.com/HarbourMasters/2ship2harkinian.git
|
||||
cd 2ship2harkinian
|
||||
# Clone the submodule libultraship
|
||||
git submodule update --init
|
||||
|
||||
# Generate Ninja project
|
||||
# Add `-DCMAKE_BUILD_TYPE:STRING=Release` if you're packaging
|
||||
cmake -H. -Bbuild-cmake -GNinja
|
||||
|
||||
# Generate 2ship.o2r
|
||||
cmake --build build-cmake --target Generate2ShipOtr
|
||||
|
||||
# Compile the project
|
||||
# Add `--config Release` if you're packaging
|
||||
cmake --build build-cmake
|
||||
|
||||
# Now you can run the executable file:
|
||||
./build-cmake/mm/2s2h-macos
|
||||
# To develop the project open the repository in VSCode (or your preferred editor)
|
||||
```
|
||||
|
||||
### Generating a distributable
|
||||
After compiling the project you can generate a distributable by running of the following:
|
||||
```bash
|
||||
# Go to build folder
|
||||
cd build-cmake
|
||||
# Generate
|
||||
cpack
|
||||
```
|
||||
|
||||
### Additional CMake Targets
|
||||
#### Clean
|
||||
```bash
|
||||
# If you need to clean the project you can run
|
||||
cmake --build build-cmake --target clean
|
||||
```
|
||||
|
||||
#### Regenerate Asset Headers
|
||||
```bash
|
||||
# If you need to regenerate the asset headers to check them into source
|
||||
cmake --build build-cmake --target ExtractAssetHeaders
|
||||
```
|
||||
|
||||
# Compatible Roms
|
||||
See [`supportedHashes.json`](supportedHashes.json)
|
||||
|
||||
## Getting CI to work on your fork
|
||||
|
||||
The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This steps extracts assets from the game file and generates an "assets" folder in `mm/`.
|
||||
|
||||
To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. Make sure to add the 'asset-builder' tag to your newly added runner to assign it to run this step. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux).
|
||||
|
||||
### Runner on Windows
|
||||
You'll have to enable the ability to run unsigned scripts through PowerShell. To do this, open Powershell as administrator and run `set-executionpolicy remotesigned`. Most dependencies get installed as part of the CI process. You will also need to separately install 7z and add it to the PATH so `7z` can be run as a command. [Chocolatey](https://chocolatey.org/) or other package managers can be used to install it easily.
|
||||
|
||||
### Runner on UNIX systems
|
||||
If you're on macOS or Linux take a look at `macports-deps.txt` or `apt-deps.txt` to see the dependencies expected to be on your machine.
|
||||
@@ -7,4 +7,4 @@
|
||||
"name": "NTSC-U GC",
|
||||
"sha1": "9743aa026e9269b339eb0e3044cd5830a440c1fd"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
+1
-1
Submodule libultraship updated: e2f0264218...7a303818b3
+42
-14
@@ -8,6 +8,7 @@
|
||||
#include <Fast3D/gfx_pc.h>
|
||||
#include "UIWidgets.hpp"
|
||||
#include "HudEditor.h"
|
||||
#include "Notification.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "graphic/Fast3D/gfx_metal.h"
|
||||
@@ -20,6 +21,9 @@
|
||||
#include "include/global.h"
|
||||
#include "include/z64audio.h"
|
||||
|
||||
#include "Enhancements/Trackers/ItemTracker.h"
|
||||
#include "Enhancements/Trackers/ItemTrackerSettings.h"
|
||||
|
||||
namespace BenGui {
|
||||
// MARK: - Delegates
|
||||
|
||||
@@ -27,7 +31,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 +38,11 @@ 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;
|
||||
std::shared_ptr<Notification::Window> mNotificationWindow;
|
||||
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||
|
||||
void SetupGuiElements() {
|
||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||
@@ -47,7 +55,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__) || defined(__ANDROID__)
|
||||
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
|
||||
#else
|
||||
@@ -55,6 +63,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,43 +76,60 @@ 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);
|
||||
|
||||
mItemTrackerWindow = std::make_shared<ItemTrackerWindow>("gWindows.ItemTracker", "Item Tracker");
|
||||
gui->AddGuiWindow(mItemTrackerWindow);
|
||||
|
||||
mItemTrackerSettingsWindow = std::make_shared<ItemTrackerSettingsWindow>("gWindows.ItemTrackerSettings",
|
||||
"Item Tracker Settings", ImVec2(800, 400));
|
||||
gui->AddGuiWindow(mItemTrackerSettingsWindow);
|
||||
gui->SetPadBtnTogglesMenu();
|
||||
|
||||
mNotificationWindow = std::make_shared<Notification::Window>("gWindows.Notifications", "Notifications Window");
|
||||
gui->AddGuiWindow(mNotificationWindow);
|
||||
mNotificationWindow->Show();
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||
|
||||
gui->RemoveAllGuiWindows();
|
||||
mBenMenuBar = nullptr;
|
||||
mBenMenu = nullptr;
|
||||
mStatsWindow = nullptr;
|
||||
mConsoleWindow = nullptr;
|
||||
mInputEditorWindow = nullptr;
|
||||
mBenInputEditorWindow = nullptr;
|
||||
mGfxDebuggerWindow = nullptr;
|
||||
mCollisionViewerWindow = nullptr;
|
||||
mEventLogWindow = nullptr;
|
||||
|
||||
mNotificationWindow = nullptr;
|
||||
mSaveEditorWindow = nullptr;
|
||||
mHudEditorWindow = nullptr;
|
||||
mActorViewerWindow = nullptr;
|
||||
mItemTrackerWindow = nullptr;
|
||||
mItemTrackerSettingsWindow = nullptr;
|
||||
}
|
||||
} // namespace BenGui
|
||||
|
||||
@@ -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
@@ -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();
|
||||
};
|
||||
+262
-28
@@ -8,12 +8,13 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include "2s2h/Enhancements/Enhancements.h"
|
||||
#include "2s2h/Enhancements/Graphics/MotionBlur.h"
|
||||
#include "2s2h/Enhancements/Graphics/PlayAsKafei.h"
|
||||
#include "2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h"
|
||||
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
||||
#include "2s2h/DeveloperTools/WarpPoint.h"
|
||||
#include "HudEditor.h"
|
||||
|
||||
#include "2s2h/Enhancements/Trackers/ItemTracker.h"
|
||||
#include "2s2h/Enhancements/Trackers/ItemTrackerSettings.h"
|
||||
|
||||
extern "C" {
|
||||
#include "z64.h"
|
||||
#include "functions.h"
|
||||
@@ -38,14 +39,14 @@ static const std::unordered_map<Ship::AudioBackend, const char*> audioBackendsMa
|
||||
};
|
||||
|
||||
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" }
|
||||
{ Ship::WindowBackend::FAST3D_DXGI_DX11, "DirectX" },
|
||||
{ Ship::WindowBackend::FAST3D_SDL_OPENGL, "OpenGL" },
|
||||
{ Ship::WindowBackend::FAST3D_SDL_METAL, "Metal" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> clockTypeOptions = {
|
||||
{ CLOCK_TYPE_ORIGINAL, "Original" },
|
||||
{ CLOCK_TYPE_3DS, "MM3D style" },
|
||||
{ CLOCK_TYPE_TEXT_BASED, "Text only" },
|
||||
};
|
||||
|
||||
@@ -55,6 +56,18 @@ static const std::unordered_map<int32_t, const char*> alwaysWinDoggyraceOptions
|
||||
{ ALWAYS_WIN_DOGGY_RACE_ALWAYS, "Always" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> cremiaRewardOptions = {
|
||||
{ CREMIA_REWARD_RANDOM, "Vanilla" },
|
||||
{ CREMIA_REWARD_ALWAYS_HUG, "Hug" },
|
||||
{ CREMIA_REWARD_ALWAYS_RUPEE, "Rupee" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> timeStopOptions = {
|
||||
{ TIME_STOP_OFF, "Off" },
|
||||
{ TIME_STOP_TEMPLES, "Temples" },
|
||||
{ TIME_STOP_TEMPLES_DUNGEONS, "Temples + Mini Dungeons" },
|
||||
};
|
||||
|
||||
namespace BenGui {
|
||||
std::shared_ptr<std::vector<Ship::WindowBackend>> availableWindowBackends;
|
||||
std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
|
||||
@@ -63,7 +76,7 @@ Ship::WindowBackend configWindowBackend;
|
||||
void UpdateWindowBackendObjects() {
|
||||
Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
||||
int32_t configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
||||
if (configWindowBackendId != -1 && configWindowBackendId < static_cast<int>(Ship::WindowBackend::BACKEND_COUNT)) {
|
||||
if (Ship::Context::GetInstance()->GetWindow()->IsAvailableWindowBackend(configWindowBackendId)) {
|
||||
configWindowBackend = static_cast<Ship::WindowBackend>(configWindowBackendId);
|
||||
} else {
|
||||
configWindowBackend = runningWindowBackend;
|
||||
@@ -147,7 +160,7 @@ void DrawBenMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
extern std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
||||
extern std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
|
||||
|
||||
void DrawSettingsMenu() {
|
||||
if (UIWidgets::BeginMenu("Settings")) {
|
||||
@@ -214,19 +227,21 @@ void DrawSettingsMenu() {
|
||||
{ // FPS Slider
|
||||
constexpr unsigned int minFps = 20;
|
||||
static unsigned int maxFps;
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() ==
|
||||
Ship::WindowBackend::FAST3D_DXGI_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;
|
||||
bool matchingRefreshRate = CVarGetInteger("gMatchRefreshRate", 0) &&
|
||||
Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() !=
|
||||
Ship::WindowBackend::FAST3D_DXGI_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) {
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() ==
|
||||
Ship::WindowBackend::FAST3D_DXGI_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 "
|
||||
@@ -238,7 +253,8 @@ void DrawSettingsMenu() {
|
||||
}
|
||||
} // END FPS Slider
|
||||
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() ==
|
||||
Ship::WindowBackend::FAST3D_DXGI_DX11) {
|
||||
// UIWidgets::Spacer(0);
|
||||
if (ImGui::Button("Match Refresh Rate")) {
|
||||
int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
||||
@@ -252,7 +268,8 @@ void DrawSettingsMenu() {
|
||||
}
|
||||
UIWidgets::Tooltip("Matches interpolation value to the current game's window refresh rate");
|
||||
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) {
|
||||
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() ==
|
||||
Ship::WindowBackend::FAST3D_DXGI_DX11) {
|
||||
UIWidgets::CVarSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off"
|
||||
: "Jitter fix: >= %d FPS",
|
||||
"gExtraLatencyThreshold", 0, 360, 80);
|
||||
@@ -302,8 +319,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__
|
||||
@@ -334,16 +351,60 @@ void DrawSettingsMenu() {
|
||||
}
|
||||
|
||||
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
||||
extern std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
extern std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||
|
||||
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." });
|
||||
"Fix Targeting Camera Snap", "gEnhancements.Camera.FixTargettingCameraSnap",
|
||||
{ .tooltip = "Fixes the camera snap that occurs when you are moving and press the targeting button." });
|
||||
|
||||
ImGui::SeparatorText("First Person");
|
||||
UIWidgets::CVarCheckbox("Disable Auto-Centering",
|
||||
"gEnhancements.Camera.FirstPerson.DisableFirstPersonAutoCenterView");
|
||||
UIWidgets::CVarCheckbox("Invert X Axis", "gEnhancements.Camera.FirstPerson.InvertX");
|
||||
UIWidgets::CVarCheckbox("Invert Y Axis", "gEnhancements.Camera.FirstPerson.InvertY",
|
||||
{ .defaultValue = true });
|
||||
UIWidgets::CVarSliderFloat("X Axis Sensitivity: %.0f%%", "gEnhancements.Camera.FirstPerson.SensitivityX",
|
||||
0.1f, 2.0f, 1.0f, { .isPercentage = true });
|
||||
UIWidgets::CVarSliderFloat("Y Axis Sensitivity: %.0f%%", "gEnhancements.Camera.FirstPerson.SensitivityY",
|
||||
0.1f, 2.0f, 1.0f, { .isPercentage = true });
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Gyro Aiming", "gEnhancements.Camera.FirstPerson.GyroEnabled",
|
||||
{ .tooltip = "Enables gyro aiming in first person mode. Requires a controller with gyro support, and "
|
||||
"for it to be mapped in the Controller Mapping menu" });
|
||||
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0)) {
|
||||
UIWidgets::CVarCheckbox("Invert Gyro X Axis", "gEnhancements.Camera.FirstPerson.GyroInvertX");
|
||||
UIWidgets::CVarCheckbox("Invert Gyro Y Axis", "gEnhancements.Camera.FirstPerson.GyroInvertY");
|
||||
UIWidgets::CVarSliderFloat("Gyro X Axis Sensitivity: %.0f%%",
|
||||
"gEnhancements.Camera.FirstPerson.GyroSensitivityX", 0.1f, 2.0f, 1.0f,
|
||||
{ .isPercentage = true });
|
||||
UIWidgets::CVarSliderFloat("Gyro Y Axis Sensitivity: %.0f%%",
|
||||
"gEnhancements.Camera.FirstPerson.GyroSensitivityY", 0.1f, 2.0f, 1.0f,
|
||||
{ .isPercentage = true });
|
||||
}
|
||||
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Right Stick Aiming", "gEnhancements.Camera.FirstPerson.RightStickEnabled",
|
||||
{ .tooltip = "Enables right stick aiming in first person mode. Requires the controller right stick to "
|
||||
"be mapped in the Controller Mapping menu" });
|
||||
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickEnabled", 0)) {
|
||||
UIWidgets::CVarCheckbox("Move with left stick while in first person",
|
||||
"gEnhancements.Camera.FirstPerson.MoveInFirstPerson");
|
||||
UIWidgets::CVarCheckbox("Invert Right Stick X Axis",
|
||||
"gEnhancements.Camera.FirstPerson.RightStickInvertX");
|
||||
UIWidgets::CVarCheckbox("Invert Right Stick Y Axis",
|
||||
"gEnhancements.Camera.FirstPerson.RightStickInvertY", { .defaultValue = true });
|
||||
UIWidgets::CVarSliderFloat("Right Stick X Axis Sensitivity: %.0f%%",
|
||||
"gEnhancements.Camera.FirstPerson.RightStickSensitivityX", 0.1f, 2.0f, 1.0f,
|
||||
{ .isPercentage = true });
|
||||
UIWidgets::CVarSliderFloat("Right Stick Y Axis Sensitivity: %.0f%%",
|
||||
"gEnhancements.Camera.FirstPerson.RightStickSensitivityY", 0.1f, 2.0f, 1.0f,
|
||||
{ .isPercentage = true });
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Free Look");
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
@@ -419,6 +480,12 @@ void DrawEnhancementsMenu() {
|
||||
{
|
||||
.tooltip = "When starting a game you will be taken straight to South Clock Town as Deku Link.",
|
||||
});
|
||||
if (CVarGetInteger("gEnhancements.Cutscenes.SkipIntroSequence", 0)) {
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Skip First Cycle", "gEnhancements.Cutscenes.SkipFirstCycle",
|
||||
{ .tooltip = "When starting a game you will be taken straight to South Clock Town as Human Link "
|
||||
"with Deku Mask, Ocarina, Song of Time, and Song of Healing." });
|
||||
}
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Skip Story Cutscenes", "gEnhancements.Cutscenes.SkipStoryCutscenes",
|
||||
{
|
||||
@@ -468,6 +535,17 @@ void DrawEnhancementsMenu() {
|
||||
{ .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." });
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Do not reset Time Speed", "gEnhancements.Cycle.DoNotResetTimeSpeed",
|
||||
{ .tooltip =
|
||||
"Playing the Song Of Time will not reset the current time speed set by Inverted Song of Time." });
|
||||
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
"Keep Express Mail", "gEnhancements.Cycle.KeepExpressMail",
|
||||
{ .tooltip = "Allows the player to keep the Express Mail in their inventory after delivering it "
|
||||
"the first time, so that both deliveries can be done within one cycle" })) {
|
||||
RegisterKeepExpressMail();
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255));
|
||||
ImGui::SeparatorText("Unstable");
|
||||
@@ -480,7 +558,12 @@ void DrawEnhancementsMenu() {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (UIWidgets::BeginMenu("Dialogues")) {
|
||||
if (UIWidgets::BeginMenu("Dialogue")) {
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Fast Bank Selection", "gEnhancements.Dialogue.FastBankSelection",
|
||||
{ .tooltip =
|
||||
"Pressing the Z or R buttons while the Deposit/Withdrawal Rupees dialogue is open will set "
|
||||
"the Rupees to Links current Rupees or 0 respectively." });
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Fast Text", "gEnhancements.Dialogue.FastText",
|
||||
{ .tooltip = "Speeds up text rendering, and enables holding of B progress to next message" });
|
||||
@@ -495,15 +578,49 @@ void DrawEnhancementsMenu() {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (UIWidgets::BeginMenu("Equipment")) {
|
||||
UIWidgets::CVarCheckbox("Fast Magic Arrow Equip Animation", "gEnhancements.Equipment.MagicArrowEquipSpeed",
|
||||
{ .tooltip = "Removes the animation for equipping Magic Arrows." });
|
||||
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Instant Fin Boomerangs Recall", "gEnhancements.PlayerActions.InstantRecall",
|
||||
{ .tooltip =
|
||||
"Pressing B will instantly recall the fin boomerang back to Zora Link after they are thrown." });
|
||||
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Two-Handed Sword Spin Attack", "gEnhancements.Equipment.TwoHandedSwordSpinAttack",
|
||||
{ .tooltip = "Enables magic spin attacks for the Fierce Deity Sword and Great Fairy's Sword." });
|
||||
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 Fierce Deity Z-Target movement",
|
||||
"gEnhancements.Fixes.FierceDeityZTargetMovement",
|
||||
{ .tooltip = "Fixes Fierce Deity movement being choppy when Z-targeting" });
|
||||
|
||||
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 });
|
||||
|
||||
UIWidgets::CVarCheckbox("Fix Text Control Characters", "gEnhancements.Fixes.ControlCharacters",
|
||||
{ .tooltip = "Fixes certain control characters not functioning properly "
|
||||
"depending on their position within the text." });
|
||||
|
||||
UIWidgets::CVarCheckbox("Fix Ikana Great Fairy Fountain Color", "gFixes.FixIkanaGreatFairyFountainColor",
|
||||
{ .tooltip = "Fixes a bug that results in the Ikana Great Fairy fountain looking "
|
||||
"green instead of yellow, this was fixed in the EU version" });
|
||||
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
"Fix Texture overflow OOB", "gEnhancements.Fixes.FixTexturesOOB",
|
||||
{ .tooltip = "Fixes textures that normally overflow to be patched with the correct size or format",
|
||||
.defaultValue = true })) {
|
||||
GfxPatcher_ApplyOverflowTexturePatches();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -511,6 +628,12 @@ void DrawEnhancementsMenu() {
|
||||
ImGui::SeparatorText("Clock");
|
||||
UIWidgets::CVarCombobox("Clock Type", "gEnhancements.Graphics.ClockType", clockTypeOptions);
|
||||
UIWidgets::CVarCheckbox("24 Hours Clock", "gEnhancements.Graphics.24HoursClock");
|
||||
|
||||
ImGui::SeparatorText("Mods");
|
||||
UIWidgets::CVarCheckbox("Use Alternate Assets", "gEnhancements.Mods.AlternateAssets",
|
||||
{ .tooltip = "Toggle between standard assets and alternate assets. Usually mods "
|
||||
"will indicate if this setting has to be used or not." });
|
||||
|
||||
MotionBlur_RenderMenuOptions();
|
||||
ImGui::SeparatorText("Other");
|
||||
UIWidgets::CVarCheckbox("Authentic logo", "gEnhancements.Graphics.AuthenticLogo",
|
||||
@@ -518,15 +641,48 @@ void DrawEnhancementsMenu() {
|
||||
"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" });
|
||||
if (UIWidgets::CVarCheckbox("3D Item Drops", "gEnhancements.Graphics.3DItemDrops",
|
||||
{ .tooltip = "Makes item drops 3D" })) {
|
||||
Register3DItemDrops();
|
||||
}
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Disable Black Bar Letterboxes", "gEnhancements.Graphics.DisableBlackBars",
|
||||
{ .tooltip = "Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be "
|
||||
"minor visual glitches that were covered up by the black bars\nPlease disable this "
|
||||
"setting before reporting a bug" });
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255));
|
||||
ImGui::SeparatorText("Unstable");
|
||||
ImGui::PopStyleColor();
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
"Disable Scene Geometry Distance Check", "gEnhancements.Graphics.DisableSceneGeometryDistanceCheck",
|
||||
{ .tooltip =
|
||||
"Disables the distance check for scene geometry, allowing it to be drawn no matter how far "
|
||||
"away it is from the player. This may have unintended side effects." })) {
|
||||
GfxPatcher_ApplyGeometryIssuePatches();
|
||||
}
|
||||
UIWidgets::CVarCheckbox("Widescreen Actor Culling",
|
||||
"gEnhancements.Graphics.ActorCullingAccountsForWidescreen",
|
||||
{ .tooltip = "Adjusts the culling planes to account for widescreen resolutions. "
|
||||
"This may have unintended side effects." });
|
||||
UIWidgets::CVarSliderInt(
|
||||
"Increase Actor Draw Distance: %dx", "gEnhancements.Graphics.IncreaseActorDrawDistance", 1, 5, 1,
|
||||
{ .tooltip = "Increase the range in which Actors are drawn. This may have unintended side effects." });
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (UIWidgets::BeginMenu("Masks")) {
|
||||
UIWidgets::CVarCheckbox("Blast Mask has Powder Keg Force", "gEnhancements.Masks.BlastMaskKeg");
|
||||
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", {});
|
||||
if (UIWidgets::CVarCheckbox("Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled",
|
||||
{ .tooltip = "Permanently toggle a speed boost from the bunny hood by pressing "
|
||||
"'A' on it in the mask menu." })) {
|
||||
UpdatePersistentMasksState();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -534,6 +690,15 @@ void DrawEnhancementsMenu() {
|
||||
if (UIWidgets::BeginMenu("Minigames")) {
|
||||
UIWidgets::CVarCombobox("Always Win Doggy Race", "gEnhancements.Minigames.AlwaysWinDoggyRace",
|
||||
alwaysWinDoggyraceOptions);
|
||||
UIWidgets::CVarCombobox(
|
||||
"Milk Run Reward Options", "gEnhancements.Minigames.CremiaHugs", cremiaRewardOptions,
|
||||
{ .tooltip = "Choose what reward you get for winning the Milk Run minigame after the first time. \n"
|
||||
"-Vanilla: Reward is Random\n"
|
||||
"-Hug: Get the hugging cutscene\n"
|
||||
"-Rupee: Get the rupee reward",
|
||||
.defaultIndex = CREMIA_REWARD_RANDOM });
|
||||
UIWidgets::CVarSliderInt("Swordsman School Winning Score: %d",
|
||||
"gEnhancements.Minigames.SwordsmanSchoolScore", 1, 30, 30);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -541,12 +706,33 @@ void DrawEnhancementsMenu() {
|
||||
if (UIWidgets::BeginMenu("Modes")) {
|
||||
UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei",
|
||||
{ .tooltip = "Requires scene reload to take effect." });
|
||||
if (UIWidgets::CVarCheckbox("Time Moves When You Move", "gModes.TimeMovesWhenYouMove")) {
|
||||
RegisterTimeMovesWhenYouMove();
|
||||
}
|
||||
if (UIWidgets::CVarCheckbox("Mirrored World", "gModes.MirroredWorld.Mode")) {
|
||||
if (CVarGetInteger("gModes.MirroredWorld.Mode", 0)) {
|
||||
CVarSetInteger("gModes.MirroredWorld.State", 1);
|
||||
} else {
|
||||
CVarClear("gModes.MirroredWorld.State");
|
||||
}
|
||||
}
|
||||
|
||||
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." });
|
||||
|
||||
if (UIWidgets::BeginMenu("Player")) {
|
||||
UIWidgets::CVarSliderInt("Climb speed", "gEnhancements.Player.ClimbSpeed", 1, 5, 1,
|
||||
{ .tooltip = "Increases the speed at which Link climbs vines and ladders." });
|
||||
if (UIWidgets::CVarCheckbox("Fast Deku Flower Launch", "gEnhancements.Player.FastFlowerLaunch",
|
||||
{ .tooltip =
|
||||
"Speeds up the time it takes to be able to get maximum height from "
|
||||
"launching out of a deku flower" })) {
|
||||
RegisterFastFlowerLaunch();
|
||||
}
|
||||
UIWidgets::CVarCheckbox("Instant Putaway", "gEnhancements.Player.InstantPutaway",
|
||||
{ .tooltip = "Allows Link to instantly puts away held item without waiting." });
|
||||
UIWidgets::CVarCheckbox("Fierce Deity Putaway", "gEnhancements.Player.FierceDeityPutaway",
|
||||
{ .tooltip = "Allows Fierce Deity Link to put away his sword." });
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -563,6 +749,14 @@ void DrawEnhancementsMenu() {
|
||||
UIWidgets::CVarCheckbox("Tatl ISG", "gEnhancements.Restorations.TatlISG",
|
||||
{ .tooltip = "Restores Navi ISG from OOT, but now with Tatl." });
|
||||
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
"Woodfall Mountain Appearance", "gEnhancements.Restorations.WoodfallMountainAppearance",
|
||||
{ .tooltip = "Restores the appearance of Woodfall mountain to not look poisoned "
|
||||
"when viewed from Termina Field after clearing Woodfall Temple\n\n"
|
||||
"Requires a scene reload to take effect" })) {
|
||||
RegisterWoodfallMountainAppearance();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -576,15 +770,40 @@ void DrawEnhancementsMenu() {
|
||||
{ .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" });
|
||||
UIWidgets::CVarCheckbox("Skip Scarecrow Song", "gEnhancements.Playback.SkipScarecrowSong",
|
||||
{ .tooltip = "Pierre appears when the Ocarina is pulled out." });
|
||||
UIWidgets::CVarCheckbox("Pause Owl Warp", "gEnhancements.Songs.PauseOwlWarp",
|
||||
{ .tooltip = "Allows the player to use the pause menu map to owl warp instead of "
|
||||
"having to play the Song of Soaring." });
|
||||
UIWidgets::CVarSliderInt("Zora Eggs For Bossa Nova", "gEnhancements.Songs.ZoraEggCount", 1, 7, 7,
|
||||
{ .tooltip = "The number of eggs required to unlock new wave bossa nova." });
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (UIWidgets::BeginMenu("Difficulty Options")) {
|
||||
if (UIWidgets::CVarCheckbox("Disable Takkuri Steal", "gEnhancements.Cheats.DisableTakkuriSteal",
|
||||
{ .tooltip = "Prevents the Takkuri from stealing key items like bottles and "
|
||||
"swords. It may still steal other items." })) {
|
||||
RegisterDisableTakkuriSteal();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (mHudEditorWindow) {
|
||||
UIWidgets::WindowButton("Hud Editor", "gWindows.HudEditor", mHudEditorWindow,
|
||||
{ .tooltip = "Enables the Hud Editor window, allowing you to edit your hud" });
|
||||
}
|
||||
|
||||
if (mItemTrackerWindow) {
|
||||
UIWidgets::WindowButton("Item Tracker", "gWindows.ItemTracker", mItemTrackerWindow);
|
||||
}
|
||||
|
||||
if (mItemTrackerSettingsWindow) {
|
||||
UIWidgets::WindowButton("Item Tracker Settings", "gWindows.ItemTrackerSettings",
|
||||
mItemTrackerSettingsWindow);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
@@ -595,13 +814,28 @@ void DrawCheatsMenu() {
|
||||
UIWidgets::CVarCheckbox("Infinite Magic", "gCheats.InfiniteMagic");
|
||||
UIWidgets::CVarCheckbox("Infinite Rupees", "gCheats.InfiniteRupees");
|
||||
UIWidgets::CVarCheckbox("Infinite Consumables", "gCheats.InfiniteConsumables");
|
||||
if (UIWidgets::CVarCheckbox(
|
||||
"Longer Deku Flower Glide", "gCheats.LongerFlowerGlide",
|
||||
{ .tooltip = "Allows Deku Link to glide longer, no longer dropping after a certain distance" })) {
|
||||
RegisterLongerFlowerGlide();
|
||||
}
|
||||
UIWidgets::CVarCheckbox("No Clip", "gCheats.NoClip");
|
||||
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");
|
||||
UIWidgets::CVarCheckbox("Elegy of Emptiness Anywhere", "gCheats.ElegyAnywhere",
|
||||
{ .tooltip = "Allows Elegy of Emptiness outside of Ikana" });
|
||||
UIWidgets::CVarCombobox(
|
||||
"Stop Time in Dungeons", "gCheats.TempleTimeStop", timeStopOptions,
|
||||
{ .tooltip = "Stops time from advancing in selected areas. Requires a room change to update.\n\n"
|
||||
"- Off: Vanilla behaviour.\n"
|
||||
"- Temples: Stops time in Woodfall, Snowhead, Great Bay, and Stone Tower Temples.\n"
|
||||
"- Temples + Mini Dungeons: In addition to the above temples, stops time in both Spider "
|
||||
"Houses, Pirate's Fortress, Beneath the Well, Ancient Castle of Ikana, and Secret Shrine.",
|
||||
.defaultIndex = TIME_STOP_OFF });
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -659,7 +893,7 @@ void DrawDeveloperToolsMenu() {
|
||||
"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",
|
||||
"- 100\% Save: All items, equipment, mask, quest status and bombers notebook complete",
|
||||
.defaultIndex = DEBUG_SAVE_INFO_NONE })) {
|
||||
RegisterDebugSaveCreate();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -17,6 +17,7 @@ HudEditorElement hudEditorElements[HUD_EDITOR_ELEMENT_MAX] = {
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_D_PAD, "D-Pad", "DPad", 271, 55, 255, 255, 255, 255),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_MINIMAP, "Minimap", "Minimap", 295, 220, 0, 255, 255, 160),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_START, "Start Button", "Start", 136, 17, 255, 130, 60, 255),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_CARROT, "Horse Carrots", "Carrots", 160, 64, 236, 92, 41, 255),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_CLOCK, "Three Day Clock", "Clock", 160, 206, 255, 255, 255, 255),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_HEARTS, "Hearts", "Hearts", 30, 26, 255, 70, 50, 255),
|
||||
HUD_EDITOR_ELEMENT(HUD_EDITOR_ELEMENT_MAGIC_METER, "Magic", "Magic", 18, 34, 0, 200, 0, 255),
|
||||
@@ -166,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++) {
|
||||
@@ -206,6 +201,8 @@ void HudEditorWindow::DrawElement() {
|
||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_RIGHT);
|
||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_START].modeCvar,
|
||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_RIGHT);
|
||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_CARROT].modeCvar,
|
||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43);
|
||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_CLOCK].modeCvar,
|
||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43);
|
||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_HEARTS].modeCvar,
|
||||
@@ -249,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,
|
||||
{
|
||||
@@ -276,6 +275,4 @@ void HudEditorWindow::DrawElement() {
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ typedef enum {
|
||||
HUD_EDITOR_ELEMENT_D_PAD,
|
||||
HUD_EDITOR_ELEMENT_MINIMAP,
|
||||
HUD_EDITOR_ELEMENT_START,
|
||||
HUD_EDITOR_ELEMENT_CARROT,
|
||||
HUD_EDITOR_ELEMENT_CLOCK,
|
||||
HUD_EDITOR_ELEMENT_HEARTS,
|
||||
HUD_EDITOR_ELEMENT_MAGIC_METER,
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
#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/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)) {
|
||||
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;
|
||||
#ifdef __ANDROID__
|
||||
float headerWidth = 600.0f + style.ItemSpacing.x;
|
||||
#else
|
||||
float headerWidth = 200.0f + style.ItemSpacing.x;
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
ImVec2 menuSize = {windowWidth,windowHeight};
|
||||
#else
|
||||
ImVec2 menuSize = {std::fminf(1280, windowWidth), std::fminf(800, windowHeight) };
|
||||
#endif
|
||||
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;
|
||||
menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), menuSearchText.end());
|
||||
if (menuSearchText.length() < 1) {
|
||||
#ifdef __ANDROID__
|
||||
ImGui::SameLine(headerWidth - 600.0f + style.ItemSpacing.x);
|
||||
#else
|
||||
ImGui::SameLine(headerWidth - 200.0f + style.ItemSpacing.x);
|
||||
#endif
|
||||
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__) && !defined(__ANDROID__)
|
||||
" (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);
|
||||
#ifdef __ANDROID__
|
||||
float sidebarWidth = 600 - style.ItemSpacing.x;
|
||||
#else
|
||||
float sidebarWidth = 200 - style.ItemSpacing.x;
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
columns=1;
|
||||
#endif
|
||||
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 != NULL ? info.widgetTooltip : "");
|
||||
std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower);
|
||||
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
|
||||
@@ -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
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
#include "Notification.h"
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
extern "C" {
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
}
|
||||
|
||||
namespace Notification {
|
||||
|
||||
static uint32_t nextId = 0;
|
||||
static std::vector<Options> notifications = {};
|
||||
|
||||
void Window::Draw() {
|
||||
auto vp = ImGui::GetMainViewport();
|
||||
|
||||
const float margin = 30.0f;
|
||||
const float padding = 10.0f;
|
||||
|
||||
int position = CVarGetInteger("gNotifications.Position", 3);
|
||||
|
||||
// Top Left
|
||||
ImVec2 basePosition;
|
||||
switch (position) {
|
||||
case 0: // Top Left
|
||||
basePosition = ImVec2(vp->Pos.x + margin, vp->Pos.y + margin);
|
||||
break;
|
||||
case 1: // Top Right
|
||||
basePosition = ImVec2(vp->Pos.x + vp->Size.x - margin, vp->Pos.y + margin);
|
||||
break;
|
||||
case 2: // Bottom Left
|
||||
basePosition = ImVec2(vp->Pos.x + margin, vp->Pos.y + vp->Size.y - margin);
|
||||
break;
|
||||
case 3: // Bottom Right
|
||||
basePosition = ImVec2(vp->Pos.x + vp->Size.x - margin, vp->Pos.y + vp->Size.y - margin);
|
||||
break;
|
||||
case 4: // Hidden
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, CVarGetFloat("gNotifications.BgOpacity", 0.5f)));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.0f * CVarGetFloat("gNotifications.Size", 1.8f), 6.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f * CVarGetFloat("gNotifications.Size", 1.8f), 8.0f));
|
||||
|
||||
for (int index = 0; index < notifications.size(); ++index) {
|
||||
auto& notification = notifications[index];
|
||||
int inverseIndex = -ABS(index - (notifications.size() - 1));
|
||||
|
||||
ImGui::SetNextWindowViewport(vp->ID);
|
||||
if (notification.remainingTime < 4.0f) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, (notification.remainingTime - 1) / 3.0f);
|
||||
} else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f);
|
||||
}
|
||||
|
||||
ImGui::Begin(("notification#" + std::to_string(notification.id)).c_str(), nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
ImGui::SetWindowFontScale(CVarGetFloat("gNotifications.Size", 1.8f));
|
||||
|
||||
ImVec2 notificationPos;
|
||||
switch (position) {
|
||||
case 0: // Top Left
|
||||
notificationPos =
|
||||
ImVec2(basePosition.x, basePosition.y + ((ImGui::GetWindowSize().y + padding) * inverseIndex));
|
||||
break;
|
||||
case 1: // Top Right
|
||||
notificationPos = ImVec2(basePosition.x - ImGui::GetWindowSize().x,
|
||||
basePosition.y + ((ImGui::GetWindowSize().y + padding) * inverseIndex));
|
||||
break;
|
||||
case 2: // Bottom Left
|
||||
notificationPos = ImVec2(basePosition.x,
|
||||
basePosition.y - ((ImGui::GetWindowSize().y + padding) * (inverseIndex + 1)));
|
||||
break;
|
||||
case 3: // Bottom Right
|
||||
notificationPos = ImVec2(basePosition.x - ImGui::GetWindowSize().x,
|
||||
basePosition.y - ((ImGui::GetWindowSize().y + padding) * (inverseIndex + 1)));
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::SetWindowPos(notificationPos);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
if (notification.itemIcon != nullptr) {
|
||||
ImGui::Image(
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(notification.itemIcon),
|
||||
ImVec2(22 * CVarGetFloat("gNotifications.Size", 1.8f), 22 * CVarGetFloat("gNotifications.Size", 1.8f)));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
if (!notification.prefix.empty()) {
|
||||
ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str());
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str());
|
||||
if (!notification.suffix.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(notification.suffixColor, "%s", notification.suffix.c_str());
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
|
||||
void Window::UpdateElement() {
|
||||
for (int index = 0; index < notifications.size(); ++index) {
|
||||
auto& notification = notifications[index];
|
||||
|
||||
// decrement remainingTime
|
||||
notification.remainingTime -= ImGui::GetIO().DeltaTime;
|
||||
|
||||
// remove notification if it has expired
|
||||
if (notification.remainingTime <= 0) {
|
||||
notifications.erase(notifications.begin() + index);
|
||||
--index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Emit(Options notification) {
|
||||
notification.id = nextId++;
|
||||
if (notification.remainingTime == 0.0f) {
|
||||
notification.remainingTime = CVarGetFloat("gNotifications.Duration", 10.0f);
|
||||
}
|
||||
notifications.push_back(notification);
|
||||
AudioSfx_PlaySfx(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultReverb);
|
||||
}
|
||||
|
||||
} // namespace Notification
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user