From 5e5ae8188efdc6048042da260a41fd304d301a6a Mon Sep 17 00:00:00 2001 From: Ralf Bernhard Date: Sat, 3 Feb 2024 17:37:26 +0100 Subject: [PATCH 1/4] - Fixed a few compiler warning (size_t/int) - VStudio solution file is now compiling - Defined variables for the Windows redistributables (makes the script version independ from VStudio) --- _build/win/qt4/_cmake_qt4/CMakeLists.txt | 37 +++++++++++++++--------- _build/win/qt4/_create_env_cfg.cmd | 7 ++++- _build/win/qt4/_create_versioninfo.cmd | 2 +- _build/win/qt4/build_qmake_qt4-x86.cmd | 5 +++- base/FightCategoryManagerDlg.cpp | 2 +- base/MainWindow.cpp | 4 +-- base/MainWindowTeam.cpp | 2 +- base/_copy_files.cmd | 27 +++++++++-------- base/base.pro | 1 - core/TournamentModel.cpp | 8 ++--- 10 files changed, 56 insertions(+), 39 deletions(-) diff --git a/_build/win/qt4/_cmake_qt4/CMakeLists.txt b/_build/win/qt4/_cmake_qt4/CMakeLists.txt index b02742a3..4eecd041 100644 --- a/_build/win/qt4/_cmake_qt4/CMakeLists.txt +++ b/_build/win/qt4/_cmake_qt4/CMakeLists.txt @@ -4,17 +4,13 @@ cmake_minimum_required(VERSION 3.13) project(Ipponboard VERSION 2.0.0 LANGUAGES C CXX) message(STATUS "using: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") -find_package(Qt4 4.8.7 REQUIRED QtCore QtGui QtXmlPatterns) - set(CMAKE_CXX_STANDARD 17) -set(CMAKE_PREFIX_PATH "$ENV{QTDIR}") -set (BOOST_DIR C:/dev/inst/boost_1_82_0) -set (XMLQUERY $ENV{QTDIR}/include/QtXmlPatterns) - set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) +##################################################### # compile Ipponboard +##################################################### set (BASE_DIR ../../../..) set( SOURCES ${BASE_DIR}/core/Controller.cpp ${BASE_DIR}/core/Controller.h @@ -68,9 +64,12 @@ ${BASE_DIR}/base/view_vertical_single.ui ${BASE_DIR}/base/qrc_ipponboard.cpp ) +set(BOOST_DIR C:/dev/inst/boost_1_82_0) include_directories(base ${BOOST_DIR} ${XMLQUERY} ) +##################################################### # Target Ipponboard: create a binary +##################################################### add_executable(Ipponboard ${SOURCES} ${BASE_DIR}/base/Ipponboard.rc) set_target_properties(Ipponboard PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BASE_DIR}/bin" @@ -83,30 +82,42 @@ set_target_properties(Ipponboard PROPERTIES ) target_link_libraries(Ipponboard Qt4::QtCore Qt4::QtGui Qt4::QtXmlPatterns) +##################################################### # Target Ipponboard_Debug: create a debug binary +##################################################### add_executable(Ipponboard_Debug ${SOURCES} ${BASE_DIR}/base/Ipponboard.rc) set_target_properties(Ipponboard_Debug PROPERTIES OUTPUT_NAME Ipponboard_Debug DEBUG_POSTFIX _d RUNTIME_OUTPUT_DIRECTORY "${BASE_DIR}/bin" + #ENV{QTDIR} "c:/dev/inst/qt/qt-4.8.7-x64-msvc2017" ) target_link_libraries(Ipponboard_Debug Qt4::QtCore Qt4::QtGui Qt4::QtXmlPatterns) if(WIN32) - set(CMAKE_SUPPRESS_REGENERATION true) + set(CMAKE_SUPPRESS_REGENERATION true) + set (CMAKE_PREFIX_PATH "$ENV{QTDIR}") + set (XMLQUERY $ENV{QTDIR}/include/QtXmlPatterns) - # Target Ipponboard - add_custom_command(TARGET Ipponboard POST_BUILD - COMMAND call "${BASE_DIR}/base/_copy_files.cmd" -release - ) + message(STATUS "Using QTDIR=$ENV{QTDIR}") + find_package(Qt4 4.8.7 REQUIRED QtCore QtGui QtXmlPatterns) - # Target Ipponboard_Debug + ##################################################### + # custom commands + ##################################################### add_custom_command(TARGET Ipponboard_Debug POST_BUILD - COMMAND call "../_env_cfg-x64.cmd" + # the following environment variable is needed, if using VStudio GUI (solution) + #COMMAND set QTDIR="c:\\dev\\inst\\qt\\qt-4.8.7-x64-msvc2017" COMMAND call "${BASE_DIR}/base/_copy_files.cmd" -debug ) + add_custom_command(TARGET Ipponboard POST_BUILD + COMMAND call "${BASE_DIR}/base/_copy_files.cmd" -release + ) + + ##################################################### # Target setup + ##################################################### add_custom_target(setup COMMAND call "../_build_doc.cmd" ${BASE_DIR} COMMAND cmd /c "%INNO_DIR%/iscc.exe" /Q /O${BASE_DIR}/bin ${BASE_DIR}/setup/setup.iss diff --git a/_build/win/qt4/_create_env_cfg.cmd b/_build/win/qt4/_create_env_cfg.cmd index db863c6f..45d2af1b 100644 --- a/_build/win/qt4/_create_env_cfg.cmd +++ b/_build/win/qt4/_create_env_cfg.cmd @@ -13,11 +13,16 @@ if EXIST "%LOCAL_CONFIG%" ( call "%LOCAL_CONFIG%" echo; ) else ( + echo create file=%LOCAL_CONFIG% echo @echo off>"%LOCAL_CONFIG%" echo set QTDIR=C:\dev\inst\qt\qt-4.8.7-%ARCH%-msvc2017>>"%LOCAL_CONFIG%" echo set PATH=%%PATH%%;%%QTDIR%%\bin;C:\dev\inst\jom_1_1_3>>"%LOCAL_CONFIG%" echo set QMAKESPEC=%%QTDIR%%\mkspecs\win32-msvc2017>>"%LOCAL_CONFIG%" echo set BOOST_DIR=C:\dev\inst\boost_1_82_0>>"%LOCAL_CONFIG%" echo set INNO_DIR=C:\dev\inst\InnoSetup6>>"%LOCAL_CONFIG%" - CALL "%LOCAL_CONFIG%" + echo set REDIST_DIR_x86=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33135\x86\Microsoft.VC143.CRT>>"%LOCAL_CONFIG%" + echo set REDIST_DIR_x64=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33135\x64\Microsoft.VC143.CRT>>"%LOCAL_CONFIG%" + echo set REDIST_DIR_x86d=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33135\debug_nonredist\x86\Microsoft.VC143.DebugCRT>>"%LOCAL_CONFIG%" + echo set REDIST_DIR_x64d=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33135\debug_nonredist\x64\Microsoft.VC143.DebugCRT>>"%LOCAL_CONFIG%" + CALL "%LOCAL_CONFIG%" ) diff --git a/_build/win/qt4/_create_versioninfo.cmd b/_build/win/qt4/_create_versioninfo.cmd index be6c1361..7bb7980b 100644 --- a/_build/win/qt4/_create_versioninfo.cmd +++ b/_build/win/qt4/_create_versioninfo.cmd @@ -1,4 +1,4 @@ -::@echo off +@echo off setlocal if [%1] == [] ( diff --git a/_build/win/qt4/build_qmake_qt4-x86.cmd b/_build/win/qt4/build_qmake_qt4-x86.cmd index c8d81581..4760aa19 100644 --- a/_build/win/qt4/build_qmake_qt4-x86.cmd +++ b/_build/win/qt4/build_qmake_qt4-x86.cmd @@ -30,7 +30,7 @@ if not exist "%QTDIR%\bin\qmake.exe" ( setlocal set BASE_DIR=%~dp0..\..\.. -call _create_versioninfo.cmd %BASE_DIR%\base +call _create_versioninfo.cmd %BASE_DIR%\base || exit /b %errorlevel% if "%2"=="debug" (set BIN_DIR=%BASE_DIR%\bin\Debug) else (set BIN_DIR=%BASE_DIR%\bin\Release) @@ -133,9 +133,12 @@ exit /b 0 rd /Q /S "%BIN_DIR%" >nul 2>&1 if exist "%BASE_DIR%\base\versioninfo.h" del "%BASE_DIR%\base\versioninfo.h" >nul || exit /b %errorlevel% + call :make_makefiles call :clean test || exit /b %errorlevel% call :clean base || exit /b %errorlevel% call :clean GamepadDemo || exit /b %errorlevel% + + call %~dp0_create_versioninfo.cmd %BASE_DIR%\base || exit /b %errorlevel% exit /b 0 ::------------------------------- diff --git a/base/FightCategoryManagerDlg.cpp b/base/FightCategoryManagerDlg.cpp index b329e5ba..52a701b0 100644 --- a/base/FightCategoryManagerDlg.cpp +++ b/base/FightCategoryManagerDlg.cpp @@ -109,7 +109,7 @@ void FightCategoryManagerDlg::on_pushButton_add_pressed() void FightCategoryManagerDlg::load_values() //--------------------------------------------------------- { - for (int i(0); i < m_pClassMgr->CategoryCount(); ++i) + for (int i(0); i < (int)m_pClassMgr->CategoryCount(); ++i) { Ipponboard::FightCategory classItem; m_pClassMgr->GetCategory(i, classItem); diff --git a/base/MainWindow.cpp b/base/MainWindow.cpp index cefb2ab1..1abcf7ee 100644 --- a/base/MainWindow.cpp +++ b/base/MainWindow.cpp @@ -62,7 +62,7 @@ void MainWindow::Init() MainWindowBase::Init(); // init tournament classes (if there are none present) - for (int i(0); i < m_pCategoryManager->CategoryCount(); ++i) + for (int i(0); i < (int)m_pCategoryManager->CategoryCount(); ++i) { FightCategory t(""); m_pCategoryManager->GetCategory(i, t); @@ -86,7 +86,7 @@ void MainWindow::on_actionManageClasses_triggered() m_pUi->comboBox_weight_class->clear(); - for (int i(0); i < m_pCategoryManager->CategoryCount(); ++i) + for (int i(0); i < (int)m_pCategoryManager->CategoryCount(); ++i) { FightCategory t(""); m_pCategoryManager->GetCategory(i, t); diff --git a/base/MainWindowTeam.cpp b/base/MainWindowTeam.cpp index 1f4f0e5a..cc6d7c6b 100644 --- a/base/MainWindowTeam.cpp +++ b/base/MainWindowTeam.cpp @@ -378,7 +378,7 @@ void MainWindowTeam::update_club_views() m_pUi->comboBox_club_home->clear(); m_pUi->comboBox_club_guest->clear(); - for (int i = 0; i < m_pClubManager->ClubCount(); ++i) + for (int i = 0; i < (int)m_pClubManager->ClubCount(); ++i) { Ipponboard::Club club; m_pClubManager->GetClub(i, club); diff --git a/base/_copy_files.cmd b/base/_copy_files.cmd index 12353270..df09b211 100644 --- a/base/_copy_files.cmd +++ b/base/_copy_files.cmd @@ -1,9 +1,12 @@ +echo off +setlocal + set ROOT=%~dp0.. set THIRDPARTY=..\..\3rdParty if "%1"=="-release" set RELEASE=1 if defined RELEASE (set DEST=%ROOT%\bin\Release) else (set DEST=%ROOT%\bin\Debug) -echo Copying files to %DEST% using QTDIR=%QTDIR% ... +echo Copying files to %DEST% using QTDIR=%QTDIR% echo languages rem (mkdir is recursive) if not exist "%DEST%" mkdir "%DEST%">nul @@ -26,24 +29,20 @@ if defined RELEASE ( copy /Y "%QTDIR%\bin\QtNetwork4.dll" "%DEST%">nul || exit /b 1 copy /Y "%QTDIR%\bin\QtXmlPatterns4.dll" "%DEST%">nul || exit /b 1 - copy /Y "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\msvcp140.dll" "%DEST%">nul - copy /Y "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime140.dll" "%DEST%">nul - ::copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\x86\Microsoft.VC143.CRT\msvcp140.dll" "%DEST%">nul - ::copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\x86\Microsoft.VC143.CRT\vcruntime140.dll" "%DEST%">nul - copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\x64\Microsoft.VC143.CRT\msvcp140.dll" "%DEST%">nul - copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\x64\Microsoft.VC143.CRT\vcruntime140.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x86%\msvcp140.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x86%\vcruntime140.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x64%\msvcp140.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x64%\vcruntime140.dll" "%DEST%">nul ) else ( copy /Y "%QTDIR%\bin\QtCored4.dll" "%DEST%">nul || exit /b 1 copy /Y "%QTDIR%\bin\QtGuid4.dll" "%DEST%">nul || exit /b 1 copy /Y "%QTDIR%\bin\QtNetworkd4.dll" "%DEST%">nul || exit /b 1 copy /Y "%QTDIR%\bin\QtXmlPatternsd4.dll" "%DEST%">nul || exit /b 1 - copy /Y "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\debug_nonredist\x64\Microsoft.VC142.DebugCRT\msvcp140d.dll" "%DEST%">nul - copy /Y "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\debug_nonredist\x64\Microsoft.VC142.DebugCRT\vcruntime140d.dll" "%DEST%">nul - ::copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\debug_nonredist\x86\Microsoft.VC143.DebugCRT\msvcp140d.dll" "%DEST%">nul - ::copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\debug_nonredist\x86\Microsoft.VC143.DebugCRT\vcruntime140d.dll" "%DEST%">nul - copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\debug_nonredist\x64\Microsoft.VC143.DebugCRT\msvcp140d.dll" "%DEST%">nul - copy /Y "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.38.33130\debug_nonredist\x64\Microsoft.VC143.DebugCRT\vcruntime140d.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x86d%\msvcp140d.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x86d%\vcruntime140d.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x64d%\msvcp140d.dll" "%DEST%">nul + copy /Y "%REDIST_DIR_x64d%\vcruntime140d.dll" "%DEST%">nul ) REM -- doc @@ -69,5 +68,5 @@ REM if not exist "%DEST%\Ipponboard.exe" ( REM pause REM exit 1 REM ) - +endlocal exit /b 0 \ No newline at end of file diff --git a/base/base.pro b/base/base.pro index 5b6861bc..dc0b2c90 100644 --- a/base/base.pro +++ b/base/base.pro @@ -118,7 +118,6 @@ HEADERS = pch.h \ SOURCES = Main.cpp \ - Main.cpp \ MainWindow.cpp \ MainWindowTeam.cpp \ ../util/jsoncpp/json.cpp \ diff --git a/core/TournamentModel.cpp b/core/TournamentModel.cpp index 9d684003..3910eaca 100644 --- a/core/TournamentModel.cpp +++ b/core/TournamentModel.cpp @@ -121,7 +121,7 @@ QVariant TournamentModel::data(const QModelIndex& index, int role) const { case Qt::EditRole: case Qt::DisplayRole: - if (index.row() < m_nRows && + if (index.row() < (int)m_nRows && index.column() >= 0 && index.column() < eCol_MAX) { @@ -296,7 +296,7 @@ bool TournamentModel::setData(const QModelIndex& index, bool result(false); - if (index.row() < m_nRows && + if (index.row() < (int)m_nRows && index.column() >= 0 && index.column() < eCol_MAX) { @@ -453,7 +453,7 @@ std::pair TournamentModel::GetTotalWins() const int wins1(0); int wins2(0); - for (int i(0); i < m_nRows; ++i) + for (int i(0); i < (int)m_nRows; ++i) { wins1 += m_pTournamentRound->at(i).HasWon(Ipponboard::FighterEnum::First); wins2 += m_pTournamentRound->at(i).HasWon(Ipponboard::FighterEnum::Second); @@ -469,7 +469,7 @@ std::pair TournamentModel::GetTotalScore() const int score1(0); int score2(0); - for (int i(0); i < m_nRows; ++i) + for (int i(0); i < (int)m_nRows; ++i) { score1 += m_pTournamentRound->at(i).GetScorePoints(Ipponboard::FighterEnum::First); score2 += m_pTournamentRound->at(i).GetScorePoints(Ipponboard::FighterEnum::Second); From c25f6978ba824ad63335b2a43fa07a5e7389162b Mon Sep 17 00:00:00 2001 From: Ralf Bernhard Date: Sat, 3 Feb 2024 17:43:24 +0100 Subject: [PATCH 2/4] Cleaned CMakefile --- _build/win/qt4/_cmake_qt4/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/_build/win/qt4/_cmake_qt4/CMakeLists.txt b/_build/win/qt4/_cmake_qt4/CMakeLists.txt index 4eecd041..3a452b32 100644 --- a/_build/win/qt4/_cmake_qt4/CMakeLists.txt +++ b/_build/win/qt4/_cmake_qt4/CMakeLists.txt @@ -77,7 +77,6 @@ set_target_properties(Ipponboard PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" else() LINK_FLAGS_RELEASE "-mwindows" -# oder das? --> SUBSYSTEM_LINKER_OPTIONS "-mwindows" endif() ) target_link_libraries(Ipponboard Qt4::QtCore Qt4::QtGui Qt4::QtXmlPatterns) @@ -90,7 +89,6 @@ set_target_properties(Ipponboard_Debug PROPERTIES OUTPUT_NAME Ipponboard_Debug DEBUG_POSTFIX _d RUNTIME_OUTPUT_DIRECTORY "${BASE_DIR}/bin" - #ENV{QTDIR} "c:/dev/inst/qt/qt-4.8.7-x64-msvc2017" ) target_link_libraries(Ipponboard_Debug Qt4::QtCore Qt4::QtGui Qt4::QtXmlPatterns) From 8d6bffff35a5fdecee46c1de0b04ff00a8c01367 Mon Sep 17 00:00:00 2001 From: Ralf Bernhard Date: Sat, 3 Feb 2024 20:55:19 +0100 Subject: [PATCH 3/4] encapsulated Gamepad source code by the compiler directive _WITH_GAMEPAD_ --- _build/win/qt4/_cmake_qt4/CMakeLists.txt | 7 +- base/MainWindow.cpp | 4 + base/MainWindowBase.cpp | 17 +- base/MainWindowBase.h | 8 + base/MainWindowTeam.cpp | 6 + base/MainWindowTeam.h | 2 + base/SettingsDlg.cpp | 11 +- base/SettingsDlg.h | 4 + gamepad/gamepad.h | 616 ----------------------- 9 files changed, 53 insertions(+), 622 deletions(-) delete mode 100644 gamepad/gamepad.h diff --git a/_build/win/qt4/_cmake_qt4/CMakeLists.txt b/_build/win/qt4/_cmake_qt4/CMakeLists.txt index 3a452b32..925d0d5e 100644 --- a/_build/win/qt4/_cmake_qt4/CMakeLists.txt +++ b/_build/win/qt4/_cmake_qt4/CMakeLists.txt @@ -89,11 +89,12 @@ set_target_properties(Ipponboard_Debug PROPERTIES OUTPUT_NAME Ipponboard_Debug DEBUG_POSTFIX _d RUNTIME_OUTPUT_DIRECTORY "${BASE_DIR}/bin" + COMPILE_FLAGS -D_WITH_GAMEPAD_ ) target_link_libraries(Ipponboard_Debug Qt4::QtCore Qt4::QtGui Qt4::QtXmlPatterns) if(WIN32) - set(CMAKE_SUPPRESS_REGENERATION true) + set (CMAKE_SUPPRESS_REGENERATION true) set (CMAKE_PREFIX_PATH "$ENV{QTDIR}") set (XMLQUERY $ENV{QTDIR}/include/QtXmlPatterns) @@ -105,7 +106,7 @@ if(WIN32) ##################################################### add_custom_command(TARGET Ipponboard_Debug POST_BUILD # the following environment variable is needed, if using VStudio GUI (solution) - #COMMAND set QTDIR="c:\\dev\\inst\\qt\\qt-4.8.7-x64-msvc2017" + COMMAND set QTDIR="c:\\dev\\inst\\qt\\qt-4.8.7-x64-msvc2017" COMMAND call "${BASE_DIR}/base/_copy_files.cmd" -debug ) @@ -126,4 +127,4 @@ endif () # compile Testsuites add_subdirectory(${BASE_DIR}/test/cmake_qt4 ${BASE_DIR}/test/_build_cmake_qt4) -add_subdirectory(${BASE_DIR}/GamepadDemo/cmake_qt4 ${BASE_DIR}/GamepadDemo/_build_cmake_qt4) +#add_subdirectory(${BASE_DIR}/GamepadDemo/cmake_qt4 ${BASE_DIR}/GamepadDemo/_build_cmake_qt4) diff --git a/base/MainWindow.cpp b/base/MainWindow.cpp index 1abcf7ee..60590491 100644 --- a/base/MainWindow.cpp +++ b/base/MainWindow.cpp @@ -14,7 +14,9 @@ #include "../core/ControllerConfig.h" #include "../core/Fighter.h" #include "../core/TournamentModel.h" +#ifdef _WITH_GAMEPAD_ #include "../gamepad/gamepad.h" +#endif #include "../util/path_helpers.h" #include "../Widgets/ScaledImage.h" #include "../Widgets/ScaledText.h" @@ -40,7 +42,9 @@ namespace StrTags static const char* const edition = "Basic Edition"; } +#ifdef _WITH_GAMEPAD_ using namespace FMlib; +#endif using namespace Ipponboard; MainWindow::MainWindow(QWidget* parent) diff --git a/base/MainWindowBase.cpp b/base/MainWindowBase.cpp index c3b883e2..09f1e6e0 100644 --- a/base/MainWindowBase.cpp +++ b/base/MainWindowBase.cpp @@ -11,7 +11,9 @@ #include "../core/Enums.h" #include "../base/versioninfo.h" #include "../base/SettingsDlg.h" +#ifdef _WITH_GAMEPAD_ #include "../gamepad/gamepad.h" +#endif #include "../core/Rules.h" #include "../util/path_helpers.h" @@ -27,7 +29,9 @@ #include #include +#ifdef _WITH_GAMEPAD_ using namespace FMlib; +#endif using namespace Ipponboard; using Point = Score::Point; @@ -44,7 +48,9 @@ MainWindowBase::MainWindowBase(QWidget* parent) , m_secondScreenNo(0) , m_secondScreenSize() , m_controllerCfg() +#ifdef _WITH_GAMEPAD_ , m_pGamepad(new Gamepad) +#endif { } @@ -83,10 +89,12 @@ void MainWindowBase::Init() change_lang(true); +#ifdef _WITH_GAMEPAD_ // Init gamepad QTimer* m_pTimer = new QTimer; connect(m_pTimer, SIGNAL(timeout()), this, SLOT(EvaluateInput())); m_pTimer->start(75); +#endif update_statebar(); @@ -598,6 +606,7 @@ void MainWindowBase::read_settings() } settings.endGroup(); +#ifdef _WITH_GAMEPAD_ settings.beginGroup(str_tag_Input); { m_controllerCfg.button_hajime_mate = @@ -647,6 +656,7 @@ void MainWindowBase::read_settings() m_pGamepad->SetInverted(FMlib::Gamepad::eAxis_Z, m_controllerCfg.axis_inverted_Z); } settings.endGroup(); +#endif settings.beginGroup(str_tag_Sounds); { @@ -736,7 +746,9 @@ void MainWindowBase::on_actionPreferences_triggered() dlg.SetTextColorsFirst(m_pPrimaryView->GetTextColorFirst(), m_pPrimaryView->GetTextBgColorFirst()); dlg.SetTextColorsSecond(m_pPrimaryView->GetTextColorSecond(), m_pPrimaryView->GetTextBgColorSecond()); dlg.SetScreensSettings(m_secondScreenNo, m_secondScreenSize); +#ifdef _WITH_GAMEPAD_ dlg.SetControllerConfig(&m_controllerCfg); +#endif dlg.SetLabels(m_MatLabel, m_pController->GetHomeLabel(), m_pController->GetGuestLabel()); dlg.SetGongFile(m_pController->GetGongFile()); @@ -752,13 +764,14 @@ void MainWindowBase::on_actionPreferences_triggered() m_secondScreenNo = dlg.GetSelectedScreen(); m_secondScreenSize = dlg.GetSize(); +#ifdef _WITH_GAMEPAD_ dlg.GetControllerConfig(&m_controllerCfg); // apply settings to gamepad m_pGamepad->SetInverted(FMlib::Gamepad::eAxis_X, m_controllerCfg.axis_inverted_X); m_pGamepad->SetInverted(FMlib::Gamepad::eAxis_Y, m_controllerCfg.axis_inverted_Y); m_pGamepad->SetInverted(FMlib::Gamepad::eAxis_R, m_controllerCfg.axis_inverted_R); m_pGamepad->SetInverted(FMlib::Gamepad::eAxis_Z, m_controllerCfg.axis_inverted_Z); - +#endif m_MatLabel = dlg.GetMatLabel(); m_pController->SetLabels(dlg.GetHomeLabel(), dlg.GetGuestLabel()); @@ -814,6 +827,7 @@ void MainWindowBase::show_hide_view() const isAlreadyCalled = false; } +#ifdef _WITH_GAMEPAD_ void MainWindowBase::EvaluateInput() { if (Gamepad::eState_ok != m_pGamepad->GetState()) @@ -973,6 +987,7 @@ void MainWindowBase::EvaluateInput() } } } +#endif void MainWindowBase::update_info_text_color(const QColor& color, const QColor& bgColor) { diff --git a/base/MainWindowBase.h b/base/MainWindowBase.h index 4e06e5a6..2b5bfe9b 100644 --- a/base/MainWindowBase.h +++ b/base/MainWindowBase.h @@ -33,11 +33,13 @@ class ScoreScreen; } class QSettings; +#ifdef _WITH_GAMEPAD_ namespace FMlib { class Gamepad; } typedef std::shared_ptr PGamepad; +#endif static const char* const str_golden_score = "Golden Score"; static const char* const str_normal_round_time = "Normal"; @@ -147,7 +149,9 @@ protected slots: //void on_actionReset_Scores_triggered(); void on_actionPreferences_triggered(); void on_button_reset_clicked(); +#ifdef _WITH_GAMEPAD_ void EvaluateInput(); +#endif void on_actionLang_English_triggered(bool); void on_actionLang_Deutsch_triggered(bool); void on_actionLang_Dutch_triggered(bool); @@ -165,7 +169,9 @@ protected slots: protected: +#ifdef _WITH_GAMEPAD_ virtual bool EvaluateSpecificInput(FMlib::Gamepad const* /*pGamepad*/) { return false; } +#endif std::shared_ptr m_pPrimaryView; std::shared_ptr m_pSecondaryView; @@ -180,7 +186,9 @@ protected slots: Ipponboard::ControllerConfig m_controllerCfg; private: +#ifdef _WITH_GAMEPAD_ PGamepad m_pGamepad; +#endif }; #endif // BASE__MAINWINDOW_BASE_H_ diff --git a/base/MainWindowTeam.cpp b/base/MainWindowTeam.cpp index cc6d7c6b..761877fd 100644 --- a/base/MainWindowTeam.cpp +++ b/base/MainWindowTeam.cpp @@ -19,7 +19,9 @@ #include "../core/ControllerConfig.h" #include "../core/Tournament.h" #include "../core/TournamentModel.h" +#ifdef _WITH_GAMEPAD_ #include "../gamepad/gamepad.h" +#endif #include "../util/path_helpers.h" #include "../Widgets/ScaledImage.h" #include "../Widgets/ScaledText.h" @@ -54,7 +56,9 @@ static const char* const mode = "Mode"; static const char* const host = "Host"; } +#ifdef _WITH_GAMEPAD_ using namespace FMlib; +#endif using namespace Ipponboard; namespace { bool initialized = false; } @@ -670,6 +674,7 @@ void MainWindowTeam::on_actionReset_Scores_triggered() UpdateButtonText_(); } +#ifdef _WITH_GAMEPAD_ bool MainWindowTeam::EvaluateSpecificInput(const Gamepad* pGamepad) { // back @@ -691,6 +696,7 @@ bool MainWindowTeam::EvaluateSpecificInput(const Gamepad* pGamepad) return false; } +#endif void MainWindowTeam::on_tabWidget_currentChanged(int /*index*/) { diff --git a/base/MainWindowTeam.h b/base/MainWindowTeam.h index 3c7aec08..146e3bb2 100644 --- a/base/MainWindowTeam.h +++ b/base/MainWindowTeam.h @@ -116,7 +116,9 @@ private slots: //void on_comboBox_weight_class_currentIndexChanged(const QString&); void on_actionReset_Scores_triggered(); +#ifdef _WITH_GAMEPAD_ virtual bool EvaluateSpecificInput(FMlib::Gamepad const* pGamepad) override; +#endif private: void update_weights(QString const& weightString); diff --git a/base/SettingsDlg.cpp b/base/SettingsDlg.cpp index 6c8931fe..d5e0fd7a 100644 --- a/base/SettingsDlg.cpp +++ b/base/SettingsDlg.cpp @@ -4,7 +4,9 @@ #include "SettingsDlg.h" #include "ui_SettingsDlg.h" +#ifdef _WITH_GAMEPAD_ #include "../gamepad/gamepad.h" +#endif #include "../core/ControllerConfig.h" #include "../core/Rules.h" @@ -26,9 +28,11 @@ SettingsDlg::SettingsDlg(EditionType edition, QWidget* parent) : if (m_edition == EditionType::Team) { +#ifdef _WITH_GAMEPAD_ ui->comboBox_next->setEnabled(true); ui->comboBox_prev->setEnabled(true); ui->comboBox_pause->setEnabled(true); +#endif ui->comboBox_mat->setEnabled(false); ui->label_home->setEnabled(true); @@ -52,6 +56,7 @@ SettingsDlg::SettingsDlg(EditionType edition, QWidget* parent) : ui->text_color_first->SetText(tr("FIRST FIGHTER")); ui->text_color_second->SetText(tr("SECOND FIGHTER")); +#ifdef _WITH_GAMEPAD_ // build button text map m_buttonTexts[FMlib::Gamepad::eButton1] = "button 1"; m_buttonTexts[FMlib::Gamepad::eButton2] = "button 2"; @@ -96,6 +101,7 @@ SettingsDlg::SettingsDlg(EditionType edition, QWidget* parent) : ui->comboBox_second_holding->addItems(buttons); ui->comboBox_hansokumake_first->addItems(buttons); ui->comboBox_hansokumake_second->addItems(buttons); +#endif // num screens int screens = QApplication::desktop()->numScreens(); @@ -177,7 +183,7 @@ SettingsDlg::SettingsDlg(EditionType edition, QWidget* parent) : modifierVals << "Alt+Shift"; modifierVals << "Ctrl+Alt+Shift"; - //FIXME: enable this when keyboard acces is customizable + //FIXME: enable this when keyboard access is customizable //for (int i = 0; i < ui->tableWidget_keys->rowCount(); ++i) //{ // QComboBox* pCombo = new QComboBox(); @@ -377,6 +383,7 @@ void SettingsDlg::on_buttonBox_rejected() reject(); } +#ifdef _WITH_GAMEPAD_ void SettingsDlg::SetControllerConfig(const ControllerConfig* pConfig) { Q_ASSERT(pConfig); @@ -451,7 +458,7 @@ void SettingsDlg::GetControllerConfig(ControllerConfig* pConfig) pConfig->axis_inverted_Z = ui->checkBox_invert_z_axis->isChecked(); } } - +#endif //--------------------------------------------------------- void SettingsDlg::changeEvent(QEvent* e) diff --git a/base/SettingsDlg.h b/base/SettingsDlg.h index 3e081b32..ebac5b55 100644 --- a/base/SettingsDlg.h +++ b/base/SettingsDlg.h @@ -19,7 +19,9 @@ class SettingsDlg; namespace Ipponboard { +#ifdef _WITH_GAMEPAD_ struct ControllerConfig; +#endif class SettingsDlg : public QDialog { @@ -52,8 +54,10 @@ class SettingsDlg : public QDialog QString GetGuestLabel() const; QString GetGongFile() const; +#ifdef _WITH_GAMEPAD_ void SetControllerConfig(const ControllerConfig* pConfig); void GetControllerConfig(ControllerConfig* pConfig); +#endif protected: void changeEvent(QEvent* e); diff --git a/gamepad/gamepad.h b/gamepad/gamepad.h deleted file mode 100644 index b725376a..00000000 --- a/gamepad/gamepad.h +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright 2018 Florian Muecke. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.txt file. - -#ifndef FMLIB_GAMEPAD_H_ -#define FMLIB_GAMEPAD_H_ - -#pragma once - -#include -#include -#include - -#include -#include - -#pragma comment(lib,"Winmm.lib") - -namespace FMlib -{ -class Gamepad -{ -public: - using UnsignedPair = std::pair; - - enum EButton - { - eButton1 = 0, - eButton2, - eButton3, - eButton4, - eButton5, - eButton6, - eButton7, - eButton8, - eButton9, - eButton10, - eButton11, - eButton12, - eButton13, - eButton14, - eButton15, - eButton16, - eButton17, - eButton18, - eButton19, - eButton20, - eButton21, - eButton22, - eButton23, - eButton24, - eButton25, - eButton26, - eButton27, - eButton28, - eButton29, - eButton30, - eButton31, - eButton32, - eButton_pov_fwd, - eButton_pov_right, - eButton_pov_back, - eButton_pov_left, - eButton_pov_right_fwd, - eButton_pov_right_back, - eButton_pov_left_back, - eButton_pov_left_fwd - }; - - enum EState - { - eState_unknown = -1, - eState_ok = JOYERR_NOERROR, - eState_no_driver = MMSYSERR_NODRIVER, - eState_invalid_param = MMSYSERR_INVALPARAM, - eState_bad_device_id = MMSYSERR_BADDEVICEID, - eState_no_service = JOYERR_NOCANDO, - eState_unplugged = JOYERR_UNPLUGGED, - eState_invalid_id = JOYERR_PARMS - }; - - enum EUpdateAction - { - update_always = false, - update_on_change = true - }; - - enum EPovType - { - ePovType_unknown = -1, - ePovType_no_pov = 0, - ePovType_discrete = JOYCAPS_POV4DIR, - ePovType_continuous = JOYCAPS_POVCTS - }; - - enum EAxis - { - eAxis_X = 0, - eAxis_Y, - eAxis_Z, - eAxis_R, - eAxis_U, - eAxis_V, - eAxis_MAX - }; - - enum - { - eMax = 65535, - eMid = 32767, - eTolerance = 100 - }; - - Gamepad() - : m_currentId(0) - , m_invertedAxes() - //, m_caps - //, m_data - , m_state(eState_unknown) - , m_hwnd(NULL) - { - reset(); - Init(); - } - - virtual ~Gamepad() - { - if (m_hwnd) - Release(); - } - - Gamepad(const Gamepad&) = delete; - Gamepad& operator=(const Gamepad&) = delete; - - /// reads capabilities - EState Init() - { - m_state = EState(::joyGetDevCaps(0, &m_caps, sizeof(JOYCAPS))); - return m_state; - } - -#if WINVER > 0x0501 - inline const wchar_t* GetProductName() const - { - size_t size = strlen(m_caps.szPname)+1; - wchar_t* unicode_product_name = new wchar_t[size]; - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, unicode_product_name, size, m_caps.szPname, size-1); - - return unicode_product_name; - } -#else - inline const wchar_t* GetProductName() const - { - return m_caps.szPname; - } -#endif - - inline WORD GetMId() const - { - return m_caps.wMid; - } - - inline WORD GetPId() const - { - return m_caps.wPid; - } - - inline unsigned GetNumButtons() const - { - return m_caps.wNumButtons; - } - - inline unsigned GetNumAxes() const - { - return m_caps.wNumAxes; - } - - inline UnsignedPair GetPollingFreq() const - { - return std::make_pair(m_caps.wPeriodMin, m_caps.wPeriodMax); - } - - inline UnsignedPair GetRangeX() const - { - return std::make_pair(m_caps.wXmin, m_caps.wXmax); - } - - inline UnsignedPair GetRangeY() const - { - return std::make_pair(m_caps.wYmin, m_caps.wYmax); - } - - inline UnsignedPair GetRangeZ() const - { - return std::make_pair(m_caps.wZmin, m_caps.wZmax); - } - - inline UnsignedPair GetRangeR() const - { - return std::make_pair(m_caps.wRmin, m_caps.wRmax); - } - - inline UnsignedPair GetRangeU() const - { - return std::make_pair(m_caps.wUmin, m_caps.wUmax); - } - - inline UnsignedPair GetRangeV() const - { - return std::make_pair(m_caps.wVmin, m_caps.wVmax); - } - - inline bool HasAxisZ() const - { - return m_caps.wCaps & JOYCAPS_HASZ; - } - - inline bool HasAxisR() const - { - return (m_caps.wCaps & JOYCAPS_HASR) != 0; - } - - inline bool HasAxisU() const - { - return (m_caps.wCaps & JOYCAPS_HASU) != 0; - } - - inline bool HasAxisV() const - { - return (m_caps.wCaps & JOYCAPS_HASV) != 0; - } - inline EPovType GetPovType() const - { - if (0 == (m_caps.wCaps & JOYCAPS_HASPOV)) - return ePovType_no_pov; - - if (0 != (m_caps.wCaps & JOYCAPS_POVCTS)) - return ePovType_continuous; - else if (0 != (m_caps.wCaps & JOYCAPS_POV4DIR)) - return ePovType_discrete; - else - return ePovType_unknown; - } - - void SetInverted(EAxis axis, bool val = true) - { - m_invertedAxes.set(axis, val); - } - - bool IsInverted(EAxis axis) const - { - return m_invertedAxes.test(axis); - } - - bool WasPressed(EButton b) const - { - if (b > eButton32) - { - if (button_code[b] == m_data.dwPOV && - m_data.dwPOV != m_lastData.dwPOV) - { - return true; - } - - return false; - } - - return (m_lastData.dwButtons & button_code[b]) == 0 && - (m_data.dwButtons & button_code[b]) > 0; - } - - bool WasReleased(EButton b) const - { - assert(b <= eButton32); - return (m_lastData.dwButtons & button_code[b]) > 0 && - (m_data.dwButtons & button_code[b]) == 0; - } - - bool IsPressed(EButton b) const - { - assert(b <= eButton32); - return (m_data.dwButtons & button_code[b]) > 0; - } - - bool WasSectionEnteredXY(float min, float max) const - { - const int lastX = m_invertedAxes.test(eAxis_X) ? - eMax - m_lastData.dwXpos : m_lastData.dwXpos; - const int lastY = m_invertedAxes.test(eAxis_Y) ? - eMax - m_lastData.dwYpos : m_lastData.dwYpos; - - int curX = m_invertedAxes.test(eAxis_X) ? - eMax - m_data.dwXpos : m_data.dwXpos; - int curY = m_invertedAxes.test(eAxis_Y) ? - eMax - m_data.dwYpos : m_data.dwYpos; - - const float lastAlpha = GetAngle( - lastX - eMid, lastY - eMid, 1.02f, eMid); - - const float curAlpha = GetAngle( - curX - eMid, curY - eMid, 1.02f, eMid); - - bool changed(false); - - if (-1.0f == lastAlpha || -1.0f == curAlpha || - fabs(lastAlpha - curAlpha) > eTolerance) - { - changed = true; - } - - if (changed && IsInSection(curAlpha, min, max)) - { - return true; - } - - return false; - } - - bool WasSectionEnteredRZ(float min, float max) const - { - const int lastR = m_invertedAxes.test(eAxis_R) ? - eMax - m_lastData.dwRpos : m_lastData.dwRpos; - const int lastZ = m_invertedAxes.test(eAxis_Z) ? - eMax - m_lastData.dwZpos : m_lastData.dwZpos; - - int curR = m_invertedAxes.test(eAxis_R) ? - eMax - m_data.dwRpos : m_data.dwRpos; - int curZ = m_invertedAxes.test(eAxis_Z) ? - eMax - m_data.dwZpos : m_data.dwZpos; - - const float lastAlpha = GetAngle( - lastR - eMid, lastZ - eMid, 1.02f, eMid); - - const float curAlpha = GetAngle( - curR - eMid, curZ - eMid, 1.02f, eMid); - - bool changed(false); - - if (-1.0f == lastAlpha || -1.0f == curAlpha || - fabs(lastAlpha - curAlpha) > eTolerance) - { - changed = true; - } - - if (changed && IsInSection(curAlpha, min, max)) - { - return true; - } - - return false; - } - - bool WasSectionLeft(float /*min*/, float /*max*/) const - { - return false; - } - - bool IsInSection(const float alpha, const float min, const float max) const - { - bool ret(false); - - if (min > max) - { - if (min <= alpha && alpha <= 360.0f) - { - ret = true; - } - else if (0 < alpha && alpha <= max) - { - ret = true; - } - } - else - { - if (min <= alpha && max >= alpha) - { - ret = true; - } - } - - return ret; - } - - template - T GetAngle(int x, int y, float factor = 0.0f, int max = 0) const - { - if (0 == x && 0 == y) - { - return -1; - } - - T h = sqrt((T)x * x + (T)y * y); - - if (h * factor < (float)max) - { - return -1; - } - - T angle = asin((T)y / h) * 180 / (T)3.141592653589793L; - angle = x > 0 ? 90 - angle : 270 + angle; - - return angle; - } - - //FIXME: use double - float GetAngleXY() const - { - return GetAngle(GetXPos() - eMid, GetYPos() - eMid, 1.2f, eMid); - } - float GetAngleRZ() const - { - return GetAngle(GetRPos() - eMid, GetZPos() - eMid, 1.2f, eMid); - } - - int PressedCount() const - { - return m_data.dwButtonNumber; - } - - unsigned GetXPos() const - { - if (m_invertedAxes.test(eAxis_X)) - return 65535 - m_data.dwXpos; - - return m_data.dwXpos; - } - - unsigned GetYPos() const - { - if (m_invertedAxes.test(eAxis_Y)) - return 65535 - m_data.dwYpos; - - return m_data.dwYpos; - } - - unsigned GetZPos() const - { - if (m_invertedAxes.test(eAxis_Z)) - return 65535 - m_data.dwZpos; - - return m_data.dwZpos; - } - - unsigned GetRPos() const - { - if (m_invertedAxes.test(eAxis_R)) - return 65535 - m_data.dwRpos; - - return m_data.dwRpos; - } - unsigned GetUPos() const - { - if (m_invertedAxes.test(eAxis_U)) - return 65535 - m_data.dwUpos; - - return m_data.dwUpos; - } - - unsigned GetVPos() const - { - if (m_invertedAxes.test(eAxis_V)) - return 65535 - m_data.dwVpos; - - return m_data.dwVpos; - } - - unsigned GetPOV() const - { - return m_data.dwPOV; - } - - - EState ReadData() - { - m_lastData = m_data; - m_state = EState(::joyGetPosEx(m_currentId, &m_data)); - return m_state; - } - - EState GetState() const - { - return m_state; - } - - /// will return -1 if threshold can not be retrieved - unsigned GetThreshold() const - { - unsigned t(0); - - if (eState_ok != ::joyGetThreshold(m_currentId, &t)) - return static_cast(-1); - - return t; - } - - /// Sets the movement threshold for the current controller. - /// @return true if value has been successfully set - bool SetThreshold(unsigned threshold) const - { - return eState_ok == ::joySetThreshold(m_currentId, threshold); - } - - - bool Capture(HWND hwnd, unsigned int period = 125, EUpdateAction when = update_on_change) - { - bool ret(false); - - if (NULL == m_hwnd) - { - int s(::joySetCapture(hwnd, m_currentId, period, - when ? TRUE : FALSE)); - - if (eState_ok == s) - { - m_hwnd = hwnd; - ret = true; - } - } - - return ret; - } - - - bool Release() - { - bool ret(false); - - if (NULL != m_hwnd) - { - int s(::joyReleaseCapture(m_currentId)); - - if (eState_ok == s) - { - m_hwnd = NULL; - ret = true; - } - } - - return ret; - } - - -private: - void reset() - { - m_invertedAxes.reset(); - - memset(&m_caps, 0, sizeof(JOYCAPS)); - memset(&m_data, 0, sizeof(JOYINFOEX)); - m_data.dwSize = sizeof(JOYINFOEX); - m_data.dwFlags = JOY_RETURNALL; - m_lastData = m_data; - } - - const unsigned int button_code[40] = - { - JOY_BUTTON1, - JOY_BUTTON2, - JOY_BUTTON3, - JOY_BUTTON4, - JOY_BUTTON5, - JOY_BUTTON6, - JOY_BUTTON7, - JOY_BUTTON8, - JOY_BUTTON9, - JOY_BUTTON10, - JOY_BUTTON11, - JOY_BUTTON12, - JOY_BUTTON13, - JOY_BUTTON14, - JOY_BUTTON15, - JOY_BUTTON16, - JOY_BUTTON17, - JOY_BUTTON18, - JOY_BUTTON19, - JOY_BUTTON20, - JOY_BUTTON21, - JOY_BUTTON22, - JOY_BUTTON23, - JOY_BUTTON24, - JOY_BUTTON25, - JOY_BUTTON26, - JOY_BUTTON27, - JOY_BUTTON28, - JOY_BUTTON29, - JOY_BUTTON30, - JOY_BUTTON31, - JOY_BUTTON32, - 0, // eButton_pov_fwd - 9000, // eButton_pov_right - 18000, // eButton_pov_back - 27000, // eButton_pov_left - 4500, // ePov_right_fwd - 13500, // eButton_pov_right_back - 22500, // eButton_pov_left_back - 31500 // eButton_pov_left_fwd - }; - - unsigned int m_currentId; - std::bitset m_invertedAxes; -#if WINVER > 0x0501 - JOYCAPSA m_caps; -#else - JOYCAPSW m_caps; -#endif - - JOYINFOEX m_data; - JOYINFOEX m_lastData; - EState m_state; - HWND m_hwnd; -}; - -} //namespace FMlib - -#endif // FMLIB_GAMEPAD_H_ From 28e322279912a1a30efd4250f00c8b353307d4cc Mon Sep 17 00:00:00 2001 From: Ralf Bernhard Date: Sat, 3 Feb 2024 22:52:55 +0100 Subject: [PATCH 4/4] fixed minor stuff --- base/SettingsDlg.cpp | 3 + base/SettingsDlg.ui | 16 +- gamepad/gamepad.h | 616 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 631 insertions(+), 4 deletions(-) create mode 100644 gamepad/gamepad.h diff --git a/base/SettingsDlg.cpp b/base/SettingsDlg.cpp index d5e0fd7a..b71b5616 100644 --- a/base/SettingsDlg.cpp +++ b/base/SettingsDlg.cpp @@ -25,6 +25,9 @@ SettingsDlg::SettingsDlg(EditionType edition, QWidget* parent) : ui(new Ui::SettingsDlg) { ui->setupUi(this); +#ifdef _WITH_GAMEPAD_ + ui->tab_gamepad->setEnabled(true); +#endif if (m_edition == EditionType::Team) { diff --git a/base/SettingsDlg.ui b/base/SettingsDlg.ui index e01aae67..6dfdb128 100644 --- a/base/SettingsDlg.ui +++ b/base/SettingsDlg.ui @@ -9,8 +9,8 @@ 0 0 - 459 - 566 + 517 + 578 @@ -39,7 +39,7 @@ true - 0 + 2 @@ -738,6 +738,9 @@ + + false + :/res/icons/controller.png:/res/icons/controller.png @@ -840,7 +843,7 @@ - true + false QComboBox::AdjustToContentsOnFirstShow @@ -1100,6 +1103,11 @@ true + + + 8 + + QFrame::StyledPanel diff --git a/gamepad/gamepad.h b/gamepad/gamepad.h new file mode 100644 index 00000000..c802d8d8 --- /dev/null +++ b/gamepad/gamepad.h @@ -0,0 +1,616 @@ +// Copyright 2018 Florian Muecke. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.txt file. + +#ifndef FMLIB_GAMEPAD_H_ +#define FMLIB_GAMEPAD_H_ + +#pragma once + +#include +#include +#include + +#include +#include + +#pragma comment(lib,"Winmm.lib") + +namespace FMlib +{ +class Gamepad +{ +public: + using UnsignedPair = std::pair; + + enum EButton + { + eButton1 = 0, + eButton2, + eButton3, + eButton4, + eButton5, + eButton6, + eButton7, + eButton8, + eButton9, + eButton10, + eButton11, + eButton12, + eButton13, + eButton14, + eButton15, + eButton16, + eButton17, + eButton18, + eButton19, + eButton20, + eButton21, + eButton22, + eButton23, + eButton24, + eButton25, + eButton26, + eButton27, + eButton28, + eButton29, + eButton30, + eButton31, + eButton32, + eButton_pov_fwd, + eButton_pov_right, + eButton_pov_back, + eButton_pov_left, + eButton_pov_right_fwd, + eButton_pov_right_back, + eButton_pov_left_back, + eButton_pov_left_fwd + }; + + enum EState + { + eState_unknown = -1, + eState_ok = JOYERR_NOERROR, + eState_no_driver = MMSYSERR_NODRIVER, + eState_invalid_param = MMSYSERR_INVALPARAM, + eState_bad_device_id = MMSYSERR_BADDEVICEID, + eState_no_service = JOYERR_NOCANDO, + eState_unplugged = JOYERR_UNPLUGGED, + eState_invalid_id = JOYERR_PARMS + }; + + enum EUpdateAction + { + update_always = false, + update_on_change = true + }; + + enum EPovType + { + ePovType_unknown = -1, + ePovType_no_pov = 0, + ePovType_discrete = JOYCAPS_POV4DIR, + ePovType_continuous = JOYCAPS_POVCTS + }; + + enum EAxis + { + eAxis_X = 0, + eAxis_Y, + eAxis_Z, + eAxis_R, + eAxis_U, + eAxis_V, + eAxis_MAX + }; + + enum + { + eMax = 65535, + eMid = 32767, + eTolerance = 100 + }; + + Gamepad() + : m_currentId(0) + , m_invertedAxes() + //, m_caps + //, m_data + , m_state(eState_unknown) + , m_hwnd(NULL) + { + reset(); + Init(); + } + + virtual ~Gamepad() + { + if (m_hwnd) + Release(); + } + + Gamepad(const Gamepad&) = delete; + Gamepad& operator=(const Gamepad&) = delete; + + /// reads capabilities + EState Init() + { + m_state = EState(::joyGetDevCaps(0, &m_caps, sizeof(JOYCAPS))); + return m_state; + } + +#if WINVER > 0x0501 + inline const wchar_t* GetProductName() const + { + size_t size = strlen(m_caps.szPname)+1; + wchar_t* unicode_product_name = new wchar_t[size]; + size_t convertedChars = 0; + mbstowcs_s(&convertedChars, unicode_product_name, size, m_caps.szPname, size-1); + + return unicode_product_name; + } +#else + inline const wchar_t* GetProductName() const + { + return m_caps.szPname; + } +#endif + + inline WORD GetMId() const + { + return m_caps.wMid; + } + + inline WORD GetPId() const + { + return m_caps.wPid; + } + + inline unsigned GetNumButtons() const + { + return m_caps.wNumButtons; + } + + inline unsigned GetNumAxes() const + { + return m_caps.wNumAxes; + } + + inline UnsignedPair GetPollingFreq() const + { + return std::make_pair(m_caps.wPeriodMin, m_caps.wPeriodMax); + } + + inline UnsignedPair GetRangeX() const + { + return std::make_pair(m_caps.wXmin, m_caps.wXmax); + } + + inline UnsignedPair GetRangeY() const + { + return std::make_pair(m_caps.wYmin, m_caps.wYmax); + } + + inline UnsignedPair GetRangeZ() const + { + return std::make_pair(m_caps.wZmin, m_caps.wZmax); + } + + inline UnsignedPair GetRangeR() const + { + return std::make_pair(m_caps.wRmin, m_caps.wRmax); + } + + inline UnsignedPair GetRangeU() const + { + return std::make_pair(m_caps.wUmin, m_caps.wUmax); + } + + inline UnsignedPair GetRangeV() const + { + return std::make_pair(m_caps.wVmin, m_caps.wVmax); + } + + inline bool HasAxisZ() const + { + return m_caps.wCaps & JOYCAPS_HASZ; + } + + inline bool HasAxisR() const + { + return (m_caps.wCaps & JOYCAPS_HASR) != 0; + } + + inline bool HasAxisU() const + { + return (m_caps.wCaps & JOYCAPS_HASU) != 0; + } + + inline bool HasAxisV() const + { + return (m_caps.wCaps & JOYCAPS_HASV) != 0; + } + inline EPovType GetPovType() const + { + if (0 == (m_caps.wCaps & JOYCAPS_HASPOV)) + return ePovType_no_pov; + + if (0 != (m_caps.wCaps & JOYCAPS_POVCTS)) + return ePovType_continuous; + else if (0 != (m_caps.wCaps & JOYCAPS_POV4DIR)) + return ePovType_discrete; + else + return ePovType_unknown; + } + + void SetInverted(EAxis axis, bool val = true) + { + m_invertedAxes.set(axis, val); + } + + bool IsInverted(EAxis axis) const + { + return m_invertedAxes.test(axis); + } + + bool WasPressed(EButton b) const + { + if (b > eButton32) + { + if (button_code[b] == m_data.dwPOV && + m_data.dwPOV != m_lastData.dwPOV) + { + return true; + } + + return false; + } + + return (m_lastData.dwButtons & button_code[b]) == 0 && + (m_data.dwButtons & button_code[b]) > 0; + } + + bool WasReleased(EButton b) const + { + assert(b <= eButton32); + return (m_lastData.dwButtons & button_code[b]) > 0 && + (m_data.dwButtons & button_code[b]) == 0; + } + + bool IsPressed(EButton b) const + { + assert(b <= eButton32); + return (m_data.dwButtons & button_code[b]) > 0; + } + + bool WasSectionEnteredXY(float min, float max) const + { + const int lastX = m_invertedAxes.test(eAxis_X) ? + eMax - m_lastData.dwXpos : m_lastData.dwXpos; + const int lastY = m_invertedAxes.test(eAxis_Y) ? + eMax - m_lastData.dwYpos : m_lastData.dwYpos; + + int curX = m_invertedAxes.test(eAxis_X) ? + eMax - m_data.dwXpos : m_data.dwXpos; + int curY = m_invertedAxes.test(eAxis_Y) ? + eMax - m_data.dwYpos : m_data.dwYpos; + + const float lastAlpha = GetAngle( + lastX - eMid, lastY - eMid, 1.02f, eMid); + + const float curAlpha = GetAngle( + curX - eMid, curY - eMid, 1.02f, eMid); + + bool changed(false); + + if (-1.0f == lastAlpha || -1.0f == curAlpha || + fabs(lastAlpha - curAlpha) > eTolerance) + { + changed = true; + } + + if (changed && IsInSection(curAlpha, min, max)) + { + return true; + } + + return false; + } + + bool WasSectionEnteredRZ(float min, float max) const + { + const int lastR = m_invertedAxes.test(eAxis_R) ? + eMax - m_lastData.dwRpos : m_lastData.dwRpos; + const int lastZ = m_invertedAxes.test(eAxis_Z) ? + eMax - m_lastData.dwZpos : m_lastData.dwZpos; + + int curR = m_invertedAxes.test(eAxis_R) ? + eMax - m_data.dwRpos : m_data.dwRpos; + int curZ = m_invertedAxes.test(eAxis_Z) ? + eMax - m_data.dwZpos : m_data.dwZpos; + + const float lastAlpha = GetAngle( + lastR - eMid, lastZ - eMid, 1.02f, eMid); + + const float curAlpha = GetAngle( + curR - eMid, curZ - eMid, 1.02f, eMid); + + bool changed(false); + + if (-1.0f == lastAlpha || -1.0f == curAlpha || + fabs(lastAlpha - curAlpha) > eTolerance) + { + changed = true; + } + + if (changed && IsInSection(curAlpha, min, max)) + { + return true; + } + + return false; + } + + bool WasSectionLeft(float /*min*/, float /*max*/) const + { + return false; + } + + bool IsInSection(const float alpha, const float min, const float max) const + { + bool ret(false); + + if (min > max) + { + if (min <= alpha && alpha <= 360.0f) + { + ret = true; + } + else if (0 < alpha && alpha <= max) + { + ret = true; + } + } + else + { + if (min <= alpha && max >= alpha) + { + ret = true; + } + } + + return ret; + } + + template + T GetAngle(int x, int y, float factor = 0.0f, int max = 0) const + { + if (0 == x && 0 == y) + { + return -1; + } + + T h = sqrt((T)x * x + (T)y * y); + + if (h * factor < (float)max) + { + return -1; + } + + T angle = asin((T)y / h) * 180 / (T)3.141592653589793L; + angle = x > 0 ? 90 - angle : 270 + angle; + + return angle; + } + + //FIXME: use double + float GetAngleXY() const + { + return GetAngle(GetXPos() - eMid, GetYPos() - eMid, 1.2f, eMid); + } + float GetAngleRZ() const + { + return GetAngle(GetRPos() - eMid, GetZPos() - eMid, 1.2f, eMid); + } + + int PressedCount() const + { + return m_data.dwButtonNumber; + } + + unsigned GetXPos() const + { + if (m_invertedAxes.test(eAxis_X)) + return 65535 - m_data.dwXpos; + + return m_data.dwXpos; + } + + unsigned GetYPos() const + { + if (m_invertedAxes.test(eAxis_Y)) + return 65535 - m_data.dwYpos; + + return m_data.dwYpos; + } + + unsigned GetZPos() const + { + if (m_invertedAxes.test(eAxis_Z)) + return 65535 - m_data.dwZpos; + + return m_data.dwZpos; + } + + unsigned GetRPos() const + { + if (m_invertedAxes.test(eAxis_R)) + return 65535 - m_data.dwRpos; + + return m_data.dwRpos; + } + unsigned GetUPos() const + { + if (m_invertedAxes.test(eAxis_U)) + return 65535 - m_data.dwUpos; + + return m_data.dwUpos; + } + + unsigned GetVPos() const + { + if (m_invertedAxes.test(eAxis_V)) + return 65535 - m_data.dwVpos; + + return m_data.dwVpos; + } + + unsigned GetPOV() const + { + return m_data.dwPOV; + } + + + EState ReadData() + { + m_lastData = m_data; + m_state = EState(::joyGetPosEx(m_currentId, &m_data)); + return m_state; + } + + EState GetState() const + { + return m_state; + } + + /// will return -1 if threshold can not be retrieved + unsigned GetThreshold() const + { + unsigned t(0); + + if (eState_ok != ::joyGetThreshold(m_currentId, &t)) + return static_cast(-1); + + return t; + } + + /// Sets the movement threshold for the current controller. + /// @return true if value has been successfully set + bool SetThreshold(unsigned threshold) const + { + return eState_ok == ::joySetThreshold(m_currentId, threshold); + } + + + bool Capture(HWND hwnd, unsigned int period = 125, EUpdateAction when = update_on_change) + { + bool ret(false); + + if (NULL == m_hwnd) + { + int s(::joySetCapture(hwnd, m_currentId, period, + when ? TRUE : FALSE)); + + if (eState_ok == s) + { + m_hwnd = hwnd; + ret = true; + } + } + + return ret; + } + + + bool Release() + { + bool ret(false); + + if (NULL != m_hwnd) + { + int s(::joyReleaseCapture(m_currentId)); + + if (eState_ok == s) + { + m_hwnd = NULL; + ret = true; + } + } + + return ret; + } + + +private: + void reset() + { + m_invertedAxes.reset(); + + memset(&m_caps, 0, sizeof(JOYCAPS)); + memset(&m_data, 0, sizeof(JOYINFOEX)); + m_data.dwSize = sizeof(JOYINFOEX); + m_data.dwFlags = JOY_RETURNALL; + m_lastData = m_data; + } + + const unsigned int button_code[40] = + { + JOY_BUTTON1, + JOY_BUTTON2, + JOY_BUTTON3, + JOY_BUTTON4, + JOY_BUTTON5, + JOY_BUTTON6, + JOY_BUTTON7, + JOY_BUTTON8, + JOY_BUTTON9, + JOY_BUTTON10, + JOY_BUTTON11, + JOY_BUTTON12, + JOY_BUTTON13, + JOY_BUTTON14, + JOY_BUTTON15, + JOY_BUTTON16, + JOY_BUTTON17, + JOY_BUTTON18, + JOY_BUTTON19, + JOY_BUTTON20, + JOY_BUTTON21, + JOY_BUTTON22, + JOY_BUTTON23, + JOY_BUTTON24, + JOY_BUTTON25, + JOY_BUTTON26, + JOY_BUTTON27, + JOY_BUTTON28, + JOY_BUTTON29, + JOY_BUTTON30, + JOY_BUTTON31, + JOY_BUTTON32, + 0, // eButton_pov_fwd + 9000, // eButton_pov_right + 18000, // eButton_pov_back + 27000, // eButton_pov_left + 4500, // ePov_right_fwd + 13500, // eButton_pov_right_back + 22500, // eButton_pov_left_back + 31500 // eButton_pov_left_fwd + }; + + unsigned int m_currentId; + std::bitset m_invertedAxes; +#if WINVER > 0x0501 + JOYCAPSA m_caps; +#else + JOYCAPSW m_caps; +#endif + + JOYINFOEX m_data; + JOYINFOEX m_lastData; + EState m_state; + HWND m_hwnd; +}; + +} //namespace FMlib + +#endif // FMLIB_GAMEPAD_H_