diff options
167 files changed, 5104 insertions, 726 deletions
@@ -7,3 +7,5 @@ /.vs/ /CMakeSettings.json .gtm/ +.vscode +.history diff --git a/CMakeLists.txt b/CMakeLists.txt index a7a95d2f..448d7667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,8 +93,15 @@ function(otr_add_subdirs) foreach(k ${_globbed}) get_filename_component(k "${k}" DIRECTORY) - add_subdirectory("${k}") + # we want to compile macosx last so we can run proper install scripts + if (k MATCHES "macosx$") + set(o ${k}) + else() + add_subdirectory("${k}") + endif() endforeach() + # Add macosx last + add_subdirectory("${o}") endfunction() otr_add_subdirs() @@ -77,6 +77,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems! assistance, testing) - Wim Vriend (original codebase author and maintainer) - Ryan Spicer (OSX tester, contributor) +- Ries van Twisk (OSX tester, OSX Build Fixes, contributor) - Donovan Baarda (filtering/control theory expert) - Mathijs Groothuis (@MathijsG, dozens of bugs and other issues reported; NL translation) - The Russian community from the [IL-2 Sturmovik forums](https://forum.il2sturmovik.ru/) (reporting bugs, requesting important features) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2da7f2fd..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- unstable - -pool: - vmImage: 'vs2017-win2016' - -steps: -- script: echo Hello, world! - displayName: 'Run a one-line script' - -- script: | - echo Add other tasks to build, test, and deploy your project. - echo See https://aka.ms/yaml - set - displayName: 'Run a multi-line script' - -- task: CMake@1 - inputs: - cmakeArgs:
\ No newline at end of file diff --git a/cmake/FindEigen3.cmake b/cmake/FindEigen3.cmake index b43208f9..bbad2298 100644 --- a/cmake/FindEigen3.cmake +++ b/cmake/FindEigen3.cmake @@ -9,6 +9,12 @@ # EIGEN3_FOUND - system has eigen lib with correct version # EIGEN3_INCLUDE_DIR - the eigen include directory # EIGEN3_VERSION - eigen version +# +# This module reads hints about search locations from +# the following enviroment variables: +# +# EIGEN3_ROOT +# EIGEN3_ROOT_DIR # Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org> # Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr> @@ -61,19 +67,29 @@ if (EIGEN3_INCLUDE_DIR) else (EIGEN3_INCLUDE_DIR) - find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library + # search first if an Eigen3Config.cmake is available in the system, + # if successful this would set EIGEN3_INCLUDE_DIR and the rest of + # the script will work as usual + find_package(Eigen3 ${Eigen3_FIND_VERSION} NO_MODULE QUIET) + + if(NOT EIGEN3_INCLUDE_DIR) + find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library + HINTS + ENV EIGEN3_ROOT + ENV EIGEN3_ROOT_DIR PATHS ${CMAKE_INSTALL_PREFIX}/include ${KDE4_INCLUDE_DIR} PATH_SUFFIXES eigen3 eigen ) - + endif(NOT EIGEN3_INCLUDE_DIR) + if(EIGEN3_INCLUDE_DIR) _eigen3_check_version() endif(EIGEN3_INCLUDE_DIR) - #include(FindPackageHandleStandardArgs) - #find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) mark_as_advanced(EIGEN3_INCLUDE_DIR) diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index b7a403a3..f108eb16 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -39,7 +39,7 @@ add_link_options(-cgthreads:1) set(_CFLAGS "") set(_CXXFLAGS "") -set(_CFLAGS_RELEASE "-O2 -O2it -Oy- -Ob3 -fp:fast -GS- -GF -GL -Gw -Gy -arch:SSE2 -GR- -MT") +set(_CFLAGS_RELEASE "-O2 -O2it -Oy- -Ob3 -fp:fast -GS- -GF -GL -Gw -Gy -arch:SSE2 -MT") set(_CFLAGS_DEBUG "-guard:cf -MTd -Gs0 -RTCs") set(_CXXFLAGS_RELEASE "${_CFLAGS_RELEASE}") set(_CXXFLAGS_DEBUG "${_CFLAGS_DEBUG}") diff --git a/cmake/opentrack-boilerplate.cmake b/cmake/opentrack-boilerplate.cmake index ffa4ea02..a78e0ed0 100644 --- a/cmake/opentrack-boilerplate.cmake +++ b/cmake/opentrack-boilerplate.cmake @@ -18,10 +18,10 @@ set(new-hier-path "#pragma once #endif #define OPENTRACK_LIBRARY_PREFIX \"\" -#define OPENTRACK_LIBRARY_PATH \"${opentrack-hier-path}\" -#define OPENTRACK_DOC_PATH \"${opentrack-hier-doc}\" -#define OPENTRACK_CONTRIB_PATH \"${opentrack-hier-doc}contrib/\" -#define OPENTRACK_I18N_PATH \"${opentrack-i18n-path}\" +#define OPENTRACK_LIBRARY_PATH \"${opentrack-runtime-libexec}\" +#define OPENTRACK_DOC_PATH \"${opentrack-runtime-doc}\" +#define OPENTRACK_CONTRIB_PATH \"${opentrack-runtime-doc}contrib/\" +#define OPENTRACK_I18N_PATH \"${opentrack-runtime-i18n}\" ") function(otr_write_library_paths) @@ -61,8 +61,8 @@ function(otr_glob_sources var) endfunction() function(otr_fixup_subsystem n) - otr_find_msvc_editbin(editbin-pathname) if(MSVC) + otr_find_msvc_editbin(editbin-pathname) set(subsystem WINDOWS) get_property(type TARGET "${n}" PROPERTY TYPE) if (NOT type STREQUAL "STATIC_LIBRARY") @@ -109,7 +109,7 @@ endfunction() function(otr_install_pdb_current_project target) if(MSVC) - install(FILES "$<TARGET_PDB_FILE:${target}>" DESTINATION "${opentrack-hier-debug}" PERMISSIONS ${opentrack-perms-file}) + install(FILES "$<TARGET_PDB_FILE:${target}>" DESTINATION "${opentrack-debug}" PERMISSIONS ${opentrack-perms-file}) endif() endfunction() @@ -143,15 +143,17 @@ function(otr_module n_) set(arg_NO-I18N TRUE) endif() - if(NOT WIN32) - set(subsys "") - elseif(arg_WIN32-CONSOLE) - set(subsys "") - else() - set(subsys "WIN32") - endif() - if(arg_EXECUTABLE) + if (APPLE) + set(subsys "MACOSX_BUNDLE") + elseif(NOT WIN32) + set(subsys "") + elseif(arg_WIN32-CONSOLE) + set(subsys "") + else() + set(subsys "WIN32") + endif() + add_executable(${n} ${subsys} "${${n}-all}") set_target_properties(${n} PROPERTIES SUFFIX "${opentrack-binary-suffix}" @@ -216,13 +218,24 @@ function(otr_module n_) endif() if(NOT arg_NO-INSTALL) + # Librarys/executable if(arg_BIN) - install(TARGETS "${n}" - RUNTIME DESTINATION ${opentrack-hier-bin} - LIBRARY DESTINATION ${opentrack-hier-pfx} + if (APPLE) + install(TARGETS "${n}" + RUNTIME DESTINATION ${opentrack-bin} + BUNDLE DESTINATION ${opentrack-bin} + LIBRARY DESTINATION ${opentrack-bin}/Library + RESOURCE DESTINATION ${opentrack-bin}/opentrack.app/Resource + PERMISSIONS ${opentrack-perms-exec}) + else() + install(TARGETS "${n}" + RUNTIME DESTINATION ${opentrack-bin} + LIBRARY DESTINATION ${opentrack-libexec} PERMISSIONS ${opentrack-perms-exec}) + endif() else() - install(TARGETS "${n}" ${opentrack-hier-str} + # Plugins + install(TARGETS "${n}" ${opentrack-install-src} PERMISSIONS ${opentrack-perms-exec}) endif() @@ -282,7 +295,7 @@ function(otr_install_lib target dest) set(pdb-path "") otr_pdb_for_dll(pdb-path "${path}") if(pdb-path) - install(FILES "${pdb-path}" DESTINATION "${opentrack-hier-debug}" PERMISSIONS ${opentrack-perms-exec}) + install(FILES "${pdb-path}" DESTINATION "${opentrack-debug}" PERMISSIONS ${opentrack-perms-exec}) endif() endif() install(FILES "${path}" DESTINATION "${dest}" PERMISSIONS ${opentrack-perms-exec}) diff --git a/cmake/opentrack-hier.cmake b/cmake/opentrack-hier.cmake index 7dcdb52d..16694d1f 100644 --- a/cmake/opentrack-hier.cmake +++ b/cmake/opentrack-hier.cmake @@ -9,50 +9,49 @@ include_guard(GLOBAL) -set(opentrack-install-rpath "") if(APPLE) - set(opentrack-hier-pfx ".") - set(opentrack-hier-path "/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-doc "/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-bin ".") - set(opentrack-doc-pfx "./doc") - set(opentrack-doc-src-pfx "./source-code") - set(opentrack-i18n-pfx "./i18n") - set(opentrack-i18n-path "./i18n") + set(opentrack-libexec "Plugins") + set(opentrack-runtime-libexec "/Plugins/") # MUST HAVE A TRAILING BACKSLASH, Used in APP + set(opentrack-runtime-doc "/") # MUST HAVE A TRAILING BACKSLASH + set(opentrack-bin "${CMAKE_INSTALL_PREFIX}") + set(opentrack-doc "./doc") + set(opentrack-src "./source-code") + set(opentrack-i18n "opentrack.app/Contents/Resources") # used during install + set(opentrack-runtime-i18n "../Resources/i18n") # used in application + set(opentrack-install-rpath "${CMAKE_INSTALL_PREFIX}/Library") elseif(WIN32) - set(opentrack-hier-pfx "modules") - set(opentrack-hier-path "/${opentrack-hier-pfx}/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-doc "/doc/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-bin ".") - set(opentrack-doc-pfx "./doc") - set(opentrack-doc-src-pfx "./source-code") - set(opentrack-i18n-pfx "./i18n") - set(opentrack-i18n-path "./i18n") - set(opentrack-hier-debug "./debug") + set(opentrack-libexec "modules") + set(opentrack-runtime-libexec "/${opentrack-libexec}/") # MUST HAVE A TRAILING BACKSLASH + set(opentrack-runtime-doc "/doc/") # MUST HAVE A TRAILING BACKSLASH + set(opentrack-bin ".") + set(opentrack-doc "./doc") + set(opentrack-src "./source-code") + set(opentrack-i18n "./i18n") + set(opentrack-runtime-i18n "./i18n") + set(opentrack-debug "./debug") + set(opentrack-install-rpath "") else() - set(opentrack-hier-pfx "libexec/opentrack") - set(opentrack-hier-path "/../${opentrack-hier-pfx}/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-doc "/share/doc/opentrack/") # MUST HAVE A TRAILING BACKSLASH - set(opentrack-hier-bin "bin") - set(opentrack-doc-pfx "./share/doc/opentrack") - set(opentrack-doc-src-pfx "./share/doc/opentrack/source-code") - set(opentrack-install-rpath "${CMAKE_INSTALL_PREFIX}/${opentrack-hier-pfx}") - set(opentrack-i18n-pfx "./share/opentrack/i18n") - set(opentrack-i18n-path "../share/opentrack/i18n") + set(opentrack-libexec "libexec/opentrack") + set(opentrack-runtime-libexec "/../${opentrack-libexec}/") # MUST HAVE A TRAILING BACKSLASH + set(opentrack-runtime-doc "/share/doc/opentrack/") # MUST HAVE A TRAILING BACKSLASH + set(opentrack-bin "bin") + set(opentrack-doc "./share/doc/opentrack") + set(opentrack-src "./share/doc/opentrack/source-code") + set(opentrack-install-rpath "${CMAKE_INSTALL_PREFIX}/${opentrack-libexec}") + set(opentrack-i18n "./share/opentrack/i18n") + set(opentrack-runtime-i18n "../share/opentrack/i18n") endif() -set(opentrack-hier-str RUNTIME DESTINATION ${opentrack-hier-pfx} LIBRARY DESTINATION ${opentrack-hier-pfx}) +set(opentrack-install-src RUNTIME DESTINATION ${opentrack-libexec} LIBRARY DESTINATION ${opentrack-libexec}) function(otr_escape_string var str) string(REGEX REPLACE "([^_A-Za-z0-9./:-])" "\\\\\\1" str "${str}") set(${var} "${str}" PARENT_SCOPE) endfunction() -set(opentrack-contrib-pfx "${opentrack-doc-pfx}/contrib") +set(opentrack-contrib-pfx "${opentrack-doc}/contrib") set(opentrack-binary-suffix "") -if(APPLE) - set(opentrack-binary-suffix ".bin") -elseif(WIN32) +if(WIN32) set(opentrack-binary-suffix ".exe") endif() diff --git a/cmake/opentrack-i18n.cmake b/cmake/opentrack-i18n.cmake index e89f5c42..f3b53895 100644 --- a/cmake/opentrack-i18n.cmake +++ b/cmake/opentrack-i18n.cmake @@ -58,7 +58,7 @@ function(otr_i18n_for_target_directory n) endfunction() function(otr_merge_translations) - otr_escape_string(i18n-pfx "${opentrack-i18n-pfx}") + otr_escape_string(i18n-pfx "${opentrack-i18n}") install(CODE "file(REMOVE_RECURSE \"\${CMAKE_INSTALL_PREFIX}/${i18n-pfx}\")") foreach(i ${opentrack_all-translations}) @@ -68,7 +68,7 @@ function(otr_merge_translations) set(qm-output "${CMAKE_BINARY_DIR}/${i}.qm") # whines about duplicate messages since tracker-pt-base is static - if(WIN32) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") set(to-null "2>NUL") else() set(to-null "2>/dev/null") @@ -92,7 +92,7 @@ function(otr_merge_translations) add_dependencies(i18n-lrelease ${target-name}) install(FILES "${qm-output}" - DESTINATION "${CMAKE_INSTALL_PREFIX}/${opentrack-i18n-pfx}" + DESTINATION "${CMAKE_INSTALL_PREFIX}/${opentrack-i18n}" PERMISSIONS ${opentrack-perms-file}) endforeach() endfunction() diff --git a/cmake/opentrack-install.cmake b/cmake/opentrack-install.cmake index 2b745a82..94f3e29d 100644 --- a/cmake/opentrack-install.cmake +++ b/cmake/opentrack-install.cmake @@ -17,8 +17,8 @@ macro(otr_install_dir path) endmacro() function(otr_setup_refresh_install_dir) - if((NOT CMAKE_INSTALL_PREFIX STREQUAL "") AND (NOT opentrack-doc-src-pfx STREQUAL "")) - otr_escape_string(dir "${CMAKE_INSTALL_PREFIX}/${opentrack-doc-src-pfx}/") + if((NOT CMAKE_INSTALL_PREFIX STREQUAL "") AND (NOT opentrack-src STREQUAL "")) + otr_escape_string(dir "${CMAKE_INSTALL_PREFIX}/${opentrack-src}/") install(CODE "file(REMOVE_RECURSE \"${dir}\")") endif() endfunction() @@ -28,18 +28,18 @@ function(otr_install_sources) get_property(source-dirs GLOBAL PROPERTY opentrack-all-source-dirs) foreach(k ${source-dirs}) file(RELATIVE_PATH dest "${CMAKE_SOURCE_DIR}" "${k}") - otr_install_dir("${opentrack-doc-src-pfx}" "${dest}") + otr_install_dir("${opentrack-src}" "${dest}") endforeach() - otr_install_dir("${opentrack-doc-src-pfx}" "${CMAKE_SOURCE_DIR}/cmake") - otr_install_dir("${opentrack-doc-src-pfx}" "${CMAKE_SOURCE_DIR}/bin") + otr_install_dir("${opentrack-src}" "${CMAKE_SOURCE_DIR}/cmake") + otr_install_dir("${opentrack-src}" "${CMAKE_SOURCE_DIR}/bin") - otr_install_misc("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt") - otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/README.md") - otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/.github/CONTRIBUTING.md") - otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/WARRANTY.txt") - otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/OPENTRACK-LICENSING.txt") - otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/AUTHORS.md") + otr_install_misc("${opentrack-src}" FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt") + otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/README.md") + otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/.github/CONTRIBUTING.md") + otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/WARRANTY.txt") + otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/OPENTRACK-LICENSING.txt") + otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/AUTHORS.md") endfunction() function(cleanup_visual_studio_debug) @@ -47,22 +47,22 @@ function(cleanup_visual_studio_debug) install(CODE "file(REMOVE_RECURSE \"${pfx}/.vs\")") endfunction() -otr_install_dir("${opentrack-doc-pfx}" ${CMAKE_SOURCE_DIR}/3rdparty-notices) -otr_install_dir("${opentrack-doc-pfx}" "${CMAKE_SOURCE_DIR}/settings" "${CMAKE_SOURCE_DIR}/contrib") +otr_install_dir("${opentrack-doc}" ${CMAKE_SOURCE_DIR}/3rdparty-notices) +otr_install_dir("${opentrack-doc}" "${CMAKE_SOURCE_DIR}/settings" "${CMAKE_SOURCE_DIR}/contrib") if(WIN32) otr_install_misc(. FILES "${CMAKE_SOURCE_DIR}/bin/qt.conf") otr_install_misc(. FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config") - otr_install_misc(${opentrack-hier-pfx} FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config") + otr_install_misc(${opentrack-libexec} FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config") endif() -otr_install_misc("${opentrack-doc-pfx}" FILES ${CMAKE_SOURCE_DIR}/README.md) +otr_install_misc("${opentrack-doc}" FILES ${CMAKE_SOURCE_DIR}/README.md) -otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/README.md") -otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/.github/CONTRIBUTING.md") -otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/WARRANTY.txt") -otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/OPENTRACK-LICENSING.txt") -otr_install_misc("${opentrack-doc-pfx}" FILES "${CMAKE_SOURCE_DIR}/AUTHORS.md") +otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/README.md") +otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/.github/CONTRIBUTING.md") +otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/WARRANTY.txt") +otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/OPENTRACK-LICENSING.txt") +otr_install_misc("${opentrack-doc}" FILES "${CMAKE_SOURCE_DIR}/AUTHORS.md") # this must be done last because the files may be in use already # do it last so in case of file-in-use failure, the rest is installed @@ -71,9 +71,13 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") cleanup_visual_studio_debug() endif() -otr_install_exec("${opentrack-hier-pfx}" FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll") -otr_install_exec("${opentrack-hier-pfx}" FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient64.dll") -otr_install_exec("${opentrack-hier-pfx}" FILES +# For now copy third party needed files into a seperate direcvtory instead of the plugins directory +if (APPLE) + set(OSX_POST_INSTALL_DIR "/../thirdparty") +endif() +otr_install_exec("${opentrack-libexec}${OSX_POST_INSTALL_DIR}" FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll") +otr_install_exec("${opentrack-libexec}${OSX_POST_INSTALL_DIR}" FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient64.dll") +otr_install_exec("${opentrack-libexec}${OSX_POST_INSTALL_DIR}" FILES "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe") diff --git a/cmake/opentrack-opencv.cmake b/cmake/opentrack-opencv.cmake index b8c3701c..40356418 100644 --- a/cmake/opentrack-opencv.cmake +++ b/cmake/opentrack-opencv.cmake @@ -5,7 +5,7 @@ find_package(OpenCV QUIET) function(otr_install_opencv_libs) foreach(k core features2d calib3d flann imgcodecs imgproc videoio) - otr_install_lib("opencv_${k}" "${opentrack-hier-pfx}") + otr_install_lib("opencv_${k}" "${opentrack-libexec}") endforeach() endfunction() diff --git a/cmake/opentrack-platform.cmake b/cmake/opentrack-platform.cmake index 02c1b2f8..23f684f3 100644 --- a/cmake/opentrack-platform.cmake +++ b/cmake/opentrack-platform.cmake @@ -54,7 +54,6 @@ set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_MACOSX_RPATH OFF) if(NOT WIN32 AND NOT APPLE) include(opentrack-pkg-config) @@ -119,8 +118,8 @@ if(MSVC) add_definitions(-D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1) add_definitions(-D_SCL_SECURE_NO_WARNINGS) - add_compile_options(-EHs-c-) - add_definitions(-D_HAS_EXCEPTIONS=0) + add_compile_options(-EHsc) + #add_definitions(-D_HAS_EXCEPTIONS=0) add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE) add_definitions(-D_ENABLE_ATOMIC_ALIGNMENT_FIX) @@ -155,14 +154,6 @@ if(MSVC) endforeach() endif() -if(APPLE) - add_compile_definitions(-stdlib=libc++) - add_link_options(-stdlib=libc++) - - add_link_options(-framework Cocoa -framework CoreFoundation -framework Carbon) - link_libraries(objc z) -endif() - if(NOT MSVC) include(FindPkgConfig) endif() diff --git a/cmake/opentrack-qt.cmake b/cmake/opentrack-qt.cmake index 8c92483c..41bd6291 100644 --- a/cmake/opentrack-qt.cmake +++ b/cmake/opentrack-qt.cmake @@ -2,19 +2,33 @@ include_guard(GLOBAL) if(WIN32) find_package(Qt5Gui REQUIRED COMPONENTS QWindowsIntegrationPlugin) endif() -find_package(Qt5 REQUIRED COMPONENTS Core Network Widgets LinguistTools Gui QUIET) -find_package(Qt5 COMPONENTS SerialPort QUIET) +set(qt-required-components Core Network Widgets LinguistTools Gui) +set(qt-optional-components SerialPort) +set(qt-imported-targets Qt5::Core Qt5::Gui Qt5::Network Qt5::SerialPort Qt5::Widgets) +if(APPLE) + list(APPEND qt-required-components "DBus") + list(APPEND qt-optional-components "Multimedia") + list(APPEND qt-imported-targets Qt5::DBus Qt5::Multimedia) +endif() + +find_package(Qt5 REQUIRED COMPONENTS ${qt-required-components} QUIET) +find_package(Qt5 COMPONENTS ${qt-optional-components} QUIET) set(MY_QT_LIBS ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES}) +if(APPLE) + list(APPEND MY_QT_LIBS ${Qt5Multimedia_LIBRARIES} ${Qt5DBus_LIBRARIES}) +endif() function(otr_install_qt_libs) - foreach(i Qt5::Core Qt5::Gui Qt5::Network Qt5::SerialPort Qt5::Widgets) + foreach(i ${qt-imported-targets}) if(NOT TARGET "${i}") continue() endif() otr_install_lib(${i} ".") endforeach() + if(WIN32) otr_install_lib(Qt5::QWindowsIntegrationPlugin "./platforms") + endif() endfunction() otr_install_qt_libs() diff --git a/cmake/opentrack-rift.cmake b/cmake/opentrack-rift.cmake deleted file mode 100644 index cdcfc946..00000000 --- a/cmake/opentrack-rift.cmake +++ /dev/null @@ -1,38 +0,0 @@ -include_guard(GLOBAL) -function(otr_rift proj opt) - if(${opt}) - set(link-flags) - set(c-flags) - if(APPLE) - set(link-flags "-framework CoreFoundation -framework CoreGraphics -framework IOKit -framework Quartz") - set(c-flags "-fno-strict-aliasing") - elseif(NOT MSVC) - set(c-flags "-fno-strict-aliasing") - endif() - otr_module(${proj} LINK ${link-flags} COMPILE ${c-flags}) - set(proj "opentrack-${proj}") - target_include_directories(${proj} SYSTEM PUBLIC ${${opt}}/Include ${${opt}}/Src) - set(c-flags) - set(link-flags) - if(MSVC) - set(ext lib) - set(p) - else() - set(ext a) - set(p lib) - endif() - if(MSVC) - set(pfx "") - else() - set(pfx "lib") - endif() - target_link_libraries(${proj} ${${opt}}/${pfx}LibOVR.${ext}) - if(WIN32) - target_link_libraries(${proj} winmm setupapi ws2_32 imagehlp wbemuuid) - set(ext) - set(p) - elseif(NOT APPLE) - target_link_libraries(${proj} udev Xinerama) - endif() - endif() -endfunction() diff --git a/compat/camera-names.cpp b/compat/camera-names.cpp index 69926e5a..5d190943 100644 --- a/compat/camera-names.cpp +++ b/compat/camera-names.cpp @@ -7,11 +7,15 @@ # include <cwchar> # define NO_DSHOW_STRSAFE # include <dshow.h> -#elif defined(__unix) || defined(__linux) || defined(__APPLE__) +#elif defined(__unix) || defined(__linux__) || defined(__APPLE__) # include <unistd.h> #endif -#ifdef __linux +#ifdef __APPLE__ +# include <QCameraInfo> +#endif + +#ifdef __linux__ # include <fcntl.h> # include <sys/ioctl.h> # include <linux/videodev2.h> @@ -24,16 +28,22 @@ int camera_name_to_index(const QString &name) { auto list = get_camera_names(); - auto it = std::find(list.cbegin(), list.cend(), name); + auto it = std::find_if(list.cbegin(), list.cend(), [&name](const auto& tuple) { + const auto& [str, idx] = tuple; + return str == name; + }); if (it != list.cend()) - return std::distance(list.cbegin(), it); + { + const auto& [ str, idx ] = *it; + return idx; + } return -1; } -std::vector<QString> get_camera_names() +std::vector<std::tuple<QString, int>> get_camera_names() { - std::vector<QString> ret; + std::vector<std::tuple<QString, int>> ret; #ifdef _WIN32 // Create the System Device Enumerator. HRESULT hr; @@ -66,7 +76,7 @@ std::vector<QString> get_camera_names() { // Display the name in your UI somehow. QString str((QChar*)var.bstrVal, int(std::wcslen(var.bstrVal))); - ret.push_back(str); + ret.push_back({ str, ret.size() }); } VariantClear(&var); pPropBag->Release(); @@ -81,7 +91,7 @@ std::vector<QString> get_camera_names() pSysDevEnum->Release(); #endif -#ifdef __linux +#ifdef __linux__ for (int i = 0; i < 16; i++) { char buf[32]; snprintf(buf, sizeof(buf), "/dev/video%d", i); @@ -97,10 +107,16 @@ std::vector<QString> get_camera_names() close(fd); continue; } - ret.push_back(QString((const char*)video_cap.card)); + ret.push_back({ QString((const char*)video_cap.card), i}); close(fd); } } #endif +#ifdef __APPLE__ + QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); + for (const QCameraInfo &cameraInfo : cameras) + ret.push_back({ cameraInfo.description(), ret.size() }); +#endif + return ret; } diff --git a/compat/camera-names.hpp b/compat/camera-names.hpp index bda15e81..3585edfe 100644 --- a/compat/camera-names.hpp +++ b/compat/camera-names.hpp @@ -10,9 +10,10 @@ #include <vector> #include <QString> +# include <tuple> #include "export.hpp" -OTR_COMPAT_EXPORT std::vector<QString> get_camera_names(); +OTR_COMPAT_EXPORT std::vector<std::tuple<QString, int>> get_camera_names(); OTR_COMPAT_EXPORT int camera_name_to_index(const QString &name); diff --git a/compat/check-visible.cpp b/compat/check-visible.cpp index f786ca14..4da649c7 100644 --- a/compat/check-visible.cpp +++ b/compat/check-visible.cpp @@ -29,6 +29,15 @@ void set_is_visible(const QWidget& w, bool force) return; } + { + int ndisplays = GetSystemMetrics(SM_CMONITORS); + if (ndisplays > 1) + { + visible = true; + return; + } + } + HWND hwnd = (HWND)w.winId(); if (!force && timer.elapsed_ms() < (visible ? visible_timeout : invisible_timeout)) diff --git a/compat/linkage-macros.hpp b/compat/linkage-macros.hpp index 64c64bdb..f4d0104b 100644 --- a/compat/linkage-macros.hpp +++ b/compat/linkage-macros.hpp @@ -1,14 +1,16 @@ #pragma once -#if defined _MSC_VER -# define OTR_GENERIC_EXPORT __declspec(dllexport) -# define OTR_GENERIC_IMPORT __declspec(dllimport) -#elif defined _WIN32 && !defined __WINE__ -# define OTR_GENERIC_EXPORT __attribute__((dllexport, visibility ("default"))) -# define OTR_GENERIC_IMPORT __attribute__((dllimport)) -#else -# define OTR_GENERIC_EXPORT __attribute__((visibility ("default"))) -# define OTR_GENERIC_IMPORT +#ifndef OTR_GENERIC_EXPORT +# if defined _MSC_VER +# define OTR_GENERIC_EXPORT __declspec(dllexport) +# define OTR_GENERIC_IMPORT __declspec(dllimport) +# elif defined _WIN32 && !defined __WINE__ +# define OTR_GENERIC_EXPORT __attribute__((dllexport, visibility ("default"))) +# define OTR_GENERIC_IMPORT __attribute__((dllimport)) +# else +# define OTR_GENERIC_EXPORT __attribute__((visibility ("default"))) +# define OTR_GENERIC_IMPORT +# endif #endif #if defined __APPLE__ || defined __MINGW32__ diff --git a/compat/process-list.hpp b/compat/process-list.hpp index d1f9999f..782dc0a4 100644 --- a/compat/process-list.hpp +++ b/compat/process-list.hpp @@ -129,7 +129,7 @@ static QStringList get_all_executable_names() } } -#elif defined __linux +#elif defined __linux__ #include <proc/readproc.h> #include <cerrno> diff --git a/compat/qhash.hpp b/compat/qhash.hpp new file mode 100644 index 00000000..5286e97e --- /dev/null +++ b/compat/qhash.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include <functional> + +#include <QtGlobal> +#include <QString> +#include <QHashFunctions> + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + +#include <cstdlib> + +namespace std { +template<> struct hash<QString> +{ + using argument_type = QString; + using result_type = std::size_t; + + std::size_t operator()(const QString& value) const noexcept + { + return (std::size_t) qHash(value); + } +}; +} + +#endif diff --git a/compat/thread-name.cpp b/compat/thread-name.cpp index 504c6f19..08a7d628 100644 --- a/compat/thread-name.cpp +++ b/compat/thread-name.cpp @@ -20,12 +20,9 @@ struct THREADNAME_INFO }; static inline -void set_curthread_name_old(const QString& name_) +void set_curthread_name_old_(const char* name) { - QByteArray str = name_.toLocal8Bit(); - const char* name = str.constData(); HANDLE curthread = GetCurrentThread(); - THREADNAME_INFO info; // NOLINT(cppcoreguidelines-pro-type-member-init) info.dwType = 0x1000; info.szName = name; @@ -41,6 +38,15 @@ void set_curthread_name_old(const QString& name_) { } } + +static inline +void set_curthread_name_old(const QString& name_) +{ + QByteArray str = name_.toLocal8Bit(); + const char* name = str.constData(); + + set_curthread_name_old_(name); +} #else static inline void set_curthread_name_old(const QString&) {} diff --git a/dinput/win32-joystick.hpp b/dinput/win32-joystick.hpp index 82590db6..ff52ad1d 100644 --- a/dinput/win32-joystick.hpp +++ b/dinput/win32-joystick.hpp @@ -17,6 +17,7 @@ #include <unordered_map> #include <iterator> +#include "compat/qhash.hpp" #include <QString> #include <QMutex> diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp index 44a341e0..b70f08cf 100644 --- a/filter-accela/ftnoir_filter_accela.cpp +++ b/filter-accela/ftnoir_filter_accela.cpp @@ -64,6 +64,9 @@ static void do_deltas(const double* deltas, double* output, F&& fun) void accela::filter(const double* input, double *output) { + static constexpr double full_turn = 360.0; + static constexpr double half_turn = 180.0; + if (unlikely(first_run)) { first_run = false; @@ -98,6 +101,7 @@ void accela::filter(const double* input, double *output) for (unsigned i = 3; i < 6; i++) { double d = input[i] - last_output[i]; + if (fabs(d) > half_turn) d -= copysign(full_turn, d); if (fabs(d) > rot_dz) d -= copysign(rot_dz, d); @@ -134,6 +138,7 @@ void accela::filter(const double* input, double *output) { output[k] *= dt; output[k] += last_output[k]; + if (fabs(output[k]) > half_turn) output[k] -= copysign(full_turn, output[k]); last_output[k] = output[k]; } diff --git a/filter-ewma2/ftnoir_filter_ewma2.cpp b/filter-ewma2/ftnoir_filter_ewma2.cpp index ce6cd040..25902280 100644 --- a/filter-ewma2/ftnoir_filter_ewma2.cpp +++ b/filter-ewma2/ftnoir_filter_ewma2.cpp @@ -26,6 +26,8 @@ ewma::ewma() = default; void ewma::filter(const double *input, double *output) { + static constexpr double full_turn = 360; + static constexpr double half_turn = 180; // Start the timer and initialise filter state if it's not running. if (first_run) { @@ -57,7 +59,13 @@ void ewma::filter(const double *input, double *output) using std::pow; // Calculate the current and smoothed delta. - double delta = input[i] - last_output[i]; + double input_value = input[i]; + double delta = input_value - last_output[i]; + if (fabs(delta) > half_turn) + { + delta -= copysign(full_turn, delta); + input_value -= copysign(full_turn, input_value); + } last_delta[i] = delta_alpha*delta + (1.0-delta_alpha)*last_delta[i]; // Calculate the current and smoothed noise variance. double noise = last_delta[i]*last_delta[i]; @@ -70,7 +78,9 @@ void ewma::filter(const double *input, double *output) // Calculate the dynamic alpha. double alpha = dt/(dt + RC); // Calculate the new output position. - output[i] = last_output[i] = alpha*input[i] + (1.0-alpha)*last_output[i]; + output[i] = alpha*input_value + (1.0-alpha)*last_output[i]; + if (fabs(output[i]) > half_turn) output[i] -= copysign(full_turn, output[i]); + last_output[i] = output[i]; } } diff --git a/filter-hamilton/CMakeLists.txt b/filter-hamilton/CMakeLists.txt new file mode 100644 index 00000000..8d4d71b0 --- /dev/null +++ b/filter-hamilton/CMakeLists.txt @@ -0,0 +1 @@ +otr_module(filter-hamilton) diff --git a/filter-hamilton/ReadMe.txt b/filter-hamilton/ReadMe.txt new file mode 100644 index 00000000..bdd476da --- /dev/null +++ b/filter-hamilton/ReadMe.txt @@ -0,0 +1,13 @@ +Add a new Hamilton filter. + +Hamilton Filter Key Features: +- Instead of square, round (spherical) floating dead zones and smoothing areas are applied. Due to this, the angular size of these zones does not change when the Pitch angle changes. Diagonally rotations is as easy as moving along the Yaw and Pitch axes. +- Rotations are not filtered by independent coordinates, but comprehensively, in 3D space. Rotations and movements are more natural. There are no view jumps at the borders of +/- 180 degrees. +- The possibility of increasing the smoothing of rotations when zooming (when the head is approaching the monitor, that is, when increasing the -Z coordinate) is introduced. This makes it possible to more accurately aim and monitor remote targets. + +A full description of the Hamilton filter is available in Russian here: +https://sites.google.com/site/diyheadtracking/home/opentrack/opentrack-hamilton-filter + +The Hamilton filter was tested by the Russian community, received positive reviews: +https://forum.il2sturmovik.ru/topic/5061-opentrack-------/page/24/ +https://forums.eagle.ru/showthread.php?t=23280&page=249 diff --git a/filter-hamilton/ftnoir_filter_hamilton.cpp b/filter-hamilton/ftnoir_filter_hamilton.cpp new file mode 100644 index 00000000..be3faa7f --- /dev/null +++ b/filter-hamilton/ftnoir_filter_hamilton.cpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2020, GO63-samara <go1@list.ru> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "ftnoir_filter_hamilton.h" +#include <cmath> +#include <QMutexLocker> +#include "api/plugin-api.hpp" +#include "hamilton-tools.h" + +hamilton::hamilton() = default; + +void hamilton::filter(const double *input, double *output) +{ + tQuat quat_input = QuatFromYPR( &input[Yaw] ); + + if (first_run) + { + first_run = false; + quat_last = quat_input; + pos_last = {input[TX], input[TY], input[TZ]}; + for (int i=0; i<6; i++) output[i] = input[i]; + return; + } + + // positions: + const double pos_max {s.kMaxDist}; + const double pos_deadzone{s.kDeadZoneDist}; + const double pos_pow {s.kPowDist}; + + double dist = VectorDistance( &input[TX], pos_last); + + double alpha = (dist - pos_deadzone) / (pos_max + pos_deadzone + EPSILON); + alpha = fmin(alpha, 1.0); + alpha = fmax(alpha, 0.0); + alpha = pow (alpha, pos_pow); + alpha = alpha * (dist - pos_deadzone) / (dist + EPSILON); + + pos_last = Lerp(pos_last, input, alpha); + + output[TX] = pos_last.v[0]; + output[TY] = pos_last.v[1]; + output[TZ] = pos_last.v[2]; + + // zoom smoothing: + const double pow_zoom {s.kPowZoom}; + const double max_z {s.kMaxZ}; + double rot_zoom = pow_zoom; + + if (output[TZ] > 0) rot_zoom = 0; + else rot_zoom *= -output[TZ] / (max_z + EPSILON); + rot_zoom = fmin( rot_zoom, pow_zoom ); + + // rotations: + const double rot_max {s.kMaxRot}; + const double rot_pow {s.kPowRot}; + const double rot_deadzone{s.kDeadZoneRot}; + + double angle = AngleBetween(quat_input, quat_last); + + alpha = (angle - rot_deadzone) / (rot_max + rot_deadzone + EPSILON); + alpha = fmin(alpha, 1.0); + alpha = fmax(alpha, 0.0); + alpha = pow (alpha, rot_pow + rot_zoom); + alpha = alpha * (angle - rot_deadzone) / (angle + EPSILON); + + quat_last = Slerp(quat_last, quat_input, alpha); + + QuatToYPR(quat_last, &output[Yaw] ); +} + +OPENTRACK_DECLARE_FILTER(hamilton, dialog_hamilton, hamiltonDll) diff --git a/filter-hamilton/ftnoir_filter_hamilton.h b/filter-hamilton/ftnoir_filter_hamilton.h new file mode 100644 index 00000000..0756c216 --- /dev/null +++ b/filter-hamilton/ftnoir_filter_hamilton.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2020, GO63-samara <go1@list.ru> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#include "api/plugin-api.hpp" +#include "ui_ftnoir_hamilton_filtercontrols.h" +#include <QWidget> +#include <QMutex> +#include "options/options.hpp" +//#include "compat/timer.hpp" +#include "hamilton-tools.h" + +using namespace options; + +struct settings : opts { + value<slider_value> kMaxRot, kPowRot, kDeadZoneRot, + kMaxDist, kPowDist, kDeadZoneDist, + kPowZoom, kMaxZ; + settings() : + opts ("hamilton-filter"), + kMaxRot (b, "max-radius-smoothing", { .01, .001, 25.0 }), + kPowRot (b, "smoothing-power-rot", { .01, .001, 4.0 }), + kDeadZoneRot (b, "dead-zone-radius-rot", { .01, .001, 0.5 }), + kMaxDist (b, "max-distance-smoothing",{ .01, .001, 20.0 }), + kPowDist (b, "smoothing-power-dist", { .01, .001, 4.0 }), + kDeadZoneDist(b, "dead-zone-radius-dist", { .01, .001, 0.5 }), + kPowZoom (b, "smoothing-power-zoom", { .01, .001, 4.0 }), + kMaxZ (b, "max-z", { .01, .001, 100.0 }) + {} +}; + +class hamilton : public IFilter +{ +public: + hamilton(); + void filter(const double *input, double *output) override; + void center() override { first_run = true; } + module_status initialize() override { return status_ok(); } +private: + tQuat quat_last; + tVector pos_last; + settings s; + bool first_run = true; +}; + +class dialog_hamilton: public IFilterDialog +{ + Q_OBJECT +public: + dialog_hamilton(); + void register_filter(IFilter*) override {} + void unregister_filter() override {} + +private: + Ui::UICdialog_hamilton ui; + settings s; + +private slots: + void doOK(); + void doCancel(); +}; + +class hamiltonDll : public Metadata +{ + Q_OBJECT + + QString name() { return tr("Hamilton"); } + QIcon icon() { return QIcon(":/images/filter-16.png"); } +}; diff --git a/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp b/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp new file mode 100644 index 00000000..11f4c067 --- /dev/null +++ b/filter-hamilton/ftnoir_filter_hamilton_dialog.cpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2020, GO63-samara <go1@list.ru> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "ftnoir_filter_hamilton.h" +#include <cmath> +#include <QDebug> +#include <QString> +#include "api/plugin-api.hpp" +#include "ui_ftnoir_hamilton_filtercontrols.h" + +dialog_hamilton::dialog_hamilton() +{ + ui.setupUi(this); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.kMaxRot, ui.maxRot); + tie_setting(s.kMaxRot, ui.lbMaxRot, [](double x) + { return QStringLiteral("%1\xB0").arg(x, 0, 'f', 2);}); + + tie_setting(s.kPowRot, ui.powRot); + tie_setting(s.kPowRot, ui.lbPowRot, [](double x) + { return QStringLiteral("%1").arg(x, 0, 'f', 2);}); + + tie_setting(s.kDeadZoneRot, ui.dzRot); + tie_setting(s.kDeadZoneRot, ui.lbDZRot, [](double x) + { return QStringLiteral("%1\xB0").arg(x, 0, 'f', 2);}); + + tie_setting(s.kPowZoom, ui.powZoom); + tie_setting(s.kPowZoom, ui.lbPowZoom, [](double x) + { return QStringLiteral("%1").arg(x, 0, 'f', 2);}); + + tie_setting(s.kMaxZ, ui.maxZ); + tie_setting(s.kMaxZ, ui.lbMaxZ, [](double x) + { return QStringLiteral("%1").arg(x, 0, 'f', 2);}); + + tie_setting(s.kMaxDist, ui.maxDist); + tie_setting(s.kMaxDist, ui.lbMaxDist, [](double x) + { return QStringLiteral("%1cm").arg(x, 0, 'f', 2);}); + + tie_setting(s.kPowDist, ui.powDist); + tie_setting(s.kPowDist, ui.lbPowDist, [](double x) + { return QStringLiteral("%1").arg(x, 0, 'f', 2);}); + + tie_setting(s.kDeadZoneDist, ui.dzDist); + tie_setting(s.kDeadZoneDist, ui.lbDZDist, [](double x) + { return QStringLiteral("%1cm").arg(x, 0, 'f', 2);}); +} + +void dialog_hamilton::doOK() +{ + s.b->save(); + close(); +} + +void dialog_hamilton::doCancel() +{ + close(); +} diff --git a/filter-hamilton/ftnoir_hamilton_filtercontrols.ui b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui new file mode 100644 index 00000000..71cdb6da --- /dev/null +++ b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui @@ -0,0 +1,940 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UICdialog_hamilton</class> + <widget class="QWidget" name="UICdialog_hamilton"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>514</width> + <height>491</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>485</height> + </size> + </property> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="windowTitle"> + <string>Hamilton filter settings</string> + </property> + <property name="windowIcon"> + <iconset resource="../gui/opentrack-res.qrc"> + <normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>496</width> + <height>150</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>8</pointsize> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="title"> + <string>Rotations: </string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <widget class="QSlider" name="maxRot"> + <property name="geometry"> + <rect> + <x>103</x> + <y>30</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>250</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" name="lbRmax"> + <property name="geometry"> + <rect> + <x>7</x> + <y>30</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Max distance:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbMaxRot"> + <property name="geometry"> + <rect> + <x>424</x> + <y>30</y> + <width>61</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string notr="true"/> + </property> + <property name="text"> + <string>10,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbRdz"> + <property name="geometry"> + <rect> + <x>7</x> + <y>110</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Dead Zone:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="dzRot"> + <property name="geometry"> + <rect> + <x>103</x> + <y>110</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>5</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + </widget> + <widget class="QLabel" name="lbDZRot"> + <property name="geometry"> + <rect> + <x>424</x> + <y>110</y> + <width>61</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string notr="true"/> + </property> + <property name="text"> + <string>0,01</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="powRot"> + <property name="geometry"> + <rect> + <x>103</x> + <y>70</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>400</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>200</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbPowRot"> + <property name="geometry"> + <rect> + <x>430</x> + <y>70</y> + <width>45</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string notr="true"/> + </property> + <property name="text"> + <string>2,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbRpow"> + <property name="geometry"> + <rect> + <x>7</x> + <y>70</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Smoothing:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>150</height> + </size> + </property> + <property name="title"> + <string>Positions: </string> + </property> + <widget class="QSlider" name="maxDist"> + <property name="geometry"> + <rect> + <x>103</x> + <y>30</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>200</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" name="lbRpow_3"> + <property name="geometry"> + <rect> + <x>7</x> + <y>70</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Smoothing:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="powDist"> + <property name="geometry"> + <rect> + <x>103</x> + <y>70</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>400</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbRdz_3"> + <property name="geometry"> + <rect> + <x>7</x> + <y>110</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Dead Zone:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbPowDist"> + <property name="geometry"> + <rect> + <x>430</x> + <y>70</y> + <width>51</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>40</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>1,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbDmax"> + <property name="geometry"> + <rect> + <x>7</x> + <y>30</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Max distance:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="dzDist"> + <property name="geometry"> + <rect> + <x>103</x> + <y>110</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + </widget> + <widget class="QLabel" name="lbMaxDist"> + <property name="geometry"> + <rect> + <x>420</x> + <y>30</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>10,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbDZDist"> + <property name="geometry"> + <rect> + <x>420</x> + <y>110</y> + <width>71</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>0,02</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>100</height> + </size> + </property> + <property name="title"> + <string>Zoom smoothing: </string> + </property> + <widget class="QLabel" name="lbPowZoom"> + <property name="geometry"> + <rect> + <x>434</x> + <y>30</y> + <width>45</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>2,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="powZoom"> + <property name="geometry"> + <rect> + <x>103</x> + <y>30</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>400</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>200</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbZpow"> + <property name="geometry"> + <rect> + <x>7</x> + <y>30</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string> Smoothing :</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QSlider" name="maxZ"> + <property name="geometry"> + <rect> + <x>103</x> + <y>60</y> + <width>311</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>1000</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="pageStep"> + <number>50</number> + </property> + <property name="value"> + <number>150</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>100</number> + </property> + </widget> + <widget class="QLabel" name="lbZpow_2"> + <property name="geometry"> + <rect> + <x>7</x> + <y>60</y> + <width>91</width> + <height>20</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>Max Z:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="lbMaxZ"> + <property name="geometry"> + <rect> + <x>434</x> + <y>60</y> + <width>45</width> + <height>20</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>45</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>15,00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../gui/opentrack-res.qrc"/> + </resources> + <connections/> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/filter-hamilton/hamilton-tools.cpp b/filter-hamilton/hamilton-tools.cpp new file mode 100644 index 00000000..e18082a8 --- /dev/null +++ b/filter-hamilton/hamilton-tools.cpp @@ -0,0 +1,135 @@ +#include "hamilton-tools.h" +#include <cmath> + +double VectorLength(const tVector v) +{ + return(sqrt(v.v[0]*v.v[0] + v.v[1]*v.v[1] + v.v[2]*v.v[2])); +} + +double sqr(const double v) { return(v*v); } + +double VectorDistance(const double v1[], const tVector v2) +{ + return(sqrt(sqr(v2.v[0]-v1[0])+sqr(v2.v[1]-v1[1])+sqr(v2.v[2]-v1[2]))); +} + +tVector Lerp(const tVector s, const double d[], const double alpha) +{ + tVector V; + V.v[0] = s.v[0] + (d[0] - s.v[0]) * alpha; + V.v[1] = s.v[1] + (d[1] - s.v[1]) * alpha; + V.v[2] = s.v[2] + (d[2] - s.v[2]) * alpha; + return(V); +} + +tQuat QuatFromAngleAxe(const double angle, const tVector axe) +{ + double a = TO_RAD * 0.5 * angle; + double d = sin(a) / VectorLength(axe); + return ( tQuat ( + axe.v[0] * d, + axe.v[1] * d, + axe.v[2] * d, + cos(a) + ) + ); +} + +tQuat QuatMultiply(const tQuat qL, const tQuat qR) +{ + tQuat Q; + Q.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y; + Q.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z; + Q.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x; + Q.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z; + return(Q); +} + +double AngleBetween(const tQuat S, const tQuat D) +{ + return( TO_DEG * 2*acos(fabs(S.x*D.x + S.y*D.y + S.z*D.z + S.w*D.w)) ); +} + +tQuat QuatFromYPR(const double YPR[]) +{ + tQuat Q, Qp, Qy; + Q = QuatFromAngleAxe( -YPR[2], {0, 0, 1} ); //Roll, Z axe + Qp = QuatFromAngleAxe( -YPR[1], {1, 0, 0} ); //Pitch, X axe + Qy = QuatFromAngleAxe( -YPR[0], {0, 1, 0} ); //Yaw, Y axe + + Q = QuatMultiply(Qp, Q); + return(QuatMultiply(Qy, Q)); +} + +void Normalize(tQuat Q) +{ + double m = sqrt(Q.x*Q.x + Q.y*Q.y + Q.z*Q.z + Q.w*Q.w); + if (m > EPSILON) + { + m = 1 / m; + Q.x = Q.x * m; + Q.y = Q.y * m; + Q.z = Q.z * m; + Q.w = Q.w * m; + } + else Q = tQuat(0, 0, 0, 1); +} + +tQuat Slerp(const tQuat S, const tQuat D, const double alpha) +{ + // calc cosine of half angle + double cosin = S.x*D.x + S.y*D.y + S.z*D.z + S.w*D.w; + + // select nearest rotation direction + tQuat Q; + if (cosin < 0) + { + cosin = - cosin; + Q.x = - D.x; + Q.y = - D.y; + Q.z = - D.z; + Q.w = - D.w; + } + else Q = D; + + // calculate coefficients + double scale0, scale1; + if ((1.0 - cosin) > EPSILON) + { + double omega = acos(cosin); + double sinus = 1 / sin(omega); + scale0 = sin((1.0 - alpha) * omega) * sinus; + scale1 = sin(alpha * omega)* sinus; + } + else + { + scale0 = 1.0 - alpha; + scale1 = alpha; + } + + Q.x = scale0 * S.x + scale1 * Q.x; + Q.y = scale0 * S.y + scale1 * Q.y; + Q.z = scale0 * S.z + scale1 * Q.z; + Q.w = scale0 * S.w + scale1 * Q.w; + + Normalize(Q); + + return( Q ); +} + +void QuatToYPR(const tQuat Q, double YPR[]) +{ + const double xx = Q.x * Q.x; + const double xy = Q.x * Q.y; + const double xz = Q.x * Q.z; + const double xw = Q.x * Q.w; + const double yy = Q.y * Q.y; + const double yz = Q.y * Q.z; + const double yw = Q.y * Q.w; + const double zz = Q.z * Q.z; + const double zw = Q.z * Q.w; + + YPR[0] = TO_DEG * ( -atan2( 2 * ( xz + yw ), 1 - 2 * ( xx + yy ) )); + YPR[1] = TO_DEG * ( asin ( 2 * ( yz - xw ) )); + YPR[2] = TO_DEG * ( -atan2( 2 * ( xy + zw ), 1 - 2 * ( xx + zz ) )); +} diff --git a/filter-hamilton/hamilton-tools.h b/filter-hamilton/hamilton-tools.h new file mode 100644 index 00000000..2e288225 --- /dev/null +++ b/filter-hamilton/hamilton-tools.h @@ -0,0 +1,27 @@ +#pragma once + +#include "compat/math.hpp" +constexpr double TO_RAD = (M_PI / 180); +constexpr double TO_DEG = (180 / M_PI); +constexpr double EPSILON = 1e-30; + +struct tVector +{ + double v[3]; + tVector(double X = 0, double Y = 0, double Z = 0) {v[0]=X; v[1]=Y; v[2]=Z;} + tVector(double V[]) {v[0]=V[0]; v[1]=V[1]; v[2]=V[2];} +}; + +struct tQuat +{ + double x, y, z, w; + tQuat(double X = 0, double Y = 0, double Z = 0, double W = 1) + {x = X; y = Y; z = Z; w = W;} +}; + +double VectorDistance(const double v1[], const tVector v2); +tVector Lerp (const tVector s, const double d[], const double alpha); +tQuat QuatFromYPR (const double YPR[]); +double AngleBetween (const tQuat S, const tQuat D); +tQuat Slerp (const tQuat S, const tQuat D, const double alpha); +void QuatToYPR (const tQuat Q, double YPR[]); diff --git a/filter-hamilton/lang/nl_NL.ts b/filter-hamilton/lang/nl_NL.ts new file mode 100644 index 00000000..b03e4c0b --- /dev/null +++ b/filter-hamilton/lang/nl_NL.ts @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>UICdialog_hamilton</name> + <message> + <source>Rotations: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing :</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Positions: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Zoom smoothing: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Hamilton filter settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max Z:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>10,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,01</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>2,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>1,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,02</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>15,00</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>hamiltonDll</name> + <message> + <source>Hamilton</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/filter-hamilton/lang/ru_RU.ts b/filter-hamilton/lang/ru_RU.ts new file mode 100644 index 00000000..dfbb2268 --- /dev/null +++ b/filter-hamilton/lang/ru_RU.ts @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>UICdialog_hamilton</name> + <message> + <source>Rotations: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing :</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Positions: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Zoom smoothing: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Hamilton filter settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max Z:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>10,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,01</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>2,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>1,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,02</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>15,00</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>hamiltonDll</name> + <message> + <source>Hamilton</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/filter-hamilton/lang/stub.ts b/filter-hamilton/lang/stub.ts new file mode 100644 index 00000000..a8af9f98 --- /dev/null +++ b/filter-hamilton/lang/stub.ts @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>UICdialog_hamilton</name> + <message> + <source>Rotations: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing :</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Positions: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Zoom smoothing: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Hamilton filter settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max Z:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>10,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,01</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>2,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>1,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,02</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>15,00</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>hamiltonDll</name> + <message> + <source>Hamilton</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/filter-hamilton/lang/zh_CN.ts b/filter-hamilton/lang/zh_CN.ts new file mode 100644 index 00000000..a8af9f98 --- /dev/null +++ b/filter-hamilton/lang/zh_CN.ts @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>UICdialog_hamilton</name> + <message> + <source>Rotations: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing :</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Positions: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Zoom smoothing: </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Hamilton filter settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max Z:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>10,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,01</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>2,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>1,00</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>0,02</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source> Smoothing:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>15,00</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>hamiltonDll</name> + <message> + <source>Hamilton</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/gui/correlation-calibrator.ui b/gui/correlation-calibrator.ui index d351d5da..02fdf1d2 100644 --- a/gui/correlation-calibrator.ui +++ b/gui/correlation-calibrator.ui @@ -40,7 +40,7 @@ Press "clear calibration" to remove any calibration data pertaining to <enum>Qt::ScrollBarAlwaysOff</enum> </property> <property name="sizeAdjustPolicy"> - <enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum> + <enum>QAbstractScrollArea::AdjustToContents</enum> </property> <property name="autoScroll"> <bool>true</bool> diff --git a/gui/init.cpp b/gui/init.cpp index 3aae5772..2b7b01ad 100644 --- a/gui/init.cpp +++ b/gui/init.cpp @@ -159,6 +159,39 @@ static void qdebug_to_console(QtMsgType loglevel, const QMessageLogContext& ctx, #ifdef _WIN32 +static void apply_dark_windows_theme_if_needed() +{ + // On Windows apply dark theme if requested by user settings + QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", QSettings::NativeFormat); + if (settings.value("AppsUseLightTheme") == 0) { + qApp->setStyle(QStyleFactory::create("Dark")); + QPalette darkPalette; + QColor darkColor = QColor(45, 45, 45); + QColor disabledColor = QColor(127, 127, 127); + darkPalette.setColor(QPalette::Window, darkColor); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Base, QColor(18, 18, 18)); + darkPalette.setColor(QPalette::AlternateBase, darkColor); + darkPalette.setColor(QPalette::ToolTipBase, Qt::white); + darkPalette.setColor(QPalette::ToolTipText, Qt::white); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, disabledColor); + darkPalette.setColor(QPalette::Button, darkColor); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + + darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::HighlightedText, Qt::black); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor); + + qApp->setPalette(darkPalette); + + qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); + } +} + static void add_win32_path() { // see https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable @@ -270,6 +303,7 @@ int otr_main(int argc, char** argv, std::function<std::unique_ptr<QWidget>()> co QApplication app(argc, argv); #ifdef _WIN32 + apply_dark_windows_theme_if_needed(); add_win32_path(); attach_parent_console(); #endif diff --git a/gui/process_detector.cpp b/gui/process_detector.cpp index b8de227d..58ea4ca9 100644 --- a/gui/process_detector.cpp +++ b/gui/process_detector.cpp @@ -56,6 +56,10 @@ void proc_detector_settings::set_is_enabled(bool enabled) }); } +#ifdef __GNUG__ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + QHash<QString, QString> proc_detector_settings::split_process_names() { QString str = get_game_list(); @@ -163,6 +167,7 @@ void process_detector::save() void process_detector::revert() { load_rows(); + ui.enabled->setChecked(s.is_enabled()); } void process_detector::add() diff --git a/installer/opentrack-installer.iss b/installer/opentrack-installer.iss index e8a20b6c..32b9159c 100644 --- a/installer/opentrack-installer.iss +++ b/installer/opentrack-installer.iss @@ -24,7 +24,7 @@ DefaultDirName={pf}\{#MyAppName} DefaultGroupName={#MyAppName} AllowNoIcons=yes OutputBaseFilename={#MyAppVersion}-win32-setup -SetupIconFile=..\variant\default\opentrack.ico +SetupIconFile=..\opentrack\opentrack.ico Compression=lzma2/ultra64 SolidCompression=yes DisableWelcomePage=True @@ -34,7 +34,7 @@ RestartIfNeededByRun=False InternalCompressLevel=ultra CompressionThreads=4 LZMANumFastBytes=273 -MinVersion=0,5.01sp2 +MinVersion=0,6 [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt index f3f128af..f3344798 100644 --- a/logic/CMakeLists.txt +++ b/logic/CMakeLists.txt @@ -1,7 +1,7 @@ otr_module(logic BIN) -target_link_libraries(opentrack-logic opentrack-spline) +target_link_libraries(${self} opentrack-spline) if(NOT WIN32) - target_link_libraries(opentrack-logic opentrack-qxt-mini) + target_link_libraries(${self} opentrack-qxt-mini) else() - target_link_libraries(opentrack-logic opentrack-dinput winmm) + target_link_libraries(${self} opentrack-dinput winmm) endif() diff --git a/logic/shortcuts.cpp b/logic/shortcuts.cpp index 377fa3e5..26465101 100644 --- a/logic/shortcuts.cpp +++ b/logic/shortcuts.cpp @@ -83,26 +83,28 @@ void Shortcuts::bind_shortcut(K& key, const key_opts& k, bool held) #ifdef _WIN32 -void Shortcuts::receiver(const Key& k) +void Shortcuts::receiver(const Key& key) { const unsigned sz = keys.size(); for (unsigned i = 0; i < sz; i++) { - K& k_ = std::get<0>(keys[i]); - if (k.guid != k_.guid) + K& k = std::get<0>(keys[i]); + if (key.guid != k.guid) continue; - if (k.keycode != k_.keycode) - continue; - - if (k_.held && !k.held) continue; - if (k_.alt != k.alt) continue; - if (k_.ctrl != k.ctrl) continue; - if (k_.shift != k.shift) continue; - if (!k_.should_process()) + if (key.keycode != k.keycode) continue; + if (k.held && !key.held) continue; + if (key.held) + { + if (k.alt != key.alt) continue; + if (k.ctrl != key.ctrl) continue; + if (k.shift != key.shift) continue; + if (!k.should_process()) + continue; + } fun& f = std::get<1>(keys[i]); - f(k.held); + f(key.held); } } diff --git a/logic/win32-shortcuts.cpp b/logic/win32-shortcuts.cpp index c2920071..086c8d92 100644 --- a/logic/win32-shortcuts.cpp +++ b/logic/win32-shortcuts.cpp @@ -74,7 +74,21 @@ static const win_key windows_key_sequences[] { { DIK_F9, Qt::Key_F9 }, { DIK_F10, Qt::Key_F10 }, { DIK_F11, Qt::Key_F11 }, - { DIK_F12, Qt::Key_F12 }, + { DIK_F13, Qt::Key_F12 }, + { DIK_F14, Qt::Key_F12 }, + { DIK_F15, Qt::Key_F12 }, + { 0x67, Qt::Key_F12 }, + { 0x68, Qt::Key_F13 }, + { 0x69, Qt::Key_F14 }, + { 0x6a, Qt::Key_F15 }, + { 0x6b, Qt::Key_F16 }, + { 0x6c, Qt::Key_F17 }, + { 0x6d, Qt::Key_F18 }, + { 0x6e, Qt::Key_F19 }, + { 0x70, Qt::Key_F20 }, + { 0x71, Qt::Key_F21 }, + { 0x72, Qt::Key_F23 }, + { 0x73, Qt::Key_F24 }, { DIK_0, Qt::Key_0 }, { DIK_1, Qt::Key_1 }, { DIK_2, Qt::Key_2 }, diff --git a/logic/work.cpp b/logic/work.cpp index 302414b8..7689f916 100644 --- a/logic/work.cpp +++ b/logic/work.cpp @@ -36,12 +36,8 @@ std::unique_ptr<TrackLogger> Work::make_logger(main_settings &s) if (s.tracklogging_enabled) { QString filename = browse_datalogging_file(s); - if (filename.isEmpty()) - { - // The user probably canceled the file dialog. In this case we don't want to do anything. - return {}; - } - else + + if (!filename.isEmpty()) { auto logger = std::make_unique<TrackLoggerCSV>(*s.tracklogging_filename); diff --git a/macosx/CMakeLists.txt b/macosx/CMakeLists.txt index 89901251..8520e9e9 100644 --- a/macosx/CMakeLists.txt +++ b/macosx/CMakeLists.txt @@ -1,13 +1,11 @@ if(APPLE) otr_escape_string(srcdir "${CMAKE_SOURCE_DIR}") - otr_escape_string(bindir "${CMAKE_BINARY_DIR}") otr_escape_string(instdir "${CMAKE_INSTALL_PREFIX}") otr_escape_string(commit "${OPENTRACK_COMMIT}") install(CODE " - execute_process(COMMAND /bin/sh \"${srcdir}/macosx/make-app-bundle.sh\" + execute_process(COMMAND /bin/sh \"${srcdir}/macosx/make-app-bundle.sh\" \"${srcdir}/macosx\" \"${instdir}\" - \"${bindir}\" - \"${commit}\") + \"${commit}\") ") endif() diff --git a/macosx/opentrack.app/Contents/Info.plist b/macosx/Info.plist index 41ca402a..3fd8b614 100644 --- a/macosx/opentrack.app/Contents/Info.plist +++ b/macosx/Info.plist @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleExecutable</key> - <string>opentrack.sh</string> + <string>opentrack</string> <key>CFBundleIdentifier</key> <string>com.github.opentrack</string> <key>CFBundleName</key> @@ -22,5 +22,13 @@ <string>opentrack</string> <key>CFBundleSignature</key> <string>????</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>NSHighResolutionCapable</key> + <string>True</string> + <key>NSCameraUsageDescription</key> + <string>OpenTrack need's to access your camera to capture track head position.</string> + <key>NSDocumentsFolderUsageDescription</key> + <string>OpenTrack need's to access your to your documents folder to store settings</string> </dict> </plist> diff --git a/macosx/PkgInfo b/macosx/PkgInfo new file mode 100644 index 00000000..6f749b0f --- /dev/null +++ b/macosx/PkgInfo @@ -0,0 +1 @@ +APPL???? diff --git a/macosx/dmgbackground.png b/macosx/dmgbackground.png Binary files differnew file mode 100644 index 00000000..e3a398c0 --- /dev/null +++ b/macosx/dmgbackground.png diff --git a/macosx/install-fail-tool b/macosx/install-fail-tool index a5464c18..16284562 100755 --- a/macosx/install-fail-tool +++ b/macosx/install-fail-tool @@ -4,22 +4,22 @@ test -n "$1" || exit 1 dir="$1" -for i in "$dir"/* "$dir"/*/* "$dir"/*/*/*; do - { test -x "$i" && test -f "$i"; } || continue +for i in "$dir"/*; do + echo $i + { test -f "$i"; } || continue case "$i" in *.dll|*.exe) continue ;; *) : ;; esac - case "$i" in - *.dylib|*.bin) strip -x "$i" ;; esac echo ---- $i ---- install_name_tool -id "@executable_path/$(echo "$i" | sed -e "s,^$dir/,,")" "$i" otool -L "$i" | awk '{ print $1 }' | while read l; do j="$(basename -- "$l")" + echo === $j === if test -e "$dir/$j"; then - install_name_tool -change "$l" "@executable_path/$j" "$i" + install_name_tool -change "$l" "@rpath/$j" "$i" fi done done diff --git a/macosx/make-app-bundle.sh b/macosx/make-app-bundle.sh index 05259702..9265eeb9 100644..100755 --- a/macosx/make-app-bundle.sh +++ b/macosx/make-app-bundle.sh @@ -1,41 +1,90 @@ #!/bin/sh +# exit when any command fails +set -e + +# keep track of the last executed command +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +# echo an error message before exiting +trap 'echo "--\n--\n--\n--\n\"${last_command}\" command failed with exit code $?."' EXIT + APPNAME=opentrack +# Alternative we could look at https://github.com/arl/macdeployqtfix ?? -dir="$1" -test -n "$dir" || exit 1 +#macosx directory +dir="$1" +test -n "$dir" +# install directory install="$2" -test -n "$install" || exit 1 -output_dir="$3" -test -n "$output_dir" || exit 1 -version="$4" -test -n "$version" || exit 1 +test -n "$install" +version="$3" +test -n "$version" tmp="$(mktemp -d "/tmp/$APPNAME-tmp.XXXXXXX")" -test $? -eq 0 || exit 1 +test $? -eq 0 + -rm -f -- "$install/.DS_Store" -sh "$dir/install-fail-tool" "$install" +# Add rpath for application so it can find the libraries +#install_name_tool -add_rpath @executable_path/../Frameworks "$install/$APPNAME.app/Contents/MacOS/$APPNAME" -cp -R "$dir/opentrack.app" "$tmp/" || exit 1 -cp -R "$install" "$tmp/$APPNAME.app/Contents/MacOS" || exit 1 -sed -i '' -e "s#@OPENTRACK-VERSION@#$version#g" "$tmp/$APPNAME.app/Contents/Info.plist" || exit 1 +# Copy our own plist and set correct version +cp "$dir/Info.plist" "$install/$APPNAME.app/Contents/" +sed -i '' -e "s#@OPENTRACK-VERSION@#$version#g" "$install/$APPNAME.app/Contents/Info.plist" -mkdir "$tmp/$APPNAME.iconset" || exit 1 -mkdir "$tmp/$APPNAME.app/Contents/Resources" || exit 1 -cp "$dir"/opentrack.sh "$tmp/$APPNAME.app/Contents/MacOS" || exit 1 +# Copy PkgInfo +cp "$dir/PkgInfo" "$install/$APPNAME.app/Contents/" -sips -z 16 16 "$dir/../gui/images/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_16x16.png" || exit 1 -sips -z 32 32 "$dir/../gui/images/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_16x16@2x.png" || exit 1 -sips -z 32 32 "$dir/../gui/images/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_32x32.png" || exit 1 -sips -z 64 64 "$dir/../gui/images/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_32x32@2x.png" || exit 1 -sips -z 128 128 "$dir/../gui/images/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_128x128.png" || exit 1 +# Copy plugins +mkdir -p "$install/$APPNAME.app/Contents/MacOS/Plugins" +cp -r "$install/Plugins" "$install/$APPNAME.app/Contents/MacOS/" -iconutil -c icns -o "$tmp/$APPNAME.app/Contents/Resources/$APPNAME.icns" "$tmp/$APPNAME.iconset" -rm -r "$tmp/$APPNAME.iconset" +# Add framework and other libraries and fixup other libraries +macdeployqt "$install/$APPNAME.app" -libpath="$install/Library" +sh "$dir/install-fail-tool" "$install/$APPNAME.app/Contents/Frameworks" -cd "$tmp" || exit 1 -rm -f "$output_dir/$version-macosx.zip" -zip -9r "$output_dir/$version-macosx.zip" "$APPNAME.app" || exit 1 +# Create an 512 resolution size for the icon (for retina displays mostly) +#gm convert -size 512x512 "$dir/../gui/images/opentrack.png" "$tmp/opentrack.png" +convert "$dir/../gui/images/opentrack.png" -filter triangle -resize 512x512 "$tmp/opentrack.png" + +# Build iconset +mkdir "$tmp/$APPNAME.iconset" +sips -z 16 16 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_16x16.png" +sips -z 32 32 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_16x16@2x.png" +sips -z 32 32 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_32x32.png" +sips -z 64 64 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_32x32@2x.png" +sips -z 128 128 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_128x128.png" +sips -z 256 256 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_128x128@2x.png" +sips -z 512 512 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_256x256@2x.png" +sips -z 512 512 "$tmp/opentrack.png" --out "$tmp/$APPNAME.iconset/icon_512x512.png" +iconutil -c icns -o "$install/$APPNAME.app/Contents/Resources/$APPNAME.icns" "$tmp/$APPNAME.iconset" rm -rf "$tmp" -ls -lh "$output_dir/$version-macosx.zip" + +#Build DMG +#https://github.com/andreyvit/create-dmg +rm -rf $install/../*.dmg +create-dmg \ + --volname "$APPNAME" \ + --volicon "$install/$APPNAME.app/Contents/Resources/$APPNAME.icns" \ + --window-pos 200 120 \ + --window-size 800 450 \ + --icon-size 80 \ + --background "$dir/dmgbackground.png" \ + --icon "$APPNAME.app" 200 180 \ + --app-drop-link 420 180 \ + --hide-extension "$APPNAME.app" \ + --no-internet-enable \ + --add-folder "Document" "$install/doc" 20 40 \ + --add-folder "source-code" "$install/source-code" 220 40 \ + --add-folder "Xplane-Plugin" "$install/xplane" 420 40 \ + --add-folder "thirdparty" "$install/thirdparty" 620 40 \ + "$version.dmg" \ + "$install/$APPNAME.app" + +# Check if we have a DMG otherwise fail +FILE=$install/../$version.dmg +if [ -f $FILE ]; then + ls -ial $install/../*.dmg +else + echo "Failed to create ${FILE}" + exit 2 +fi diff --git a/macosx/opentrack.app/Contents/PkgInfo b/macosx/opentrack.app/Contents/PkgInfo deleted file mode 100644 index b18f8c6c..00000000 --- a/macosx/opentrack.app/Contents/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPLopentrack diff --git a/macosx/opentrack.sh b/macosx/opentrack.sh deleted file mode 100755 index 74a911e2..00000000 --- a/macosx/opentrack.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -cd -- "$(dirname -- "$0")" && -exec ./opentrack.bin -platformpluginpath "$(pwd)" "$@" - -exit 1 diff --git a/migration/CMakeLists.txt b/migration/CMakeLists.txt index b2dfac6d..effeddcb 100644 --- a/migration/CMakeLists.txt +++ b/migration/CMakeLists.txt @@ -1,5 +1,5 @@ otr_module(migration BIN) -target_link_libraries(opentrack-migration opentrack-logic opentrack-spline) +target_link_libraries(${self} opentrack-logic opentrack-spline) if(CMAKE_COMPILER_IS_CLANGXX) target_compile_options(${self} PRIVATE -Wno-weak-vtables) endif() diff --git a/opentrack/main-window.cpp b/opentrack/main-window.cpp index cd715216..4f6972f4 100644 --- a/opentrack/main-window.cpp +++ b/opentrack/main-window.cpp @@ -34,7 +34,7 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) { ui.setupUi(this); -#if !defined _WIN32 && !defined __APPLE__ +#if !defined _WIN32 annoy_if_root(); #endif @@ -47,7 +47,7 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) init_shortcuts(); init_tray_menu(); - setVisible(start_in_tray()); + setVisible(!start_in_tray()); ensure_tray(); connect(&pose_update_timer, &QTimer::timeout, @@ -280,14 +280,7 @@ main_window::~main_window() stop_tracker_(); close(); - constexpr int inc = 25, max = 1000; - - for (int k = 0; k < max; k += inc) - { - QEventLoop ev; - ev.processEvents(); - portable::sleep(inc); - } + portable::sleep(1000); } exit(); diff --git a/opentrack/main-window.ui b/opentrack/main-window.ui index a30ef9ed..0ec5b5ab 100644 --- a/opentrack/main-window.ui +++ b/opentrack/main-window.ui @@ -8,7 +8,7 @@ <x>0</x> <y>0</y> <width>818</width> - <height>666</height> + <height>567</height> </rect> </property> <property name="sizePolicy"> diff --git a/options/bundle.hpp b/options/bundle.hpp index ce859bb1..158fcef9 100644 --- a/options/bundle.hpp +++ b/options/bundle.hpp @@ -10,6 +10,7 @@ #include "group.hpp" #include "connector.hpp" +#include "compat/qhash.hpp" #include <memory> #include <tuple> diff --git a/options/connector.hpp b/options/connector.hpp index ffef2a3d..025efda2 100644 --- a/options/connector.hpp +++ b/options/connector.hpp @@ -8,12 +8,13 @@ #pragma once +#include "compat/qhash.hpp" + #include <unordered_map> #include <vector> #include <QString> #include <QMutex> -#include <QHashFunctions> #include "export.hpp" diff --git a/options/globals.cpp b/options/globals.cpp index 099a7208..386ef56d 100644 --- a/options/globals.cpp +++ b/options/globals.cpp @@ -154,8 +154,8 @@ fail: constexpr const char* subdir = "ini"; QString dir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0, QString()); if (dir.isEmpty()) goto fail; -#if !defined _WIN32 && !defined __APPLE__ const QString fmt = QStringLiteral("%1/%2"); +#if !defined _WIN32 && !defined __APPLE__ if (!QFile::exists(fmt.arg(dir, OPENTRACK_ORG))) { dir = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).value(0, QString()); diff --git a/options/group.hpp b/options/group.hpp index 751eee34..93299b6e 100644 --- a/options/group.hpp +++ b/options/group.hpp @@ -5,6 +5,7 @@ #include "compat/base-path.hpp" #include "compat/library-path.hpp" #include "compat/macros.hpp" +#include "compat/qhash.hpp" #include "export.hpp" #include <optional> diff --git a/pose-widget/CMakeLists.txt b/pose-widget/CMakeLists.txt index fd109bc3..28dc918b 100644 --- a/pose-widget/CMakeLists.txt +++ b/pose-widget/CMakeLists.txt @@ -1,2 +1,2 @@ otr_module(pose-widget BIN) -target_link_libraries(opentrack-pose-widget) +target_link_libraries(${self}) diff --git a/pose-widget/ReadMe.txt b/pose-widget/ReadMe.txt new file mode 100644 index 00000000..c504ff41 --- /dev/null +++ b/pose-widget/ReadMe.txt @@ -0,0 +1,26 @@ +Hi everyone! + +In the extreme version of OpenTrack-2.3.12, the Octopus pose is still displayed incorrectly. +The pose-widget is responsible for displaying the Octopus pose in OpenTrack. I have fixed this widget. + +Fixed bugs: +- The turns and movements of the Octopussy are now performed truly independently of each other, as it should be in 6DOF. +- When cornering, there is no "gimbal lock" at Pitch = +/- 90 degrees. +- Fixed directions of axes of rotations and positions. Now the Octopus pose displays the actual direction of view on the plane. +- Fixed display of the back (green) surface of the Octopus. Previously, it was displayed mirrored. + +Additional features: +- Applied "perspective projection", the picture becomes more voluminous. +- Added lighting effect from above, with the same purpose. +- Added background fill for the widget. This makes it possible to see the borders of the widget. +- Added X and Y axes. This helps to estimate how far the Octopus is deviated from the center. +- Added [Mirror] checkbox, mirroring positions and rotations. It is often more convenient to observe the Octopussy's mirror pose. +- If before compilation in the file "pose-widget.hpp" include line 19: "#define TEST", then a rectangular frame will be drawn around the Octopus. This is useful when testing a pose-widget to assess distortion and size. + +The corrected pose-widget now displays the Octopus pose correctly and can be used to check OpenTrack settings, sometimes even without launching the flight simulator. + +A video of the corrected pose-widget is available here: + +https://youtu.be/my4_VOwGmq4 + +fixed by GO63-samara <go1@list.ru> <github.com/GO63-samara> 2020 diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp index 53bf214f..c5a6b78e 100644 --- a/pose-widget/pose-widget.cpp +++ b/pose-widget/pose-widget.cpp @@ -13,12 +13,40 @@ #include <QtEvents> #include <QDebug> -#include <QImage> +#include <QQuaternion> +#include <QMatrix4x4> namespace pose_widget_impl { pose_widget::pose_widget(QWidget* parent) : QWidget(parent) { + QPainter p; +#ifdef TEST + //draw rectangle frame around of Octopus, only if TEST defined + p.begin(&front); + p.setPen(QPen(Qt::red, 3, Qt::SolidLine)); + p.drawRect(0, 0, front.width()-1, front.height()-1); + p.end(); + + p.begin(&back); + p.setPen(QPen(Qt::darkGreen, 3, Qt::SolidLine)); + p.drawRect(0, 0, back.width()-1, back.height()-1); + p.end(); +#endif + + //draw Octopus shine + shine.fill(QColor(255,255,255)); + p.begin(&shine); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawImage(QPointF(0,0), front); + p.end(); + + //draw Octopus shadow + shadow.fill(QColor(0,0,0)); + p.begin(&shadow); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawImage(QPointF(0,0), front); + p.end(); } void pose_widget::present(double yaw, double pitch, double roll, double x, double y, double z) @@ -29,39 +57,87 @@ void pose_widget::present(double yaw, double pitch, double roll, double x, doubl repaint(); } +void pose_widget::resizeEvent(QResizeEvent *event) +{ + // adapt to widget size + float w = event->size().width(); + float h = event->size().height(); + + // fill background by color + constexpr int clr = 220; + QImage background(QImage(w, h, QImage::Format_ARGB32)); + background.fill(QColor(clr,clr,clr)); + + // draw axes + QPainter p(&background); + p.setPen(QPen(Qt::gray, 1, Qt::SolidLine)); + p.drawLine(0.5*w, 0 , 0.5*w, h ); + p.drawLine( 0 , 0.5*h, w , 0.5*h); + + // set AutoFillBackground + QPalette palette; + palette.setBrush(this->backgroundRole(), QBrush(background)); + setPalette(palette); + setAutoFillBackground(true); + + // move the mirror checkbox in the lower right corner of the widget + mirror.setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + mirror.move(w - mirror.width(), h - mirror.height()); +} + void pose_widget::paintEvent(QPaintEvent*) { + // widget settings: + constexpr float scale = 0.5; // scale of Octopus height, when x = y = z = 0.0 + constexpr float XYZmax = 50.0; // -XYZmax < x,y,z < +XYZmax (offset the Octopus by one body) + constexpr float Kz = 0.25; // Z scale change limit (simulate camera focus length) + + // get a local copy of input data auto [ yaw, pitch, roll ] = R; auto [ x, y, z ] = T; - const QImage& img = (std::fabs(pitch) > 90) ^ (std::fabs(yaw) > 90) - ? back - : front; - - int w = img.width(), h = img.height(); - - QTransform t; - - t.translate(w*.5, h*.5); - - constexpr double z_scale = 1./250; - constexpr double xy_scale = .0075; - double xy = std::sqrt(w*w + h*h) * xy_scale; - - double s = clamp(.4 + -z * z_scale, .1, 2); - t.scale(s, s); - - t.rotate(pitch, Qt::XAxis); - t.rotate(yaw, Qt::YAxis); - t.rotate(roll, Qt::ZAxis); - - t.translate(x * xy / s, y * xy / s); - - t.translate(w*-.5, h*-.5); - QPainter p(this); + #ifdef TEST + // use antialiasing for correct frame around the Octopus, only if TEST defined + p.setRenderHint(QPainter::Antialiasing, true); + #endif + + // check mirror state + if (mirror.checkState() == Qt::Checked) x = -x; + else { yaw = -yaw; roll = -roll; } + y = -y; + + // rotations + QQuaternion q = QQuaternion::fromEulerAngles(pitch, yaw, roll); + QMatrix4x4 m = QMatrix4x4(q.toRotationMatrix()); + + // x and y positions + const float Kxy = (float)front.height() / XYZmax; + QVector3D v(Kxy*x, Kxy*y, 0.0); + v = m.transposed().map(v); + m.translate(v); + + // perspective projection to x-y plane + QTransform t = m.toTransform(1024).translate(-.5 * front.width(), -.5 * front.height()); + + // z position by setViewport + const float mz = scale * height()/front.height()/exp(1.0) * exp(1.0 - z * (Kz/XYZmax)); + p.setViewport(QRect(.5 * width(), .5 * height(), width()*mz, height()*mz)); + + // define forward or backward side by cross product of mapped x and y axes + QPointF point0 = t.map(QPointF(0, 0)); + QPointF x_dir = (t.map(QPointF(1, 0)) -= point0); + QPointF y_dir = (t.map(QPointF(0, 1)) -= point0); + const bool forward = x_dir.ry()*y_dir.rx() - x_dir.rx()*y_dir.ry() < 0 ? true : false; + + // draw red or green Octopus p.setTransform(t); - p.drawImage(rect(), img); + p.drawImage(QPointF(0,0), forward ? front : back); + + // top lighting simulation + const float alpha = sin(pitch * M_PI / 180.0); + p.setOpacity(0.333 * fabs(alpha)); + p.drawImage(QPointF(0,0), forward == (alpha >= 0.0) ? shine : shadow); } QSize pose_widget::sizeHint() const diff --git a/pose-widget/pose-widget.hpp b/pose-widget/pose-widget.hpp index b3267ff9..49044d93 100644 --- a/pose-widget/pose-widget.hpp +++ b/pose-widget/pose-widget.hpp @@ -14,7 +14,9 @@ #include <QWidget> #include <QImage> +#include <QCheckBox> +//#define TEST namespace pose_widget_impl { using namespace euler; @@ -25,13 +27,17 @@ public: pose_widget(QWidget *parent = nullptr); void present(double xAngle, double yAngle, double zAngle, double x, double y, double z); QSize sizeHint() const override; - + QCheckBox mirror{QCheckBox{"Mirror", this}}; private: + void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent*) override; Pose_ R, T; QImage front{QImage{":/images/side1.png"}.convertToFormat(QImage::Format_ARGB32)}; - QImage back{QImage{":/images/side6.png"}.convertToFormat(QImage::Format_ARGB32)}; + QImage back {QImage{":/images/side6.png"}.convertToFormat(QImage::Format_ARGB32) + .mirrored(true,false)}; + QImage shine {QImage{front.width(), front.height(), QImage::Format_ARGB32}}; + QImage shadow{QImage{front.width(), front.height(), QImage::Format_ARGB32}}; }; } diff --git a/proto-iokit-foohid/CMakeLists.txt b/proto-iokit-foohid/CMakeLists.txt index 31d3dcdc..6a4bf89a 100644 --- a/proto-iokit-foohid/CMakeLists.txt +++ b/proto-iokit-foohid/CMakeLists.txt @@ -1,4 +1,4 @@ -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if(APPLE) otr_module(proto-iokit-foohid) target_link_options(${self} PRIVATE -framework IOKit) endif() diff --git a/proto-iokit-foohid/foohidjoystick.cpp b/proto-iokit-foohid/foohidjoystick.cpp index 0b305d08..898db2f4 100644 --- a/proto-iokit-foohid/foohidjoystick.cpp +++ b/proto-iokit-foohid/foohidjoystick.cpp @@ -51,7 +51,7 @@ static bool connectToService(io_connect_t *connection, QString *errorMessage) IOServiceMatching(FOOHID_SERVICE_NAME), &iterator); if (ret != KERN_SUCCESS) { - *errorMessage = otr_tr("Unable to find FooHID IOService."); + *errorMessage = QObject::tr("Unable to find FooHID IOService."); return false; } // Iterate over services and try to open connection @@ -66,7 +66,7 @@ static bool connectToService(io_connect_t *connection, QString *errorMessage) } IOObjectRelease(iterator); if (!found) { - *errorMessage = otr_tr("Unable to connect to FooHID IOService."); + *errorMessage = QObject::tr("Unable to connect to FooHID IOService."); return false; } return true; @@ -89,7 +89,7 @@ FooHIDJoystick::FooHIDJoystick(const QByteArray &name, const QByteArray &serialN deviceCreated = createDevice(); _hasError = !deviceCreated; if (!deviceCreated) - _errorMessage = otr_tr("Failed to create virtual joystick"); + _errorMessage = tr("Failed to create virtual joystick"); } } @@ -116,7 +116,7 @@ void FooHIDJoystick::setValue(JoystickValues newValues) values = newValues; if (!sendToDevice()) { _hasError = true; - _errorMessage = otr_tr("Failed to send values to virtual joystick"); + _errorMessage = tr("Failed to send values to virtual joystick"); } } diff --git a/proto-iokit-foohid/foohidjoystick.h b/proto-iokit-foohid/foohidjoystick.h index a1f74304..e987c229 100644 --- a/proto-iokit-foohid/foohidjoystick.h +++ b/proto-iokit-foohid/foohidjoystick.h @@ -9,6 +9,7 @@ #include <QByteArray> #include <QString> +#include <QCoreApplication> #include <IOKit/IOKitLib.h> @@ -23,6 +24,7 @@ struct JoystickValues { class FooHIDJoystick { + Q_DECLARE_TR_FUNCTIONS(FooHIDJoystick) public: FooHIDJoystick(const QByteArray &name, const QByteArray &serialNumber); ~FooHIDJoystick(); diff --git a/proto-iokit-foohid/iokitprotocol.cpp b/proto-iokit-foohid/iokitprotocol.cpp index 6f163d8f..abc43a60 100644 --- a/proto-iokit-foohid/iokitprotocol.cpp +++ b/proto-iokit-foohid/iokitprotocol.cpp @@ -25,14 +25,14 @@ IOKitProtocol::IOKitProtocol() module_status IOKitProtocol::initialize() { if (!joystick) - return otr_tr("Load failure"); + return tr("Load failure"); if (joystick->hasError()) { QString msg = joystick->errorMessage(); if (msg.isEmpty()) - msg = otr_tr("Unknown error"); + msg = tr("Unknown error"); return error(msg); } diff --git a/proto-libevdev/ftnoir_libevdev_controls.ui b/proto-libevdev/ftnoir_libevdev_controls.ui index d2b86445..8aa52627 100644 --- a/proto-libevdev/ftnoir_libevdev_controls.ui +++ b/proto-libevdev/ftnoir_libevdev_controls.ui @@ -14,7 +14,7 @@ </rect> </property> <property name="windowTitle"> - <string>VJoy</string> + <string>libevdev options</string> </property> <property name="windowIcon"> <iconset> diff --git a/proto-libevdev/lang/nl_NL.ts b/proto-libevdev/lang/nl_NL.ts index 462ea6fc..d6a2c333 100644 --- a/proto-libevdev/lang/nl_NL.ts +++ b/proto-libevdev/lang/nl_NL.ts @@ -4,10 +4,6 @@ <context> <name>UICLibevdevControls</name> <message> - <source>VJoy</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Make sure rw for /dev/input/uinput!</source> <translation type="unfinished"></translation> </message> @@ -19,6 +15,10 @@ <source>Cancel</source> <translation type="unfinished"></translation> </message> + <message> + <source>libevdev options</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>evdev</name> diff --git a/proto-libevdev/lang/ru_RU.ts b/proto-libevdev/lang/ru_RU.ts index f659b1dd..c6310cd0 100644 --- a/proto-libevdev/lang/ru_RU.ts +++ b/proto-libevdev/lang/ru_RU.ts @@ -4,10 +4,6 @@ <context> <name>UICLibevdevControls</name> <message> - <source>VJoy</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Make sure rw for /dev/input/uinput!</source> <translation type="unfinished"></translation> </message> @@ -19,6 +15,10 @@ <source>Cancel</source> <translation type="unfinished"></translation> </message> + <message> + <source>libevdev options</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>evdev</name> diff --git a/proto-libevdev/lang/stub.ts b/proto-libevdev/lang/stub.ts index 5250e21a..ffafa2ec 100644 --- a/proto-libevdev/lang/stub.ts +++ b/proto-libevdev/lang/stub.ts @@ -4,10 +4,6 @@ <context> <name>UICLibevdevControls</name> <message> - <source>VJoy</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Make sure rw for /dev/input/uinput!</source> <translation type="unfinished"></translation> </message> @@ -19,6 +15,10 @@ <source>Cancel</source> <translation type="unfinished"></translation> </message> + <message> + <source>libevdev options</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>evdev</name> diff --git a/proto-libevdev/lang/zh_CN.ts b/proto-libevdev/lang/zh_CN.ts index 5250e21a..ffafa2ec 100644 --- a/proto-libevdev/lang/zh_CN.ts +++ b/proto-libevdev/lang/zh_CN.ts @@ -4,10 +4,6 @@ <context> <name>UICLibevdevControls</name> <message> - <source>VJoy</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Make sure rw for /dev/input/uinput!</source> <translation type="unfinished"></translation> </message> @@ -19,6 +15,10 @@ <source>Cancel</source> <translation type="unfinished"></translation> </message> + <message> + <source>libevdev options</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>evdev</name> diff --git a/proto-vjoystick/CMakeLists.txt b/proto-vjoystick/CMakeLists.txt index 3dbf5bea..5b6a1f07 100644 --- a/proto-vjoystick/CMakeLists.txt +++ b/proto-vjoystick/CMakeLists.txt @@ -11,6 +11,6 @@ if(WIN32 AND opentrack-intel) otr_module(proto-vjoy) target_link_libraries(opentrack-proto-vjoy ${lib}) target_include_directories(opentrack-proto-vjoy SYSTEM PUBLIC "${SDK_VJOYSTICK}/inc") - install(FILES "${dll}" DESTINATION ${opentrack-hier-pfx}) + install(FILES "${dll}" DESTINATION ${opentrack-libexec}) endif() endif() diff --git a/proto-vjoystick/lang/nl_NL.ts b/proto-vjoystick/lang/nl_NL.ts index a5ec2128..ff2eb9c9 100644 --- a/proto-vjoystick/lang/nl_NL.ts +++ b/proto-vjoystick/lang/nl_NL.ts @@ -20,10 +20,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>driver/SDK version mismatch</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Device missing. Add joystick #1.</source> <translation type="unfinished"></translation> </message> @@ -59,6 +55,10 @@ <source>Unknown error #%1.</source> <translation type="unfinished"></translation> </message> + <message> + <source>driver/SDK version mismatch (dll 0x%1, driver 0x%2)</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>vjoystick_metadata</name> diff --git a/proto-vjoystick/lang/ru_RU.ts b/proto-vjoystick/lang/ru_RU.ts index 47c93a83..3d867d07 100644 --- a/proto-vjoystick/lang/ru_RU.ts +++ b/proto-vjoystick/lang/ru_RU.ts @@ -20,10 +20,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>driver/SDK version mismatch</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Device missing. Add joystick #1.</source> <translation type="unfinished"></translation> </message> @@ -59,6 +55,10 @@ <source>Unknown error #%1.</source> <translation type="unfinished"></translation> </message> + <message> + <source>driver/SDK version mismatch (dll 0x%1, driver 0x%2)</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>vjoystick_metadata</name> diff --git a/proto-vjoystick/lang/stub.ts b/proto-vjoystick/lang/stub.ts index 078888fa..39a74043 100644 --- a/proto-vjoystick/lang/stub.ts +++ b/proto-vjoystick/lang/stub.ts @@ -20,10 +20,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>driver/SDK version mismatch</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Device missing. Add joystick #1.</source> <translation type="unfinished"></translation> </message> @@ -59,6 +55,10 @@ <source>Unknown error #%1.</source> <translation type="unfinished"></translation> </message> + <message> + <source>driver/SDK version mismatch (dll 0x%1, driver 0x%2)</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>vjoystick_metadata</name> diff --git a/proto-vjoystick/lang/zh_CN.ts b/proto-vjoystick/lang/zh_CN.ts index 078888fa..39a74043 100644 --- a/proto-vjoystick/lang/zh_CN.ts +++ b/proto-vjoystick/lang/zh_CN.ts @@ -20,10 +20,6 @@ <translation type="unfinished"></translation> </message> <message> - <source>driver/SDK version mismatch</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Device missing. Add joystick #1.</source> <translation type="unfinished"></translation> </message> @@ -59,6 +55,10 @@ <source>Unknown error #%1.</source> <translation type="unfinished"></translation> </message> + <message> + <source>driver/SDK version mismatch (dll 0x%1, driver 0x%2)</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>vjoystick_metadata</name> diff --git a/proto-vjoystick/vjoystick.cpp b/proto-vjoystick/vjoystick.cpp index f322ced9..2962a393 100644 --- a/proto-vjoystick/vjoystick.cpp +++ b/proto-vjoystick/vjoystick.cpp @@ -104,8 +104,11 @@ module_status vjoystick::initialize() if (!vJoyEnabled()) msg = tr("vjoystick won't work without the driver installed."); +#if 0 else if (WORD VerDll, VerDrv; !DriverMatch(&VerDll, &VerDrv)) - msg = tr("driver/SDK version mismatch"); + msg = tr("driver/SDK version mismatch (dll 0x%1, driver 0x%2)") + .arg(QString::number(VerDll, 16), QString::number(VerDrv, 16)); +#endif else { int code; diff --git a/proto-wine/CMakeLists.txt b/proto-wine/CMakeLists.txt index b0f18bb2..0beb50e1 100644 --- a/proto-wine/CMakeLists.txt +++ b/proto-wine/CMakeLists.txt @@ -16,7 +16,7 @@ if(NOT WIN32) set(my-rt) endif() file(GLOB wine-deps "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx") - #install(FILES ${wine-deps} DESTINATION "${opentrack-doc-src-pfx}/proto-wine") + #install(FILES ${wine-deps} DESTINATION "${opentrack-src}/proto-wine") add_custom_command( OUTPUT opentrack-wrapper-wine.exe.so DEPENDS ${wine-deps} @@ -27,7 +27,7 @@ if(NOT WIN32) add_custom_target(wine-wrapper DEPENDS opentrack-wrapper-wine.exe.so) add_dependencies(opentrack-proto-wine wine-wrapper) add_dependencies(wine-wrapper opentrack-compat) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/opentrack-wrapper-wine.exe.so" DESTINATION ${opentrack-hier-pfx}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/opentrack-wrapper-wine.exe.so" DESTINATION ${opentrack-libexec}) endif() endif() endif() diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index bed1fed3..af53ff1f 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -1,12 +1,15 @@ #include "ftnoir_protocol_wine.h" -#include <QString> -#include <string.h> -#include <math.h> #ifndef OTR_WINE_NO_WRAPPER # include "csv/csv.h" #endif #include "compat/library-path.hpp" +#include <cstring> +#include <cmath> + +#include <QString> +#include <QDebug> + wine::wine() = default; wine::~wine() @@ -16,11 +19,14 @@ wine::~wine() if (shm) { shm->stop = true; exit = wrapper.waitForFinished(100); + if (exit) + qDebug() << "proto/wine: wrapper exit code" << wrapper.exitCode(); } if (!exit) { - wrapper.kill(); - wrapper.waitForFinished(-1); + if (wrapper.state() != QProcess::NotRunning) + wrapper.kill(); + wrapper.waitForFinished(1000); } #endif //shm_unlink("/" WINE_SHM_NAME); @@ -64,11 +70,15 @@ module_status wine::initialize() if (s.proton_appid == 0) return error(tr("Must specify application id for Proton (Steam Play)")); - QProcessEnvironment make_steam_environ(const QString& proton_version, int appid); - QString proton_path(const QString& proton_version); + std::tuple<QProcessEnvironment, QString, bool> make_steam_environ(const QString& proton_path, int appid); + QString proton_path(const QString& proton_path); + + wine_path = proton_path(s.proton_path().toString()); + auto [proton_env, error_string, success] = make_steam_environ(s.proton_path().toString(), s.proton_appid); + env = proton_env; - wine_path = proton_path(s.proton_version); - env = make_steam_environ(s.proton_version, s.proton_appid); + if (!success) + return error(error_string); } else { @@ -79,7 +89,7 @@ module_status wine::initialize() wineprefix = qgetenv("HOME") + wineprefix.mid(1); if (wineprefix[0] != '/') - error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix)); + return error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix)); env.insert("WINEPREFIX", wineprefix); } @@ -89,6 +99,8 @@ module_status wine::initialize() if (s.fsync) env.insert("WINEFSYNC", "1"); + env.insert("OTR_WINE_PROTO", QString::number(s.protocol+1)); + wrapper.setProcessEnvironment(env); wrapper.setWorkingDirectory(OPENTRACK_BASE_PATH); wrapper.start(wine_path, { library_path + "opentrack-wrapper-wine.exe.so" }); diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h index 8175be03..f7346be9 100644 --- a/proto-wine/ftnoir_protocol_wine.h +++ b/proto-wine/ftnoir_protocol_wine.h @@ -9,9 +9,10 @@ #include "options/options.hpp" using namespace options; -#include <QString> -#include <QProcess> #include <QMutex> +#include <QProcess> +#include <QString> +#include <QVariant> #include <QDebug> @@ -24,8 +25,9 @@ struct settings : opts esync{b, "esync", true}; value<int> proton_appid{b, "proton-appid", 0}; - value<QString> proton_version{b, "proton-version", {} }, - wineprefix{b, "wineprefix", "~/.wine"}; + value<QVariant> proton_path{b, "proton-version", {} }; + value<QString> wineprefix{b, "wineprefix", "~/.wine"}; + value<int> protocol{b, "protocol", 2}; }; class wine : TR, public IProtocol diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp index f1cb01c2..a954a752 100644 --- a/proto-wine/ftnoir_protocol_wine_dialog.cpp +++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp @@ -1,25 +1,37 @@ #include "ftnoir_protocol_wine.h" #include <QDebug> +#include <QDir> + #include "api/plugin-api.hpp" -static const char* proton_versions[] = { - "4.11", "4.2", "3.16", "3.7", +static const char* proton_paths[] = { + "/.steam/steam/steamapps/common", + "/.steam/root/compatibilitytools.d", + "/.local/share/Steam/steamapps/common", }; FTControls::FTControls() { ui.setupUi(this); - for (const char* version : proton_versions) - ui.proton_version->addItem(version, QVariant{version}); - - tie_setting(s.proton_version, ui.proton_version); + for (const char* path : proton_paths) { + QDir dir(QDir::homePath() + path); + dir.setFilter(QDir::Dirs); + dir.setNameFilters({ "Proton*" }); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + ui.proton_version->addItem(fileInfo.fileName(), QVariant{fileInfo.filePath()}); + } + } + tie_setting(s.proton_path, ui.proton_version); tie_setting(s.variant_wine, ui.variant_wine); tie_setting(s.variant_proton, ui.variant_proton); tie_setting(s.esync, ui.esync); tie_setting(s.fsync, ui.fsync); tie_setting(s.proton_appid, ui.proton_appid); tie_setting(s.wineprefix, ui.wineprefix); + tie_setting(s.protocol, ui.protocol_selection); connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &FTControls::doOK); connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &FTControls::doCancel); @@ -36,4 +48,3 @@ void FTControls::doCancel() s.b->reload(); close(); } - diff --git a/proto-wine/ftnoir_winecontrols.ui b/proto-wine/ftnoir_winecontrols.ui index a0a1e071..e9541447 100644 --- a/proto-wine/ftnoir_winecontrols.ui +++ b/proto-wine/ftnoir_winecontrols.ui @@ -9,8 +9,8 @@ <rect> <x>0</x> <y>0</y> - <width>544</width> - <height>410</height> + <width>528</width> + <height>424</height> </rect> </property> <property name="windowTitle"> @@ -33,6 +33,19 @@ <string>Wine variant</string> </property> <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QRadioButton" name="variant_wine"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Wine (system)</string> + </property> + </widget> + </item> <item row="2" column="1" alignment="Qt::AlignRight"> <widget class="QComboBox" name="proton_version"> <property name="sizePolicy"> @@ -49,16 +62,19 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QRadioButton" name="variant_wine"> + <item row="0" column="1"> + <widget class="QLineEdit" name="wineprefix"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Wine (system)</string> + <property name="minimumSize"> + <size> + <width>286</width> + <height>0</height> + </size> </property> </widget> </item> @@ -75,22 +91,6 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="wineprefix"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>286</width> - <height>0</height> - </size> - </property> - </widget> - </item> </layout> </widget> </item> @@ -100,6 +100,9 @@ <string>Advanced</string> </property> <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>6</number> + </property> <item> <widget class="QCheckBox" name="esync"> <property name="sizePolicy"> @@ -133,18 +136,80 @@ </widget> </item> <item> + <widget class="QWidget" name="widget_2" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Protocol</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="protocol_selection"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Freetrack</string> + </property> + </item> + <item> + <property name="text"> + <string>NPClient</string> + </property> + </item> + <item> + <property name="text"> + <string>Both</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + <item> <widget class="QWidget" name="widget" native="true"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <widget class="QLabel" name="label"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> diff --git a/proto-wine/lang/nl_NL.ts b/proto-wine/lang/nl_NL.ts index f71d8ad7..e2183cc8 100644 --- a/proto-wine/lang/nl_NL.ts +++ b/proto-wine/lang/nl_NL.ts @@ -39,6 +39,22 @@ <source>Proton (Steam Play)</source> <translation type="unfinished"></translation> </message> + <message> + <source>Protocol</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Freetrack</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>NPClient</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Both</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> diff --git a/proto-wine/lang/ru_RU.ts b/proto-wine/lang/ru_RU.ts index 9937083f..f3b44bd2 100644 --- a/proto-wine/lang/ru_RU.ts +++ b/proto-wine/lang/ru_RU.ts @@ -39,6 +39,22 @@ <source>Proton (Steam Play)</source> <translation type="unfinished"></translation> </message> + <message> + <source>Protocol</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Freetrack</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>NPClient</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Both</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> diff --git a/proto-wine/lang/stub.ts b/proto-wine/lang/stub.ts index 9b74a44d..dd4f946f 100644 --- a/proto-wine/lang/stub.ts +++ b/proto-wine/lang/stub.ts @@ -39,6 +39,22 @@ <source>Proton (Steam Play)</source> <translation type="unfinished"></translation> </message> + <message> + <source>Protocol</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Freetrack</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>NPClient</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Both</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> diff --git a/proto-wine/lang/zh_CN.ts b/proto-wine/lang/zh_CN.ts index 9b74a44d..dd4f946f 100644 --- a/proto-wine/lang/zh_CN.ts +++ b/proto-wine/lang/zh_CN.ts @@ -39,6 +39,22 @@ <source>Proton (Steam Play)</source> <translation type="unfinished"></translation> </message> + <message> + <source>Protocol</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Freetrack</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>NPClient</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Both</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> diff --git a/proto-wine/opentrack-wrapper-wine-main.cxx b/proto-wine/opentrack-wrapper-wine-main.cxx index 3df3abc7..9248a212 100644 --- a/proto-wine/opentrack-wrapper-wine-main.cxx +++ b/proto-wine/opentrack-wrapper-wine-main.cxx @@ -5,7 +5,6 @@ #include <cstdio> #include "freetrackclient/fttypes.h" -#include "wine-shm.h" #include "compat/export.hpp" enum Axis { @@ -14,6 +13,7 @@ enum Axis { #define __WINE_OLE2_H #include "compat/shm.h" +#include "wine-shm.h" void create_registry_key(void); @@ -42,7 +42,6 @@ private: void* mem; void *hMutex, *hMapFile; }; -#include <windows.h> int main(void) { diff --git a/proto-wine/opentrack-wrapper-wine-windows.cxx b/proto-wine/opentrack-wrapper-wine-windows.cxx index 88ced502..c1d552e1 100644 --- a/proto-wine/opentrack-wrapper-wine-windows.cxx +++ b/proto-wine/opentrack-wrapper-wine-windows.cxx @@ -4,18 +4,22 @@ #define shm_wrapper ShmWine #define __WINE_OLE2_H +// OSX sdk 10.8 build error otherwise +#undef _LIBCPP_MSVCRT + #include "compat/shm.h" #include "compat/shm.cpp" #include "wine-shm.h" #include "compat/library-path.hpp" +#include <cstdlib> #include <cstring> +#include <sysexits.h> using std::strcat; -static void write_path(const char* key, const char* subkey) +static void write_path(const char* key, const char* subkey, bool path) { - char dir[8192]; - dir[sizeof(dir)-1] = '\0'; + char dir[8192] {}; if (GetCurrentDirectoryA(8192, dir) < 8190) { @@ -36,13 +40,32 @@ static void write_path(const char* key, const char* subkey) // there's always a leading and trailing slash strcat(dir, OPENTRACK_LIBRARY_PATH); //strcat(dir, "/"); + if (!path) + dir[0] = '\0'; (void) RegSetValueExA(hkpath, subkey, 0, REG_SZ, (BYTE*) dir, strlen(dir) + 1); RegCloseKey(hkpath); } } } -void create_registry_key(void) { - write_path("Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", "Path"); - write_path("Software\\Freetrack\\FreeTrackClient", "Path"); +void create_registry_key(void) +{ + bool use_freetrack, use_npclient; + const char* env = getenv("OTR_WINE_PROTO"); + char* endptr; + if (!env) env = ""; + int selection = strtol(env, &endptr, 10); + if (*endptr) + selection = 0; + + switch (selection) + { + default: std::exit(EX_USAGE); + case 1: use_freetrack = true, use_npclient = false; break; + case 2: use_freetrack = false, use_npclient = true; break; + case 3: use_freetrack = true, use_npclient = true; break; + } + + write_path("Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", "Path", use_npclient); + write_path("Software\\Freetrack\\FreeTrackClient", "Path", use_freetrack); } diff --git a/proto-wine/proton.cpp b/proto-wine/proton.cpp index 15306d26..5ecd1f93 100644 --- a/proto-wine/proton.cpp +++ b/proto-wine/proton.cpp @@ -7,56 +7,86 @@ #ifndef OTR_WINE_NO_WRAPPER -#include <QtGlobal> -#include <QString> +#include <QDebug> +#include <QDir> +#include <QFileInfo> #include <QProcessEnvironment> +#include <QtGlobal> + + +static const char* steam_paths[] = { + "/.steam/steam/steamapps/compatdata", + "/.local/share/Steam/steamapps/compatdata", +}; + +static const char* runtime_paths[] = { + "/.local/share/Steam/ubuntu12_32/steam-runtime", + "/.steam/ubuntu12_32/steam-runtime", +}; -QProcessEnvironment make_steam_environ(const QString& proton_version, int appid) + +std::tuple<QProcessEnvironment, QString, bool> make_steam_environ(const QString& proton_path, int appid) { - auto ret = QProcessEnvironment::systemEnvironment(); + using ret = std::tuple<QProcessEnvironment, QString, bool>; + auto env = QProcessEnvironment::systemEnvironment(); + QString error = ""; QString home = qgetenv("HOME"); + QString runtime_path, app_wineprefix; auto expand = [&](QString x) { - x.replace("HOME", home); - x.replace("PROTON", proton_version); - return x; - }; + x.replace("HOME", home); + x.replace("PROTON_PATH", proton_path); + x.replace("RUNTIME_PATH", runtime_path); + return x; + }; + + for (const char* path : runtime_paths) { + QDir dir(QDir::homePath() + path); + if (dir.exists()) + runtime_path = dir.absolutePath(); + } + + if (runtime_path.isEmpty()) + error = QString("Couldn't find a Steam runtime."); + + for (const char* path : steam_paths) { + QDir dir(QDir::homePath() + path + expand("/%1/pfx").arg(appid)); + if (dir.exists()) + app_wineprefix = dir.absolutePath(); + } + if (app_wineprefix.isEmpty()) + error = QString("Couldn't find a Wineprefix for AppId %1").arg(appid); QString path = expand( - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/bin" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/bin" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/bin" + ":PROTON_PATH/dist/bin" ); path += ':'; path += qgetenv("PATH"); - ret.insert("PATH", path); + env.insert("PATH", path); QString library_path = expand( - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/lib" - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/lib64" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_32" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_64" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/lib/x86_64-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/lib" + ":PROTON_PATH/dist/lib" + ":PROTON_PATH/dist/lib64" + ":RUNTIME_PATH/pinned_libs_32" + ":RUNTIME_PATH/pinned_libs_64" + ":RUNTIME_PATH/i386/lib/i386-linux-gnu" + ":RUNTIME_PATH/i386/lib" + ":RUNTIME_PATH/i386/usr/lib/i386-linux-gnu" + ":RUNTIME_PATH/i386/usr/lib" + ":RUNTIME_PATH/amd64/lib/x86_64-linux-gnu" + ":RUNTIME_PATH/amd64/lib" + ":RUNTIME_PATH/amd64/usr/lib/x86_64-linux-gnu" + ":RUNTIME_PATH/amd64/usr/lib" ); library_path += ':'; library_path += qgetenv("LD_LIBRARY_PATH"); - ret.insert("LD_LIBRARY_PATH", library_path); - ret.insert("WINEPREFIX", expand("HOME/.local/share/Steam/steamapps/compatdata/%1/pfx").arg(appid)); + env.insert("LD_LIBRARY_PATH", library_path); + env.insert("WINEPREFIX", app_wineprefix); - return ret; + return ret(env, error, error.isEmpty()); } -QString proton_path(const QString& proton_version) +QString proton_path(const QString& proton_path) { - QString wine_path = "HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/bin/wine"; - wine_path.replace("HOME", qgetenv("HOME")); - wine_path.replace("PROTON", proton_version); - return wine_path; + return proton_path + "/dist/bin/wine"; } #endif diff --git a/proto-wine/wine-shm.h b/proto-wine/wine-shm.h index 536f647f..62e8bbec 100644 --- a/proto-wine/wine-shm.h +++ b/proto-wine/wine-shm.h @@ -8,17 +8,10 @@ # pragma clang diagnostic ignored "-Wreserved-id-macro" #endif -// OSX sdk 10.8 build error otherwise -#undef _LIBCPP_MSVCRT - #ifdef __clang__ # pragma clang diagnostic pop #endif -#include <memory> - -template<typename t> using ptr = std::shared_ptr<t>; - struct WineSHM { double data[6]; int gameid, gameid2; diff --git a/qxt-mini/CMakeLists.txt b/qxt-mini/CMakeLists.txt index 21b2b160..1b2496f6 100644 --- a/qxt-mini/CMakeLists.txt +++ b/qxt-mini/CMakeLists.txt @@ -3,7 +3,9 @@ if(UNIX OR APPLE) include_directories(SYSTEM ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) otr_module(qxt-mini NO-COMPAT BIN) if(APPLE) - target_link_options(${self} PUBLIC -framework Carbon -framework CoreFoundation) + find_library(CoreFoundation CoreFoundation) + find_library(Carbon Carbon) + target_link_options(${self} PUBLIC -framework Carbon -I ${CoreFoundation}) else() otr_pkgconfig(${self} x11 xcb xproto) endif() diff --git a/qxt-mini/qxtglobalshortcut.cpp b/qxt-mini/qxtglobalshortcut.cpp index 69514f88..52758f71 100644 --- a/qxt-mini/qxtglobalshortcut.cpp +++ b/qxt-mini/qxtglobalshortcut.cpp @@ -36,6 +36,10 @@ #include <QtDebug> #include <QtGlobal> +#ifdef __GNUG__ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; void QxtGlobalShortcutPrivate::event_filter_installer::ensure_event_filter() @@ -55,7 +59,7 @@ void QxtGlobalShortcutPrivate::event_filter_installer::ensure_event_filter() QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate(QxtGlobalShortcutPrivate::tag) : keystate(false), enabled(false), key(Qt::Key(0)), mods(Qt::NoModifier) { - qDebug() << "qxt-mini: adding event filter"; + //qDebug() << "qxt-mini: adding event filter"; } QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : diff --git a/qxt-mini/qxtglobalshortcut_x11.cpp b/qxt-mini/qxtglobalshortcut_x11.cpp index 6647d803..01894cfc 100644 --- a/qxt-mini/qxtglobalshortcut_x11.cpp +++ b/qxt-mini/qxtglobalshortcut_x11.cpp @@ -355,9 +355,7 @@ bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, (void) XkbSetDetectableAutoRepeat(x11.display(), True, &val); - if (val) - qDebug() << "qxt-mini: fixed x11 autorepeat"; - else + if (!val) qDebug() << "qxt-mini: can't fix x11 autorepeat"; } } diff --git a/sdk-paths-sthalik@Clang-Linux.cmake b/sdk-paths-sthalik@Clang-Linux.cmake index b72a7a81..fb6e64d9 100644 --- a/sdk-paths-sthalik@Clang-Linux.cmake +++ b/sdk-paths-sthalik@Clang-Linux.cmake @@ -13,7 +13,8 @@ add_compile_options( -Wno-padded -Wno-shadow-field -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-extra-semi-stmt # for qt moc -) + -Wno-implicit-int-float-conversion + -Wno-alloca) set(base-flags "-Wall -Wextra -Wpedantic") @@ -33,8 +34,14 @@ set(CMAKE_C_FLAGS_RELEASE "${opt-flags} ${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb ${CMAKE_CXX_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_DEBUG "-ggdb ${CMAKE_C_FLAGS_DEBUG}") +set(CMAKE_C_FLAGS "-ggdb") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") + +add_compile_options("-emit-llvm") +add_link_options("-fuse-ld=lld") + foreach(x EXE MODULE SHARED) - set(CMAKE_${x}_LINKER_FLAGS "-fuse-ld=lld ${CMAKE_${x}_LINKER_FLAGS}") + set(CMAKE_${x}_LINKER_FLAGS "${CMAKE_${x}_LINKER_FLAGS}") endforeach() function(set_sdk var path) @@ -46,4 +53,3 @@ set_sdk(SDK_HYDRA "SixenseSDK") set_sdk(SDK_VALVE_STEAMVR "steamvr") set_sdk(SDK_WINE TRUE) set_sdk(SDK_XPLANE "X-Plane-SDK") - diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake index 7d87287a..f1fd3264 100644 --- a/sdk-paths-sthalik@MSVC-windows.cmake +++ b/sdk-paths-sthalik@MSVC-windows.cmake @@ -31,11 +31,15 @@ setq(SDK_HYDRA "SixenseSDK") setq(SDK_KINECT20 "Kinect-v2.0") setq(SDK_LIBUSB "libusb-msvc-x86") setq(SDK_PS3EYEDRIVER "PS3EYEDriver") -setq(SDK_REALSENSE "RSSDK-R2") -setq(SDK_RIFT_140 "LibOVR-140/build") +setq(SDK_REALSENSE "RSSDK-R3") +setq(SDK_RIFT_140 "ovr_sdk_win_1.43.0/LibOVR") setq(SDK_VALVE_STEAMVR "steamvr") setq(SDK_VJOYSTICK "vjoystick") +set(Qt5_DIR "c:/qt/qt-5.14.0/lib/cmake/Qt5" CACHE PATH "" FORCE) +set(Qt5Core_DIR "${Qt5_DIR}Core" CACHE PATH "" FORCE) +set(Qt5Gui_DIR "${Qt5_DIR}Gui" CACHE PATH "" FORCE) + if(CMAKE_GENERATOR STREQUAL "NMake Makefiles") set(CMAKE_MAKE_PROGRAM "jom" CACHE STRING "" FORCE) endif() diff --git a/spline/spline-widget.cpp b/spline/spline-widget.cpp index 2429ffc3..7aeaf590 100644 --- a/spline/spline-widget.cpp +++ b/spline/spline-widget.cpp @@ -5,10 +5,12 @@ #include <algorithm> #include <QPainter> +#include <QPainterPath> #include <QPixmap> #include <QString> #include <QToolTip> #include <QtEvents> +#include <QPainterPath> #include <QDebug> @@ -118,6 +120,8 @@ void spline_widget::drawBackground() double space_width = metrics.averageCharWidth(); #endif + painter.setPen(palette().text().color()); + // vertical grid for (int i = 0; i <= maxy; i += ystep) { @@ -156,7 +160,7 @@ void spline_widget::drawBackground() #endif painter.drawText(QPointF(x - advance/2 - rect.left(), - pixel_bounds.height() - rect.top() + rect.height()), + pixel_bounds.bottom() + metrics.lineSpacing()), text); } } diff --git a/tracker-aruco/CMakeLists.txt b/tracker-aruco/CMakeLists.txt index 69fe7aa1..d3c1f28c 100644 --- a/tracker-aruco/CMakeLists.txt +++ b/tracker-aruco/CMakeLists.txt @@ -29,7 +29,7 @@ if(OpenCV_FOUND) endif() maybe_add_static_define() - otr_install_lib("${SDK_ARUCO_LIBPATH}" "${opentrack-hier-pfx}") + otr_install_lib("${SDK_ARUCO_LIBPATH}" "${opentrack-libexec}") otr_module(tracker-aruco) target_include_directories(${self} SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS} "${dir}") diff --git a/tracker-aruco/aruco-trackercontrols.ui b/tracker-aruco/aruco-trackercontrols.ui index 9c3bd78a..4d40b6ef 100644 --- a/tracker-aruco/aruco-trackercontrols.ui +++ b/tracker-aruco/aruco-trackercontrols.ui @@ -113,6 +113,11 @@ </item> <item> <property name="text"> + <string>1280x720</string> + </property> + </item> + <item> + <property name="text"> <string>Default (not recommended!)</string> </property> </item> diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 0cdf4c2c..6e94e618 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -56,6 +56,7 @@ static const resolution_tuple resolution_choices[] = { { 640, 480 }, { 320, 240 }, + { 1280, 720 }, { 0, 0 } }; @@ -157,9 +158,7 @@ static int enum_to_fps(int value) bool aruco_tracker::open_camera() { - int rint = s.resolution; - if (rint < 0 || rint >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple))) - rint = 0; + int rint = std::clamp(*s.resolution, 0, (int)std::size(resolution_choices)-1); resolution_tuple res = resolution_choices[rint]; int fps = enum_to_fps(s.force_fps); diff --git a/tracker-aruco/lang/nl_NL.ts b/tracker-aruco/lang/nl_NL.ts index 87040565..c9213ea0 100644 --- a/tracker-aruco/lang/nl_NL.ts +++ b/tracker-aruco/lang/nl_NL.ts @@ -59,6 +59,10 @@ <source>Toggle calibration</source> <translation>Schakel tussen kalibratie</translation> </message> + <message> + <source>1280x720</source> + <translation>1280x720</translation> + </message> </context> <context> <name>aruco_dialog</name> diff --git a/tracker-aruco/lang/ru_RU.ts b/tracker-aruco/lang/ru_RU.ts index 57c8170d..f78a7cae 100644 --- a/tracker-aruco/lang/ru_RU.ts +++ b/tracker-aruco/lang/ru_RU.ts @@ -59,6 +59,10 @@ <source>Toggle calibration</source> <translation type="unfinished"></translation> </message> + <message> + <source>1280x720</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>aruco_dialog</name> diff --git a/tracker-aruco/lang/stub.ts b/tracker-aruco/lang/stub.ts index 67cb36b8..82ccd296 100644 --- a/tracker-aruco/lang/stub.ts +++ b/tracker-aruco/lang/stub.ts @@ -59,6 +59,10 @@ <source>Toggle calibration</source> <translation type="unfinished"></translation> </message> + <message> + <source>1280x720</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>aruco_dialog</name> diff --git a/tracker-aruco/lang/zh_CN.ts b/tracker-aruco/lang/zh_CN.ts index b5093b4e..e060c387 100644 --- a/tracker-aruco/lang/zh_CN.ts +++ b/tracker-aruco/lang/zh_CN.ts @@ -59,6 +59,10 @@ <source>Toggle calibration</source> <translation type="unfinished"></translation> </message> + <message> + <source>1280x720</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>aruco_dialog</name> diff --git a/tracker-easy/CMakeLists.txt b/tracker-easy/CMakeLists.txt index 670b9003..c377dd9c 100644 --- a/tracker-easy/CMakeLists.txt +++ b/tracker-easy/CMakeLists.txt @@ -9,7 +9,7 @@ if(OpenCV_FOUND) OUTPUT_VARIABLE krap) if(tracker-easy_ocv-check) foreach(k video highgui) - otr_install_lib("opencv_${k}" "${opentrack-hier-pfx}") + otr_install_lib("opencv_${k}" "${opentrack-libexec}") endforeach() if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/tracker-easy/lang/nl_NL.ts b/tracker-easy/lang/nl_NL.ts index 9c4e1843..775ec4d9 100644 --- a/tracker-easy/lang/nl_NL.ts +++ b/tracker-easy/lang/nl_NL.ts @@ -4,17 +4,13 @@ <context> <name>EasyTracker::Metadata</name> <message> - <source>Easy Tracker 1.0</source> + <source>Easy Tracker 1.1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>UICPTClientControls</name> <message> - <source>PointTracker Settings</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Camera</source> <translation type="unfinished"></translation> </message> @@ -151,79 +147,103 @@ <translation type="unfinished"></translation> </message> <message> - <source>Top Right</source> + <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top Left</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Left</source> + <source>Auto center</source> <translation type="unfinished"></translation> </message> <message> - <source>Vertex count</source> + <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Three vertices</source> + <source>Auto center timeout</source> <translation type="unfinished"></translation> </message> <message> - <source>Four vertices</source> + <source>If no valid pose can be determined after that much time the center pose will be used.</source> <translation type="unfinished"></translation> </message> <message> - <source>Five vertices</source> + <source> ms</source> <translation type="unfinished"></translation> </message> <message> - <source>Center</source> + <source>Easy Tracker Settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Right</source> + <source>Model type:</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> + <source>Hat three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> + <source>Hat four vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> + <source>Hat five vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> + <source>Clip three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center</source> + <source>Vertices: </source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> + <source>Top:</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center timeout</source> + <source>Right:</source> <translation type="unfinished"></translation> </message> <message> - <source>If no valid pose can be determined after that much time the center pose will be used.</source> + <source>Left:</source> <translation type="unfinished"></translation> </message> <message> - <source> ms</source> + <source>Center:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top right:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top left:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip top:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip middle:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip bottom:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-easy/lang/ru_RU.ts b/tracker-easy/lang/ru_RU.ts index 6499415f..2ae262a5 100644 --- a/tracker-easy/lang/ru_RU.ts +++ b/tracker-easy/lang/ru_RU.ts @@ -4,17 +4,13 @@ <context> <name>EasyTracker::Metadata</name> <message> - <source>Easy Tracker 1.0</source> + <source>Easy Tracker 1.1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>UICPTClientControls</name> <message> - <source>PointTracker Settings</source> - <translation>Настройки PointTracker</translation> - </message> - <message> <source>Camera</source> <translation>Камера</translation> </message> @@ -151,79 +147,103 @@ <translation type="unfinished"></translation> </message> <message> - <source>Top Right</source> + <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top Left</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Left</source> + <source>Auto center</source> <translation type="unfinished"></translation> </message> <message> - <source>Vertex count</source> + <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Three vertices</source> + <source>Auto center timeout</source> <translation type="unfinished"></translation> </message> <message> - <source>Four vertices</source> + <source>If no valid pose can be determined after that much time the center pose will be used.</source> <translation type="unfinished"></translation> </message> <message> - <source>Five vertices</source> + <source> ms</source> <translation type="unfinished"></translation> </message> <message> - <source>Center</source> + <source>Easy Tracker Settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Right</source> + <source>Model type:</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> + <source>Hat three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> + <source>Hat four vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> + <source>Hat five vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> + <source>Clip three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center</source> + <source>Vertices: </source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> + <source>Top:</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center timeout</source> + <source>Right:</source> <translation type="unfinished"></translation> </message> <message> - <source>If no valid pose can be determined after that much time the center pose will be used.</source> + <source>Left:</source> <translation type="unfinished"></translation> </message> <message> - <source> ms</source> + <source>Center:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top right:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top left:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip top:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip middle:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip bottom:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-easy/lang/stub.ts b/tracker-easy/lang/stub.ts index 7b6facec..b10f5885 100644 --- a/tracker-easy/lang/stub.ts +++ b/tracker-easy/lang/stub.ts @@ -4,17 +4,13 @@ <context> <name>EasyTracker::Metadata</name> <message> - <source>Easy Tracker 1.0</source> + <source>Easy Tracker 1.1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>UICPTClientControls</name> <message> - <source>PointTracker Settings</source> - <translation type="unfinished"></translation> - </message> - <message> <source>Camera</source> <translation type="unfinished"></translation> </message> @@ -151,79 +147,103 @@ <translation type="unfinished"></translation> </message> <message> - <source>Top Right</source> + <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top Left</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Left</source> + <source>Auto center</source> <translation type="unfinished"></translation> </message> <message> - <source>Vertex count</source> + <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Three vertices</source> + <source>Auto center timeout</source> <translation type="unfinished"></translation> </message> <message> - <source>Four vertices</source> + <source>If no valid pose can be determined after that much time the center pose will be used.</source> <translation type="unfinished"></translation> </message> <message> - <source>Five vertices</source> + <source> ms</source> <translation type="unfinished"></translation> </message> <message> - <source>Center</source> + <source>Easy Tracker Settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Right</source> + <source>Model type:</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> + <source>Hat three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> + <source>Hat four vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> + <source>Hat five vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> + <source>Clip three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center</source> + <source>Vertices: </source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> + <source>Top:</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center timeout</source> + <source>Right:</source> <translation type="unfinished"></translation> </message> <message> - <source>If no valid pose can be determined after that much time the center pose will be used.</source> + <source>Left:</source> <translation type="unfinished"></translation> </message> <message> - <source> ms</source> + <source>Center:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top right:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top left:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip top:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip middle:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip bottom:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-easy/lang/zh_CN.ts b/tracker-easy/lang/zh_CN.ts index bbd8aff1..71fc6368 100644 --- a/tracker-easy/lang/zh_CN.ts +++ b/tracker-easy/lang/zh_CN.ts @@ -4,17 +4,13 @@ <context> <name>EasyTracker::Metadata</name> <message> - <source>Easy Tracker 1.0</source> + <source>Easy Tracker 1.1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>UICPTClientControls</name> <message> - <source>PointTracker Settings</source> - <translation>PointTracker设置</translation> - </message> - <message> <source>Camera</source> <translation>摄像头</translation> </message> @@ -151,79 +147,103 @@ <translation type="unfinished"></translation> </message> <message> - <source>Top Right</source> + <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Top Left</source> + <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Left</source> + <source>Auto center</source> <translation type="unfinished"></translation> </message> <message> - <source>Vertex count</source> + <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> <translation type="unfinished"></translation> </message> <message> - <source>Three vertices</source> + <source>Auto center timeout</source> <translation type="unfinished"></translation> </message> <message> - <source>Four vertices</source> + <source>If no valid pose can be determined after that much time the center pose will be used.</source> <translation type="unfinished"></translation> </message> <message> - <source>Five vertices</source> + <source> ms</source> <translation type="unfinished"></translation> </message> <message> - <source>Center</source> + <source>Easy Tracker Settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Right</source> + <source>Model type:</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">X</span></p></body></html></source> + <source>Hat three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Y</span></p></body></html></source> + <source>Hat four vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-size:12pt;">Z</span></p></body></html></source> + <source>Hat five vertices</source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> + <source>Clip three vertices</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center</source> + <source>Vertices: </source> <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>Use P3P or AP3P for three and four points setup. Use EPNP or ITERATIVE for five points setup. Inconsistent configuration will result in undefined behavior.</p></body></html></source> + <source>Top:</source> <translation type="unfinished"></translation> </message> <message> - <source>Auto center timeout</source> + <source>Right:</source> <translation type="unfinished"></translation> </message> <message> - <source>If no valid pose can be determined after that much time the center pose will be used.</source> + <source>Left:</source> <translation type="unfinished"></translation> </message> <message> - <source> ms</source> + <source>Center:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top right:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Top left:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip top:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip middle:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clip bottom:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-easy/module.cpp b/tracker-easy/module.cpp index 3a9df22b..8fcfeae1 100644 --- a/tracker-easy/module.cpp +++ b/tracker-easy/module.cpp @@ -6,7 +6,7 @@ namespace EasyTracker { - QString Metadata::name() { return tr("Easy Tracker 1.0"); } + QString Metadata::name() { return tr("Easy Tracker 1.1"); } QIcon Metadata::icon() { return QIcon(":/Resources/easy-tracker-logo.png"); } } diff --git a/tracker-easy/settings.h b/tracker-easy/settings.h index b0f14417..4141ebe0 100644 --- a/tracker-easy/settings.h +++ b/tracker-easy/settings.h @@ -30,6 +30,7 @@ namespace EasyTracker { value<bool> iCustomModelThree{ b, "iCustomModelThree", true }; value<bool> iCustomModelFour{ b, "iCustomModelFour", false }; value<bool> iCustomModelFive{ b, "iCustomModelFive", false }; + value<bool> iClipModelThree{ b, "iClipModelThree", false }; // Custom model vertices value<int> iVertexTopX{ b, "iVertexTopX", 0 }, iVertexTopY{ b, "iVertexTopY", 0 }, iVertexTopZ{ b, "iVertexTopZ", 0 }; @@ -38,7 +39,10 @@ namespace EasyTracker { value<int> iVertexCenterX{ b, "iVertexCenterX", 0 }, iVertexCenterY{ b, "iVertexCenterY", 0 }, iVertexCenterZ{ b, "iVertexCenterZ", 0 }; value<int> iVertexTopRightX{ b, "iVertexTopRightX", 0 }, iVertexTopRightY{ b, "iVertexTopRightY", 0 }, iVertexTopRightZ{ b, "iVertexTopRightZ", 0 }; value<int> iVertexTopLeftX{ b, "iVertexTopLeftX", 0 }, iVertexTopLeftY{ b, "iVertexTopLeftY", 0 }, iVertexTopLeftZ{ b, "iVertexTopLeftZ", 0 }; - + // Clip model vertices + value<int> iVertexClipTopX{ b, "iVertexClipTopX", 0 }, iVertexClipTopY{ b, "iVertexClipTopY", 0 }, iVertexClipTopZ{ b, "iVertexClipTopZ", 0 }; + value<int> iVertexClipMiddleX{ b, "iVertexClipMiddleX", 0 }, iVertexClipMiddleY{ b, "iVertexClipMiddleY", 0 }, iVertexClipMiddleZ{ b, "iVertexClipMiddleZ", 0 }; + value<int> iVertexClipBottomX{ b, "iVertexClipBottomX", 0 }, iVertexClipBottomY{ b, "iVertexClipBottomY", 0 }, iVertexClipBottomZ{ b, "iVertexClipBottomZ", 0 }; value<int> fov{ b, "camera-fov", 56 }; diff --git a/tracker-easy/tracker-easy-dialog.cpp b/tracker-easy/tracker-easy-dialog.cpp index 4a49e194..b0870b50 100644 --- a/tracker-easy/tracker-easy-dialog.cpp +++ b/tracker-easy/tracker-easy-dialog.cpp @@ -68,6 +68,19 @@ namespace EasyTracker tie_setting(s.iVertexTopLeftY, ui.iSpinVertexTopLeftY); tie_setting(s.iVertexTopLeftZ, ui.iSpinVertexTopLeftZ); + // Clip model + tie_setting(s.iVertexClipTopX, ui.iSpinVertexClipTopX); + tie_setting(s.iVertexClipTopY, ui.iSpinVertexClipTopY); + tie_setting(s.iVertexClipTopZ, ui.iSpinVertexClipTopZ); + + tie_setting(s.iVertexClipMiddleX, ui.iSpinVertexClipMiddleX); + tie_setting(s.iVertexClipMiddleY, ui.iSpinVertexClipMiddleY); + tie_setting(s.iVertexClipMiddleZ, ui.iSpinVertexClipMiddleZ); + + tie_setting(s.iVertexClipBottomX, ui.iSpinVertexClipBottomX); + tie_setting(s.iVertexClipBottomY, ui.iSpinVertexClipBottomY); + tie_setting(s.iVertexClipBottomZ, ui.iSpinVertexClipBottomZ); + tie_setting(s.fov, ui.fov); tie_setting(s.debug, ui.debug); @@ -87,10 +100,12 @@ namespace EasyTracker connect(ui.iRadioButtonCustomModelThree, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); connect(ui.iRadioButtonCustomModelFour, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); connect(ui.iRadioButtonCustomModelFive, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); + connect(ui.iRadioButtonClipModelThree, &QRadioButton::clicked, this, &Dialog::UpdateCustomModelControls); tie_setting(s.iCustomModelThree, ui.iRadioButtonCustomModelThree); tie_setting(s.iCustomModelFour, ui.iRadioButtonCustomModelFour); tie_setting(s.iCustomModelFive, ui.iRadioButtonCustomModelFive); + tie_setting(s.iClipModelThree, ui.iRadioButtonClipModelThree); for (unsigned k = 0; k < cv::SOLVEPNP_MAX_COUNT; k++) @@ -111,20 +126,49 @@ namespace EasyTracker ui.iGroupBoxCenter->hide(); ui.iGroupBoxTopRight->hide(); ui.iGroupBoxTopLeft->hide(); + ui.iGroupBoxTop->show(); + ui.iGroupBoxRight->show(); + ui.iGroupBoxLeft->show(); + ui.iGroupBoxClipTop->hide(); + ui.iGroupBoxClipMiddle->hide(); + ui.iGroupBoxClipBottom->hide(); } else if (ui.iRadioButtonCustomModelFour->isChecked()) { ui.iGroupBoxCenter->show(); ui.iGroupBoxTopRight->hide(); ui.iGroupBoxTopLeft->hide(); + ui.iGroupBoxTop->show(); + ui.iGroupBoxRight->show(); + ui.iGroupBoxLeft->show(); + ui.iGroupBoxClipTop->hide(); + ui.iGroupBoxClipMiddle->hide(); + ui.iGroupBoxClipBottom->hide(); } else if (ui.iRadioButtonCustomModelFive->isChecked()) { ui.iGroupBoxCenter->hide(); ui.iGroupBoxTopRight->show(); ui.iGroupBoxTopLeft->show(); + ui.iGroupBoxTop->show(); + ui.iGroupBoxRight->show(); + ui.iGroupBoxLeft->show(); + ui.iGroupBoxClipTop->hide(); + ui.iGroupBoxClipMiddle->hide(); + ui.iGroupBoxClipBottom->hide(); + } + else if (ui.iRadioButtonClipModelThree->isChecked()) + { + ui.iGroupBoxTop->hide(); + ui.iGroupBoxRight->hide(); + ui.iGroupBoxLeft->hide(); + ui.iGroupBoxCenter->hide(); + ui.iGroupBoxTopRight->hide(); + ui.iGroupBoxTopLeft->hide(); + ui.iGroupBoxClipTop->show(); + ui.iGroupBoxClipMiddle->show(); + ui.iGroupBoxClipBottom->show(); } - } diff --git a/tracker-easy/tracker-easy-settings.ui b/tracker-easy/tracker-easy-settings.ui index 451b3e54..d6cc86b6 100644 --- a/tracker-easy/tracker-easy-settings.ui +++ b/tracker-easy/tracker-easy-settings.ui @@ -9,8 +9,8 @@ <rect> <x>0</x> <y>0</y> - <width>465</width> - <height>764</height> + <width>328</width> + <height>923</height> </rect> </property> <property name="sizePolicy"> @@ -20,7 +20,7 @@ </sizepolicy> </property> <property name="windowTitle"> - <string>PointTracker Settings</string> + <string>Easy Tracker Settings</string> </property> <property name="windowIcon"> <iconset> @@ -32,24 +32,8 @@ <property name="autoFillBackground"> <bool>false</bool> </property> - <layout class="QGridLayout" name="gridLayout_9"> - <property name="sizeConstraint"> - <enum>QLayout::SetFixedSize</enum> - </property> - <item row="7" column="0"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item alignment="Qt::AlignTop"> <widget class="QTabWidget" name="tabWidget"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> @@ -61,7 +45,7 @@ <locale language="English" country="UnitedStates"/> </property> <property name="currentIndex"> - <number>0</number> + <number>2</number> </property> <widget class="QWidget" name="tabTracker"> <attribute name="title"> @@ -548,13 +532,13 @@ <item> <widget class="QGroupBox" name="groupBoxCustomModelType"> <property name="title"> - <string>Vertex count</string> + <string>Model type:</string> </property> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_4"> <item> <widget class="QRadioButton" name="iRadioButtonCustomModelThree"> <property name="text"> - <string>Three vertices</string> + <string>Hat three vertices</string> </property> <property name="checked"> <bool>true</bool> @@ -564,14 +548,21 @@ <item> <widget class="QRadioButton" name="iRadioButtonCustomModelFour"> <property name="text"> - <string>Four vertices</string> + <string>Hat four vertices</string> </property> </widget> </item> <item> <widget class="QRadioButton" name="iRadioButtonCustomModelFive"> <property name="text"> - <string>Five vertices</string> + <string>Hat five vertices</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="iRadioButtonClipModelThree"> + <property name="text"> + <string>Clip three vertices</string> </property> </widget> </item> @@ -581,7 +572,7 @@ <item> <widget class="QGroupBox" name="groupBox"> <property name="title"> - <string/> + <string>Vertices: </string> </property> <property name="flat"> <bool>false</bool> @@ -614,7 +605,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxTop"> <property name="title"> - <string>Top</string> + <string>Top:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_2"> <property name="topMargin"> @@ -665,7 +656,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxRight"> <property name="title"> - <string>Right</string> + <string>Right:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> @@ -713,7 +704,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxLeft"> <property name="title"> - <string>Left</string> + <string>Left:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> @@ -761,7 +752,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxCenter"> <property name="title"> - <string>Center</string> + <string>Center:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_5"> <item> @@ -809,7 +800,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxTopRight"> <property name="title"> - <string>Top Right</string> + <string>Top right:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_6"> <item> @@ -857,7 +848,7 @@ <item> <widget class="QGroupBox" name="iGroupBoxTopLeft"> <property name="title"> - <string>Top Left</string> + <string>Top left:</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_7"> <item> @@ -902,6 +893,159 @@ </layout> </widget> </item> + <item> + <widget class="QGroupBox" name="iGroupBoxClipTop"> + <property name="title"> + <string>Clip top:</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_10"> + <property name="topMargin"> + <number>9</number> + </property> + <item> + <widget class="QSpinBox" name="iSpinVertexClipTopX"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipTopY"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipTopZ"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="iGroupBoxClipMiddle"> + <property name="title"> + <string>Clip middle:</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <property name="topMargin"> + <number>9</number> + </property> + <item> + <widget class="QSpinBox" name="iSpinVertexClipMiddleX"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipMiddleY"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipMiddleZ"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="iGroupBoxClipBottom"> + <property name="title"> + <string>Clip bottom:</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_11"> + <property name="topMargin"> + <number>9</number> + </property> + <item> + <widget class="QSpinBox" name="iSpinVertexClipBottomX"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipBottomY"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="iSpinVertexClipBottomZ"> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <number>-65535</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> </layout> </widget> <widget class="QWidget" name="tab_3"> @@ -912,7 +1056,7 @@ <item row="0" column="0"> <widget class="QLabel" name="label_10"> <property name="text"> - <string><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.0</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></string> + <string><html><head/><body><p><span style=" font-weight:600;">Easy Tracker<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Stéphane Lenclud</span></p><p>See <a href="https://github.com/opentrack/opentrack/wiki/Easy-Tracker"><span style=" font-weight:600; text-decoration: underline; color:#9999aa;">documentation on GitHub</span></a></p></body></html></string> </property> <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> @@ -939,10 +1083,22 @@ </widget> </widget> </item> + <item alignment="Qt::AlignBottom"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> </layout> </widget> <tabstops> - <tabstop>tabWidget</tabstop> <tabstop>camdevice_combo</tabstop> <tabstop>res_x_spin</tabstop> <tabstop>res_y_spin</tabstop> diff --git a/tracker-easy/tracker-easy.cpp b/tracker-easy/tracker-easy.cpp index 31c604c9..0487d031 100644 --- a/tracker-easy/tracker-easy.cpp +++ b/tracker-easy/tracker-easy.cpp @@ -154,8 +154,13 @@ namespace EasyTracker // 5 - Radial fourth order // 6 - Radial fifth order // 7 - Radial sixth order - for (unsigned k = 0; k < 8; k++) - iDistCoeffsMatrix(k) = (double)iCameraInfo.dist_c[k]; + // + // SL: Using distortion coefficients in this way is breaking our face tracking output. + // Just disable them for now until we invest time and effort to work it out. + // For our face tracking use case not having proper distortion coefficients ain't a big deal anyway + // See issues #1141 and #1020 + //for (unsigned k = 0; k < 8; k++) + // iDistCoeffsMatrix(k) = (double)iCameraInfo.dist_c[k]; } @@ -165,10 +170,15 @@ namespace EasyTracker { MatchFiveVertices(aTopIndex, aRightIndex, aLeftIndex, aTopRight, aTopLeft); } - else + else if (!iSettings.iClipModelThree) { MatchThreeOrFourVertices(aTopIndex, aRightIndex, aLeftIndex, aCenterIndex); } + else + { + // Clip model + MatchClipVertices(aTopIndex, aRightIndex, aLeftIndex); + } } @@ -183,7 +193,7 @@ namespace EasyTracker // Tracked points must match the order of the object model points. // Find top most point, that's the one with min Y as we assume our guy's head is not up side down int minY = std::numeric_limits<int>::max(); - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { if (iPoints[i].y < minY) { @@ -195,7 +205,7 @@ namespace EasyTracker // Find right most point int maxX = 0; - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { // Excluding top most point if (i != vertexIndices[VertexPosition::Top] && iPoints[i].x > maxX) @@ -208,7 +218,7 @@ namespace EasyTracker // Find left most point int minX = std::numeric_limits<int>::max(); - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { // Excluding top most point and right most point if (i != vertexIndices[VertexPosition::Top] && i != vertexIndices[VertexPosition::Right] && iPoints[i].x < minX) @@ -281,7 +291,7 @@ namespace EasyTracker // Tracked points must match the order of the object model points. // Find top most point, that's the one with min Y as we assume our guy's head is not up side down int minY = std::numeric_limits<int>::max(); - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { if (iPoints[i].y < minY) { @@ -294,7 +304,7 @@ namespace EasyTracker int maxX = 0; // Find right most point - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { // Excluding top most point if (i != aTopIndex && iPoints[i].x > maxX) @@ -306,7 +316,7 @@ namespace EasyTracker // Find left most point int minX = std::numeric_limits<int>::max(); - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { // Excluding top most point and right most point if (i != aTopIndex && i != aRightIndex && iPoints[i].x < minX) @@ -317,7 +327,7 @@ namespace EasyTracker } // Find center point, the last one - for (int i = 0; i < iPoints.size(); i++) + for (int i = 0; i < (int)iPoints.size(); i++) { // Excluding the three points we already have if (i != aTopIndex && i != aRightIndex && i != aLeftIndex) @@ -337,7 +347,56 @@ namespace EasyTracker } } - + /** + */ + void Tracker::MatchClipVertices(int& aTopIndex, int& aMiddleIndex, int& aBottomIndex) + { + //Bitmap origin is top left + iTrackedPoints.clear(); + // Tracked points must match the order of the object model points. + // Find top most point, that's the one with min Y as we assume our guy's head is not up side down + int minY = std::numeric_limits<int>::max(); + for (int i = 0; i < (int)iPoints.size(); i++) + { + if (iPoints[i].y < minY) + { + minY = iPoints[i].y; + aTopIndex = i; + } + } + + + int maxY = 0; + + // Find bottom most point + for (int i = 0; i < (int)iPoints.size(); i++) + { + // Excluding top most point + if (i != aTopIndex && iPoints[i].y > maxY) + { + maxY = iPoints[i].y; + aBottomIndex = i; + } + } + + + // Find center point, the last one + for (int i = 0; i < (int)iPoints.size(); i++) + { + // Excluding the three points we already have + if (i != aTopIndex && i != aBottomIndex) + { + aMiddleIndex = i; + } + } + + // Order matters + iTrackedPoints.push_back(iPoints[aTopIndex]); + iTrackedPoints.push_back(iPoints[aMiddleIndex]); + iTrackedPoints.push_back(iPoints[aBottomIndex]); + } + + /// /// @@ -720,18 +779,29 @@ namespace EasyTracker // We are converting them from millimeters to centimeters. // TODO: Need to support clip too. That's cap only for now. iModel.clear(); - iModel.push_back(cv::Point3f(iSettings.iVertexTopX / 10.0, iSettings.iVertexTopY / 10.0, iSettings.iVertexTopZ / 10.0)); // Top - iModel.push_back(cv::Point3f(iSettings.iVertexRightX / 10.0, iSettings.iVertexRightY / 10.0, iSettings.iVertexRightZ / 10.0)); // Right - iModel.push_back(cv::Point3f(iSettings.iVertexLeftX / 10.0, iSettings.iVertexLeftY / 10.0, iSettings.iVertexLeftZ / 10.0)); // Left - if (iSettings.iCustomModelFour) + if (!iSettings.iClipModelThree) { - iModel.push_back(cv::Point3f(iSettings.iVertexCenterX / 10.0, iSettings.iVertexCenterY / 10.0, iSettings.iVertexCenterZ / 10.0)); // Center + iModel.push_back(cv::Point3f(iSettings.iVertexTopX / 10.0, iSettings.iVertexTopY / 10.0, iSettings.iVertexTopZ / 10.0)); // Top + iModel.push_back(cv::Point3f(iSettings.iVertexRightX / 10.0, iSettings.iVertexRightY / 10.0, iSettings.iVertexRightZ / 10.0)); // Right + iModel.push_back(cv::Point3f(iSettings.iVertexLeftX / 10.0, iSettings.iVertexLeftY / 10.0, iSettings.iVertexLeftZ / 10.0)); // Left + + if (iSettings.iCustomModelFour) + { + iModel.push_back(cv::Point3f(iSettings.iVertexCenterX / 10.0, iSettings.iVertexCenterY / 10.0, iSettings.iVertexCenterZ / 10.0)); // Center + } + else if (iSettings.iCustomModelFive) + { + iModel.push_back(cv::Point3f(iSettings.iVertexTopRightX / 10.0, iSettings.iVertexTopRightY / 10.0, iSettings.iVertexTopRightZ / 10.0)); // Top Right + iModel.push_back(cv::Point3f(iSettings.iVertexTopLeftX / 10.0, iSettings.iVertexTopLeftY / 10.0, iSettings.iVertexTopLeftZ / 10.0)); // Top Left + } } - else if (iSettings.iCustomModelFive) + else { - iModel.push_back(cv::Point3f(iSettings.iVertexTopRightX / 10.0, iSettings.iVertexTopRightY / 10.0, iSettings.iVertexTopRightZ / 10.0)); // Top Right - iModel.push_back(cv::Point3f(iSettings.iVertexTopLeftX / 10.0, iSettings.iVertexTopLeftY / 10.0, iSettings.iVertexTopLeftZ / 10.0)); // Top Left + // Clip model type + iModel.push_back(cv::Point3f(iSettings.iVertexClipTopX / 10.0, iSettings.iVertexClipTopY / 10.0, iSettings.iVertexClipTopZ / 10.0)); // Top + iModel.push_back(cv::Point3f(iSettings.iVertexClipMiddleX / 10.0, iSettings.iVertexClipMiddleY / 10.0, iSettings.iVertexClipMiddleZ / 10.0)); // Middle + iModel.push_back(cv::Point3f(iSettings.iVertexClipBottomX / 10.0, iSettings.iVertexClipBottomY / 10.0, iSettings.iVertexClipBottomZ / 10.0)); // Bottom } infout << "Update model - end"; diff --git a/tracker-easy/tracker-easy.h b/tracker-easy/tracker-easy.h index 0b51f9c7..4510fc7d 100644 --- a/tracker-easy/tracker-easy.h +++ b/tracker-easy/tracker-easy.h @@ -77,6 +77,7 @@ namespace EasyTracker void MatchVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex, int& aTopRight, int& aTopLeft); void MatchThreeOrFourVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aCenterIndex); void MatchFiveVertices(int& aTopIndex, int& aRightIndex, int& aLeftIndex, int& aTopRight, int& aTopLeft); + void MatchClipVertices(int& aTopIndex, int& aMiddleIndex, int& aBottomIndex); // diff --git a/tracker-hatire/ftnoir_hatcontrols.ui b/tracker-hatire/ftnoir_hatcontrols.ui index aa84758b..ca4cefbc 100644 --- a/tracker-hatire/ftnoir_hatcontrols.ui +++ b/tracker-hatire/ftnoir_hatcontrols.ui @@ -103,7 +103,7 @@ <bool>false</bool> </property> <property name="sizeAdjustPolicy"> - <enum>QComboBox::AdjustToMinimumContentsLength</enum> + <enum>QComboBox::AdjustToContents</enum> </property> <property name="modelColumn"> <number>0</number> diff --git a/tracker-hydra/CMakeLists.txt b/tracker-hydra/CMakeLists.txt index b99c1d7a..48471765 100644 --- a/tracker-hydra/CMakeLists.txt +++ b/tracker-hydra/CMakeLists.txt @@ -22,7 +22,7 @@ if(SDK_HYDRA AND opentrack-intel) endif() set(lib "${SDK_HYDRA}/${dir}/${part}/release_dll/sixense${six4}.${ext}") set(dll "${SDK_HYDRA}/bin/${part}/release_dll/sixense${six4}.dll") - install(FILES "${dll}" DESTINATION ${opentrack-hier-pfx} PERMISSIONS ${opentrack-perms-exec}) + install(FILES "${dll}" DESTINATION ${opentrack-libexec} PERMISSIONS ${opentrack-perms-exec}) target_link_libraries(opentrack-tracker-hydra "${lib}") else() if(APPLE) @@ -31,13 +31,13 @@ if(SDK_HYDRA AND opentrack-intel) set(soext "dylib") set(plat "osx") else() # assume Linux - set(dest "${opentrack-hier-pfx}") + set(dest "${opentrack-libexec}") set(part "release") set(soext "so") set(plat "linux") endif() set(lib "libsixense${six4}.${soext}") target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/lib/${plat}${six4}/${part}/${lib}") - install(FILES "${SDK_HYDRA}/lib/${plat}${six4}/${part}/${lib}" DESTINATION ${opentrack-hier-pfx} PERMISSIONS ${opentrack-perms-exec}) + install(FILES "${SDK_HYDRA}/lib/${plat}${six4}/${part}/${lib}" DESTINATION ${opentrack-libexec} PERMISSIONS ${opentrack-perms-exec}) endif() endif() diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index 7ab62df2..0a110e5a 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -30,14 +30,14 @@ if (WIN32 AND opentrack-intel) target_link_libraries(${self} opentrack-video) # Install Kinect Face DLL - install(FILES "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll" DESTINATION "${opentrack-hier-pfx}" PERMISSIONS ${opentrack-perms-exec}) + install(FILES "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll" DESTINATION "${opentrack-libexec}" PERMISSIONS ${opentrack-perms-exec}) # Install Kinect Face Database - install(DIRECTORY "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/NuiDatabase" DESTINATION "${opentrack-hier-pfx}") + install(DIRECTORY "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/NuiDatabase" DESTINATION "${opentrack-libexec}") set(redist-dir "${CMAKE_SOURCE_DIR}/redist/${kinect-arch-dir}") install( FILES "${redist-dir}/msvcp110.dll" "${redist-dir}/msvcr110.dll" - DESTINATION "${opentrack-hier-pfx}" + DESTINATION "${opentrack-libexec}" PERMISSIONS ${opentrack-perms-exec} ) diff --git a/tracker-linux-joystick/CMakeLists.txt b/tracker-linux-joystick/CMakeLists.txt new file mode 100644 index 00000000..4e821b01 --- /dev/null +++ b/tracker-linux-joystick/CMakeLists.txt @@ -0,0 +1,4 @@ +if(LINUX) + otr_module(tracker-linux-joystick) + target_link_libraries(opentrack-tracker-linux-joystick) +endif() diff --git a/tracker-linux-joystick/ftnoir_tracker_linux_joystick.cpp b/tracker-linux-joystick/ftnoir_tracker_linux_joystick.cpp new file mode 100644 index 00000000..8fa600e7 --- /dev/null +++ b/tracker-linux-joystick/ftnoir_tracker_linux_joystick.cpp @@ -0,0 +1,87 @@ +/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#include "ftnoir_tracker_linux_joystick.h" +#include "api/plugin-api.hpp" +#include "compat/math.hpp" +#include <QMutexLocker> + +joystick::joystick() +{ + QString device = getJoystickDevice(s.guid); + joy_fd = open(device.toUtf8().data(), O_RDONLY | O_NONBLOCK); +} + + +joystick::~joystick() { + if (joy_fd > 0) close(joy_fd); +} + +module_status joystick::start_tracker(QFrame *) +{ + if (joy_fd == -1) return error("Couldn't open joystick"); + return status_ok(); +} + + +void joystick::data(double *data) +{ + int map[6] = { + s.joy_1 - 1, + s.joy_2 - 1, + s.joy_3 - 1, + s.joy_4 - 1, + s.joy_5 - 1, + s.joy_6 - 1, + }; + + const double limits[] = { + 100, + 100, + 100, + 180, + 180, + 180 + }; + + const QString guid = s.guid; + int axes[8]; + struct js_event event; + bool ret = true; + if (read(joy_fd, &event, sizeof(event)) > 0) + { + switch (event.type) + { + case JS_EVENT_AXIS: + if (event.number >= 8) break; + axes_state[event.number] = event.value; + + break; + default: + /* Ignore init/button events. */ + break; + } + } + + for (int i = 0; i < 6; i++) + { + axes[i] = axes_state[i]; + } + if (ret) + { + for (int i = 0; i < 6; i++) + { + int k = map[i]; + if (k < 0 || k >= 8) + data[i] = 0; + else + data[i] = clamp(axes[k] * limits[i] / AXIS_MAX, + -limits[i], limits[i]); + } + } +} + +OPENTRACK_DECLARE_TRACKER(joystick, dialog_joystick, joystickDll) diff --git a/tracker-linux-joystick/ftnoir_tracker_linux_joystick.h b/tracker-linux-joystick/ftnoir_tracker_linux_joystick.h new file mode 100644 index 00000000..6ddc4909 --- /dev/null +++ b/tracker-linux-joystick/ftnoir_tracker_linux_joystick.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#pragma once +#include "ui_ftnoir_tracker_linux_joystick_controls.h" +#include <QComboBox> +#include <QCheckBox> +#include <QSpinBox> +#include <QMessageBox> +#include <QSettings> +#include <QList> +#include <QFrame> +#include <QStringList> +#include <cmath> +#include "api/plugin-api.hpp" + +#include <linux/joystick.h> +#include <fcntl.h> +#include <unistd.h> + +#include "options/options.hpp" +using namespace options; + +struct settings : opts { + value<QString> guid; + value<int> joy_1, joy_2, joy_3, joy_4, joy_5, joy_6; + settings() : + opts("tracker-linux-joystick"), + guid(b, "joy-guid", ""), + joy_1(b, "axis-map-1", 1), + joy_2(b, "axis-map-2", 2), + joy_3(b, "axis-map-3", 3), + joy_4(b, "axis-map-4", 4), + joy_5(b, "axis-map-5", 5), + joy_6(b, "axis-map-6", 6) + {} +}; + +struct linux_joystick { + QString name; + QString device_id; + QString dev; +}; +QList<linux_joystick> getJoysticks(); +QString getJoystickDevice(QString guid); + +class joystick : public ITracker +{ +public: + joystick(); + ~joystick(); + module_status start_tracker(QFrame *); + void data(double *data); + settings s; + QString guid; + static constexpr int AXIS_MAX = USHRT_MAX; + int axes_state[6] = {0}; + int joy_fd; +}; + +class dialog_joystick: public ITrackerDialog +{ + Q_OBJECT +public: + dialog_joystick(); + void register_tracker(ITracker *) {} + void unregister_tracker() {} + Ui::UILinuxJoystickControls ui; + joystick* tracker; + settings s; + struct joys { + QString name; + QString guid; + }; + QList<joys> joys_; +private slots: + void doOK(); + void doCancel(); +}; + +class joystickDll : public Metadata +{ + Q_OBJECT + + QString name() { return tr("Linux Joystick input"); } + QIcon icon() { return QIcon(":/images/opentrack.png"); } +}; diff --git a/tracker-linux-joystick/ftnoir_tracker_linux_joystick_controls.ui b/tracker-linux-joystick/ftnoir_tracker_linux_joystick_controls.ui new file mode 100644 index 00000000..2a54c74a --- /dev/null +++ b/tracker-linux-joystick/ftnoir_tracker_linux_joystick_controls.ui @@ -0,0 +1,492 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UILinuxJoystickControls</class> + <widget class="QWidget" name="UILinuxJoystickControls"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>498</width> + <height>334</height> + </rect> + </property> + <property name="windowTitle"> + <string>Tracker settings</string> + </property> + <property name="windowIcon"> + <iconset> + <normaloff>../gui/images/opentrack.png</normaloff>../gui/images/opentrack.png</iconset> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>12</number> + </property> + <property name="topMargin"> + <number>6</number> + </property> + <property name="rightMargin"> + <number>12</number> + </property> + <property name="bottomMargin"> + <number>6</number> + </property> + <item> + <widget class="QFrame" name="frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Device</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="joylist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Mapping</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="1"> + <widget class="QComboBox" name="joy_1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="joy_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>2</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="joy_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>3</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="joy_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>4</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="4" column="1"> + <widget class="QComboBox" name="joy_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>5</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="5" column="1"> + <widget class="QComboBox" name="joy_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>6</number> + </property> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #1</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #2</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #3</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #4</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #5</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #6</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #7</string> + </property> + </item> + <item> + <property name="text"> + <string>Joystick axis #8</string> + </property> + </item> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>X</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Y</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Z</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Yaw</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Pitch</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Roll</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections/> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/tracker-linux-joystick/ftnoir_tracker_linux_joystick_dialog.cpp b/tracker-linux-joystick/ftnoir_tracker_linux_joystick_dialog.cpp new file mode 100644 index 00000000..1cf75bc1 --- /dev/null +++ b/tracker-linux-joystick/ftnoir_tracker_linux_joystick_dialog.cpp @@ -0,0 +1,40 @@ +#include "ftnoir_tracker_linux_joystick.h" +#include "api/plugin-api.hpp" + +dialog_joystick::dialog_joystick() : tracker(nullptr) +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + QList<::linux_joystick> joysticks = getJoysticks(); + + for (int i = 0; i < joysticks.size(); i++) { + ::linux_joystick joy = joysticks[i]; + joys_.push_back(joys { joy.name, joy.device_id}); + ui.joylist->addItem(QString("%1 | %2").arg(joy.dev).arg(joy.name)); + if (joysticks[i].device_id == s.guid) ui.joylist->setCurrentIndex(i); + } + + tie_setting(s.joy_1, ui.joy_1); + tie_setting(s.joy_2, ui.joy_2); + tie_setting(s.joy_3, ui.joy_3); + tie_setting(s.joy_4, ui.joy_4); + tie_setting(s.joy_5, ui.joy_5); + tie_setting(s.joy_6, ui.joy_6); +} + +void dialog_joystick::doOK() { + int idx = ui.joylist->currentIndex(); + static const joys def { {}, {} }; + auto val = joys_.value(idx, def); + s.guid = val.guid; + s.b->save(); + close(); +} + +void dialog_joystick::doCancel() { + close(); +} diff --git a/tracker-linux-joystick/lang/nl_NL.ts b/tracker-linux-joystick/lang/nl_NL.ts new file mode 100644 index 00000000..1c9b89d0 --- /dev/null +++ b/tracker-linux-joystick/lang/nl_NL.ts @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>UILinuxJoystickControls</name> + <message> + <source>Tracker settings</source> + <translation type="unfinished">Tracker-instellingen</translation> + </message> + <message> + <source>Device</source> + <translation type="unfinished">Apparaat</translation> + </message> + <message> + <source>Mapping</source> + <translation type="unfinished">Verwijzing</translation> + </message> + <message> + <source>Disabled</source> + <translation type="unfinished">Uitgeschakeld</translation> + </message> + <message> + <source>Joystick axis #1</source> + <translation type="unfinished">Joystick-as #1</translation> + </message> + <message> + <source>Joystick axis #2</source> + <translation type="unfinished">Joystick-as #2</translation> + </message> + <message> + <source>Joystick axis #3</source> + <translation type="unfinished">Joystick-as #3</translation> + </message> + <message> + <source>Joystick axis #4</source> + <translation type="unfinished">Joystick-as #4</translation> + </message> + <message> + <source>Joystick axis #5</source> + <translation type="unfinished">Joystick-as #5</translation> + </message> + <message> + <source>Joystick axis #6</source> + <translation type="unfinished">Joystick-as #6</translation> + </message> + <message> + <source>Joystick axis #7</source> + <translation type="unfinished">Joystick-as #7</translation> + </message> + <message> + <source>Joystick axis #8</source> + <translation type="unfinished">Joystick-as #8</translation> + </message> + <message> + <source>X</source> + <translation type="unfinished">X</translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished">Y</translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished">Z</translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished">Yaw</translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished">Pitch</translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished">Rol</translation> + </message> +</context> +<context> + <name>joystickDll</name> + <message> + <source>Linux Joystick input</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-linux-joystick/lang/ru_RU.ts b/tracker-linux-joystick/lang/ru_RU.ts new file mode 100644 index 00000000..34ed1089 --- /dev/null +++ b/tracker-linux-joystick/lang/ru_RU.ts @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>UILinuxJoystickControls</name> + <message> + <source>Tracker settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Device</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #3</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #4</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #5</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #6</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #7</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #8</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>joystickDll</name> + <message> + <source>Linux Joystick input</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-linux-joystick/lang/stub.ts b/tracker-linux-joystick/lang/stub.ts new file mode 100644 index 00000000..12dc1400 --- /dev/null +++ b/tracker-linux-joystick/lang/stub.ts @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>UILinuxJoystickControls</name> + <message> + <source>Tracker settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Device</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #3</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #4</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #5</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #6</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #7</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #8</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>joystickDll</name> + <message> + <source>Linux Joystick input</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-linux-joystick/lang/zh_CN.ts b/tracker-linux-joystick/lang/zh_CN.ts new file mode 100644 index 00000000..12dc1400 --- /dev/null +++ b/tracker-linux-joystick/lang/zh_CN.ts @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>UILinuxJoystickControls</name> + <message> + <source>Tracker settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Device</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #1</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #3</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #4</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #5</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #6</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #7</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Joystick axis #8</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>X</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Y</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Z</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yaw</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Pitch</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Roll</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>joystickDll</name> + <message> + <source>Linux Joystick input</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-linux-joystick/linux_joystick.cpp b/tracker-linux-joystick/linux_joystick.cpp new file mode 100644 index 00000000..49718b52 --- /dev/null +++ b/tracker-linux-joystick/linux_joystick.cpp @@ -0,0 +1,65 @@ +#include "ftnoir_tracker_linux_joystick.h" + +#include <QDir> +#include <QFileInfo> +#include <QVariant> + +// Discovery is done by searching for devices in the sys file system. +// +// Given a path like this +// /sys/devices/pci0000:00/0000:00:14.0/usb1/1-10/1-10:1.2/0003:2341:8036.0170/input/input380/js0 +// we want to get this part of the string 2341:8036, it will allow us to +// identify the device in the future. +// alternative way of doing this https://stackoverflow.com/questions/21173988/linux-attempting-to-get-joystick-vendor-and-product-ids-via-ioctl-get-einval-i +std::tuple<QString, QString> sysfsDeviceToJsDev(QFileInfo device) { + using ret = std::tuple<QString, QString>; + QString symlink = device.symLinkTarget(); + QString js_dev = QString("/dev/input/%1").arg(device.fileName()); + + QRegExp sep(QString("[:.%1]").arg(QDir::separator())); + QString device_id = symlink.section(sep, -6, -5); + return ret(js_dev, device_id); +} + +QList<linux_joystick> getJoysticks() +{ + char name[128]; + QList<linux_joystick> joysticks; + + QDir dir("/sys/class/input/"); + dir.setNameFilters({ "js*" }); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) + { + QFileInfo device = list.at(i); + auto [js_dev, device_id] = sysfsDeviceToJsDev(device); + int iFile = open(js_dev.toUtf8().data(), O_RDONLY | O_NONBLOCK); + if (iFile == -1) continue; + if (ioctl(iFile, JSIOCGNAME(sizeof(name)), &name) > 0) + { + linux_joystick j; + j.name = name; + j.dev = js_dev; + j.device_id = device_id; + joysticks.append(j); + } + close(iFile); + + } + + return joysticks; +} + +QString getJoystickDevice(QString guid) { + QDir dir("/sys/class/input/"); + dir.setNameFilters({ "js*" }); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) + { + QFileInfo device = list.at(i); + auto [js_dev, device_id] = sysfsDeviceToJsDev(device); + if (device_id == guid) return js_dev; + } + + return {}; +} diff --git a/tracker-pt/FTNoIR_PT_Controls.ui b/tracker-pt/FTNoIR_PT_Controls.ui index 061f5351..f683d7c3 100644 --- a/tracker-pt/FTNoIR_PT_Controls.ui +++ b/tracker-pt/FTNoIR_PT_Controls.ui @@ -420,6 +420,36 @@ <string>Blue only</string> </property> </item> + <item> + <property name="text"> + <string>Red chroma key</string> + </property> + </item> + <item> + <property name="text"> + <string>Green chroma key</string> + </property> + </item> + <item> + <property name="text"> + <string>Blue chroma key</string> + </property> + </item> + <item> + <property name="text"> + <string>Cyan chroma key</string> + </property> + </item> + <item> + <property name="text"> + <string>Yellow chroma key</string> + </property> + </item> + <item> + <property name="text"> + <string>Magenta chroma key</string> + </property> + </item> </widget> </item> <item row="5" column="0"> diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 194fd423..de95a0d4 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -85,9 +85,7 @@ void Tracker_PT::run() if (success) { - int dynamic_pose_ms = s.dynamic_pose && s.active_model_panel != PointModel::Clip - ? s.init_phase_timeout - : 0; + int dynamic_pose_ms = s.dynamic_pose ? s.init_phase_timeout : 0; point_tracker.track(points, PointModel(s), diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index edf689a9..32916cc5 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -100,6 +100,12 @@ TrackerDialog_PT::TrackerDialog_PT(const QString& module_name) : pt_color_red_only, pt_color_green_only, pt_color_blue_only, + pt_color_red_chromakey, + pt_color_green_chromakey, + pt_color_blue_chromakey, + pt_color_cyan_chromakey, + pt_color_yellow_chromakey, + pt_color_magenta_chromakey, }; for (unsigned k = 0; k < std::size(color_types); k++) diff --git a/tracker-pt/lang/nl_NL.ts b/tracker-pt/lang/nl_NL.ts index 1456157c..3d12a7ea 100644 --- a/tracker-pt/lang/nl_NL.ts +++ b/tracker-pt/lang/nl_NL.ts @@ -232,6 +232,30 @@ Don't roll or change position.</source> <source>Green only</source> <translation type="unfinished"></translation> </message> + <message> + <source>Red chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Green chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Blue chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cyan chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yellow chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Magenta chroma key</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>pt_impl::TrackerDialog_PT</name> diff --git a/tracker-pt/lang/ru_RU.ts b/tracker-pt/lang/ru_RU.ts index c91dd087..0315d493 100644 --- a/tracker-pt/lang/ru_RU.ts +++ b/tracker-pt/lang/ru_RU.ts @@ -237,6 +237,30 @@ ROLL или X/Y-смещения.</translation> <source>Green only</source> <translation type="unfinished"></translation> </message> + <message> + <source>Red chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Green chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Blue chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cyan chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yellow chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Magenta chroma key</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>pt_impl::TrackerDialog_PT</name> diff --git a/tracker-pt/lang/stub.ts b/tracker-pt/lang/stub.ts index 36090e5e..4c8c4f82 100644 --- a/tracker-pt/lang/stub.ts +++ b/tracker-pt/lang/stub.ts @@ -232,6 +232,30 @@ Don't roll or change position.</source> <source>Green only</source> <translation type="unfinished"></translation> </message> + <message> + <source>Red chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Green chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Blue chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cyan chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yellow chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Magenta chroma key</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>pt_impl::TrackerDialog_PT</name> diff --git a/tracker-pt/lang/zh_CN.ts b/tracker-pt/lang/zh_CN.ts index 667c2811..bbbc7f8d 100644 --- a/tracker-pt/lang/zh_CN.ts +++ b/tracker-pt/lang/zh_CN.ts @@ -232,6 +232,30 @@ Don't roll or change position.</source> <source>Green only</source> <translation type="unfinished"></translation> </message> + <message> + <source>Red chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Green chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Blue chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Cyan chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Yellow chroma key</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Magenta chroma key</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>pt_impl::TrackerDialog_PT</name> diff --git a/tracker-pt/module/point_extractor.cpp b/tracker-pt/module/point_extractor.cpp index 7ad9925a..a92c87c9 100644 --- a/tracker-pt/module/point_extractor.cpp +++ b/tracker-pt/module/point_extractor.cpp @@ -33,7 +33,7 @@ using namespace numeric_types; /* http://en.wikipedia.org/wiki/Mean-shift -In this application the idea, is to eliminate any bias of the point estimate +In this application the idea, is to eliminate any bias of the point estimate which is introduced by the rather arbitrary thresholded area. One must recognize that the thresholded area can only move in one pixel increments since it is binary. Thus, its center of mass might make "jumps" as pixels are added/removed @@ -42,9 +42,9 @@ With mean-shift, a moving "window" or kernel is multiplied with the gray-scale image, and the COM is calculated of the result. This is iterated where the kernel center is set the previously computed COM. Thus, peaks in the image intensity distribution "pull" the kernel towards themselves. Eventually it stops moving, i.e. -then the computed COM coincides with the kernel center. We hope that the +then the computed COM coincides with the kernel center. We hope that the corresponding location is a good candidate for the extracted point. -The idea similar to the window scaling suggested in Berglund et al. "Fast, bias-free +The idea similar to the window scaling suggested in Berglund et al. "Fast, bias-free algorithm for tracking single particles with variable size and shape." (2008). */ static vec2 MeanShiftIteration(const cv::Mat1b &frame_gray, const vec2 ¤t_center, f filter_width) @@ -115,6 +115,13 @@ void PointExtractor::extract_single_channel(const cv::Mat& orig_frame, int idx, cv::mixChannels(&orig_frame, 1, &dest, 1, from_to, 1); } +void PointExtractor::filter_single_channel(const cv::Mat& orig_frame, float r, float g, float b, cv::Mat1b& dest) +{ + ensure_channel_buffers(orig_frame); + + cv::transform(orig_frame, dest, cv::Mat(cv::Matx13f(b, g, r))); +} + void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) { switch (s.blob_color) @@ -134,6 +141,36 @@ void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) extract_single_channel(frame, 2, output); break; } + case pt_color_red_chromakey: + { + filter_single_channel(frame, 1, -0.5, -0.5, output); + break; + } + case pt_color_green_chromakey: + { + filter_single_channel(frame, -0.5, 1, -0.5, output); + break; + } + case pt_color_blue_chromakey: + { + filter_single_channel(frame, -0.5, -0.5, 1, output); + break; + } + case pt_color_cyan_chromakey: + { + filter_single_channel(frame, -1, 0.5, 0.5, output); + break; + } + case pt_color_yellow_chromakey: + { + filter_single_channel(frame, 0.5, 0.5, -1, output); + break; + } + case pt_color_magenta_chromakey: + { + filter_single_channel(frame, 0.5, -1, 0.5, output); + break; + } case pt_color_average: { const int W = frame.cols, H = frame.rows, sz = W*H; diff --git a/tracker-pt/module/point_extractor.h b/tracker-pt/module/point_extractor.h index a6103667..9c97b6ce 100644 --- a/tracker-pt/module/point_extractor.h +++ b/tracker-pt/module/point_extractor.h @@ -49,6 +49,7 @@ private: void ensure_buffers(const cv::Mat& frame); void extract_single_channel(const cv::Mat& orig_frame, int idx, cv::Mat1b& dest); + void filter_single_channel(const cv::Mat& orig_frame, float r, float g, float b, cv::Mat1b& dest); void color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output); void threshold_image(const cv::Mat& frame_gray, cv::Mat1b& output); diff --git a/tracker-pt/pt-settings.hpp b/tracker-pt/pt-settings.hpp index 723ee08d..ed13a1ec 100644 --- a/tracker-pt/pt-settings.hpp +++ b/tracker-pt/pt-settings.hpp @@ -13,6 +13,12 @@ enum pt_color_type pt_color_average = 5, pt_color_blue_only = 6, pt_color_green_only = 7, + pt_color_red_chromakey = 8, + pt_color_green_chromakey = 9, + pt_color_blue_chromakey = 10, + pt_color_cyan_chromakey = 11, + pt_color_yellow_chromakey = 12, + pt_color_magenta_chromakey = 13, }; namespace pt_impl { diff --git a/tracker-rift-140/CMakeLists.txt b/tracker-rift-140/CMakeLists.txt index 6e54412a..278effe2 100644 --- a/tracker-rift-140/CMakeLists.txt +++ b/tracker-rift-140/CMakeLists.txt @@ -1,5 +1,14 @@ -if(WIN32 OR APPLE) - include(opentrack-rift) - otr_rift(tracker-rift-140 SDK_RIFT_140) +if(WIN32) SET(SDK_RIFT_140 "" CACHE PATH "libOVR 1.4.0 path for Oculus Rift") + if(SDK_RIFT_140) + include_directories("${SDK_RIFT_140}/Include") + if(opentrack-64bit) + link_directories("${SDK_RIFT_140}/Lib/Windows/x64/Release/VS2017") + else() + link_directories("${SDK_RIFT_140}/Lib/Windows/Win32/Release/VS2017") + endif() + link_libraries(LibOVR winmm setupapi ws2_32 imagehlp wbemuuid) + + otr_module(tracker-rift) + endif() endif() diff --git a/tracker-rs/README.md b/tracker-rs/README.md index 7ea4ad86..a603878b 100644 --- a/tracker-rs/README.md +++ b/tracker-rs/README.md @@ -3,7 +3,7 @@ This is a tracker providing markerless 3D head tracking using the Intel® RealSe More information on RealSense can be found on [Intel.com](http://www.intel.com/content/www/us/en/architecture-and-technology/realsense-overview.html) -This tracker uses a separate library that gets data from the SDK. Its sources are under rs_impl and can be recompiled by calling build.bat, which depends on Microsoft Visual C++ Compiler and the [Intel® RealSense™ SDK 2016 R2](http://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/9078/intel_rs_sdk_offline_package_10.0.26.0396.exe) +This tracker uses a separate library that gets data from the SDK. Its sources are under rs_impl and can be recompiled by calling build.bat, which depends on Microsoft Visual C++ Compiler and the [Intel® RealSense™ SDK 2016 R3](http://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/9078/intel_rs_sdk_offline_package_10.0.26.0396.exe) # ISC License Copyright (c) 2015-2017, Intel Corporation diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp index 4672b3a4..0f458725 100644 --- a/tracker-rs/ftnoir_tracker_rs.cpp +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -104,7 +104,7 @@ void RSTracker::showRealSenseErrorMessageBox(int exitCode) switch(exitCode){ case -101: //The implementation got an invalid handle from the RealSense SDK session/modules - msgBox.setInformativeText(tr("Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.")); + msgBox.setInformativeText(tr("Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R3 is installed.")); break; case -301: //RealSense SDK runtime execution aborted. msgBox.setInformativeText(tr("Tracking stopped after the RealSense SDK Runtime execution has aborted.")); @@ -113,10 +113,10 @@ void RSTracker::showRealSenseErrorMessageBox(int exitCode) msgBox.setInformativeText(tr("Tracking stopped after another program changed camera streams configuration.")); break; default: - msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime 2016 R2 to be installed."); + msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime 2016 R3 to be installed."); } - QPushButton* triggerSdkInstallation = msgBox.addButton(tr("Install SDK 2016 R2 Runtime"), QMessageBox::ActionRole); + QPushButton* triggerSdkInstallation = msgBox.addButton(tr("Install SDK 2016 R3 Runtime"), QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Ok); msgBox.exec(); diff --git a/tracker-rs/ftnoir_tracker_rs_controls.ui b/tracker-rs/ftnoir_tracker_rs_controls.ui index de7516b9..af25f74d 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.ui +++ b/tracker-rs/ftnoir_tracker_rs_controls.ui @@ -30,7 +30,7 @@ <item alignment="Qt::AlignTop"> <widget class="QLabel" name="label"> <property name="text"> - <string><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R2 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R2 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></string> + <string><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R3 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R3 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></string> </property> <property name="wordWrap"> <bool>true</bool> diff --git a/tracker-rs/lang/nl_NL.ts b/tracker-rs/lang/nl_NL.ts index 256b7f25..a4c28187 100644 --- a/tracker-rs/lang/nl_NL.ts +++ b/tracker-rs/lang/nl_NL.ts @@ -12,7 +12,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.</source> + <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R3 is installed.</source> <translation type="unfinished"></translation> </message> <message> @@ -24,7 +24,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Install SDK 2016 R2 Runtime</source> + <source>Install SDK 2016 R3 Runtime</source> <translation type="unfinished"></translation> </message> </context> @@ -42,7 +42,7 @@ <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R2 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R2 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> + <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R3 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R3 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-rs/lang/ru_RU.ts b/tracker-rs/lang/ru_RU.ts index 91668018..592c72a3 100644 --- a/tracker-rs/lang/ru_RU.ts +++ b/tracker-rs/lang/ru_RU.ts @@ -12,7 +12,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.</source> + <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R3 is installed.</source> <translation type="unfinished"></translation> </message> <message> @@ -24,7 +24,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Install SDK 2016 R2 Runtime</source> + <source>Install SDK 2016 R3 Runtime</source> <translation type="unfinished"></translation> </message> </context> @@ -42,7 +42,7 @@ <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R2 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R2 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> + <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R3 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R3 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-rs/lang/stub.ts b/tracker-rs/lang/stub.ts index 3a8e4f45..fe0faa6a 100644 --- a/tracker-rs/lang/stub.ts +++ b/tracker-rs/lang/stub.ts @@ -12,7 +12,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.</source> + <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R3 is installed.</source> <translation type="unfinished"></translation> </message> <message> @@ -24,7 +24,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Install SDK 2016 R2 Runtime</source> + <source>Install SDK 2016 R3 Runtime</source> <translation type="unfinished"></translation> </message> </context> @@ -42,7 +42,7 @@ <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R2 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R2 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> + <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R3 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R3 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-rs/lang/zh_CN.ts b/tracker-rs/lang/zh_CN.ts index 3a8e4f45..fe0faa6a 100644 --- a/tracker-rs/lang/zh_CN.ts +++ b/tracker-rs/lang/zh_CN.ts @@ -12,7 +12,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.</source> + <source>Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R3 is installed.</source> <translation type="unfinished"></translation> </message> <message> @@ -24,7 +24,7 @@ <translation type="unfinished"></translation> </message> <message> - <source>Install SDK 2016 R2 Runtime</source> + <source>Install SDK 2016 R3 Runtime</source> <translation type="unfinished"></translation> </message> </context> @@ -42,7 +42,7 @@ <translation type="unfinished"></translation> </message> <message> - <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R2 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R2 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> + <source><html><head/><body><p>In order to use this tracker, you need a PC equipped with an Intel® RealSense™ F200 or SR300 camera and the RealSense™ <a href="https://software.intel.com/en-us/realsense-sdk-windows-eol"><span style=" text-decoration: underline; color:#0000ff;">SDK 2016 R3 runtime</span></a>.</p><p>Scroll down to the bottom of the page, choosing <span style=" font-weight:600;">2016 R3 Full SDK</span> on the right-hand side. Unfortunately it's necessary to create an account prior to downloading.</p></body></html></source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp index 3230ef56..eb97380c 100644 --- a/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp +++ b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp @@ -11,14 +11,17 @@ #endif #include <pxcsensemanager.h> -#include <pxcfacemodule.h> -#include <pxcfaceconfiguration.h> +#include <RealSense/Face/FaceModule.h> +#include <RealSense/Face/FaceConfiguration.h> #include <cstdlib> const size_t kPreviewStreamWidth = 640; const size_t kPreviewStreamHeight = 480; +using PXCFaceData = Intel::RealSense::Face::FaceData; +using PXCFaceConfiguration = Intel::RealSense::Face::FaceConfiguration; + PXCSenseManager* g_senseManager = NULL; PXCFaceData* g_faceData = NULL; void* g_previewImage = NULL; diff --git a/tracker-s2bot/ftnoir_tracker_s2bot.cpp b/tracker-s2bot/ftnoir_tracker_s2bot.cpp index c1cb7d9b..c9d684aa 100644 --- a/tracker-s2bot/ftnoir_tracker_s2bot.cpp +++ b/tracker-s2bot/ftnoir_tracker_s2bot.cpp @@ -27,6 +27,10 @@ static constexpr int add_cbx[] = -180, }; +#ifdef __GNUG__ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + void tracker_s2bot::run() { int freq = s.freq; if (freq <= 0) diff --git a/tracker-steamvr/CMakeLists.txt b/tracker-steamvr/CMakeLists.txt index dc487cba..eb8b20b9 100644 --- a/tracker-steamvr/CMakeLists.txt +++ b/tracker-steamvr/CMakeLists.txt @@ -38,7 +38,7 @@ if(steamvr-dll AND opentrack-intel) SET(SDK_VALVE_STEAMVR "" CACHE PATH "Valve's SteamVR") if(SDK_VALVE_STEAMVR) otr_module(tracker-steamvr) - install(FILES "${SDK_VALVE_STEAMVR}/bin/${steamvr-dir}/${steamvr-dll}" DESTINATION "${opentrack-hier-pfx}") + install(FILES "${SDK_VALVE_STEAMVR}/bin/${steamvr-dir}/${steamvr-dll}" DESTINATION "${opentrack-libexec}") target_include_directories(opentrack-tracker-steamvr SYSTEM PRIVATE "${SDK_VALVE_STEAMVR}/headers") target_link_libraries(opentrack-tracker-steamvr "${SDK_VALVE_STEAMVR}/lib/${steamvr-dir}/${steamvr-lib}") diff --git a/video-opencv/impl-metadata.cpp b/video-opencv/impl-metadata.cpp index 48a2e693..ffc51773 100644 --- a/video-opencv/impl-metadata.cpp +++ b/video-opencv/impl-metadata.cpp @@ -17,7 +17,14 @@ std::unique_ptr<camera> metadata::make_camera(const QString& name) std::vector<QString> metadata::camera_names() const { - return get_camera_names(); + std::vector<std::tuple<QString, int>> names = get_camera_names(); + std::vector<QString> ret; + for (const auto& t : names) + { + const auto& [str, idx] = t; + ret.push_back(str); + } + return ret; } bool metadata::can_show_dialog(const QString& camera_name) diff --git a/video-opencv/video-property-page.cpp b/video-opencv/video-property-page.cpp index 8057bf9e..d56d4b91 100644 --- a/video-opencv/video-property-page.cpp +++ b/video-opencv/video-property-page.cpp @@ -147,7 +147,7 @@ bool video_property_page::show(int idx) return true; } -#elif defined(__linux) +#elif defined(__linux__) # include <QProcess> # include "compat/camera-names.hpp" diff --git a/video-ps3eye/CMakeLists.txt b/video-ps3eye/CMakeLists.txt index 2fac5f9c..2f0bf50b 100644 --- a/video-ps3eye/CMakeLists.txt +++ b/video-ps3eye/CMakeLists.txt @@ -10,6 +10,7 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ps3eye-driver/CMakeLists.txt") if(libusb_FOUND) include_directories(SYSTEM ${libusb_INCLUDE_DIRS}) link_libraries(${libusb_LIBRARIES}) + link_directories(${libusb_LIBRARY_DIRS}) endif() else() set(SDK_LIBUSB CACHE PATH "") @@ -21,26 +22,14 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ps3eye-driver/CMakeLists.txt") endif() endif() -if(TARGET ps3eye-driver) - otr_module(video-ps3eye) - link_libraries(ps3eye-driver) - add_executable(ps3eye-subprocess "wrapper.cxx") - if(WIN32) - set(path "${SDK_LIBUSB}/libusb-1.0.dll") - if(EXISTS "${path}") - otr_install_lib("${path}" "${opentrack-hier-pfx}") - endif() - endif() -endif() - -if(TARGET ps3eye-sdl) - install(TARGETS "ps3eye-sdl" DESTINATION "${opentrack-hier-pfx}") +if(TARGET ps3eye-sdl AND FALSE) + install(TARGETS "ps3eye-sdl" DESTINATION "${opentrack-libexec}") if(WIN32) foreach(k ${SDL2_LIBRARIES}) get_filename_component(path "${k}" PATH) set(lib "${path}/SDL2.dll") if(EXISTS "${lib}") - otr_install_lib("${lib}" "${opentrack-hier-pfx}") + otr_install_lib("${lib}" "${opentrack-libexec}") break() endif() endforeach() @@ -48,9 +37,29 @@ if(TARGET ps3eye-sdl) endif() if(TARGET ps3eye-mode-test) - install(TARGETS "ps3eye-mode-test" DESTINATION "${opentrack-hier-pfx}") + install(TARGETS "ps3eye-mode-test" DESTINATION "${opentrack-libexec}") +endif() + +if(TARGET ps3eye-driver) + add_executable(ps3eye-subprocess "wrapper.cxx" "shm.cxx") + target_link_libraries(ps3eye-subprocess ps3eye-driver) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + target_link_libraries(ps3eye-subprocess rt) + endif() + install(TARGETS "ps3eye-subprocess" DESTINATION "${opentrack-libexec}") +endif() + +if(TARGET ps3eye-subprocess) + otr_module(video-ps3eye) + target_link_libraries(${self} ps3eye-driver opentrack-video) + if(WIN32) + set(path "${SDK_LIBUSB}/libusb-1.0.dll") + if(EXISTS "${path}") + otr_install_lib("${path}" "${opentrack-libexec}") + endif() + endif() endif() if(TARGET ps3eye-frame-test) - install(TARGETS "ps3eye-frame-test" DESTINATION "${opentrack-hier-pfx}") + install(TARGETS "ps3eye-frame-test" DESTINATION "${opentrack-libexec}") endif() diff --git a/video-ps3eye/dialog.ui b/video-ps3eye/dialog.ui new file mode 100644 index 00000000..1e94ce74 --- /dev/null +++ b/video-ps3eye/dialog.ui @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QWidget" name="Dialog"> + <property name="windowModality"> + <enum>Qt::ApplicationModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>439</width> + <height>211</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>439</width> + <height>0</height> + </size> + </property> + <property name="windowTitle"> + <string>PS3 Eye</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Camera settings</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="2"> + <widget class="QSpinBox" name="exposure_label"> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QSpinBox" name="gain_label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>63</number> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="exposure_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>255</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Exposure</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="gain_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>63</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Gain</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/video-ps3eye/lang/nl_NL.ts b/video-ps3eye/lang/nl_NL.ts index 6401616d..c98370ec 100644 --- a/video-ps3eye/lang/nl_NL.ts +++ b/video-ps3eye/lang/nl_NL.ts @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> +<context> + <name>Dialog</name> + <message> + <source>PS3 Eye</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/ru_RU.ts b/video-ps3eye/lang/ru_RU.ts index 6401616d..c98370ec 100644 --- a/video-ps3eye/lang/ru_RU.ts +++ b/video-ps3eye/lang/ru_RU.ts @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> +<context> + <name>Dialog</name> + <message> + <source>PS3 Eye</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/stub.ts b/video-ps3eye/lang/stub.ts index 6401616d..c98370ec 100644 --- a/video-ps3eye/lang/stub.ts +++ b/video-ps3eye/lang/stub.ts @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> +<context> + <name>Dialog</name> + <message> + <source>PS3 Eye</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/lang/zh_CN.ts b/video-ps3eye/lang/zh_CN.ts index 6401616d..c98370ec 100644 --- a/video-ps3eye/lang/zh_CN.ts +++ b/video-ps3eye/lang/zh_CN.ts @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> +<context> + <name>Dialog</name> + <message> + <source>PS3 Eye</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Camera settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Exposure</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Gain</source> + <translation type="unfinished"></translation> + </message> +</context> </TS> diff --git a/video-ps3eye/module.cpp b/video-ps3eye/module.cpp index ac6d8807..a7078180 100644 --- a/video-ps3eye/module.cpp +++ b/video-ps3eye/module.cpp @@ -1,7 +1,22 @@ #include "module.hpp" -#if 0 +#include "compat/library-path.hpp" +#include "compat/sleep.hpp" +#include "compat/run-in-thread.hpp" + +#include <cstddef> +#include <thread> + +#include <QCoreApplication> +#include <QMessageBox> + #include <libusb.h> +using namespace options; + +#ifdef __GNUG__ +# pragma clang diagnostic ignored "-Wcast-qual" +#endif + int device_count() { libusb_context * ctx = nullptr; @@ -42,16 +57,24 @@ end: return cnt; } +#ifdef __linux__ +# include <unistd.h> +#endif + bool check_device_exists() { +#ifdef __linux__ + // don't show when system driver exists + if (!access("/sys/module/gspca_ov534", R_OK|X_OK)) + return false; +#endif + static bool ret = device_count() > 0; return ret; } static const QString camera_name = QStringLiteral("PS3 Eye open driver"); -namespace video::impl { - std::vector<QString> ps3eye_camera_::camera_names() const { if (check_device_exists()) @@ -66,16 +89,195 @@ std::unique_ptr<camera> ps3eye_camera_::make_camera(const QString& name) else return {}; } -bool ps3eye_camera_::show_dialog(const QString& camera_name) + +static bool show_dialog_() { - // TODO - return false; + (new dialog)->show(); + return true; } -bool ps3eye_camera_::can_show_dialog(const QString& camera_name) + +bool ps3eye_camera_::show_dialog(const QString&) { - return false; + return show_dialog_(); } -} // ns video::impl +bool ps3eye_camera_::can_show_dialog(const QString& name) +{ + return name == camera_name && check_device_exists(); +} + +ps3eye_camera::ps3eye_camera() +{ + if (!shm.success()) + return; + + static const QString library_path(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH); + wrapper.setWorkingDirectory(library_path); +#ifdef _WIN32 + wrapper.setProgram("\"ps3eye-subprocess.exe\""); +#else + wrapper.setProgram("ps3eye-subprocess"); #endif +} + +ps3eye_camera::~ps3eye_camera() +{ + stop(); +} + +void ps3eye_camera::stop() +{ + open = false; + + if (wrapper.state() != QProcess::NotRunning) + { + if (wrapper.state() != QProcess::NotRunning) + wrapper.kill(); + wrapper.waitForFinished(1000); + } +} + +bool ps3eye_camera::start(info& args) +{ + if (!shm.success()) + return false; + + volatile auto& ptr = *(ps3eye::shm*)shm.ptr(); + QString error; + + using mode = ps3eye::shm_in::mode; + + open = false; + fr = {}; + fr.channels = 3; + fr.channel_size = 1; + + if (!args.width || args.width > 320) + { + ptr.in.resolution = mode::vga; + fr.width = 640; fr.height = 480; + } + else + { + ptr.in.resolution = mode::qvga; + fr.width = 320; fr.height = 240; + } + + ptr.in.auto_gain = false; + ptr.in.framerate = (uint8_t)std::clamp(args.fps, 30, 187); + ptr.in.gain = (uint8_t)s.gain; + ptr.in.exposure = (uint8_t)s.exposure; + + sleep_ms = std::clamp(int(std::floor(1000./ptr.in.framerate*2)), 1, 10); + + wrapper.start(); + + constexpr int sleep_ms = 10, max_sleeps = 5000/sleep_ms; + + for (int i = 0; i < max_sleeps; i++) + { + if (ptr.out.timecode > 0) + goto ok; + portable::sleep(sleep_ms); + } + + if (ptr.out.error_string[0] == '\0') + error = "Unknown error"; + else + error = QString::fromLatin1((const char*)ptr.out.error_string, + strnlen((const char*)ptr.out.error_string, sizeof(ptr.out.error_string))); + + run_in_thread_async(qApp, [=]() { + QMessageBox::critical(nullptr, "Can't open camera", "PS3 Eye driver error: " + error, QMessageBox::Close); + }); + + return false; + +ok: + open = true; + return true; +} + +std::tuple<const frame&, bool> ps3eye_camera::get_frame() +{ + auto volatile* ptr = (ps3eye::shm*)shm.ptr(); + + if (shm.success() && open) + { + int elapsed = std::min((int)std::ceil(t.elapsed_ms()), 100); + portable::sleep(sleep_ms - elapsed); + + if (unsigned tc = ptr->out.timecode; tc != timecode) + { + timecode = tc; + goto ok; + } + } + + for (int i = 0; i < 2000; i++) + { + if (unsigned tc = ptr->out.timecode; tc != timecode) + { + timecode = tc; + goto ok; + } + portable::sleep(1); + } + + stop(); + return { fr, false }; + + static_assert(offsetof(decltype(ptr->out), data_640x480) == offsetof(decltype(ptr->out), data_320x240)); + +ok: + t.start(); + memcpy(data, (unsigned char*)ptr->out.data_640x480,sizeof(ptr->out.data_640x480)); + fr.data = data; + return { fr, true }; +} + +bool ps3eye_camera::show_dialog() +{ + return show_dialog_(); +} + +OTR_REGISTER_CAMERA(ps3eye_camera_) + +dialog::dialog(QWidget* parent) : QWidget(parent) +{ + ui.setupUi(this); + tie_setting(s.exposure, ui.exposure_slider); + tie_setting(s.gain, ui.gain_slider); + ui.exposure_label->setValue((int)*s.exposure); + ui.gain_label->setValue((int)*s.gain); + connect(&s.exposure, value_::value_changed<slider_value>(), this, [this](const slider_value&) { s.set_exposure(); }); + connect(&s.gain, value_::value_changed<slider_value>(), this, [this](const slider_value&) { s.set_gain(); }); + connect(ui.exposure_slider, &QSlider::valueChanged, ui.exposure_label, &QSpinBox::setValue); + connect(ui.gain_slider, &QSlider::valueChanged, ui.gain_label, &QSpinBox::setValue); + connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &dialog::do_ok); + connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &dialog::do_cancel); +} + +// XXX copypasta -sh 20200329 +void settings::set_gain() +{ + if (!shm.success()) + return; + + auto& ptr = *(ps3eye::shm volatile*)shm.ptr(); + ptr.in.gain = (unsigned char)*gain; + ++ptr.in.settings_updated; + std::atomic_thread_fence(std::memory_order_seq_cst); +} + +void settings::set_exposure() +{ + if (!shm.success()) + return; + + auto& ptr = *(ps3eye::shm volatile*)shm.ptr(); + ptr.in.exposure = (unsigned char)*exposure; + ++ptr.in.settings_updated; + std::atomic_thread_fence(std::memory_order_seq_cst); +} diff --git a/video-ps3eye/module.hpp b/video-ps3eye/module.hpp index 357af14c..56ffe5df 100644 --- a/video-ps3eye/module.hpp +++ b/video-ps3eye/module.hpp @@ -1,54 +1,79 @@ #pragma once #include "video/camera.hpp" +#include "shm-layout.hpp" +#include "compat/shm.h" +#include "options/options.hpp" +#include "compat/macros1.h" +#include "compat/timer.hpp" +#include "ui_dialog.h" -#if 0 +#include <QDialog> +#include <QProcess> -namespace video { +using namespace options; -struct OTR_VIDEO_EXPORT camera_ +using video::impl::camera; +using video::impl::camera_; +using video::frame; + +struct settings final { - camera_(); - virtual ~camera_(); + bundle b = make_bundle("video-ps3eye"); + shm_wrapper shm { "ps3eye-driver-shm", nullptr, sizeof(ps3eye::shm) }; + + value<slider_value> exposure{b, "exposure", {255, 0, 255}}; + value<slider_value> gain{b, "gain", {30, 0, 63}}; - virtual std::vector<QString> camera_names() const = 0; - virtual std::unique_ptr<camera> make_camera(const QString& name) = 0; - virtual bool show_dialog(const QString& camera_name) = 0; - virtual bool can_show_dialog(const QString& camera_name) = 0; + void set_exposure(); + void set_gain(); }; -struct OTR_VIDEO_EXPORT camera +class dialog final : public QWidget { - struct info final - { - // TODO: expose FOV-based focal length for regular webcams - int width = 0, height = 0, fps = 0; - double fx = 0, fy = 0; // focal length - double P_x = 0, P_y = 0; // principal point - double dist_c[8] {}; // distortion coefficients - }; - - camera(); - virtual ~camera(); - - [[nodiscard]] virtual bool start(info& args) = 0; - virtual void stop() = 0; - virtual bool is_open() = 0; - - virtual std::tuple<const frame&, bool> get_frame() = 0; - [[nodiscard]] virtual bool show_dialog() = 0; + Q_OBJECT + Ui_Dialog ui; + settings s; + + shm_wrapper shm { "ps3eye-driver-shm", nullptr, sizeof(ps3eye::shm) }; + + void do_ok() { s.b->save(); close(); deleteLater(); } + void do_cancel() { s.b->reload(); close(); deleteLater(); } + +protected: + void closeEvent(QCloseEvent*) override { do_cancel(); } + +public: + explicit dialog(QWidget* parent = nullptr); }; -} // ns video +struct ps3eye_camera final : video::impl::camera +{ + QProcess wrapper; + shm_wrapper shm { "ps3eye-driver-shm", nullptr, sizeof(ps3eye::shm) }; + settings s; + frame fr; + Timer t; + unsigned char data[640 * 480 * 3] = {}; + int framerate = 30, sleep_ms = 1; + bool open = false; + unsigned timecode = 0; + + ps3eye_camera(); + ~ps3eye_camera() override; -#endif + bool start(info& args) override; + void stop() override; + bool is_open() override { return open; } + + std::tuple<const frame&, bool> get_frame() override; + [[nodiscard]] bool show_dialog() override; +}; -namespace video::impl { -struct ps3eye_camera_ : camera_ +struct ps3eye_camera_ final : video::impl::camera_ { std::vector<QString> camera_names() const override; std::unique_ptr<camera> make_camera(const QString& name) override; bool show_dialog(const QString& camera_name) override; bool can_show_dialog(const QString& camera_name) override; }; -} // ns video::impl diff --git a/video-ps3eye/ps3eye-driver b/video-ps3eye/ps3eye-driver -Subproject 7a2dcb0ff586bd0865d35d964b75c4d0a29b4e9 +Subproject ac056aa85dca83be3b1a14df7b20fd07104e052 diff --git a/video-ps3eye/shm-layout.hpp b/video-ps3eye/shm-layout.hpp index 7fa29115..577021b9 100644 --- a/video-ps3eye/shm-layout.hpp +++ b/video-ps3eye/shm-layout.hpp @@ -3,21 +3,25 @@ namespace ps3eye { -struct shm_out { +struct shm_in { enum class mode : uint8_t { qvga, vga, }; - enum class status : uint8_t { starting, running, fail, terminate, }; - uint8_t settings_updated; - uint16_t framerate; + uint32_t settings_updated; + uint8_t framerate; mode resolution; - status status_; - uint8_t sharpness, contrast, brightness, hue, saturation; - uint8_t gain, exposure, auto_gain, awb, test_pattern; + //uint8_t sharpness, contrast, brightness hue, saturation; + uint8_t gain, exposure, auto_gain, test_pattern; + uint8_t do_exit; }; -struct shm_in { - uint8_t settings_updated_ack; - uint8_t timecode; +struct shm_out +{ + enum class status : uint8_t { starting, running, fail, terminate, }; + + uint32_t timecode; + uint32_t settings_updated_ack; + status status_; + char error_string[256]; union { uint8_t data_320x240[320][240][3]; uint8_t data_640x480[640][480][3]; @@ -29,9 +33,6 @@ struct shm { static constexpr unsigned _padding_len = (_cacheline_len - (sizeof(shm_in) & (_cacheline_len - 1))) & (_cacheline_len - 1); - using resolution = shm_out::mode; - using status = shm_out::status; - shm_out out; const char* _padding[_padding_len]; shm_in in; diff --git a/video-ps3eye/shm.cxx b/video-ps3eye/shm.cxx new file mode 100644 index 00000000..57e35c3a --- /dev/null +++ b/video-ps3eye/shm.cxx @@ -0,0 +1,2 @@ +#include "shm.hpp" +#include "../compat/shm.cpp" diff --git a/video-ps3eye/shm.hpp b/video-ps3eye/shm.hpp new file mode 100644 index 00000000..2bb8cb89 --- /dev/null +++ b/video-ps3eye/shm.hpp @@ -0,0 +1,4 @@ +#pragma once +#define OTR_GENERIC_EXPORT +#define OTR_GENERIC_IMPORT +#include "../compat/shm.h" diff --git a/video-ps3eye/wrapper.cxx b/video-ps3eye/wrapper.cxx index add62992..eca8968d 100644 --- a/video-ps3eye/wrapper.cxx +++ b/video-ps3eye/wrapper.cxx @@ -1,7 +1,117 @@ #include "shm-layout.hpp" +#include "shm.hpp" + +#include "ps3eye-driver/ps3eye.hpp" + +#include <cstdlib> +#include <atomic> + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Watomic-implicit-seq-cst" +#endif + +#ifdef __GNUG__ +# pragma GCC diagnostic ignored "-Wcast-qual" +# pragma GCC diagnostic ignored "-Wformat-security" +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + +template<int N, typename... xs> +[[noreturn]] +static void error(volatile ps3eye::shm_out& out, const char (&error)[N], const xs&... args) +{ + snprintf((char*)out.error_string, sizeof(ps3eye::shm_out::error_string), error, args...); + std::quick_exit(2); +} + +static void update_settings(ps3eye::camera& camera, const volatile ps3eye::shm_in& in) +{ + //camera.set_framerate(in.framerate); + camera.set_auto_gain(in.auto_gain); + camera.set_gain(in.gain); + camera.set_exposure(in.exposure); + camera.set_test_pattern_status(in.test_pattern); +} + +static ps3eye::resolution get_mode(ps3eye::shm_in::mode res) +{ + switch (res) + { + default: + case ps3eye::shm_in::mode::qvga: + return ps3eye::res_QVGA; + case ps3eye::shm_in::mode::vga: + return ps3eye::res_VGA; + } +} int main(int argc, char** argv) { (void)argc; (void)argv; + shm_wrapper mem_("ps3eye-driver-shm", nullptr, sizeof(ps3eye::shm)); + volatile auto& ptr_ = *(ps3eye::shm*)mem_.ptr(); + volatile auto& in = ptr_.in; + volatile auto& out = ptr_.out; + + auto cameras = ps3eye::list_devices(); + + out.status_ = ps3eye::shm_out::status::starting; + + if (cameras.empty()) + error(out, "no camera found"); + + auto& camera = cameras[0]; + camera->set_debug(false); + auto* frame = (uint8_t*)out.data_640x480; + decltype(out.timecode) timecode = 0; + + { + int framerate = in.framerate; + if (framerate <= 0) + framerate = 60; + + if (!camera->init(get_mode(in.resolution), framerate)) + error(out, "camera init failed: %s", camera->error_string()); + + update_settings(*camera, in); + + if (!camera->start()) + error(out, "can't start camera: %s", camera->error_string()); + } + + out.timecode = 0; + in.do_exit = false; + std::atomic_thread_fence(std::memory_order_seq_cst); + + for (;;) + { + { + auto cookie = in.settings_updated; + if (cookie != out.settings_updated_ack) + { + camera->stop(); + update_settings(*camera, in); + int framerate = in.framerate; + if (framerate <= 0) + framerate = 60; + if (!camera->init(get_mode(in.resolution), framerate)) + error(out, "camera init failed: %s", camera->error_string()); + if (!camera->start()) + error(out, "can't start camera: %s", camera->error_string()); + out.settings_updated_ack = cookie; + } + } + + if (!camera->get_frame(frame)) + continue; + + out.timecode = ++timecode; + + if (in.do_exit) + break; + + std::atomic_thread_fence(std::memory_order_seq_cst); + } + return 0; } diff --git a/video/video-widget.cpp b/video/video-widget.cpp index 8262a380..4399b11a 100644 --- a/video/video-widget.cpp +++ b/video/video-widget.cpp @@ -11,7 +11,7 @@ void video_widget::init_image_nolock() { - double dpi = screen_dpi(); + double dpi = devicePixelRatioF(); size_.store({ iround(width() * dpi), iround(height() * dpi) }, std::memory_order_release); } diff --git a/video/video-widget.hpp b/video/video-widget.hpp index 9218643b..bb218c69 100644 --- a/video/video-widget.hpp +++ b/video/video-widget.hpp @@ -7,7 +7,6 @@ #pragma once -#include "compat/qt-dpi.hpp" #include "compat/math.hpp" #include "export.hpp" @@ -21,7 +20,7 @@ #include <QMutex> -struct OTR_VIDEO_EXPORT video_widget : QWidget, public screen_dpi_mixin<video_widget> +struct OTR_VIDEO_EXPORT video_widget : QWidget { video_widget(QWidget* parent = nullptr); diff --git a/x-plane-plugin/CMakeLists.txt b/x-plane-plugin/CMakeLists.txt index 1d686d98..8e8fb338 100644 --- a/x-plane-plugin/CMakeLists.txt +++ b/x-plane-plugin/CMakeLists.txt @@ -2,19 +2,30 @@ if(LINUX OR APPLE) set(SDK_XPLANE "" CACHE PATH "Path to the X-Plane SDK") if(SDK_XPLANE) - otr_module(xplane-plugin NO-QT) + if (APPLE) + otr_module(xplane-plugin NO-QT NO-INSTALL) + else() + otr_module(xplane-plugin NO-QT) + endif() # probably librt already included - #install(FILES ${opentrack-xplane-plugin-c} DESTINATION "${opentrack-doc-src-pfx}/opentrack-xplane-plugin") - target_include_directories(opentrack-xplane-plugin SYSTEM PUBLIC ${SDK_XPLANE}/CHeaders ${SDK_XPLANE}/CHeaders/XPLM) + #install(FILES ${opentrack-xplane-plugin-c} DESTINATION "opentrack-libexec") + target_include_directories(opentrack-xplane-plugin SYSTEM PUBLIC ${SDK_XPLANE}/CHeaders/XPLM) if(APPLE) target_compile_options(${self} PRIVATE -iframework "${SDK_XPLANE}/Libraries/Mac/" - -DAPL -DXPLM200 -DXPLM210 - -framework XPLM -framework XPWidgets) - target_link_options(${self} + -DAPL -DXPLM200 -DXPLM210 + -framework XPLM) + target_link_options(${self} PRIVATE "-F${SDK_XPLANE}/Libraries/Mac/" - -framework XPLM -framework XPWidgets) + -framework XPLM) + + install(TARGETS "${self}" + RUNTIME DESTINATION ${opentrack-bin}/xplane + BUNDLE DESTINATION ${opentrack-bin}/xplane + LIBRARY DESTINATION ${opentrack-bin}/xplane + PERMISSIONS ${opentrack-perms-exec}) + elseif(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(${self} PRIVATE -DLIN -DXPLM200 -DXPLM210) target_link_options(${self} PRIVATE -rdynamic -nodefaultlibs) |