mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 09:34:00 +02:00
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3707a86c79 | |||
| eea3ec7f95 | |||
| 4a2c6761fc | |||
| 7a4e179f4c | |||
| 11eaadb739 | |||
| 41b77b54ea | |||
| 22689bd9ee | |||
| 831535c86f | |||
| ce43955784 | |||
| e85f4f4309 | |||
| 00b3f33530 | |||
| 1b0116a0cb | |||
| 486281427c | |||
| 8ccdc415bc | |||
| 008049265d | |||
| fef407b839 | |||
| 084570bc4b | |||
| 3d91e0c3e3 | |||
| b5a942b4fe | |||
| 5c5cc8453d | |||
| 30495795cd | |||
| 073cdd2815 | |||
| fe21c73f75 | |||
| a6cba2ce2a | |||
| 9afd971b43 | |||
| b0f9136fe8 | |||
| b513439565 | |||
| 42494e5019 | |||
| 8653234cb3 | |||
| 6a14761770 | |||
| 399a5c93b2 | |||
| be2db3c95a | |||
| 7f7ac4c5fb | |||
| 7ca98bb496 | |||
| e9cf27411b | |||
| d8f1a5a118 | |||
| 07ea2d8ec4 | |||
| 2c63963134 | |||
| c9d9e71631 | |||
| 69726baa48 | |||
| c02a44d020 | |||
| 1c0c3eb6aa | |||
| 7f9f30181e | |||
| 2bc788beea | |||
| 4a0d20c1a1 | |||
| 2ea9efd622 | |||
| 723f4ab16b | |||
| a242ae78eb | |||
| c037e1465f | |||
| 3e8578f2fd | |||
| 0050646ad7 | |||
| f2ef7e345f | |||
| 3c0698d14b | |||
| ec677c8d26 | |||
| f115c82512 | |||
| 9f4f8ab15b | |||
| 532d8bcaee | |||
| 2978b8443c | |||
| 3b1fbcd9d3 | |||
| de4d4c27c7 | |||
| 91bf6ad996 | |||
| 312885bec1 | |||
| 8641e1b3ba | |||
| ca203d96b0 | |||
| 6774c8731a | |||
| b603f3b75c | |||
| b546826b67 | |||
| a39263aeb5 | |||
| ecaa5b9dee | |||
| 7fcc468353 | |||
| 52952942e9 | |||
| 81dc449637 | |||
| ce25524ed9 | |||
| 30a3522def | |||
| f62de70aa5 | |||
| ec190adc51 | |||
| 7095824874 | |||
| b243f48fff | |||
| 3bc052e948 | |||
| 482e237d08 | |||
| 86f38ab024 | |||
| c837d736bb | |||
| ab94fd484f | |||
| 1508b11044 | |||
| b4e18d1b63 | |||
| f49272288d | |||
| f1dd82c65e | |||
| 7aa7eaffb9 | |||
| 6577fa9810 | |||
| 6aabc4eca8 | |||
| bf5b3d3c99 | |||
| 420eb39c16 | |||
| 6dd764c04c | |||
| 95d5141a2b | |||
| 51c6c3904d | |||
| 32a39afc75 | |||
| fd967cc2a3 | |||
| 8c0bb09667 | |||
| 8c753d6cfe | |||
| 276e681f29 | |||
| f23b17e1b8 | |||
| f1e10fa4b1 | |||
| be67cd03cb | |||
| d7dfe12fb4 | |||
| be437afd2f | |||
| f72688773a | |||
| fb328d8d92 | |||
| 36e6d2fcc7 | |||
| 7b3293341b | |||
| 0a7b72a51b | |||
| 6265973cc6 | |||
| f1edc47a80 | |||
| 8f60d5c80f | |||
| c42489fa81 | |||
| 66b60c988a |
@@ -16,7 +16,7 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get upgrade
|
||||
sudo apt-get -y install cmake libhidapi-dev libsamplerate0-dev libspeex-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt6-base-dev libqt6svg6-dev build-essential nasm git zip
|
||||
sudo apt-get -y install cmake ninja-build libhidapi-dev libsamplerate0-dev libspeex-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt6-base-dev libqt6svg6-dev build-essential nasm git zip
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
echo "GIT_REVISION=$(git describe --tags --always)" >> $GITHUB_ENV
|
||||
@@ -45,19 +45,17 @@ jobs:
|
||||
install: >-
|
||||
make
|
||||
mingw-w64-x86_64-cmake
|
||||
mingw-w64-x86_64-ninja
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-hidapi
|
||||
mingw-w64-x86_64-freetype
|
||||
mingw-w64-x86_64-libpng
|
||||
mingw-w64-x86_64-SDL2
|
||||
mingw-w64-x86_64-jasper
|
||||
mingw-w64-x86_64-qt6
|
||||
mingw-w64-x86_64-SDL2
|
||||
mingw-w64-x86_64-hidapi
|
||||
mingw-w64-x86_64-speexdsp
|
||||
mingw-w64-x86_64-libsamplerate
|
||||
mingw-w64-x86_64-python3-pip
|
||||
mingw-w64-x86_64-python3-pyopenssl
|
||||
mingw-w64-x86_64-nasm
|
||||
mingw-w64-x86_64-minizip
|
||||
git
|
||||
@@ -69,9 +67,6 @@ jobs:
|
||||
- name: Build RMG (Portable)
|
||||
run: ./Source/Script/Build.sh Release
|
||||
shell: msys2 {0}
|
||||
- name: Download Styles
|
||||
run: ./Source/Script/DownloadStyles.sh
|
||||
shell: msys2 {0}
|
||||
- name: Create Installer
|
||||
run: .\Build\Release\Source\Installer\CreateInstaller.bat
|
||||
- name: Upload RMG (Portable)
|
||||
|
||||
+8
-3
@@ -1,7 +1,12 @@
|
||||
# CMake build directory
|
||||
Build/
|
||||
Bin/
|
||||
# VSCode Configuration
|
||||
.vscode/
|
||||
# Clangd cache
|
||||
.cache/
|
||||
.cache/
|
||||
# Archlinux Package
|
||||
Package/ArchLinux/pkg/
|
||||
Package/ArchLinux/rmg/
|
||||
Package/ArchLinux/src/
|
||||
Package/ArchLinux/*.pkg.*
|
||||
# Clangd compile_commands.json
|
||||
compile_commands.json
|
||||
+5
-11
@@ -7,7 +7,6 @@ option(PORTABLE_INSTALL "Portable Installation" ON)
|
||||
option(NO_GIT_CLONE "Disables git clone usage for 3rdParty dependencies" OFF)
|
||||
option(UPDATER "Enables updater" ${PORTABLE_INSTALL})
|
||||
option(DISCORD_RPC "Enables Discord Rich Presence" ON)
|
||||
option(USE_QT5 "Enables Qt5 instead of Qt6 (will be removed in the future)" OFF)
|
||||
option(USE_CCACHE "Enables usage of ccache when ccache has been found" ON)
|
||||
|
||||
project(RMG)
|
||||
@@ -59,14 +58,6 @@ else()
|
||||
set(ICON_INSTALL_PATH "share/icons/hicolor/scalable/apps/")
|
||||
endif()
|
||||
|
||||
if (USE_QT5)
|
||||
set(QT_VERSION "Qt5")
|
||||
set(USE_QT6 OFF)
|
||||
else(USE_QT5)
|
||||
set(QT_VERSION "Qt6")
|
||||
set(USE_QT6 ON)
|
||||
endif(USE_QT5)
|
||||
|
||||
add_subdirectory(Source/3rdParty)
|
||||
|
||||
add_subdirectory(Source/RMG-Core)
|
||||
@@ -87,9 +78,9 @@ if (WIN32)
|
||||
add_subdirectory(Source/Installer)
|
||||
|
||||
add_custom_target(bundle_dependencies
|
||||
COMMAND "${CMAKE_SOURCE_DIR}/Source/Script/BundleDependencies.sh" "${CMAKE_SOURCE_DIR}/Bin/${CMAKE_BUILD_TYPE}/RMG.exe" "${CMAKE_SOURCE_DIR}/Bin/${CMAKE_BUILD_TYPE}/" "/mingw64/bin"
|
||||
COMMAND bash "${CMAKE_SOURCE_DIR}/Source/Script/BundleDependencies.sh" "${CMAKE_SOURCE_DIR}/Bin/${CMAKE_BUILD_TYPE}/RMG.exe" "${CMAKE_SOURCE_DIR}/Bin/${CMAKE_BUILD_TYPE}" "/mingw64/bin"
|
||||
)
|
||||
endif()
|
||||
endif(WIN32)
|
||||
|
||||
install(FILES ${MUPEN64PLUSCORE_LIB}
|
||||
DESTINATION ${CORE_INSTALL_PATH}
|
||||
@@ -97,6 +88,9 @@ install(FILES ${MUPEN64PLUSCORE_LIB}
|
||||
install(FILES ${MUPEN64PLUSCORE_INI} Data/font.ttf
|
||||
DESTINATION ${DATA_INSTALL_PATH}
|
||||
)
|
||||
install(FILES ${SDL_GAMECONTROLLERDB}
|
||||
DESTINATION ${DATA_INSTALL_PATH}
|
||||
)
|
||||
file(GLOB GENERATED_CHEAT_FILES ${CMAKE_SOURCE_DIR}/Data/Cheats/Generated/*.cht)
|
||||
file(GLOB CUSTOM_CHEAT_FILES ${CMAKE_SOURCE_DIR}/Data/Cheats/Custom/*.cht)
|
||||
install(FILES ${GENERATED_CHEAT_FILES} ${CUSTOM_CHEAT_FILES}
|
||||
|
||||
@@ -12,7 +12,7 @@ provides=("$_pkgname")
|
||||
conflicts=("$_pkgname")
|
||||
|
||||
depends=("hidapi" "libsamplerate" "minizip" "sdl2" "zlib" "freetype2" "qt6-base" "qt6-svg" "xdg-user-dirs")
|
||||
makedepends=("git" "pkg-config" "nasm" "cmake" "cargo")
|
||||
makedepends=("git" "pkg-config" "nasm" "cmake" "cargo" "ninja")
|
||||
|
||||
source=("git+https://github.com/Rosalie241/${_pkgname}.git")
|
||||
sha256sums=('SKIP')
|
||||
@@ -26,26 +26,21 @@ pkgver()
|
||||
|
||||
prepare()
|
||||
{
|
||||
cd "$srcdir/${_pkgname}"
|
||||
|
||||
mkdir -p build
|
||||
mkdir -p "$srcdir/${_pkgname}/build"
|
||||
}
|
||||
|
||||
build()
|
||||
{
|
||||
cd "$srcdir/${_pkgname}/build"
|
||||
|
||||
cmake -S "$srcdir/${_pkgname}" -B "$srcdir/${_pkgname}/build" \
|
||||
-DCMAKE_BUILD_TYPE="Release" \
|
||||
-DPORTABLE_INSTALL="OFF" \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-G "Unix Makefiles"
|
||||
make
|
||||
-G "Ninja" \
|
||||
|
||||
cmake --build "$srcdir/${_pkgname}/build"
|
||||
}
|
||||
|
||||
package()
|
||||
{
|
||||
cd "$srcdir/${_pkgname}/build"
|
||||
|
||||
make install DESTDIR="$pkgdir"
|
||||
cmake --install "$srcdir/${_pkgname}/build" --prefix="$pkgdir/usr"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,82 @@
|
||||
</screenshots>
|
||||
<description/>
|
||||
<releases>
|
||||
<release version="v0.3.2" date="2023-02-06" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix ndd/d64 files in zip files not working when the disk file is inside a subdirectory inside the zip file</li>
|
||||
<li>Fix ndd/d64 files in zip files not working correctly on windows</li>
|
||||
<li>Fix controller image in RMG-Input sometimes being stuck when having a trigger bound to a button</li>
|
||||
<li>Fix trigger mapping in RMG-Input</li>
|
||||
<li>Remove "Invert Axis Mapped To LRZ" setting in RMG-Input</li>
|
||||
<li>Add "Sort Results After Search" ROM Browser setting</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.3.1" date="2023-02-04" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix taking a screenshot not working in some cases</li>
|
||||
<li>Fix some games being unable to save due to having an illegal character in the save filename</li>
|
||||
<li>Fix OSD tab crash in GLideN64</li>
|
||||
<li>Fix an issue where the graphics plugin would show the 64DD IPL as ROM name in the settings even after booting a cartridge</li>
|
||||
<li>Fix "Refresh ROM List" in Hotkeys tab in settings dialog not reverting back to defaults when clicking on 'restore defaults'</li>
|
||||
<li>Fix "Remove Duplicate Keybindings" in settings dialog not behaving correctly in some cases</li>
|
||||
<li>Fix fallback application icons not respecting system icon theme on linux</li>
|
||||
<li>Add support for ndd/d64 files in zip files</li>
|
||||
<li>Add support for using the basename of the ROM filename for covers</li>
|
||||
<li>Add support for binding multiple inputs in RMG-Input</li>
|
||||
<li>Improve behavior of window when launching RMG with a ROM using the commandline</li>
|
||||
<li>Improve behavior of error message when emulation fails</li>
|
||||
<li>Improve behavior of hotkey buttons in settings dialog</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.3.0" date="2023-01-23" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix GLideN64 not being able to load texture packs from relative paths</li>
|
||||
<li>Fix "Save State Slot" keybindings not working in fullscreen</li>
|
||||
<li>Fix deadzone percentage being incorrect when set to 0% in RMG-Input</li>
|
||||
<li>Fix low deadzone value not working in RMG-Input (thank you porcino)</li>
|
||||
<li>Fix toolbar being hidden when ending emulation while in fullscreen</li>
|
||||
<li>Fix zip files with japanese characters in the file name not being able to be opened on windows</li>
|
||||
<li>Fix ROM Browser not returning to a maximized state when ending emulation</li>
|
||||
<li>Fix ROM Browser not opening maximized when closing RMG with it maximized</li>
|
||||
<li>Fix window not being able to be maximized during emulation when scaling is enabled</li>
|
||||
<li>Fix read-only ROM files not being able to be opened on linux</li>
|
||||
<li>Remove "Allow Manual Window Resizing" setting due to it being always enabled</li>
|
||||
<li>Remove Styles tab from settings dialog on windows</li>
|
||||
<li>Add "Play Game with Cartridge" to context menu when a 64DD disk is selected in the ROM Browser</li>
|
||||
<li>Add "Open ROM Directory" to context menu in the ROM Browser</li>
|
||||
<li>Add an On-Screen Display (see the OSD tab in the settings dialog for settings)</li>
|
||||
<li>Add Theme setting to settings dialog (see Interface -> Miscellaneous, this is a replacement for the previous Styles settings)</li>
|
||||
<li>Improve error message when opening a zip file fails</li>
|
||||
<li>Improve tab order and naming in settings dialog</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.2.9" date="2023-01-03" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix wrong 64DD Disk extension being listed in empty ROM browser</li>
|
||||
<li>Fix memory corruption when having 64DD Disk files</li>
|
||||
<li>Fix possible crash when render window wasn't visible yet</li>
|
||||
<li>Fix RMG changing the current directory on non-portable installs</li>
|
||||
<li>Remove Qt warning messages (you can view them by setting RMG_SHOW_DEBUG_QT_MESSAGES to 1)</li>
|
||||
<li>Change "Choose ROM Directory" to "Change ROM Directory"</li>
|
||||
<li>Add -q/--quit-after-emulation commandline option</li>
|
||||
<li>Add 2 more icons to menubar menus/items</li>
|
||||
<li>Add "Current Save State" tab to Hotkeys tab in settings dialog (this allows you to use a hotkey to change save state slots)</li>
|
||||
<li>Improve behavior of Hotkeys tab in settings dialog</li>
|
||||
<li>Improve behavior of window when exiting RMG while in-game</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.2.8" date="2023-01-01" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
|
||||
@@ -4,51 +4,6 @@ Rosalie's Mupen GUI is a free and open-source mupen64plus GUI written in C++.
|
||||
|
||||
It offers a simple-to-use user interface.
|
||||
|
||||
## System Requirements
|
||||
|
||||
* Operating System
|
||||
* Windows Or Linux
|
||||
* CPU
|
||||
* Intel or AMD processor with SSE2 support
|
||||
* RAM
|
||||
* 512MB or more
|
||||
* Graphics card
|
||||
* OpenGL 3.3 capable
|
||||
|
||||
## Building
|
||||
|
||||
#### Linux
|
||||
* Portable Debian/Ubuntu
|
||||
|
||||
```shell
|
||||
sudo apt-get -y install cmake libhidapi-dev libsamplerate0-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt5-default build-essential nasm git zip
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
* Portable Fedora
|
||||
```shell
|
||||
sudo dnf install hidapi-devel libsamplerate-devel minizip-compat-devel SDL2-devel freetype-devel mesa-libGL-devel mesa-libGLU-devel zlib-ng-devel binutils-devel speexdsp-devel qt5-qtbase-devel qt5-qtsvg-devel gcc-c++ nasm git
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
When it's done building, executables can be found in `Bin/Release`
|
||||
|
||||
* Installation/Packaging
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE="Release" -DPORTABLE_INSTALL="OFF" -G "Unix Makefiles"
|
||||
make install
|
||||
```
|
||||
|
||||
#### Windows
|
||||
* Download & Install [MSYS2](https://www.msys2.org/)
|
||||
```
|
||||
sudo pacman -S git make mingw-w64-x86_64-cmake mingw-w64-x86_64-freetype mingw-w64-x86_64-gcc mingw-w64-x86_64-hidapi mingw-w64-x86_64-jasper mingw-w64-x86_64-libpng mingw-w64-x86_64-libsamplerate mingw-w64-x86_64-nasm mingw-w64-x86_64-python3-pip mingw-w64-x86_64-python3-pyopenssl mingw-w64-x86_64-qt5 mingw-w64-x86_64-rust mingw-w64-x86_64-SDL2
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
When it's done building, executables can be found in `Bin/Release`
|
||||
|
||||
## Support
|
||||
|
||||
Join the [Rosalie's Mupen GUI Discord Server](https://discord.gg/k9GuyJ2PpF) for support
|
||||
@@ -56,3 +11,46 @@ Join the [Rosalie's Mupen GUI Discord Server](https://discord.gg/k9GuyJ2PpF) for
|
||||
## License
|
||||
|
||||
Rosalie's Mupen GUI is licensed under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
|
||||
## Showcase
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Building
|
||||
|
||||
#### Linux
|
||||
* Portable Debian/Ubuntu
|
||||
|
||||
```bash
|
||||
sudo apt-get -y install cmake libhidapi-dev libsamplerate0-dev libspeex-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt6-base-dev libqt6svg6-dev build-essential nasm git zip ninja-build
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
* Portable Fedora
|
||||
```bash
|
||||
sudo dnf install hidapi-devel libsamplerate-devel minizip-compat-devel SDL2-devel freetype-devel mesa-libGL-devel mesa-libGLU-devel zlib-ng-devel binutils-devel speexdsp-devel qt6-qtbase-devel qt6-qtsvg-devel gcc-c++ nasm git ninja-build
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
When it's done building, executables can be found in `Bin/Release`
|
||||
|
||||
* Installation/Packaging
|
||||
```bash
|
||||
export src_dir="$(pwd)"
|
||||
export build_dir="$(pwd)/build"
|
||||
mkdir -p "$build_dir"
|
||||
cmake -S "$src_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE="Release" -DPORTABLE_INSTALL="OFF" -DCMAKE_INSTALL_PREFIX="/usr" -G "Ninja"
|
||||
cmake --build "$build_dir"
|
||||
cmake --install "$build_dir" --prefix="/usr"
|
||||
```
|
||||
|
||||
#### Windows
|
||||
* Download & Install [MSYS2](https://www.msys2.org/)
|
||||
```bash
|
||||
pacman -S --needed make mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-hidapi mingw-w64-x86_64-freetype mingw-w64-x86_64-libpng mingw-w64-x86_64-SDL2 mingw-w64-x86_64-qt6 mingw-w64-x86_64-SDL2 mingw-w64-x86_64-hidapi mingw-w64-x86_64-speexdsp mingw-w64-x86_64-libsamplerate mingw-w64-x86_64-nasm mingw-w64-x86_64-minizip git
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
When it's done building, executables can be found in `Bin/Release`
|
||||
|
||||
Vendored
+84
-18
@@ -37,7 +37,7 @@ endif(USE_CCACHE)
|
||||
|
||||
if(NOT NO_GIT_CLONE)
|
||||
set(MUPEN64PLUSCORE_URL "https://github.com/Rosalie241/mupen64plus-core")
|
||||
set(MUPEN64PLUSCORE_TAG "3b6523edd467eb9224310e0862005c7e5ae9c290")
|
||||
set(MUPEN64PLUSCORE_TAG "022e7de28067ac633ca23d405e9f0c4ed5cc368b")
|
||||
|
||||
set(MUPEN64PLUS_RSP_CXD4_URL "https://github.com/mupen64plus/mupen64plus-rsp-cxd4")
|
||||
set(MUPEN64PLUS_RSP_CXD4_TAG "39f79201baa15890c4cbae92f2215a634cc3ee6d")
|
||||
@@ -58,13 +58,19 @@ if(NOT NO_GIT_CLONE)
|
||||
set(MUPEN64PLUS_GFX_ANGRYLION_TAG "158e74d4ec1c818289cd19c3a05e498c3ceff758")
|
||||
|
||||
set(MUPEN64PLUS_GFX_GLIDEN64_URL "https://github.com/gonetz/GLideN64")
|
||||
set(MUPEN64PLUS_GFX_GLIDEN64_TAG "7bbde56cf08ff96108efb592848e5b6eaac293c9")
|
||||
set(MUPEN64PLUS_GFX_GLIDEN64_TAG "263a7bd2ca81759ece98209bd282a6c1173a129f")
|
||||
|
||||
set(MUPEN64PLUS_GFX_PARALLEL_URL "https://github.com/Rosalie241/parallel-rdp-standalone")
|
||||
set(MUPEN64PLUS_GFX_PARALLEL_TAG "88d3626362e41aa9b011fca1f65e1c1237ddb3b2")
|
||||
set(MUPEN64PLUS_GFX_PARALLEL_TAG "48abaa5e082add7848e6f98648111c69c4a71632")
|
||||
|
||||
set(DISCORD_RPC_URL "https://github.com/discord/discord-rpc")
|
||||
set(DISCORD_RPC_TAG "963aa9f3e5ce81a4682c6ca3d136cddda614db33")
|
||||
|
||||
set(IMGUI_URL "https://github.com/ocornut/imgui")
|
||||
set(IMGUI_TAG "d7c8516a4b848c0291e3d75b627c0843f515f591")
|
||||
|
||||
set(SDL_GAMECONTROLLERDB_URL "https://github.com/gabomdq/SDL_GameControllerDB")
|
||||
set(SDL_GAMECONTROLLERDB_TAG "0562b00eaf5c0308c49d329b79263d2dae1c3a85")
|
||||
endif(NOT NO_GIT_CLONE)
|
||||
|
||||
ExternalProject_Add(mupen64plus-core
|
||||
@@ -76,7 +82,7 @@ ExternalProject_Add(mupen64plus-core
|
||||
GIT_REPOSITORY ${MUPEN64PLUSCORE_URL}
|
||||
GIT_TAG ${MUPEN64PLUSCORE_TAG}
|
||||
|
||||
BUILD_COMMAND $(MAKE) all OSD=0 NEW_DYNAREC=1 TARGET=${CORE_FILE} DEBUG=$<CONFIG:Debug> KEYBINDINGS=0 CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_COMMAND make all OSD=0 NEW_DYNAREC=1 TARGET=${CORE_FILE} DEBUG=$<CONFIG:Debug> KEYBINDINGS=0 CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_IN_SOURCE False
|
||||
|
||||
BINARY_DIR ${M64P_CORE_DIR}/projects/unix
|
||||
@@ -95,7 +101,7 @@ ExternalProject_Add(mupen64plus-rsp-cxd4
|
||||
GIT_REPOSITORY ${MUPEN64PLUS_RSP_CXD4_URL}
|
||||
GIT_TAG ${MUPEN64PLUS_RSP_CXD4_TAG}
|
||||
|
||||
BUILD_COMMAND $(MAKE) all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> POSTFIX= CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> POSTFIX= CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_IN_SOURCE False
|
||||
|
||||
BINARY_DIR ${THIRDPARTY_DIR}/mupen64plus-rsp-cxd4/projects/unix
|
||||
@@ -113,7 +119,7 @@ ExternalProject_Add(mupen64plus-rsp-hle
|
||||
GIT_REPOSITORY ${MUPEN64PLUS_RSP_HLE_URL}
|
||||
GIT_TAG ${MUPEN64PLUS_RSP_HLE_TAG}
|
||||
|
||||
BUILD_COMMAND $(MAKE) all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_IN_SOURCE False
|
||||
|
||||
BINARY_DIR ${THIRDPARTY_DIR}/mupen64plus-rsp-hle/projects/unix
|
||||
@@ -146,7 +152,7 @@ ExternalProject_Add(mupen64plus-input-raphnetraw
|
||||
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_RAPHNET_URL}
|
||||
GIT_TAG ${MUPEN64PLUS_INPUT_RAPHNET_TAG}
|
||||
|
||||
BUILD_COMMAND $(MAKE) all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug> CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
|
||||
BUILD_IN_SOURCE False
|
||||
|
||||
BINARY_DIR ${THIRDPARTY_DIR}/mupen64plus-input-raphnetraw/projects/unix
|
||||
@@ -175,11 +181,12 @@ endif(BUILD_INPUT_GCA)
|
||||
|
||||
set(GLIDEN64_DIR "${THIRDPARTY_DIR}/mupen64plus-video-GLideN64")
|
||||
set(GLIDEN64_BUILD_DIR "${GLIDEN64_DIR}/projects/cmake")
|
||||
if (MSYS)
|
||||
set(GLIDEN64_CUSTOM_INI "${GLIDEN64_DIR}/ini/GLideN64.custom.ini")
|
||||
if (WIN32)
|
||||
set(GLIDEN64_LIB "${GLIDEN64_BUILD_DIR}/mupen64plus-video-GLideN64.${SO_EXT}")
|
||||
else()
|
||||
else(WIN32)
|
||||
set(GLIDEN64_LIB "${GLIDEN64_BUILD_DIR}/plugin/${CMAKE_BUILD_TYPE}/mupen64plus-video-GLideN64.${SO_EXT}")
|
||||
endif()
|
||||
endif(WIN32)
|
||||
|
||||
set(GLIDENUI_TRANSLATIONS_LANGS "de;es;fr;it;ja;pl;pt_BR")
|
||||
foreach(LANG ${GLIDENUI_TRANSLATIONS_LANGS})
|
||||
@@ -195,7 +202,7 @@ ExternalProject_Add(mupen64plus-video-angrylion-plus
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
BUILD_IN_SOURCE True
|
||||
CMAKE_ARGS -DBUILD_MUPEN64PLUS=ON -DBUILD_PROJECT64=OFF -DUSE_QT5=${USE_QT5} ${CMAKE_CONFIGURE_ARGS}
|
||||
CMAKE_ARGS -DBUILD_MUPEN64PLUS=ON -DBUILD_PROJECT64=OFF -DUSE_QT5=OFF ${CMAKE_CONFIGURE_ARGS}
|
||||
|
||||
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-video-angrylion-plus/mupen64plus-video-angrylion-plus.${SO_EXT}
|
||||
DEPENDS mupen64plus-core
|
||||
@@ -210,14 +217,12 @@ ExternalProject_Add(mupen64plus-video-GLideN64
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
BUILD_IN_SOURCE False
|
||||
CMAKE_ARGS -DMUPENPLUSAPI=ON -DMUPENPLUSAPI_GLIDENUI=ON -DGLIDENUI_QT6=${USE_QT6} -DUSE_SYSTEM_LIBS=ON ${CMAKE_CONFIGURE_ARGS}
|
||||
CMAKE_ARGS -DMUPENPLUSAPI=ON -DMUPENPLUSAPI_GLIDENUI=ON -DGLIDENUI_QT6=ON -DUSE_SYSTEM_LIBS=ON ${CMAKE_CONFIGURE_ARGS}
|
||||
|
||||
SOURCE_SUBDIR ./src/
|
||||
BINARY_DIR ${GLIDEN64_BUILD_DIR}
|
||||
|
||||
BUILD_BYPRODUCTS ${GLIDEN64_LIB}
|
||||
BUILD_BYPRODUCTS ${GLIDEN64_DIR}/ini/GLideN64.custom.ini
|
||||
BUILD_BYPRODUCTS ${GLIDENUI_TRANSLATIONS}
|
||||
)
|
||||
|
||||
ExternalProject_Add(mupen64plus-video-parallel
|
||||
@@ -229,7 +234,7 @@ ExternalProject_Add(mupen64plus-video-parallel
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
BUILD_IN_SOURCE True
|
||||
CMAKE_ARGS -DUSE_QT5=${USE_QT5} ${CMAKE_CONFIGURE_ARGS}
|
||||
CMAKE_ARGS -DUSE_QT5=OFF ${CMAKE_CONFIGURE_ARGS}
|
||||
|
||||
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-video-parallel/mupen64plus-video-parallel.${SO_EXT}
|
||||
DEPENDS mupen64plus-core
|
||||
@@ -251,6 +256,60 @@ if (DISCORD_RPC)
|
||||
)
|
||||
endif(DISCORD_RPC)
|
||||
|
||||
set(IMGUI_DIR ${THIRDPARTY_DIR}/imgui)
|
||||
set(IMGUI_BUILD_DIR ${IMGUI_DIR}/build)
|
||||
set(IMGUI_SOURCES_IN
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_opengl3.h
|
||||
${IMGUI_DIR}/backends/imgui_impl_opengl3_loader.h
|
||||
)
|
||||
set(IMGUI_SOURCES_OUT
|
||||
${IMGUI_BUILD_DIR}/imgui_draw.cpp
|
||||
${IMGUI_BUILD_DIR}/imgui_tables.cpp
|
||||
${IMGUI_BUILD_DIR}/imgui_widgets.cpp
|
||||
${IMGUI_BUILD_DIR}/imgui.cpp
|
||||
${IMGUI_BUILD_DIR}/imgui_impl_opengl3.cpp
|
||||
${IMGUI_BUILD_DIR}/imgui_impl_opengl3.h
|
||||
${IMGUI_BUILD_DIR}/imgui_impl_opengl3_loader.h
|
||||
)
|
||||
ExternalProject_Add(imgui
|
||||
SOURCE_DIR imgui
|
||||
|
||||
GIT_REPOSITORY ${IMGUI_URL}
|
||||
GIT_TAG ${IMGUI_TAG}
|
||||
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${IMGUI_BUILD_DIR}
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E copy ${IMGUI_SOURCES_IN} ${IMGUI_BUILD_DIR}
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
BUILD_BYPRODUCTS ${IMGUI_SOURCES_OUT}
|
||||
)
|
||||
|
||||
set(SDL_GAMECONTROLLERDB_DIR ${THIRDPARTY_DIR}/SDL_GameControllerDB)
|
||||
set(SDL_GAMECONTROLLERDB_BUILD_DIR ${SDL_GAMECONTROLLERDB_DIR}/build)
|
||||
set(SDL_GAMECONTROLLERDB_SOURCES_IN
|
||||
${SDL_GAMECONTROLLERDB_DIR}/gamecontrollerdb.txt
|
||||
)
|
||||
set(SDL_GAMECONTROLLERDB_SOURCES_OUT
|
||||
${SDL_GAMECONTROLLERDB_BUILD_DIR}/gamecontrollerdb.txt
|
||||
)
|
||||
ExternalProject_Add(SDL_GameControllerDB
|
||||
SOURCE_DIR SDL_GameControllerDB
|
||||
|
||||
GIT_REPOSITORY ${SDL_GAMECONTROLLERDB_URL}
|
||||
GIT_TAG ${SDL_GAMECONTROLLERDB_TAG}
|
||||
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${SDL_GAMECONTROLLERDB_BUILD_DIR}
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E copy ${SDL_GAMECONTROLLERDB_SOURCES_IN} ${SDL_GAMECONTROLLERDB_SOURCES_OUT}
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
BUILD_BYPRODUCTS ${SDL_GAMECONTROLLERDB_SOURCES_OUT}
|
||||
)
|
||||
|
||||
ExternalProject_Get_property(mupen64plus-core BUILD_BYPRODUCTS)
|
||||
set(MUPEN64PLUSCORE_LIB ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
set(MUPEN64PLUSCORE_INI ${M64P_CORE_DIR}/data/mupen64plus.ini PARENT_SCOPE)
|
||||
@@ -276,12 +335,19 @@ ExternalProject_Get_property(mupen64plus-video-angrylion-plus BUILD_BYPRODUCTS)
|
||||
set(MUPEN64PLUS_PLUGIN_GFX_ANGRYLION ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
|
||||
ExternalProject_Get_property(mupen64plus-video-GLideN64 BUILD_BYPRODUCTS)
|
||||
set(MUPEN64PLUS_PLUGIN_GFX_GLIDEN64 ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
set(MUPEN64PLUS_PLUGIN_GFX_GLIDEN64 ${BUILD_BYPRODUCTS} ${GLIDENUI_TRANSLATIONS} ${GLIDEN64_CUSTOM_INI} PARENT_SCOPE)
|
||||
|
||||
ExternalProject_Get_property(mupen64plus-video-parallel BUILD_BYPRODUCTS)
|
||||
set(MUPEN64PLUS_PLUGIN_GFX_PARALLEL ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
|
||||
if (DISCORD_RPC)
|
||||
ExternalProject_Get_property(discord-rpc BUILD_BYPRODUCTS)
|
||||
set(DISCORD_RPC_LIB ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
ExternalProject_Get_property(discord-rpc BUILD_BYPRODUCTS)
|
||||
set(DISCORD_RPC_LIB ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
endif(DISCORD_RPC)
|
||||
|
||||
ExternalProject_Get_property(imgui BUILD_BYPRODUCTS)
|
||||
set(IMGUI_SOURCES ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
set(IMGUI_DIR ${THIRDPARTY_DIR}/imgui PARENT_SCOPE)
|
||||
|
||||
ExternalProject_Get_property(SDL_GameControllerDB BUILD_BYPRODUCTS)
|
||||
set(SDL_GAMECONTROLLERDB ${BUILD_BYPRODUCTS} PARENT_SCOPE)
|
||||
|
||||
@@ -7,7 +7,7 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(${QT_VERSION} COMPONENTS Gui Widgets Core REQUIRED)
|
||||
find_package(Qt6 COMPONENTS Gui Widgets Core REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SDL2 REQUIRED sdl2)
|
||||
@@ -36,7 +36,7 @@ target_link_libraries(RMG-Audio
|
||||
${SDL2_LIBRARIES}
|
||||
${SPEEX_LIBRARIES}
|
||||
${SAMPLERATE_LIBRARIES}
|
||||
${QT_VERSION}::Gui ${QT_VERSION}::Widgets
|
||||
Qt6::Gui Qt6::Widgets
|
||||
)
|
||||
|
||||
target_include_directories(RMG-Audio PRIVATE
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
#define MD5_LEN 33
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheWindows_04"
|
||||
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheWindows_05"
|
||||
#else // Linux
|
||||
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheLinux_04"
|
||||
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheLinux_05"
|
||||
#endif // _WIN32
|
||||
#define CACHE_FILE_ITEMS_MAX 10000
|
||||
|
||||
@@ -53,6 +53,7 @@ struct l_CacheEntry
|
||||
std::filesystem::path fileName;
|
||||
osal_files_file_time fileTime;
|
||||
|
||||
CoreRomType type;
|
||||
CoreRomHeader header;
|
||||
CoreRomSettings settings;
|
||||
};
|
||||
@@ -138,6 +139,8 @@ void CoreReadRomHeaderAndSettingsCache(void)
|
||||
FREAD_STR(fileNameBuf, size);
|
||||
cacheEntry.fileName = std::filesystem::path(fileNameBuf);
|
||||
FREAD(cacheEntry.fileTime);
|
||||
// type
|
||||
FREAD(cacheEntry.type);
|
||||
// header
|
||||
FREAD(size);
|
||||
FREAD_STR(headerNameBuf, size);
|
||||
@@ -211,6 +214,8 @@ bool CoreSaveRomHeaderAndSettingsCache(void)
|
||||
FWRITE(size);
|
||||
FWRITE_STR(fileNameBuf, size);
|
||||
FWRITE(cacheEntry.fileTime);
|
||||
// type
|
||||
FWRITE(cacheEntry.type);
|
||||
// header
|
||||
size = cacheEntry.header.Name.size();
|
||||
FWRITE(size);
|
||||
@@ -237,7 +242,7 @@ bool CoreHasRomHeaderAndSettingsCached(std::filesystem::path file)
|
||||
return get_cache_entry_iter(file) != l_CacheEntries.end();
|
||||
}
|
||||
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader& header, CoreRomSettings& settings)
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomType& type, CoreRomHeader& header, CoreRomSettings& settings)
|
||||
{
|
||||
auto iter = get_cache_entry_iter(file);
|
||||
if (iter == l_CacheEntries.end())
|
||||
@@ -245,12 +250,13 @@ bool CoreGetCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader
|
||||
return false;
|
||||
}
|
||||
|
||||
type = (*iter).type;
|
||||
header = (*iter).header;
|
||||
settings = (*iter).settings;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader header, CoreRomSettings settings)
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings)
|
||||
{
|
||||
l_CacheEntry cacheEntry;
|
||||
|
||||
@@ -268,6 +274,7 @@ bool CoreAddCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader
|
||||
|
||||
cacheEntry.fileName = file;
|
||||
cacheEntry.fileTime = osal_files_get_file_time(file);
|
||||
cacheEntry.type = type;
|
||||
cacheEntry.header = header;
|
||||
cacheEntry.settings = settings;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "Rom.hpp"
|
||||
#include "RomHeader.hpp"
|
||||
#include "RomSettings.hpp"
|
||||
|
||||
@@ -30,11 +31,11 @@ bool CoreHasRomHeaderAndSettingsCached(std::filesystem::path file);
|
||||
|
||||
// returns whether retrieving the rom header & settings
|
||||
// for given filename succeeds
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader& header, CoreRomSettings& settings);
|
||||
bool CoreGetCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomType& type, CoreRomHeader& header, CoreRomSettings& settings);
|
||||
|
||||
// returns whether adding cached rom header & settings
|
||||
// for given filename succeeds
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomHeader header, CoreRomSettings settings);
|
||||
bool CoreAddCachedRomHeaderAndSettings(std::filesystem::path file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings);
|
||||
|
||||
// returns whether clearing rom header & settings cache
|
||||
// succeeds
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define CORE_VERSION "${GIT_VERSION}"
|
||||
|
||||
#ifndef PORTABLE_INSTALL
|
||||
#define CORE_INSTAlL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||
#define CORE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||
#endif // PORTABLE_INSTALL
|
||||
|
||||
#endif // CORE_CONFIG_HPP
|
||||
|
||||
@@ -30,18 +30,19 @@ static char l_CoreContextString[20];
|
||||
// Local Functions
|
||||
//
|
||||
|
||||
std::string find_core_lib(void)
|
||||
std::filesystem::path find_core_lib(void)
|
||||
{
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(CoreGetCoreDirectory()))
|
||||
{
|
||||
std::string path = entry.path().string();
|
||||
if (path.ends_with(OSAL_DYNLIB_LIB_EXT_STR))
|
||||
std::filesystem::path path = entry.path();
|
||||
if (path.has_extension() &&
|
||||
path.extension() == OSAL_DYNLIB_LIB_EXT_STR)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return std::filesystem::path();
|
||||
}
|
||||
|
||||
bool config_override_user_dirs(void)
|
||||
@@ -78,9 +79,9 @@ bool config_override_user_dirs(void)
|
||||
|
||||
bool CoreInit(void)
|
||||
{
|
||||
std::string error;
|
||||
std::string core_file;
|
||||
m64p_error m64p_ret;
|
||||
std::string error;
|
||||
std::filesystem::path core_file;
|
||||
m64p_error m64p_ret;
|
||||
bool ret = false;
|
||||
|
||||
// initialize context string
|
||||
@@ -94,7 +95,7 @@ bool CoreInit(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
l_CoreLibHandle = osal_dynlib_open(core_file.c_str());
|
||||
l_CoreLibHandle = osal_dynlib_open(core_file);
|
||||
if (l_CoreLibHandle == nullptr)
|
||||
{
|
||||
error = "osal_dynlib_open Failed: ";
|
||||
|
||||
@@ -123,7 +123,7 @@ std::filesystem::path CoreGetCoreDirectory(void)
|
||||
#ifdef PORTABLE_INSTALL
|
||||
directory = "Core";
|
||||
#else // Not Portable
|
||||
directory = CORE_INSTAlL_PREFIX;
|
||||
directory = CORE_INSTALL_PREFIX;
|
||||
directory += "/lib/RMG/Core";
|
||||
#endif // PORTABLE_INSTALL
|
||||
return directory;
|
||||
@@ -135,7 +135,7 @@ std::filesystem::path CoreGetPluginDirectory(void)
|
||||
#ifdef PORTABLE_INSTALL
|
||||
directory = "Plugin";
|
||||
#else // Not Portable
|
||||
directory = CORE_INSTAlL_PREFIX;
|
||||
directory = CORE_INSTALL_PREFIX;
|
||||
directory += "/lib/RMG/Plugin";
|
||||
#endif // PORTABLE_INSTALL
|
||||
return directory;
|
||||
@@ -233,7 +233,7 @@ std::filesystem::path CoreGetSharedDataDirectory(void)
|
||||
#ifdef PORTABLE_INSTALL
|
||||
directory = "Data";
|
||||
#else // Not Portable
|
||||
directory = CORE_INSTAlL_PREFIX;
|
||||
directory = CORE_INSTALL_PREFIX;
|
||||
directory += "/share/RMG";
|
||||
#endif // PORTABLE_INSTALL
|
||||
return directory;
|
||||
|
||||
@@ -157,6 +157,9 @@ bool CoreStartEmulation(std::filesystem::path n64rom, std::filesystem::path n64d
|
||||
// restore plugin settings
|
||||
CoreApplyPluginSettings();
|
||||
|
||||
// reset media loader state
|
||||
CoreResetMediaLoader();
|
||||
|
||||
#ifdef DISCORD_RPC
|
||||
CoreDiscordRpcUpdate(false);
|
||||
#endif // DISCORD_RPC
|
||||
|
||||
@@ -139,7 +139,12 @@ bool CoreSetupMediaLoader(void)
|
||||
return ret == M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
void CoreMediaLoaderSetDiskFile(std::filesystem::path ddRom)
|
||||
void CoreResetMediaLoader(void)
|
||||
{
|
||||
l_DdDiskFile = ddRom;
|
||||
l_DdRomFile = "";
|
||||
}
|
||||
|
||||
void CoreMediaLoaderSetDiskFile(std::filesystem::path disk)
|
||||
{
|
||||
l_DdDiskFile = disk;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
// sets up the medialoader
|
||||
bool CoreSetupMediaLoader(void);
|
||||
|
||||
// resets media loader state
|
||||
void CoreResetMediaLoader(void);
|
||||
|
||||
// sets the media loader disk file
|
||||
void CoreMediaLoaderSetDiskFile(std::filesystem::path ddRom);
|
||||
void CoreMediaLoaderSetDiskFile(std::filesystem::path disk);
|
||||
|
||||
#endif // CORE_MEDIALOADER_HPP
|
||||
|
||||
+216
-23
@@ -8,11 +8,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "Rom.hpp"
|
||||
#include "Directories.hpp"
|
||||
#include "Error.hpp"
|
||||
#include "MediaLoader.hpp"
|
||||
#include "m64p/Api.hpp"
|
||||
#include "RomSettings.hpp"
|
||||
#include "Cheats.hpp"
|
||||
#include "osal/osal_files.hpp"
|
||||
|
||||
#include <unzip.h>
|
||||
#include <fstream>
|
||||
@@ -30,8 +32,10 @@
|
||||
// Local Variables
|
||||
//
|
||||
|
||||
static bool l_HasRomOpen = false;
|
||||
static bool l_HasDisk = false;
|
||||
static bool l_HasRomOpen = false;
|
||||
static bool l_HasDisk = false;
|
||||
static bool l_HasExtractedDisk = false;
|
||||
static std::filesystem::path l_ExtractedDiskPath;
|
||||
|
||||
//
|
||||
// Local Functions
|
||||
@@ -51,25 +55,113 @@ static std::string to_lower_str(std::string str)
|
||||
return resultString;
|
||||
}
|
||||
|
||||
static bool read_zip_file(std::filesystem::path file, char** buf, int* size)
|
||||
static voidpf zlib_filefunc_open(voidpf opaque, const void* filename, int mode)
|
||||
{
|
||||
std::filesystem::path path = *(std::filesystem::path*)filename;
|
||||
|
||||
// we need a static filestream
|
||||
static std::ifstream fileStream;
|
||||
|
||||
// attempt to open file
|
||||
fileStream.open(path, std::ios::binary);
|
||||
if (!fileStream.is_open())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (voidpf)&fileStream;
|
||||
}
|
||||
|
||||
static uLong zlib_filefunc_read(voidpf opaque, voidpf stream, void* buf, uLong size)
|
||||
{
|
||||
std::ifstream* fileStream = (std::ifstream*)stream;
|
||||
fileStream->read((char*)buf, size);
|
||||
return fileStream->fail() ? 0 : size;
|
||||
}
|
||||
|
||||
static ZPOS64_T zlib_filefunc_tell(voidpf opaque, voidpf stream)
|
||||
{
|
||||
std::ifstream* fileStream = (std::ifstream*)stream;
|
||||
return fileStream->tellg();
|
||||
}
|
||||
|
||||
static long zlib_filefunc_seek(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
|
||||
{
|
||||
std::ifstream* fileStream = (std::ifstream*)stream;
|
||||
std::ios_base::seekdir seekOrigin;
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
seekOrigin = std::ios::cur;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
seekOrigin = std::ios::end;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET:
|
||||
seekOrigin = std::ios::beg;
|
||||
break;
|
||||
}
|
||||
|
||||
fileStream->seekg(offset, seekOrigin);
|
||||
return fileStream->fail() ? -1 : 0;
|
||||
}
|
||||
|
||||
static int zlib_filefunc_close(voidpf opaque, voidpf stream)
|
||||
{
|
||||
std::ifstream* fileStream = (std::ifstream*)stream;
|
||||
fileStream->close();
|
||||
return fileStream->fail() ? -1 : 0;
|
||||
}
|
||||
|
||||
static int zlib_filefunc_testerror(voidpf opaque, voidpf stream)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
static bool read_zip_file(std::filesystem::path file, std::filesystem::path* extractedFileName, bool* isDisk, char** buf, int* size)
|
||||
{
|
||||
std::string error;
|
||||
std::fstream fileStream;
|
||||
int fileStreamLen;
|
||||
char* fileStreamBuf;
|
||||
|
||||
unzFile zipFile;
|
||||
unz_global_info zipInfo;
|
||||
unzFile zipFile;
|
||||
unz_global_info64 zipInfo;
|
||||
|
||||
zipFile = unzOpen(file.string().c_str());
|
||||
zlib_filefunc64_def filefuncs;
|
||||
filefuncs.zopen64_file = zlib_filefunc_open;
|
||||
filefuncs.zread_file = zlib_filefunc_read;
|
||||
filefuncs.zwrite_file = nullptr;
|
||||
filefuncs.ztell64_file = zlib_filefunc_tell;
|
||||
filefuncs.zseek64_file = zlib_filefunc_seek;
|
||||
filefuncs.zclose_file = zlib_filefunc_close;
|
||||
filefuncs.zerror_file = zlib_filefunc_testerror;
|
||||
filefuncs.opaque = nullptr;
|
||||
|
||||
zipFile = unzOpen2_64((const void*)&file, &filefuncs);
|
||||
if (zipFile == nullptr)
|
||||
{
|
||||
error = "read_zip_file: unzOpen Failed!";
|
||||
if (errno == 0)
|
||||
{
|
||||
error = "read_zip_file: unzOpen Failed!";
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "read_zip_file: unzOpen Failed: ";
|
||||
error += "failed to open file: ";
|
||||
error += strerror(errno);
|
||||
error += " (";
|
||||
error += std::to_string(errno);
|
||||
error += ")";
|
||||
}
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unzGetGlobalInfo(zipFile, &zipInfo) != UNZ_OK)
|
||||
if (unzGetGlobalInfo64(zipFile, &zipInfo) != UNZ_OK)
|
||||
{
|
||||
error = "read_zip_file: unzGetGlobalInfo Failed!";
|
||||
CoreSetError(error);
|
||||
@@ -95,7 +187,9 @@ static bool read_zip_file(std::filesystem::path file, char** buf, int* size)
|
||||
fileExtension = to_lower_str(fileExtension);
|
||||
if (fileExtension == ".z64" ||
|
||||
fileExtension == ".v64" ||
|
||||
fileExtension == ".n64")
|
||||
fileExtension == ".n64" ||
|
||||
fileExtension == ".ndd" ||
|
||||
fileExtension == ".d64")
|
||||
{
|
||||
char* buffer;
|
||||
char* outBuffer;
|
||||
@@ -167,8 +261,10 @@ static bool read_zip_file(std::filesystem::path file, char** buf, int* size)
|
||||
}
|
||||
} while (bytes_read > 0);
|
||||
|
||||
*size = total_bytes_read;
|
||||
*buf = outBuffer;
|
||||
*size = total_bytes_read;
|
||||
*buf = outBuffer;
|
||||
*extractedFileName = fileNamePath;
|
||||
*isDisk = (fileExtension == ".ndd" || fileExtension == ".d64");
|
||||
unzCloseCurrentFile(zipFile);
|
||||
unzClose(zipFile);
|
||||
free(buffer);
|
||||
@@ -199,13 +295,13 @@ static bool read_zip_file(std::filesystem::path file, char** buf, int* size)
|
||||
|
||||
static bool read_raw_file(std::filesystem::path file, char** buf, int* size)
|
||||
{
|
||||
std::string error;
|
||||
std::fstream fileStream;
|
||||
int fileStreamLen;
|
||||
char* fileStreamBuf;
|
||||
std::string error;
|
||||
std::ifstream fileStream;
|
||||
int fileStreamLen;
|
||||
char* fileStreamBuf;
|
||||
|
||||
// attempt to open file
|
||||
fileStream.open(file);
|
||||
fileStream.open(file, std::ios::binary);
|
||||
if (!fileStream.is_open())
|
||||
{
|
||||
error = "read_raw_file Failed: ";
|
||||
@@ -245,6 +341,32 @@ static bool read_raw_file(std::filesystem::path file, char** buf, int* size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write_file(std::filesystem::path file, char* buf, int size)
|
||||
{
|
||||
std::string error;
|
||||
std::ofstream fileStream;
|
||||
|
||||
// attempt to open file
|
||||
fileStream.open(file, std::ios::binary);
|
||||
if (!fileStream.is_open())
|
||||
{
|
||||
error = "write_file Failed: ";
|
||||
error += "failed to open file: ";
|
||||
error += strerror(errno);
|
||||
error += " (";
|
||||
error += std::to_string(errno);
|
||||
error += ")";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// write buffer to file
|
||||
fileStream.write(buf, size);
|
||||
|
||||
fileStream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
@@ -253,8 +375,8 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
{
|
||||
std::string error;
|
||||
m64p_error ret;
|
||||
char* buf;
|
||||
int buf_size;
|
||||
char* buf = nullptr;
|
||||
int buf_size = 0;
|
||||
std::string file_extension;
|
||||
|
||||
if (!m64p::Core.IsHooked())
|
||||
@@ -275,18 +397,62 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
|
||||
if (file_extension == ".zip")
|
||||
{
|
||||
if (!read_zip_file(file, &buf, &buf_size))
|
||||
std::filesystem::path extracted_file;
|
||||
bool is_disk = false;
|
||||
|
||||
if (!read_zip_file(file, &extracted_file, &is_disk, &buf, &buf_size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
l_HasDisk = false;
|
||||
if (is_disk)
|
||||
{
|
||||
std::filesystem::path disk_file;
|
||||
disk_file = CoreGetUserCacheDirectory();
|
||||
disk_file += "/extracted_disks/";
|
||||
disk_file += extracted_file.filename();
|
||||
|
||||
// attempt to create extraction directory
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::exists(disk_file.parent_path()))
|
||||
{
|
||||
if (!std::filesystem::create_directory(disk_file.parent_path()))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "CoreOpenRom Failed: ";
|
||||
error += "Failed to create \"";
|
||||
error += disk_file.parent_path().string();
|
||||
error += "\"!";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// attempt to write temporary file
|
||||
if (!write_file(disk_file, buf, buf_size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CoreMediaLoaderSetDiskFile(disk_file);
|
||||
|
||||
l_ExtractedDiskPath = disk_file;
|
||||
}
|
||||
|
||||
l_HasDisk = is_disk;
|
||||
l_HasExtractedDisk = is_disk;
|
||||
}
|
||||
else if (file_extension == ".d64" ||
|
||||
file_extension == ".ndd")
|
||||
{
|
||||
CoreMediaLoaderSetDiskFile(file);
|
||||
l_HasDisk = true;
|
||||
l_HasDisk = true;
|
||||
l_HasExtractedDisk = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -295,7 +461,8 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
return false;
|
||||
}
|
||||
|
||||
l_HasDisk = false;
|
||||
l_HasDisk = false;
|
||||
l_HasExtractedDisk = false;
|
||||
}
|
||||
|
||||
if (l_HasDisk)
|
||||
@@ -307,6 +474,7 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
{
|
||||
ret = m64p::Core.DoCommand(M64CMD_ROM_OPEN, buf_size, buf);
|
||||
error = "CoreOpenRom: m64p::Core.DoCommand(M64CMD_ROM_OPEN) Failed: ";
|
||||
free(buf);
|
||||
}
|
||||
|
||||
if (ret != M64ERR_SUCCESS)
|
||||
@@ -315,7 +483,6 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
CoreSetError(error);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
l_HasRomOpen = (ret == M64ERR_SUCCESS);
|
||||
|
||||
if (l_HasRomOpen)
|
||||
@@ -383,6 +550,32 @@ bool CoreCloseRom(void)
|
||||
// clear default ROM settings
|
||||
CoreClearCurrentDefaultRomSettings();
|
||||
|
||||
// if removing the temporary extracted disk file
|
||||
// fails, then we shouldn't break the state of
|
||||
// whether we currently have an open ROM/disk,
|
||||
// so we can safely say the ROM/disk isn't open
|
||||
// anymore here
|
||||
l_HasRomOpen = false;
|
||||
|
||||
// attempt to clean temporary extracted disk file
|
||||
if (l_HasExtractedDisk)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::remove(l_ExtractedDiskPath))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "CoreCloseRom: Failed to remove \"";
|
||||
error += l_ExtractedDiskPath.string();
|
||||
error += "\"!";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
enum class CoreRomType
|
||||
{
|
||||
Cartridge,
|
||||
Disk
|
||||
Cartridge = 0,
|
||||
Disk = 1
|
||||
};
|
||||
|
||||
// opens the given file as ROM
|
||||
|
||||
@@ -140,9 +140,6 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::GUI_SettingsDialogHeight:
|
||||
setting = {SETTING_SECTION_GUI, "SettingsDialogHeight", 0};
|
||||
break;
|
||||
case SettingsID::GUI_AllowManualResizing:
|
||||
setting = {SETTING_SECTION_GUI, "AllowManualResizing", true};
|
||||
break;
|
||||
case SettingsID::GUI_HideCursorInEmulation:
|
||||
setting = {SETTING_SECTION_GUI, "HideCursorInEmulation", false};
|
||||
break;
|
||||
@@ -164,17 +161,32 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::GUI_ShowVerboseLogMessages:
|
||||
setting = {SETTING_SECTION_GUI, "ShowVerboseLogMessages", false};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayEnabled:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayEnabled", true};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayLocation:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayLocation", 0};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayPaddingX:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayPaddingX", 20};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayPaddingY:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayPaddingY", 20};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayOpacity:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayOpacity", 0.5f};
|
||||
break;
|
||||
case SettingsID::GUI_OnScreenDisplayDuration:
|
||||
setting = {SETTING_SECTION_GUI, "OnScreenDisplayDuration", 3};
|
||||
break;
|
||||
case SettingsID::GUI_Toolbar:
|
||||
setting = {SETTING_SECTION_GUI, "Toolbar", true};
|
||||
break;
|
||||
case SettingsID::GUI_StatusBar:
|
||||
setting = {SETTING_SECTION_GUI, "StatusBar", true};
|
||||
break;
|
||||
case SettingsID::GUI_Style:
|
||||
setting = {SETTING_SECTION_GUI, "Style", ""};
|
||||
break;
|
||||
case SettingsID::GUI_IconTheme:
|
||||
setting = {SETTING_SECTION_GUI, "IconTheme", "black"};
|
||||
case SettingsID::GUI_Theme:
|
||||
setting = {SETTING_SECTION_GUI, "Theme", "Native"};
|
||||
break;
|
||||
case SettingsID::GUI_CheckForUpdates:
|
||||
setting = {SETTING_SECTION_GUI, "CheckForUpdates", true};
|
||||
@@ -422,6 +434,36 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::KeyBinding_GSButton:
|
||||
setting = {SETTING_SECTION_KEYBIND, "GSButton", "F9"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot0:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot0", "Ctrl+0"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot1:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot1", "Ctrl+1"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot2:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot2", "Ctrl+2"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot3:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot3", "Ctrl+3"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot4:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot4", "Ctrl+4"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot5:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot5", "Ctrl+5"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot6:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot6", "Ctrl+6"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot7:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot7", "Ctrl+7"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot8:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot8", "Ctrl+8"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_SaveStateSlot9:
|
||||
setting = {SETTING_SECTION_KEYBIND, "SaveStateSlot9", "Ctrl+9"};
|
||||
break;
|
||||
case SettingsID::KeyBinding_Fullscreen:
|
||||
setting = {SETTING_SECTION_KEYBIND, "Fullscreen", "Alt+Return"};
|
||||
break;
|
||||
@@ -435,6 +477,9 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::RomBrowser_Geometry:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "Geometry", ""};
|
||||
break;
|
||||
case SettingsID::RomBrowser_Maximized:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "Maximized", false};
|
||||
break;
|
||||
case SettingsID::RomBrowser_Recursive:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "Recursive", true};
|
||||
break;
|
||||
@@ -447,6 +492,9 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::RomBrowser_ColumnSizes:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "ColumnSizes", std::vector<int>({-1, -1, -1})};
|
||||
break;
|
||||
case SettingsID::RomBrowser_SortAfterSearch:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "SortAfterSearch", true};
|
||||
break;
|
||||
case SettingsID::RomBrowser_ViewMode:
|
||||
setting = {SETTING_SECTION_ROMBROWSER, "ViewMode", 0};
|
||||
break;
|
||||
@@ -525,9 +573,6 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::Input_RemoveDuplicateMappings:
|
||||
setting = {"", "RemoveDuplicateMappings"};
|
||||
break;
|
||||
case SettingsID::Input_InvertAxis:
|
||||
setting = {"", "InvertAxis"};
|
||||
break;
|
||||
case SettingsID::Input_A_InputType:
|
||||
setting = {"", "A_InputType"};
|
||||
break;
|
||||
@@ -950,6 +995,94 @@ static bool config_option_default_set(std::string section, std::string key, m64p
|
||||
return ret == M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static bool int_list_to_string(std::vector<int> intList, std::string& string)
|
||||
{
|
||||
for (int i = 0; i < intList.size(); i++)
|
||||
{
|
||||
int num = intList.at(i);
|
||||
string += std::to_string(num);
|
||||
|
||||
// don't add seperator at end
|
||||
// of the list
|
||||
if (i < (intList.size() - 1))
|
||||
{
|
||||
string += ";";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool string_to_int_list(std::string string, std::vector<int>& intList)
|
||||
{
|
||||
std::string error;
|
||||
|
||||
// split string by ';'
|
||||
// and append list with each item
|
||||
std::stringstream value_str_stream(string);
|
||||
std::string tmp_str;
|
||||
while (std::getline(value_str_stream, tmp_str, ';'))
|
||||
{
|
||||
try
|
||||
{
|
||||
intList.emplace_back(std::stoi(tmp_str));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "string_to_int_list: std::stroi threw an exception!";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool string_list_to_string(std::vector<std::string> stringList, std::string& string)
|
||||
{
|
||||
std::string error;
|
||||
|
||||
for (int i = 0; i < stringList.size(); i++)
|
||||
{
|
||||
std::string str = stringList.at(i);
|
||||
|
||||
// ensure the string doesn't contain
|
||||
// the separator character
|
||||
if (str.find(";") != std::string::npos)
|
||||
{
|
||||
error = "string_list_to_string: string cannot contain ';'!";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
string += str;
|
||||
|
||||
// don't add separator at end
|
||||
// of the list
|
||||
if (i < (stringList.size() - 1))
|
||||
{
|
||||
string += ";";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool string_to_string_list(std::string string, std::vector<std::string>& stringList)
|
||||
{
|
||||
std::string error;
|
||||
|
||||
// split string by ';'
|
||||
// and append list with each item
|
||||
std::stringstream value_str_stream(string);
|
||||
std::string tmp_str;
|
||||
while (std::getline(value_str_stream, tmp_str, ';'))
|
||||
{
|
||||
stringList.emplace_back(tmp_str);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
@@ -1064,7 +1197,7 @@ bool CoreSettingsSetupDefaults(void)
|
||||
ret = config_option_default_set(setting.Section, setting.Key, M64TYPE_BOOL, &setting.DefaultValue.boolValue, setting.Description.c_str());
|
||||
break;
|
||||
case M64TYPE_FLOAT:
|
||||
ret = config_option_default_set(setting.Section, setting.Key, M64TYPE_FLOAT, &setting.DefaultValue.intValue, setting.Description.c_str());
|
||||
ret = config_option_default_set(setting.Section, setting.Key, M64TYPE_FLOAT, &setting.DefaultValue.floatValue, setting.Description.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1148,10 +1281,19 @@ bool CoreSettingsSetValue(SettingsID settingId, std::string value)
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::vector<int> value)
|
||||
{
|
||||
std::string value_str;
|
||||
for (const int& num : value)
|
||||
if (!int_list_to_string(value, value_str))
|
||||
{
|
||||
value_str += std::to_string(num);
|
||||
value_str += ";";
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(settingId, value_str);
|
||||
}
|
||||
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::vector<std::string> value)
|
||||
{
|
||||
std::string value_str;
|
||||
if (!string_list_to_string(value, value_str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(settingId, value_str);
|
||||
}
|
||||
@@ -1184,10 +1326,19 @@ bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::string
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::vector<int> value)
|
||||
{
|
||||
std::string value_str;
|
||||
for (const int& num : value)
|
||||
if (!int_list_to_string(value, value_str))
|
||||
{
|
||||
value_str += std::to_string(num);
|
||||
value_str += ";";
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(settingId, section, value_str);
|
||||
}
|
||||
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::vector<std::string> value)
|
||||
{
|
||||
std::string value_str;
|
||||
if (!string_list_to_string(value, value_str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(settingId, section, value_str);
|
||||
}
|
||||
@@ -1216,10 +1367,19 @@ bool CoreSettingsSetValue(std::string section, std::string key, std::string valu
|
||||
bool CoreSettingsSetValue(std::string section, std::string key, std::vector<int> value)
|
||||
{
|
||||
std::string value_str;
|
||||
for (const int& num : value)
|
||||
if (!int_list_to_string(value, value_str))
|
||||
{
|
||||
value_str += std::to_string(num);
|
||||
value_str += ";";
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(section, key, value_str);
|
||||
}
|
||||
|
||||
bool CoreSettingsSetValue(std::string section, std::string key, std::vector<std::string> value)
|
||||
{
|
||||
std::string value_str;
|
||||
if (!string_list_to_string(value, value_str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CoreSettingsSetValue(section, key, value_str);
|
||||
}
|
||||
@@ -1292,6 +1452,12 @@ std::vector<int> CoreSettingsGetIntListValue(SettingsID settingId)
|
||||
return CoreSettingsGetIntListValue(settingId, setting.Section);
|
||||
}
|
||||
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(SettingsID settingId)
|
||||
{
|
||||
l_Setting setting = get_setting(settingId);
|
||||
return CoreSettingsGetStringListValue(settingId, setting.Section);
|
||||
}
|
||||
|
||||
int CoreSettingsGetIntValue(SettingsID settingId, std::string section)
|
||||
{
|
||||
l_Setting setting = get_setting(settingId);
|
||||
@@ -1332,25 +1498,31 @@ std::vector<int> CoreSettingsGetIntListValue(SettingsID settingId, std::string s
|
||||
std::string value_str;
|
||||
value_str = CoreSettingsGetStringValue(settingId, section);
|
||||
|
||||
// split string by ';'
|
||||
// and append list with each item
|
||||
std::stringstream value_str_stream(value_str);
|
||||
std::string tmp_str;
|
||||
while (std::getline(value_str_stream, tmp_str, ';'))
|
||||
if (!string_to_int_list(value_str, value))
|
||||
{
|
||||
try
|
||||
{
|
||||
value.emplace_back(std::stoi(tmp_str));
|
||||
}
|
||||
catch (...)
|
||||
{ // ignore exception
|
||||
continue;
|
||||
}
|
||||
return std::vector<int>();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(SettingsID settingId, std::string section)
|
||||
{
|
||||
l_Setting setting = get_setting(settingId);
|
||||
std::vector<std::string> value;
|
||||
|
||||
std::string value_str;
|
||||
value_str = CoreSettingsGetStringValue(settingId, section);
|
||||
|
||||
if (!string_to_string_list(value_str, value))
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int CoreSettingsGetIntValue(std::string section, std::string key, int defaultValue)
|
||||
{
|
||||
int value = defaultValue;
|
||||
@@ -1379,27 +1551,31 @@ std::string CoreSettingsGetStringValue(std::string section, std::string key)
|
||||
return std::string(value);
|
||||
}
|
||||
|
||||
std::vector<int> CoreSettingsGetIntListValue(std::string section, std::string key, std::vector<int> defaultValue)
|
||||
std::vector<int> CoreSettingsGetIntListValue(std::string section, std::string key)
|
||||
{
|
||||
std::vector<int> value;
|
||||
|
||||
std::string value_str;
|
||||
value_str = CoreSettingsGetStringValue(section, key);
|
||||
|
||||
// split string by ';'
|
||||
// and append list with each item
|
||||
std::stringstream value_str_stream(value_str);
|
||||
std::string tmp_str;
|
||||
while (std::getline(value_str_stream, tmp_str, ';'))
|
||||
if (!string_to_int_list(value_str, value))
|
||||
{
|
||||
try
|
||||
{
|
||||
value.emplace_back(std::stoi(tmp_str));
|
||||
}
|
||||
catch (...)
|
||||
{ // ignore exception
|
||||
continue;
|
||||
}
|
||||
return std::vector<int>();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(std::string section, std::string key)
|
||||
{
|
||||
std::vector<std::string> value;
|
||||
|
||||
std::string value_str;
|
||||
value_str = CoreSettingsGetStringValue(section, key);
|
||||
|
||||
if (!string_to_string_list(value_str, value))
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
@@ -43,6 +43,8 @@ bool CoreSettingsSetValue(SettingsID settingId, float value);
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string value);
|
||||
// sets setting as int list value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::vector<int> value);
|
||||
// sets setting as string list value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::vector<std::string> value);
|
||||
|
||||
// sets setting in section as int value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, int value);
|
||||
@@ -54,6 +56,8 @@ bool CoreSettingsSetValue(SettingsID settingId, std::string section, float value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::string value);
|
||||
// sets setting in section as int list value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::vector<int> value);
|
||||
// sets setting as section as string list value
|
||||
bool CoreSettingsSetValue(SettingsID settingId, std::string section, std::vector<std::string> value);
|
||||
|
||||
#ifdef CORE_INTERNAL
|
||||
// sets key in section as int value
|
||||
@@ -66,6 +70,8 @@ bool CoreSettingsSetValue(std::string section, std::string key, float value);
|
||||
bool CoreSettingsSetValue(std::string section, std::string key, std::string value);
|
||||
// sets key in section as int list value
|
||||
bool CoreSettingsSetValue(std::string section, std::string key, std::vector<int> value);
|
||||
// sets key in section as string list value
|
||||
bool CoreSettingsSetValue(std::string section, std::string key, std::vector<std::string> value);
|
||||
#endif // CORE_INTERNAL
|
||||
|
||||
// retrieves default setting as int
|
||||
@@ -78,6 +84,8 @@ float CoreSettingsGetDefaultFloatValue(SettingsID settingId);
|
||||
std::string CoreSettingsGetDefaultStringValue(SettingsID settingId);
|
||||
// retrieves default setting as int list
|
||||
std::vector<int> CoreSettingsGetDefaultIntListValue(SettingsID settingId);
|
||||
// retrieves default setting as string list
|
||||
std::vector<std::string> CoreSettingsGetDefaultStringListValue(SettingsID settingId);
|
||||
|
||||
// retrieves setting as int
|
||||
int CoreSettingsGetIntValue(SettingsID settingId);
|
||||
@@ -89,6 +97,8 @@ float CoreSettingsGetFloatValue(SettingsID settingId);
|
||||
std::string CoreSettingsGetStringValue(SettingsID settingId);
|
||||
// retrieves setting as int list
|
||||
std::vector<int> CoreSettingsGetIntListValue(SettingsID settingId);
|
||||
// retrieves setting as string list
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(SettingsID settingId);
|
||||
|
||||
// retrieves setting in section as int
|
||||
int CoreSettingsGetIntValue(SettingsID settingId, std::string section);
|
||||
@@ -100,6 +110,8 @@ float CoreSettingsGetFloatValue(SettingsID settingId, std::string section);
|
||||
std::string CoreSettingsGetStringValue(SettingsID settingId, std::string section);
|
||||
// retrieves setting in section as int list
|
||||
std::vector<int> CoreSettingsGetIntListValue(SettingsID settingId, std::string section);
|
||||
// retrieves setting in section as string list
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(SettingsID settingId, std::string section);
|
||||
|
||||
#ifdef CORE_INTERNAL
|
||||
// retrieves key in section as int
|
||||
@@ -112,6 +124,8 @@ float CoreSettingsGetFloatValue(std::string section, std::string key, float defa
|
||||
std::string CoreSettingsGetStringValue(std::string section, std::string key);
|
||||
// retrieves key in section as int list
|
||||
std::vector<int> CoreSettingsGetIntListValue(std::string section, std::string key);
|
||||
// retrieves key in section as string list
|
||||
std::vector<std::string> CoreSettingsGetStringListValue(std::string section, std::string key);
|
||||
#endif // CORE_INTERNAL
|
||||
|
||||
#endif // CORE_SETTINGS_HPP
|
||||
|
||||
@@ -6,7 +6,6 @@ enum class SettingsID
|
||||
// GUI Settings
|
||||
GUI_SettingsDialogWidth = 0,
|
||||
GUI_SettingsDialogHeight,
|
||||
GUI_AllowManualResizing,
|
||||
GUI_HideCursorInEmulation,
|
||||
GUI_HideCursorInFullscreenEmulation,
|
||||
GUI_StatusbarMessageDuration,
|
||||
@@ -14,10 +13,15 @@ enum class SettingsID
|
||||
GUI_ResumeEmulationOnFocus,
|
||||
GUI_AutomaticFullscreen,
|
||||
GUI_ShowVerboseLogMessages,
|
||||
GUI_OnScreenDisplayEnabled,
|
||||
GUI_OnScreenDisplayLocation,
|
||||
GUI_OnScreenDisplayPaddingX,
|
||||
GUI_OnScreenDisplayPaddingY,
|
||||
GUI_OnScreenDisplayOpacity,
|
||||
GUI_OnScreenDisplayDuration,
|
||||
GUI_Toolbar,
|
||||
GUI_StatusBar,
|
||||
GUI_Style,
|
||||
GUI_IconTheme,
|
||||
GUI_Theme,
|
||||
GUI_CheckForUpdates,
|
||||
GUI_DiscordRpc,
|
||||
GUI_Version,
|
||||
@@ -110,16 +114,28 @@ enum class SettingsID
|
||||
KeyBinding_Load,
|
||||
KeyBinding_Cheats,
|
||||
KeyBinding_GSButton,
|
||||
KeyBinding_SaveStateSlot0,
|
||||
KeyBinding_SaveStateSlot1,
|
||||
KeyBinding_SaveStateSlot2,
|
||||
KeyBinding_SaveStateSlot3,
|
||||
KeyBinding_SaveStateSlot4,
|
||||
KeyBinding_SaveStateSlot5,
|
||||
KeyBinding_SaveStateSlot6,
|
||||
KeyBinding_SaveStateSlot7,
|
||||
KeyBinding_SaveStateSlot8,
|
||||
KeyBinding_SaveStateSlot9,
|
||||
KeyBinding_Fullscreen,
|
||||
KeyBinding_Settings,
|
||||
|
||||
// RomBrowser Settings
|
||||
RomBrowser_Directory,
|
||||
RomBrowser_Geometry,
|
||||
RomBrowser_Maximized,
|
||||
RomBrowser_Recursive,
|
||||
RomBrowser_MaxItems,
|
||||
RomBrowser_Columns,
|
||||
RomBrowser_ColumnSizes,
|
||||
RomBrowser_SortAfterSearch,
|
||||
RomBrowser_ViewMode,
|
||||
RomBrowser_ListViewSortSection,
|
||||
RomBrowser_ListViewSortOrder,
|
||||
@@ -151,7 +167,6 @@ enum class SettingsID
|
||||
Input_GameboyRom,
|
||||
Input_GameboySave,
|
||||
Input_RemoveDuplicateMappings,
|
||||
Input_InvertAxis,
|
||||
Input_A_InputType,
|
||||
Input_A_Name,
|
||||
Input_A_Data,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define OSAL_DYNLIB_HPP
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@@ -25,11 +26,11 @@ typedef void* osal_dynlib_lib_sym;
|
||||
|
||||
// returns library handle for given filename,
|
||||
// return nullptr when invalid library
|
||||
osal_dynlib_lib_handle osal_dynlib_open(const char *);
|
||||
osal_dynlib_lib_handle osal_dynlib_open(std::filesystem::path path);
|
||||
|
||||
// retrieves symbol handle for given library
|
||||
// handle, returns nullptr when not found
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle, const char *);
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle, const char* symbol);
|
||||
|
||||
// closes library handle
|
||||
void osal_dynlib_close(osal_dynlib_lib_handle);
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
osal_dynlib_lib_handle osal_dynlib_open(const char* file)
|
||||
osal_dynlib_lib_handle osal_dynlib_open(std::filesystem::path path)
|
||||
{
|
||||
return dlopen(file, RTLD_LAZY);
|
||||
return dlopen(path.string().c_str(), RTLD_LAZY);
|
||||
}
|
||||
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle handle, const char *sym)
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle handle, const char* symbol)
|
||||
{
|
||||
return dlsym(handle, sym);
|
||||
return dlsym(handle, symbol);
|
||||
}
|
||||
|
||||
void osal_dynlib_close(osal_dynlib_lib_handle handle)
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
*/
|
||||
#include "osal_dynlib.hpp"
|
||||
|
||||
osal_dynlib_lib_handle osal_dynlib_open(const char* file)
|
||||
osal_dynlib_lib_handle osal_dynlib_open(std::filesystem::path path)
|
||||
{
|
||||
return LoadLibrary(file);
|
||||
return LoadLibraryW(path.wstring().c_str());
|
||||
}
|
||||
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle handle, const char *sym)
|
||||
osal_dynlib_lib_sym osal_dynlib_sym(osal_dynlib_lib_handle handle, const char* symbol)
|
||||
{
|
||||
return GetProcAddress(handle, sym);
|
||||
return GetProcAddress(handle, symbol);
|
||||
}
|
||||
|
||||
void osal_dynlib_close(osal_dynlib_lib_handle handle)
|
||||
|
||||
@@ -17,8 +17,9 @@ osal_files_file_time osal_files_get_file_time(std::filesystem::path file)
|
||||
BOOL ret;
|
||||
HANDLE file_handle;
|
||||
FILETIME file_time;
|
||||
ULARGE_INTEGER ularge_int;
|
||||
|
||||
file_handle = CreateFileA(file.string().c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
file_handle = CreateFileW(file.wstring().c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return -1;
|
||||
@@ -36,7 +37,8 @@ osal_files_file_time osal_files_get_file_time(std::filesystem::path file)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// this is probably incorrect but it doesn't matter
|
||||
// for our use-case
|
||||
return file_time.dwLowDateTime + file_time.dwHighDateTime;
|
||||
ularge_int.LowPart = file_time.dwLowDateTime;
|
||||
ularge_int.HighPart = file_time.dwHighDateTime;
|
||||
|
||||
return ularge_int.QuadPart;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
# disable lib prefix
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
|
||||
find_package(${QT_VERSION} COMPONENTS Gui Widgets Core Svg REQUIRED)
|
||||
find_package(Qt6 COMPONENTS Gui Widgets Core Svg REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SDL2 REQUIRED sdl2)
|
||||
@@ -17,7 +17,9 @@ set(RMG_INPUT_SOURCES
|
||||
UserInterface/Widget/ControllerWidget.ui
|
||||
UserInterface/Widget/ControllerWidget.cpp
|
||||
UserInterface/Widget/ControllerImageWidget.cpp
|
||||
UserInterface/Widget/CustomButton.cpp
|
||||
UserInterface/Widget/MappingButton.cpp
|
||||
UserInterface/Widget/AddMappingButton.cpp
|
||||
UserInterface/Widget/RemoveMappingButton.cpp
|
||||
UserInterface/EventFilter.cpp
|
||||
UserInterface/OptionsDialog.ui
|
||||
UserInterface/OptionsDialog.cpp
|
||||
@@ -41,4 +43,4 @@ target_include_directories(RMG-Input PRIVATE
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(RMG-Input ${QT_VERSION}::Gui ${QT_VERSION}::Widgets ${QT_VERSION}::Svg)
|
||||
target_link_libraries(RMG-Input Qt6::Gui Qt6::Widgets Qt6::Svg)
|
||||
|
||||
@@ -111,9 +111,11 @@ void MainDialog::openInputDevice(QString deviceName, int deviceNum)
|
||||
currentJoystick = SDL_JoystickOpen(deviceNum);
|
||||
currentController = nullptr;
|
||||
}
|
||||
|
||||
currentDeviceNum = deviceNum;
|
||||
joystickId = SDL_JoystickGetDeviceInstanceID(deviceNum);
|
||||
controllerWidget->SetCurrentJoystickID(joystickId);
|
||||
controllerWidget->SetIsCurrentJoystickGameController(currentController != nullptr);
|
||||
}
|
||||
|
||||
void MainDialog::closeInputDevice()
|
||||
|
||||
@@ -24,7 +24,6 @@ OptionsDialog::OptionsDialog(QWidget* parent, OptionsDialogSettings settings) :
|
||||
this->gameboyRomLineEdit->setText(QString::fromStdString(settings.GameboyRom));
|
||||
this->gameboySaveLineEdit->setText(QString::fromStdString(settings.GameboySave));
|
||||
this->removeDuplicateMappingsCheckbox->setChecked(settings.RemoveDuplicateMappings);
|
||||
this->invertAxisCheckBox->setChecked(settings.InvertAxis);
|
||||
|
||||
if (!CoreIsEmulationRunning() && !CoreIsEmulationPaused())
|
||||
{
|
||||
@@ -84,7 +83,6 @@ void OptionsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
this->settings.GameboyRom = this->gameboyRomLineEdit->text().toStdString();
|
||||
this->settings.GameboySave = this->gameboySaveLineEdit->text().toStdString();
|
||||
this->settings.RemoveDuplicateMappings = this->removeDuplicateMappingsCheckbox->isChecked();
|
||||
this->settings.InvertAxis = this->invertAxisCheckBox->isChecked();
|
||||
}
|
||||
|
||||
this->accept();
|
||||
|
||||
@@ -24,7 +24,6 @@ struct OptionsDialogSettings
|
||||
|
||||
// UI settings
|
||||
bool RemoveDuplicateMappings = false;
|
||||
bool InvertAxis = false;
|
||||
};
|
||||
|
||||
namespace UserInterface
|
||||
|
||||
@@ -202,13 +202,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="invertAxisCheckBox">
|
||||
<property name="text">
|
||||
<string>Invert Axes Mapped To LRZ</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "AddMappingButton.hpp"
|
||||
#include "ControllerWidget.hpp"
|
||||
#include "MappingButton.hpp"
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
AddMappingButton::AddMappingButton(QWidget* parent) : QPushButton(parent)
|
||||
{
|
||||
}
|
||||
|
||||
AddMappingButton::~AddMappingButton()
|
||||
{
|
||||
}
|
||||
|
||||
void AddMappingButton::Initialize(ControllerWidget* widget, MappingButton* button)
|
||||
{
|
||||
this->controllerWidget = widget;
|
||||
this->mappingButton = button;
|
||||
|
||||
connect(this, &QPushButton::released, [=]
|
||||
{
|
||||
emit this->controllerWidget->on_AddMappingButton_Released(this->mappingButton);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ADDMAPPINGBUTTON_HPP
|
||||
#define ADDMAPPINGBUTTON_HPP
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace Widget
|
||||
{
|
||||
|
||||
// we can't include ControllerWidget.hpp
|
||||
// because that header includes this header,
|
||||
// so forward-declare it to prevent issues
|
||||
class ControllerWidget;
|
||||
class MappingButton;
|
||||
|
||||
class AddMappingButton : public QPushButton
|
||||
{
|
||||
private:
|
||||
ControllerWidget* controllerWidget = nullptr;
|
||||
MappingButton* mappingButton = nullptr;
|
||||
|
||||
public:
|
||||
AddMappingButton(QWidget* parent);
|
||||
~AddMappingButton();
|
||||
|
||||
void Initialize(ControllerWidget* widget, MappingButton* button);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ADDMAPPINGBUTTON_HPP
|
||||
@@ -91,7 +91,7 @@ ControllerWidget::ControllerWidget(QWidget* parent, EventFilter* eventFilter) :
|
||||
{ this->analogStickRightButton, SettingsID::Input_AnalogStickRight_InputType, SettingsID::Input_AnalogStickRight_Name, SettingsID::Input_AnalogStickRight_Data, SettingsID::Input_AnalogStickRight_ExtraData },
|
||||
});
|
||||
|
||||
CustomButton* buttonList[] =
|
||||
MappingButton* buttonList[] =
|
||||
{
|
||||
// dpad
|
||||
this->dpadUpButton,
|
||||
@@ -133,37 +133,50 @@ ControllerWidget::~ControllerWidget()
|
||||
|
||||
void ControllerWidget::initializeButtons()
|
||||
{
|
||||
CustomButton* buttonList[] =
|
||||
struct
|
||||
{
|
||||
MappingButton* mappingButton;
|
||||
AddMappingButton* addMappingButton;
|
||||
RemoveMappingButton* removeMappingButton;
|
||||
} mappingList[] =
|
||||
{
|
||||
// dpad
|
||||
this->dpadUpButton,
|
||||
this->dpadDownButton,
|
||||
this->dpadLeftButton,
|
||||
this->dpadRightButton,
|
||||
{ this->dpadUpButton, this->dpadUpAddButton, this->dpadUpRemoveButton },
|
||||
{ this->dpadDownButton, this->dpadDownAddButton, this->dpadDownRemoveButton },
|
||||
{ this->dpadLeftButton, this->dpadLeftAddButton, this->dpadLeftRemoveButton },
|
||||
{ this->dpadRightButton, this->dpadRightAddButton, this->dpadRightRemoveButton },
|
||||
// analog stick
|
||||
this->analogStickUpButton,
|
||||
this->analogStickDownButton,
|
||||
this->analogStickLeftButton,
|
||||
this->analogStickRightButton,
|
||||
{ this->analogStickUpButton, this->analogStickUpAddButton, this->analogStickUpRemoveButton },
|
||||
{ this->analogStickDownButton, this->analogStickDownAddButton, this->analogStickDownRemoveButton },
|
||||
{ this->analogStickLeftButton, this->analogStickLeftAddButton, this->analogStickLeftRemoveButton },
|
||||
{ this->analogStickRightButton, this->analogStickRightAddButton, this->analogStickRightRemoveButton },
|
||||
// cbuttons
|
||||
this->cbuttonUpButton,
|
||||
this->cbuttonDownButton,
|
||||
this->cbuttonLeftButton,
|
||||
this->cbuttonRightButton,
|
||||
{ this->cbuttonUpButton, this->cbuttonUpAddButton, this->cbuttonUpRemoveButton },
|
||||
{ this->cbuttonDownButton, this->cbuttonDownAddButton, this->cbuttonDownRemoveButton },
|
||||
{ this->cbuttonLeftButton, this->cbuttonLeftAddButton, this->cbuttonLeftRemoveButton },
|
||||
{ this->cbuttonRightButton, this->cbuttonRightAddButton, this->cbuttonRightRemoveButton },
|
||||
// triggers
|
||||
this->leftTriggerButton,
|
||||
this->rightTriggerButton,
|
||||
this->zTriggerButton,
|
||||
{ this->leftTriggerButton, this->leftTriggerAddButton, this->leftTriggerRemoveButton },
|
||||
{ this->rightTriggerButton, this->rightTriggerAddButton, this->rightTriggerRemoveButton },
|
||||
{ this->zTriggerButton, this->zTriggerAddButton, this->zTriggerRemoveButton },
|
||||
// buttons
|
||||
this->aButton,
|
||||
this->bButton,
|
||||
this->startButton,
|
||||
{ this->aButton, this->aAddButton, this->aRemoveButton },
|
||||
{ this->bButton, this->bAddButton, this->bRemoveButton },
|
||||
{ this->startButton, this->startAddButton, this->startRemoveButton },
|
||||
};
|
||||
|
||||
for (auto& button : buttonList)
|
||||
for (auto& mapping : mappingList)
|
||||
{
|
||||
button->Initialize(this);
|
||||
button->setText(" ");
|
||||
// initialize buttons
|
||||
mapping.mappingButton->Initialize(this);
|
||||
mapping.addMappingButton->Initialize(this, mapping.mappingButton);
|
||||
mapping.removeMappingButton->Initialize(this, mapping.mappingButton);
|
||||
|
||||
// clear text & set icon
|
||||
mapping.addMappingButton->setText("");
|
||||
mapping.removeMappingButton->setText("");
|
||||
mapping.addMappingButton->setIcon(QIcon::fromTheme("add-line"));
|
||||
mapping.removeMappingButton->setIcon(QIcon::fromTheme("delete-back-line"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +225,7 @@ void ControllerWidget::enableAllChildren()
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerWidget::removeDuplicates(CustomButton* button)
|
||||
void ControllerWidget::removeDuplicates(MappingButton* button)
|
||||
{
|
||||
std::string section = this->getCurrentSettingsSection().toStdString();
|
||||
|
||||
@@ -229,11 +242,20 @@ void ControllerWidget::removeDuplicates(CustomButton* button)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((buttonWidget->GetInputType() == button->GetInputType()) &&
|
||||
(buttonWidget->GetInputData() == button->GetInputData()) &&
|
||||
(buttonWidget->GetExtraInputData() == button->GetExtraInputData()))
|
||||
std::vector<int> inputType;
|
||||
std::vector<int> inputData;
|
||||
std::vector<int> extraInputData;
|
||||
|
||||
inputType = button->GetInputType();
|
||||
inputData = button->GetInputData();
|
||||
extraInputData = button->GetExtraInputData();
|
||||
|
||||
for (int i = 0; i < inputType.size(); i++)
|
||||
{
|
||||
buttonWidget->Clear();
|
||||
if (buttonWidget->HasInputData((InputType)inputType.at(i), inputData.at(i), extraInputData.at(i)))
|
||||
{
|
||||
buttonWidget->RemoveInputData((InputType)inputType.at(i), inputData.at(i), extraInputData.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,34 +428,37 @@ void ControllerWidget::on_controllerPluggedCheckBox_toggled(bool value)
|
||||
QWidget* widgetList[] =
|
||||
{
|
||||
// dpad
|
||||
this->dpadUpButton,
|
||||
this->dpadDownButton,
|
||||
this->dpadLeftButton,
|
||||
this->dpadRightButton,
|
||||
this->groupBox,
|
||||
this->dpadUpButton, this->dpadUpAddButton, this->dpadUpRemoveButton,
|
||||
this->dpadDownButton, this->dpadDownAddButton, this->dpadDownRemoveButton,
|
||||
this->dpadLeftButton, this->dpadLeftAddButton, this->dpadLeftRemoveButton,
|
||||
this->dpadRightButton, this->dpadRightAddButton, this->dpadRightRemoveButton,
|
||||
// analog stick
|
||||
this->analogStickUpButton,
|
||||
this->analogStickDownButton,
|
||||
this->analogStickLeftButton,
|
||||
this->analogStickRightButton,
|
||||
this->groupBox_2,
|
||||
this->analogStickUpButton, this->analogStickUpAddButton, this->analogStickUpRemoveButton,
|
||||
this->analogStickDownButton, this->analogStickDownAddButton, this->analogStickDownRemoveButton,
|
||||
this->analogStickLeftButton, this->analogStickLeftAddButton, this->analogStickLeftRemoveButton,
|
||||
this->analogStickRightButton, this->analogStickRightAddButton, this->analogStickRightRemoveButton,
|
||||
// cbuttons
|
||||
this->cbuttonUpButton,
|
||||
this->cbuttonDownButton,
|
||||
this->cbuttonLeftButton,
|
||||
this->cbuttonRightButton,
|
||||
this->groupBox_3,
|
||||
this->cbuttonUpButton, this->cbuttonUpAddButton, this->cbuttonUpRemoveButton,
|
||||
this->cbuttonDownButton, this->cbuttonDownAddButton, this->cbuttonDownRemoveButton,
|
||||
this->cbuttonLeftButton, this->cbuttonLeftAddButton, this->cbuttonLeftRemoveButton,
|
||||
this->cbuttonRightButton, this->cbuttonRightAddButton, this->cbuttonRightRemoveButton,
|
||||
// triggers
|
||||
this->leftTriggerButton,
|
||||
this->rightTriggerButton,
|
||||
this->zTriggerButton,
|
||||
this->leftTriggerButton, this->leftTriggerAddButton, this->leftTriggerRemoveButton,
|
||||
this->rightTriggerButton, this->rightTriggerAddButton, this->rightTriggerRemoveButton,
|
||||
this->zTriggerButton, this->zTriggerAddButton, this->zTriggerRemoveButton,
|
||||
// buttons
|
||||
this->aButton,
|
||||
this->bButton,
|
||||
this->startButton,
|
||||
this->groupBox_6,
|
||||
this->aButton, this->aAddButton, this->aRemoveButton,
|
||||
this->bButton, this->bAddButton, this->bRemoveButton,
|
||||
this->startButton, this->startAddButton, this->startRemoveButton,
|
||||
// misc UI elements
|
||||
this->deadZoneSlider,
|
||||
this->optionsButton,
|
||||
this->profileComboBox,
|
||||
this->removeProfileButton,
|
||||
//this->setupButton,
|
||||
this->resetButton,
|
||||
this->inputDeviceComboBox,
|
||||
this->inputDeviceRefreshButton
|
||||
@@ -483,15 +508,6 @@ void ControllerWidget::on_removeProfileButton_clicked()
|
||||
this->profileComboBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void ControllerWidget::on_setupButton_clicked()
|
||||
{
|
||||
this->currentInSetup = true;
|
||||
this->currentSetupButtonWidgetIndex = 0;
|
||||
|
||||
this->setupButtonWidgets.at(0)->setFocus(Qt::OtherFocusReason);
|
||||
this->setupButtonWidgets.at(0)->click();
|
||||
}
|
||||
|
||||
void ControllerWidget::on_resetButton_clicked()
|
||||
{
|
||||
this->LoadSettings();
|
||||
@@ -509,7 +525,7 @@ void ControllerWidget::on_optionsButton_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerWidget::on_CustomButton_released(CustomButton* button)
|
||||
void ControllerWidget::on_MappingButton_Released(MappingButton* button)
|
||||
{
|
||||
if (this->currentButton != nullptr)
|
||||
{
|
||||
@@ -524,11 +540,23 @@ void ControllerWidget::on_CustomButton_released(CustomButton* button)
|
||||
this->disableAllChildren();
|
||||
}
|
||||
|
||||
void ControllerWidget::on_CustomButton_TimerFinished(CustomButton* button)
|
||||
void ControllerWidget::on_AddMappingButton_Released(MappingButton* button)
|
||||
{
|
||||
this->addMappingToButton = true;
|
||||
button->click();
|
||||
}
|
||||
|
||||
void ControllerWidget::on_RemoveMappingButton_Released(MappingButton* button)
|
||||
{
|
||||
button->RemoveLastInputData();
|
||||
}
|
||||
|
||||
void ControllerWidget::on_MappingButton_TimerFinished(MappingButton* button)
|
||||
{
|
||||
if (this->currentButton == button)
|
||||
{
|
||||
this->currentButton = nullptr;
|
||||
this->currentButton = nullptr;
|
||||
this->addMappingToButton = false;
|
||||
}
|
||||
|
||||
button->RestoreState();
|
||||
@@ -536,11 +564,12 @@ void ControllerWidget::on_CustomButton_TimerFinished(CustomButton* button)
|
||||
this->enableAllChildren();
|
||||
}
|
||||
|
||||
void ControllerWidget::on_CustomButton_DataSet(CustomButton* button)
|
||||
void ControllerWidget::on_MappingButton_DataSet(MappingButton* button)
|
||||
{
|
||||
this->enableAllChildren();
|
||||
this->removeDuplicates(button);
|
||||
this->currentButton = nullptr;
|
||||
this->currentButton = nullptr;
|
||||
this->addMappingToButton = false;
|
||||
}
|
||||
|
||||
void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
@@ -561,6 +590,11 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
if ((event->type == SDL_CONTROLLERBUTTONDOWN) ||
|
||||
(event->type == SDL_CONTROLLERBUTTONUP))
|
||||
{ // gamepad button
|
||||
if (!this->isCurrentJoystickGameController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->cbutton.which;
|
||||
inputType = InputType::GamepadButton;
|
||||
sdlButton = event->cbutton.button;
|
||||
@@ -569,6 +603,11 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
else
|
||||
{ // joystick button
|
||||
if (this->isCurrentJoystickGameController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->jbutton.which;
|
||||
inputType = InputType::JoystickButton;
|
||||
sdlButton = event->jbutton.button;
|
||||
@@ -587,12 +626,24 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
{
|
||||
if (sdlButtonPressed)
|
||||
{
|
||||
this->currentButton->SetInputData(
|
||||
inputType,
|
||||
sdlButton,
|
||||
0,
|
||||
sdlButtonName
|
||||
);
|
||||
if (this->addMappingToButton)
|
||||
{
|
||||
this->currentButton->AddInputData(
|
||||
inputType,
|
||||
sdlButton,
|
||||
0,
|
||||
sdlButtonName
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->currentButton->SetInputData(
|
||||
inputType,
|
||||
sdlButton,
|
||||
0,
|
||||
sdlButtonName
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -600,8 +651,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller button state
|
||||
for (auto& button : this->buttonWidgetMappings)
|
||||
{
|
||||
if (button.buttonWidget->GetInputType() == inputType &&
|
||||
button.buttonWidget->GetInputData() == sdlButton)
|
||||
if (button.buttonWidget->HasInputData(inputType, sdlButton))
|
||||
{
|
||||
this->controllerImageWidget->SetButtonState(button.button, sdlButtonPressed);
|
||||
}
|
||||
@@ -610,8 +660,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller analog stick state
|
||||
for (auto& joystick : this->joystickWidgetMappings)
|
||||
{
|
||||
if (joystick.buttonWidget->GetInputType() == inputType &&
|
||||
joystick.buttonWidget->GetInputData() == sdlButton)
|
||||
if (joystick.buttonWidget->HasInputData(inputType, sdlButton))
|
||||
{
|
||||
switch (joystick.direction)
|
||||
{
|
||||
@@ -655,6 +704,11 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
|
||||
if (event->type == SDL_CONTROLLERAXISMOTION)
|
||||
{ // gamepad axis
|
||||
if (!this->isCurrentJoystickGameController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->caxis.which;
|
||||
inputType = InputType::GamepadAxis;
|
||||
sdlAxis = event->caxis.axis;
|
||||
@@ -664,6 +718,11 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
else
|
||||
{ // joystick axis
|
||||
if (this->isCurrentJoystickGameController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->jaxis.which;
|
||||
inputType = InputType::JoystickAxis;
|
||||
sdlAxis = event->jaxis.axis;
|
||||
@@ -689,24 +748,24 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
{
|
||||
if (sdlAxisButtonPressed)
|
||||
{
|
||||
// invert axis for left, right & z trigger mappings
|
||||
if (this->optionsDialogSettings.InvertAxis)
|
||||
if (this->addMappingToButton)
|
||||
{
|
||||
if (this->currentButton == this->leftTriggerButton ||
|
||||
this->currentButton == this->rightTriggerButton ||
|
||||
this->currentButton == this->zTriggerButton)
|
||||
{
|
||||
sdlAxisDirection = (sdlAxisDirection == 1 ? 0 : 1);
|
||||
sdlAxisName = "axis " + QString::number(sdlAxis);
|
||||
sdlAxisName += sdlAxisDirection > 0 ? "+" : "-";
|
||||
}
|
||||
this->currentButton->AddInputData(
|
||||
inputType,
|
||||
sdlAxis,
|
||||
sdlAxisDirection,
|
||||
sdlAxisName
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->currentButton->SetInputData(
|
||||
inputType,
|
||||
sdlAxis,
|
||||
sdlAxisDirection,
|
||||
sdlAxisName
|
||||
);
|
||||
}
|
||||
this->currentButton->SetInputData(
|
||||
inputType,
|
||||
sdlAxis,
|
||||
sdlAxisDirection,
|
||||
sdlAxisName
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -714,9 +773,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller button state
|
||||
for (auto& button : this->buttonWidgetMappings)
|
||||
{
|
||||
if (button.buttonWidget->GetInputType() == inputType &&
|
||||
button.buttonWidget->GetInputData() == sdlAxis &&
|
||||
button.buttonWidget->GetExtraInputData() == sdlAxisDirection)
|
||||
if (button.buttonWidget->HasInputData(inputType, sdlAxis, sdlAxisDirection))
|
||||
{
|
||||
this->controllerImageWidget->SetButtonState(button.button, sdlAxisButtonPressed);
|
||||
}
|
||||
@@ -725,9 +782,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller analog stick state
|
||||
for (auto& joystick : this->joystickWidgetMappings)
|
||||
{
|
||||
if (joystick.buttonWidget->GetInputType() == inputType &&
|
||||
joystick.buttonWidget->GetInputData() == sdlAxis &&
|
||||
joystick.buttonWidget->GetExtraInputData() == sdlAxisDirection)
|
||||
if (joystick.buttonWidget->HasInputData(inputType, sdlAxis, sdlAxisDirection))
|
||||
{
|
||||
const int value = -(double)((double)sdlAxisValue / SDL_AXIS_PEAK * 100);
|
||||
|
||||
@@ -770,12 +825,24 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
{
|
||||
if (sdlButtonPressed)
|
||||
{
|
||||
this->currentButton->SetInputData(
|
||||
InputType::Keyboard,
|
||||
sdlButton,
|
||||
0,
|
||||
SDL_GetScancodeName(sdlButton)
|
||||
);
|
||||
if (this->addMappingToButton)
|
||||
{
|
||||
this->currentButton->AddInputData(
|
||||
InputType::Keyboard,
|
||||
sdlButton,
|
||||
0,
|
||||
SDL_GetScancodeName(sdlButton)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->currentButton->SetInputData(
|
||||
InputType::Keyboard,
|
||||
sdlButton,
|
||||
0,
|
||||
SDL_GetScancodeName(sdlButton)
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -783,8 +850,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller button state
|
||||
for (auto& button : this->buttonWidgetMappings)
|
||||
{
|
||||
if (button.buttonWidget->GetInputType() == InputType::Keyboard &&
|
||||
button.buttonWidget->GetInputData() == sdlButton)
|
||||
if (button.buttonWidget->HasInputData(InputType::Keyboard, sdlButton))
|
||||
{
|
||||
this->controllerImageWidget->SetButtonState(button.button, sdlButtonPressed);
|
||||
}
|
||||
@@ -793,8 +859,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
// update controller analog stick state
|
||||
for (auto& joystick : this->joystickWidgetMappings)
|
||||
{
|
||||
if (joystick.buttonWidget->GetInputType() == InputType::Keyboard &&
|
||||
joystick.buttonWidget->GetInputData() == sdlButton)
|
||||
if (joystick.buttonWidget->HasInputData(InputType::Keyboard, sdlButton))
|
||||
{
|
||||
switch (joystick.direction)
|
||||
{
|
||||
@@ -909,21 +974,39 @@ void ControllerWidget::LoadSettings(QString sectionQString)
|
||||
this->controllerPluggedCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::Input_PluggedIn, section));
|
||||
this->deadZoneSlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section));
|
||||
this->optionsDialogSettings.RemoveDuplicateMappings = CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, section);
|
||||
this->optionsDialogSettings.InvertAxis = CoreSettingsGetBoolValue(SettingsID::Input_InvertAxis, section);
|
||||
this->optionsDialogSettings.ControllerPak = CoreSettingsGetIntValue(SettingsID::Input_Pak, section);
|
||||
this->optionsDialogSettings.GameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section);
|
||||
this->optionsDialogSettings.GameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section);
|
||||
|
||||
for (auto& buttonSetting : this->buttonSettingMappings)
|
||||
{
|
||||
enum InputType type = (InputType)CoreSettingsGetIntValue(buttonSetting.inputTypeSettingsId, section);
|
||||
std::string name = CoreSettingsGetStringValue(buttonSetting.nameSettingsId, section);
|
||||
int data = CoreSettingsGetIntValue(buttonSetting.dataSettingsId, section);
|
||||
int extraData = CoreSettingsGetIntValue(buttonSetting.extraDataSettingsId, section);
|
||||
buttonSetting.button->Clear();
|
||||
|
||||
buttonSetting.button->SetInputData(type, data, extraData, QString::fromStdString(name));
|
||||
std::vector<int> types = CoreSettingsGetIntListValue(buttonSetting.inputTypeSettingsId, section);
|
||||
std::vector<std::string> names = CoreSettingsGetStringListValue(buttonSetting.nameSettingsId, section);
|
||||
std::vector<int> data = CoreSettingsGetIntListValue(buttonSetting.dataSettingsId, section);
|
||||
std::vector<int> extraData = CoreSettingsGetIntListValue(buttonSetting.extraDataSettingsId, section);
|
||||
|
||||
int count = std::min(extraData.size(), std::min(types.size(), std::min(names.size(), data.size())));
|
||||
|
||||
if (count == 0)
|
||||
{ // attempt to load old profile type
|
||||
types.push_back(CoreSettingsGetIntValue(buttonSetting.inputTypeSettingsId, section));
|
||||
names.push_back(CoreSettingsGetStringValue(buttonSetting.nameSettingsId, section));
|
||||
data.push_back(CoreSettingsGetIntValue(buttonSetting.dataSettingsId, section));
|
||||
extraData.push_back(CoreSettingsGetIntValue(buttonSetting.extraDataSettingsId, section));
|
||||
count = 1;
|
||||
}
|
||||
|
||||
// add all input data
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
buttonSetting.button->AddInputData((InputType)types[i], data[i], extraData[i], QString::fromStdString(names.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// force refresh some UI elements
|
||||
this->on_deadZoneSlider_valueChanged(this->deadZoneSlider->value());
|
||||
this->on_controllerPluggedCheckBox_toggled(this->IsPluggedIn());
|
||||
}
|
||||
|
||||
@@ -941,19 +1024,14 @@ void ControllerWidget::SaveDefaultSettings()
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceNum, section, -1);
|
||||
CoreSettingsSetValue(SettingsID::Input_Deadzone, section, 9);
|
||||
CoreSettingsSetValue(SettingsID::Input_Pak, section, 0);
|
||||
#ifdef _WIN32
|
||||
CoreSettingsSetValue(SettingsID::Input_RemoveDuplicateMappings, section, true);
|
||||
#else
|
||||
CoreSettingsSetValue(SettingsID::Input_RemoveDuplicateMappings, section, false);
|
||||
#endif // _WIN32
|
||||
CoreSettingsSetValue(SettingsID::Input_InvertAxis, section, true);
|
||||
|
||||
for (auto& buttonSetting : this->buttonSettingMappings)
|
||||
{
|
||||
CoreSettingsSetValue(buttonSetting.inputTypeSettingsId, section, (int)InputType::Invalid);
|
||||
CoreSettingsSetValue(buttonSetting.nameSettingsId, section, std::string(" "));
|
||||
CoreSettingsSetValue(buttonSetting.dataSettingsId, section, 0);
|
||||
CoreSettingsSetValue(buttonSetting.extraDataSettingsId, section, 0);
|
||||
CoreSettingsSetValue(buttonSetting.inputTypeSettingsId, section, std::vector<int>({ (int)InputType::Invalid }));
|
||||
CoreSettingsSetValue(buttonSetting.nameSettingsId, section, std::vector<std::string>({ std::string() }));
|
||||
CoreSettingsSetValue(buttonSetting.dataSettingsId, section, std::vector<int>({ 0 }));
|
||||
CoreSettingsSetValue(buttonSetting.extraDataSettingsId, section, std::vector<int>({ 0 }));
|
||||
}
|
||||
|
||||
CoreSettingsSave();
|
||||
@@ -980,12 +1058,11 @@ void ControllerWidget::SaveSettings()
|
||||
CoreSettingsSetValue(SettingsID::Input_GameboyRom, section, this->optionsDialogSettings.GameboyRom);
|
||||
CoreSettingsSetValue(SettingsID::Input_GameboySave, section, this->optionsDialogSettings.GameboySave);
|
||||
CoreSettingsSetValue(SettingsID::Input_RemoveDuplicateMappings, section, this->optionsDialogSettings.RemoveDuplicateMappings);
|
||||
CoreSettingsSetValue(SettingsID::Input_InvertAxis, section, this->optionsDialogSettings.InvertAxis);
|
||||
|
||||
for (auto& buttonSetting : this->buttonSettingMappings)
|
||||
{
|
||||
CoreSettingsSetValue(buttonSetting.inputTypeSettingsId, section, (int)buttonSetting.button->GetInputType());
|
||||
CoreSettingsSetValue(buttonSetting.nameSettingsId, section, buttonSetting.button->text().toStdString());
|
||||
CoreSettingsSetValue(buttonSetting.inputTypeSettingsId, section, buttonSetting.button->GetInputType());
|
||||
CoreSettingsSetValue(buttonSetting.nameSettingsId, section, buttonSetting.button->GetInputText());
|
||||
CoreSettingsSetValue(buttonSetting.dataSettingsId, section, buttonSetting.button->GetInputData());
|
||||
CoreSettingsSetValue(buttonSetting.extraDataSettingsId, section, buttonSetting.button->GetExtraInputData());
|
||||
}
|
||||
@@ -998,3 +1075,8 @@ void ControllerWidget::SetCurrentJoystickID(SDL_JoystickID joystickId)
|
||||
this->currentJoystickId = joystickId;
|
||||
}
|
||||
|
||||
void ControllerWidget::SetIsCurrentJoystickGameController(bool isGameController)
|
||||
{
|
||||
this->isCurrentJoystickGameController = isGameController;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef CONTROLLERWIDGET_H
|
||||
#define CONTROLLERWIDGET_H
|
||||
|
||||
#include "CustomButton.hpp"
|
||||
#include "MappingButton.hpp"
|
||||
#include "ControllerImageWidget.hpp"
|
||||
|
||||
#include "UserInterface/EventFilter.hpp"
|
||||
@@ -39,23 +39,24 @@ private:
|
||||
OptionsDialogSettings optionsDialogSettings;
|
||||
|
||||
QList<QString> inputDeviceNameList;
|
||||
CustomButton* currentButton = nullptr;
|
||||
|
||||
MappingButton* currentButton = nullptr;
|
||||
bool addMappingToButton = false;
|
||||
|
||||
struct buttonWidgetMapping
|
||||
{
|
||||
enum N64ControllerButton button;
|
||||
CustomButton* buttonWidget;
|
||||
MappingButton* buttonWidget;
|
||||
};
|
||||
|
||||
struct axisWidgetMapping
|
||||
{
|
||||
enum InputAxisDirection direction;
|
||||
CustomButton* buttonWidget;
|
||||
MappingButton* buttonWidget;
|
||||
};
|
||||
|
||||
struct buttonSettingMapping
|
||||
{
|
||||
CustomButton* button;
|
||||
MappingButton* button;
|
||||
SettingsID inputTypeSettingsId;
|
||||
SettingsID nameSettingsId;
|
||||
SettingsID dataSettingsId;
|
||||
@@ -65,9 +66,7 @@ private:
|
||||
QList<buttonWidgetMapping> buttonWidgetMappings;
|
||||
QList<axisWidgetMapping> joystickWidgetMappings;
|
||||
QList<buttonSettingMapping> buttonSettingMappings;
|
||||
QList<CustomButton*> setupButtonWidgets;
|
||||
int currentSetupButtonWidgetIndex = 0;
|
||||
bool currentInSetup = false;
|
||||
QList<MappingButton*> setupButtonWidgets;
|
||||
|
||||
void initializeButtons();
|
||||
|
||||
@@ -77,11 +76,12 @@ private:
|
||||
void disableAllChildren();
|
||||
void enableAllChildren();
|
||||
|
||||
void removeDuplicates(CustomButton* button);
|
||||
void removeDuplicates(MappingButton* button);
|
||||
|
||||
QString getCurrentSettingsSection();
|
||||
|
||||
SDL_JoystickID currentJoystickId = -1;
|
||||
SDL_JoystickID currentJoystickId = -1;
|
||||
bool isCurrentJoystickGameController = false;
|
||||
|
||||
public:
|
||||
ControllerWidget(QWidget* parent, EventFilter* eventFilter);
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
void SaveSettings();
|
||||
|
||||
void SetCurrentJoystickID(SDL_JoystickID joystickId);
|
||||
void SetIsCurrentJoystickGameController(bool isGameController);
|
||||
|
||||
private slots:
|
||||
void on_deadZoneSlider_valueChanged(int value);
|
||||
@@ -117,15 +118,18 @@ private slots:
|
||||
void on_controllerPluggedCheckBox_toggled(bool value);
|
||||
|
||||
void on_removeProfileButton_clicked();
|
||||
void on_setupButton_clicked();
|
||||
|
||||
void on_resetButton_clicked();
|
||||
void on_optionsButton_clicked();
|
||||
|
||||
public slots:
|
||||
void on_CustomButton_released(CustomButton* button);
|
||||
void on_CustomButton_TimerFinished(CustomButton* button);
|
||||
void on_CustomButton_DataSet(CustomButton* button);
|
||||
void on_MappingButton_Released(MappingButton* button);
|
||||
void on_MappingButton_TimerFinished(MappingButton* button);
|
||||
void on_MappingButton_DataSet(MappingButton* button);
|
||||
|
||||
void on_AddMappingButton_Released(MappingButton* button);
|
||||
void on_RemoveMappingButton_Released(MappingButton* button);
|
||||
|
||||
void on_MainDialog_SdlEvent(SDL_Event* event);
|
||||
void on_MainDialog_SdlEventPollFinished();
|
||||
signals:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "CustomButton.hpp"
|
||||
#include "ControllerWidget.hpp"
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
CustomButton::CustomButton(QWidget* parent) : QPushButton(parent)
|
||||
{
|
||||
this->countDownTimer = new QTimer(this);
|
||||
connect(this->countDownTimer, &QTimer::timeout, this, &CustomButton::on_countDownTimer_triggered);
|
||||
}
|
||||
|
||||
CustomButton::~CustomButton()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CustomButton::Initialize(QWidget* widget)
|
||||
{
|
||||
this->controllerWidget = (ControllerWidget*)widget;
|
||||
|
||||
connect(this, &QPushButton::released,
|
||||
[=]
|
||||
{
|
||||
emit this->controllerWidget->on_CustomButton_released(this);
|
||||
});
|
||||
}
|
||||
|
||||
void CustomButton::Clear()
|
||||
{
|
||||
this->inputType = InputType::Invalid;
|
||||
this->inputData = 0;
|
||||
this->extraInputData = 0;
|
||||
this->savedInputData = 0;
|
||||
this->savedExtraInputData = 0;
|
||||
this->setText(" ");
|
||||
}
|
||||
|
||||
void CustomButton::StartTimer()
|
||||
{
|
||||
this->currentCountDownNum = 5;
|
||||
this->on_countDownTimer_triggered();
|
||||
this->countDownTimer->start(1000);
|
||||
}
|
||||
|
||||
void CustomButton::StopTimer()
|
||||
{
|
||||
this->countDownTimer->stop();
|
||||
}
|
||||
|
||||
void CustomButton::SetInputData(enum InputType type, int value, int extraValue, QString name)
|
||||
{
|
||||
this->inputType = type;
|
||||
this->inputData = value;
|
||||
this->extraInputData = extraValue;
|
||||
this->setText(name);
|
||||
this->StopTimer();
|
||||
emit this->controllerWidget->on_CustomButton_DataSet(this);
|
||||
}
|
||||
|
||||
enum InputType CustomButton::GetInputType()
|
||||
{
|
||||
return this->inputType;
|
||||
}
|
||||
|
||||
int CustomButton::GetInputData()
|
||||
{
|
||||
return this->inputData;
|
||||
}
|
||||
|
||||
int CustomButton::GetExtraInputData()
|
||||
{
|
||||
return this->extraInputData;
|
||||
}
|
||||
|
||||
void CustomButton::SaveState()
|
||||
{
|
||||
this->savedInputType = this->inputType;
|
||||
this->savedInputData = this->inputData;
|
||||
this->savedExtraInputData = this->extraInputData;
|
||||
this->savedText = this->text();
|
||||
}
|
||||
|
||||
void CustomButton::RestoreState()
|
||||
{
|
||||
this->inputType = this->savedInputType;
|
||||
this->inputData = this->savedInputData;
|
||||
this->extraInputData = this->savedExtraInputData;
|
||||
this->setText(this->savedText);
|
||||
}
|
||||
|
||||
void CustomButton::on_countDownTimer_triggered()
|
||||
{
|
||||
this->setText(QString::number(this->currentCountDownNum));
|
||||
|
||||
if (this->currentCountDownNum == 0)
|
||||
{
|
||||
this->setText("");
|
||||
this->currentCountDownNum = 5;
|
||||
this->countDownTimer->stop();
|
||||
emit this->controllerWidget->on_CustomButton_TimerFinished(this);
|
||||
}
|
||||
|
||||
this->currentCountDownNum--;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CUSTOMBUTTON_HPP
|
||||
#define CUSTOMBUTTON_HPP
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace Widget
|
||||
{
|
||||
|
||||
// we can't include ControllerWidget.hpp
|
||||
// because that header includes this header,
|
||||
// so forward-declare it to prevent issues
|
||||
class ControllerWidget;
|
||||
|
||||
class CustomButton : public QPushButton
|
||||
{
|
||||
private:
|
||||
QTimer* countDownTimer = nullptr;
|
||||
ControllerWidget* controllerWidget = nullptr;
|
||||
int currentCountDownNum = 0;
|
||||
enum InputType inputType = InputType::Invalid;
|
||||
int inputData = 0;
|
||||
int extraInputData = 0;
|
||||
|
||||
enum InputType savedInputType = InputType::Invalid;
|
||||
int savedInputData = 0;
|
||||
int savedExtraInputData = 0;
|
||||
QString savedText;
|
||||
public:
|
||||
CustomButton(QWidget* parent);
|
||||
~CustomButton();
|
||||
void Initialize(QWidget* widget);
|
||||
void Clear();
|
||||
|
||||
void StartTimer();
|
||||
void StopTimer();
|
||||
|
||||
|
||||
void SetInputData(enum InputType type, int value, int extraValue, QString name);
|
||||
enum InputType GetInputType();
|
||||
int GetInputData();
|
||||
int GetExtraInputData();
|
||||
|
||||
void SaveState();
|
||||
void RestoreState();
|
||||
|
||||
private slots:
|
||||
void on_countDownTimer_triggered();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // CUSTOMBUTTON_HPP
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "MappingButton.hpp"
|
||||
#include "ControllerWidget.hpp"
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
MappingButton::MappingButton(QWidget* parent) : QPushButton(parent)
|
||||
{
|
||||
this->countDownTimer = new QTimer(this);
|
||||
connect(this->countDownTimer, &QTimer::timeout, this, &MappingButton::on_countDownTimer_triggered);
|
||||
}
|
||||
|
||||
MappingButton::~MappingButton()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MappingButton::Initialize(ControllerWidget* widget)
|
||||
{
|
||||
this->controllerWidget = widget;
|
||||
|
||||
connect(this, &QPushButton::released, [=]
|
||||
{
|
||||
emit this->controllerWidget->on_MappingButton_Released(this);
|
||||
});
|
||||
|
||||
this->setText(" ");
|
||||
}
|
||||
|
||||
void MappingButton::Clear()
|
||||
{
|
||||
this->inputData.clear();
|
||||
this->savedInputData.clear();
|
||||
this->setText(" ");
|
||||
}
|
||||
|
||||
void MappingButton::StartTimer()
|
||||
{
|
||||
this->currentCountDownNum = 5;
|
||||
this->on_countDownTimer_triggered();
|
||||
this->countDownTimer->start(1000);
|
||||
}
|
||||
|
||||
void MappingButton::StopTimer()
|
||||
{
|
||||
this->countDownTimer->stop();
|
||||
}
|
||||
|
||||
void MappingButton::SetInputData(enum InputType type, int value, int extraValue, QString name)
|
||||
{
|
||||
// don't add stub
|
||||
if (name.simplified().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->inputData.clear();
|
||||
this->inputData.push_back(
|
||||
{
|
||||
type,
|
||||
value,
|
||||
extraValue,
|
||||
name
|
||||
}
|
||||
);
|
||||
|
||||
this->reloadText();
|
||||
this->StopTimer();
|
||||
|
||||
emit this->controllerWidget->on_MappingButton_DataSet(this);
|
||||
}
|
||||
|
||||
void MappingButton::AddInputData(enum InputType type, int value, int extraValue, QString name)
|
||||
{
|
||||
// don't add stub
|
||||
if (name.simplified().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->HasInputData(type, value, extraValue))
|
||||
{
|
||||
this->inputData.push_back(
|
||||
{
|
||||
type,
|
||||
value,
|
||||
extraValue,
|
||||
name
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this->reloadText();
|
||||
this->StopTimer();
|
||||
|
||||
emit this->controllerWidget->on_MappingButton_DataSet(this);
|
||||
}
|
||||
|
||||
void MappingButton::RemoveLastInputData(void)
|
||||
{
|
||||
if (!this->inputData.empty())
|
||||
{
|
||||
this->inputData.pop_back();
|
||||
}
|
||||
|
||||
this->reloadText();
|
||||
}
|
||||
|
||||
void MappingButton::RemoveInputData(InputType type, int value, int extraValue)
|
||||
{
|
||||
auto iter = this->getInputDataIter(type, value, extraValue);
|
||||
if (iter == this->inputData.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->inputData.erase(iter);
|
||||
this->reloadText();
|
||||
}
|
||||
|
||||
bool MappingButton::HasInputData(enum InputType type, int value, int extraValue)
|
||||
{
|
||||
return this->getInputDataIter(type, value, extraValue) != this->inputData.end();
|
||||
}
|
||||
|
||||
std::vector<int> MappingButton::GetInputType()
|
||||
{
|
||||
std::vector<int> inputTypeList;
|
||||
|
||||
for (const auto& data : this->inputData)
|
||||
{
|
||||
inputTypeList.push_back((int)data.Type);
|
||||
}
|
||||
|
||||
return inputTypeList;
|
||||
}
|
||||
|
||||
std::vector<int> MappingButton::GetInputData()
|
||||
{
|
||||
std::vector<int> inputDataList;
|
||||
|
||||
for (const auto& data : this->inputData)
|
||||
{
|
||||
inputDataList.push_back(data.Data);
|
||||
}
|
||||
|
||||
return inputDataList;
|
||||
}
|
||||
|
||||
std::vector<int> MappingButton::GetExtraInputData()
|
||||
{
|
||||
std::vector<int> extraInputDataList;
|
||||
|
||||
for (const auto& data : this->inputData)
|
||||
{
|
||||
extraInputDataList.push_back(data.ExtraData);
|
||||
}
|
||||
|
||||
return extraInputDataList;
|
||||
}
|
||||
|
||||
std::vector<std::string> MappingButton::GetInputText()
|
||||
{
|
||||
std::vector<std::string> inputTextList;
|
||||
|
||||
for (const auto& data : this->inputData)
|
||||
{
|
||||
inputTextList.push_back(data.Text.toStdString());
|
||||
}
|
||||
|
||||
return inputTextList;
|
||||
}
|
||||
|
||||
void MappingButton::SaveState()
|
||||
{
|
||||
this->savedInputData = this->inputData;
|
||||
}
|
||||
|
||||
void MappingButton::RestoreState()
|
||||
{
|
||||
this->inputData = this->savedInputData;
|
||||
this->reloadText();
|
||||
}
|
||||
|
||||
void MappingButton::on_countDownTimer_triggered()
|
||||
{
|
||||
this->setText(QString::number(this->currentCountDownNum));
|
||||
|
||||
if (this->currentCountDownNum == 0)
|
||||
{
|
||||
this->setText("");
|
||||
this->currentCountDownNum = 5;
|
||||
this->countDownTimer->stop();
|
||||
emit this->controllerWidget->on_MappingButton_TimerFinished(this);
|
||||
}
|
||||
|
||||
this->currentCountDownNum--;
|
||||
}
|
||||
|
||||
void MappingButton::reloadText()
|
||||
{
|
||||
QString text;
|
||||
QFontMetrics fontMetrics(this->font());
|
||||
|
||||
int size = this->inputData.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
text += this->inputData.at(i).Text;
|
||||
|
||||
// only add comma when
|
||||
// not at the last item
|
||||
if (i < (size - 1))
|
||||
{
|
||||
text += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
QString elidedText = fontMetrics.elidedText(text, Qt::ElideRight, this->width());
|
||||
|
||||
// needed for spacing
|
||||
if (elidedText.isEmpty())
|
||||
{
|
||||
elidedText = " ";
|
||||
}
|
||||
|
||||
this->setToolTip(text);
|
||||
this->setText(elidedText);
|
||||
}
|
||||
|
||||
std::vector<MappingButtonInputDataType>::iterator MappingButton::getInputDataIter(InputType type, int value, int extraValue)
|
||||
{
|
||||
auto predicate = [type, value, extraValue](const auto& entry)
|
||||
{
|
||||
return entry.Type == type &&
|
||||
(value == -1 || entry.Data == value) &&
|
||||
(extraValue == -1 || entry.ExtraData == extraValue);
|
||||
};
|
||||
|
||||
return std::find_if(this->inputData.begin(), this->inputData.end(), predicate);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef MAPPINGBUTTON_HPP
|
||||
#define MAPPINGBUTTON_HPP
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace Widget
|
||||
{
|
||||
|
||||
// we can't include ControllerWidget.hpp
|
||||
// because that header includes this header,
|
||||
// so forward-declare it to prevent issues
|
||||
class ControllerWidget;
|
||||
|
||||
struct MappingButtonInputDataType
|
||||
{
|
||||
InputType Type;
|
||||
int Data;
|
||||
int ExtraData;
|
||||
QString Text;
|
||||
};
|
||||
|
||||
class MappingButton : public QPushButton
|
||||
{
|
||||
private:
|
||||
QTimer* countDownTimer = nullptr;
|
||||
ControllerWidget* controllerWidget = nullptr;
|
||||
int currentCountDownNum = 0;
|
||||
|
||||
std::vector<MappingButtonInputDataType> inputData;
|
||||
|
||||
std::vector<MappingButtonInputDataType> savedInputData;
|
||||
|
||||
void reloadText();
|
||||
|
||||
std::vector<MappingButtonInputDataType>::iterator getInputDataIter(InputType type, int value, int extraValue);
|
||||
|
||||
public:
|
||||
MappingButton(QWidget* parent);
|
||||
~MappingButton();
|
||||
|
||||
void Initialize(ControllerWidget* widget);
|
||||
void Clear();
|
||||
|
||||
void StartTimer();
|
||||
void StopTimer();
|
||||
|
||||
void SetInputData(InputType type, int value, int extraValue, QString name);
|
||||
void AddInputData(InputType type, int value, int extraValue, QString name);
|
||||
|
||||
void RemoveLastInputData(void);
|
||||
void RemoveInputData(InputType type, int value, int extraValue);
|
||||
|
||||
bool HasInputData(InputType type, int value = -1, int extraValue = -1);
|
||||
|
||||
std::vector<int> GetInputType();
|
||||
std::vector<int> GetInputData();
|
||||
std::vector<int> GetExtraInputData();
|
||||
std::vector<std::string> GetInputText();
|
||||
|
||||
void SaveState();
|
||||
void RestoreState();
|
||||
|
||||
private slots:
|
||||
void on_countDownTimer_triggered();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MAPPINGBUTTON_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "RemoveMappingButton.hpp"
|
||||
#include "ControllerWidget.hpp"
|
||||
#include "MappingButton.hpp"
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
RemoveMappingButton::RemoveMappingButton(QWidget* parent) : QPushButton(parent)
|
||||
{
|
||||
}
|
||||
|
||||
RemoveMappingButton::~RemoveMappingButton()
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveMappingButton::Initialize(ControllerWidget* widget, MappingButton* button)
|
||||
{
|
||||
this->controllerWidget = widget;
|
||||
this->mappingButton = button;
|
||||
|
||||
connect(this, &QPushButton::released, [=]
|
||||
{
|
||||
emit this->controllerWidget->on_RemoveMappingButton_Released(this->mappingButton);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef REMOVEMAPPINGBUTTON_HPP
|
||||
#define REMOVEMAPPINGBUTTON_HPP
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
namespace Widget
|
||||
{
|
||||
|
||||
// we can't include ControllerWidget.hpp
|
||||
// because that header includes this header,
|
||||
// so forward-declare it to prevent issues
|
||||
class ControllerWidget;
|
||||
class MappingButton;
|
||||
|
||||
class RemoveMappingButton : public QPushButton
|
||||
{
|
||||
private:
|
||||
ControllerWidget* controllerWidget = nullptr;
|
||||
MappingButton* mappingButton = nullptr;
|
||||
|
||||
public:
|
||||
RemoveMappingButton(QWidget* parent);
|
||||
~RemoveMappingButton();
|
||||
|
||||
void Initialize(ControllerWidget* widget, MappingButton* button);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // REMOVEMAPPINGBUTTON_HPP
|
||||
+105
-71
@@ -49,9 +49,10 @@
|
||||
|
||||
struct InputMapping
|
||||
{
|
||||
InputType Type = InputType::Invalid;
|
||||
int Data = 0;
|
||||
int ExtraData = 0;
|
||||
std::vector<int> Type;
|
||||
std::vector<int> Data;
|
||||
std::vector<int> ExtraData;
|
||||
int Count = 0;
|
||||
};
|
||||
|
||||
struct InputProfile
|
||||
@@ -122,9 +123,18 @@ static bool l_KeyboardState[SDL_NUM_SCANCODES];
|
||||
static void load_inputmapping_settings(InputMapping* mapping, std::string section,
|
||||
SettingsID inputTypeSettingsId, SettingsID dataSettingsId, SettingsID extraDataSettingsId)
|
||||
{
|
||||
mapping->Type = (InputType)CoreSettingsGetIntValue(inputTypeSettingsId, section);
|
||||
mapping->Data = CoreSettingsGetIntValue(dataSettingsId, section);
|
||||
mapping->ExtraData = CoreSettingsGetIntValue(extraDataSettingsId, section);
|
||||
mapping->Type = CoreSettingsGetIntListValue(inputTypeSettingsId, section);
|
||||
mapping->Data = CoreSettingsGetIntListValue(dataSettingsId, section);
|
||||
mapping->ExtraData = CoreSettingsGetIntListValue(extraDataSettingsId, section);
|
||||
mapping->Count = std::min(mapping->Type.size(), std::min(mapping->Data.size(), mapping->ExtraData.size()));
|
||||
|
||||
if (mapping->Count == 0)
|
||||
{ // try to load old profile type
|
||||
mapping->Type.push_back(CoreSettingsGetIntValue(inputTypeSettingsId, section));
|
||||
mapping->Data.push_back(CoreSettingsGetIntValue(dataSettingsId, section));
|
||||
mapping->ExtraData.push_back(CoreSettingsGetIntValue(extraDataSettingsId, section));
|
||||
mapping->Count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void load_settings(void)
|
||||
@@ -286,88 +296,104 @@ static void close_controllers(void)
|
||||
|
||||
static int get_button_state(InputProfile* profile, InputMapping* inputMapping)
|
||||
{
|
||||
switch (inputMapping->Type)
|
||||
int state = 0;
|
||||
|
||||
for (int i = 0; i < inputMapping->Count; i++)
|
||||
{
|
||||
case InputType::GamepadButton:
|
||||
const int data = inputMapping->Data.at(i);
|
||||
const int extraData = inputMapping->ExtraData.at(i);
|
||||
|
||||
switch ((InputType)inputMapping->Type[i])
|
||||
{
|
||||
return SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)inputMapping->Data);
|
||||
};
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
int axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)inputMapping->Data);
|
||||
return (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (inputMapping->ExtraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
};
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
return SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), inputMapping->Data);
|
||||
};
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
int axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), inputMapping->Data);
|
||||
return (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (inputMapping->ExtraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
case InputType::GamepadButton:
|
||||
{
|
||||
state |= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
int axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)data);
|
||||
state |= (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (extraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
} break;
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
state |= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
} break;
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
int axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), data);
|
||||
state |= (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (extraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
} break;
|
||||
case InputType::Keyboard:
|
||||
{
|
||||
state |= l_KeyboardState[data] ? 1 : 0;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case InputType::Keyboard:
|
||||
{
|
||||
return l_KeyboardState[inputMapping->Data] ? 1 : 0;
|
||||
};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
// returns axis input scaled to the range [-1, 1]
|
||||
static double get_axis_state(InputProfile* profile, InputMapping* inputMapping, int direction, double value)
|
||||
{
|
||||
switch (inputMapping->Type)
|
||||
{
|
||||
case InputType::GamepadButton:
|
||||
{
|
||||
int buttonState = SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)inputMapping->Data);
|
||||
return buttonState ? direction : value;
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
double axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)inputMapping->Data);
|
||||
if (inputMapping->ExtraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
axis_value = (axis_value / SDL_AXIS_PEAK);
|
||||
axis_value = abs(axis_value) * direction;
|
||||
return axis_value;
|
||||
}
|
||||
} break;
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
int buttonState = SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), inputMapping->Data);
|
||||
return buttonState ? direction : value;
|
||||
} break;
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
double axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), inputMapping->Data);
|
||||
if (inputMapping->ExtraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
axis_value = (axis_value / SDL_AXIS_PEAK);
|
||||
axis_value = abs(axis_value) * direction;
|
||||
return axis_value;
|
||||
}
|
||||
} break;
|
||||
case InputType::Keyboard:
|
||||
{
|
||||
return l_KeyboardState[inputMapping->Data] ? direction : value;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int state = 0;
|
||||
|
||||
return value;
|
||||
for (int i = 0; i < inputMapping->Count; i++)
|
||||
{
|
||||
const int data = inputMapping->Data.at(i);
|
||||
const int extraData = inputMapping->ExtraData.at(i);
|
||||
|
||||
switch ((InputType)inputMapping->Type[i])
|
||||
{
|
||||
case InputType::GamepadButton:
|
||||
{
|
||||
int buttonState = SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
state |= buttonState;
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
double axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)data);
|
||||
if (extraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
axis_value = (axis_value / SDL_AXIS_PEAK);
|
||||
axis_value = abs(axis_value) * direction;
|
||||
return axis_value;
|
||||
}
|
||||
} break;
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
int buttonState = SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
state |= buttonState;
|
||||
} break;
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
double axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), data);
|
||||
if (extraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
axis_value = (axis_value / SDL_AXIS_PEAK);
|
||||
axis_value = abs(axis_value) * direction;
|
||||
return axis_value;
|
||||
}
|
||||
} break;
|
||||
case InputType::Keyboard:
|
||||
{
|
||||
state |= l_KeyboardState[data];
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return state ? direction : value;
|
||||
}
|
||||
|
||||
static double simulate_deadzone(double n64InputAxis, double maxAxis, int deadzone, double axisRange)
|
||||
{
|
||||
double axisAbsolute = std::abs(n64InputAxis);
|
||||
|
||||
if (axisAbsolute < deadzone)
|
||||
if (axisAbsolute <= deadzone)
|
||||
{
|
||||
axisAbsolute = 0; // No input when inside deadzone
|
||||
}
|
||||
@@ -450,6 +476,8 @@ static unsigned char data_crc(unsigned char *data, int length)
|
||||
|
||||
void sdl_init()
|
||||
{
|
||||
std::filesystem::path gameControllerDbPath;
|
||||
|
||||
for (int subsystem : {SDL_INIT_GAMECONTROLLER, SDL_INIT_VIDEO, SDL_INIT_HAPTIC})
|
||||
{
|
||||
if (!SDL_WasInit(subsystem))
|
||||
@@ -457,6 +485,12 @@ void sdl_init()
|
||||
SDL_InitSubSystem(subsystem);
|
||||
}
|
||||
}
|
||||
|
||||
gameControllerDbPath = CoreGetSharedDataDirectory();
|
||||
gameControllerDbPath += "/gamecontrollerdb.txt";
|
||||
|
||||
// load mappings from file
|
||||
SDL_GameControllerAddMappingsFromFile(gameControllerDbPath.string().c_str());
|
||||
}
|
||||
|
||||
void sdl_quit()
|
||||
|
||||
+27
-14
@@ -5,15 +5,19 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(${QT_VERSION} COMPONENTS Gui Widgets Core OpenGL REQUIRED)
|
||||
find_package(Qt6 COMPONENTS Gui Widgets Core OpenGL REQUIRED)
|
||||
|
||||
if (PORTABLE_INSTALL)
|
||||
add_definitions(-DPORTABLE_INSTALL)
|
||||
endif(PORTABLE_INSTALL)
|
||||
|
||||
if (UPDATER)
|
||||
find_package(${QT_VERSION} COMPONENTS Network REQUIRED)
|
||||
add_definitions(-DUPDATER)
|
||||
find_package(Qt6 COMPONENTS Network REQUIRED)
|
||||
add_definitions(-DUPDATER)
|
||||
endif(UPDATER)
|
||||
|
||||
if (DISCORD_RPC)
|
||||
add_definitions(-DDISCORD_RPC)
|
||||
add_definitions(-DDISCORD_RPC)
|
||||
endif(DISCORD_RPC)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
@@ -51,28 +55,36 @@ set(RMG_SOURCES
|
||||
Thread/RomSearcherThread.cpp
|
||||
Thread/EmulationThread.cpp
|
||||
Utilities/QtKeyToSdl2Key.cpp
|
||||
OnScreenDisplay.cpp
|
||||
Callbacks.cpp
|
||||
VidExt.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if (UPDATER)
|
||||
list(APPEND RMG_SOURCES
|
||||
UserInterface/Dialog/UpdateDialog.cpp
|
||||
UserInterface/Dialog/UpdateDialog.ui
|
||||
UserInterface/Dialog/DownloadUpdateDialog.cpp
|
||||
UserInterface/Dialog/DownloadUpdateDialog.ui
|
||||
UserInterface/Dialog/InstallUpdateDialog.cpp
|
||||
UserInterface/Dialog/InstallUpdateDialog.ui
|
||||
)
|
||||
list(APPEND RMG_SOURCES
|
||||
UserInterface/Dialog/UpdateDialog.cpp
|
||||
UserInterface/Dialog/UpdateDialog.ui
|
||||
UserInterface/Dialog/DownloadUpdateDialog.cpp
|
||||
UserInterface/Dialog/DownloadUpdateDialog.ui
|
||||
UserInterface/Dialog/InstallUpdateDialog.cpp
|
||||
UserInterface/Dialog/InstallUpdateDialog.ui
|
||||
)
|
||||
endif(UPDATER)
|
||||
|
||||
set_source_files_properties(${IMGUI_SOURCES} PROPERTIES GENERATED TRUE)
|
||||
list(APPEND RMG_SOURCES ${IMGUI_SOURCES})
|
||||
|
||||
if (CMAKE_BUILD_TYPE MATCHES Release)
|
||||
add_executable(RMG WIN32 ${RMG_SOURCES})
|
||||
else()
|
||||
add_executable(RMG ${RMG_SOURCES})
|
||||
endif()
|
||||
|
||||
add_dependencies(RMG
|
||||
imgui
|
||||
)
|
||||
|
||||
target_link_libraries(RMG
|
||||
RMG-Core
|
||||
)
|
||||
@@ -82,11 +94,12 @@ target_include_directories(RMG PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
${IMGUI_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(RMG ${QT_VERSION}::Gui ${QT_VERSION}::Widgets ${QT_VERSION}::OpenGL)
|
||||
target_link_libraries(RMG Qt6::Gui Qt6::Widgets Qt6::OpenGL)
|
||||
|
||||
if (UPDATER)
|
||||
target_link_libraries(RMG ${QT_VERSION}::Network)
|
||||
target_link_libraries(RMG Qt6::Network)
|
||||
endif(UPDATER)
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "OnScreenDisplay.hpp"
|
||||
|
||||
#include <RMG-Core/Core.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <backends/imgui_impl_opengl3.h>
|
||||
#include <chrono>
|
||||
|
||||
//
|
||||
// Local Variables
|
||||
//
|
||||
|
||||
static bool l_Initialized = false;
|
||||
static bool l_Enabled = false;
|
||||
static bool l_RenderingPaused = false;
|
||||
|
||||
static std::chrono::time_point<std::chrono::high_resolution_clock> l_MessageTime;
|
||||
static std::string l_Message;
|
||||
static int l_MessagePosition = 1;
|
||||
static float l_MessagePaddingX = 20.0f;
|
||||
static float l_MessagePaddingY = 20.0f;
|
||||
static float l_MessageOpacity = 1.0f;
|
||||
static int l_MessageDuration = 3;
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
|
||||
bool OnScreenDisplayInit(void)
|
||||
{
|
||||
if (l_Initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
if (!ImGui_ImplOpenGL3_Init())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
l_Initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnScreenDisplayShutdown(void)
|
||||
{
|
||||
if (!l_Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
l_Message = "";
|
||||
l_Initialized = false;
|
||||
l_RenderingPaused = false;
|
||||
}
|
||||
|
||||
void OnScreenDisplayLoadSettings(void)
|
||||
{
|
||||
l_Enabled = CoreSettingsGetBoolValue(SettingsID::GUI_OnScreenDisplayEnabled);
|
||||
l_MessagePosition = CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayLocation);
|
||||
l_MessagePaddingX = CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingX);
|
||||
l_MessagePaddingY = CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingY);
|
||||
l_MessageOpacity = CoreSettingsGetFloatValue(SettingsID::GUI_OnScreenDisplayOpacity);
|
||||
l_MessageDuration = CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayDuration);
|
||||
}
|
||||
|
||||
bool OnScreenDisplaySetDisplaySize(int width, int height)
|
||||
{
|
||||
if (!l_Initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.IniFilename = nullptr;
|
||||
io.DisplaySize = ImVec2((float)width, (float)height);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnScreenDisplaySetMessage(std::string message)
|
||||
{
|
||||
if (!l_Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
l_Message = message;
|
||||
l_MessageTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void OnScreenDisplayRender(void)
|
||||
{
|
||||
if (!l_Initialized || !l_Enabled || l_RenderingPaused || l_Message.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
const int secondsPassed = std::chrono::duration_cast<std::chrono::seconds>(currentTime - l_MessageTime).count();
|
||||
if (secondsPassed >= l_MessageDuration)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(l_MessageOpacity);
|
||||
|
||||
// right bottom = ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - 20.0f, io.DisplaySize.y - 20.0f), ImGuiCond_Always, ImVec2(1.0f, 1.0f));
|
||||
// right top = ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - 20.0f, 20.0f), ImGuiCond_Always, ImVec2(1.0f, 0));
|
||||
// left bottom = ImGui::SetNextWindowPos(ImVec2(20.0f, io.DisplaySize.y - 20.0f), ImGuiCond_Always, ImVec2(0.0f, 1.0f));
|
||||
// left top = ImGui::SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
|
||||
switch (l_MessagePosition)
|
||||
{
|
||||
default:
|
||||
case 0: // left bottom
|
||||
ImGui::SetNextWindowPos(ImVec2(l_MessagePaddingX, io.DisplaySize.y - l_MessagePaddingY), ImGuiCond_Always, ImVec2(0.0f, 1.0f));
|
||||
break;
|
||||
case 1: // left top
|
||||
ImGui::SetNextWindowPos(ImVec2(l_MessagePaddingX, l_MessagePaddingY), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
|
||||
break;
|
||||
case 2: // right top
|
||||
ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - l_MessagePaddingX, l_MessagePaddingY), ImGuiCond_Always, ImVec2(1.0f, 0));
|
||||
break;
|
||||
case 3: // right bottom
|
||||
ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - l_MessagePaddingX, io.DisplaySize.y - l_MessagePaddingY), ImGuiCond_Always, ImVec2(1.0f, 1.0f));
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::Begin("Message", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
ImGui::Text("%s", l_Message.c_str());
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
void OnScreenDisplayPause(void)
|
||||
{
|
||||
l_RenderingPaused = true;
|
||||
}
|
||||
|
||||
void OnScreenDisplayResume(void)
|
||||
{
|
||||
l_RenderingPaused = false;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RMG_ONSCREENDISPLAY_HPP
|
||||
#define RMG_ONSCREENDISPLAY_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
// attempts to initialize the OSD
|
||||
bool OnScreenDisplayInit(void);
|
||||
|
||||
// shuts down the OSD when initialized
|
||||
void OnScreenDisplayShutdown(void);
|
||||
|
||||
// loads settings for the OSD
|
||||
void OnScreenDisplayLoadSettings(void);
|
||||
|
||||
// sets the display size for the OSD
|
||||
bool OnScreenDisplaySetDisplaySize(int width, int height);
|
||||
|
||||
// sets the current message to the OSD
|
||||
void OnScreenDisplaySetMessage(std::string message);
|
||||
|
||||
// renders the OSD
|
||||
void OnScreenDisplayRender(void);
|
||||
|
||||
// pauses OSD rendering
|
||||
void OnScreenDisplayPause(void);
|
||||
|
||||
// resumes OSD rendering
|
||||
void OnScreenDisplayResume(void);
|
||||
|
||||
#endif // RMG_ONSCREENDISPLAY_HPP
|
||||
@@ -18,6 +18,7 @@ using namespace Thread;
|
||||
|
||||
RomSearcherThread::RomSearcherThread(QObject *parent) : QThread(parent)
|
||||
{
|
||||
qRegisterMetaType<CoreRomType>("CoreRomType");
|
||||
qRegisterMetaType<CoreRomHeader>("CoreRomHeader");
|
||||
qRegisterMetaType<CoreRomSettings>("CoreRomSettings");
|
||||
}
|
||||
@@ -75,6 +76,7 @@ void RomSearcherThread::searchDirectory(QString directory)
|
||||
QDirIterator::NoIteratorFlags;
|
||||
QDirIterator romDirIt(directory, filter, QDir::Files, flag);
|
||||
|
||||
CoreRomType type;
|
||||
CoreRomHeader header;
|
||||
CoreRomSettings settings;
|
||||
bool ret;
|
||||
@@ -89,20 +91,24 @@ void RomSearcherThread::searchDirectory(QString directory)
|
||||
|
||||
if (CoreHasRomHeaderAndSettingsCached(file.toStdU32String()))
|
||||
{ // found cache entry
|
||||
ret = CoreGetCachedRomHeaderAndSettings(file.toStdU32String(), header, settings);
|
||||
ret = CoreGetCachedRomHeaderAndSettings(file.toStdU32String(), type, header, settings);
|
||||
}
|
||||
else
|
||||
{ // no cache entry
|
||||
// open rom, retrieve rom settings & header
|
||||
ret = CoreOpenRom(file.toStdU32String()) &&
|
||||
ret = CoreOpenRom(file.toStdU32String()) &&
|
||||
CoreGetCurrentRomSettings(settings) &&
|
||||
CoreGetCurrentRomHeader(header);
|
||||
if (ret)
|
||||
{
|
||||
type = CoreGetRomType();
|
||||
}
|
||||
// always close the ROM,
|
||||
// even when retrieving rom info failed
|
||||
ret = CoreCloseRom() && ret;
|
||||
if (ret)
|
||||
{ // add to cache when everything succeeded
|
||||
CoreAddCachedRomHeaderAndSettings(file.toStdU32String(), header, settings);
|
||||
CoreAddCachedRomHeaderAndSettings(file.toStdU32String(), type, header, settings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +119,7 @@ void RomSearcherThread::searchDirectory(QString directory)
|
||||
break;
|
||||
}
|
||||
|
||||
emit this->RomFound(file, header, settings);
|
||||
emit this->RomFound(file, type, header, settings);
|
||||
}
|
||||
|
||||
if (this->stop)
|
||||
|
||||
@@ -41,7 +41,7 @@ class RomSearcherThread : public QThread
|
||||
void searchDirectory(QString);
|
||||
|
||||
signals:
|
||||
void RomFound(QString file, CoreRomHeader header, CoreRomSettings settings);
|
||||
void RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings);
|
||||
void Finished(bool canceled);
|
||||
};
|
||||
} // namespace Thread
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Copyright © 2020-2022 Rosalie Wanders</string>
|
||||
<string>Copyright © 2020-2023 Rosalie Wanders</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "SettingsDialog.hpp"
|
||||
#include "OnScreenDisplay.hpp"
|
||||
#include "RMG-Core/DiscordRpc.hpp"
|
||||
#include "RMG-Core/Settings/Settings.hpp"
|
||||
#include "UserInterface/Widget/KeybindButton.hpp"
|
||||
@@ -42,18 +43,18 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent)
|
||||
else
|
||||
{
|
||||
this->hideEmulationInfoText();
|
||||
this->tabWidget->setTabEnabled(1, false);
|
||||
this->tabWidget->setTabEnabled(3, false);
|
||||
}
|
||||
|
||||
pluginList = CoreGetAllPlugins();
|
||||
|
||||
for (int i = 0; i < 13; i++)
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
this->reloadSettings(i);
|
||||
this->loadSettings(i);
|
||||
}
|
||||
|
||||
// connect hotkey settings to slot
|
||||
this->commonHotkeySettings(-1);
|
||||
this->commonHotkeySettings(SettingsDialogAction::ConnectSignals);
|
||||
|
||||
#ifndef UPDATER
|
||||
this->checkForUpdatesCheckBox->setHidden(true);
|
||||
@@ -61,19 +62,8 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent)
|
||||
|
||||
#ifndef DISCORD_RPC
|
||||
this->discordRpcCheckBox->setHidden(true);
|
||||
|
||||
// if both DISCORD_RPC & UPDATER
|
||||
// aren't defined, hide the tab
|
||||
// with the settings for those
|
||||
#ifndef UPDATER
|
||||
this->innerInterfaceTabWidget->removeTab(4);
|
||||
#endif // !UPDATER
|
||||
#endif // !DISCORD_RPC
|
||||
|
||||
#ifndef _WIN32
|
||||
this->innerInterfaceTabWidget->removeTab(3);
|
||||
#endif
|
||||
|
||||
int width = CoreSettingsGetIntValue(SettingsID::GUI_SettingsDialogWidth);
|
||||
int height = CoreSettingsGetIntValue(SettingsID::GUI_SettingsDialogHeight);
|
||||
|
||||
@@ -94,29 +84,33 @@ SettingsDialog::~SettingsDialog(void)
|
||||
|
||||
void SettingsDialog::ShowGameTab(void)
|
||||
{
|
||||
this->tabWidget->setCurrentIndex(1);
|
||||
this->tabWidget->setCurrentIndex(3);
|
||||
}
|
||||
|
||||
int SettingsDialog::currentIndex(void)
|
||||
{
|
||||
int currentIndex = this->tabWidget->currentIndex();
|
||||
int index = currentIndex;
|
||||
|
||||
if (currentIndex == 1)
|
||||
{ // game tab
|
||||
currentIndex += this->innerGameTabWidget->currentIndex();
|
||||
}
|
||||
|
||||
if (currentIndex > 1)
|
||||
{ // above game tab
|
||||
currentIndex += this->innerGameTabWidget->count() - 1;
|
||||
}
|
||||
|
||||
if (currentIndex == 8)
|
||||
if (currentIndex == 0)
|
||||
{ // interface tab
|
||||
currentIndex += this->innerInterfaceTabWidget->currentIndex();
|
||||
index += this->innerInterfaceTabWidget->currentIndex();
|
||||
}
|
||||
else if (currentIndex > 0)
|
||||
{ // above interface tab
|
||||
index += this->innerInterfaceTabWidget->count() - 1;
|
||||
}
|
||||
|
||||
return currentIndex;
|
||||
if (currentIndex == 3)
|
||||
{ // game tab
|
||||
index += this->innerGameTabWidget->currentIndex();
|
||||
}
|
||||
else if (currentIndex > 3)
|
||||
{ // above game tab
|
||||
index += this->innerGameTabWidget->count() - 1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void SettingsDialog::restoreDefaults(int stackedWidgetIndex)
|
||||
@@ -124,91 +118,93 @@ void SettingsDialog::restoreDefaults(int stackedWidgetIndex)
|
||||
switch (stackedWidgetIndex)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case 0:
|
||||
this->loadDefaultCoreSettings();
|
||||
break;
|
||||
case 1:
|
||||
this->loadDefaultGameSettings();
|
||||
break;
|
||||
case 2:
|
||||
this->loadDefaultGameCoreSettings();
|
||||
break;
|
||||
case 3:
|
||||
this->loadDefaultGamePluginSettings();
|
||||
break;
|
||||
case 4:
|
||||
this->loadDefaultPluginSettings();
|
||||
break;
|
||||
case 5:
|
||||
this->loadDefaultDirectorySettings();
|
||||
break;
|
||||
case 6:
|
||||
this->loadDefault64DDSettings();
|
||||
break;
|
||||
case 7:
|
||||
this->loadDefaultHotkeySettings();
|
||||
break;
|
||||
case 8:
|
||||
this->loadDefaultInterfaceEmulationSettings();
|
||||
break;
|
||||
case 9:
|
||||
case 1:
|
||||
this->loadDefaultInterfaceRomBrowserSettings();
|
||||
break;
|
||||
case 2:
|
||||
this->loadDefaultInterfaceLogSettings();
|
||||
break;
|
||||
case 3:
|
||||
this->loadDefaultInterfaceOSDSettings();
|
||||
break;
|
||||
case 4:
|
||||
this->loadDefaultInterfaceMiscSettings();
|
||||
break;
|
||||
case 5:
|
||||
this->loadDefaultHotkeySettings();
|
||||
break;
|
||||
case 6:
|
||||
this->loadDefaultCoreSettings();
|
||||
break;
|
||||
case 7:
|
||||
this->loadDefaultGameSettings();
|
||||
break;
|
||||
case 8:
|
||||
this->loadDefaultGameCoreSettings();
|
||||
break;
|
||||
case 9:
|
||||
this->loadDefaultGamePluginSettings();
|
||||
break;
|
||||
case 10:
|
||||
this->loadDefaultInterfaceLogWindowSettings();
|
||||
this->loadDefaultPluginSettings();
|
||||
break;
|
||||
case 11:
|
||||
this->loadDefaultInterfaceStyleSettings();
|
||||
this->loadDefaultDirectorySettings();
|
||||
break;
|
||||
case 12:
|
||||
this->loadDefaultInterfaceMiscSettings();
|
||||
this->loadDefault64DDSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::reloadSettings(int stackedWidgetIndex)
|
||||
void SettingsDialog::loadSettings(int stackedWidgetIndex)
|
||||
{
|
||||
switch (stackedWidgetIndex)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case 0:
|
||||
this->loadCoreSettings();
|
||||
break;
|
||||
case 1:
|
||||
this->loadGameSettings();
|
||||
break;
|
||||
case 2:
|
||||
this->loadGameCoreSettings();
|
||||
break;
|
||||
case 3:
|
||||
this->loadGamePluginSettings();
|
||||
break;
|
||||
case 4:
|
||||
this->loadPluginSettings();
|
||||
break;
|
||||
case 5:
|
||||
this->loadDirectorySettings();
|
||||
break;
|
||||
case 6:
|
||||
this->load64DDSettings();
|
||||
break;
|
||||
case 7:
|
||||
this->loadHotkeySettings();
|
||||
break;
|
||||
case 8:
|
||||
this->loadInterfaceEmulationSettings();
|
||||
break;
|
||||
case 9:
|
||||
case 1:
|
||||
this->loadInterfaceRomBrowserSettings();
|
||||
break;
|
||||
case 2:
|
||||
this->loadInterfaceLogSettings();
|
||||
break;
|
||||
case 3:
|
||||
this->loadInterfaceOSDSettings();
|
||||
break;
|
||||
case 4:
|
||||
this->loadInterfaceMiscSettings();
|
||||
break;
|
||||
case 5:
|
||||
this->loadHotkeySettings();
|
||||
break;
|
||||
case 6:
|
||||
this->loadCoreSettings();
|
||||
break;
|
||||
case 7:
|
||||
this->loadGameSettings();
|
||||
break;
|
||||
case 8:
|
||||
this->loadGameCoreSettings();
|
||||
break;
|
||||
case 9:
|
||||
this->loadGamePluginSettings();
|
||||
break;
|
||||
case 10:
|
||||
this->loadInterfaceLogWindowSettings();
|
||||
this->loadPluginSettings();
|
||||
break;
|
||||
case 11:
|
||||
this->loadInterfaceStyleSettings();
|
||||
this->loadDirectorySettings();
|
||||
break;
|
||||
case 12:
|
||||
this->loadInterfaceMiscSettings();
|
||||
this->load64DDSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +320,7 @@ void SettingsDialog::loadGamePluginSettings(void)
|
||||
|
||||
void SettingsDialog::loadPluginSettings(void)
|
||||
{
|
||||
this->commonPluginSettings(0);
|
||||
this->commonPluginSettings(SettingsDialogAction::LoadSettings);
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDirectorySettings(void)
|
||||
@@ -373,12 +369,11 @@ void SettingsDialog::load64DDSettings(void)
|
||||
|
||||
void SettingsDialog::loadHotkeySettings(void)
|
||||
{
|
||||
this->commonHotkeySettings(0);
|
||||
this->commonHotkeySettings(SettingsDialogAction::LoadSettings);
|
||||
}
|
||||
|
||||
void SettingsDialog::loadInterfaceEmulationSettings(void)
|
||||
{
|
||||
this->manualResizingCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_AllowManualResizing));
|
||||
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
|
||||
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
|
||||
this->hideCursorCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInEmulation));
|
||||
@@ -390,21 +385,28 @@ void SettingsDialog::loadInterfaceEmulationSettings(void)
|
||||
void SettingsDialog::loadInterfaceRomBrowserSettings(void)
|
||||
{
|
||||
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::RomBrowser_Recursive));
|
||||
this->sortRomBrowserResultsCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::RomBrowser_SortAfterSearch));
|
||||
this->romSearchLimitSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::RomBrowser_MaxItems));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadInterfaceLogWindowSettings(void)
|
||||
void SettingsDialog::loadInterfaceLogSettings(void)
|
||||
{
|
||||
this->showVerboseLogMessagesCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ShowVerboseLogMessages));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadInterfaceStyleSettings(void)
|
||||
void SettingsDialog::loadInterfaceOSDSettings(void)
|
||||
{
|
||||
this->commonInterfaceStyleSettings(0);
|
||||
this->osdEnabledCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_OnScreenDisplayEnabled));
|
||||
this->osdLocationComboBox->setCurrentIndex(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayLocation));
|
||||
this->osdVerticalPaddingSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingY));
|
||||
this->osdHorizontalPaddingSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingX));
|
||||
this->osdOpacitySpinBox->setValue(CoreSettingsGetFloatValue(SettingsID::GUI_OnScreenDisplayOpacity));
|
||||
this->osdDurationSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayDuration));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadInterfaceMiscSettings(void)
|
||||
{
|
||||
this->themeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_Theme)));
|
||||
#ifdef UPDATER
|
||||
this->checkForUpdatesCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_CheckForUpdates));
|
||||
#endif // UPDATER
|
||||
@@ -487,7 +489,7 @@ void SettingsDialog::loadDefaultGamePluginSettings(void)
|
||||
|
||||
void SettingsDialog::loadDefaultPluginSettings(void)
|
||||
{
|
||||
this->commonPluginSettings(1);
|
||||
this->commonPluginSettings(SettingsDialogAction::LoadDefaultSettings);
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDefaultDirectorySettings(void)
|
||||
@@ -510,12 +512,11 @@ void SettingsDialog::loadDefault64DDSettings(void)
|
||||
|
||||
void SettingsDialog::loadDefaultHotkeySettings(void)
|
||||
{
|
||||
this->commonHotkeySettings(1);
|
||||
this->commonHotkeySettings(SettingsDialogAction::LoadDefaultSettings);
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDefaultInterfaceEmulationSettings(void)
|
||||
{
|
||||
this->manualResizingCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_AllowManualResizing));
|
||||
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
|
||||
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
|
||||
this->hideCursorCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_HideCursorInEmulation));
|
||||
@@ -527,21 +528,28 @@ void SettingsDialog::loadDefaultInterfaceEmulationSettings(void)
|
||||
void SettingsDialog::loadDefaultInterfaceRomBrowserSettings(void)
|
||||
{
|
||||
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::RomBrowser_Recursive));
|
||||
this->sortRomBrowserResultsCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::RomBrowser_SortAfterSearch));
|
||||
this->romSearchLimitSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::RomBrowser_MaxItems));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDefaultInterfaceLogWindowSettings(void)
|
||||
void SettingsDialog::loadDefaultInterfaceLogSettings(void)
|
||||
{
|
||||
this->showVerboseLogMessagesCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ShowVerboseLogMessages));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDefaultInterfaceStyleSettings(void)
|
||||
void SettingsDialog::loadDefaultInterfaceOSDSettings(void)
|
||||
{
|
||||
this->commonInterfaceStyleSettings(1);
|
||||
this->osdEnabledCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_OnScreenDisplayEnabled));
|
||||
this->osdLocationComboBox->setCurrentIndex(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayLocation));
|
||||
this->osdVerticalPaddingSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayPaddingY));
|
||||
this->osdHorizontalPaddingSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayPaddingX));
|
||||
this->osdOpacitySpinBox->setValue(CoreSettingsGetDefaultFloatValue(SettingsID::GUI_OnScreenDisplayOpacity));
|
||||
this->osdDurationSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayDuration));
|
||||
}
|
||||
|
||||
void SettingsDialog::loadDefaultInterfaceMiscSettings(void)
|
||||
{
|
||||
this->themeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::GUI_Theme)));
|
||||
#ifdef UPDATER
|
||||
this->checkForUpdatesCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_CheckForUpdates));
|
||||
#endif // UPDATER
|
||||
@@ -567,8 +575,8 @@ void SettingsDialog::saveSettings(void)
|
||||
this->saveHotkeySettings();
|
||||
this->saveInterfaceEmulationSettings();
|
||||
this->saveInterfaceRomBrowserSettings();
|
||||
this->saveInterfaceLogWindowSettings();
|
||||
this->saveInterfaceStyleSettings();
|
||||
this->saveInterfaceLogSettings();
|
||||
this->saveInterfaceOSDSettings();
|
||||
this->saveInterfaceMiscSettings();
|
||||
}
|
||||
|
||||
@@ -708,12 +716,11 @@ void SettingsDialog::save64DDSettings(void)
|
||||
|
||||
void SettingsDialog::saveHotkeySettings(void)
|
||||
{
|
||||
this->commonHotkeySettings(2);
|
||||
this->commonHotkeySettings(SettingsDialogAction::SaveSettings);
|
||||
}
|
||||
|
||||
void SettingsDialog::saveInterfaceEmulationSettings(void)
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::GUI_AllowManualResizing, this->manualResizingCheckBox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::GUI_HideCursorInEmulation, this->hideCursorCheckBox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::GUI_HideCursorInFullscreenEmulation, this->hideCursorFullscreenCheckBox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::GUI_PauseEmulationOnFocusLoss, this->pauseEmulationOnFocusCheckbox->isChecked());
|
||||
@@ -725,24 +732,28 @@ void SettingsDialog::saveInterfaceEmulationSettings(void)
|
||||
void SettingsDialog::saveInterfaceRomBrowserSettings(void)
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Recursive, this->searchSubDirectoriesCheckbox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_SortAfterSearch, this->sortRomBrowserResultsCheckBox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_MaxItems, this->romSearchLimitSpinBox->value());
|
||||
}
|
||||
|
||||
void SettingsDialog::saveInterfaceLogWindowSettings(void)
|
||||
void SettingsDialog::saveInterfaceLogSettings(void)
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::GUI_ShowVerboseLogMessages, this->showVerboseLogMessagesCheckBox->isChecked());
|
||||
}
|
||||
|
||||
void SettingsDialog::saveInterfaceStyleSettings(void)
|
||||
void SettingsDialog::saveInterfaceOSDSettings(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CoreSettingsSetValue(SettingsID::GUI_Style, this->styleComboBox->currentData().toString().toStdString());
|
||||
CoreSettingsSetValue(SettingsID::GUI_IconTheme, this->iconThemeComboBox->currentText().toStdString());
|
||||
#endif // _WIN32
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayEnabled, this->osdEnabledCheckBox->isChecked());
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayLocation, this->osdLocationComboBox->currentIndex());
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayPaddingY, this->osdVerticalPaddingSpinBox->value());
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayPaddingX, this->osdHorizontalPaddingSpinBox->value());
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayOpacity, (float)this->osdOpacitySpinBox->value());
|
||||
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayDuration, this->osdDurationSpinBox->value());
|
||||
}
|
||||
|
||||
void SettingsDialog::saveInterfaceMiscSettings(void)
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::GUI_Theme, this->themeComboBox->currentText().toStdString());
|
||||
#ifdef UPDATER
|
||||
CoreSettingsSetValue(SettingsID::GUI_CheckForUpdates, this->checkForUpdatesCheckBox->isChecked());
|
||||
#endif // UPDATER
|
||||
@@ -751,13 +762,17 @@ void SettingsDialog::saveInterfaceMiscSettings(void)
|
||||
#endif // DISCORD_RPC
|
||||
}
|
||||
|
||||
void SettingsDialog::commonHotkeySettings(int action)
|
||||
void SettingsDialog::commonHotkeySettings(SettingsDialogAction action)
|
||||
{
|
||||
struct
|
||||
struct keybinding
|
||||
{
|
||||
KeybindButton* button;
|
||||
SettingsID settingId;
|
||||
} keybindings[] =
|
||||
};
|
||||
|
||||
std::vector<keybinding> keybindings;
|
||||
|
||||
std::vector<keybinding> keybindings_System =
|
||||
{
|
||||
{ this->startRomKeyButton, SettingsID::KeyBinding_StartROM },
|
||||
{ this->startComboKeyButton, SettingsID::KeyBinding_StartCombo },
|
||||
@@ -775,21 +790,73 @@ void SettingsDialog::commonHotkeySettings(int action)
|
||||
{ this->loadKeyButton, SettingsID::KeyBinding_Load },
|
||||
{ this->cheatsKeyButton, SettingsID::KeyBinding_Cheats },
|
||||
{ this->gsButtonKeyButton, SettingsID::KeyBinding_GSButton },
|
||||
{ this->fullscreenKeyButton, SettingsID::KeyBinding_Fullscreen },
|
||||
};
|
||||
|
||||
std::vector<keybinding> keybindings_CurrentSaveState =
|
||||
{
|
||||
{ this->saveState0KeyButton, SettingsID::KeyBinding_SaveStateSlot0 },
|
||||
{ this->saveState1KeyButton, SettingsID::KeyBinding_SaveStateSlot1 },
|
||||
{ this->saveState2KeyButton, SettingsID::KeyBinding_SaveStateSlot2 },
|
||||
{ this->saveState3KeyButton, SettingsID::KeyBinding_SaveStateSlot3 },
|
||||
{ this->saveState4KeyButton, SettingsID::KeyBinding_SaveStateSlot4 },
|
||||
{ this->saveState5KeyButton, SettingsID::KeyBinding_SaveStateSlot5 },
|
||||
{ this->saveState6KeyButton, SettingsID::KeyBinding_SaveStateSlot6 },
|
||||
{ this->saveState7KeyButton, SettingsID::KeyBinding_SaveStateSlot7 },
|
||||
{ this->saveState8KeyButton, SettingsID::KeyBinding_SaveStateSlot8 },
|
||||
{ this->saveState9KeyButton, SettingsID::KeyBinding_SaveStateSlot9 },
|
||||
};
|
||||
|
||||
std::vector<keybinding> keybindings_Settings =
|
||||
{
|
||||
{ this->settingsKeyButton, SettingsID::KeyBinding_Settings },
|
||||
};
|
||||
|
||||
std::vector<keybinding> keybindings_View =
|
||||
{
|
||||
{ this->fullscreenKeyButton, SettingsID::KeyBinding_Fullscreen },
|
||||
{ this->refreshRomListKeyButton, SettingsID::KeyBinding_RefreshROMList }
|
||||
};
|
||||
|
||||
|
||||
if (action == SettingsDialogAction::LoadDefaultSettings)
|
||||
{
|
||||
int index = this->keybindingsMenuTabWidget->currentIndex();
|
||||
switch (index)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
keybindings.insert(keybindings.end(), keybindings_System.begin(), keybindings_System.end());
|
||||
break;
|
||||
case 1:
|
||||
keybindings.insert(keybindings.end(), keybindings_CurrentSaveState.begin(), keybindings_CurrentSaveState.end());
|
||||
break;
|
||||
case 2:
|
||||
keybindings.insert(keybindings.end(), keybindings_Settings.begin(), keybindings_Settings.end());
|
||||
break;
|
||||
case 3:
|
||||
keybindings.insert(keybindings.end(), keybindings_View.begin(), keybindings_View.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keybindings.insert(keybindings.end(), keybindings_System.begin(), keybindings_System.end());
|
||||
keybindings.insert(keybindings.end(), keybindings_CurrentSaveState.begin(), keybindings_CurrentSaveState.end());
|
||||
keybindings.insert(keybindings.end(), keybindings_Settings.begin(), keybindings_Settings.end());
|
||||
keybindings.insert(keybindings.end(), keybindings_View.begin(), keybindings_View.end());
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case 0:
|
||||
case SettingsDialogAction::LoadSettings:
|
||||
this->removeDuplicateHotkeysCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::KeyBinding_RemoveDuplicates));
|
||||
break;
|
||||
case 1:
|
||||
case SettingsDialogAction::LoadDefaultSettings:
|
||||
this->removeDuplicateHotkeysCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::KeyBinding_RemoveDuplicates));
|
||||
break;
|
||||
case 2:
|
||||
case SettingsDialogAction::SaveSettings:
|
||||
CoreSettingsSetValue(SettingsID::KeyBinding_RemoveDuplicates, this->removeDuplicateHotkeysCheckBox->isChecked());
|
||||
break;
|
||||
}
|
||||
@@ -799,22 +866,23 @@ void SettingsDialog::commonHotkeySettings(int action)
|
||||
switch (action)
|
||||
{
|
||||
default:
|
||||
case -1:
|
||||
case SettingsDialogAction::ConnectSignals:
|
||||
connect(keybinding.button, &KeybindButton::on_KeybindButton_KeybindingChanged, this, &SettingsDialog::on_KeybindButton_KeybindingChanged);
|
||||
case 0:
|
||||
keybinding.button->setText(QString::fromStdString(CoreSettingsGetStringValue(keybinding.settingId)));
|
||||
connect(keybinding.button, &KeybindButton::on_KeybindButton_Clicked, this, &SettingsDialog::on_KeybindButton_Clicked);
|
||||
case SettingsDialogAction::LoadSettings:
|
||||
keybinding.button->SetText(QString::fromStdString(CoreSettingsGetStringValue(keybinding.settingId)));
|
||||
break;
|
||||
case 1:
|
||||
keybinding.button->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(keybinding.settingId)));
|
||||
case SettingsDialogAction::LoadDefaultSettings:
|
||||
keybinding.button->SetText(QString::fromStdString(CoreSettingsGetDefaultStringValue(keybinding.settingId)));
|
||||
break;
|
||||
case 2:
|
||||
CoreSettingsSetValue(keybinding.settingId, keybinding.button->text().toStdString());
|
||||
case SettingsDialogAction::SaveSettings:
|
||||
CoreSettingsSetValue(keybinding.settingId, keybinding.button->GetCurrentText().toStdString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::commonPluginSettings(int action)
|
||||
void SettingsDialog::commonPluginSettings(SettingsDialogAction action)
|
||||
{
|
||||
QComboBox *comboBoxArray[] = {this->rspPluginsComboBox, this->videoPluginsComboBox,
|
||||
this->audioPluginsComboBox, this->inputPluginsComboBox};
|
||||
@@ -837,7 +905,7 @@ void SettingsDialog::commonPluginSettings(int action)
|
||||
index = ((int)p.Type - 1);
|
||||
comboBox = comboBoxArray[index];
|
||||
|
||||
pluginFileName = action == 0 ?
|
||||
pluginFileName = action == SettingsDialogAction::LoadSettings ?
|
||||
CoreSettingsGetStringValue(settingsIdArray[index]) :
|
||||
CoreSettingsGetDefaultStringValue(settingsIdArray[index]);
|
||||
|
||||
@@ -861,63 +929,12 @@ void SettingsDialog::commonPluginSettings(int action)
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::commonInterfaceStyleSettings(int action)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
this->styleComboBox->clear();
|
||||
this->styleComboBox->addItem("None", "");
|
||||
|
||||
QString currentStyle = action == 0 ?
|
||||
QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_Style)) :
|
||||
QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::GUI_Style));
|
||||
|
||||
QString directory;
|
||||
directory = QString::fromStdString(CoreGetSharedDataDirectory().string());
|
||||
directory += "\\Styles\\";
|
||||
|
||||
QStringList filter;
|
||||
filter << "*.qss";
|
||||
|
||||
bool styleFound = false;
|
||||
QDirIterator stylesDirectoryIter(directory, filter, QDir::Files, QDirIterator::NoIteratorFlags);
|
||||
while (stylesDirectoryIter.hasNext())
|
||||
{
|
||||
QString filePath = stylesDirectoryIter.next();
|
||||
QFileInfo fileInfo(filePath);
|
||||
|
||||
this->styleComboBox->addItem(fileInfo.baseName(), filePath);
|
||||
if (filePath == currentStyle)
|
||||
{
|
||||
styleFound = true;
|
||||
this->styleComboBox->setCurrentText(fileInfo.baseName());
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStyle.isEmpty())
|
||||
{
|
||||
this->styleComboBox->setCurrentText("None");
|
||||
styleFound = true;
|
||||
}
|
||||
|
||||
if (!styleFound)
|
||||
{
|
||||
this->styleComboBox->addItem("", "");
|
||||
this->styleComboBox->setCurrentText("");
|
||||
}
|
||||
|
||||
QString currentIconTheme = action == 0 ?
|
||||
QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_IconTheme)) :
|
||||
QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::GUI_IconTheme));
|
||||
this->iconThemeComboBox->setCurrentText(currentIconTheme);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
void SettingsDialog::setIconsForEmulationInfoText(void)
|
||||
{
|
||||
QLabel* labels[] = {
|
||||
this->infoIconLabel_0, this->infoIconLabel_1, this->infoIconLabel_2,
|
||||
this->infoIconLabel_3, this->infoIconLabel_4, this->infoIconLabel_5,
|
||||
this->infoIconLabel_6, this->infoIconLabel_7
|
||||
this->infoIconLabel_7
|
||||
};
|
||||
|
||||
QIcon infoIcon = QIcon::fromTheme("information-line");
|
||||
@@ -1005,6 +1022,23 @@ void SettingsDialog::closeEvent(QCloseEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::timerEvent(QTimerEvent* event)
|
||||
{
|
||||
this->keybindButtonTimeLeft--;
|
||||
|
||||
if (this->currentKeybindButton != nullptr)
|
||||
{
|
||||
this->currentKeybindButton->SetSecondsLeft(this->keybindButtonTimeLeft);
|
||||
}
|
||||
|
||||
if (this->keybindButtonTimeLeft == 0)
|
||||
{
|
||||
this->killTimer(this->keybindButtonTimerId);
|
||||
this->keybindButtonTimerId = -1;
|
||||
this->currentKeybindButton = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
{
|
||||
QPushButton *pushButton = (QPushButton *)button;
|
||||
@@ -1018,6 +1052,9 @@ void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
if (pushButton == okButton)
|
||||
{
|
||||
this->saveSettings();
|
||||
|
||||
// re-load OSD settings
|
||||
OnScreenDisplayLoadSettings();
|
||||
}
|
||||
|
||||
if (!this->applyPluginSettings())
|
||||
@@ -1082,27 +1119,45 @@ void SettingsDialog::on_changeDevelopmentIPLRomPathButton_clicked(void)
|
||||
|
||||
void SettingsDialog::on_KeybindButton_KeybindingChanged(KeybindButton* button)
|
||||
{
|
||||
if (this->keybindButtonTimerId != -1)
|
||||
{
|
||||
this->killTimer(this->keybindButtonTimerId);
|
||||
this->keybindButtonTimerId = -1;
|
||||
}
|
||||
|
||||
if (this->currentKeybindButton != nullptr)
|
||||
{
|
||||
this->currentKeybindButton->Reset();
|
||||
this->currentKeybindButton = nullptr;
|
||||
}
|
||||
|
||||
if (!this->removeDuplicateHotkeysCheckBox->isChecked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QString text = button->text();
|
||||
QString text = button->GetCurrentText();
|
||||
if (text.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KeybindButton* keybindButtons[] =
|
||||
QList<KeybindButton*> rombrowserKeybindButtons =
|
||||
{
|
||||
this->startRomKeyButton,
|
||||
this->startComboKeyButton,
|
||||
this->shutdownKeyButton,
|
||||
this->refreshRomListKeyButton,
|
||||
this->exitKeyButton,
|
||||
this->settingsKeyButton,
|
||||
this->refreshRomListKeyButton,
|
||||
};
|
||||
|
||||
QList<KeybindButton*> emulationKeybindButtons =
|
||||
{
|
||||
this->shutdownKeyButton,
|
||||
this->softResetKeyButton,
|
||||
this->hardResetKeyButton,
|
||||
this->pauseKeyButton,
|
||||
this->pauseKeyButton,
|
||||
this->generateBitmapKeyButton,
|
||||
this->limitFPSKeyButton,
|
||||
this->saveStateKeyButton,
|
||||
@@ -1111,18 +1166,67 @@ void SettingsDialog::on_KeybindButton_KeybindingChanged(KeybindButton* button)
|
||||
this->loadKeyButton,
|
||||
this->cheatsKeyButton,
|
||||
this->gsButtonKeyButton,
|
||||
this->fullscreenKeyButton,
|
||||
this->saveState0KeyButton,
|
||||
this->saveState1KeyButton,
|
||||
this->saveState2KeyButton,
|
||||
this->saveState3KeyButton,
|
||||
this->saveState4KeyButton,
|
||||
this->saveState5KeyButton,
|
||||
this->saveState6KeyButton,
|
||||
this->saveState7KeyButton,
|
||||
this->saveState8KeyButton,
|
||||
this->saveState9KeyButton,
|
||||
this->exitKeyButton,
|
||||
this->settingsKeyButton,
|
||||
this->fullscreenKeyButton,
|
||||
};
|
||||
|
||||
|
||||
QList<KeybindButton*> keybindButtons;
|
||||
|
||||
if (rombrowserKeybindButtons.contains(button))
|
||||
{
|
||||
keybindButtons.append(rombrowserKeybindButtons);
|
||||
}
|
||||
if (emulationKeybindButtons.contains(button))
|
||||
{
|
||||
keybindButtons.append(emulationKeybindButtons);
|
||||
}
|
||||
|
||||
for (KeybindButton* keybindButton : keybindButtons)
|
||||
{
|
||||
if (keybindButton != button)
|
||||
{
|
||||
if (keybindButton->text() == text)
|
||||
if (keybindButton->GetCurrentText() == text)
|
||||
{
|
||||
keybindButton->Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::on_KeybindButton_Clicked(KeybindButton* button)
|
||||
{
|
||||
if (this->currentKeybindButton == button)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->currentKeybindButton != nullptr)
|
||||
{
|
||||
this->currentKeybindButton->Reset();
|
||||
this->currentKeybindButton = nullptr;
|
||||
}
|
||||
|
||||
if (this->keybindButtonTimerId != -1)
|
||||
{
|
||||
this->killTimer(this->keybindButtonTimerId);
|
||||
this->keybindButtonTimerId = -1;
|
||||
}
|
||||
|
||||
this->currentKeybindButton = button;
|
||||
this->keybindButtonTimeLeft = 5;
|
||||
this->keybindButtonTimerId = this->startTimer(1000);
|
||||
|
||||
// notify button
|
||||
this->currentKeybindButton->SetSecondsLeft(5);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QTreeWidget>
|
||||
#include <QWidget>
|
||||
#include <QMutex>
|
||||
|
||||
#include <RMG-Core/Core.hpp>
|
||||
|
||||
@@ -37,18 +38,30 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
enum class SettingsDialogAction
|
||||
{
|
||||
ConnectSignals = 0,
|
||||
LoadSettings,
|
||||
LoadDefaultSettings,
|
||||
SaveSettings
|
||||
};
|
||||
|
||||
bool romOpened = false;
|
||||
|
||||
CoreRomSettings currentGameSettings;
|
||||
CoreRomSettings defaultGameSettings;
|
||||
std::string gameSection;
|
||||
|
||||
int keybindButtonTimerId = -1;
|
||||
int keybindButtonTimeLeft = 5;
|
||||
KeybindButton* currentKeybindButton = nullptr;
|
||||
|
||||
std::vector<CorePlugin> pluginList;
|
||||
|
||||
int currentIndex(void);
|
||||
|
||||
void restoreDefaults(int);
|
||||
void reloadSettings(int);
|
||||
void loadSettings(int);
|
||||
void saveSettings(int);
|
||||
|
||||
void loadCoreSettings(void);
|
||||
@@ -61,7 +74,8 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
void loadHotkeySettings(void);
|
||||
void loadInterfaceEmulationSettings(void);
|
||||
void loadInterfaceRomBrowserSettings(void);
|
||||
void loadInterfaceLogWindowSettings(void);
|
||||
void loadInterfaceLogSettings(void);
|
||||
void loadInterfaceOSDSettings(void);
|
||||
void loadInterfaceStyleSettings(void);
|
||||
void loadInterfaceMiscSettings(void);
|
||||
|
||||
@@ -75,7 +89,8 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
void loadDefaultHotkeySettings(void);
|
||||
void loadDefaultInterfaceEmulationSettings(void);
|
||||
void loadDefaultInterfaceRomBrowserSettings(void);
|
||||
void loadDefaultInterfaceLogWindowSettings(void);
|
||||
void loadDefaultInterfaceLogSettings(void);
|
||||
void loadDefaultInterfaceOSDSettings(void);
|
||||
void loadDefaultInterfaceStyleSettings(void);
|
||||
void loadDefaultInterfaceMiscSettings(void);
|
||||
|
||||
@@ -90,13 +105,13 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
void saveHotkeySettings(void);
|
||||
void saveInterfaceEmulationSettings(void);
|
||||
void saveInterfaceRomBrowserSettings(void);
|
||||
void saveInterfaceLogWindowSettings(void);
|
||||
void saveInterfaceLogSettings(void);
|
||||
void saveInterfaceOSDSettings(void);
|
||||
void saveInterfaceStyleSettings(void);
|
||||
void saveInterfaceMiscSettings(void);
|
||||
|
||||
void commonHotkeySettings(int);
|
||||
void commonPluginSettings(int);
|
||||
void commonInterfaceStyleSettings(int);
|
||||
void commonHotkeySettings(SettingsDialogAction);
|
||||
void commonPluginSettings(SettingsDialogAction);
|
||||
|
||||
void setIconsForEmulationInfoText(void);
|
||||
void hideEmulationInfoText(void);
|
||||
@@ -108,6 +123,7 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE;
|
||||
void timerEvent(QTimerEvent* event) Q_DECL_OVERRIDE;
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *);
|
||||
@@ -123,6 +139,8 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
void on_changeDevelopmentIPLRomPathButton_clicked(void);
|
||||
|
||||
void on_KeybindButton_KeybindingChanged(KeybindButton* button);
|
||||
void on_KeybindButton_Clicked(KeybindButton* button);
|
||||
|
||||
public:
|
||||
SettingsDialog(QWidget *parent);
|
||||
~SettingsDialog(void);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@
|
||||
#endif // UPDATER
|
||||
#include "UserInterface/EventFilter.hpp"
|
||||
#include "Utilities/QtKeyToSdl2Key.hpp"
|
||||
#include "OnScreenDisplay.hpp"
|
||||
#include "Callbacks.hpp"
|
||||
#include "VidExt.hpp"
|
||||
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QStyleFactory>
|
||||
#include <QFileDialog>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
@@ -34,6 +36,7 @@
|
||||
#include <QUrl>
|
||||
#include <QActionGroup>
|
||||
#include <QTimer>
|
||||
#include <cmath>
|
||||
|
||||
using namespace UserInterface;
|
||||
|
||||
@@ -94,14 +97,32 @@ bool MainWindow::Init(QApplication* app)
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::OpenROM(QString file, QString disk, bool fullscreen)
|
||||
void MainWindow::OpenROM(QString file, QString disk, bool fullscreen, bool quitAfterEmulation)
|
||||
{
|
||||
this->ui_LaunchInFullscreen = fullscreen;
|
||||
this->ui_QuitAfterEmulation = quitAfterEmulation;
|
||||
|
||||
// ensure we don't switch to the ROM browser
|
||||
// because it can cause a slight flicker,
|
||||
// if we just ensure the UI is in an emulation
|
||||
// state, then the transition will be smoother
|
||||
this->updateUI(true, false);
|
||||
|
||||
this->launchEmulationThread(file, disk);
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
// we have to make sure we save the geomtry
|
||||
// for the ROM browser when emulation
|
||||
// isn't running (or hasn't run at all)
|
||||
if (!this->ui_QuitAfterEmulation &&
|
||||
!this->emulationThread->isRunning())
|
||||
{
|
||||
this->storeGeometry();
|
||||
}
|
||||
|
||||
this->ui_NoSwitchToRomBrowser = true;
|
||||
this->on_Action_System_Shutdown();
|
||||
|
||||
this->ui_Widget_RomBrowser->StopRefreshRomList();
|
||||
@@ -115,11 +136,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
std::string geometryStr = this->saveGeometry().toBase64().toStdString();
|
||||
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Geometry, geometryStr);
|
||||
CoreSettingsSave();
|
||||
|
||||
CoreShutdown();
|
||||
|
||||
QMainWindow::closeEvent(event);
|
||||
@@ -139,14 +156,14 @@ void MainWindow::initializeUI(void)
|
||||
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::PlayGame, this,
|
||||
&MainWindow::on_RomBrowser_PlayGame);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::PlayGameWithDisk, this,
|
||||
&MainWindow::on_RomBrowser_PlayGameWithDisk);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::PlayGameWith, this,
|
||||
&MainWindow::on_RomBrowser_PlayGameWith);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::EditGameSettings, this,
|
||||
&MainWindow::on_RomBrowser_EditGameSettings);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::Cheats, this,
|
||||
&MainWindow::on_RomBrowser_Cheats);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::ChooseRomDirectory, this,
|
||||
&MainWindow::on_Action_File_ChooseDirectory);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::ChangeRomDirectory, this,
|
||||
&MainWindow::on_RomBrowser_ChangeRomDirectory);
|
||||
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::RomInformation, this,
|
||||
&MainWindow::on_RomBrowser_RomInformation);
|
||||
|
||||
@@ -161,8 +178,15 @@ void MainWindow::configureUI(QApplication* app)
|
||||
this->setCentralWidget(this->ui_Widgets);
|
||||
|
||||
QString geometry;
|
||||
bool maximized;
|
||||
|
||||
geometry = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::RomBrowser_Geometry));
|
||||
if (!geometry.isEmpty())
|
||||
maximized = CoreSettingsGetBoolValue(SettingsID::RomBrowser_Maximized);
|
||||
if (maximized)
|
||||
{
|
||||
this->showMaximized();
|
||||
}
|
||||
else if (!geometry.isEmpty())
|
||||
{
|
||||
this->restoreGeometry(QByteArray::fromBase64(geometry.toLocal8Bit()));
|
||||
}
|
||||
@@ -179,7 +203,7 @@ void MainWindow::configureUI(QApplication* app)
|
||||
this->ui_Widgets->addWidget(this->ui_Widget_RomBrowser);
|
||||
this->ui_Widgets->addWidget(this->ui_Widget_OpenGL->GetWidget());
|
||||
|
||||
this->ui_Widgets->setCurrentIndex(0);
|
||||
this->ui_Widgets->setCurrentWidget(this->ui_Widget_RomBrowser);
|
||||
|
||||
this->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
|
||||
this->installEventFilter(this->ui_EventFilter);
|
||||
@@ -194,42 +218,70 @@ void MainWindow::configureUI(QApplication* app)
|
||||
|
||||
void MainWindow::configureTheme(QApplication* app)
|
||||
{
|
||||
// we have to retrieve the fallback icon theme
|
||||
// before applying the app theme
|
||||
QString fallbackThemeName = QIcon::themeName();
|
||||
|
||||
// set theme style
|
||||
QString fallbackStyleSheet = "QTableView { border: none; color: #0096d3; selection-color: #FFFFFF; selection-background-color: #0096d3; }";
|
||||
|
||||
#ifndef _WIN32
|
||||
this->setStyleSheet(fallbackStyleSheet);
|
||||
|
||||
// set application theme
|
||||
QString theme = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_Theme));
|
||||
if (theme == "Fusion")
|
||||
{
|
||||
app->setPalette(QApplication::style()->standardPalette());
|
||||
app->setStyleSheet(QString());
|
||||
app->setStyle(QStyleFactory::create("Fusion"));
|
||||
}
|
||||
else if (theme == "Fusion Dark")
|
||||
{
|
||||
// adapted from https://gist.github.com/QuantumCD/6245215
|
||||
app->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
const QColor lighterGray(75, 75, 75);
|
||||
const QColor darkGray(53, 53, 53);
|
||||
const QColor gray(128, 128, 128);
|
||||
const QColor black(25, 25, 25);
|
||||
const QColor blue(198, 238, 255);
|
||||
|
||||
QPalette darkPalette;
|
||||
darkPalette.setColor(QPalette::Window, darkGray);
|
||||
darkPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Base, black);
|
||||
darkPalette.setColor(QPalette::AlternateBase, darkGray);
|
||||
darkPalette.setColor(QPalette::ToolTipBase, darkGray);
|
||||
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Text, Qt::white);
|
||||
darkPalette.setColor(QPalette::Button, darkGray);
|
||||
darkPalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Link, blue);
|
||||
darkPalette.setColor(QPalette::Highlight, lighterGray);
|
||||
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
darkPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
|
||||
|
||||
darkPalette.setColor(QPalette::Active, QPalette::Button, darkGray);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
|
||||
|
||||
app->setPalette(darkPalette);
|
||||
|
||||
app->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
|
||||
}
|
||||
else if (theme == "Native")
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// set icon theme
|
||||
QString fallbackThemeName = QIcon::themeName();
|
||||
QPalette palette = app->palette();
|
||||
bool dark = palette.windowText().color().value() > palette.window().color().value();
|
||||
QIcon::setThemeName(dark ? "white" : "black");
|
||||
|
||||
// fallback for icons we don't provide (i.e standard system icons)
|
||||
QIcon::setFallbackThemeName(fallbackThemeName);
|
||||
#else // _WIN32
|
||||
|
||||
// set icon theme
|
||||
QIcon::setThemeName(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_IconTheme)));
|
||||
|
||||
QString styleFilePath = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_Style));
|
||||
QFile styleFile(styleFilePath);
|
||||
|
||||
if (styleFilePath.isEmpty() || !styleFile.exists())
|
||||
{
|
||||
this->setStyleSheet(fallbackStyleSheet);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!styleFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
this->setStyleSheet(fallbackStyleSheet);
|
||||
return;
|
||||
}
|
||||
|
||||
app->setStyleSheet(styleFile.readAll());
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
void MainWindow::showErrorMessage(QString text, QString details = "")
|
||||
@@ -260,13 +312,13 @@ void MainWindow::updateUI(bool inEmulation, bool isPaused)
|
||||
this->setWindowTitle(QString::fromStdString(settings.GoodName) + QString(" - ") + this->ui_WindowTitle);
|
||||
}
|
||||
|
||||
this->ui_Widgets->setCurrentIndex(1);
|
||||
this->ui_Widgets->setCurrentWidget(this->ui_Widget_OpenGL->GetWidget());
|
||||
this->storeGeometry();
|
||||
}
|
||||
else if (!this->ui_NoSwitchToRomBrowser)
|
||||
{
|
||||
this->setWindowTitle(this->ui_WindowTitle);
|
||||
this->ui_Widgets->setCurrentIndex(0);
|
||||
this->ui_Widgets->setCurrentWidget(this->ui_Widget_RomBrowser);
|
||||
this->loadGeometry();
|
||||
}
|
||||
else
|
||||
@@ -286,7 +338,12 @@ void MainWindow::storeGeometry(void)
|
||||
}
|
||||
|
||||
this->ui_Geometry = this->saveGeometry();
|
||||
this->ui_Geometry_Maximized = this->isMaximized();
|
||||
this->ui_Geometry_Saved = true;
|
||||
|
||||
std::string geometryStr = this->ui_Geometry.toBase64().toStdString();
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Geometry, geometryStr);
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Maximized, this->ui_Geometry_Maximized);
|
||||
}
|
||||
|
||||
void MainWindow::loadGeometry(void)
|
||||
@@ -296,9 +353,14 @@ void MainWindow::loadGeometry(void)
|
||||
return;
|
||||
}
|
||||
|
||||
this->setMinimumSize(0, 0);
|
||||
this->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
this->restoreGeometry(this->ui_Geometry);
|
||||
if (this->ui_Geometry_Maximized)
|
||||
{
|
||||
this->showMaximized();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->restoreGeometry(this->ui_Geometry);
|
||||
}
|
||||
|
||||
if (this->isFullScreen())
|
||||
{
|
||||
@@ -310,6 +372,11 @@ void MainWindow::loadGeometry(void)
|
||||
this->menuBar()->show();
|
||||
}
|
||||
|
||||
if (this->ui_ShowToolbar && this->toolBar->isHidden())
|
||||
{
|
||||
this->toolBar->show();
|
||||
}
|
||||
|
||||
if (this->ui_ShowStatusbar && this->statusBar()->isHidden())
|
||||
{
|
||||
this->statusBar()->show();
|
||||
@@ -376,7 +443,6 @@ void MainWindow::launchEmulationThread(QString cartRom, QString diskRom)
|
||||
return;
|
||||
}
|
||||
|
||||
this->ui_AllowManualResizing = CoreSettingsGetBoolValue(SettingsID::GUI_AllowManualResizing);
|
||||
this->ui_HideCursorInEmulation = CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInEmulation);
|
||||
this->ui_HideCursorInFullscreenEmulation = CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInFullscreenEmulation);
|
||||
this->ui_ShowToolbar = CoreSettingsGetBoolValue(SettingsID::GUI_Toolbar);
|
||||
@@ -447,6 +513,28 @@ void MainWindow::updateActions(bool inEmulation, bool isPaused)
|
||||
keyBinding = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::KeyBinding_Exit));
|
||||
this->action_System_Exit->setShortcut(QKeySequence(keyBinding));
|
||||
|
||||
// configure keybindings for save slots
|
||||
QAction* slotActions[] =
|
||||
{
|
||||
this->actionSlot_0, this->actionSlot_1, this->actionSlot_2,
|
||||
this->actionSlot_3, this->actionSlot_4, this->actionSlot_5,
|
||||
this->actionSlot_6, this->actionSlot_7, this->actionSlot_8,
|
||||
this->actionSlot_9
|
||||
};
|
||||
SettingsID slotKeybindSettingsId[] =
|
||||
{
|
||||
SettingsID::KeyBinding_SaveStateSlot0, SettingsID::KeyBinding_SaveStateSlot1,
|
||||
SettingsID::KeyBinding_SaveStateSlot2, SettingsID::KeyBinding_SaveStateSlot3,
|
||||
SettingsID::KeyBinding_SaveStateSlot4, SettingsID::KeyBinding_SaveStateSlot5,
|
||||
SettingsID::KeyBinding_SaveStateSlot6, SettingsID::KeyBinding_SaveStateSlot7,
|
||||
SettingsID::KeyBinding_SaveStateSlot8, SettingsID::KeyBinding_SaveStateSlot9
|
||||
};
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
keyBinding = QString::fromStdString(CoreSettingsGetStringValue(slotKeybindSettingsId[i]));
|
||||
slotActions[i]->setShortcut(QKeySequence(keyBinding));
|
||||
}
|
||||
|
||||
this->action_Settings_Graphics->setEnabled(CorePluginsHasConfig(CorePluginType::Gfx));
|
||||
this->action_Settings_Audio->setEnabled(CorePluginsHasConfig(CorePluginType::Audio));
|
||||
this->action_Settings_Rsp->setEnabled(CorePluginsHasConfig(CorePluginType::Rsp));
|
||||
@@ -478,6 +566,16 @@ void MainWindow::addFullscreenActions(void)
|
||||
this->addAction(this->action_System_SaveAs);
|
||||
this->addAction(this->action_System_LoadState);
|
||||
this->addAction(this->action_System_Load);
|
||||
this->addAction(this->actionSlot_0);
|
||||
this->addAction(this->actionSlot_1);
|
||||
this->addAction(this->actionSlot_2);
|
||||
this->addAction(this->actionSlot_3);
|
||||
this->addAction(this->actionSlot_4);
|
||||
this->addAction(this->actionSlot_5);
|
||||
this->addAction(this->actionSlot_6);
|
||||
this->addAction(this->actionSlot_7);
|
||||
this->addAction(this->actionSlot_8);
|
||||
this->addAction(this->actionSlot_9);
|
||||
this->addAction(this->action_System_Cheats);
|
||||
this->addAction(this->action_System_GSButton);
|
||||
this->addAction(this->action_System_Exit);
|
||||
@@ -505,6 +603,16 @@ void MainWindow::removeFullscreenActions(void)
|
||||
this->removeAction(this->action_System_SaveAs);
|
||||
this->removeAction(this->action_System_LoadState);
|
||||
this->removeAction(this->action_System_Load);
|
||||
this->removeAction(this->actionSlot_0);
|
||||
this->removeAction(this->actionSlot_1);
|
||||
this->removeAction(this->actionSlot_2);
|
||||
this->removeAction(this->actionSlot_3);
|
||||
this->removeAction(this->actionSlot_4);
|
||||
this->removeAction(this->actionSlot_5);
|
||||
this->removeAction(this->actionSlot_6);
|
||||
this->removeAction(this->actionSlot_7);
|
||||
this->removeAction(this->actionSlot_8);
|
||||
this->removeAction(this->actionSlot_9);
|
||||
this->removeAction(this->action_System_Cheats);
|
||||
this->removeAction(this->action_System_GSButton);
|
||||
this->removeAction(this->action_System_Exit);
|
||||
@@ -586,7 +694,7 @@ void MainWindow::connectActionSignals(void)
|
||||
connect(this->action_System_HardReset, &QAction::triggered, this, &MainWindow::on_Action_System_HardReset);
|
||||
connect(this->action_System_Pause, &QAction::triggered, this, &MainWindow::on_Action_System_Pause);
|
||||
connect(this->action_System_Screenshot, &QAction::triggered, this,
|
||||
&MainWindow::on_Action_System_GenerateBitmap);
|
||||
&MainWindow::on_Action_System_Screenshot);
|
||||
connect(this->action_System_LimitFPS, &QAction::triggered, this, &MainWindow::on_Action_System_LimitFPS);
|
||||
connect(this->action_System_SaveState, &QAction::triggered, this, &MainWindow::on_Action_System_SaveState);
|
||||
connect(this->action_System_SaveAs, &QAction::triggered, this, &MainWindow::on_Action_System_SaveAs);
|
||||
@@ -877,24 +985,6 @@ void MainWindow::on_Action_System_Shutdown(void)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_File_ChooseDirectory(void)
|
||||
{
|
||||
QString dir;
|
||||
|
||||
dir = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Directory, dir.toStdString());
|
||||
this->ui_Widget_RomBrowser->RefreshRomList();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_File_RefreshRomList(void)
|
||||
{
|
||||
this->ui_Widget_RomBrowser->RefreshRomList();
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_Exit(void)
|
||||
{
|
||||
this->close();
|
||||
@@ -915,9 +1005,9 @@ void MainWindow::on_Action_System_HardReset(void)
|
||||
this->showErrorMessage("CoreResetEmulation() Failed!", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_Pause(void)
|
||||
{
|
||||
bool isRunning = CoreIsEmulationRunning();
|
||||
bool isPaused = CoreIsEmulationPaused();
|
||||
|
||||
bool ret;
|
||||
@@ -925,11 +1015,19 @@ void MainWindow::on_Action_System_Pause(void)
|
||||
|
||||
if (!isPaused)
|
||||
{
|
||||
if (isRunning)
|
||||
{
|
||||
OnScreenDisplayPause();
|
||||
}
|
||||
ret = CorePauseEmulation();
|
||||
error = "CorePauseEmulation() Failed!";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isPaused)
|
||||
{
|
||||
OnScreenDisplayResume();
|
||||
}
|
||||
ret = CoreResumeEmulation();
|
||||
error = "CoreResumeEmulation() Failed!";
|
||||
}
|
||||
@@ -943,12 +1041,16 @@ void MainWindow::on_Action_System_Pause(void)
|
||||
this->ui_ManuallyPaused = true;
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_GenerateBitmap(void)
|
||||
void MainWindow::on_Action_System_Screenshot(void)
|
||||
{
|
||||
if (!CoreTakeScreenshot())
|
||||
{
|
||||
this->showErrorMessage("CoreTakeScreenshot() Failed!", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("Captured screenshot.");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_LimitFPS(void)
|
||||
@@ -971,6 +1073,10 @@ void MainWindow::on_Action_System_SaveState(void)
|
||||
{
|
||||
this->showErrorMessage("CoreSaveState() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("Saved state to slot: " + std::to_string(CoreGetSaveStateSlot()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_SaveAs(void)
|
||||
@@ -991,6 +1097,10 @@ void MainWindow::on_Action_System_SaveAs(void)
|
||||
{
|
||||
this->showErrorMessage("CoreSaveState() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("Saved state to: " + fileName.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
if (isRunning && !isPaused)
|
||||
@@ -1005,6 +1115,10 @@ void MainWindow::on_Action_System_LoadState(void)
|
||||
{
|
||||
this->showErrorMessage("CoreLoadSaveState() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("State loaded from slot: " + std::to_string(CoreGetSaveStateSlot()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_Load(void)
|
||||
@@ -1026,6 +1140,10 @@ void MainWindow::on_Action_System_Load(void)
|
||||
{
|
||||
this->showErrorMessage("CoreLoadSaveState() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("State loaded from: " + fileName.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
if (isRunning && !isPaused)
|
||||
@@ -1040,6 +1158,10 @@ void MainWindow::on_Action_System_CurrentSaveState(int slot)
|
||||
{
|
||||
this->showErrorMessage("CoreSetSaveStateSlot() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScreenDisplaySetMessage("Selected save slot: " + std::to_string(slot));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_System_Cheats(void)
|
||||
@@ -1211,7 +1333,6 @@ void MainWindow::on_Emulation_Finished(bool ret)
|
||||
{
|
||||
if (!ret)
|
||||
{
|
||||
this->showErrorMessage("EmulationThread::run Failed", this->emulationThread->GetLastError());
|
||||
// whatever we do on failure,
|
||||
// always return to the rombrowser
|
||||
this->ui_NoSwitchToRomBrowser = false;
|
||||
@@ -1229,8 +1350,21 @@ void MainWindow::on_Emulation_Finished(bool ret)
|
||||
this->ui_FullscreenTimerId = 0;
|
||||
}
|
||||
|
||||
if (this->ui_QuitAfterEmulation)
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
|
||||
// always refresh UI
|
||||
this->updateUI(false, false);
|
||||
|
||||
// show error message to the user
|
||||
// after switching back to the ROM browser
|
||||
if (!ret)
|
||||
{
|
||||
this->showErrorMessage("EmulationThread::run Failed", this->emulationThread->GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_RomBrowser_PlayGame(QString file)
|
||||
@@ -1238,18 +1372,41 @@ void MainWindow::on_RomBrowser_PlayGame(QString file)
|
||||
this->launchEmulationThread(file);
|
||||
}
|
||||
|
||||
void MainWindow::on_RomBrowser_PlayGameWithDisk(QString file)
|
||||
void MainWindow::on_RomBrowser_PlayGameWith(CoreRomType type, QString file)
|
||||
{
|
||||
QString diskRom;
|
||||
QString mainRom;
|
||||
QString otherRom;
|
||||
|
||||
diskRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64)");
|
||||
if (type == CoreRomType::Cartridge)
|
||||
{ // cartridge
|
||||
mainRom = file;
|
||||
otherRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64)");
|
||||
}
|
||||
else
|
||||
{ // disk
|
||||
mainRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip)");
|
||||
otherRom = file;
|
||||
}
|
||||
|
||||
if (diskRom.isEmpty())
|
||||
if (mainRom.isEmpty() || otherRom.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->launchEmulationThread(file, diskRom);
|
||||
this->launchEmulationThread(mainRom, otherRom);
|
||||
}
|
||||
|
||||
void MainWindow::on_RomBrowser_ChangeRomDirectory(void)
|
||||
{
|
||||
QString dir;
|
||||
|
||||
dir = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Directory, dir.toStdString());
|
||||
this->ui_Widget_RomBrowser->RefreshRomList();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_RomBrowser_RomInformation(QString file)
|
||||
@@ -1447,9 +1604,11 @@ void MainWindow::on_VidExt_SetFullscreenMode(int width, int height, int bps, int
|
||||
void MainWindow::on_VidExt_ResizeWindow(int width, int height)
|
||||
{
|
||||
// account for HiDPI scaling
|
||||
// see https://github.com/Rosalie241/RMG/issues/2
|
||||
height /= this->devicePixelRatioF();
|
||||
width /= this->devicePixelRatioF();
|
||||
if (this->devicePixelRatio() != 1)
|
||||
{
|
||||
width = (int)std::ceil((double)((double)width / this->devicePixelRatio()));
|
||||
height = (int)std::ceil((double)((double)height / this->devicePixelRatio()));
|
||||
}
|
||||
|
||||
if (!this->menuBar()->isHidden())
|
||||
{
|
||||
@@ -1479,14 +1638,7 @@ void MainWindow::on_VidExt_ResizeWindow(int width, int height)
|
||||
this->showNormal();
|
||||
}
|
||||
|
||||
if (this->ui_AllowManualResizing)
|
||||
{
|
||||
this->resize(width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setFixedSize(width, height);
|
||||
}
|
||||
this->resize(width, height);
|
||||
|
||||
// we've force set the size once,
|
||||
// we can safely disable it now
|
||||
|
||||
@@ -48,7 +48,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
~MainWindow(void);
|
||||
|
||||
bool Init(QApplication*);
|
||||
void OpenROM(QString, QString, bool);
|
||||
void OpenROM(QString, QString, bool, bool);
|
||||
|
||||
private:
|
||||
Thread::EmulationThread *emulationThread;
|
||||
@@ -62,14 +62,15 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
QLabel *ui_StatusBar_Label;
|
||||
|
||||
QByteArray ui_Geometry;
|
||||
bool ui_Geometry_Maximized = false;
|
||||
bool ui_Geometry_Saved = false;
|
||||
|
||||
bool ui_AllowManualResizing = false;
|
||||
bool ui_HideCursorInEmulation = false;
|
||||
bool ui_HideCursorInFullscreenEmulation = false;
|
||||
bool ui_NoSwitchToRomBrowser = false;
|
||||
bool ui_VidExtForceSetMode = false;
|
||||
bool ui_LaunchInFullscreen = false;
|
||||
bool ui_QuitAfterEmulation = false;
|
||||
bool ui_RefreshRomListAfterEmulation = false;
|
||||
|
||||
bool ui_ShowToolbar = false;
|
||||
@@ -129,16 +130,13 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
void on_networkAccessManager_Finished(QNetworkReply *);
|
||||
#endif // UPDATER
|
||||
|
||||
void on_Action_File_ChooseDirectory(void);
|
||||
void on_Action_File_RefreshRomList(void);
|
||||
|
||||
void on_Action_System_OpenRom(void);
|
||||
void on_Action_System_OpenCombo(void);
|
||||
void on_Action_System_Shutdown(void);
|
||||
void on_Action_System_SoftReset(void);
|
||||
void on_Action_System_HardReset(void);
|
||||
void on_Action_System_Pause(void);
|
||||
void on_Action_System_GenerateBitmap(void);
|
||||
void on_Action_System_Screenshot(void);
|
||||
void on_Action_System_LimitFPS(void);
|
||||
void on_Action_System_SaveState(void);
|
||||
void on_Action_System_SaveAs(void);
|
||||
@@ -172,7 +170,8 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
void on_Emulation_Finished(bool);
|
||||
|
||||
void on_RomBrowser_PlayGame(QString);
|
||||
void on_RomBrowser_PlayGameWithDisk(QString);
|
||||
void on_RomBrowser_PlayGameWith(CoreRomType, QString);
|
||||
void on_RomBrowser_ChangeRomDirectory(void);
|
||||
void on_RomBrowser_RomInformation(QString);
|
||||
void on_RomBrowser_EditGameSettings(QString);
|
||||
void on_RomBrowser_Cheats(QString);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>639</width>
|
||||
<height>22</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuSystem">
|
||||
@@ -48,6 +48,10 @@
|
||||
<property name="title">
|
||||
<string>Current Save State</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="save-3-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<addaction name="actionSlot_0"/>
|
||||
<addaction name="actionSlot_1"/>
|
||||
<addaction name="actionSlot_2"/>
|
||||
@@ -358,6 +362,10 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_System_GSButton">
|
||||
<property name="icon">
|
||||
<iconset theme="checkbox-blank-circle-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>GS Button</string>
|
||||
</property>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 171 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"/></svg>
|
||||
|
After Width: | Height: | Size: 246 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M6.535 3H21a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H6.535a1 1 0 0 1-.832-.445l-5.333-8a1 1 0 0 1 0-1.11l5.333-8A1 1 0 0 1 6.535 3zm.535 2l-4.666 7 4.666 7H20V5H7.07zM16 11v2H9v-2h7z"/></svg>
|
||||
|
After Width: | Height: | Size: 310 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 186 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 261 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M6.535 3H21a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H6.535a1 1 0 0 1-.832-.445l-5.333-8a1 1 0 0 1 0-1.11l5.333-8A1 1 0 0 1 6.535 3zm.535 2l-4.666 7 4.666 7H20V5H7.07zM16 11v2H9v-2h7z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 325 B |
@@ -4,8 +4,11 @@
|
||||
<file>Resource/CoverFallback.png</file>
|
||||
|
||||
<file alias="icons/black/index.theme">Resource/icons/black/index.theme</file>
|
||||
<file alias="icons/black/svg/add-line.svg">Resource/icons/black/svg/add-line.svg</file>
|
||||
<file alias="icons/black/svg/brush-line.svg">Resource/icons/black/svg/brush-line.svg</file>
|
||||
<file alias="icons/black/svg/checkbox-blank-circle-line.svg">Resource/icons/black/svg/checkbox-blank-circle-line.svg</file>
|
||||
<file alias="icons/black/svg/code-box-line.svg">Resource/icons/black/svg/code-box-line.svg</file>
|
||||
<file alias="icons/black/svg/delete-back-line.svg">Resource/icons/black/svg/delete-back-line.svg</file>
|
||||
<file alias="icons/black/svg/delete-bin-line.svg">Resource/icons/black/svg/delete-bin-line.svg</file>
|
||||
<file alias="icons/black/svg/door-open-line.svg">Resource/icons/black/svg/door-open-line.svg</file>
|
||||
<file alias="icons/black/svg/file-line.svg">Resource/icons/black/svg/file-line.svg</file>
|
||||
@@ -30,8 +33,11 @@
|
||||
<file alias="icons/black/svg/volume-up-line.svg">Resource/icons/black/svg/volume-up-line.svg</file>
|
||||
|
||||
<file alias="icons/white/index.theme">Resource/icons/white/index.theme</file>
|
||||
<file alias="icons/white/svg/add-line.svg">Resource/icons/white/svg/add-line.svg</file>
|
||||
<file alias="icons/white/svg/brush-line.svg">Resource/icons/white/svg/brush-line.svg</file>
|
||||
<file alias="icons/white/svg/checkbox-blank-circle-line.svg">Resource/icons/white/svg/checkbox-blank-circle-line.svg</file>
|
||||
<file alias="icons/white/svg/code-box-line.svg">Resource/icons/white/svg/code-box-line.svg</file>
|
||||
<file alias="icons/white/svg/delete-back-line.svg">Resource/icons/white/svg/delete-back-line.svg</file>
|
||||
<file alias="icons/white/svg/delete-bin-line.svg">Resource/icons/white/svg/delete-bin-line.svg</file>
|
||||
<file alias="icons/white/svg/door-open-line.svg">Resource/icons/white/svg/door-open-line.svg</file>
|
||||
<file alias="icons/white/svg/file-line.svg">Resource/icons/white/svg/file-line.svg</file>
|
||||
|
||||
@@ -19,14 +19,51 @@ KeybindButton::~KeybindButton(void)
|
||||
{
|
||||
}
|
||||
|
||||
void KeybindButton::Reset(void)
|
||||
{
|
||||
this->setText(this->GetCurrentText());
|
||||
}
|
||||
|
||||
void KeybindButton::Clear(void)
|
||||
{
|
||||
this->setText("");
|
||||
emit this->on_KeybindButton_KeybindingChanged(this);
|
||||
this->SetText("");
|
||||
}
|
||||
|
||||
void KeybindButton::SetText(QString text)
|
||||
{
|
||||
this->currentText = text;
|
||||
this->setText(text);
|
||||
}
|
||||
|
||||
void KeybindButton::SetSecondsLeft(int seconds)
|
||||
{
|
||||
if (seconds == 0)
|
||||
{
|
||||
this->listenForInput = false;
|
||||
this->Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
QString text;
|
||||
text = "Press key... [";
|
||||
text += QString::number(seconds);
|
||||
text += "]";
|
||||
this->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
QString KeybindButton::GetCurrentText(void)
|
||||
{
|
||||
return this->currentText;
|
||||
}
|
||||
|
||||
void KeybindButton::keyPressEvent(QKeyEvent * event)
|
||||
{
|
||||
if (!this->listenForInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// filter keys
|
||||
switch (event->key())
|
||||
{
|
||||
@@ -71,26 +108,42 @@ void KeybindButton::keyPressEvent(QKeyEvent * event)
|
||||
|
||||
void KeybindButton::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (!this->listenForInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->currentText = this->keySequence.toString();
|
||||
this->clearFocus();
|
||||
}
|
||||
|
||||
void KeybindButton::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::RightButton)
|
||||
if (this->listenForInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
this->currentText = this->text();
|
||||
this->listenForInput = true;
|
||||
emit this->on_KeybindButton_Clicked(this);
|
||||
}
|
||||
else if (event->button() == Qt::RightButton)
|
||||
{
|
||||
this->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void KeybindButton::focusInEvent(QFocusEvent *event)
|
||||
{
|
||||
currentText = this->text();
|
||||
this->setText("...");
|
||||
}
|
||||
|
||||
void KeybindButton::focusOutEvent(QFocusEvent *event)
|
||||
{
|
||||
if (!this->listenForInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->setText(this->currentText);
|
||||
emit this->on_KeybindButton_KeybindingChanged(this);
|
||||
this->listenForInput = false;
|
||||
}
|
||||
|
||||
@@ -26,20 +26,28 @@ class KeybindButton : public QPushButton
|
||||
private:
|
||||
QKeySequence keySequence;
|
||||
QString currentText;
|
||||
bool listenForInput = false;
|
||||
|
||||
public:
|
||||
KeybindButton(QWidget* parent);
|
||||
~KeybindButton(void);
|
||||
|
||||
void Reset(void);
|
||||
void Clear(void);
|
||||
|
||||
void SetText(QString text);
|
||||
void SetSecondsLeft(int seconds);
|
||||
|
||||
QString GetCurrentText(void);
|
||||
|
||||
signals:
|
||||
void on_KeybindButton_KeybindingChanged(KeybindButton* button);
|
||||
void on_KeybindButton_Clicked(KeybindButton* button);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *);
|
||||
void keyReleaseEvent(QKeyEvent *);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
void focusOutEvent(QFocusEvent *event);
|
||||
};
|
||||
} // namespace Widget
|
||||
|
||||
@@ -15,7 +15,7 @@ using namespace UserInterface::Widget;
|
||||
|
||||
OGLWidget::OGLWidget(QWidget *parent)
|
||||
{
|
||||
this->widgetParent = parent;
|
||||
this->widgetContainer = QWidget::createWindowContainer(this, parent);
|
||||
this->setSurfaceType(QWindow::OpenGLSurface);
|
||||
this->openGLcontext = new QOpenGLContext();
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void OGLWidget::SetHideCursor(bool hide)
|
||||
|
||||
QWidget *OGLWidget::GetWidget(void)
|
||||
{
|
||||
return QWidget::createWindowContainer(this, this->widgetParent);
|
||||
return this->widgetContainer;
|
||||
}
|
||||
|
||||
void OGLWidget::resizeEvent(QResizeEvent *event)
|
||||
|
||||
@@ -39,7 +39,7 @@ class OGLWidget : public QWindow
|
||||
void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
QWidget* widgetParent = nullptr;
|
||||
QWidget* widgetContainer = nullptr;
|
||||
QOpenGLContext* openGLcontext = nullptr;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>.ndd/.64d (64DD Disks)</string>
|
||||
<string>.ndd/.d64 (64DD Disks)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
#include <QList>
|
||||
#include <QScrollBar>
|
||||
#include <QDesktopServices>
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
@@ -30,16 +31,18 @@ using namespace UserInterface::Widget;
|
||||
struct RomBrowserModelData
|
||||
{
|
||||
QString file;
|
||||
CoreRomType type;
|
||||
CoreRomHeader header;
|
||||
CoreRomSettings settings;
|
||||
QString coverFile;
|
||||
|
||||
RomBrowserModelData() {}
|
||||
|
||||
RomBrowserModelData(QString file, CoreRomHeader header, CoreRomSettings settings)
|
||||
RomBrowserModelData(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings)
|
||||
{
|
||||
this->file = file;
|
||||
this->header = header;
|
||||
this->file = file;
|
||||
this->type = type;
|
||||
this->header = header;
|
||||
this->settings = settings;
|
||||
}
|
||||
};
|
||||
@@ -52,6 +55,9 @@ Q_DECLARE_METATYPE(RomBrowserModelData);
|
||||
|
||||
RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
{
|
||||
// configure signal types
|
||||
qRegisterMetaType<CoreRomType>("CoreRomType");
|
||||
|
||||
// configure rom searcher thread
|
||||
this->romSearcherThread = new Thread::RomSearcherThread(this);
|
||||
connect(this->romSearcherThread, &Thread::RomSearcherThread::RomFound, this, &RomBrowserWidget::on_RomBrowserThread_RomFound);
|
||||
@@ -60,7 +66,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
// configure empty widget
|
||||
this->emptyWidget = new Widget::RomBrowserEmptyWidget(this);
|
||||
this->addWidget(this->emptyWidget);
|
||||
connect(this->emptyWidget, &RomBrowserEmptyWidget::SelectRomDirectory, this, &RomBrowserWidget::on_Action_ChooseRomDirectory);
|
||||
connect(this->emptyWidget, &RomBrowserEmptyWidget::SelectRomDirectory, this, &RomBrowserWidget::on_Action_ChangeRomDirectory);
|
||||
connect(this->emptyWidget, &RomBrowserEmptyWidget::Refresh, this, &RomBrowserWidget::on_Action_RefreshRomList);
|
||||
|
||||
// configure loading widget
|
||||
@@ -138,28 +144,30 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
|
||||
// configure context menu actions
|
||||
this->action_PlayGame = new QAction(this);
|
||||
this->action_PlayGameWithDisk = new QAction(this);
|
||||
this->action_PlayGameWith = new QAction(this);
|
||||
this->action_RefreshRomList = new QAction(this);
|
||||
this->action_ChooseRomDirectory = new QAction(this);
|
||||
this->action_OpenRomDirectory = new QAction(this);
|
||||
this->action_ChangeRomDirectory = new QAction(this);
|
||||
this->action_RomInformation = new QAction(this);
|
||||
this->action_EditGameSettings = new QAction(this);
|
||||
this->action_EditCheats = new QAction(this);
|
||||
this->action_SetCoverImage = new QAction(this);
|
||||
this->action_RemoveCoverImage = new QAction(this);
|
||||
this->action_PlayGame->setText("Play Game");
|
||||
this->action_PlayGameWithDisk->setText("Play Game with Disk");
|
||||
this->action_PlayGameWith->setText("Play Game with Disk");
|
||||
this->action_RefreshRomList->setText("Refresh ROM List");
|
||||
this->action_ChooseRomDirectory->setText("Choose ROM Directory...");
|
||||
this->action_OpenRomDirectory->setText("Open ROM Directory");
|
||||
this->action_ChangeRomDirectory->setText("Change ROM Directory...");
|
||||
this->action_RomInformation->setText("ROM Information");
|
||||
this->action_EditGameSettings->setText("Edit Game Settings");
|
||||
this->action_EditCheats->setText("Edit Cheats");
|
||||
this->action_SetCoverImage->setText("Set Cover Image...");
|
||||
this->action_RemoveCoverImage->setText("Remove Cover Image");
|
||||
connect(this->action_PlayGame, &QAction::triggered, this, &RomBrowserWidget::on_Action_PlayGame);
|
||||
connect(this->action_PlayGameWithDisk, &QAction::triggered, this, &RomBrowserWidget::on_Action_PlayGameWithDisk);
|
||||
connect(this->action_PlayGameWith, &QAction::triggered, this, &RomBrowserWidget::on_Action_PlayGameWith);
|
||||
connect(this->action_RefreshRomList, &QAction::triggered, this, &RomBrowserWidget::on_Action_RefreshRomList);
|
||||
connect(this->action_ChooseRomDirectory, &QAction::triggered, this,
|
||||
&RomBrowserWidget::on_Action_ChooseRomDirectory);
|
||||
connect(this->action_OpenRomDirectory, &QAction::triggered, this, &RomBrowserWidget::on_Action_OpenRomDirectory);
|
||||
connect(this->action_ChangeRomDirectory, &QAction::triggered, this, &RomBrowserWidget::on_Action_ChangeRomDirectory);
|
||||
connect(this->action_RomInformation, &QAction::triggered, this, &RomBrowserWidget::on_Action_RomInformation);
|
||||
connect(this->action_EditGameSettings, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditGameSettings);
|
||||
connect(this->action_EditCheats, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditCheats);
|
||||
@@ -169,10 +177,12 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
// configure context menu
|
||||
this->contextMenu = new QMenu(this);
|
||||
this->contextMenu->addAction(this->action_PlayGame);
|
||||
this->contextMenu->addAction(this->action_PlayGameWithDisk);
|
||||
this->contextMenu->addAction(this->action_PlayGameWith);
|
||||
this->contextMenu->addSeparator();
|
||||
this->contextMenu->addAction(this->action_RefreshRomList);
|
||||
this->contextMenu->addAction(this->action_ChooseRomDirectory);
|
||||
this->contextMenu->addSeparator();
|
||||
this->contextMenu->addAction(this->action_OpenRomDirectory);
|
||||
this->contextMenu->addAction(this->action_ChangeRomDirectory);
|
||||
this->contextMenu->addSeparator();
|
||||
this->contextMenu->addAction(this->action_RomInformation);
|
||||
this->contextMenu->addSeparator();
|
||||
@@ -206,6 +216,7 @@ void RomBrowserWidget::RefreshRomList(void)
|
||||
this->coversDirectory = QString::fromStdString(CoreGetUserDataDirectory().string());
|
||||
this->coversDirectory += "/Covers";
|
||||
|
||||
this->sortRomResults = CoreSettingsGetBoolValue(SettingsID::RomBrowser_SortAfterSearch);
|
||||
this->listViewSortSection = CoreSettingsGetIntValue(SettingsID::RomBrowser_ListViewSortSection);
|
||||
this->listViewSortOrder = CoreSettingsGetIntValue(SettingsID::RomBrowser_ListViewSortOrder);
|
||||
|
||||
@@ -342,16 +353,29 @@ QString RomBrowserWidget::getCurrentRom(void)
|
||||
return data.file;
|
||||
}
|
||||
|
||||
QIcon RomBrowserWidget::getCurrentCover(CoreRomHeader header, CoreRomSettings settings, QString& coverFileName)
|
||||
QIcon RomBrowserWidget::getCurrentCover(QString file, CoreRomHeader header, CoreRomSettings settings, QString& coverFileName)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
|
||||
// construct basename of file,
|
||||
// by retrieving the last index of '.'
|
||||
// and removing all characters from that index
|
||||
// until the end of the string
|
||||
QString baseName = QFileInfo(file).fileName();
|
||||
qsizetype lastIndexOfDot = baseName.lastIndexOf(".");
|
||||
if (lastIndexOfDot != -1)
|
||||
{ // only remove when index was found
|
||||
baseName.remove(lastIndexOfDot, baseName.size() - lastIndexOfDot);
|
||||
}
|
||||
|
||||
// try to load cover using
|
||||
// 1) MD5
|
||||
// 2) good name
|
||||
// 3) internal name
|
||||
// 1) basename of file
|
||||
// 2) MD5
|
||||
// 3) good name
|
||||
// 4) internal name
|
||||
bool foundCover = false;
|
||||
for (QString name : {
|
||||
baseName,
|
||||
QString::fromStdString(settings.MD5),
|
||||
QString::fromStdString(settings.GoodName),
|
||||
QString::fromStdString(header.Name) })
|
||||
@@ -369,6 +393,15 @@ QIcon RomBrowserWidget::getCurrentCover(CoreRomHeader header, CoreRomSettings se
|
||||
fixedName.replace(c, "_");
|
||||
}
|
||||
|
||||
// skip empty names,
|
||||
// this can i.e happen
|
||||
// when ROMs don't have
|
||||
// an internal ROM name
|
||||
if (fixedName.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// we support jpg & png as file extensions
|
||||
for (QString ext : { ".png", ".jpg", ".jpeg" })
|
||||
{
|
||||
@@ -426,7 +459,7 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position)
|
||||
this->getCurrentData(data);
|
||||
|
||||
this->action_PlayGame->setEnabled(hasSelection);
|
||||
this->action_PlayGameWithDisk->setEnabled(hasSelection);
|
||||
this->action_PlayGameWith->setEnabled(hasSelection);
|
||||
this->action_RomInformation->setEnabled(hasSelection);
|
||||
this->action_EditGameSettings->setEnabled(hasSelection);
|
||||
this->action_EditCheats->setEnabled(hasSelection);
|
||||
@@ -435,6 +468,15 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position)
|
||||
this->action_RemoveCoverImage->setEnabled(hasSelection && !data.coverFile.isEmpty());
|
||||
this->action_RemoveCoverImage->setVisible(view == this->gridViewWidget);
|
||||
|
||||
if (hasSelection && data.type == CoreRomType::Disk)
|
||||
{ // disk selected
|
||||
this->action_PlayGameWith->setText("Play Game with Cartridge");
|
||||
}
|
||||
else
|
||||
{ // cartridge selected
|
||||
this->action_PlayGameWith->setText("Play Game with Disk");
|
||||
}
|
||||
|
||||
if (view == this->gridViewWidget)
|
||||
{ // grid view
|
||||
if (data.coverFile.isEmpty())
|
||||
@@ -500,7 +542,7 @@ void RomBrowserWidget::on_ZoomOut(void)
|
||||
view->setIconSize(view->iconSize() - QSize(10, 10));
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomHeader header, CoreRomSettings settings)
|
||||
void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings)
|
||||
{
|
||||
QString name;
|
||||
QString coverFile;
|
||||
@@ -509,7 +551,7 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomHeader
|
||||
RomBrowserModelData modelData;
|
||||
|
||||
// create item data
|
||||
modelData = RomBrowserModelData(file, header, settings);
|
||||
modelData = RomBrowserModelData(file, type, header, settings);
|
||||
|
||||
// generate name to use in UI
|
||||
name = QString::fromStdString(settings.GoodName);
|
||||
@@ -520,7 +562,7 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomHeader
|
||||
}
|
||||
|
||||
// retrieve cover image
|
||||
coverIcon = this->getCurrentCover(header, settings, coverFile);
|
||||
coverIcon = this->getCurrentCover(file, header, settings, coverFile);
|
||||
modelData.coverFile = coverFile;
|
||||
|
||||
// create item data
|
||||
@@ -554,8 +596,11 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomHeader
|
||||
void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled)
|
||||
{
|
||||
// sort data
|
||||
this->listViewModel->sort(this->listViewSortSection, (Qt::SortOrder)this->listViewSortOrder);
|
||||
this->gridViewModel->sort(0, Qt::SortOrder::AscendingOrder);
|
||||
if (this->sortRomResults)
|
||||
{
|
||||
this->listViewModel->sort(this->listViewSortSection, (Qt::SortOrder)this->listViewSortOrder);
|
||||
this->gridViewModel->sort(0, Qt::SortOrder::AscendingOrder);
|
||||
}
|
||||
|
||||
// resize list view's columns
|
||||
std::vector<int> columnSizes = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnSizes);
|
||||
@@ -603,9 +648,16 @@ void RomBrowserWidget::on_Action_PlayGame(void)
|
||||
emit this->PlayGame(this->getCurrentRom());
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_Action_PlayGameWithDisk(void)
|
||||
void RomBrowserWidget::on_Action_PlayGameWith(void)
|
||||
{
|
||||
emit this->PlayGameWithDisk(this->getCurrentRom());
|
||||
RomBrowserModelData data;
|
||||
|
||||
if (!this->getCurrentData(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
emit this->PlayGameWith(data.type, data.file);
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_Action_RefreshRomList(void)
|
||||
@@ -613,9 +665,21 @@ void RomBrowserWidget::on_Action_RefreshRomList(void)
|
||||
this->RefreshRomList();
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_Action_ChooseRomDirectory(void)
|
||||
void RomBrowserWidget::on_Action_OpenRomDirectory(void)
|
||||
{
|
||||
emit this->ChooseRomDirectory();
|
||||
QString directory = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::RomBrowser_Directory));
|
||||
|
||||
if (directory.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QDesktopServices::openUrl(QUrl("file:///" + directory));
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_Action_ChangeRomDirectory(void)
|
||||
{
|
||||
emit this->ChangeRomDirectory();
|
||||
}
|
||||
|
||||
void RomBrowserWidget::on_Action_RomInformation(void)
|
||||
@@ -691,7 +755,7 @@ void RomBrowserWidget::on_Action_SetCoverImage(void)
|
||||
QFile::copy(sourceFile, newFileName);
|
||||
|
||||
// update item
|
||||
item->setIcon(this->getCurrentCover(data.header, data.settings, coverFile));
|
||||
item->setIcon(this->getCurrentCover(data.file, data.header, data.settings, coverFile));
|
||||
data.coverFile = coverFile;
|
||||
item->setData(QVariant::fromValue<RomBrowserModelData>(data));
|
||||
}
|
||||
@@ -716,7 +780,7 @@ void RomBrowserWidget::on_Action_RemoveCoverImage(void)
|
||||
}
|
||||
|
||||
// update item
|
||||
item->setIcon(this->getCurrentCover(data.header, data.settings, coverFile));
|
||||
item->setIcon(this->getCurrentCover(data.file, data.header, data.settings, coverFile));
|
||||
data.coverFile = coverFile;
|
||||
item->setData(QVariant::fromValue<RomBrowserModelData>(data));
|
||||
}
|
||||
|
||||
@@ -67,14 +67,17 @@ class RomBrowserWidget : public QStackedWidget
|
||||
QElapsedTimer romSearcherTimer;
|
||||
Thread::RomSearcherThread* romSearcherThread = nullptr;
|
||||
|
||||
bool sortRomResults = false;
|
||||
|
||||
int listViewSortSection = 0;
|
||||
int listViewSortOrder = 0;
|
||||
|
||||
QMenu* contextMenu;
|
||||
QAction* action_PlayGame;
|
||||
QAction* action_PlayGameWithDisk;
|
||||
QAction* action_PlayGameWith;
|
||||
QAction* action_RefreshRomList;
|
||||
QAction* action_ChooseRomDirectory;
|
||||
QAction* action_OpenRomDirectory;
|
||||
QAction* action_ChangeRomDirectory;
|
||||
QAction* action_RomInformation;
|
||||
QAction* action_EditGameSettings;
|
||||
QAction* action_EditCheats;
|
||||
@@ -89,7 +92,7 @@ class RomBrowserWidget : public QStackedWidget
|
||||
|
||||
QString getCurrentRom(void);
|
||||
|
||||
QIcon getCurrentCover(CoreRomHeader header, CoreRomSettings settings, QString& coverFileName);
|
||||
QIcon getCurrentCover(QString file, CoreRomHeader header, CoreRomSettings settings, QString& coverFileName);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
|
||||
@@ -106,13 +109,14 @@ class RomBrowserWidget : public QStackedWidget
|
||||
void on_ZoomIn(void);
|
||||
void on_ZoomOut(void);
|
||||
|
||||
void on_RomBrowserThread_RomFound(QString file, CoreRomHeader header, CoreRomSettings settings);
|
||||
void on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings);
|
||||
void on_RomBrowserThread_Finished(bool canceled);
|
||||
|
||||
void on_Action_PlayGame(void);
|
||||
void on_Action_PlayGameWithDisk(void);
|
||||
void on_Action_PlayGameWith(void);
|
||||
void on_Action_RefreshRomList(void);
|
||||
void on_Action_ChooseRomDirectory(void);
|
||||
void on_Action_OpenRomDirectory(void);
|
||||
void on_Action_ChangeRomDirectory(void);
|
||||
void on_Action_RomInformation(void);
|
||||
void on_Action_EditGameSettings(void);
|
||||
void on_Action_EditCheats(void);
|
||||
@@ -121,10 +125,10 @@ class RomBrowserWidget : public QStackedWidget
|
||||
|
||||
signals:
|
||||
void PlayGame(QString);
|
||||
void PlayGameWithDisk(QString);
|
||||
void PlayGameWith(CoreRomType, QString);
|
||||
void EditGameSettings(QString);
|
||||
void Cheats(QString);
|
||||
void ChooseRomDirectory(void);
|
||||
void ChangeRomDirectory(void);
|
||||
void RomInformation(QString);
|
||||
};
|
||||
} // namespace Widget
|
||||
|
||||
+32
-7
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <RMG-Core/VidExt.hpp>
|
||||
#include <RMG-Core/m64p/Api.hpp>
|
||||
#include "OnScreenDisplay.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QOpenGLContext>
|
||||
@@ -25,7 +26,8 @@ static Thread::EmulationThread* l_EmuThread = nullptr;
|
||||
static UserInterface::MainWindow* l_MainWindow = nullptr;
|
||||
static UserInterface::Widget::OGLWidget* l_OGLWidget = nullptr;
|
||||
static QThread* l_RenderThread = nullptr;
|
||||
static bool l_VidExtSetup = false;
|
||||
static bool l_VidExtInitialized = false;
|
||||
static bool l_OsdInitialized = false;
|
||||
static QSurfaceFormat l_SurfaceFormat;
|
||||
|
||||
//
|
||||
@@ -36,13 +38,14 @@ static void VidExt_OglSetup(void)
|
||||
{
|
||||
l_EmuThread->on_VidExt_SetupOGL(l_SurfaceFormat, QThread::currentThread());
|
||||
|
||||
while (!l_OGLWidget->GetContext()->isValid())
|
||||
while (!l_OGLWidget->isVisible() ||
|
||||
!l_OGLWidget->GetContext()->isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
l_OGLWidget->GetContext()->makeCurrent(l_OGLWidget);
|
||||
l_VidExtSetup = true;
|
||||
l_VidExtInitialized = true;
|
||||
}
|
||||
|
||||
static m64p_error VidExt_Init(void)
|
||||
@@ -53,8 +56,8 @@ static m64p_error VidExt_Init(void)
|
||||
l_SurfaceFormat.setOption(QSurfaceFormat::DeprecatedFunctions, 1);
|
||||
l_SurfaceFormat.setDepthBufferSize(24);
|
||||
l_SurfaceFormat.setProfile(QSurfaceFormat::CompatibilityProfile);
|
||||
l_SurfaceFormat.setMajorVersion(2);
|
||||
l_SurfaceFormat.setMinorVersion(1);
|
||||
l_SurfaceFormat.setMajorVersion(3);
|
||||
l_SurfaceFormat.setMinorVersion(0);
|
||||
l_SurfaceFormat.setSwapInterval(0);
|
||||
|
||||
l_EmuThread->on_VidExt_Init();
|
||||
@@ -64,9 +67,13 @@ static m64p_error VidExt_Init(void)
|
||||
|
||||
static m64p_error VidExt_Quit(void)
|
||||
{
|
||||
OnScreenDisplayShutdown();
|
||||
|
||||
l_OGLWidget->MoveContextToThread(QApplication::instance()->thread());
|
||||
l_EmuThread->on_VidExt_Quit();
|
||||
l_VidExtSetup = false;
|
||||
|
||||
l_VidExtInitialized = false;
|
||||
l_OsdInitialized = false;
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
@@ -83,11 +90,25 @@ static m64p_error VidExt_ListRates(m64p_2d_size Size, int *NumRates, int *Rates)
|
||||
|
||||
static m64p_error VidExt_SetMode(int Width, int Height, int BitsPerPixel, int ScreenMode, int Flags)
|
||||
{
|
||||
if (!l_VidExtSetup)
|
||||
if (!l_VidExtInitialized)
|
||||
{
|
||||
VidExt_OglSetup();
|
||||
}
|
||||
|
||||
// try to initialize the OSD
|
||||
// when opengl 3 is used
|
||||
if (l_SurfaceFormat.majorVersion() == 3 &&
|
||||
!l_OsdInitialized)
|
||||
{
|
||||
if (!OnScreenDisplayInit())
|
||||
{
|
||||
return M64ERR_SYSTEM_FAIL;
|
||||
}
|
||||
|
||||
OnScreenDisplayLoadSettings();
|
||||
l_OsdInitialized = true;
|
||||
}
|
||||
|
||||
switch (ScreenMode)
|
||||
{
|
||||
default:
|
||||
@@ -101,6 +122,7 @@ static m64p_error VidExt_SetMode(int Width, int Height, int BitsPerPixel, int Sc
|
||||
break;
|
||||
}
|
||||
|
||||
OnScreenDisplaySetDisplaySize(Width, Height);
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -244,6 +266,8 @@ static m64p_error VidExt_GLSwapBuf(void)
|
||||
return M64ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
OnScreenDisplayRender();
|
||||
|
||||
l_OGLWidget->GetContext()->swapBuffers(l_OGLWidget);
|
||||
l_OGLWidget->GetContext()->makeCurrent(l_OGLWidget);
|
||||
|
||||
@@ -280,6 +304,7 @@ static m64p_error VidExt_ToggleFS(void)
|
||||
static m64p_error VidExt_ResizeWindow(int Width, int Height)
|
||||
{
|
||||
l_EmuThread->on_VidExt_ResizeWindow(Width, Height);
|
||||
OnScreenDisplaySetDisplaySize(Width, Height);
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+61
-1
@@ -15,14 +15,72 @@
|
||||
#include <QFile>
|
||||
|
||||
#include <RMG-Core/Core.hpp>
|
||||
#include <iostream>
|
||||
|
||||
//
|
||||
// Local Functions
|
||||
//
|
||||
|
||||
void message_handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
bool showDebugQtMessages = false;
|
||||
|
||||
const char* env = std::getenv("RMG_SHOW_DEBUG_QT_MESSAGES");
|
||||
showDebugQtMessages = env != nullptr && std::string(env) == "1";
|
||||
|
||||
std::string typeString;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
if (!showDebugQtMessages)
|
||||
{
|
||||
return;
|
||||
}
|
||||
typeString = "[QT DEBUG] ";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
if (!showDebugQtMessages)
|
||||
{
|
||||
return;
|
||||
}
|
||||
typeString = "[QT WARNING] ";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
if (!showDebugQtMessages)
|
||||
{
|
||||
return;
|
||||
}
|
||||
typeString = "[QT INFO] ";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
typeString = "[QT CRITICAL] ";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
typeString = "[QT FATAL] ";
|
||||
break;
|
||||
}
|
||||
|
||||
std::cerr << typeString << localMsg.constData() << std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// install message handler
|
||||
qInstallMessageHandler(message_handler);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
UserInterface::MainWindow window;
|
||||
|
||||
#ifdef PORTABLE_INSTALL
|
||||
QDir::setCurrent(app.applicationDirPath());
|
||||
#endif
|
||||
|
||||
QCoreApplication::setApplicationName("Rosalie's Mupen GUI");
|
||||
QCoreApplication::setApplicationVersion(QString::fromStdString(CoreGetVersion()));
|
||||
@@ -34,8 +92,10 @@ int main(int argc, char **argv)
|
||||
parser.addVersionOption();
|
||||
// custom options
|
||||
QCommandLineOption fullscreenOption({"f", "fullscreen"}, "Launches ROM in fullscreen mode");
|
||||
QCommandLineOption quitAfterEmulation({"q", "quit-after-emulation"}, "Quits RMG when emulation has finished");
|
||||
QCommandLineOption diskOption("disk", "64DD Disk to open ROM in combination with", "64DD Disk");
|
||||
parser.addOption(fullscreenOption);
|
||||
parser.addOption(quitAfterEmulation);
|
||||
parser.addOption(diskOption);
|
||||
parser.addPositionalArgument("ROM", "ROM to open");
|
||||
|
||||
@@ -52,7 +112,7 @@ int main(int argc, char **argv)
|
||||
QStringList args = parser.positionalArguments();
|
||||
if (!args.empty())
|
||||
{
|
||||
window.OpenROM(args.at(0), parser.value(diskOption), parser.isSet(fullscreenOption));
|
||||
window.OpenROM(args.at(0), parser.value(diskOption), parser.isSet(fullscreenOption), parser.isSet(quitAfterEmulation));
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
|
||||
+5
-18
@@ -4,12 +4,8 @@ script_dir="$(dirname "$0")"
|
||||
toplvl_dir="$(realpath "$script_dir/../../")"
|
||||
build_config="${1:-Debug}"
|
||||
build_dir="$toplvl_dir/Build/$build_config"
|
||||
install_dir="$toplvl_dir/Bin/$build_config"
|
||||
threads="${2:-$(nproc)}"
|
||||
|
||||
generator="Unix Makefiles"
|
||||
msys2="0"
|
||||
|
||||
if [ "$1" = "--help" ] ||
|
||||
[ "$1" = "-h" ]
|
||||
then
|
||||
@@ -19,21 +15,12 @@ fi
|
||||
|
||||
mkdir -p "$build_dir"
|
||||
|
||||
pushd "$build_dir"
|
||||
cmake -S "$toplvl_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE="$build_config" -DPORTABLE_INSTALL=ON -G "Ninja"
|
||||
|
||||
cmake --build "$build_dir" --parallel "$threads"
|
||||
cmake --install "$build_dir" --prefix="$toplvl_dir"
|
||||
|
||||
if [[ $(uname -s) = *MINGW64* ]]
|
||||
then
|
||||
msys2="1"
|
||||
generator="MSYS Makefiles"
|
||||
cmake --build "$build_dir" --target=bundle_dependencies
|
||||
fi
|
||||
|
||||
cmake -S "$toplvl_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE="$build_config" -DPORTABLE_INSTALL=ON -G "$generator"
|
||||
|
||||
make install DESTDIR="$toplvl_dir" -j$threads
|
||||
|
||||
if [[ "$msys2" = "1" ]]
|
||||
then
|
||||
make bundle_dependencies
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
@@ -29,17 +29,17 @@ function findAndCopyDLL() {
|
||||
}
|
||||
|
||||
|
||||
for file in "$bin_dir"/*.exe "$bin_dir/Plugin"/*/*.dll
|
||||
for file in "$bin_dir"/*.exe "$bin_dir/Core"/*.dll "$bin_dir/Plugin"/*/*.dll
|
||||
do
|
||||
echo "=> Copying dependencies for $file"
|
||||
copyForOBJ "$file"
|
||||
done
|
||||
|
||||
windeployqt-qt6 "$exe"
|
||||
windeployqt-qt6 --no-translations "$exe"
|
||||
|
||||
# needed by Qt at runtime
|
||||
cp "$path/libcrypto-1_1-x64.dll" "$bin_dir/"
|
||||
cp "$path/libssl-1_1-x64.dll" "$bin_dir/"
|
||||
cp "$path/libjpeg-8.dll" "$bin_dir/"
|
||||
cp "$path/libcrypto-3-x64.dll" "$bin_dir/"
|
||||
cp "$path/libssl-3-x64.dll" "$bin_dir/"
|
||||
cp "$path/libjpeg-8.dll" "$bin_dir/"
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
script_dir="$(dirname "$0")"
|
||||
toplvl_dir="$(realpath "$script_dir/../../")"
|
||||
tmp_dir="$toplvl_dir/Build/RMG-Dark-Style/"
|
||||
target_styles_dir="$toplvl_dir/Bin/Release/Data/Styles/"
|
||||
|
||||
mkdir -p "$target_styles_dir"
|
||||
rm -rf "$tmp_dir"
|
||||
|
||||
git clone https://github.com/Rosalie241/Dolphin-Dark-Mode/ "$tmp_dir" -b RMG
|
||||
|
||||
cp -r "$tmp_dir/Data/Styles"/* "$target_styles_dir/"
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
script_dir="$(dirname "$0")"
|
||||
toplvl_dir="$(realpath "$script_dir/../../")"
|
||||
|
||||
pushd "$toplvl_dir"
|
||||
|
||||
find Source/ -iname *.hpp -o -iname *.cpp | xargs clang-format -i
|
||||
|
||||
popd
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
script_dir="$(dirname "$0")"
|
||||
toplvl_dir="$(realpath "$script_dir/../../")"
|
||||
build_config="${1:-Debug}"
|
||||
version="$(git describe --always)"
|
||||
|
||||
pushd "$toplvl_dir/Bin/$build_config"
|
||||
|
||||
zip -r "$toplvl_dir/Bin/RMG-linux-$version.zip" *
|
||||
|
||||
popd
|
||||
Reference in New Issue
Block a user