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') }}
|
key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-14-macports-
|
${{ runner.os }}-14-macports-
|
||||||
|
# Updated PATH applies to the next step and onwards
|
||||||
- name: Install MacPorts (if necessary)
|
- name: Install MacPorts (if necessary)
|
||||||
run: |
|
run: |
|
||||||
if [ command -v port &>/dev/null ]; then
|
if command -v /opt/local/bin/port 2>&1 >/dev/null; then
|
||||||
echo "MacPorts already installed"
|
echo "MacPorts already installed"
|
||||||
else
|
else
|
||||||
|
echo "Installing MacPorts"
|
||||||
wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg
|
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 /
|
sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target /
|
||||||
fi
|
fi
|
||||||
echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
|
echo "/opt/local/bin:/opt/local/sbin" >> "$GITHUB_PATH"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew uninstall --ignore-dependencies libpng
|
brew uninstall --ignore-dependencies libpng
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||||
steps:
|
steps:
|
||||||
- id: 'pr-number'
|
- id: 'pr-number'
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
result-encoding: string
|
result-encoding: string
|
||||||
script: |
|
script: |
|
||||||
@@ -20,8 +20,9 @@ jobs:
|
|||||||
const pullHeadSHA = '${{github.event.workflow_run.head_sha}}';
|
const pullHeadSHA = '${{github.event.workflow_run.head_sha}}';
|
||||||
const pullUserId = ${{github.event.sender.id}};
|
const pullUserId = ${{github.event.sender.id}};
|
||||||
const prNumber = await (async () => {
|
const prNumber = await (async () => {
|
||||||
const pulls = await github.rest.pulls.list({owner, repo});
|
for await (const { data } of github.paginate.iterator(
|
||||||
for await (const {data} of github.paginate.iterator(pulls)) {
|
github.rest.pulls.list, { owner, repo }
|
||||||
|
)) {
|
||||||
for (const pull of data) {
|
for (const pull of data) {
|
||||||
if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) {
|
if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) {
|
||||||
return pull.number;
|
return pull.number;
|
||||||
@@ -36,7 +37,7 @@ jobs:
|
|||||||
|
|
||||||
return prNumber;
|
return prNumber;
|
||||||
- id: 'artifacts-text'
|
- id: 'artifacts-text'
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
result-encoding: string
|
result-encoding: string
|
||||||
script: |
|
script: |
|
||||||
@@ -54,7 +55,7 @@ jobs:
|
|||||||
return acc;
|
return acc;
|
||||||
}, '### Build Artifacts');
|
}, '### Build Artifacts');
|
||||||
- id: 'add-to-pr'
|
- id: 'add-to-pr'
|
||||||
uses: garrettjoecox/pr-section@3.1.0
|
uses: garrettjoecox/pr-section@4.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
pr-number: ${{ steps.pr-number.outputs.result }}
|
pr-number: ${{ steps.pr-number.outputs.result }}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ android {
|
|||||||
}
|
}
|
||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 3
|
versionCode 4
|
||||||
versionName "1.0.2"
|
versionName "1.1.1"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
//ndkBuild {
|
//ndkBuild {
|
||||||
// arguments "APP_PLATFORM=android-23"
|
// arguments "APP_PLATFORM=android-23"
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.dishii.mm"
|
package="com.dishii.mm"
|
||||||
android:versionCode="3"
|
android:versionCode="4"
|
||||||
android:versionName="1.0.2"
|
android:versionName="1.1.1"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<!-- OpenGL ES 3.0 -->
|
<!-- 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")
|
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/2ship-cvars.cmake)
|
||||||
include(CMake/lus-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(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT 2ship)
|
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT 2ship)
|
||||||
@@ -32,7 +32,7 @@ endif()
|
|||||||
set(GFX_DEBUG_DISASSEMBLER ON)
|
set(GFX_DEBUG_DISASSEMBLER ON)
|
||||||
|
|
||||||
# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd)
|
# 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.
|
# 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",
|
"name": "NTSC-U GC",
|
||||||
"sha1": "9743aa026e9269b339eb0e3044cd5830a440c1fd"
|
"sha1": "9743aa026e9269b339eb0e3044cd5830a440c1fd"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
Submodule libultraship updated: e2f0264218...7a303818b3
+42
-14
@@ -8,6 +8,7 @@
|
|||||||
#include <Fast3D/gfx_pc.h>
|
#include <Fast3D/gfx_pc.h>
|
||||||
#include "UIWidgets.hpp"
|
#include "UIWidgets.hpp"
|
||||||
#include "HudEditor.h"
|
#include "HudEditor.h"
|
||||||
|
#include "Notification.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include "graphic/Fast3D/gfx_metal.h"
|
#include "graphic/Fast3D/gfx_metal.h"
|
||||||
@@ -20,6 +21,9 @@
|
|||||||
#include "include/global.h"
|
#include "include/global.h"
|
||||||
#include "include/z64audio.h"
|
#include "include/z64audio.h"
|
||||||
|
|
||||||
|
#include "Enhancements/Trackers/ItemTracker.h"
|
||||||
|
#include "Enhancements/Trackers/ItemTrackerSettings.h"
|
||||||
|
|
||||||
namespace BenGui {
|
namespace BenGui {
|
||||||
// MARK: - Delegates
|
// MARK: - Delegates
|
||||||
|
|
||||||
@@ -27,7 +31,6 @@ std::shared_ptr<BenMenuBar> mBenMenuBar;
|
|||||||
|
|
||||||
std::shared_ptr<Ship::GuiWindow> mConsoleWindow;
|
std::shared_ptr<Ship::GuiWindow> mConsoleWindow;
|
||||||
std::shared_ptr<Ship::GuiWindow> mStatsWindow;
|
std::shared_ptr<Ship::GuiWindow> mStatsWindow;
|
||||||
std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
|
||||||
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
|
std::shared_ptr<Ship::GuiWindow> mGfxDebuggerWindow;
|
||||||
|
|
||||||
std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
|
std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
|
||||||
@@ -35,6 +38,11 @@ std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
|||||||
std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
|
std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
|
||||||
std::shared_ptr<CollisionViewerWindow> mCollisionViewerWindow;
|
std::shared_ptr<CollisionViewerWindow> mCollisionViewerWindow;
|
||||||
std::shared_ptr<EventLogWindow> mEventLogWindow;
|
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() {
|
void SetupGuiElements() {
|
||||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
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));
|
mBenMenuBar = std::make_shared<BenMenuBar>(CVAR_MENU_BAR_OPEN, CVarGetInteger(CVAR_MENU_BAR_OPEN, 0));
|
||||||
gui->SetMenuBar(std::reinterpret_pointer_cast<Ship::GuiMenuBar>(mBenMenuBar));
|
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__)
|
#if defined(__SWITCH__) || defined(__WIIU__) || defined(__ANDROID__)
|
||||||
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
|
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
|
||||||
#else
|
#else
|
||||||
@@ -55,6 +63,9 @@ void SetupGuiElements() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBenMenu = std::make_shared<BenMenu>("gWindows.Menu", "Settings Menu");
|
||||||
|
gui->SetMenu(mBenMenu);
|
||||||
|
|
||||||
mStatsWindow = gui->GetGuiWindow("Stats");
|
mStatsWindow = gui->GetGuiWindow("Stats");
|
||||||
if (mStatsWindow == nullptr) {
|
if (mStatsWindow == nullptr) {
|
||||||
SPDLOG_ERROR("Could not find stats window");
|
SPDLOG_ERROR("Could not find stats window");
|
||||||
@@ -65,43 +76,60 @@ void SetupGuiElements() {
|
|||||||
SPDLOG_ERROR("Could not find console window");
|
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");
|
mGfxDebuggerWindow = gui->GetGuiWindow("GfxDebuggerWindow");
|
||||||
if (mGfxDebuggerWindow == nullptr) {
|
if (mGfxDebuggerWindow == nullptr) {
|
||||||
SPDLOG_ERROR("Could not find input GfxDebuggerWindow");
|
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);
|
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);
|
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);
|
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);
|
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->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() {
|
void Destroy() {
|
||||||
|
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
|
|
||||||
|
gui->RemoveAllGuiWindows();
|
||||||
mBenMenuBar = nullptr;
|
mBenMenuBar = nullptr;
|
||||||
|
mBenMenu = nullptr;
|
||||||
mStatsWindow = nullptr;
|
mStatsWindow = nullptr;
|
||||||
mConsoleWindow = nullptr;
|
mConsoleWindow = nullptr;
|
||||||
mInputEditorWindow = nullptr;
|
mBenInputEditorWindow = nullptr;
|
||||||
mGfxDebuggerWindow = nullptr;
|
mGfxDebuggerWindow = nullptr;
|
||||||
mCollisionViewerWindow = nullptr;
|
mCollisionViewerWindow = nullptr;
|
||||||
mEventLogWindow = nullptr;
|
mEventLogWindow = nullptr;
|
||||||
|
mNotificationWindow = nullptr;
|
||||||
mSaveEditorWindow = nullptr;
|
mSaveEditorWindow = nullptr;
|
||||||
mHudEditorWindow = nullptr;
|
mHudEditorWindow = nullptr;
|
||||||
mActorViewerWindow = nullptr;
|
mActorViewerWindow = nullptr;
|
||||||
|
mItemTrackerWindow = nullptr;
|
||||||
|
mItemTrackerSettingsWindow = nullptr;
|
||||||
}
|
}
|
||||||
} // namespace BenGui
|
} // namespace BenGui
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "DeveloperTools/ActorViewer.h"
|
#include "DeveloperTools/ActorViewer.h"
|
||||||
#include "DeveloperTools/CollisionViewer.h"
|
#include "DeveloperTools/CollisionViewer.h"
|
||||||
#include "DeveloperTools/EventLog.h"
|
#include "DeveloperTools/EventLog.h"
|
||||||
|
#include "BenInputEditorWindow.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
namespace BenGui {
|
namespace BenGui {
|
||||||
void SetupHooks();
|
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 <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "2s2h/Enhancements/Enhancements.h"
|
#include "2s2h/Enhancements/Enhancements.h"
|
||||||
#include "2s2h/Enhancements/Graphics/MotionBlur.h"
|
#include "2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h"
|
||||||
#include "2s2h/Enhancements/Graphics/PlayAsKafei.h"
|
|
||||||
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
||||||
#include "2s2h/DeveloperTools/WarpPoint.h"
|
|
||||||
#include "HudEditor.h"
|
#include "HudEditor.h"
|
||||||
|
|
||||||
|
#include "2s2h/Enhancements/Trackers/ItemTracker.h"
|
||||||
|
#include "2s2h/Enhancements/Trackers/ItemTrackerSettings.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "z64.h"
|
#include "z64.h"
|
||||||
#include "functions.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 = {
|
static std::unordered_map<Ship::WindowBackend, const char*> windowBackendsMap = {
|
||||||
{ Ship::WindowBackend::DX11, "DirectX" },
|
{ Ship::WindowBackend::FAST3D_DXGI_DX11, "DirectX" },
|
||||||
{ Ship::WindowBackend::SDL_OPENGL, "OpenGL" },
|
{ Ship::WindowBackend::FAST3D_SDL_OPENGL, "OpenGL" },
|
||||||
{ Ship::WindowBackend::SDL_METAL, "Metal" },
|
{ Ship::WindowBackend::FAST3D_SDL_METAL, "Metal" },
|
||||||
{ Ship::WindowBackend::GX2, "GX2" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::unordered_map<int32_t, const char*> clockTypeOptions = {
|
static const std::unordered_map<int32_t, const char*> clockTypeOptions = {
|
||||||
{ CLOCK_TYPE_ORIGINAL, "Original" },
|
{ CLOCK_TYPE_ORIGINAL, "Original" },
|
||||||
|
{ CLOCK_TYPE_3DS, "MM3D style" },
|
||||||
{ CLOCK_TYPE_TEXT_BASED, "Text only" },
|
{ 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" },
|
{ 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 {
|
namespace BenGui {
|
||||||
std::shared_ptr<std::vector<Ship::WindowBackend>> availableWindowBackends;
|
std::shared_ptr<std::vector<Ship::WindowBackend>> availableWindowBackends;
|
||||||
std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
|
std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
|
||||||
@@ -63,7 +76,7 @@ Ship::WindowBackend configWindowBackend;
|
|||||||
void UpdateWindowBackendObjects() {
|
void UpdateWindowBackendObjects() {
|
||||||
Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
||||||
int32_t configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
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);
|
configWindowBackend = static_cast<Ship::WindowBackend>(configWindowBackendId);
|
||||||
} else {
|
} else {
|
||||||
configWindowBackend = runningWindowBackend;
|
configWindowBackend = runningWindowBackend;
|
||||||
@@ -147,7 +160,7 @@ void DrawBenMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::shared_ptr<Ship::GuiWindow> mInputEditorWindow;
|
extern std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
|
||||||
|
|
||||||
void DrawSettingsMenu() {
|
void DrawSettingsMenu() {
|
||||||
if (UIWidgets::BeginMenu("Settings")) {
|
if (UIWidgets::BeginMenu("Settings")) {
|
||||||
@@ -214,19 +227,21 @@ void DrawSettingsMenu() {
|
|||||||
{ // FPS Slider
|
{ // FPS Slider
|
||||||
constexpr unsigned int minFps = 20;
|
constexpr unsigned int minFps = 20;
|
||||||
static unsigned int maxFps;
|
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;
|
maxFps = 360;
|
||||||
} else {
|
} else {
|
||||||
maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
||||||
}
|
}
|
||||||
unsigned int currentFps =
|
unsigned int currentFps =
|
||||||
std::max(std::min(OTRGlobals::Instance->GetInterpolationFPS(), maxFps), minFps);
|
std::max(std::min(OTRGlobals::Instance->GetInterpolationFPS(), maxFps), minFps);
|
||||||
bool matchingRefreshRate =
|
bool matchingRefreshRate = CVarGetInteger("gMatchRefreshRate", 0) &&
|
||||||
CVarGetInteger("gMatchRefreshRate", 0) &&
|
Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() !=
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11;
|
Ship::WindowBackend::FAST3D_DXGI_DX11;
|
||||||
UIWidgets::CVarSliderInt((currentFps == 20) ? "FPS: Original (20)" : "FPS: %d", "gInterpolationFPS",
|
UIWidgets::CVarSliderInt((currentFps == 20) ? "FPS: Original (20)" : "FPS: %d", "gInterpolationFPS",
|
||||||
minFps, maxFps, 20, { .disabled = matchingRefreshRate });
|
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(
|
UIWidgets::Tooltip(
|
||||||
"Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is "
|
"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 "
|
"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
|
} // 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);
|
// UIWidgets::Spacer(0);
|
||||||
if (ImGui::Button("Match Refresh Rate")) {
|
if (ImGui::Button("Match Refresh Rate")) {
|
||||||
int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate();
|
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");
|
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"
|
UIWidgets::CVarSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off"
|
||||||
: "Jitter fix: >= %d FPS",
|
: "Jitter fix: >= %d FPS",
|
||||||
"gExtraLatencyThreshold", 0, 360, 80);
|
"gExtraLatencyThreshold", 0, 360, 80);
|
||||||
@@ -302,8 +319,8 @@ void DrawSettingsMenu() {
|
|||||||
// #region 2S2H [Todo] None of this works yet
|
// #region 2S2H [Todo] None of this works yet
|
||||||
/*
|
/*
|
||||||
if (UIWidgets::BeginMenu("Controller")) { */
|
if (UIWidgets::BeginMenu("Controller")) { */
|
||||||
if (mInputEditorWindow) {
|
if (mBenInputEditorWindow) {
|
||||||
UIWidgets::WindowButton("Controller Mapping", "gWindows.InputEditor", mInputEditorWindow);
|
UIWidgets::WindowButton("Controller Mapping", "gWindows.InputEditor", mBenInputEditorWindow);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
@@ -334,16 +351,60 @@ void DrawSettingsMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
|
||||||
|
extern std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||||
|
extern std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||||
|
|
||||||
void DrawEnhancementsMenu() {
|
void DrawEnhancementsMenu() {
|
||||||
if (UIWidgets::BeginMenu("Enhancements")) {
|
if (UIWidgets::BeginMenu("Enhancements")) {
|
||||||
|
|
||||||
if (UIWidgets::BeginMenu("Camera")) {
|
if (UIWidgets::BeginMenu("Camera")) {
|
||||||
ImGui::SeparatorText("Fixes");
|
ImGui::SeparatorText("Fixes");
|
||||||
UIWidgets::CVarCheckbox(
|
UIWidgets::CVarCheckbox(
|
||||||
"Fix Targetting Camera Snap", "gEnhancements.Camera.FixTargettingCameraSnap",
|
"Fix Targeting Camera Snap", "gEnhancements.Camera.FixTargettingCameraSnap",
|
||||||
{ .tooltip =
|
{ .tooltip = "Fixes the camera snap that occurs when you are moving and press the targeting button." });
|
||||||
"Fixes the camera snap that occurs when you are moving and press the targetting 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");
|
ImGui::SeparatorText("Free Look");
|
||||||
if (UIWidgets::CVarCheckbox(
|
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.",
|
.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(
|
UIWidgets::CVarCheckbox(
|
||||||
"Skip Story Cutscenes", "gEnhancements.Cutscenes.SkipStoryCutscenes",
|
"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." });
|
{ .tooltip = "Playing the Song Of Time will not reset the Sword back to Kokiri Sword." });
|
||||||
UIWidgets::CVarCheckbox("Do not reset Rupees", "gEnhancements.Cycle.DoNotResetRupees",
|
UIWidgets::CVarCheckbox("Do not reset Rupees", "gEnhancements.Cycle.DoNotResetRupees",
|
||||||
{ .tooltip = "Playing the Song Of Time will not reset the your rupees." });
|
{ .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::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255));
|
||||||
ImGui::SeparatorText("Unstable");
|
ImGui::SeparatorText("Unstable");
|
||||||
@@ -480,7 +558,12 @@ void DrawEnhancementsMenu() {
|
|||||||
ImGui::EndMenu();
|
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(
|
UIWidgets::CVarCheckbox(
|
||||||
"Fast Text", "gEnhancements.Dialogue.FastText",
|
"Fast Text", "gEnhancements.Dialogue.FastText",
|
||||||
{ .tooltip = "Speeds up text rendering, and enables holding of B progress to next message" });
|
{ .tooltip = "Speeds up text rendering, and enables holding of B progress to next message" });
|
||||||
@@ -495,15 +578,49 @@ void DrawEnhancementsMenu() {
|
|||||||
ImGui::EndMenu();
|
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")) {
|
if (UIWidgets::BeginMenu("Fixes")) {
|
||||||
UIWidgets::CVarCheckbox("Fix Ammo Count Color", "gFixes.FixAmmoCountEnvColor",
|
UIWidgets::CVarCheckbox("Fix Ammo Count Color", "gFixes.FixAmmoCountEnvColor",
|
||||||
{ .tooltip = "Fixes a missing gDPSetEnvColor, which causes the ammo count to be "
|
{ .tooltip = "Fixes a missing gDPSetEnvColor, which causes the ammo count to be "
|
||||||
"the wrong color prior to obtaining magic or other conditions." });
|
"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",
|
UIWidgets::CVarCheckbox("Fix Hess and Weirdshot Crash", "gEnhancements.Fixes.HessCrash",
|
||||||
{ .tooltip = "Fixes a crash that can occur when performing a HESS or Weirdshot.",
|
{ .tooltip = "Fixes a crash that can occur when performing a HESS or Weirdshot.",
|
||||||
.defaultValue = true });
|
.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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,6 +628,12 @@ void DrawEnhancementsMenu() {
|
|||||||
ImGui::SeparatorText("Clock");
|
ImGui::SeparatorText("Clock");
|
||||||
UIWidgets::CVarCombobox("Clock Type", "gEnhancements.Graphics.ClockType", clockTypeOptions);
|
UIWidgets::CVarCombobox("Clock Type", "gEnhancements.Graphics.ClockType", clockTypeOptions);
|
||||||
UIWidgets::CVarCheckbox("24 Hours Clock", "gEnhancements.Graphics.24HoursClock");
|
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();
|
MotionBlur_RenderMenuOptions();
|
||||||
ImGui::SeparatorText("Other");
|
ImGui::SeparatorText("Other");
|
||||||
UIWidgets::CVarCheckbox("Authentic logo", "gEnhancements.Graphics.AuthenticLogo",
|
UIWidgets::CVarCheckbox("Authentic logo", "gEnhancements.Graphics.AuthenticLogo",
|
||||||
@@ -518,15 +641,48 @@ void DrawEnhancementsMenu() {
|
|||||||
"model and texture on the boot logo start screen" });
|
"model and texture on the boot logo start screen" });
|
||||||
UIWidgets::CVarCheckbox("Bow Reticle", "gEnhancements.Graphics.BowReticle",
|
UIWidgets::CVarCheckbox("Bow Reticle", "gEnhancements.Graphics.BowReticle",
|
||||||
{ .tooltip = "Gives the bow a reticle when you draw an arrow" });
|
{ .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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UIWidgets::BeginMenu("Masks")) {
|
if (UIWidgets::BeginMenu("Masks")) {
|
||||||
|
UIWidgets::CVarCheckbox("Blast Mask has Powder Keg Force", "gEnhancements.Masks.BlastMaskKeg");
|
||||||
UIWidgets::CVarCheckbox("Fast Transformation", "gEnhancements.Masks.FastTransformation");
|
UIWidgets::CVarCheckbox("Fast Transformation", "gEnhancements.Masks.FastTransformation");
|
||||||
UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere",
|
UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere",
|
||||||
{ .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." });
|
{ .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." });
|
||||||
UIWidgets::CVarCheckbox("No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", {});
|
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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@@ -534,6 +690,15 @@ void DrawEnhancementsMenu() {
|
|||||||
if (UIWidgets::BeginMenu("Minigames")) {
|
if (UIWidgets::BeginMenu("Minigames")) {
|
||||||
UIWidgets::CVarCombobox("Always Win Doggy Race", "gEnhancements.Minigames.AlwaysWinDoggyRace",
|
UIWidgets::CVarCombobox("Always Win Doggy Race", "gEnhancements.Minigames.AlwaysWinDoggyRace",
|
||||||
alwaysWinDoggyraceOptions);
|
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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@@ -541,12 +706,33 @@ void DrawEnhancementsMenu() {
|
|||||||
if (UIWidgets::BeginMenu("Modes")) {
|
if (UIWidgets::BeginMenu("Modes")) {
|
||||||
UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei",
|
UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei",
|
||||||
{ .tooltip = "Requires scene reload to take effect." });
|
{ .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();
|
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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,6 +749,14 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::CVarCheckbox("Tatl ISG", "gEnhancements.Restorations.TatlISG",
|
UIWidgets::CVarCheckbox("Tatl ISG", "gEnhancements.Restorations.TatlISG",
|
||||||
{ .tooltip = "Restores Navi ISG from OOT, but now with Tatl." });
|
{ .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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,15 +770,40 @@ void DrawEnhancementsMenu() {
|
|||||||
{ .tooltip = "Enables using the Dpad for Ocarina playback." });
|
{ .tooltip = "Enables using the Dpad for Ocarina playback." });
|
||||||
UIWidgets::CVarCheckbox("Prevent Dropped Ocarina Inputs", "gEnhancements.Playback.NoDropOcarinaInput",
|
UIWidgets::CVarCheckbox("Prevent Dropped Ocarina Inputs", "gEnhancements.Playback.NoDropOcarinaInput",
|
||||||
{ .tooltip = "Prevent dropping inputs when playing the ocarina quickly" });
|
{ .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();
|
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) {
|
if (mHudEditorWindow) {
|
||||||
UIWidgets::WindowButton("Hud Editor", "gWindows.HudEditor", mHudEditorWindow,
|
UIWidgets::WindowButton("Hud Editor", "gWindows.HudEditor", mHudEditorWindow,
|
||||||
{ .tooltip = "Enables the Hud Editor window, allowing you to edit your hud" });
|
{ .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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,13 +814,28 @@ void DrawCheatsMenu() {
|
|||||||
UIWidgets::CVarCheckbox("Infinite Magic", "gCheats.InfiniteMagic");
|
UIWidgets::CVarCheckbox("Infinite Magic", "gCheats.InfiniteMagic");
|
||||||
UIWidgets::CVarCheckbox("Infinite Rupees", "gCheats.InfiniteRupees");
|
UIWidgets::CVarCheckbox("Infinite Rupees", "gCheats.InfiniteRupees");
|
||||||
UIWidgets::CVarCheckbox("Infinite Consumables", "gCheats.InfiniteConsumables");
|
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("Unbreakable Razor Sword", "gCheats.UnbreakableRazorSword");
|
||||||
UIWidgets::CVarCheckbox("Unrestricted Items", "gCheats.UnrestrictedItems");
|
UIWidgets::CVarCheckbox("Unrestricted Items", "gCheats.UnrestrictedItems");
|
||||||
if (UIWidgets::CVarCheckbox("Moon Jump on L", "gCheats.MoonJumpOnL",
|
if (UIWidgets::CVarCheckbox("Moon Jump on L", "gCheats.MoonJumpOnL",
|
||||||
{ .tooltip = "Holding L makes you float into the air" })) {
|
{ .tooltip = "Holding L makes you float into the air" })) {
|
||||||
RegisterMoonJumpOnL();
|
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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@@ -659,7 +893,7 @@ void DrawDeveloperToolsMenu() {
|
|||||||
"Change the behavior of creating saves while debug mode is enabled:\n\n"
|
"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"
|
"- 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"
|
"- 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 })) {
|
.defaultIndex = DEBUG_SAVE_INFO_NONE })) {
|
||||||
RegisterDebugSaveCreate();
|
RegisterDebugSaveCreate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "DeveloperTools/ActorViewer.h"
|
#include "DeveloperTools/ActorViewer.h"
|
||||||
#include "DeveloperTools/CollisionViewer.h"
|
#include "DeveloperTools/CollisionViewer.h"
|
||||||
#include "DeveloperTools/EventLog.h"
|
#include "DeveloperTools/EventLog.h"
|
||||||
|
#include "BenInputEditorWindow.h"
|
||||||
|
|
||||||
namespace BenGui {
|
namespace BenGui {
|
||||||
class BenMenuBar : public Ship::GuiMenuBar {
|
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_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_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_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_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_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),
|
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() {
|
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;
|
static HudEditor::Presets preset = HudEditor::Presets::VANILLA;
|
||||||
if (UIWidgets::Combobox("Preset", &preset, presetNames)) {
|
if (UIWidgets::Combobox("Preset", &preset, presetNames)) {
|
||||||
for (int i = HUD_EDITOR_ELEMENT_B; i < HUD_EDITOR_ELEMENT_MAX; i++) {
|
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);
|
HUD_EDITOR_ELEMENT_MODE_MOVABLE_RIGHT);
|
||||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_START].modeCvar,
|
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_START].modeCvar,
|
||||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_RIGHT);
|
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,
|
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_CLOCK].modeCvar,
|
||||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43);
|
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43);
|
||||||
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_HEARTS].modeCvar,
|
CVarSetInteger(hudEditorElements[HUD_EDITOR_ELEMENT_HEARTS].modeCvar,
|
||||||
@@ -249,7 +246,9 @@ void HudEditorWindow::DrawElement() {
|
|||||||
}
|
}
|
||||||
if (CVarGetInteger(hudEditorElements[i].modeCvar, HUD_EDITOR_ELEMENT_MODE_VANILLA) >=
|
if (CVarGetInteger(hudEditorElements[i].modeCvar, HUD_EDITOR_ELEMENT_MODE_VANILLA) >=
|
||||||
HUD_EDITOR_ELEMENT_MODE_MOVABLE_43) {
|
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();
|
ImGui::TableNextColumn();
|
||||||
UIWidgets::CVarSliderInt("X", hudEditorElements[i].xCvar, -10, 330, hudEditorElements[i].defaultX,
|
UIWidgets::CVarSliderInt("X", hudEditorElements[i].xCvar, -10, 330, hudEditorElements[i].defaultX,
|
||||||
{
|
{
|
||||||
@@ -276,6 +275,4 @@ void HudEditorWindow::DrawElement() {
|
|||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ typedef enum {
|
|||||||
HUD_EDITOR_ELEMENT_D_PAD,
|
HUD_EDITOR_ELEMENT_D_PAD,
|
||||||
HUD_EDITOR_ELEMENT_MINIMAP,
|
HUD_EDITOR_ELEMENT_MINIMAP,
|
||||||
HUD_EDITOR_ELEMENT_START,
|
HUD_EDITOR_ELEMENT_START,
|
||||||
|
HUD_EDITOR_ELEMENT_CARROT,
|
||||||
HUD_EDITOR_ELEMENT_CLOCK,
|
HUD_EDITOR_ELEMENT_CLOCK,
|
||||||
HUD_EDITOR_ELEMENT_HEARTS,
|
HUD_EDITOR_ELEMENT_HEARTS,
|
||||||
HUD_EDITOR_ELEMENT_MAGIC_METER,
|
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