diff options
54 files changed, 1838 insertions, 1166 deletions
diff --git a/.clang-tidy b/.clang-tidy index a29d0ffd..8898ca05 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -39,7 +39,6 @@ clang-analyzer-deadcode.DeadStores, -cppcoreguidelines-pro-type-union-access, -cppcoreguidelines-pro-type-vararg, -cppcoreguidelines-special-member-functions, --hicpp-special-member-functions, -google-readability-braces-around-statements, -google-readability-casting, -hicpp-avoid-c-arrays, diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c24e9c99..92bda418 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -36,20 +36,17 @@ jobs: - uses: seanmiddleditch/gha-setup-ninja@master - name: Install Linux Dependencies - run: sudo apt update && sudo apt install libprocps-dev libopencv-dev libopencv-dev wine64-tools + run: | + sudo apt-get update + sudo apt-get install libprocps-dev libopencv-dev libopencv-dev wine64-tools + sudo apt-get install qttools5-dev qtbase5-dev libqt5serialport5-dev qtbase5-private-dev if: matrix.os == 'ubuntu-latest' - - name: Cache Qt - id: cache-qt - uses: actions/cache@v3 - with: - path: ../Qt - key: ${{ runner.os }}-QtCache - - name: Install Qt uses: jurplel/install-qt-action@v3 with: - cached: ${{ steps.cache-qt.outputs.cache-hit }} + archives: qtbase qtimageformats qtgamepad qttools qtserialport qtmultimedia + if: matrix.os != 'ubuntu-latest' - name: Configure run: ${{matrix.cmake}} -GNinja -S ${{github.workspace}}/ -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DQt5_DIR=${{env.Qt5_DIR}} -DQt5Gui_DIR=${{env.Qt5_DIR}}/lib/cmake/Qt5Gui diff --git a/CMakeLists.txt b/CMakeLists.txt index bb1cfff2..4e2ddd1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,8 @@ otr_merge_translations() include(opentrack-install) +message("Install directory:") +message(" ${CMAKE_INSTALL_PREFIX}") string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE) message("Compile flags:") #foreach(j C CXX) @@ -1,6 +1,6 @@ ## Intro -[<img src="https://ci.appveyor.com/api/projects/status/n0j9h38jnif5qbe9/branch/unstable?svg=true"/>](https://ci.appveyor.com/project/sthalik/opentrack/branch/unstable) +[<img src="https://github.com/opentrack/opentrack/actions/workflows/cmake.yml/badge.svg">](https://github.com/opentrack/opentrack/actions/workflows/cmake.yml) opentrack project home is located at <<http://github.com/opentrack/opentrack>>. @@ -40,6 +40,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems! - BBC micro:bit, LEGO, sensortag support via Smalltalk<sup>[(1)](https://en.wikipedia.org/wiki/Smalltalk)[(2)](https://en.wikipedia.org/wiki/Alan_Kay)</sup> [S2Bot](http://www.picaxe.com/Teaching/Other-Software/Scratch-Helper-Apps/) - Wiimote (Windows) +- Eyeware Beam<sup>[[1](https://beam.eyeware.tech/)]</sup> ## Output protocols @@ -69,6 +70,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems! - Wei Shuai (Wiimote tracker) - Stéphane Lenclud (Kinect Face Tracker, Easy Tracker) - GO63-samara (Hamilton Filter, Pose-widget improvement) +- Davide Mameli (Eyeware Beam tracker) ## Thanks diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index e7e3c329..cf3bb0cb 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -37,7 +37,7 @@ add_definitions(-D_HAS_EXCEPTIONS=0) if(DEFINED CMAKE_TOOLCHAIN_FILE) # ignore cmake warning: Manually-specified variable not used by the project - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}}") + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}") endif() include("${CMAKE_CURRENT_LIST_DIR}/opentrack-policy.cmake" NO_POLICY_SCOPE) @@ -106,6 +106,10 @@ if(CMAKE_PROJECT_NAME STREQUAL "OpenCV") set(BUILD_opencv_gapi OFF) endif() +if(CMAKE_PROJECT_NAME STREQUAL "TestOscpack") + add_compile_definitions(OSC_HOST_LITTLE_ENDIAN) +endif() + set(opentrack-simd "SSE2") if(CMAKE_PROJECT_NAME STREQUAL "onnxruntime") diff --git a/cmake/opentrack-pkg-config.cmake b/cmake/opentrack-pkg-config.cmake index 5b84cf40..0f13defc 100644 --- a/cmake/opentrack-pkg-config.cmake +++ b/cmake/opentrack-pkg-config.cmake @@ -1,7 +1,8 @@ include_guard(GLOBAL) include(FindPkgConfig) -function(otr_pkgconfig target) +function(otr_pkgconfig_ ret target) + set(${ret} 1 PARENT_SCOPE) foreach(i ${ARGN}) set(k pkg-config_${i}) pkg_check_modules(${k} QUIET ${i}) @@ -11,6 +12,17 @@ function(otr_pkgconfig target) target_include_directories(${target} SYSTEM PRIVATE ${${k}_INCLUDE_DIRS} ${${k}_INCLUDEDIR}) target_link_libraries(${target} ${${k}_LIBRARIES}) else() + set(${ret} 0 PARENT_SCOPE) + endif() + endforeach() +endfunction() + +function(otr_pkgconfig target) + set(ret "") + otr_pkgconfig_(ret "${target}" ${ARGN}) + foreach(i ${ARGN}) + set(k pkg-config_${i}) + if(NOT ${${k}_FOUND}) message(FATAL_ERROR "Can't find '${i}'. Please install development files for this package.") endif() endforeach() diff --git a/compat/process-list.hpp b/compat/process-list.hpp index 782dc0a4..6d960610 100644 --- a/compat/process-list.hpp +++ b/compat/process-list.hpp @@ -131,6 +131,46 @@ static QStringList get_all_executable_names() #elif defined __linux__ +#include <cerrno> + +#ifdef OTR_HAS_LIBPROC2 +#include <libproc2/pids.h> +template<typename = void> +QStringList get_all_executable_names() +{ + QStringList ret; + enum pids_item items[] = { PIDS_ID_PID, PIDS_CMD, PIDS_CMDLINE_V }; + + enum rel_items { rel_pid, rel_cmd, rel_cmdline }; + struct pids_info *info = NULL; + struct pids_stack *stack; + QString tmp; tmp.reserve(64); + + procps_pids_new(&info, items, 3); + + while ((stack = procps_pids_get(info, PIDS_FETCH_TASKS_ONLY))) + { + char **p_cmdline = PIDS_VAL(rel_cmdline, strv, stack, info); + + // note, wine sets argv[0] so no parsing like in OSX case + if (p_cmdline && p_cmdline[0] && p_cmdline[0][0] && + !(p_cmdline[0][0] == '-' && !p_cmdline[0][1])) + { + tmp = QString{p_cmdline[0]}; + const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/')); + if (idx != -1) + tmp = tmp.mid(idx+1); + //qDebug() << "procps" << tmp; + ret.append(tmp); + } + } + //qDebug() << "-- procps end"; + + procps_pids_unref(&info); + + return ret; +} +#else #include <proc/readproc.h> #include <cerrno> @@ -160,6 +200,7 @@ QStringList get_all_executable_names() free(procs); return ret; } +#endif #else template<typename = void> diff --git a/filter-hamilton/ftnoir_filter_hamilton.cpp b/filter-hamilton/ftnoir_filter_hamilton.cpp index be3faa7f..7bbc91de 100644 --- a/filter-hamilton/ftnoir_filter_hamilton.cpp +++ b/filter-hamilton/ftnoir_filter_hamilton.cpp @@ -34,11 +34,15 @@ void hamilton::filter(const double *input, double *output) 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); - + alpha = std::min(1.0, std::max(0.0, alpha)); + if (alpha > 0.0) + alpha = pow(alpha, pos_pow); + // Scale alpha so that alpha * dist <= dist - pos_deadzone. This ensures that + // the center of the deadzone will never move closer to the input position than + // distance dist. And this ensures that the view never jumps ahead of head + // movements. + alpha *= (dist - pos_deadzone) / (dist + EPSILON); + pos_last = Lerp(pos_last, input, alpha); output[TX] = pos_last.v[0]; @@ -48,11 +52,11 @@ void hamilton::filter(const double *input, double *output) // zoom smoothing: const double pow_zoom {s.kPowZoom}; const double max_z {s.kMaxZ}; - double rot_zoom = pow_zoom; + 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 ); + else rot_zoom *= -output[TZ] / (max_z + EPSILON); + rot_zoom = fmin( rot_zoom, pow_zoom ); // rotations: const double rot_max {s.kMaxRot}; @@ -62,10 +66,11 @@ void hamilton::filter(const double *input, double *output) 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); + alpha = std::min(1.0, std::max(0.0, alpha)); + if (alpha > 0.0) + alpha = pow(alpha, rot_pow + rot_zoom); + // see comment in earlier alpha calculation above + alpha *= (angle - rot_deadzone) / (angle + EPSILON); quat_last = Slerp(quat_last, quat_input, alpha); diff --git a/filter-hamilton/ftnoir_filter_hamilton.h b/filter-hamilton/ftnoir_filter_hamilton.h index 0756c216..b724d973 100644 --- a/filter-hamilton/ftnoir_filter_hamilton.h +++ b/filter-hamilton/ftnoir_filter_hamilton.h @@ -43,7 +43,7 @@ public: module_status initialize() override { return status_ok(); } private: tQuat quat_last; - tVector pos_last; + tVector pos_last; settings s; bool first_run = true; }; diff --git a/filter-hamilton/ftnoir_hamilton_filtercontrols.ui b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui index 71cdb6da..4c8b1536 100644 --- a/filter-hamilton/ftnoir_hamilton_filtercontrols.ui +++ b/filter-hamilton/ftnoir_hamilton_filtercontrols.ui @@ -13,7 +13,7 @@ <x>0</x> <y>0</y> <width>514</width> - <height>491</height> + <height>563</height> </rect> </property> <property name="sizePolicy"> @@ -50,8 +50,8 @@ <property name="styleSheet"> <string notr="true"/> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="0"> <widget class="QGroupBox" name="groupBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> @@ -65,322 +65,286 @@ <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> + <layout class="QGridLayout" name="gridLayout"> + <item row="8" column="2"> + <widget class="QSlider" name="powRot"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="8" column="3"> + <widget class="QLabel" name="lbPowRot"> + <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> + </item> + <item row="6" column="2"> + <widget class="QSlider" name="dzRot"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="lbRpow"> + <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 power:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="lbRdz"> + <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::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="6" column="3"> + <widget class="QLabel" name="lbDZRot"> + <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> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="lbRmax"> + <property name="text"> + <string>Max distance:</string> + </property> + </widget> + </item> + <item row="7" column="2"> + <widget class="QSlider" name="maxRot"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="7" column="3"> + <widget class="QLabel" name="lbMaxRot"> + <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> + </item> + </layout> + </widget> + </item> + <item row="6" column="0"> + <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> - <item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>For both rotations and positions: No movement occurs within the dead zone. Smoothing scales down to minimum at max distance + 2 x dead zone.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0"> <widget class="QGroupBox" name="groupBox_2"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> @@ -397,300 +361,248 @@ <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> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="1" column="2"> + <widget class="QLabel" name="lbMaxDist"> + <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> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="lbRpow_3"> + <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 power:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="lbDmax"> + <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::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="maxDist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="powDist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="lbPowDist"> + <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> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="lbRdz_3"> + <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::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="dzDist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="lbDZDist"> + <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> + </item> + </layout> </widget> </item> - <item> + <item row="5" column="0"> <widget class="QGroupBox" name="groupBox_3"> <property name="sizePolicy"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> @@ -707,227 +619,194 @@ <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> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="2" column="0"> + <widget class="QLabel" name="lbZpow"> + <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 power:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="lbPowZoom"> + <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> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="powZoom"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="lbZpow_2"> + <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::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="maxZ"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" 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> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="lbMaxZ"> + <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> + </item> + </layout> </widget> </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>When you lean forward, zoom smoothing increases the smoothing power for rotations. Maximum additonal smoothing power occurs when you lean forward by a distance of Max Z.</string> </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - <property name="centerButtons"> + <property name="wordWrap"> <bool>true</bool> </property> </widget> </item> </layout> </widget> + <tabstops> + <tabstop>dzRot</tabstop> + <tabstop>maxRot</tabstop> + <tabstop>powRot</tabstop> + <tabstop>dzDist</tabstop> + <tabstop>maxDist</tabstop> + <tabstop>powDist</tabstop> + <tabstop>maxZ</tabstop> + <tabstop>powZoom</tabstop> + </tabstops> <resources> <include location="../gui/opentrack-res.qrc"/> </resources> diff --git a/filter-hamilton/lang/nl_NL.ts b/filter-hamilton/lang/nl_NL.ts index b03e4c0b..1c720540 100644 --- a/filter-hamilton/lang/nl_NL.ts +++ b/filter-hamilton/lang/nl_NL.ts @@ -8,18 +8,10 @@ <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> @@ -52,15 +44,27 @@ <translation type="unfinished"></translation> </message> <message> - <source> Dead Zone:</source> + <source>15,00</source> <translation type="unfinished"></translation> </message> <message> - <source> Smoothing:</source> + <source>Smoothing power:</source> <translation type="unfinished"></translation> </message> <message> - <source>15,00</source> + <source>Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>For both rotations and positions: No movement occurs within the dead zone. Smoothing scales down to minimum at max distance + 2 x dead zone.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>When you lean forward, zoom smoothing increases the smoothing power for rotations. Maximum additonal smoothing power occurs when you lean forward by a distance of Max Z.</source> <translation type="unfinished"></translation> </message> </context> diff --git a/filter-hamilton/lang/ru_RU.ts b/filter-hamilton/lang/ru_RU.ts index dfbb2268..f0681b21 100644 --- a/filter-hamilton/lang/ru_RU.ts +++ b/filter-hamilton/lang/ru_RU.ts @@ -8,18 +8,10 @@ <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> @@ -52,15 +44,27 @@ <translation type="unfinished"></translation> </message> <message> - <source> Dead Zone:</source> + <source>15,00</source> <translation type="unfinished"></translation> </message> <message> - <source> Smoothing:</source> + <source>Smoothing power:</source> <translation type="unfinished"></translation> </message> <message> - <source>15,00</source> + <source>Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>For both rotations and positions: No movement occurs within the dead zone. Smoothing scales down to minimum at max distance + 2 x dead zone.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>When you lean forward, zoom smoothing increases the smoothing power for rotations. Maximum additonal smoothing power occurs when you lean forward by a distance of Max Z.</source> <translation type="unfinished"></translation> </message> </context> diff --git a/filter-hamilton/lang/stub.ts b/filter-hamilton/lang/stub.ts index a8af9f98..2b767312 100644 --- a/filter-hamilton/lang/stub.ts +++ b/filter-hamilton/lang/stub.ts @@ -8,18 +8,10 @@ <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> @@ -52,15 +44,27 @@ <translation type="unfinished"></translation> </message> <message> - <source> Dead Zone:</source> + <source>15,00</source> <translation type="unfinished"></translation> </message> <message> - <source> Smoothing:</source> + <source>Smoothing power:</source> <translation type="unfinished"></translation> </message> <message> - <source>15,00</source> + <source>Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>For both rotations and positions: No movement occurs within the dead zone. Smoothing scales down to minimum at max distance + 2 x dead zone.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>When you lean forward, zoom smoothing increases the smoothing power for rotations. Maximum additonal smoothing power occurs when you lean forward by a distance of Max Z.</source> <translation type="unfinished"></translation> </message> </context> diff --git a/filter-hamilton/lang/zh_CN.ts b/filter-hamilton/lang/zh_CN.ts index 4fc4d812..222569e4 100644 --- a/filter-hamilton/lang/zh_CN.ts +++ b/filter-hamilton/lang/zh_CN.ts @@ -8,18 +8,10 @@ <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> @@ -52,15 +44,27 @@ <translation type="unfinished"></translation> </message> <message> - <source> Dead Zone:</source> + <source>15,00</source> <translation type="unfinished"></translation> </message> <message> - <source> Smoothing:</source> + <source>Smoothing power:</source> <translation type="unfinished"></translation> </message> <message> - <source>15,00</source> + <source>Dead Zone:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Max distance:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>For both rotations and positions: No movement occurs within the dead zone. Smoothing scales down to minimum at max distance + 2 x dead zone.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>When you lean forward, zoom smoothing increases the smoothing power for rotations. Maximum additonal smoothing power occurs when you lean forward by a distance of Max Z.</source> <translation type="unfinished"></translation> </message> </context> diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index db2f0b9e..8c57221a 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -11,7 +11,12 @@ target_link_libraries(${self} if(APPLE) target_link_libraries(${self} proc) elseif(LINUX) - otr_pkgconfig(${self} libprocps) + otr_pkgconfig_(has-libproc2 ${self} libproc2) + if(has-libproc2) + target_compile_definitions(${self} PRIVATE -DOTR_HAS_LIBPROC2) + else() + otr_pkgconfig(${self} libprocps) + endif() endif() if(NOT APPLE AND NOT WIN32) diff --git a/gui/init.cpp b/gui/init.cpp index b54a085e..5984269c 100644 --- a/gui/init.cpp +++ b/gui/init.cpp @@ -193,51 +193,56 @@ static void apply_dark_windows_theme_if_needed() static void add_win32_path() { - // see https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable - static char env_path[4096] { '\0', }; + // see https://web.archive.org/web/20180924055536/https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable { QString lib_path = OPENTRACK_BASE_PATH; lib_path.replace("/", "\\"); - const QByteArray lib_path_ = QFile::encodeName(lib_path); - QString mod_path = OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH; mod_path.replace("/", "\\"); - const QByteArray mod_path_ = QFile::encodeName(mod_path); - - const char* contents[] { - "PATH=", - lib_path_.constData(), - ";", - mod_path_.constData(), - ";", - getenv("PATH"), - }; - bool ok = true; + const QString orig_path = qgetenv("PATH"); - for (const char* ptr : contents) - { - if (ptr) - strcat_s(env_path, sizeof(env_path), ptr); + QString env_path; env_path.reserve(4096); - if (!ptr || ptr[0] == '\0' || env_path[0] == '\0') - { - qDebug() << "bad path element" - << (ptr == nullptr ? "<null>" : ptr); - ok = false; - break; - } - } +#if 0 + qDebug() << "orig" << orig_path; + qDebug() << "libpath" << lib_path; + qDebug() << "modpath" << mod_path; +#endif - if (ok) + if (lib_path.isEmpty()) + qDebug() << "env: empty lib_path!"; + else { - const int error = _putenv(env_path); - - if (error) - qDebug() << "can't _putenv win32 path"; + if (!QFile(lib_path).exists()) + qDebug() << "env: lib_path doesn't exist, this shouldn't happen!"; + env_path += lib_path; + env_path += ';'; } + if (mod_path.isEmpty()) + qDebug() << "env: can't add mod_path to env PATH"; else - qDebug() << "can't set win32 path"; + { + if (!QFile(mod_path).exists()) + qDebug() << "env: mod_path doesn't exist, did you install it correctly?"; + env_path += mod_path; + env_path += ';'; + } + + if (orig_path.isEmpty()) + qDebug() << "env: empty PATH"; + else + env_path += orig_path; + +#if 0 + qDebug() << "data" << env_path.constData(); +#endif + + // better length limit than putenv() and SetEnvironmentVariableA + bool ret = SetEnvironmentVariableW(L"PATH", (const wchar_t*)env_path.constData()); + + if (!ret) + qDebug() << "_putenv() failed with" << (void*)GetLastError(); } } @@ -300,11 +305,13 @@ 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 (void)qInstallMessageHandler(qdebug_to_console); +#ifdef _WIN32 + apply_dark_windows_theme_if_needed(); + add_win32_path(); +#endif QDir::setCurrent(OPENTRACK_BASE_PATH); @@ -345,4 +352,3 @@ int otr_main(int argc, char** argv, std::function<std::unique_ptr<QWidget>()> co return ret; } - diff --git a/proto-osc/CMakeLists.txt b/proto-osc/CMakeLists.txt new file mode 100644 index 00000000..eeaf206c --- /dev/null +++ b/proto-osc/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SDK_OSCPACK "" CACHE PATH "oscpack build directory") +if(SDK_OSCPACK) + if(WIN32) + if(NOT EXISTS "${SDK_OSCPACK}/include/.") + message(FATAL_ERROR "SDK_OSCPACK should have 'include' subdirectory (or symlink) to src dir") + endif() + link_directories("${SDK_OSCPACK}") + include_directories("${SDK_OSCPACK}/include" "${SDK_OSCPACK}/include/oscpack") + else() + link_directories("${SDK_OSCPACK}/lib" "${SDK_OSCPACK}/lib32") + include_directories("${SDK_OSCPACK}/include/oscpack") + endif() + link_libraries(oscpack) + otr_module(proto-osc) +endif() diff --git a/proto-osc/dialog.cpp b/proto-osc/dialog.cpp new file mode 100644 index 00000000..54bf6885 --- /dev/null +++ b/proto-osc/dialog.cpp @@ -0,0 +1,38 @@ +#include "dialog.hpp" +#include <QHostAddress> +#include <QPalette> + +void osc_dialog::host_address_edited(const QString& str) +{ + bool bad = QHostAddress{str}.isNull(); + auto pal = pal_; + for (auto role : { QPalette::Highlight, QPalette::Window }) + if (bad) + pal.setColor(role, Qt::red); + ui.address->setPalette(pal); +} + +osc_dialog::osc_dialog() : + pal_{palette()} +{ + ui.setupUi( this ); + + tie_setting(s.address, ui.address); + tie_setting(s.port, ui.port); + connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &osc_dialog::doOK); + connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &osc_dialog::doCancel); + connect(ui.address, &QLineEdit::textChanged, this, &osc_dialog::host_address_edited); + host_address_edited(ui.address->text()); +} + +void osc_dialog::save() { s.b->save(); } +void osc_dialog::reload() { s.b->reload(); } + +void osc_dialog::doOK() { s.b->save(); close(); } +void osc_dialog::doCancel() { close(); } + +void osc_dialog::register_protocol(IProtocol*) {} +void osc_dialog::unregister_protocol() {} + +bool osc_dialog::embeddable() noexcept { return true; } +void osc_dialog::set_buttons_visible(bool x) noexcept { ui.buttonBox->setVisible(x); } diff --git a/proto-osc/dialog.hpp b/proto-osc/dialog.hpp new file mode 100644 index 00000000..29682843 --- /dev/null +++ b/proto-osc/dialog.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "settings.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" + +class osc_dialog: public IProtocolDialog +{ + Q_OBJECT + +public: + osc_dialog(); + void register_protocol(IProtocol*) override; + void unregister_protocol() override; +private: + void set_buttons_visible(bool x) noexcept override; + bool embeddable() noexcept override; + void save() override; + void reload() override; + + Ui_OSC_Dialog ui; + osc_settings s; + const QPalette pal_; + +private slots: + void doOK(); + void doCancel(); + void host_address_edited(const QString& str); +}; diff --git a/proto-osc/dialog.ui b/proto-osc/dialog.ui new file mode 100644 index 00000000..5a078bbd --- /dev/null +++ b/proto-osc/dialog.ui @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>OSC_Dialog</class> + <widget class="QWidget" name="OSC_Dialog"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>284</width> + <height>102</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>284</width> + <height>102</height> + </size> + </property> + <property name="windowTitle"> + <string>OSC protocol settings</string> + </property> + <property name="windowIcon"> + <iconset resource="osc-res.qrc"> + <normaloff>:/images/osc-icon.png</normaloff>:/images/osc-icon.png</iconset> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Destination address</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="address"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + <property name="maxLength"> + <number>256</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Port</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="port"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../gui/opentrack-res.qrc"/> + <include location="osc-res.qrc"/> + </resources> + <connections/> + <designerdata> + <property name="gridDeltaX"> + <number>5</number> + </property> + <property name="gridDeltaY"> + <number>5</number> + </property> + <property name="gridSnapX"> + <bool>true</bool> + </property> + <property name="gridSnapY"> + <bool>true</bool> + </property> + <property name="gridVisible"> + <bool>false</bool> + </property> + </designerdata> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/proto-osc/images/osc-icon.png b/proto-osc/images/osc-icon.png Binary files differnew file mode 100644 index 00000000..3ef546e9 --- /dev/null +++ b/proto-osc/images/osc-icon.png diff --git a/proto-osc/lang/nl_NL.ts b/proto-osc/lang/nl_NL.ts new file mode 100644 index 00000000..260b7adc --- /dev/null +++ b/proto-osc/lang/nl_NL.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/ru_RU.ts b/proto-osc/lang/ru_RU.ts new file mode 100644 index 00000000..498d68d6 --- /dev/null +++ b/proto-osc/lang/ru_RU.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/stub.ts b/proto-osc/lang/stub.ts new file mode 100644 index 00000000..20828cbd --- /dev/null +++ b/proto-osc/lang/stub.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/zh_CN.ts b/proto-osc/lang/zh_CN.ts new file mode 100644 index 00000000..e0d49844 --- /dev/null +++ b/proto-osc/lang/zh_CN.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/metadata.cpp b/proto-osc/metadata.cpp new file mode 100644 index 00000000..9d69347d --- /dev/null +++ b/proto-osc/metadata.cpp @@ -0,0 +1,8 @@ +#include "metadata.hpp" +#include "proto.hpp" +#include "dialog.hpp" + +QString osc_metadata::name() { return tr("Open Sound Control"); } +QIcon osc_metadata::icon() { return QIcon(":/images/osc-icon.png"); } + +OPENTRACK_DECLARE_PROTOCOL(osc_proto, osc_dialog, osc_metadata) diff --git a/proto-osc/metadata.hpp b/proto-osc/metadata.hpp new file mode 100644 index 00000000..c0a947aa --- /dev/null +++ b/proto-osc/metadata.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "api/plugin-api.hpp" + +class osc_metadata : public Metadata +{ + Q_OBJECT + + QString name() override; + QIcon icon() override; +}; diff --git a/proto-osc/osc-res.qrc b/proto-osc/osc-res.qrc new file mode 100644 index 00000000..ade4c629 --- /dev/null +++ b/proto-osc/osc-res.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>images/osc-icon.png</file> + </qresource> +</RCC> diff --git a/proto-osc/proto.cpp b/proto-osc/proto.cpp new file mode 100644 index 00000000..2f90957c --- /dev/null +++ b/proto-osc/proto.cpp @@ -0,0 +1,54 @@ +#include "proto.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" +#include <QQuaternion> +#include <QHostAddress> +#include "osc/OscOutboundPacketStream.h" + +osc_proto::osc_proto() +{ + auto reload_fn = [this] { + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + }; + connect(&*s.b, &bundle_::changed, this, reload_fn); + connect(&*s.b, &bundle_::reloading, this, reload_fn); +} + +void osc_proto::pose(const double* data, const double*) +{ + if (dest.isNull()) + return; + + static constexpr unsigned buffer_size = 1024; + char buffer[buffer_size] = {}; + osc::OutboundPacketStream p{buffer, buffer_size}; + auto q = QQuaternion::fromEulerAngles((float)data[Pitch], (float)data[Yaw], (float)-data[Roll]).normalized(); + p << osc::BeginMessage("/bridge/quat") << q.scalar() << q.x() << q.y() << q.z() << osc::EndMessage; + sock.writeDatagram(p.Data(), (int)p.Size(), dest, port); +} + +module_status osc_proto::initialize() +{ + QString error; + + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + + if (dest.isNull()) + { + error = tr("Invalid destination address '%1'").arg(s.address); + goto fail; + } + + if (!sock.bind()) + { + error = tr("Error binding socket to INADDR_ANY"); + goto fail; + } + + return status_ok(); + +fail: + return { tr("%1: %2").arg(error, sock.errorString()) }; +} diff --git a/proto-osc/proto.hpp b/proto-osc/proto.hpp new file mode 100644 index 00000000..53a5dee4 --- /dev/null +++ b/proto-osc/proto.hpp @@ -0,0 +1,29 @@ +#pragma once + +/* Copyright (c) 2023 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 "settings.hpp" +#include "api/plugin-api.hpp" +#include <QUdpSocket> +#include <QHostAddress> + +class osc_proto : public QObject, public IProtocol +{ + Q_OBJECT + + osc_settings s; + QUdpSocket sock; + QHostAddress dest; + unsigned short port = 0; + +public: + osc_proto(); + module_status initialize() override; + void pose(const double *headpose, const double*) override; + QString game_name() override { return tr("Open Sound Control"); } +}; diff --git a/proto-osc/settings.hpp b/proto-osc/settings.hpp new file mode 100644 index 00000000..edeb45c6 --- /dev/null +++ b/proto-osc/settings.hpp @@ -0,0 +1,14 @@ +#pragma once +#include <QString> +#include "options/options.hpp" + +using namespace options; + +struct osc_settings : opts +{ + value<QString> address; + value<int> port; + osc_settings() : opts("proto-osc"), address{b, "address", "127.0.0.1"}, + port(b, "port", 53101) + {} +}; diff --git a/proto-simconnect/ftnoir_protocol_sc.cpp b/proto-simconnect/ftnoir_protocol_sc.cpp index 226a427b..ca76e0ce 100644 --- a/proto-simconnect/ftnoir_protocol_sc.cpp +++ b/proto-simconnect/ftnoir_protocol_sc.cpp @@ -43,20 +43,15 @@ void simconnect::run() qDebug() << "fsx: connect failed, retry in" << sleep_time << "seconds..."; else { - Timer tm; - - if (!SUCCEEDED(hr = simconnect_subscribe(handle, 0, "Frame"))) + if (!SUCCEEDED(hr = simconnect_subscribe(handle, 0, "1sec"))) qDebug() << "fsx: can't subscribe to frame event:" << (void*)hr; else { while (!isInterruptionRequested()) { - constexpr int max_idle_seconds = 2; - - if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) - tm.start(); + constexpr int max_idle_ms = 2000; - if ((int)tm.elapsed_seconds() > max_idle_seconds) + if (WaitForSingleObject(event, max_idle_ms) != WAIT_OBJECT_0) { qDebug() << "fsx: timeout reached, reconnecting"; break; @@ -73,7 +68,9 @@ void simconnect::run() } } + QMutexLocker l(&mtx); (void)simconnect_close(handle); + handle = nullptr; } for (unsigned k = 0; k < sleep_time * 25; k++) @@ -91,8 +88,6 @@ void simconnect::run() void simconnect::pose(const double* pose, const double*) { - QMutexLocker l(&mtx); - data[Pitch] = (float)-pose[Pitch]; data[Yaw] = (float)pose[Yaw]; data[Roll] = (float)pose[Roll]; @@ -101,6 +96,12 @@ void simconnect::pose(const double* pose, const double*) data[TX] = (float)-pose[TX] * to_meters; data[TY] = (float)pose[TY] * to_meters; data[TZ] = (float)-pose[TZ] * to_meters; + + QMutexLocker l(&mtx); + if (handle) + (void)simconnect_set6DOF(handle, + data[TX], data[TY], data[TZ], + data[Pitch], data[Roll], data[Yaw]); } module_status simconnect::initialize() @@ -148,14 +149,6 @@ module_status simconnect::initialize() return {}; } -void simconnect::handler() -{ - QMutexLocker l(&mtx); - (void)simconnect_set6DOF(handle, - data[TX], data[TY], data[TZ], - data[Pitch], data[Roll], data[Yaw]); -} - void simconnect::event_handler(SIMCONNECT_RECV* pData, DWORD, void* self_) { simconnect& self = *reinterpret_cast<simconnect*>(self_); @@ -172,9 +165,6 @@ void simconnect::event_handler(SIMCONNECT_RECV* pData, DWORD, void* self_) qDebug() << "fsx: got quit event"; self.reconnect = true; break; - case SIMCONNECT_RECV_ID_EVENT_FRAME: - self.handler(); - break; } } diff --git a/proto-simconnect/ftnoir_protocol_sc.h b/proto-simconnect/ftnoir_protocol_sc.h index 28b9b1d8..df3a538d 100644 --- a/proto-simconnect/ftnoir_protocol_sc.h +++ b/proto-simconnect/ftnoir_protocol_sc.h @@ -47,8 +47,6 @@ public: void run() override; private: - void handler(); - enum { SIMCONNECT_RECV_ID_EXCEPTION = 2, SIMCONNECT_RECV_ID_QUIT = 3, diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake index 8f185695..340b78ad 100644 --- a/sdk-paths-sthalik@MSVC-windows.cmake +++ b/sdk-paths-sthalik@MSVC-windows.cmake @@ -28,22 +28,23 @@ setq(SDK_REALSENSE "RSSDK-R2") setq(SDK_VALVE_STEAMVR "steamvr") setq(SDK_FSUIPC "fsuipc") setq(SDK_HYDRA "SixenseSDK") +setq(SDK_EYEWARE_BEAM "eyeware-beam-sdk") if(CMAKE_SIZEOF_VOID_P EQUAL 8) setq(Qt5_DIR "../qt-5.15-kde-amd64/lib/cmake/Qt5") setq(OpenCV_DIR "opencv/build-amd64/install") setq(SDK_ARUCO_LIBPATH "aruco/build-amd64/src/aruco.lib") setq(SDK_LIBUSB "libusb-msvc-amd64") -setq(ONNXRuntime_DIR "onnxruntime-1.12.1-amd64") +setq(ONNXRuntime_DIR "onnxruntime-1.14.1-amd64") setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build-amd64/install") -setq(SDK_EYEWARE_BEAM "BeamSDK-Windows64-1.1.0") +setq(SDK_OSCPACK "oscpack/build-amd64") elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) setq(Qt5_DIR "../qt-5.15-kde/lib/cmake/Qt5") setq(OpenCV_DIR "opencv/build/install") setq(SDK_ARUCO_LIBPATH "aruco/build/src/aruco.lib") setq(SDK_LIBUSB "libusb-msvc-x86") -setq(ONNXRuntime_DIR "onnxruntime-1.12.1") +setq(ONNXRuntime_DIR "onnxruntime-1.14.1") setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build/install") -set(SDK_EYEWARE_BEAM "" CACHE PATH "" FORCE) +setq(SDK_OSCPACK "oscpack/build") else() message(FATAL_ERROR "unknown word size ${CMAKE_SIZEOF_VOID_P}b") endif() diff --git a/tracker-aruco/aruco-trackercontrols.ui b/tracker-aruco/aruco-trackercontrols.ui index 0cd76b89..729d4b48 100644 --- a/tracker-aruco/aruco-trackercontrols.ui +++ b/tracker-aruco/aruco-trackercontrols.ui @@ -139,6 +139,11 @@ </item> <item> <property name="text"> + <string>1920x1080</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 1f39db32..5130a889 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -57,6 +57,7 @@ static const resolution_tuple resolution_choices[] = { 640, 480 }, { 320, 240 }, { 1280, 720 }, + { 1920, 1080 }, { 0, 0 } }; diff --git a/tracker-aruco/lang/nl_NL.ts b/tracker-aruco/lang/nl_NL.ts index 1a510ac1..e5a94f3b 100644 --- a/tracker-aruco/lang/nl_NL.ts +++ b/tracker-aruco/lang/nl_NL.ts @@ -67,6 +67,10 @@ <source>MJPEG</source> <translation type="unfinished"></translation> </message> + <message> + <source>1920x1080</source> + <translation type="unfinished">1280x1080 {1920x?}</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 3e0aa86a..639b59ce 100644 --- a/tracker-aruco/lang/ru_RU.ts +++ b/tracker-aruco/lang/ru_RU.ts @@ -67,6 +67,10 @@ <source>MJPEG</source> <translation type="unfinished"></translation> </message> + <message> + <source>1920x1080</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 bbd78995..f213eb41 100644 --- a/tracker-aruco/lang/stub.ts +++ b/tracker-aruco/lang/stub.ts @@ -67,6 +67,10 @@ <source>MJPEG</source> <translation type="unfinished"></translation> </message> + <message> + <source>1920x1080</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 71fa163c..8c4e5511 100644 --- a/tracker-aruco/lang/zh_CN.ts +++ b/tracker-aruco/lang/zh_CN.ts @@ -67,6 +67,10 @@ <source>MJPEG</source> <translation type="unfinished"></translation> </message> + <message> + <source>1920x1080</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>aruco_dialog</name> diff --git a/tracker-eyeware-beam/CMakeLists.txt b/tracker-eyeware-beam/CMakeLists.txt index 73ea231a..e041c131 100644 --- a/tracker-eyeware-beam/CMakeLists.txt +++ b/tracker-eyeware-beam/CMakeLists.txt @@ -7,9 +7,15 @@ if(WIN32 AND SDK_EYEWARE_BEAM) endif() otr_module(tracker-eyeware-beam) + if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(arch "x86") + else() + set(arch "x64") + endif() + target_include_directories(${self} SYSTEM PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/include") - target_link_directories(${self} PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/lib") - set(dll "${SDK_EYEWARE_BEAM}/API/cpp/lib/tracker_client.dll" "${SDK_EYEWARE_BEAM}/API/cpp/lib/libsodium.dll") + target_link_directories(${self} PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}") + set(dll "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}/tracker_client.dll") set(lib tracker_client.lib) #message(${self}) diff --git a/tracker-neuralnet/CMakeLists.txt b/tracker-neuralnet/CMakeLists.txt index 4689dba1..db568fae 100644 --- a/tracker-neuralnet/CMakeLists.txt +++ b/tracker-neuralnet/CMakeLists.txt @@ -16,16 +16,21 @@ if(OpenCV_FOUND AND ONNXRuntime_FOUND AND OpenMP_FOUND) otr_module(tracker-neuralnet) - target_link_libraries(${self} + target_link_libraries(${self} opentrack-cv onnxruntime::onnxruntime opencv_calib3d opencv_imgproc opencv_imgcodecs opencv_core - OpenMP::OpenMP_C + OpenMP::OpenMP_CXX ) + # OpenMP::OpenMP_CXX doesn't set up the -fopenmp linking option, so set it up ourselves. + if(NOT MSVC) + target_link_options(${self} PUBLIC ${OpenMP_CXX_FLAGS}) + endif() + install( FILES "models/head-localizer.onnx" "models/head-pose.onnx" diff --git a/tracker-neuralnet/model_adapters.cpp b/tracker-neuralnet/model_adapters.cpp index af599321..a8580a89 100644 --- a/tracker-neuralnet/model_adapters.cpp +++ b/tracker-neuralnet/model_adapters.cpp @@ -8,7 +8,6 @@ #include <QDebug> - namespace neuralnet_tracker_ns { @@ -165,6 +164,24 @@ double Localizer::last_inference_time_millis() const } +std::string PoseEstimator::get_network_input_name(size_t i) const +{ +#if ORT_API_VERSION >= 12 + return std::string(&*session_.GetInputNameAllocated(i, allocator_)); +#else + return std::string(session_.GetInputName(i, allocator_)); +#endif +} + +std::string PoseEstimator::get_network_output_name(size_t i) const +{ +#if ORT_API_VERSION >= 12 + return std::string(&*session_.GetOutputNameAllocated(i, allocator_)); +#else + return std::string(session_.GetOutputName(i, allocator_)); +#endif +} + PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&session) : model_version_{session.GetModelMetadata().GetVersion()} , session_{std::move(session)} @@ -215,14 +232,16 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses qDebug() << "Pose model inputs (" << session_.GetInputCount() << ")"; qDebug() << "Pose model outputs (" << session_.GetOutputCount() << "):"; + output_names_.resize(session_.GetOutputCount()); + output_c_names_.resize(session_.GetOutputCount()); for (size_t i=0; i<session_.GetOutputCount(); ++i) { - const char* name = session_.GetOutputName(i, allocator_); + std::string name = get_network_output_name(i); const auto& output_info = session_.GetOutputTypeInfo(i); const auto& onnx_tensor_spec = output_info.GetTensorTypeAndShapeInfo(); auto my_tensor_spec = understood_outputs.find(name); - qDebug() << "\t" << name << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " << + qDebug() << "\t" << name.c_str() << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " << (my_tensor_spec != understood_outputs.end() ? "ok" : "unknown"); if (my_tensor_spec != understood_outputs.end()) @@ -240,7 +259,8 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses // Create tensor regardless and ignore output output_val_.push_back(create_tensor(output_info, allocator_)); } - output_names_.push_back(name); + output_names_[i] = name; + output_c_names_[i] = output_names_[i].c_str(); } has_uncertainty_ = understood_outputs.at("rotaxis_scales_tril").available || @@ -270,9 +290,12 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses // output_val_.push_back(create_tensor(output_info, allocator_)); // } + input_names_.resize(session_.GetInputCount()); + input_c_names_.resize(session_.GetInputCount()); for (size_t i = 0; i < session_.GetInputCount(); ++i) { - input_names_.push_back(session_.GetInputName(i, allocator_)); + input_names_[i] = get_network_input_name(i); + input_c_names_[i] = input_names_[i].c_str(); } assert (input_names_.size() == input_val_.size()); @@ -312,11 +335,11 @@ std::optional<PoseEstimator::Face> PoseEstimator::run( { session_.Run( Ort::RunOptions{ nullptr }, - input_names_.data(), + input_c_names_.data(), input_val_.data(), input_val_.size(), - output_names_.data(), - output_val_.data(), + output_c_names_.data(), + output_val_.data(), output_val_.size()); } catch (const Ort::Exception &e) @@ -430,4 +453,4 @@ double PoseEstimator::last_inference_time_millis() const -} // namespace neuralnet_tracker_ns
\ No newline at end of file +} // namespace neuralnet_tracker_ns diff --git a/tracker-neuralnet/model_adapters.h b/tracker-neuralnet/model_adapters.h index 3fbfb861..820330cf 100644 --- a/tracker-neuralnet/model_adapters.h +++ b/tracker-neuralnet/model_adapters.h @@ -3,6 +3,7 @@ #include <optional> #include <array> #include <vector> +#include <string> #include <onnxruntime_cxx_api.h> #include <opencv2/core.hpp> @@ -21,7 +22,7 @@ class Localizer public: Localizer(Ort::MemoryInfo &allocator_info, Ort::Session &&session); - + // Returns bounding wrt image coordinate of the input image // The preceeding float is the score for being a face normalized to [0,1]. std::pair<float, cv::Rect2f> run( @@ -68,13 +69,16 @@ class PoseEstimator bool has_uncertainty() const { return has_uncertainty_; } private: + std::string get_network_input_name(size_t i) const; + std::string get_network_output_name(size_t i) const; int64_t model_version_ = 0; // Queried meta data from the ONNX file Ort::Session session_{nullptr}; // ONNX's runtime context for running the model Ort::Allocator allocator_; // Memory allocator for tensors // Inputs cv::Mat scaled_frame_{}, input_mat_{}; // Input. One is the original crop, the other is rescaled (?) std::vector<Ort::Value> input_val_; // Tensors to put into the model - std::vector<const char*> input_names_; // Refers to the names in the onnx model. + std::vector<std::string> input_names_; // Refers to the names in the onnx model. + std::vector<const char *> input_c_names_; // Refers to the C names in the onnx model. // Outputs cv::Vec<float, 3> output_coord_{}; // 2d Coordinate and head size output. cv::Vec<float, 4> output_quat_{}; // Quaternion output @@ -83,7 +87,8 @@ class PoseEstimator cv::Vec<float, 2> output_eyes_{}; cv::Vec<float, 3> output_coord_scales_{}; std::vector<Ort::Value> output_val_; // Tensors to put the model outputs in. - std::vector<const char*> output_names_; // Refers to the names in the onnx model. + std::vector<std::string> output_names_; // Refers to the names in the onnx model. + std::vector<const char *> output_c_names_; // Refers to the C names in the onnx model. // More bookkeeping size_t num_recurrent_states_ = 0; double last_inference_time_ = 0; @@ -99,4 +104,4 @@ int find_input_intensity_quantile(const cv::Mat& frame, float percentage); void normalize_brightness(const cv::Mat& frame, cv::Mat& out); -} // namespace neuralnet_tracker_ns
\ No newline at end of file +} // namespace neuralnet_tracker_ns diff --git a/tracker-pt/FTNoIR_PT_Controls.ui b/tracker-pt/FTNoIR_PT_Controls.ui index 4cf4344c..53a29c1a 100644 --- a/tracker-pt/FTNoIR_PT_Controls.ui +++ b/tracker-pt/FTNoIR_PT_Controls.ui @@ -10,7 +10,7 @@ <x>0</x> <y>0</y> <width>413</width> - <height>575</height> + <height>630</height> </rect> </property> <property name="sizePolicy"> @@ -79,21 +79,47 @@ <string>Camera settings</string> </property> <layout class="QGridLayout" name="gridLayout_2"> - <item row="8" column="1"> - <widget class="QPushButton" name="camera_settings"> + <item row="11" column="1"> + <widget class="QCheckBox" name="chroma_key_overexposed"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_4"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="cursor"> + <cursorShape>WhatsThisCursor</cursorShape> + </property> + <property name="toolTip"> + <string>This should be 56° or 76° for the PS3 Eye, dependent upon the physical lens setting. It's only neccessary to get position correspond to real-world values.</string> + </property> <property name="text"> - <string>Open</string> + <string>Diagonal field of view</string> </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_4"> + <item row="6" column="0"> + <widget class="QLabel" name="label_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Dynamic pose (for caps only, never clips)</string> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="label_12"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> @@ -104,23 +130,49 @@ <cursorShape>WhatsThisCursor</cursorShape> </property> <property name="toolTip"> - <string>This should be 56° or 76° for the PS3 Eye, dependent upon the physical lens setting. It's only neccessary to get position correspond to real-world values.</string> + <string><html><head/><body><p>For LEDs, 'Natural' is the fastest grayscale mode thanks to optimized SIMD code. Color key allows to track regular pieces of colored paper.</p></body></html></string> </property> <property name="text"> - <string>Diagonal field of view</string> + <string>Color channels used</string> </property> </widget> </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_9"> + <item row="8" column="1"> + <widget class="QPushButton" name="camera_settings"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Open</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QCheckBox" name="use_mjpeg"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_13"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="cursor"> + <cursorShape>WhatsThisCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Enable MJPEG compression for high-speed cameras other than the PS3 Eye. Windows only.</string> + </property> <property name="text"> - <string>Camera settings (when available)</string> + <string>MJPEG compression</string> </property> </widget> </item> @@ -153,73 +205,15 @@ </property> </widget> </item> - <item row="9" column="1"> - <widget class="QComboBox" name="blob_color"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <item row="11" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Chroma key includes overexposed pixels</string> </property> - <item> - <property name="text"> - <string>Grayscale BT.709</string> - </property> - </item> - <item> - <property name="text"> - <string>Grayscale (from hardware)</string> - </property> - </item> - <item> - <property name="text"> - <string>Red only</string> - </property> - </item> - <item> - <property name="text"> - <string>Green only</string> - </property> - </item> - <item> - <property name="text"> - <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="2" column="0"> - <widget class="QLabel" name="label_41"> + <item row="8" column="0"> + <widget class="QLabel" name="label_9"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> @@ -227,20 +221,26 @@ </sizepolicy> </property> <property name="text"> - <string>Height</string> + <string>Camera settings (when available)</string> </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_5"> + <item row="7" column="1"> + <widget class="QSpinBox" name="init_phase_timeout"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Dynamic pose (for caps only, never clips)</string> + <property name="suffix"> + <string> ms</string> + </property> + <property name="minimum"> + <number>50</number> + </property> + <property name="maximum"> + <number>5000</number> </property> </widget> </item> @@ -257,8 +257,8 @@ </property> </widget> </item> - <item row="2" column="1"> - <widget class="QSpinBox" name="res_y_spin"> + <item row="1" column="1"> + <widget class="QSpinBox" name="res_x_spin"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> @@ -266,7 +266,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Desired capture height</string> + <string>Desired capture width</string> </property> <property name="suffix"> <string> px</string> @@ -279,22 +279,16 @@ </property> </widget> </item> - <item row="9" column="0"> - <widget class="QLabel" name="label_12"> + <item row="7" column="0"> + <widget class="QLabel" name="label_6"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="cursor"> - <cursorShape>WhatsThisCursor</cursorShape> - </property> - <property name="toolTip"> - <string><html><head/><body><p>For LEDs, 'Natural' is the fastest grayscale mode thanks to optimized SIMD code. Color key allows to track regular pieces of colored paper.</p></body></html></string> - </property> <property name="text"> - <string>Color channels used</string> + <string>Dynamic pose timeout</string> </property> </widget> </item> @@ -311,25 +305,32 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="res_x_spin"> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="toolTip"> - <string>Desired capture width</string> + <property name="text"> + <string>Device</string> </property> - <property name="suffix"> - <string> px</string> + <property name="buddy"> + <cstring>camdevice_combo</cstring> </property> - <property name="maximum"> - <number>2000</number> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_41"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="singleStep"> - <number>10</number> + <property name="text"> + <string>Height</string> </property> </widget> </item> @@ -352,23 +353,69 @@ </property> </widget> </item> - <item row="7" column="1"> - <widget class="QSpinBox" name="init_phase_timeout"> + <item row="9" column="1"> + <widget class="QComboBox" name="blob_color"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="suffix"> - <string> ms</string> - </property> - <property name="minimum"> - <number>50</number> - </property> - <property name="maximum"> - <number>5000</number> - </property> + <item> + <property name="text"> + <string>Grayscale BT.709</string> + </property> + </item> + <item> + <property name="text"> + <string>Grayscale (from hardware)</string> + </property> + </item> + <item> + <property name="text"> + <string>Red only</string> + </property> + </item> + <item> + <property name="text"> + <string>Green only</string> + </property> + </item> + <item> + <property name="text"> + <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="1"> @@ -393,60 +440,70 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_2"> + <item row="2" column="1"> + <widget class="QSpinBox" name="res_y_spin"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Device</string> + <property name="toolTip"> + <string>Desired capture height</string> </property> - <property name="buddy"> - <cstring>camdevice_combo</cstring> + <property name="suffix"> + <string> px</string> </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_6"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="maximum"> + <number>2000</number> </property> - <property name="text"> - <string>Dynamic pose timeout</string> + <property name="singleStep"> + <number>10</number> </property> </widget> </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_13"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="cursor"> - <cursorShape>WhatsThisCursor</cursorShape> - </property> - <property name="toolTip"> - <string>Enable MJPEG compression for high-speed cameras other than the PS3 Eye. Windows only.</string> - </property> + <item row="10" column="0"> + <widget class="QLabel" name="label_17"> <property name="text"> - <string>MJPEG compression</string> + <string>Chroma key strength</string> </property> </widget> </item> - <item row="4" column="1"> - <widget class="QCheckBox" name="use_mjpeg"> - <property name="text"> - <string/> - </property> - </widget> + <item row="10" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSlider" name="chroma_key_strength_slider"> + <property name="minimum"> + <number>5</number> + </property> + <property name="maximum"> + <number>40</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="chroma_key_strength_label"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="minimum"> + <double>0.500000000000000</double> + </property> + <property name="maximum"> + <double>4.000000000000000</double> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> @@ -602,6 +659,26 @@ </property> </widget> </item> + <item row="2" column="1"> + <widget class="QLabel" name="threshold_value_display"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Value</string> + </property> + </widget> + </item> <item row="3" column="1"> <widget class="QDoubleSpinBox" name="mindiam_spin"> <property name="sizePolicy"> @@ -624,26 +701,6 @@ </property> </widget> </item> - <item row="2" column="1"> - <widget class="QLabel" name="threshold_value_display"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_14"> - <property name="text"> - <string>Value</string> - </property> - </widget> - </item> </layout> </widget> </item> @@ -1635,55 +1692,55 @@ Don't roll or change position.</string> <string>Status</string> </property> <layout class="QGridLayout" name="gridLayout_10"> - <item row="1" column="0"> - <widget class="QLabel" name="label_3"> + <item row="1" column="1"> + <widget class="QLabel" name="pointinfo_label"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string>Extracted Points:</string> + <string/> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_38"> + <item row="0" column="1"> + <widget class="QLabel" name="caminfo_label"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string>Camera Info:</string> + <string/> </property> </widget> </item> - <item row="1" column="1"> - <widget class="QLabel" name="pointinfo_label"> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string/> + <string>Extracted Points:</string> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLabel" name="caminfo_label"> + <item row="0" column="0"> + <widget class="QLabel" name="label_38"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string/> + <string>Camera Info:</string> </property> </widget> </item> @@ -1717,6 +1774,8 @@ Don't roll or change position.</string> <tabstop>init_phase_timeout</tabstop> <tabstop>camera_settings</tabstop> <tabstop>blob_color</tabstop> + <tabstop>chroma_key_strength_slider</tabstop> + <tabstop>chroma_key_overexposed</tabstop> <tabstop>auto_threshold</tabstop> <tabstop>threshold_slider</tabstop> <tabstop>mindiam_spin</tabstop> diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp index 160eb831..d67f79a7 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -110,6 +110,16 @@ TrackerDialog_PT::TrackerDialog_PT(const QString& module_name) : tie_setting(s.blob_color, ui.blob_color); + tie_setting(s.chroma_key_strength, ui.chroma_key_strength_slider); + connect(&s.chroma_key_strength, value_::value_changed<slider_value>(), ui.chroma_key_strength_label, + [this] { ui.chroma_key_strength_label->setValue(*s.chroma_key_strength); }); + ui.chroma_key_strength_label->setValue(*s.chroma_key_strength); + + tie_setting(s.chroma_key_overexposed, ui.chroma_key_overexposed); + connect(ui.blob_color, &QComboBox::currentTextChanged, this, &TrackerDialog_PT::chroma_key_controls_enable); + + chroma_key_controls_enable(""); + tie_setting(s.threshold_slider, ui.threshold_value_display, [this](const slider_value& val) { return threshold_display_text(int(val)); }); @@ -248,6 +258,20 @@ void TrackerDialog_PT::show_camera_settings() (void)video::show_dialog(s.camera_name); } +void TrackerDialog_PT::chroma_key_controls_enable(const QString&) +{ + bool enabled = false; + QVariant data = ui.blob_color->currentData(); + if (data.isValid()) + { + pt_color_type blob_color = pt_color_type(data.toInt()); + enabled = blob_color >= pt_color_red_chromakey && blob_color <= pt_color_magenta_chromakey; + } + ui.chroma_key_strength_slider->setEnabled(enabled); + ui.chroma_key_strength_label->setEnabled(enabled); + ui.chroma_key_overexposed->setEnabled(enabled); +} + void TrackerDialog_PT::trans_calib_step() { QMutexLocker l(&calibrator_mutex); diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.h b/tracker-pt/ftnoir_tracker_pt_dialog.h index f4b0ff8c..79cd91bd 100644 --- a/tracker-pt/ftnoir_tracker_pt_dialog.h +++ b/tracker-pt/ftnoir_tracker_pt_dialog.h @@ -39,6 +39,8 @@ public slots: void poll_tracker_info_impl(); void set_camera_settings_available(const QString& camera_name); void show_camera_settings(); + void chroma_key_controls_enable(const QString&); + protected: QString threshold_display_text(int threshold_value); diff --git a/tracker-pt/lang/nl_NL.ts b/tracker-pt/lang/nl_NL.ts index 90383b97..fc44b0f1 100644 --- a/tracker-pt/lang/nl_NL.ts +++ b/tracker-pt/lang/nl_NL.ts @@ -304,6 +304,14 @@ Don't roll or change position.</source> <source>Filter</source> <translation type="unfinished"></translation> </message> + <message> + <source>Chroma key includes overexposed pixels</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Chroma key strength</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 b7146449..7ff4657e 100644 --- a/tracker-pt/lang/ru_RU.ts +++ b/tracker-pt/lang/ru_RU.ts @@ -309,6 +309,14 @@ ROLL или X/Y-смещения.</translation> <source>Filter</source> <translation type="unfinished"></translation> </message> + <message> + <source>Chroma key includes overexposed pixels</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Chroma key strength</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 3d5e9ae7..3dbe208d 100644 --- a/tracker-pt/lang/stub.ts +++ b/tracker-pt/lang/stub.ts @@ -304,6 +304,14 @@ Don't roll or change position.</source> <source>Filter</source> <translation type="unfinished"></translation> </message> + <message> + <source>Chroma key includes overexposed pixels</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Chroma key strength</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 d8aff4b5..3519d719 100644 --- a/tracker-pt/lang/zh_CN.ts +++ b/tracker-pt/lang/zh_CN.ts @@ -304,6 +304,14 @@ Don't roll or change position.</source> <source>Filter</source> <translation type="unfinished"></translation> </message> + <message> + <source>Chroma key includes overexposed pixels</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Chroma key strength</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 17819d78..3329fafc 100644 --- a/tracker-pt/module/point_extractor.cpp +++ b/tracker-pt/module/point_extractor.cpp @@ -11,6 +11,7 @@ #include "frame.hpp" #include "cv/numeric.hpp" #include "compat/math.hpp" +#include "compat/math-imports.hpp" #include <opencv2/imgproc.hpp> @@ -111,11 +112,31 @@ 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) +void PointExtractor::filter_single_channel(const cv::Mat& orig_frame, float r, float g, float b, bool overexp, cv::Mat1b& dest) { ensure_channel_buffers(orig_frame); - cv::transform(orig_frame, dest, cv::Mat(cv::Matx13f(b, g, r))); + // just filter for colour or also include overexposed regions? + if (!overexp) + cv::transform(orig_frame, dest, cv::Mat(cv::Matx13f(b, g, r))); + else + { + for (int i = 0; i < orig_frame.rows; i++) + { + cv::Vec3b const* const __restrict orig_ptr = orig_frame.ptr<cv::Vec3b>(i); + uint8_t* const __restrict dest_ptr = dest.ptr(i); + for (int j = 0; j < orig_frame.cols; j++) + { + // get the intensity of the key color (i.e. +ve coefficients) + uchar blue = orig_ptr[j][0], green = orig_ptr[j][1], red = orig_ptr[j][2]; + float key = std::max(b, 0.0f) * blue + std::max(g, 0.0f) * green + std::max(r, 0.0f) * red; + // get the intensity of the non-key color (i.e. -ve coefficients) + float nonkey = std::max(-b, 0.0f) * blue + std::max(-g, 0.0f) * green + std::max(-r, 0.0f) * red; + // the result is key color minus non-key color inversely weighted by key colour intensity + dest_ptr[j] = std::max(0.0f, std::min(255.0f, key - (255.0f - key) / 255.0f * nonkey)); + } + } + } } void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) @@ -127,6 +148,7 @@ void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) return; } + const float half_chr_key_str = *s.chroma_key_strength * 0.5; switch (s.blob_color) { case pt_color_green_only: @@ -146,32 +168,32 @@ void PointExtractor::color_to_grayscale(const cv::Mat& frame, cv::Mat1b& output) } case pt_color_red_chromakey: { - filter_single_channel(frame, 1, -0.5, -0.5, output); + filter_single_channel(frame, 1, -half_chr_key_str, -half_chr_key_str, s.chroma_key_overexposed, output); break; } case pt_color_green_chromakey: { - filter_single_channel(frame, -0.5, 1, -0.5, output); + filter_single_channel(frame, -half_chr_key_str, 1, -half_chr_key_str, s.chroma_key_overexposed, output); break; } case pt_color_blue_chromakey: { - filter_single_channel(frame, -0.5, -0.5, 1, output); + filter_single_channel(frame, -half_chr_key_str, -half_chr_key_str, 1, s.chroma_key_overexposed, output); break; } case pt_color_cyan_chromakey: { - filter_single_channel(frame, -1, 0.5, 0.5, output); + filter_single_channel(frame, -*s.chroma_key_strength, 0.5, 0.5, s.chroma_key_overexposed, output); break; } case pt_color_yellow_chromakey: { - filter_single_channel(frame, 0.5, 0.5, -1, output); + filter_single_channel(frame, 0.5, 0.5, -*s.chroma_key_strength, s.chroma_key_overexposed, output); break; } case pt_color_magenta_chromakey: { - filter_single_channel(frame, 0.5, -1, 0.5, output); + filter_single_channel(frame, 0.5, -*s.chroma_key_strength, 0.5, s.chroma_key_overexposed, output); break; } case pt_color_hardware: diff --git a/tracker-pt/module/point_extractor.h b/tracker-pt/module/point_extractor.h index 3f7fb4ee..fbfdbb0b 100644 --- a/tracker-pt/module/point_extractor.h +++ b/tracker-pt/module/point_extractor.h @@ -51,7 +51,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 filter_single_channel(const cv::Mat& orig_frame, float r, float g, float b, bool overexp, 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 6f7a18d5..5d16d973 100644 --- a/tracker-pt/pt-settings.hpp +++ b/tracker-pt/pt-settings.hpp @@ -65,6 +65,8 @@ struct pt_settings final : options::opts value<bool> auto_threshold { b, "automatic-threshold", true }; value<pt_color_type> blob_color { b, "blob-color", pt_color_bt709 }; value<bool> use_mjpeg { b, "use-mjpeg", false }; + value<slider_value> chroma_key_strength{ b, "chroma-key-strength", { 1.0, 0.5, 4. } }; + value<bool> chroma_key_overexposed{ b, "chroma-key-overexposed", false }; value<slider_value> threshold_slider { b, "threshold-slider", { 128, 0, 255 } }; |