diff options
112 files changed, 2941 insertions, 2080 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 00b9bcdc..2be2a878 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ file(GLOB opentrack-subprojects      "csv/${C}"      "pose-widget/${C}"      "spline-widget/${C}" -    "macosx/${C}"      "qxt-mini/${C}" +    "macosx/${C}"  )  foreach(i ${opentrack-subprojects})      get_filename_component(i ${i} DIRECTORY) @@ -22,7 +22,7 @@ Not to be confused with railway planning software <<http://opentrack.ch>>  # Tracking sources  - PointTracker by Patrick Ruoff, freetrack-like light sources -- Oculus Rift DK2 +- Oculus Rift DK1, DK2 and legacy versions  - Paper marker support via the ArUco library <<https://github.com/rmsalinas/aruco>>  - Human face tracker <<https://github.com/sthalik/headtracker>>  - Razer Hydra diff --git a/cmake/mingw-w64.cmake b/cmake/mingw-w64.cmake index 02ab66cb..679f67de 100644 --- a/cmake/mingw-w64.cmake +++ b/cmake/mingw-w64.cmake @@ -27,7 +27,7 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)  # oldest CPU supported here is Northwood-based Pentium 4. -sh 20150811  set(fpu "-ffast-math -fno-finite-math-only -mfpmath=both") -set(cpu "-O3 -march=pentium4 -mtune=corei7-avx ${fpu} -msse -msse2 -mno-sse3") +set(cpu "-O3 -march=pentium4 -mtune=corei7-avx ${fpu} -msse -msse2 -mno-sse3 -frename-registers")  set(CFLAGS-OVERRIDE "" CACHE STRING "") diff --git a/cmake/opentrack-macros.cmake b/cmake/opentrack-macros.cmake index e43dc3b5..d84f9175 100644 --- a/cmake/opentrack-macros.cmake +++ b/cmake/opentrack-macros.cmake @@ -32,7 +32,7 @@ endfunction()  macro(opentrack_library n dir)      cmake_parse_arguments(opentrack-foolib -        "NO-LIBRARY;STATIC;NO-COMPAT;NO-LINKER-SCRIPT" +        "NO-LIBRARY;STATIC;NO-COMPAT;NO-LINKER-SCRIPT;LINKAGE"          "LINK;COMPILE;GNU-LINK;GNU-COMPILE"          ""          ${ARGN} @@ -53,20 +53,33 @@ macro(opentrack_library n dir)              target_link_libraries(${n} opentrack-api opentrack-compat)          endif()          target_link_libraries(${n} ${MY_QT_LIBS}) -        if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE AND NOT opentrack-foolib_NO-LINKER-SCRIPT) -            SET_TARGET_PROPERTIES(${n} PROPERTIES -                LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"" +        if(CMAKE_COMPILER_IS_GNUCXX AND NOT opentrack-foolib_NO-LINKER-SCRIPT) +            set(l-flags) +            if(NOT APPLE) +                set(l-flags "-Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"") +            endif() +            set_target_properties(${n} PROPERTIES +                LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} ${l-flags}"                  COMPILE_FLAGS "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden"              )          else() -            set(link-flags) -            if(MSVC) -                set(link-flags "${msvc-subsystem} /DEBUG /OPT:ICF") +            set(c-props) +            set(l-props) +            if(opentrack-foolib_LINKAGE AND CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) +                set(c-props "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden") +                set(l-props "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed") +            else() +                if(MSVC) +                    set(l-props "${msvc-subsystem} /DEBUG /OPT:ICF") +                endif()              endif() -            set_target_properties(${n} PROPERTIES LINK_FLAGS "${link-flags} ${opentrack-foolib_LINK}" COMPILE_FLAGS "${opentrack-foolib_COMPILE}") -            set(link-flags) +            set_target_properties(${n} PROPERTIES +                LINK_FLAGS "${l-props} ${opentrack-foolib_LINK}" +                COMPILE_FLAGS "${c-props} ${opentrack-foolib_COMPILE}" +            )          endif() -        string(REPLACE "-" "_" n_ ${n}) +        string(REGEX REPLACE "^opentrack-" "" n_ ${n}) +        string(REPLACE "-" "_" n_ ${n_})          target_compile_definitions(${n} PRIVATE "BUILD_${n_}")          if(NOT opentrack-foolib_STATIC)              install(TARGETS ${n} RUNTIME DESTINATION . LIBRARY DESTINATION .) diff --git a/contrib/aruco/test3.jpg b/contrib/aruco/test3.jpg Binary files differdeleted file mode 100644 index 2ff6dbd0..00000000 --- a/contrib/aruco/test3.jpg +++ /dev/null diff --git a/contrib/aruco/test3.png b/contrib/aruco/test3.png Binary files differnew file mode 100644 index 00000000..81f2d201 --- /dev/null +++ b/contrib/aruco/test3.png diff --git a/contrib/very-important-source-code/make-csv.pl b/contrib/very-important-source-code/make-csv.pl index ee60364e..fcac9369 100644 --- a/contrib/very-important-source-code/make-csv.pl +++ b/contrib/very-important-source-code/make-csv.pl @@ -58,7 +58,7 @@ sub merge {  		}  	}  	print "No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID\n"; -	for (sort { lc($a->{name}) cmp lc($b->{name}) } values %game_hash) { +	for (sort { $a->{name} cmp $b->{name} } values %game_hash) {  		my $g = {%$_};  		if (!defined $g->{key}) {  			$g->{key} = (sprintf "%04X", $g->{no}) . (join"", map { sprintf "%02X", int rand 256 } 0 .. 7) . '00'; diff --git a/csv/CMakeLists.txt b/csv/CMakeLists.txt index 7e80317c..7bafc7ff 100644 --- a/csv/CMakeLists.txt +++ b/csv/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-csv NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-csv NO-LINKER-SCRIPT LINKAGE) @@ -7,7 +7,7 @@  #include <QRegExp>  #include <QtGlobal> -#ifdef BUILD_opentrack_csv +#ifdef BUILD_csv  #   define CSV_EXPORT Q_DECL_EXPORT  #else  #   define CSV_EXPORT Q_DECL_IMPORT diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp index e43db7e4..b29c989a 100644 --- a/filter-accela/ftnoir_filter_accela.cpp +++ b/filter-accela/ftnoir_filter_accela.cpp @@ -12,11 +12,13 @@  #include "opentrack/plugin-api.hpp"  static constexpr double rot_gains[][2] = { +    { 4.0, 350 }, +    //{ 3.33, 200 },      { 2.66, 110 }, -    { 2.33, 80 }, -    { 2, 50 }, +    //{ 2.33, 85 }, +    //{ 2, 45 },      { 1.66, 30 }, -    { 1.33, 15 }, +    //{ 1.33, 15 },      { 1, 5 },      { .66, 1.4 },      { .33, .4 }, diff --git a/filter-accela/ftnoir_filter_accela.h b/filter-accela/ftnoir_filter_accela.h index 3242c9e1..94408fb1 100644 --- a/filter-accela/ftnoir_filter_accela.h +++ b/filter-accela/ftnoir_filter_accela.h @@ -11,7 +11,7 @@  #include <QMutex>  #include <QTimer> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #include "opentrack-compat/timer.hpp" diff --git a/filter-ewma2/ftnoir_filter_ewma2.h b/filter-ewma2/ftnoir_filter_ewma2.h index bf4e83ad..bdb9cedc 100644 --- a/filter-ewma2/ftnoir_filter_ewma2.h +++ b/filter-ewma2/ftnoir_filter_ewma2.h @@ -5,7 +5,7 @@  #include <QElapsedTimer>  #include <QWidget>  #include <QMutex> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/filter-kalman/ftnoir_filter_kalman.h b/filter-kalman/ftnoir_filter_kalman.h index a6f40bb7..773f61d5 100644 --- a/filter-kalman/ftnoir_filter_kalman.h +++ b/filter-kalman/ftnoir_filter_kalman.h @@ -16,7 +16,7 @@  #include <QString>  #include <QElapsedTimer>  #include <QWidget> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index f56641fb..778cbf08 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -41,4 +41,18 @@ if(LINUX)      target_link_libraries(opentrack procps)  endif() +set(c-props) +set(l-props) +if(CMAKE_COMPILER_IS_GNUCXX) +    set(c-props "-fvisibility=hidden -fvisibility-inlines-hidden") +    if(NOT APPLE) +        set(l-props "-Wl,--as-needed") +    endif() +endif() + +set_target_properties(opentrack PROPERTIES +    LINK_FLAGS "${l-props}" +    COMPILE_FLAGS "${c-props}" +) +  install(TARGETS opentrack DESTINATION .) diff --git a/gui/curve-config.cpp b/gui/curve-config.cpp index 2e9065b4..7cd78580 100644 --- a/gui/curve-config.cpp +++ b/gui/curve-config.cpp @@ -54,6 +54,12 @@ MapWidget::MapWidget(Mappings& m, main_settings& s) :                  qfc.setEnabled(qfcs[i].checkbox->isChecked());                  qfc.force_redraw();              } +             +            if (qfcs[i].axis >= 3) +                qfcs[i].qfc->set_snap(2, 5); +            else +                qfcs[i].qfc->set_snap(1, 5); +                          qfcs[i].qfc->setConfig(conf, name);          }      } diff --git a/gui/keyboard.h b/gui/keyboard.h index 62a9ce20..696df605 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -2,7 +2,7 @@  #include "ui_keyboard_listener.h"  #ifdef _WIN32  #include "opentrack/win32-shortcuts.h" -#include "opentrack/shortcuts.h" +#include "opentrack/keybinding-worker.hpp"  #endif  #include <QLabel>  #include <QKeyEvent> @@ -13,25 +13,32 @@ class KeyboardListener : public QLabel      Q_OBJECT      Ui_keyboard_listener ui;  #ifdef _WIN32 -    KeybindingWorker w; +    KeybindingWorker::Token token;  #endif  public:      KeyboardListener(QWidget* parent = nullptr) : QLabel(parent)  #ifdef _WIN32 -      , w([&](Key& k) -    { -        Qt::KeyboardModifiers m; -        QKeySequence k_; -        if (win_key::to_qt(k, k_, m)) -            key_pressed(static_cast<QVariant>(k_).toInt() | m); -    }, this->winId()) +      , token([&](const Key& k) { +        if(k.guid != "") +        { +            int mods = 0; +            if (k.alt) mods |= Qt::AltModifier; +            if (k.shift) mods |= Qt::ShiftModifier; +            if (k.ctrl) mods |= Qt::ControlModifier; +            joystick_button_pressed(k.guid, k.keycode | mods, k.held); +        } +        else +        { +            Qt::KeyboardModifiers m; +            QKeySequence k_; +            if (win_key::to_qt(k, k_, m)) +                key_pressed(static_cast<QVariant>(k_).toInt() | m); +        } +    })  #endif      {          ui.setupUi(this);          setFocusPolicy(Qt::StrongFocus); -#ifdef _WIN32 -        w.start(); -#endif      }  #ifndef _WIN32      void keyPressEvent(QKeyEvent* event) override @@ -47,4 +54,5 @@ public:  #endif  signals:      void key_pressed(QKeySequence k); +    void joystick_button_pressed(QString guid, int idx, bool held);  }; diff --git a/gui/main.cpp b/gui/main.cpp index 4e56b3df..43a8b0c6 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -5,8 +5,8 @@  #include "opentrack/opencv-camera-dialog.hpp"  #include "wizard.h"  #include "ui.h" -#include "opentrack/options.hpp"  #include "ui_install-driver-dialog.h" +#include "opentrack-compat/options.hpp"  using namespace options;  #include <QApplication>  #include <QCommandLineParser> diff --git a/gui/main.ui b/gui/main.ui index 532d3124..43f725af 100644 --- a/gui/main.ui +++ b/gui/main.ui @@ -7,8 +7,8 @@     <rect>      <x>0</x>      <y>0</y> -    <width>693</width> -    <height>575</height> +    <width>646</width> +    <height>435</height>     </rect>    </property>    <property name="windowIcon"> @@ -37,10 +37,10 @@       <number>0</number>      </property>      <property name="rightMargin"> -     <number>0</number> +     <number>6</number>      </property>      <property name="bottomMargin"> -     <number>0</number> +     <number>6</number>      </property>      <item>       <widget class="QFrame" name="frame"> @@ -53,7 +53,10 @@        <property name="lineWidth">         <number>0</number>        </property> -      <layout class="QGridLayout" name="gridLayout_5"> +      <layout class="QVBoxLayout" name="verticalLayout_5"> +       <property name="spacing"> +        <number>0</number> +       </property>         <property name="leftMargin">          <number>0</number>         </property> @@ -66,11 +69,14 @@         <property name="bottomMargin">          <number>0</number>         </property> -       <property name="spacing"> -        <number>0</number> -       </property> -       <item row="0" column="0"> +       <item>          <widget class="QFrame" name="top"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property>           <property name="frameShape">            <enum>QFrame::NoFrame</enum>           </property> @@ -88,26 +94,20 @@             <number>0</number>            </property>            <property name="bottomMargin"> -           <number>0</number> +           <number>4</number>            </property>            <item>             <widget class="QFrame" name="video_feed">              <property name="sizePolicy"> -             <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> +             <sizepolicy hsizetype="Maximum" vsizetype="Maximum">                <horstretch>0</horstretch>                <verstretch>0</verstretch>               </sizepolicy>              </property>              <property name="minimumSize">               <size> -              <width>480</width> -              <height>360</height> -             </size> -            </property> -            <property name="maximumSize"> -             <size> -              <width>480</width> -              <height>360</height> +              <width>320</width> +              <height>240</height>               </size>              </property>              <widget class="QFrame" name="video_frame"> @@ -115,12 +115,12 @@                <rect>                 <x>0</x>                 <y>0</y> -               <width>480</width> -               <height>360</height> +               <width>320</width> +               <height>240</height>                </rect>               </property>               <property name="sizePolicy"> -              <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> +              <sizepolicy hsizetype="Fixed" vsizetype="Fixed">                 <horstretch>0</horstretch>                 <verstretch>0</verstretch>                </sizepolicy> @@ -130,8 +130,8 @@                 <rect>                  <x>0</x>                  <y>0</y> -                <width>480</width> -                <height>360</height> +                <width>320</width> +                <height>240</height>                 </rect>                </property>                <property name="sizePolicy"> @@ -142,83 +142,761 @@                </property>                <property name="minimumSize">                 <size> -                <width>480</width> -                <height>360</height> +                <width>320</width> +                <height>240</height>                 </size>                </property>                <property name="maximumSize">                 <size> -                <width>480</width> -                <height>360</height> +                <width>320</width> +                <height>240</height>                 </size>                </property>                <property name="text">                 <string/>                </property> +              <property name="pixmap"> +               <pixmap resource="ui-res.qrc">:/images/no-feed.png</pixmap> +              </property> +              <property name="scaledContents"> +               <bool>true</bool> +              </property>               </widget>              </widget>             </widget>            </item>            <item> -           <widget class="QFrame" name="top_display"> -            <property name="frameShape"> -             <enum>QFrame::NoFrame</enum> +           <widget class="GLWidget" name="pose_display" native="true"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy>              </property> -            <property name="lineWidth"> -             <number>0</number> +            <property name="minimumSize"> +             <size> +              <width>320</width> +              <height>240</height> +             </size> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QFrame" name="top_display"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property> +         <property name="frameShape"> +          <enum>QFrame::NoFrame</enum> +         </property> +         <property name="lineWidth"> +          <number>0</number> +         </property> +         <layout class="QHBoxLayout" name="horizontalLayout_3"> +          <property name="spacing"> +           <number>6</number> +          </property> +          <property name="leftMargin"> +           <number>5</number> +          </property> +          <property name="topMargin"> +           <number>0</number> +          </property> +          <property name="rightMargin"> +           <number>0</number> +          </property> +          <property name="bottomMargin"> +           <number>6</number> +          </property> +          <item> +           <widget class="QGroupBox" name="box_raw_headpose"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="title"> +             <string notr="true">Raw tracker data</string>              </property> -            <layout class="QVBoxLayout"> +            <layout class="QGridLayout" name="gridLayout_12"> +             <property name="leftMargin"> +              <number>0</number> +             </property> +             <property name="topMargin"> +              <number>0</number> +             </property> +             <property name="rightMargin"> +              <number>0</number> +             </property> +             <property name="bottomMargin"> +              <number>0</number> +             </property>               <property name="spacing"> -              <number>12</number> +              <number>0</number>               </property> +             <item row="0" column="3"> +              <widget class="QLCDNumber" name="raw_yaw"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="0"> +              <widget class="QLabel" name="lblZ_4"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TZ</string> +               </property> +              </widget> +             </item> +             <item row="1" column="2"> +              <widget class="QLabel" name="lblRotY_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>pitch</string> +               </property> +              </widget> +             </item> +             <item row="1" column="3"> +              <widget class="QLCDNumber" name="raw_pitch"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="1" column="0"> +              <widget class="QLabel" name="lblY_4"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TY</string> +               </property> +              </widget> +             </item> +             <item row="0" column="0"> +              <widget class="QLabel" name="lblX_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TX</string> +               </property> +              </widget> +             </item> +             <item row="0" column="1"> +              <widget class="QLCDNumber" name="raw_x"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="2"> +              <widget class="QLabel" name="lblRotZ_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>roll</string> +               </property> +              </widget> +             </item> +             <item row="0" column="2"> +              <widget class="QLabel" name="lblRotX_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>yaw</string> +               </property> +              </widget> +             </item> +             <item row="1" column="1"> +              <widget class="QLCDNumber" name="raw_y"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="3"> +              <widget class="QLCDNumber" name="raw_roll"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="1"> +              <widget class="QLCDNumber" name="raw_z"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +          <item> +           <widget class="QGroupBox" name="box_mapped_headpose"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="title"> +             <string notr="true">Game data</string> +            </property> +            <layout class="QGridLayout" name="gridLayout_14">               <property name="leftMargin"> -              <number>6</number> +              <number>0</number>               </property>               <property name="topMargin"> -              <number>12</number> +              <number>0</number>               </property>               <property name="rightMargin"> -              <number>8</number> +              <number>0</number>               </property>               <property name="bottomMargin"> -              <number>4</number> +              <number>0</number>               </property> -             <item> -              <widget class="GLWidget" name="pose_display" native="true"> +             <property name="spacing"> +              <number>0</number> +             </property> +             <item row="1" column="3"> +              <widget class="QLCDNumber" name="pose_pitch"> +               <property name="enabled"> +                <bool>true</bool> +               </property>                 <property name="sizePolicy"> -                <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum">                   <horstretch>0</horstretch>                   <verstretch>0</verstretch>                  </sizepolicy>                 </property> -               <property name="maximumSize"> -                <size> -                 <width>110</width> -                 <height>120</height> -                </size> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum>                 </property>                </widget>               </item> -             <item> -              <widget class="QGroupBox" name="box_raw_headpose"> +             <item row="0" column="3"> +              <widget class="QLCDNumber" name="pose_yaw"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="1"> +              <widget class="QLCDNumber" name="pose_z"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="0" column="0"> +              <widget class="QLabel" name="lblx">                 <property name="sizePolicy"> -                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum">                   <horstretch>0</horstretch>                   <verstretch>0</verstretch>                  </sizepolicy>                 </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TX</string> +               </property> +              </widget> +             </item> +             <item row="1" column="0"> +              <widget class="QLabel" name="lblY_2"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TY</string> +               </property> +              </widget> +             </item> +             <item row="0" column="1"> +              <widget class="QLCDNumber" name="pose_x"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="1" column="2"> +              <widget class="QLabel" name="lblRotY_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>pitch</string> +               </property> +              </widget> +             </item> +             <item row="2" column="2"> +              <widget class="QLabel" name="lblRotZ_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>roll</string> +               </property> +              </widget> +             </item> +             <item row="0" column="2"> +              <widget class="QLabel" name="lblRotX_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>yaw</string> +               </property> +              </widget> +             </item> +             <item row="2" column="0"> +              <widget class="QLabel" name="lblZ_2"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>TZ</string> +               </property> +              </widget> +             </item> +             <item row="1" column="1"> +              <widget class="QLCDNumber" name="pose_y"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="3"> +              <widget class="QLCDNumber" name="pose_roll"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QFrame" name="bottom_controls"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property> +         <layout class="QGridLayout" name="gridLayout_2"> +          <property name="leftMargin"> +           <number>6</number> +          </property> +          <property name="topMargin"> +           <number>0</number> +          </property> +          <property name="rightMargin"> +           <number>0</number> +          </property> +          <property name="bottomMargin"> +           <number>0</number> +          </property> +          <property name="spacing"> +           <number>6</number> +          </property> +          <item row="0" column="0"> +           <widget class="QFrame" name="frame_2"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +              <horstretch>4</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="frameShape"> +             <enum>QFrame::NoFrame</enum> +            </property> +            <property name="frameShadow"> +             <enum>QFrame::Raised</enum> +            </property> +            <layout class="QVBoxLayout" name="verticalLayout"> +             <property name="spacing"> +              <number>2</number> +             </property> +             <property name="leftMargin"> +              <number>3</number> +             </property> +             <property name="topMargin"> +              <number>2</number> +             </property> +             <property name="rightMargin"> +              <number>3</number> +             </property> +             <property name="bottomMargin"> +              <number>8</number> +             </property> +             <item> +              <widget class="QGroupBox" name="groupGameProtocol">                 <property name="title"> -                <string notr="true">Raw tracker data</string> +                <string>Protocol</string>                 </property> -               <layout class="QGridLayout" name="gridLayout_12"> +               <layout class="QGridLayout" name="gridLayout_4">                  <property name="leftMargin"> -                 <number>0</number> +                 <number>4</number>                  </property>                  <property name="topMargin">                   <number>0</number>                  </property>                  <property name="rightMargin"> -                 <number>0</number> +                 <number>4</number>                  </property>                  <property name="bottomMargin">                   <number>0</number> @@ -227,322 +905,47 @@                   <number>3</number>                  </property>                  <property name="verticalSpacing"> -                 <number>2</number> +                 <number>0</number>                  </property> -                <item row="0" column="1"> -                 <widget class="QLCDNumber" name="raw_x"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="0" column="2"> -                 <widget class="QLabel" name="lblRotX_4"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>yaw</string> -                  </property> -                 </widget> -                </item> -                <item row="2" column="2"> -                 <widget class="QLabel" name="lblRotZ_4"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>roll</string> -                  </property> -                 </widget> -                </item> -                <item row="2" column="0"> -                 <widget class="QLabel" name="lblZ_4"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="autoFillBackground"> -                   <bool>false</bool> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>TZ</string> -                  </property> -                 </widget> -                </item> -                <item row="1" column="2"> -                 <widget class="QLabel" name="lblRotY_4"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>pitch</string> -                  </property> -                 </widget> +                <item row="1" column="0"> +                 <widget class="QComboBox" name="iconcomboProtocol"/>                  </item>                  <item row="1" column="1"> -                 <widget class="QLCDNumber" name="raw_y"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="0" column="3"> -                 <widget class="QLCDNumber" name="raw_yaw"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="2" column="3"> -                 <widget class="QLCDNumber" name="raw_roll"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="2" column="1"> -                 <widget class="QLCDNumber" name="raw_z"> +                 <widget class="QToolButton" name="btnShowServerControls">                    <property name="enabled">                     <bool>true</bool>                    </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="0" column="0"> -                 <widget class="QLabel" name="lblX_4"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property>                    <property name="text"> -                   <string>TX</string> -                  </property> -                 </widget> -                </item> -                <item row="1" column="3"> -                 <widget class="QLCDNumber" name="raw_pitch"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Plain</enum> -                  </property> -                  <property name="lineWidth"> -                   <number>1</number> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Outline</enum> -                  </property> -                 </widget> -                </item> -                <item row="1" column="0"> -                 <widget class="QLabel" name="lblY_4"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> +                   <string>...</string>                    </property> -                  <property name="autoFillBackground"> +                  <property name="flat" stdset="0">                     <bool>false</bool>                    </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>TY</string> -                  </property>                   </widget>                  </item>                 </layout>                </widget>               </item>               <item> -              <widget class="QGroupBox" name="box_mapped_headpose"> +              <widget class="QGroupBox" name="groupStartStop">                 <property name="sizePolicy"> -                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> -                 <horstretch>0</horstretch> +                <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                 <horstretch>3</horstretch>                   <verstretch>0</verstretch>                  </sizepolicy>                 </property>                 <property name="title"> -                <string notr="true">Game data</string> +                <string notr="true">Controls</string>                 </property> -               <layout class="QGridLayout" name="gridLayout_14"> +               <layout class="QHBoxLayout" name="horizontalLayout_4"> +                <property name="spacing"> +                 <number>8</number> +                </property>                  <property name="leftMargin">                   <number>0</number>                  </property>                  <property name="topMargin"> -                 <number>0</number> +                 <number>4</number>                  </property>                  <property name="rightMargin">                   <number>0</number> @@ -550,267 +953,32 @@                  <property name="bottomMargin">                   <number>0</number>                  </property> -                <property name="horizontalSpacing"> -                 <number>3</number> -                </property> -                <property name="verticalSpacing"> -                 <number>2</number> -                </property> -                <item row="1" column="0"> -                 <widget class="QLabel" name="lblY_2"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> +                <item> +                 <widget class="QToolButton" name="btnStartTracker">                    <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Preferred">                      <horstretch>0</horstretch>                      <verstretch>0</verstretch>                     </sizepolicy>                    </property> -                  <property name="autoFillBackground"> -                   <bool>false</bool> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property>                    <property name="text"> -                   <string>TY</string> +                   <string>Start</string>                    </property>                   </widget>                  </item> -                <item row="2" column="0"> -                 <widget class="QLabel" name="lblZ_2"> +                <item> +                 <widget class="QToolButton" name="btnStopTracker">                    <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="autoFillBackground">                     <bool>false</bool>                    </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>TZ</string> -                  </property> -                 </widget> -                </item> -                <item row="2" column="2"> -                 <widget class="QLabel" name="lblRotZ_2">                    <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Preferred">                      <horstretch>0</horstretch>                      <verstretch>0</verstretch>                     </sizepolicy>                    </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property>                    <property name="text"> -                   <string>roll</string> -                  </property> -                 </widget> -                </item> -                <item row="0" column="1"> -                 <widget class="QLCDNumber" name="pose_x"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> -                  </property> -                 </widget> -                </item> -                <item row="0" column="2"> -                 <widget class="QLabel" name="lblRotX_2"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>yaw</string> -                  </property> -                 </widget> -                </item> -                <item row="1" column="2"> -                 <widget class="QLabel" name="lblRotY_2"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>pitch</string> -                  </property> -                 </widget> -                </item> -                <item row="0" column="0"> -                 <widget class="QLabel" name="lblx"> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShadow"> -                   <enum>QFrame::Raised</enum> -                  </property> -                  <property name="text"> -                   <string>TX</string> -                  </property> -                 </widget> -                </item> -                <item row="1" column="3"> -                 <widget class="QLCDNumber" name="pose_pitch"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> -                  </property> -                 </widget> -                </item> -                <item row="1" column="1"> -                 <widget class="QLCDNumber" name="pose_y"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> -                  </property> -                 </widget> -                </item> -                <item row="2" column="3"> -                 <widget class="QLCDNumber" name="pose_roll"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> -                  </property> -                 </widget> -                </item> -                <item row="2" column="1"> -                 <widget class="QLCDNumber" name="pose_z"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> -                  </property> -                 </widget> -                </item> -                <item row="0" column="3"> -                 <widget class="QLCDNumber" name="pose_yaw"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property> -                  <property name="frameShape"> -                   <enum>QFrame::NoFrame</enum> -                  </property> -                  <property name="smallDecimalPoint"> -                   <bool>true</bool> -                  </property> -                  <property name="digitCount"> -                   <number>4</number> -                  </property> -                  <property name="segmentStyle"> -                   <enum>QLCDNumber::Flat</enum> +                   <string>Stop</string>                    </property>                   </widget>                  </item> @@ -820,141 +988,89 @@              </layout>             </widget>            </item> -         </layout> -        </widget> -       </item> -       <item row="1" column="0"> -        <widget class="QFrame" name="bottom_controls"> -         <property name="sizePolicy"> -          <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> -           <horstretch>0</horstretch> -           <verstretch>0</verstretch> -          </sizepolicy> -         </property> -         <layout class="QGridLayout" name="gridLayout_2"> -          <property name="leftMargin"> -           <number>4</number> -          </property> -          <property name="topMargin"> -           <number>8</number> -          </property> -          <property name="rightMargin"> -           <number>10</number> -          </property> -          <property name="bottomMargin"> -           <number>0</number> -          </property> -          <property name="horizontalSpacing"> -           <number>4</number> -          </property> -          <property name="verticalSpacing"> -           <number>0</number> -          </property> -          <item row="1" column="1"> -           <widget class="QGroupBox" name="groupWindows"> +          <item row="0" column="1"> +           <widget class="QFrame" name="groupWindows">              <property name="sizePolicy">               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">                <horstretch>4</horstretch>                <verstretch>0</verstretch>               </sizepolicy>              </property> -            <property name="title"> -             <string>Settings</string> -            </property> -            <property name="flat"> -             <bool>true</bool> +            <property name="lineWidth"> +             <number>0</number>              </property>              <layout class="QVBoxLayout" name="verticalLayout_3">               <property name="spacing">                <number>3</number>               </property>               <property name="leftMargin"> -              <number>4</number> +              <number>0</number>               </property>               <property name="topMargin"> -              <number>2</number> +              <number>0</number>               </property>               <property name="rightMargin">                <number>0</number>               </property>               <property name="bottomMargin"> -              <number>6</number> +              <number>0</number>               </property>               <item> -              <widget class="QGroupBox" name="groupGameProtocol"> -               <property name="title"> -                <string>Protocol</string> +              <widget class="QFrame" name="groupProfile"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy>                 </property> -               <layout class="QGridLayout" name="gridLayout_4"> +               <layout class="QHBoxLayout" name="horizontalLayout"> +                <property name="spacing"> +                 <number>0</number> +                </property>                  <property name="leftMargin"> -                 <number>4</number> +                 <number>0</number>                  </property>                  <property name="topMargin">                   <number>0</number>                  </property>                  <property name="rightMargin"> -                 <number>4</number> -                </property> -                <property name="bottomMargin">                   <number>0</number>                  </property> -                <property name="horizontalSpacing"> -                 <number>3</number> -                </property> -                <property name="verticalSpacing"> +                <property name="bottomMargin">                   <number>0</number>                  </property> -                <item row="0" column="0"> -                 <widget class="QComboBox" name="iconcomboProtocol"/> -                </item> -                <item row="0" column="1"> -                 <widget class="QToolButton" name="btnShowServerControls"> -                  <property name="enabled"> -                   <bool>true</bool> -                  </property> -                  <property name="text"> -                   <string>...</string> -                  </property> -                  <property name="flat" stdset="0"> -                   <bool>false</bool> -                  </property> -                 </widget> -                </item>                 </layout>                </widget>               </item>               <item> -              <widget class="QFrame" name="groupProfile"> +              <widget class="QFrame" name="frame_3">                 <property name="sizePolicy"> -                <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum">                   <horstretch>0</horstretch> -                 <verstretch>2</verstretch> +                 <verstretch>0</verstretch>                  </sizepolicy>                 </property> -               <layout class="QHBoxLayout" name="horizontalLayout"> +               <layout class="QHBoxLayout" name="horizontalLayout_5">                  <property name="spacing">                   <number>0</number>                  </property>                  <property name="leftMargin">                   <number>0</number>                  </property> +                <property name="topMargin"> +                 <number>0</number> +                </property>                  <property name="rightMargin"> -                 <number>2</number> +                 <number>0</number>                  </property>                  <property name="bottomMargin"> -                 <number>2</number> +                 <number>0</number>                  </property>                  <item>                   <widget class="QToolButton" name="profile_button">                    <property name="enabled">                     <bool>true</bool>                    </property> -                  <property name="sizePolicy"> -                   <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> -                    <horstretch>0</horstretch> -                    <verstretch>0</verstretch> -                   </sizepolicy> -                  </property>                    <property name="text">                     <string>Profile</string>                    </property> @@ -975,7 +1091,7 @@                  <item>                   <widget class="QComboBox" name="iconcomboProfile">                    <property name="sizePolicy"> -                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">                      <horstretch>0</horstretch>                      <verstretch>0</verstretch>                     </sizepolicy> @@ -991,9 +1107,9 @@               <item>                <widget class="QPushButton" name="btnEditCurves">                 <property name="sizePolicy"> -                <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                <sizepolicy hsizetype="Preferred" vsizetype="Fixed">                   <horstretch>0</horstretch> -                 <verstretch>3</verstretch> +                 <verstretch>0</verstretch>                  </sizepolicy>                 </property>                 <property name="text"> @@ -1014,9 +1130,9 @@               <item>                <widget class="QPushButton" name="btnShortcuts">                 <property name="sizePolicy"> -                <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                <sizepolicy hsizetype="Preferred" vsizetype="Fixed">                   <horstretch>0</horstretch> -                 <verstretch>3</verstretch> +                 <verstretch>0</verstretch>                  </sizepolicy>                 </property>                 <property name="text"> @@ -1037,68 +1153,6 @@              </layout>             </widget>            </item> -          <item row="1" column="0"> -           <widget class="QGroupBox" name="groupStartStop"> -            <property name="sizePolicy"> -             <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> -              <horstretch>3</horstretch> -              <verstretch>0</verstretch> -             </sizepolicy> -            </property> -            <property name="title"> -             <string notr="true">Controls</string> -            </property> -            <property name="flat"> -             <bool>true</bool> -            </property> -            <layout class="QVBoxLayout" name="verticalLayout_4"> -             <property name="spacing"> -              <number>8</number> -             </property> -             <property name="leftMargin"> -              <number>0</number> -             </property> -             <property name="topMargin"> -              <number>8</number> -             </property> -             <property name="rightMargin"> -              <number>0</number> -             </property> -             <property name="bottomMargin"> -              <number>9</number> -             </property> -             <item> -              <widget class="QToolButton" name="btnStartTracker"> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string>Start</string> -               </property> -              </widget> -             </item> -             <item> -              <widget class="QToolButton" name="btnStopTracker"> -               <property name="enabled"> -                <bool>false</bool> -               </property> -               <property name="sizePolicy"> -                <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> -                 <horstretch>0</horstretch> -                 <verstretch>0</verstretch> -                </sizepolicy> -               </property> -               <property name="text"> -                <string>Stop</string> -               </property> -              </widget> -             </item> -            </layout> -           </widget> -          </item>           </layout>          </widget>         </item> @@ -1116,12 +1170,12 @@    </customwidget>   </customwidgets>   <tabstops> -  <tabstop>btnStartTracker</tabstop>    <tabstop>btnStopTracker</tabstop>    <tabstop>iconcomboProtocol</tabstop>    <tabstop>btnShowServerControls</tabstop> -  <tabstop>btnEditCurves</tabstop>    <tabstop>btnShortcuts</tabstop> +  <tabstop>profile_button</tabstop> +  <tabstop>iconcomboProfile</tabstop>   </tabstops>   <resources>    <include location="ui-res.qrc"/> diff --git a/gui/new_file_dialog.h b/gui/new_file_dialog.h index 3a35cf71..5fdabb3a 100644 --- a/gui/new_file_dialog.h +++ b/gui/new_file_dialog.h @@ -1,7 +1,7 @@  #pragma once  #include "ui_new_config.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include <QFile>  #include <QRegExp>  #include <QString> diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 06346b25..1e734135 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -11,38 +11,42 @@  #include "keyboard.h"  #include <QPushButton>  #include <QLayout> +#include <QDialog> -OptionsDialog::OptionsDialog(State& state) : state(state), trans_calib_running(false) +static QString kopts_to_string(const key_opts& kopts)  { -    ui.setupUi( this ); +    if (static_cast<QString>(kopts.guid) != "") +    { +        const int btn = kopts.button & ~Qt::KeyboardModifierMask; +        const int mods = kopts.button & Qt::KeyboardModifierMask; +        QString mm; +        if (mods & Qt::ControlModifier) mm += "Control+"; +        if (mods & Qt::AltModifier) mm += "Alt+"; +        if (mods & Qt::ShiftModifier) mm += "Shift+"; +        return mm + "Joy button " + QString::number(btn); +    } +    if (static_cast<QString>(kopts.keycode) == "") +        return "None"; +    return kopts.keycode; +} + +OptionsDialog::OptionsDialog(main_settings& main, +                             State& state, +                             std::function<void()> register_global_keys, +                             std::function<void(bool)> pause_keybindings) : +    main(main), +    state(state), +    register_global_keys(register_global_keys), +    pause_keybindings(pause_keybindings) +{ +    ui.setupUi(this);      connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));      connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); -    tie_setting(s.s_main.tray_enabled, ui.trayp); -     -    tie_setting(s.s_main.center_at_startup, ui.center_at_startup); +    tie_setting(main.tray_enabled, ui.trayp); -    tie_setting(s.s_main.tcomp_p, ui.tcomp_enable); -    tie_setting(s.s_main.tcomp_tz, ui.tcomp_rz); - -    tie_setting(s.s_main.a_yaw.invert, ui.invert_yaw); -    tie_setting(s.s_main.a_pitch.invert, ui.invert_pitch); -    tie_setting(s.s_main.a_roll.invert, ui.invert_roll); -    tie_setting(s.s_main.a_x.invert, ui.invert_x); -    tie_setting(s.s_main.a_y.invert, ui.invert_y); -    tie_setting(s.s_main.a_z.invert, ui.invert_z); - -    tie_setting(s.s_main.a_yaw.src, ui.src_yaw); -    tie_setting(s.s_main.a_pitch.src, ui.src_pitch); -    tie_setting(s.s_main.a_roll.src, ui.src_roll); -    tie_setting(s.s_main.a_x.src, ui.src_x); -    tie_setting(s.s_main.a_y.src, ui.src_y); -    tie_setting(s.s_main.a_z.src, ui.src_z); -     -    tie_setting(s.s_main.camera_yaw, ui.camera_yaw); -    tie_setting(s.s_main.camera_pitch, ui.camera_pitch); -    tie_setting(s.s_main.camera_roll, ui.camera_roll); +    tie_setting(main.center_at_startup, ui.center_at_startup);      tie_setting(pt.camera_mode, ui.camera_mode); @@ -86,48 +90,96 @@ OptionsDialog::OptionsDialog(State& state) : state(state), trans_calib_running(f      timer.start(100); -    connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center.keycode, ui.center_text); }); -    connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero.keycode, ui.zero_text); }); -    connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle.keycode, ui.toggle_text); }); +    tie_setting(main.tcomp_p, ui.tcomp_enable); +    tie_setting(main.tcomp_tz, ui.tcomp_rz); + +    tie_setting(main.a_yaw.invert, ui.invert_yaw); +    tie_setting(main.a_pitch.invert, ui.invert_pitch); +    tie_setting(main.a_roll.invert, ui.invert_roll); +    tie_setting(main.a_x.invert, ui.invert_x); +    tie_setting(main.a_y.invert, ui.invert_y); +    tie_setting(main.a_z.invert, ui.invert_z); -    ui.center_text->setText(s.center.keycode == "" ? "None" : static_cast<QString>(s.center.keycode)); -    ui.toggle_text->setText(s.toggle.keycode == "" ? "None" : static_cast<QString>(s.toggle.keycode)); -    ui.zero_text->setText(s.zero.keycode == "" ? "None" : static_cast<QString>(s.zero.keycode)); +    tie_setting(main.a_yaw.src, ui.src_yaw); +    tie_setting(main.a_pitch.src, ui.src_pitch); +    tie_setting(main.a_roll.src, ui.src_roll); +    tie_setting(main.a_x.src, ui.src_x); +    tie_setting(main.a_y.src, ui.src_y); +    tie_setting(main.a_z.src, ui.src_z); +     +    tie_setting(main.camera_yaw, ui.camera_yaw); +    tie_setting(main.camera_pitch, ui.camera_pitch); +    tie_setting(main.camera_roll, ui.camera_roll); + +    tie_setting(main.center_method, ui.center_method); + +    connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(main.key_center, ui.center_text); }); +    connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(main.key_zero, ui.zero_text); }); +    connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle, ui.toggle_text); }); +    connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(main.key_start_tracking, ui.start_tracking_text); }); +    connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(main.key_stop_tracking, ui.stop_tracking_text); }); +    connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle_tracking, ui.toggle_tracking_text); }); + +    ui.center_text->setText(kopts_to_string(main.key_center)); +    ui.toggle_text->setText(kopts_to_string(main.key_toggle)); +    ui.zero_text->setText(kopts_to_string(main.key_zero)); +     +    ui.start_tracking_text->setText(kopts_to_string(main.key_start_tracking)); +    ui.stop_tracking_text->setText(kopts_to_string(main.key_stop_tracking)); +    ui.toggle_tracking_text->setText(kopts_to_string(main.key_toggle_tracking));  } -void OptionsDialog::bind_key(value<QString>& ret, QLabel* label) +void OptionsDialog::bind_key(key_opts& kopts, QLabel* label)  { -    ret = ""; -    QDialog d; +    kopts.button = -1; +    kopts.guid = ""; +    kopts.keycode = ""; +    QDialog d(this);      auto l = new QHBoxLayout;      l->setMargin(0); -    auto k = new KeyboardListener; -    l->addWidget(k); +    KeyboardListener k; +    l->addWidget(&k);      d.setLayout(l);      d.setFixedSize(QSize(500, 300));      d.setWindowFlags(Qt::Dialog); -    connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { ret = s.toString(QKeySequence::PortableText); d.close(); }); +    d.setWindowModality(Qt::ApplicationModal); +    connect(&k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { +        kopts.keycode = s.toString(QKeySequence::PortableText); +        kopts.guid = ""; +        kopts.button = -1; +        d.close(); +    }); +    connect(&k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx, bool held) -> void { +        if (!held) +        { +            kopts.guid = guid; +            kopts.keycode = ""; +            kopts.button = idx; +            d.close(); +        } +    }); +    pause_keybindings(true); +    d.show();      d.exec(); -    label->setText(ret == "" ? "None" : static_cast<QString>(ret)); -    delete k; +    pause_keybindings(false); +    register_global_keys(); +    label->setText(kopts_to_string(kopts));      delete l;  }  void OptionsDialog::doOK() { -    s.b->save();      pt.b->save(); -    s.s_main.b->save();      acc.b->save(); +    main.b->save();      ui.game_detector->save();      this->close();      emit reload();  }  void OptionsDialog::doCancel() { -    s.b->reload();      pt.b->reload(); -    s.s_main.b->reload();      acc.b->reload(); +    main.b->reload();      ui.game_detector->revert();      close();  } diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 8fc16611..f333c690 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -10,6 +10,9 @@  #include "trans_calib.h"  #include "tracker-pt/ftnoir_tracker_pt.h"  #include "filter-accela/ftnoir_filter_accela.h" +#include <QObject> +#include <QWidget> +#include <functional>  class OptionsDialog: public QWidget  { @@ -17,14 +20,16 @@ class OptionsDialog: public QWidget  signals:      void reload();  public: -    OptionsDialog(State &state); +    OptionsDialog(main_settings& main, State& state, std::function<void()> register_global_keys, std::function<void(bool)> pause_keybindings);  private: +    main_settings& main; +    State& state; +    std::function<void()> register_global_keys; +    std::function<void(bool)> pause_keybindings;      Ui::UI_Settings ui; -    Shortcuts::settings s;      settings_pt pt;      settings_accela acc;      QTimer timer; -    State& state;      TranslationCalibrator trans_calib;      bool trans_calib_running; @@ -42,5 +47,5 @@ private slots:      void startstop_trans_calib(bool start);      void poll_tracker_info();      void trans_calib_step(); -    void bind_key(value<QString>& ret, QLabel* label); +    void bind_key(key_opts &kopts, QLabel* label);  }; diff --git a/gui/process_detector.h b/gui/process_detector.h index f6497c90..e395e1a2 100644 --- a/gui/process_detector.h +++ b/gui/process_detector.h @@ -13,7 +13,7 @@  #include <QTableWidget>  #include <QResizeEvent> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  class FancyTable : public QTableWidget diff --git a/gui/settings.ui b/gui/settings.ui index 5bf819fd..cb292a35 100644 --- a/gui/settings.ui +++ b/gui/settings.ui @@ -7,7 +7,7 @@      <x>0</x>      <y>0</y>      <width>428</width> -    <height>535</height> +    <height>525</height>     </rect>    </property>    <property name="windowTitle"> @@ -34,6 +34,33 @@         <string>Shortcuts</string>        </attribute>        <layout class="QGridLayout" name="gridLayout_9"> +       <item row="2" column="0"> +        <widget class="QCheckBox" name="center_at_startup"> +         <property name="text"> +          <string>Center at startup</string> +         </property> +        </widget> +       </item> +       <item row="4" column="0"> +        <spacer name="verticalSpacer"> +         <property name="orientation"> +          <enum>Qt::Vertical</enum> +         </property> +         <property name="sizeHint" stdset="0"> +          <size> +           <width>20</width> +           <height>40</height> +          </size> +         </property> +        </spacer> +       </item> +       <item row="3" column="0"> +        <widget class="QCheckBox" name="trayp"> +         <property name="text"> +          <string>Minimize to tray</string> +         </property> +        </widget> +       </item>         <item row="0" column="0">          <widget class="QGroupBox" name="groupBox_8">           <property name="title"> @@ -62,8 +89,15 @@               <string notr="true">QGroupBox { border: 0; }</string>              </property>              <layout class="QGridLayout" name="gridLayout_8"> -             <item row="0" column="1"> -              <widget class="QLabel" name="center_text"> +             <item row="6" column="1"> +              <widget class="QLabel" name="zero_text"> +               <property name="text"> +                <string/> +               </property> +              </widget> +             </item> +             <item row="5" column="1"> +              <widget class="QLabel" name="toggle_text">                 <property name="text">                  <string/>                 </property> @@ -79,17 +113,10 @@                 </property>                </widget>               </item> -             <item row="6" column="1"> -              <widget class="QLabel" name="zero_text"> -               <property name="text"> -                <string/> -               </property> -              </widget> -             </item> -             <item row="5" column="1"> -              <widget class="QLabel" name="toggle_text"> +             <item row="0" column="2"> +              <widget class="QPushButton" name="bind_center">                 <property name="text"> -                <string/> +                <string>Bind</string>                 </property>                </widget>               </item> @@ -113,8 +140,8 @@                 </property>                </widget>               </item> -             <item row="0" column="2"> -              <widget class="QPushButton" name="bind_center"> +             <item row="6" column="2"> +              <widget class="QPushButton" name="bind_zero">                 <property name="text">                  <string>Bind</string>                 </property> @@ -127,13 +154,85 @@                 </property>                </widget>               </item> -             <item row="6" column="2"> -              <widget class="QPushButton" name="bind_zero"> +             <item row="7" column="0"> +              <widget class="QLabel" name="textLabel2_7"> +               <property name="text"> +                <string>Start tracking</string> +               </property> +               <property name="wordWrap"> +                <bool>false</bool> +               </property> +              </widget> +             </item> +             <item row="0" column="1"> +              <widget class="QLabel" name="center_text"> +               <property name="text"> +                <string/> +               </property> +              </widget> +             </item> +             <item row="8" column="0"> +              <widget class="QLabel" name="textLabel2_8"> +               <property name="text"> +                <string>Stop tracking</string> +               </property> +               <property name="wordWrap"> +                <bool>false</bool> +               </property> +              </widget> +             </item> +             <item row="9" column="0"> +              <widget class="QLabel" name="textLabel2_9"> +               <property name="text"> +                <string>Toggle tracking</string> +               </property> +               <property name="wordWrap"> +                <bool>false</bool> +               </property> +              </widget> +             </item> +             <item row="7" column="2"> +              <widget class="QPushButton" name="bind_start"> +               <property name="text"> +                <string>Bind</string> +               </property> +              </widget> +             </item> +             <item row="8" column="2"> +              <widget class="QPushButton" name="bind_stop">                 <property name="text">                  <string>Bind</string>                 </property>                </widget>               </item> +             <item row="9" column="2"> +              <widget class="QPushButton" name="bind_toggle_tracking"> +               <property name="text"> +                <string>Bind</string> +               </property> +              </widget> +             </item> +             <item row="7" column="1"> +              <widget class="QLabel" name="start_tracking_text"> +               <property name="text"> +                <string/> +               </property> +              </widget> +             </item> +             <item row="8" column="1"> +              <widget class="QLabel" name="stop_tracking_text"> +               <property name="text"> +                <string/> +               </property> +              </widget> +             </item> +             <item row="9" column="1"> +              <widget class="QLabel" name="toggle_tracking_text"> +               <property name="text"> +                <string/> +               </property> +              </widget> +             </item>              </layout>             </widget>            </item> @@ -141,32 +240,45 @@          </widget>         </item>         <item row="1" column="0"> -        <widget class="QCheckBox" name="center_at_startup"> -         <property name="text"> -          <string>Center at startup</string> -         </property> -        </widget> -       </item> -       <item row="2" column="0"> -        <widget class="QCheckBox" name="trayp"> -         <property name="text"> -          <string>Minimize to tray</string> +        <widget class="QGroupBox" name="groupBox_9111"> +         <property name="title"> +          <string>Centering method</string>           </property> +         <layout class="QGridLayout" name="gridLayout111"> +          <item row="1" column="0"> +           <widget class="QLabel" name="label_26"> +            <property name="text"> +             <string>Method</string> +            </property> +           </widget> +          </item> +          <item row="1" column="1"> +           <widget class="QComboBox" name="center_method"> +            <item> +             <property name="text"> +              <string>Relative (inertial device)</string> +             </property> +            </item> +            <item> +             <property name="text"> +              <string>Absolute (camera device)</string> +             </property> +            </item> +           </widget> +          </item> +          <item row="0" column="1"> +           <widget class="QLabel" name="label_25"> +            <property name="text"> +             <string>Try changing this if centering doesn't perform correctly for your input device.</string> +            </property> +            <property name="wordWrap"> +             <bool>true</bool> +            </property> +           </widget> +          </item> +         </layout>          </widget>         </item> -       <item row="3" column="0"> -        <spacer name="verticalSpacer"> -         <property name="orientation"> -          <enum>Qt::Vertical</enum> -         </property> -         <property name="sizeHint" stdset="0"> -          <size> -           <width>20</width> -           <height>40</height> -          </size> -         </property> -        </spacer> -       </item>        </layout>       </widget>       <widget class="QWidget" name="tab_3"> diff --git a/gui/software-update-dialog.hpp b/gui/software-update-dialog.hpp index fe132402..21d92ecc 100644 --- a/gui/software-update-dialog.hpp +++ b/gui/software-update-dialog.hpp @@ -7,7 +7,7 @@  #include <QRegExp>  #include <functional>  #include "ui_software-update.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  extern "C" const char* opentrack_version; @@ -8,9 +8,9 @@  #include "ui.h"  #include "opentrack/tracker.h" -#include "opentrack/options.hpp"  #include "tracker-pt/ftnoir_tracker_pt.h"  #include "filter-accela/ftnoir_filter_accela.h" +#include "opentrack-compat/options.hpp"  #include "new_file_dialog.h"  #include <QFileDialog>  #include <QDesktopServices> @@ -24,8 +24,8 @@  MainWindow::MainWindow() :      pose_update_timer(this),      kbd_quit(QKeySequence("Ctrl+Q"), this), -    no_feed_pixmap(":/images/no-feed.png"),      is_refreshing_profiles(false), +    keys_paused(false),      update_query(this)  {      ui.setupUi(this); @@ -33,7 +33,6 @@ MainWindow::MainWindow() :      setFixedSize(size());      updateButtonState(false, false); -    ui.video_frame_label->setPixmap(no_feed_pixmap);      connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration()));      connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(show_options_dialog())); @@ -91,7 +90,23 @@ MainWindow::MainWindow() :                               "Configuration not saved.",                               "Can't create configuration directory! Expect major malfunction.",                               QMessageBox::Ok, QMessageBox::NoButton); - +     +    connect(this, &MainWindow::emit_start_tracker, +            this, [&]() -> void { if (keys_paused) return; qDebug() << "start tracker"; startTracker(); }, +            Qt::QueuedConnection); +     +    connect(this, &MainWindow::emit_stop_tracker, +            this, [&]() -> void { if (keys_paused) return; qDebug() << "stop tracker"; stopTracker(); }, +            Qt::QueuedConnection); +     +    connect(this, &MainWindow::emit_toggle_tracker, +            this, [&]() -> void { if (keys_paused) return; qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, +            Qt::QueuedConnection); +     +    register_shortcuts(); +     +    connect(this, &MainWindow::emit_minimized, this, &MainWindow::mark_minimized, Qt::QueuedConnection); +          ui.btnStartTracker->setFocus();      update_query.maybe_show_dialog(); @@ -105,6 +120,22 @@ void MainWindow::closeEvent(QCloseEvent *e)          e->accept();  } +void MainWindow::register_shortcuts() +{ +    using t_shortcut = std::tuple<key_opts&, Shortcuts::fun>; +     +    std::vector<t_shortcut> keys { +        t_shortcut(s.key_start_tracking, [&]() -> void { emit_start_tracker(); }), +        t_shortcut(s.key_stop_tracking, [&]() -> void { emit_stop_tracker(); }), +        t_shortcut(s.key_toggle_tracking, [&]() -> void { emit_toggle_tracker(); }), +    }; +     +    global_shortcuts.reload(keys); +     +    if (work) +        work->reload_shortcuts(); +} +  bool MainWindow::get_new_config_name_from_dialog(QString& ret)  {      new_file_dialog dlg; @@ -252,6 +283,9 @@ void MainWindow::reload_options()  }  void MainWindow::startTracker() { +    if (work) +        return; +          // tracker dtor needs run first      work = nullptr; @@ -272,7 +306,7 @@ void MainWindow::startTracker() {          return;      } -    work = std::make_shared<Work>(s, pose, libs, this, winId()); +    work = std::make_shared<Work>(s, pose, libs, winId());      reload_options(); @@ -291,7 +325,10 @@ void MainWindow::startTracker() {      ui.btnStopTracker->setFocus();  } -void MainWindow::stopTracker( ) { +void MainWindow::stopTracker() { +    if (!work) +        return; +          //ui.game_name->setText("Not connected");      pose_update_timer.stop(); @@ -361,6 +398,9 @@ void MainWindow::set_title(const QString& game_title_)  void MainWindow::showHeadPose()  { +    if (!ui.video_frame->isEnabled()) +        return; +      double mapped[6], raw[6];      work->tracker->get_raw_and_mapped_poses(mapped, raw); @@ -386,7 +426,6 @@ bool mk_dialog(mem<dylib> lib, mem<t>* orig)          *orig = dialog;          dialog->show(); -        dialog->raise();          return true;      } @@ -398,7 +437,7 @@ void MainWindow::showProtocolSettings() {          pProtocolDialog->register_protocol(libs.pProtocol.get());  }  template<typename t, typename... Args> -bool mk_window(mem<t>* place, Args... params) +bool mk_window(mem<t>* place, Args&&... params)  {      if (*place && (*place)->isVisible())      { @@ -408,21 +447,24 @@ bool mk_window(mem<t>* place, Args... params)      }      else      { -        *place = std::make_shared<t>(params...); +        *place = std::make_shared<t>(std::forward<Args>(params)...);          (*place)->setWindowFlags(Qt::Dialog);          (*place)->show(); -        (*place)->raise();          return true;      }  }  void MainWindow::show_options_dialog() { -    if (mk_window<OptionsDialog, State&>(&options_widget, static_cast<State&>(*this))) +    if (mk_window(&options_widget, +                  s, +                  *this, +                  [&]() -> void { register_shortcuts(); }, +                  [&](bool flag) -> void { keys_paused = flag; }))          connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options()));  }  void MainWindow::showCurveConfiguration() { -    mk_window<MapWidget, Mappings&, main_settings&>(&mapping_widget, pose, s); +    mk_window(&mapping_widget, pose, s);  }  bool MainWindow::maybe_not_close_tracking() @@ -468,27 +510,6 @@ void MainWindow::profileSelected(QString name)      }  } -void MainWindow::shortcutRecentered() -{ -    qDebug() << "Center"; -    if (work) -        work->tracker->center(); -} - -void MainWindow::shortcutToggled() -{ -    qDebug() << "Toggle"; -    if (work) -        work->tracker->toggle_enabled(); -} - -void MainWindow::shortcutZeroed() -{ -    qDebug() << "Zero"; -    if (work) -        work->tracker->zero(); -} -  void MainWindow::ensure_tray()  {      if (tray) @@ -512,15 +533,28 @@ void MainWindow::restore_from_tray(QSystemTrayIcon::ActivationReason)  void MainWindow::changeEvent(QEvent* e)  { -    if (s.tray_enabled && e->type() == QEvent::WindowStateChange && (windowState() & Qt::WindowMinimized)) +    if (e->type() == QEvent::WindowStateChange)      { -        if (!tray) -            ensure_tray(); -        hide(); +        const bool is_minimized = windowState() & Qt::WindowMinimized; +         +        if (s.tray_enabled && is_minimized) +        { +            if (!tray) +                ensure_tray(); +            hide(); +        } +         +        emit_minimized(is_minimized);      } +          QMainWindow::changeEvent(e);  } +void MainWindow::mark_minimized(bool is_minimized) +{ +    ui.video_frame->setEnabled(!is_minimized); +} +  void MainWindow::maybe_start_profile_from_executable()  {      if (!work) @@ -17,9 +17,12 @@  #include <QString>  #include <QMenu> +#include <vector> +#include <tuple> +  #include "ui_main.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "opentrack/main-settings.hpp"  #include "opentrack/plugin-support.hpp"  #include "opentrack/tracker.h" @@ -33,9 +36,11 @@  using namespace options; -class MainWindow : public QMainWindow, private State +class MainWindow : public QMainWindow, public State  {      Q_OBJECT +     +    Shortcuts global_shortcuts;      Ui::OpentrackUI ui;      mem<QSystemTrayIcon> tray; @@ -45,11 +50,11 @@ class MainWindow : public QMainWindow, private State      mem<OptionsDialog> options_widget;      mem<MapWidget> mapping_widget;      QShortcut kbd_quit; -    QPixmap no_feed_pixmap;      mem<IProtocolDialog> pProtocolDialog;      process_detector_worker det;      QMenu profile_menu;      bool is_refreshing_profiles; +    volatile bool keys_paused;      QTimer save_timer;      update_dialog::query update_query; @@ -70,6 +75,7 @@ class MainWindow : public QMainWindow, private State      void maybe_save();      bool maybe_not_close_tracking();      void closeEvent(QCloseEvent *e) override; +    void register_shortcuts();  private slots:      void _save();      void save(); @@ -92,10 +98,13 @@ private slots:      void startTracker();      void stopTracker();      void reload_options(); -public slots: -    void shortcutRecentered(); -    void shortcutToggled(); -    void shortcutZeroed(); +    void mark_minimized(bool is_minimized); +signals: +    void emit_start_tracker(); +    void emit_stop_tracker(); +    void emit_toggle_tracker(); +     +    void emit_minimized(bool);  public:      MainWindow();      ~MainWindow(); diff --git a/gui/wizard.h b/gui/wizard.h index ea848e36..9d359172 100644 --- a/gui/wizard.h +++ b/gui/wizard.h @@ -1,6 +1,6 @@  #pragma once -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "opentrack/main-settings.hpp"  #include "opentrack/mappings.hpp"  #include "ui_trackhat-wizard.h" diff --git a/make-tar.sh b/make-tar.sh index 3e119d12..08114127 100644 --- a/make-tar.sh +++ b/make-tar.sh @@ -4,7 +4,7 @@ prefix="$1"  filename="$2"  bin="$3" -cmake --build "$bin" --target install || exit 1 +cmake --build "$bin" --target install -- -j4 || exit 1  if  : &&      cd $(dirname -- "${prefix}") && diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index a92f4f31..8dba67e2 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -1,4 +1,5 @@ -opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE)  if(NOT WIN32 AND NOT APPLE)      target_link_libraries(opentrack-compat rt)  endif() +link_with_dinput8(opentrack-compat) diff --git a/opentrack/camera-names.hpp b/opentrack-compat/camera-names.cpp index f6ab736e..72bcf41a 100644 --- a/opentrack/camera-names.hpp +++ b/opentrack-compat/camera-names.cpp @@ -1,16 +1,4 @@ -/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> - - * Permission to use, copy, modify, and/or distribute this - * software for any purpose with or without fee is hereby granted, - * provided that the above copyright notice and this permission - * notice appear in all copies. - */ - -#pragma once - -#include <QList> -#include <QString> -#include <QDebug> +#include "camera-names.hpp"  #if defined(OPENTRACK_API) && defined(_WIN32)  #   define NO_DSHOW_STRSAFE @@ -29,8 +17,18 @@  #include <cerrno>  #endif -template<typename = void> -QList<QString> get_camera_names() { +#include <QDebug> + +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name) +{ +    auto list = get_camera_names(); +    int ret = list.indexOf(name); +    if (ret < 0) +        ret = 0; +    return ret; +} + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names() {      QList<QString> ret;  #if defined(_WIN32)      // Create the System Device Enumerator. @@ -112,14 +110,4 @@ QList<QString> get_camera_names() {      }  #endif      return ret; -} - -template<typename = void> -int camera_name_to_index(const QString &name) -{ -    auto list = get_camera_names(); -    int ret = list.indexOf(name); -    if (ret < 0) -        ret = 0; -    return ret; -} +}
\ No newline at end of file diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp new file mode 100644 index 00000000..c2879000 --- /dev/null +++ b/opentrack-compat/camera-names.hpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#pragma once + +#include <QList> +#include <QString> + +#ifdef BUILD_compat +#   include "compat-export.hpp" +#else +#   include "compat-import.hpp" +#endif + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/opentrack-compat/compat-export.hpp b/opentrack-compat/compat-export.hpp new file mode 100644 index 00000000..2d6f1d3d --- /dev/null +++ b/opentrack-compat/compat-export.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_COMPAT_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_COMPAT_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +#   else +#       define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/compat-import.hpp b/opentrack-compat/compat-import.hpp new file mode 100644 index 00000000..161ccc5d --- /dev/null +++ b/opentrack-compat/compat-import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_COMPAT_LINKAGE __declspec(dllimport) +#   else +#       define OPENTRACK_COMPAT_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +#   else +#       define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/export.hpp b/opentrack-compat/export.hpp index f0983b75..100950a0 100644 --- a/opentrack-compat/export.hpp +++ b/opentrack-compat/export.hpp @@ -1,13 +1,15 @@  #pragma once -#ifdef _WIN32 -#   define OPENTRACK_LINKAGE __declspec(dllexport) -#else -#   define OPENTRACK_LINKAGE -#endif +#ifndef OPENTRACK_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_LINKAGE +#   endif -#ifndef _MSC_VER -#	define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE -#else -#	define OPENTRACK_EXPORT OPENTRACK_LINKAGE -#endif
\ No newline at end of file +#   ifndef _MSC_VER +#       define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +#   else +#       define OPENTRACK_EXPORT OPENTRACK_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/import.hpp b/opentrack-compat/import.hpp new file mode 100644 index 00000000..3747b141 --- /dev/null +++ b/opentrack-compat/import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_LINKAGE __declspec(dllimport) +#   else +#       define OPENTRACK_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +#   else +#       define OPENTRACK_EXPORT OPENTRACK_LINKAGE +#   endif +#endif diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp new file mode 100644 index 00000000..550fec24 --- /dev/null +++ b/opentrack-compat/options.cpp @@ -0,0 +1,199 @@ +#include "options.hpp" + +namespace options +{ + +namespace detail +{ +OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() +{ +    static opt_singleton ret; +    return ret; +} + +} + +group::group(const QString& name) : name(name) +{ +    auto conf = ini_file(); +    conf->beginGroup(name); +    for (auto& k_ : conf->childKeys()) +    { +        auto tmp = k_.toUtf8(); +        QString k(tmp); +        kvs[k] = conf->value(k_); +    } +    conf->endGroup(); +} + +void group::save() +{ +    auto s = ini_file(); +    s->beginGroup(name); +    for (auto& i : kvs) +        s->setValue(i.first, i.second); +    s->endGroup(); +    s->sync(); +} + +void group::put(const QString &s, const QVariant &d) +{ +    kvs[s] = d; +} + +bool group::contains(const QString &s) +{ +    return kvs.count(s) != 0; +} + +QString group::ini_directory() +{ +    const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); +    if (dirs.size() == 0) +        return ""; +    if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) +        return dirs[0] + "/" OPENTRACK_ORG; +    return ""; +} + +QString group::ini_filename() +{ +    QSettings settings(OPENTRACK_ORG); +    return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +QString group::ini_pathname() +{ +    const auto dir = ini_directory(); +    if (dir == "") +        return ""; +    QSettings settings(OPENTRACK_ORG); +    return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +const QStringList group::ini_list() +{ +    const auto dirname = ini_directory(); +    if (dirname == "") +        return QStringList(); +    QDir settings_dir(dirname); +    return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); +} + +const mem<QSettings> group::ini_file() +{ +    const auto pathname = ini_pathname(); +    if (pathname != "") +        return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); +    return std::make_shared<QSettings>(); +} + +impl_bundle::impl_bundle(const QString &group_name) +    : +      mtx(QMutex::Recursive), +      group_name(group_name), +      saved(group_name), +      transient(saved), +      modified(false) +{} + +void impl_bundle::reload() +{ +    { +        QMutexLocker l(&mtx); +        saved = group(group_name); +        transient = saved; +        modified = false; +    } +    emit reloading(); +} + +void impl_bundle::store_kv(const QString &name, const QVariant &datum) +{ +    QMutexLocker l(&mtx); + +    auto old = transient.get<QVariant>(name); +    if (!transient.contains(name) || datum != old) +    { +        modified = true; +        transient.put(name, datum); +    } +} + +bool impl_bundle::contains(const QString &name) +{ +    QMutexLocker l(&mtx); +    return transient.contains(name); +} + +void impl_bundle::save() +{ +    { +        QMutexLocker l(&mtx); +        modified = false; +        saved = transient; +        transient.save(); +    } +    emit saving(); +} + +bool impl_bundle::modifiedp() +{ +    QMutexLocker l(&mtx); +    return modified; +} + +namespace detail +{ + +pbundle opt_singleton::bundle(const opt_singleton::k &key) +{ +    QMutexLocker l(&implsgl_mtx); + +    if (implsgl_data.count(key) != 0) +    { +        auto shared = std::get<1>(implsgl_data[key]).lock(); +        if (shared != nullptr) +            return shared; +    } +     +    qDebug() << "bundle +" << key; + +    auto shr = std::make_shared<v>(key); +    implsgl_data[key] = tt(cnt(1), shr); +    return shr; +} + +void opt_singleton::bundle_decf(const opt_singleton::k &key) +{ +    QMutexLocker l(&implsgl_mtx); + +    if (--std::get<0>(implsgl_data[key]) == 0) +        implsgl_data.erase(key); +} + +opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + +} + +opt_bundle::opt_bundle(const QString &group_name) +    : impl_bundle(group_name) +{ +} + +opt_bundle::~opt_bundle() +{ +    qDebug() << "bundle -" << group_name; +    detail::singleton().bundle_decf(group_name); +} + +base_value::base_value(pbundle b, const QString &name) : b(b), self_name(name) {} + +opts::~opts() +{ +    b->reload(); +} + +opts::opts(const QString &name) : b(bundle(name)) {} + +} diff --git a/opentrack/options.hpp b/opentrack-compat/options.hpp index f2c09479..a317a1f7 100644 --- a/opentrack/options.hpp +++ b/opentrack-compat/options.hpp @@ -10,7 +10,6 @@  #include <memory>  #include <tuple>  #include <map> -#include <string>  #include <QObject>  #include <QSettings> @@ -37,6 +36,13 @@  #include <QDebug>  #include <memory> + +#ifdef BUILD_compat +#   include "compat-export.hpp" +#else +#   include "compat-import.hpp" +#endif +  template<typename t> using mem = std::shared_ptr<t>;  #define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" @@ -44,9 +50,7 @@ template<typename t> using mem = std::shared_ptr<t>;  #define OPENTRACK_ORG "TrackHat opentrack-2.3"  namespace options { -    template<typename k, typename v> -    using map = std::map<k, v>; -    using std::string; +    template<typename k, typename v> using map = std::map<k, v>;      template<typename t>      // don't elide usages of the function, qvariant default implicit @@ -84,103 +88,33 @@ namespace options {      }      // snapshot of qsettings group at given time -    class group { +    class OPENTRACK_COMPAT_EXPORT group {      private: -        map<string, QVariant> kvs; -        string name; +        map<QString, QVariant> kvs; +        QString name;      public: -        group(const string& name) : name(name) -        { -            auto conf = ini_file(); -            auto q_name = QString::fromStdString(name); -            conf->beginGroup(q_name); -            for (auto& k_ : conf->childKeys()) -            { -                auto tmp = k_.toUtf8(); -                string k(tmp); -                kvs[k] = conf->value(k_); -            } -            conf->endGroup(); -        } - -        void save() -        { -            auto s = ini_file(); -            auto q_name = QString::fromStdString(name); -            s->beginGroup(q_name); -            for (auto& i : kvs) -            { -                auto k = QString::fromStdString(i.first); -                s->setValue(k, i.second); -            } -            s->endGroup(); -            s->sync(); -        } +        group(const QString& name); +        void save(); +        void put(const QString& s, const QVariant& d); +        bool contains(const QString& s); +        static QString ini_directory(); +        static QString ini_filename(); +        static QString ini_pathname(); +        static const QStringList ini_list(); +        static const mem<QSettings> ini_file();          template<typename t> -        t get(const string& k) +        t get(const QString& k)          {              return qcruft_to_t<t>(kvs[k]);          } - -        void put(const string& s, const QVariant& d) -        { -            kvs[s] = d; -        } - -        bool contains(const string& s) -        { -            return kvs.count(s) != 0; -        } - -        static QString ini_directory() -        { -            const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); -            if (dirs.size() == 0) -                return ""; -            if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) -                return dirs[0] + "/" OPENTRACK_ORG; -            return ""; -        } - -        static QString ini_filename() -        { -            QSettings settings(OPENTRACK_ORG); -            return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); -        } - -        static QString ini_pathname() -        { -            const auto dir = ini_directory(); -            if (dir == "") -                return ""; -            QSettings settings(OPENTRACK_ORG); -            return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); -        } -         -        static const QStringList ini_list() -        { -            const auto dirname = ini_directory(); -            if (dirname == "") -                return QStringList(); -            QDir settings_dir(dirname); -            return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); -        } -         -        static const mem<QSettings> ini_file() -        { -            const auto pathname = ini_pathname(); -            if (pathname != "") -                return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); -            return std::make_shared<QSettings>(); -        }      }; -    class impl_bundle : public QObject { +    class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject {          Q_OBJECT      protected:          QMutex mtx; -        const string group_name; +        const QString group_name;          group saved;          group transient;          bool modified; @@ -190,144 +124,66 @@ namespace options {          void reloading();          void saving();      public: -        impl_bundle(const string& group_name) : -            mtx(QMutex::Recursive), -            group_name(group_name), -            saved(group_name), -            transient(saved), -            modified(false) -        { -        } - -        string name() { return group_name; } - -        void reload() { -            { -                QMutexLocker l(&mtx); -                saved = group(group_name); -                transient = saved; -                modified = false; -            } -            emit reloading(); -        } - -        void store_kv(const string& name, const QVariant& datum) -        { -            QMutexLocker l(&mtx); - -            auto old = transient.get<QVariant>(name); -            if (!transient.contains(name) || datum != old) -            { -                modified = true; -                transient.put(name, datum); -            } -        } -        bool contains(const string& name) -        { -            QMutexLocker l(&mtx); -            return transient.contains(name); -        } +        impl_bundle(const QString& group_name); +        QString name() { return group_name; } +        void reload(); +        void store_kv(const QString& name, const QVariant& datum); +        bool contains(const QString& name); +        void save(); +        bool modifiedp(); +                  template<typename t> -        t get(const string& name) +        t get(const QString& name)          {              QMutexLocker l(&mtx);              return transient.get<t>(name);          } -        void save() -        { -            { -                QMutexLocker l(&mtx); -                modified = false; -                saved = transient; -                transient.save(); -            } -            emit saving(); -        } - -        bool modifiedp() { -            QMutexLocker l(&mtx); -            return modified; -        }      };      class opt_bundle; -    namespace +    namespace detail      { -        template<typename k, typename v, typename cnt = int> -        struct opt_singleton +        struct OPENTRACK_COMPAT_EXPORT opt_singleton          {          public: +            using k = QString; +            using v = opt_bundle; +            using cnt = int;              using pbundle = std::shared_ptr<v>;              using tt = std::tuple<cnt, std::weak_ptr<v>>;          private:              QMutex implsgl_mtx;              map<k, tt> implsgl_data;          public: -            opt_singleton() : implsgl_mtx(QMutex::Recursive) {} - -            static opt_singleton<k, v>& datum() -            { -                static auto ret = std::make_shared<opt_singleton<k, v>>(); -                return *ret; -            } - -            pbundle bundle(const k& key) -            { -                QMutexLocker l(&implsgl_mtx); - -                if (implsgl_data.count(key) != 0) -                { -                    auto shared = std::get<1>(implsgl_data[key]).lock(); -                    if (shared != nullptr) -                        return shared; -                } -                 -                qDebug() << "bundle +" << QString::fromStdString(key); - -                auto shr = std::make_shared<v>(key); -                implsgl_data[key] = tt(cnt(1), shr); -                return shr; -            } - -            void bundle_decf(const k& key) -            { -                QMutexLocker l(&implsgl_mtx); - -                if (--std::get<0>(implsgl_data[key]) == 0) -                    implsgl_data.erase(key); -            } +            opt_singleton(); +            pbundle bundle(const k& key); +            void bundle_decf(const k& key);          }; - -        using pbundle = std::shared_ptr<opt_bundle>; -        using t_fact = opt_singleton<string, opt_bundle>; +         +        OPENTRACK_COMPAT_EXPORT opt_singleton& singleton();      } +     +    using pbundle = std::shared_ptr<opt_bundle>; +     +    static inline pbundle bundle(const QString name) { return detail::singleton().bundle(name); } -    static inline t_fact::pbundle bundle(const string name) { return t_fact::datum().bundle(name); } - -    class opt_bundle : public impl_bundle +    class OPENTRACK_COMPAT_EXPORT opt_bundle : public impl_bundle      {      public:          opt_bundle() : impl_bundle("i-have-no-name") {} -        opt_bundle(const string& group_name) : impl_bundle(group_name) -        { -        } - -        ~opt_bundle() -        { -            qDebug() << "bundle -" << QString::fromStdString(group_name); -            t_fact::datum().bundle_decf(group_name); -        } +        opt_bundle(const QString& group_name); +        ~opt_bundle();      }; -    class base_value : public QObject +    class OPENTRACK_COMPAT_EXPORT base_value : public QObject      {          Q_OBJECT  #define DEFINE_SLOT(t) void setValue(t datum) { store(datum); }  #define DEFINE_SIGNAL(t) void valueChanged(t)      public: -        string name() { return self_name; } -        base_value(pbundle b, const string& name) : b(b), self_name(name) {} +        QString name() { return self_name; } +        base_value(pbundle b, const QString& name);      signals:          DEFINE_SIGNAL(double);          DEFINE_SIGNAL(int); @@ -335,7 +191,7 @@ namespace options {          DEFINE_SIGNAL(QString);      protected:          pbundle b; -        string self_name; +        QString self_name;          template<typename t>          void store(const t& datum) @@ -352,12 +208,6 @@ namespace options {          virtual void reload() = 0;      }; -    static inline string string_from_qstring(const QString& datum) -    { -        auto tmp = datum.toUtf8(); -        return string(tmp.constData()); -    } -      template<typename t>      class value : public base_value {      public: @@ -368,7 +218,7 @@ namespace options {          }          static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection;          static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; -        value(pbundle b, const string& name, t def) : base_value(b, name), def(def) +        value(pbundle b, const QString& name, t def) : base_value(b, name), def(def)          {              QObject::connect(b.get(), SIGNAL(reloading()),                               this, SLOT(reload()), @@ -376,10 +226,9 @@ namespace options {              if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)                  *this = def;          } -        value(pbundle b, const QString& name, t def) : value(b, string_from_qstring(name), def) {} -        value(pbundle b, const char* name, t def) : value(b, string(name), def) {} +        value(pbundle b, const char* name, t def) : value(b, QString(name), def) {} -        operator t() +        operator t() const          {              return b->contains(self_name) ? b->get<t>(self_name) : def;          } @@ -390,18 +239,13 @@ namespace options {          t def;      }; -    struct opts +    struct OPENTRACK_COMPAT_EXPORT opts      {          pbundle b; -         -        opts(const std::string& name) : b(bundle(name)) {} -         -        ~opts() -        { -            b->reload(); -        } +        opts(const QString& name); +        ~opts();      }; -     +      template<typename t, typename q>      inline void tie_setting(value<t>&, q*); diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 029a4c95..55aa7a41 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -5,25 +5,140 @@   * copyright notice and this permission notice appear in all copies.   */ -#include <cstring>  #include "shm.h"  #if defined(_WIN32) + +#include <cstring> +#include <stdio.h> + +#include <accctrl.h> +#include <aclapi.h> + +struct secattr +{ +    bool success; +    SECURITY_DESCRIPTOR* pSD; +    SECURITY_ATTRIBUTES attrs; +    PSID pEveryoneSID; +    PACL pACL; + +    void cleanup() +    { +        if (pEveryoneSID) +            FreeSid(pEveryoneSID); +        if (pACL) +            LocalFree(pACL); +        if (pSD) +            LocalFree(pSD); +        success = false; +        pSD = nullptr; +        pEveryoneSID = nullptr; +        pACL = nullptr; +    } + +    secattr(DWORD perms) : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) +    { +        SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; +        EXPLICIT_ACCESS ea; + +        if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, +                         SECURITY_WORLD_RID, +                         0, 0, 0, 0, 0, 0, 0, +                         &pEveryoneSID)) +        { +            fprintf(stderr, "AllocateAndInitializeSid: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        memset(&ea, 0, sizeof(ea)); + +        ea.grfAccessPermissions = perms; +        ea.grfAccessMode = SET_ACCESS; +        ea.grfInheritance = NO_INHERITANCE; +        ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; +        ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; +        ea.Trustee.ptstrName  = (LPTSTR) pEveryoneSID; + +        if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS) +        { +            fprintf(stderr, "SetEntriesInAcl: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); +        if (pSD == nullptr) +        { +            fprintf(stderr, "LocalAlloc: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        if (!InitializeSecurityDescriptor(pSD, +                    SECURITY_DESCRIPTOR_REVISION)) +        { +            fprintf(stderr, "InitializeSecurityDescriptor: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        if (!SetSecurityDescriptorDacl(pSD, +                                       TRUE, +                                       pACL, +                                       FALSE)) +        { +            fprintf(stderr, "SetSecurityDescriptorDacl: %d\n", (int) GetLastError()); +            goto cleanup; +        } + +        attrs.bInheritHandle = false; +        attrs.lpSecurityDescriptor = pSD; +        attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + +        fflush(stderr); + +        return; +cleanup: +        fflush(stderr); +        cleanup(); +    } + +    ~secattr() +    { +        cleanup(); +    } +}; +  PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize)  { -    hMutex = CreateMutexA(NULL, false, mutexName); +    secattr sa(GENERIC_ALL|SYNCHRONIZE); + +    hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); +    if (!hMutex) +    { +        fprintf(stderr, "CreateMutexA: %d\n", (int) GetLastError()); +        fflush(stderr); +    }      hMapFile = CreateFileMappingA(                   INVALID_HANDLE_VALUE, -                 NULL, +                 sa.success ? &sa.attrs : nullptr,                   PAGE_READWRITE,                   0,                   mapSize,                   shmName); +    if (!hMapFile) +    { +        fprintf(stderr, "CreateFileMappingA: %d\n", (int) GetLastError()); +        fflush(stderr); +    }      mem = MapViewOfFile(hMapFile,                          FILE_MAP_WRITE,                          0,                          0,                          mapSize); +    if (!mem) +    { +        fprintf(stderr, "MapViewOfFile: %d\n", (int) GetLastError()); +        fflush(stderr); +    }  }  PortableLockedShm::~PortableLockedShm() diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index c74534e7..3edb0080 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -19,32 +19,18 @@  #include <sys/types.h>  #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wattributes" -  #ifdef __GNUC__ -#   define COMPAT_GNUC_VISIBILITY __attribute__ ((visibility ("default"))) -#else -#   define COMPAT_GNUC_VISIBILITY +#   pragma GCC diagnostic push +#   pragma GCC diagnostic ignored "-Wattributes"  #endif -#ifdef BUILD_opentrack_compat -#   ifdef _WIN32 -#       define COMPAT_WIN32_EXPORT __declspec(dllexport) -#   else -#       define COMPAT_WIN32_EXPORT -#   endif +#ifdef BUILD_compat +#   include "compat-export.hpp"  #else -#   ifdef _WIN32 -#       define COMPAT_WIN32_EXPORT __declspec(dllimport) -#   else -#       define COMPAT_WIN32_EXPORT -#   endif +#   include "compat-import.hpp"  #endif -#define COMPAT_EXPORT COMPAT_WIN32_EXPORT COMPAT_GNUC_VISIBILITY - -class COMPAT_EXPORT PortableLockedShm { +class OPENTRACK_COMPAT_EXPORT PortableLockedShm {  public:      PortableLockedShm(const char *shmName, const char *mutexName, int mapSize);      ~PortableLockedShm(); @@ -61,4 +47,6 @@ private:  #endif  }; -#pragma GCC diagnostic pop +#ifdef __GNUC__ +#   pragma GCC diagnostic pop +#endif diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt index 590eaca5..6baa05db 100644 --- a/opentrack/CMakeLists.txt +++ b/opentrack/CMakeLists.txt @@ -1,6 +1,8 @@ -opentrack_boilerplate(opentrack-api NO-LINKER-SCRIPT NO-COMPAT) +opentrack_boilerplate(opentrack-api NO-LINKER-SCRIPT NO-COMPAT LINKAGE)  if(NOT WIN32)      target_link_libraries(opentrack-api opentrack-qxt-mini opentrack-compat dl)  else()      target_link_libraries(opentrack-api winmm)  endif() +target_link_libraries(opentrack-api opentrack-spline-widget) +link_with_dinput8(opentrack-api) diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp new file mode 100644 index 00000000..39693a7c --- /dev/null +++ b/opentrack/keybinding-worker.cpp @@ -0,0 +1,192 @@ +/* Copyright (c) 2014-2015, 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. + */ + +#ifdef _WIN32 + +#include "keybinding-worker.hpp" +#include <functional> +#include <windows.h> +#include <QDebug> +#include <QMutexLocker> + +bool Key::should_process() +{ +    if (keycode == 0 && guid == "") +        return false; +    bool ret = timer.elapsed_ms() > 100; +    timer.start(); +    return ret; +} + +KeybindingWorker::~KeybindingWorker() { +    should_quit = true; +    wait(); +    if (dinkeyboard) { +        dinkeyboard->Unacquire(); +        dinkeyboard->Release(); +    } +    if (din) +        din->Release(); +} + +KeybindingWorker::KeybindingWorker() : +    should_quit(true) +{ +    if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { +        qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); +        return; +    } +    if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { +        din->Release(); +        din = 0; +        qDebug() << "setup CreateDevice function failed!" << GetLastError(); +        return; +    } +    if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { +        qDebug() << "setup SetDataFormat function failed!" << GetLastError(); +        dinkeyboard->Release(); +        dinkeyboard = 0; +        din->Release(); +        din = 0; +        return; +    } +     +    if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { +        dinkeyboard->Release(); +        din->Release(); +        din = 0; +        dinkeyboard = 0; +        qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); +        return; +    } +    if (dinkeyboard->Acquire() != DI_OK) +    { +        dinkeyboard->Release(); +        din->Release(); +        din = 0; +        dinkeyboard = 0; +        qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); +        return; +    } +    should_quit = false; +    start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ +    static KeybindingWorker k; +    return k; +} + +void KeybindingWorker::run() { +    BYTE keystate[256] = {0}; +    BYTE old_keystate[256] = {0}; + +    while (!should_quit) +    { +        { +            QMutexLocker l(&mtx); + +            if (receivers.size()) +            { +                { +                    const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + +                    if (hr != DI_OK) { +                        qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); +                        Sleep(25); +                        continue; +                    } +                } + +                { +                    using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; + +                    joy_fn f = [&](const QString& guid, int idx, bool held) -> void { +                        Key k; +                        k.keycode = idx; +                        k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); +                        k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); +                        k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); +                        k.guid = guid; +                        k.held = held; + +                        for (auto& r : receivers) +                            r->operator()(k); +                    }; + +                    joy_ctx.poll(f); +                } + +                for (int i = 0; i < 256; i++) +                { +                    Key k; +                    if (old_keystate[i] != keystate[i] && keystate[i] & 0x80) +                    { +                        switch (i) +                        { +                        case DIK_LCONTROL: +                        case DIK_LSHIFT: +                        case DIK_LALT: +                        case DIK_RCONTROL: +                        case DIK_RSHIFT: +                        case DIK_RALT: +                            break; +                        default: +                            k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); +                            k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); +                            k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); +                            k.keycode = i; + +                            for (auto& r : receivers) +                                r->operator()(k); +                            break; +                        } +                    } +                    old_keystate[i] = keystate[i]; +                } +            } +        } + +        // keypresses get dropped with high values +        Sleep(4); +    } +} + +KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) +{ +    QMutexLocker l(&mtx); +    receivers.push_back(std::unique_ptr<fun>(new fun(receiver))); +    fun* f = receivers[receivers.size() - 1].get(); +    qDebug() << "add receiver" << (long) f; +    joy_ctx.refresh(); +    return f; +} + +void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) +{ +    QMutexLocker l(&mtx); +    bool ok = false; + +    for (int i = receivers.size() - 1; i >= 0; i--) +    { +        if (receivers[i].get() == pos) +        { +            ok = true; +            qDebug() << "remove receiver" << (long) pos; +            receivers.erase(receivers.begin() + i); +            break; +        } +    } +    if (!ok) +    { +        qDebug() << "bad remove receiver" << (long) pos; +    } +} + +#endif diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp new file mode 100644 index 00000000..fa50a974 --- /dev/null +++ b/opentrack/keybinding-worker.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#pragma once + +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +#include "opentrack-compat/timer.hpp" +#include "opentrack/win32-joystick.hpp" +#include <QThread> +#include <QMutex> +#include <QWidget> +#include <QMainWindow> +#include <functional> +#include <vector> + +#undef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#include <windows.h> +#include <dinput.h> +struct Key { +    BYTE keycode; +    QString guid; +    bool shift; +    bool ctrl; +    bool alt; +    bool held; +    Timer timer; +public: +    Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) {} + +    bool should_process(); +}; + +struct OPENTRACK_EXPORT KeybindingWorker : private QThread +{ +private: +    LPDIRECTINPUT8 din; +    LPDIRECTINPUTDEVICE8 dinkeyboard; +    win32_joy_ctx joy_ctx; +    volatile bool should_quit; +    using fun = std::function<void(const Key&)>; +    std::vector<std::unique_ptr<fun>> receivers; +    QMutex mtx; +    QMainWindow fake_main_window; + +    void run() override; +    KeybindingWorker(); + +    KeybindingWorker(const KeybindingWorker&) = delete; +    KeybindingWorker& operator=(KeybindingWorker&) = delete; +    static KeybindingWorker& make(); +    fun* _add_receiver(fun &receiver); +    void remove_receiver(fun* pos); +    ~KeybindingWorker(); +public: +    class Token +    { +        fun* pos; +        Token(const Token&) = delete; +        Token& operator=(Token&) = delete; +    public: +        ~Token() +        { +            make().remove_receiver(pos); +        } +        Token(fun receiver) +        { +            pos = make()._add_receiver(receiver); +        } +    }; +}; diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp index dd61143e..2d1c1f22 100644 --- a/opentrack/main-settings.hpp +++ b/opentrack/main-settings.hpp @@ -9,7 +9,7 @@  #pragma once  #include <QString> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "opentrack/plugin-api.hpp"  using namespace options; @@ -30,13 +30,27 @@ private:      }  }; -struct main_settings : opts { +struct key_opts { +    value<QString> keycode, guid; +    value<int> button; + +    key_opts(pbundle b, const QString& name) : +        keycode(b, QString("keycode-%1").arg(name), ""), +        guid(b, QString("guid-%1").arg(name), ""), +        button(b, QString("button-%1").arg(name), -1) +    {} +}; + +struct main_settings : opts {          value<QString> protocol_dll;      axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll;      value<bool> tcomp_p, tcomp_tz;      value<bool> tray_enabled;      value<int> camera_yaw, camera_pitch, camera_roll;      value<bool> center_at_startup, wizard_done; +    value<int> center_method; +    key_opts key_start_tracking, key_stop_tracking, key_toggle_tracking; +    key_opts key_center, key_toggle, key_zero;      main_settings() :          opts("opentrack-ui"),          protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced"), @@ -53,6 +67,14 @@ struct main_settings : opts {          camera_pitch(b, "camera-pitch", 0),          camera_roll(b, "camera-roll", 0),          center_at_startup(b, "center-at-startup", true), -        wizard_done(b, "wizard-done", false) -    {} +        wizard_done(b, "wizard-done", false), +        center_method(b, "centering-method", true), +        key_start_tracking(b, "start-tracking"), +        key_stop_tracking(b, "stop-tracking"), +        key_toggle_tracking(b, "toggle-tracking"), +        key_center(b, "center"), +        key_toggle(b, "toggle"), +        key_zero(b, "zero") +    { +    }  }; diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp index bb38a3ca..087ea7f3 100644 --- a/opentrack/mappings.hpp +++ b/opentrack/mappings.hpp @@ -8,7 +8,7 @@  #pragma once  #include <QSettings> -#include "options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #include "spline-widget/functionconfig.h"  #include "main-settings.hpp" diff --git a/opentrack/opencv-camera-dialog.hpp b/opentrack/opencv-camera-dialog.hpp index 0d4a51af..96c7a643 100644 --- a/opentrack/opencv-camera-dialog.hpp +++ b/opentrack/opencv-camera-dialog.hpp @@ -12,7 +12,7 @@  #include <QMutex>  #include <QMutexLocker>  #include <opencv2/videoio.hpp> -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp"  #ifdef __linux  #include <QProcess> diff --git a/opentrack/plugin-api.hpp b/opentrack/plugin-api.hpp index a57077ab..5fdc3bcb 100644 --- a/opentrack/plugin-api.hpp +++ b/opentrack/plugin-api.hpp @@ -8,17 +8,38 @@  #pragma once -#include "../opentrack-compat/export.hpp"  #include <QString>  #include <QWidget>  #include <QFrame>  #include <QIcon> +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +#ifndef OPENTRACK_PLUGIN_EXPORT +#   ifdef _WIN32 +#       define OPENTRACK_PLUGIN_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_PLUGIN_LINKAGE +#   endif +#   ifndef _MSC_VER +#       define OPENTRACK_PLUGIN_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_PLUGIN_LINKAGE +#   else +#       define OPENTRACK_PLUGIN_EXPORT OPENTRACK_PLUGIN_LINKAGE +#   endif +#endif +  enum Axis {      TX = 0, TY, TZ, Yaw, Pitch, Roll  }; -class BaseDialog : public QWidget +namespace plugin_api { +namespace detail { + +class OPENTRACK_EXPORT BaseDialog : public QWidget  {      Q_OBJECT  public: @@ -27,16 +48,19 @@ signals:      void closing();  }; +} // ns +} // ns +  #define OPENTRACK_DECLARE_PLUGIN_INTERNAL(ctor_class, ctor_ret_class, metadata_class, dialog_class, dialog_ret_class) \ -    extern "C" OPENTRACK_EXPORT ctor_ret_class* GetConstructor() \ +    extern "C" OPENTRACK_PLUGIN_EXPORT ctor_ret_class* GetConstructor() \      { \          return new ctor_class; \      } \ -    extern "C" OPENTRACK_EXPORT Metadata* GetMetadata() \ +    extern "C" OPENTRACK_PLUGIN_EXPORT Metadata* GetMetadata() \      { \          return new metadata_class; \      } \ -    extern "C" OPENTRACK_EXPORT dialog_ret_class* GetDialog() \ +    extern "C" OPENTRACK_PLUGIN_EXPORT dialog_ret_class* GetDialog() \      { \          return new dialog_class; \      } @@ -65,7 +89,7 @@ struct IFilter      virtual void center() {}  }; -struct IFilterDialog : public BaseDialog +struct IFilterDialog : public plugin_api::detail::BaseDialog  {      // optional destructor      virtual ~IFilterDialog() {} @@ -93,7 +117,7 @@ struct IProtocol      virtual QString game_name() = 0;  }; -struct IProtocolDialog : public BaseDialog +struct IProtocolDialog : public plugin_api::detail::BaseDialog  {      // optional destructor      virtual ~IProtocolDialog() {} @@ -118,7 +142,7 @@ struct ITracker      virtual void data(double *data) = 0;  }; -struct ITrackerDialog : public BaseDialog +struct ITrackerDialog : public plugin_api::detail::BaseDialog  {      // optional destructor      virtual ~ITrackerDialog() {} diff --git a/opentrack/plugin-support.hpp b/opentrack/plugin-support.hpp index 3a0a3420..9968890d 100644 --- a/opentrack/plugin-support.hpp +++ b/opentrack/plugin-support.hpp @@ -8,7 +8,7 @@  #pragma once  #include "plugin-api.hpp" -#include "options.hpp" +#include "opentrack-compat/options.hpp"  #include <QWidget>  #include <QDebug> diff --git a/opentrack/selected-libraries.hpp b/opentrack/selected-libraries.hpp index 7779c231..5384f9e2 100644 --- a/opentrack/selected-libraries.hpp +++ b/opentrack/selected-libraries.hpp @@ -11,7 +11,14 @@  #include "opentrack/plugin-support.hpp"  #include <QFrame> -struct SelectedLibraries { + +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +struct OPENTRACK_EXPORT SelectedLibraries {      using dylibptr = mem<dylib>;      mem<ITracker> pTracker;      mem<IFilter> pFilter; diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index a33cf088..bab1283a 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -7,112 +7,9 @@   */  #include "shortcuts.h" -#include <QMutexLocker> - -#if defined(_WIN32) -#include <functional> -#include <windows.h>  #include "win32-shortcuts.h" -KeybindingWorker::~KeybindingWorker() { -    should_quit = true; -    wait(); -    if (dinkeyboard) { -        dinkeyboard->Unacquire(); -        dinkeyboard->Release(); -    } -    if (din) -        din->Release(); -} - -KeybindingWorker::KeybindingWorker(std::function<void(Key&)> receiver, WId h) : -    should_quit(true), receiver(receiver) -{ -    HWND handle = reinterpret_cast<HWND>(h); - -    if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { -        qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); -        return; -    } -    if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { -        din->Release(); -        din = 0; -        qDebug() << "setup CreateDevice function failed!" << GetLastError(); -        return; -    } -    if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { -        qDebug() << "setup SetDataFormat function failed!" << GetLastError(); -        dinkeyboard->Release(); -        dinkeyboard = 0; -        din->Release(); -        din = 0; -        return; -    } -    if (dinkeyboard->SetCooperativeLevel((HWND) handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { -        dinkeyboard->Release(); -        din->Release(); -        din = 0; -        dinkeyboard = 0; -        qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); -        return; -    } -    if (dinkeyboard->Acquire() != DI_OK) -    { -        dinkeyboard->Release(); -        din->Release(); -        din = 0; -        dinkeyboard = 0; -        qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); -        return; -    } -    should_quit = false; -} - -void KeybindingWorker::run() { -    BYTE keystate[256]; - -    while (!should_quit) -    { -        if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { -            qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); -            Sleep(25); -            continue; -        } - -        QMutexLocker l(&mtx); - -        for (int i = 0; i < 256; i++) -        { -            Key k; -            if (keystate[i] & 0x80) -            { -                switch (i) -                { -                case DIK_LCONTROL: -                case DIK_LSHIFT: -                case DIK_LALT: -                case DIK_RCONTROL: -                case DIK_RSHIFT: -                case DIK_RALT: -                    break; -                default: -                    k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); -                    k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); -                    k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); -                    k.keycode = i; -                    receiver(k); -                    break; -                } -            } -        } - -        // keypresses get dropped with high values -        Sleep(4); -    } -} -#endif - -void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) +void Shortcuts::bind_keyboard_shortcut(K &key, const key_opts& k)  {  #if !defined(_WIN32)      using sh = QxtGlobalShortcut; @@ -136,56 +33,73 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k)      key = K();      int idx = 0;      QKeySequence code; - -    if (k.keycode == "") -        code = QKeySequence(Qt::Key_unknown); +     +    if (k.guid != "") +    { +        key.guid = k.guid; +        key.keycode = k.button & ~Qt::KeyboardModifierMask; +        key.ctrl = !!(k.button & Qt::ControlModifier); +        key.alt = !!(k.button & Qt::AltModifier); +        key.shift = !!(k.button & Qt::ShiftModifier); +    }      else -        code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); - -    Qt::KeyboardModifiers mods = Qt::NoModifier; -    if (code != Qt::Key_unknown) -        win_key::from_qt(code, idx, mods); -    key.shift = !!(mods & Qt::ShiftModifier); -    key.alt = !!(mods & Qt::AltModifier); -    key.ctrl = !!(mods & Qt::ControlModifier); -    key.keycode = idx; +    { +        if (k.keycode == "") +            code = QKeySequence(Qt::Key_unknown); +        else +            code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); +     +        Qt::KeyboardModifiers mods = Qt::NoModifier; +        if (code != Qt::Key_unknown) +            win_key::from_qt(code, idx, mods); +        key.shift = !!(mods & Qt::ShiftModifier); +        key.alt = !!(mods & Qt::AltModifier); +        key.ctrl = !!(mods & Qt::ControlModifier); +        key.keycode = idx; +    }  }  #endif  #ifdef _WIN32 -void Shortcuts::receiver(Key &k) +void Shortcuts::receiver(const Key& k)  { -    std::vector<K*> ks { &keyCenter, &keyToggle, &keyZero }; -    for (K* k_ : ks) +    const int sz = keys.size(); +    for (int i = 0; i < sz; i++)      { -        if (k.keycode != k_->keycode) +        K& k_ = std::get<0>(keys[i]); +        auto& fun = std::get<1>(keys[i]); +        if (k.guid != k_.guid) +            continue; +        if (k.keycode != k_.keycode) +            continue; +        if (!k.held)              continue; -        if (!k_->should_process()) +        if (!k_.should_process())              continue; -        if (k_->alt && !k.alt) continue; -        if (k_->ctrl && !k.ctrl) continue; -        if (k_->shift && !k.shift) continue; +        if (k_.alt && !k.alt) continue; +        if (k_.ctrl && !k.ctrl) continue; +        if (k_.shift && !k.shift) continue; -        if (k_ == &keyCenter) -            emit center(); -        else if (k_ == &keyToggle) -            emit toggle(); -        else if (k_ == &keyZero) -            emit zero(); +        fun();      }  }  #endif -void Shortcuts::reload() { -    bind_keyboard_shortcut(keyCenter, s.center); -    bind_keyboard_shortcut(keyToggle, s.toggle); -    bind_keyboard_shortcut(keyZero, s.zero); -#ifdef _WIN32 -    bool is_new = keybindingWorker == nullptr; -    if (is_new) +void Shortcuts::reload(const std::vector<std::tuple<key_opts&, fun> > &keys_) +{ +    const int sz = keys_.size(); +    keys = std::vector<tt>(); +     +    for (int i = 0; i < sz; i++)      { -        keybindingWorker = std::make_shared<KeybindingWorker>([&](Key& k) { receiver(k); }, handle); -        keybindingWorker->start(); -    } +        const auto& kk = keys_[i]; +        const key_opts& opts = std::get<0>(kk); +        auto& fun = std::get<1>(kk); +        K k; +        bind_keyboard_shortcut(k, opts); +        keys.push_back(std::tuple<K, Shortcuts::fun>(k, fun)); +#ifndef _WIN32 +        connect(k.get(), &QxtGlobalShortcut::activated, fun);  #endif +    }  } diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 63d91829..38037923 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -8,86 +8,27 @@  #pragma once  #include <QObject> -#include <QWidget> -#include "opentrack-compat/timer.hpp" -#include <QThread> -#include <QMessageBox> -#include <QCheckBox> -#include <QComboBox> -#include <QSettings> -#include <QMutex> +#include <tuple> +#include <vector> +#include <functional> -#include "qxt-mini/QxtGlobalShortcut" -#include "opentrack/plugin-support.hpp" -#include "opentrack/options.hpp" -#include "opentrack/main-settings.hpp" - -using namespace options; - -extern QList<QString> global_key_sequences; - -struct key_opts { -    value<QString> keycode; - -    key_opts(pbundle b, const QString& name) : -        keycode(b, QString("keycode-%1").arg(name), "") -    {} -}; - -#if defined(_WIN32) -extern QList<int> global_windows_key_sequences; -#   undef DIRECTINPUT_VERSION -#   define DIRECTINPUT_VERSION 0x0800 -#   include <windows.h> -#   include <dinput.h> - -struct Key { -    BYTE keycode; -    bool shift; -    bool ctrl; -    bool alt; -    Timer timer; -public: -    Key() : keycode(0), shift(false), ctrl(false), alt(false) -    { -    } - -    bool should_process() -    { -        if (keycode == 0) -            return false; -        bool ret = timer.elapsed_ms() > 100; -        timer.start(); -        return ret; -    } -}; +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp"  #else -typedef unsigned char BYTE; -struct Key { int foo; }; +#   include "opentrack-compat/import.hpp"  #endif -struct Shortcuts; +#include "qxt-mini/QxtGlobalShortcut" +#include "opentrack-compat/options.hpp" +#include "opentrack/main-settings.hpp" -struct KeybindingWorker : public QThread {  #ifdef _WIN32 -private: -    LPDIRECTINPUT8 din; -    LPDIRECTINPUTDEVICE8 dinkeyboard; -    QMutex mtx; -public: -    volatile bool should_quit; -    std::function<void(Key&)> receiver; -    ~KeybindingWorker(); -    KeybindingWorker(std::function<void(Key&)> receiver, WId h); -    void run(); -#else -public: -    KeybindingWorker(Key, Key, Key, WId) {} -    void run() {} +#   include "keybinding-worker.hpp"  #endif -}; -struct Shortcuts : public QObject { +using namespace options; + +struct OPENTRACK_EXPORT Shortcuts : public QObject {      Q_OBJECT  public: @@ -98,39 +39,24 @@ public:      Key  #endif      ; - -    K keyCenter; -    K keyToggle; -    K keyZero; - -    WId handle; +     +    using fun = std::function<void(void)>; +    using tt = std::tuple<K, fun>; +    std::vector<tt> keys;  #ifdef _WIN32 -    mem<KeybindingWorker> keybindingWorker; +    KeybindingWorker::Token key_token;  #endif -    struct settings : opts { -        key_opts center, toggle, zero; -        main_settings s_main; -        settings() : -            opts("keyboard-shortcuts"), -            center(b, "center"), -            toggle(b, "toggle"), -            zero(b, "zero") -        {} -    } s; - -    Shortcuts(WId handle) : handle(handle) { reload(); } +    Shortcuts() +#ifdef _WIN32 +        : key_token([&](const Key& k) { receiver(k); }) +#endif +    {} -    void reload(); +    void reload(const std::vector<std::tuple<key_opts &, fun> > &keys);  private: -    void bind_keyboard_shortcut(K &key, key_opts& k); +    void bind_keyboard_shortcut(K &key, const key_opts& k);  #ifdef _WIN32 -    void receiver(Key& k); +    void receiver(const Key& k);  #endif -signals: -    void center(); -    void toggle(); -    void zero();  }; - - diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp index e462812b..4f885f4f 100644 --- a/opentrack/simple-mat.hpp +++ b/opentrack/simple-mat.hpp @@ -157,7 +157,7 @@ public:          return ret;      } -    Mat<num, h_, w_> operator*(const num& other) const +    Mat<num, h_, w_> operator*(const num other) const      {          Mat<num, h_, w_> ret;          for (int j = 0; j < h_; j++) @@ -167,20 +167,16 @@ public:      }      template<int p> -    Mat<num, w_, p> operator*(const Mat<num, w_, p>& other) const +    Mat<num, h_, p> operator*(const Mat<num, w_, p>& other) const      { -        Mat<num, w_, p> ret; -        for (int j = 0; j < w_; j++) +        Mat<num, h_, p> ret; +        for (int k = 0; k < h_; k++)              for (int i = 0; i < p; i++)              { -                num sum = num(0); - -                for (int k = 0; k < h_; k++) -                    sum += data[j][k]*other(k, i); - -                ret(j, i) = sum; +                ret(k, i) = 0; +                for (int j = 0; j < w_; j++) +                    ret(k, i) += data[k][j] * other(j, i);              } -          return ret;      } @@ -189,7 +185,7 @@ public:      template<typename... ts, int h__ = h_, int w__ = w_,               typename = typename std::enable_if<is_arglist_correct<num, h__, w__, ts...>::value>::type> -    Mat(ts const&... xs) +    Mat(const ts... xs)      {          const std::initializer_list<num> init = { static_cast<num>(xs)... };          auto iter = init.begin(); @@ -198,14 +194,6 @@ public:                  data[j][i] = *iter++;      } -    template<typename t> -    Mat(const t* xs) -    { -        for (int j = 0; j < h_; j++) -            for (int i = 0; i < w_; i++) -                data[j][i] = num(*xs++); -    } -      Mat()      {          for (int j = 0; j < h_; j++) @@ -244,7 +232,7 @@ public:          for (int j = 0; j < h_; j++)              for (int i = 0; i < w_; i++) -                ret.data[i][j] = data[j][i]; +                ret(i, j) = data[j][i];          return ret;      } diff --git a/opentrack/state.hpp b/opentrack/state.hpp index e4cb0f04..dcb18293 100644 --- a/opentrack/state.hpp +++ b/opentrack/state.hpp @@ -9,7 +9,7 @@  #pragma once  #include <vector> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #include "opentrack/plugin-support.hpp"  #include "opentrack/main-settings.hpp" diff --git a/opentrack/tracker.h b/opentrack/tracker.h index 890660e1..36b5cad4 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -18,7 +18,7 @@  #include "spline-widget/functionconfig.h"  #include "main-settings.hpp" -#include "options.hpp" +#include "opentrack-compat/options.hpp"  #include <QMutex>  #include <QThread> @@ -40,7 +40,13 @@ public:      inline double operator()(int i) const { return axes[i]; }  }; -class Tracker : private QThread { +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +class OPENTRACK_EXPORT Tracker : private QThread {      Q_OBJECT  private:      QMutex mtx; @@ -74,7 +80,7 @@ public:      void get_raw_and_mapped_poses(double* mapped, double* raw) const;      void start() { QThread::start(); } -    void toggle_enabled() { enabledp = !enabledp; } -    void center() { centerp = !centerp; } -    void zero() { zero_ = !zero_; } +    void toggle_enabled() { qDebug() << "toggle enabled"; enabledp = !enabledp; } +    void center() { qDebug() << "toggle center"; centerp = !centerp; } +    void zero() { qDebug() << "toggle zero"; zero_ = !zero_; }  }; diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp new file mode 100644 index 00000000..5e6f2011 --- /dev/null +++ b/opentrack/win32-joystick.cpp @@ -0,0 +1,299 @@ +#undef NDEBUG +#include <cassert> +#include "win32-joystick.hpp" + +#ifdef _WIN32 + +void win32_joy_ctx::poll(fn f) +{ +    //refresh(false); +     +    QMutexLocker l(&mtx); +     +    for (auto& j : joys) +    { +        j.second->poll(f); +    } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) +{ +    //refresh(false); +     +    QMutexLocker l(&mtx); +     +    auto iter = joys.find(guid); +     +    if (iter == joys.end()) +        return false; +     +    auto& j = iter->second; +     +    auto& joy_handle = j->joy_handle; +    bool ok = false; +    HRESULT hr; +     +    (void) joy_handle->Acquire(); +     +    if (!FAILED(hr = joy_handle->Poll())) +        ok = true; +     +    if (!ok) +    { +        qDebug() << "joy acquire failed" << guid << hr; +        (void) joy_handle->Unacquire(); +        return false; +    } +     +    DIJOYSTATE2 js; +    memset(&js, 0, sizeof(js)); +     +    if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) +    { +        qDebug() << "joy get state failed" << guid << hr; +        return false; +    } +     +    const int values[] = { +        js.lX, +        js.lY, +        js.lZ, +        js.lRx, +        js.lRy, +        js.lRz, +        js.rglSlider[0], +        js.rglSlider[1] +    }; +     +    for (int i = 0; i < 8; i++) +        axes[i] = values[i]; +     +    return true; +} + +win32_joy_ctx::~win32_joy_ctx() +{ +    release(); +} + +std::vector<win32_joy_ctx::joy_info> win32_joy_ctx::get_joy_info() +{ +    QMutexLocker l(&mtx); +     +    std::vector<joy_info> ret; +     +    for (auto& j : joys) +        ret.push_back(joy_info { j.second->name, j.first }); +     +    return ret; +} + +win32_joy_ctx::win32_joy_ctx() +{ +    if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) != DI_OK) { +        qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); +        assert(!"direct input handle can't be created"); +    } +    refresh(); +} + +void win32_joy_ctx::release() +{ +    joys = std::unordered_map<QString, std::shared_ptr<joy>>(); +    di->Release(); +    di = nullptr; +} + +void win32_joy_ctx::refresh() +{ +    QMutexLocker l(&mtx); +     +    qDebug() << "joy list refresh"; +    enum_state st(joys, fake_main_window, di); +} + +QString win32_joy_ctx::guid_to_string(const GUID guid) +{ +    char buf[40] = {0}; +    wchar_t szGuidW[40] = {0}; +     +    StringFromGUID2(guid, szGuidW, 40); +    WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); +     +    return QString(buf); +} + +using fn = win32_joy_ctx::fn; + +void win32_joy_ctx::joy::release() +{ +    if (joy_handle) +    { +        (void) joy_handle->Unacquire(); +        joy_handle->Release(); +        joy_handle = nullptr; +    } +} + +bool win32_joy_ctx::joy::poll(fn f) +{ +    HRESULT hr; +    bool ok = false; +     +    (void) joy_handle->Acquire(); +     +    if (!FAILED(hr = joy_handle->Poll())) +        ok = true; +     +    if (!ok) +    { +        qDebug() << "joy acquire failed" << guid << hr; +        (void) joy_handle->Unacquire(); +        return false; +    } +     +    DIJOYSTATE2 js; +    memset(&js, 0, sizeof(js)); +     +    if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) +    { +        qDebug() << "joy get state failed" << guid << hr; +        return false; +    } +     +    for (int i = 0; i < 128; i++) +    { +        const bool state = !!(js.rgbButtons[i] & 0x80) && js.rgbButtons[i] != js_old.rgbButtons[i]; +        if (state != pressed[i]) +        { +            f(guid, i, state); +            qDebug() << "btn" << guid << i << state; +        } +        pressed[i] = state; +    } +     +    js_old = js; +     +    return true; +} + +win32_joy_ctx::enum_state::enum_state(std::unordered_map<QString, std::shared_ptr<joy>> &joys, +                                      QMainWindow &fake_main_window, +                                      LPDIRECTINPUT8 di) : +    fake_main_window(fake_main_window), +    di(di) +{ +    this->joys = joys; +     +    HRESULT hr; + +    if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, +                                   EnumJoysticksCallback, +                                   this, +                                   DIEDFL_ATTACHEDONLY))) +    { +        qDebug() << "failed enum joysticks" << hr; +        return; +    } +     +    auto& js = this->joys; +     +    for (auto it = js.begin(); it != js.end(); ) +    { +        if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) +            it = js.erase(it); +        else +            it++; +    } +     +    joys = this->joys; +} + +win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) +{ +    enum_state& state = *reinterpret_cast<enum_state*>(pContext); +    const QString guid = guid_to_string(pdidInstance->guidInstance); +    const QString name = QString(pdidInstance->tszInstanceName); +     +    auto it = state.joys.find(guid); +    const bool exists = it != state.joys.end(); +     +    state.all.push_back(guid); +     +    if (!exists) +    { +        HRESULT hr; +        LPDIRECTINPUTDEVICE8 h; +        if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) +        { +            qDebug() << "createdevice" << guid << hr; +            goto end; +        } +        if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) +        { +            qDebug() << "format"; +            h->Release(); +            goto end; +        } +         +        if (FAILED(h->SetCooperativeLevel((HWND) state.fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) +        { +            qDebug() << "coop"; +            h->Release(); +            goto end; +        } +        if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) +        { +            qDebug() << "enum-objects"; +            h->Release(); +            goto end; +        } +         +        qDebug() << "add joy" << guid; +        state.joys[guid] = std::make_shared<joy>(h, guid, name); +    } +end: +    return DIENUM_CONTINUE; +} + +win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) +{ +    if (pdidoi->dwType & DIDFT_AXIS) +    { +        DIPROPRANGE diprg; +        memset(&diprg, 0, sizeof(diprg)); +        diprg.diph.dwSize = sizeof( DIPROPRANGE ); +        diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); +        diprg.diph.dwHow = DIPH_BYID; +        diprg.diph.dwObj = pdidoi->dwType; +        diprg.lMax = joy_axis_size; +        diprg.lMin = -joy_axis_size; +         +        HRESULT hr; +         +        if (FAILED(hr = reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) +        { +            qDebug() << "DIPROP_RANGE" << hr; +            return DIENUM_STOP; +        } +    } +     +    return DIENUM_CONTINUE; +} + +win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString &guid, const QString &name) +    : joy_handle(handle), guid(guid), name(name) +{ +    qDebug() << "got joy" << guid; +    for (int i = 0; i < 128; i++) +        pressed[i] = false; +    memset(&js_old, 0, sizeof(js_old)); +} + +win32_joy_ctx::joy::~joy() +{ +    qDebug() << "nix joy" << guid; +    release(); +} + +#endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp new file mode 100644 index 00000000..9c888326 --- /dev/null +++ b/opentrack/win32-joystick.hpp @@ -0,0 +1,100 @@ +#pragma once + +#ifdef _WIN32 + +#include <cstring> +#include <memory> +#include <vector> +#include <functional> +#include <algorithm> +#include <unordered_map> +#ifndef DIRECTINPUT_VERSION +#   define DIRECTINPUT_VERSION 0x800 +#endif +#include <dinput.h> +#include <windows.h> +#include "opentrack-compat/timer.hpp" +#include <QString> +#include <QDebug> +#include <QMutex> +#include <QMutexLocker> +#include <QMainWindow> + +namespace std { +template<> +struct hash<QString> +{ +    inline std::size_t operator()(const QString& value) const +    { +        return qHash(value); +    } +}; +} + +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +struct OPENTRACK_EXPORT win32_joy_ctx +{ +    using fn = std::function<void(const QString& guid, int btn, bool held)>; +     +    enum { joy_axis_size = 65535 }; +     +    struct joy_info +    { +        QString name, guid; +    }; + +    void poll(fn f); +    bool poll_axis(const QString& guid, int axes[8]); +    std::vector<joy_info> get_joy_info(); +     +    win32_joy_ctx(const win32_joy_ctx&) = delete; +    win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; +     +    win32_joy_ctx(); +    ~win32_joy_ctx(); +    void refresh(); +private: +    QMutex mtx; +    QMainWindow fake_main_window; +    LPDIRECTINPUT8 di; +     +    static QString guid_to_string(const GUID guid); +    void release(); +     +    struct joy +    { +        LPDIRECTINPUTDEVICE8 joy_handle; +        QString guid, name; +        bool pressed[128]; +        Timer first_timer; +        DIJOYSTATE2 js_old; + +        joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name); +        ~joy(); + +        void release(); +        bool poll(fn f); +    }; +     +    std::unordered_map<QString, std::shared_ptr<joy>> joys; + +    class enum_state +    { +        std::unordered_map<QString, std::shared_ptr<joy>> joys; +        QMainWindow& fake_main_window; +        LPDIRECTINPUT8 di; +         +        std::vector<QString> all; +        static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); +        static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); +    public: +        enum_state(std::unordered_map<QString, std::shared_ptr<joy>>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); +    }; +}; + +#endif diff --git a/opentrack/win32-shortcuts.cpp b/opentrack/win32-shortcuts.cpp index a0ed51b3..fb84e709 100644 --- a/opentrack/win32-shortcuts.cpp +++ b/opentrack/win32-shortcuts.cpp @@ -116,6 +116,7 @@ QList<win_key> windows_key_sequences =         win_key(DIK_Z, Qt::Key::Key_Z ),         win_key(DIK_RETURN, Qt::Key::Key_Return),         win_key(DIK_INSERT, Qt::Key::Key_Insert), +       win_key(DIK_DELETE, Qt::Key::Key_Delete),         win_key(DIK_SPACE, Qt::Key::Key_Space),         win_key(DIK_SYSRQ, Qt::Key::Key_Print),         win_key(DIK_SCROLL, Qt::Key::Key_ScrollLock), diff --git a/opentrack/win32-shortcuts.h b/opentrack/win32-shortcuts.h index fe92ae53..9b2c6121 100644 --- a/opentrack/win32-shortcuts.h +++ b/opentrack/win32-shortcuts.h @@ -10,7 +10,13 @@ struct win_key;  extern QList<win_key> windows_key_mods;  extern QList<win_key> windows_key_sequences; -struct win_key +#ifdef BUILD_api +#   include "opentrack-compat/export.hpp" +#else +#   include "opentrack-compat/import.hpp" +#endif + +struct OPENTRACK_EXPORT win_key  {      win_key(int win, Qt::Key qt) : win(win), qt(qt) {}      int win; diff --git a/opentrack/work.hpp b/opentrack/work.hpp index 5d1f6b54..4188b937 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -16,6 +16,9 @@  #include <QObject>  #include <QFrame>  #include <memory> +#include <vector> +#include <functional> +#include <tuple>  struct Work  { @@ -24,32 +27,33 @@ struct Work      mem<Tracker> tracker;      mem<Shortcuts> sc;      WId handle; - -    Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) : +    using fn = std::function<void(void)>; +    using tt = std::tuple<key_opts&, fn>; +    std::vector<std::tuple<key_opts&, fn>> keys; +     +    Work(main_settings& s, Mappings& m, SelectedLibraries& libs, WId handle) :          s(s), libs(libs),          tracker(std::make_shared<Tracker>(s, m, libs)), -        sc(std::make_shared<Shortcuts>(handle)), -        handle(handle) +        sc(std::make_shared<Shortcuts>()), +        handle(handle), +        keys { +            tt(s.key_center, [&]() -> void { tracker->center(); }), +            tt(s.key_toggle, [&]() -> void { tracker->toggle_enabled(); }), +            tt(s.key_zero, [&]() -> void { tracker->zero(); }), +        }      { -#ifndef _WIN32 -        QObject::connect(sc->keyCenter.get(), SIGNAL(activated()), recv, SLOT(shortcutRecentered())); -        QObject::connect(sc->keyToggle.get(), SIGNAL(activated()), recv, SLOT(shortcutToggled())); -        QObject::connect(sc->keyZero.get(), SIGNAL(activated()), recv, SLOT(shortcutZeroed())); -#else -        QObject::connect(sc.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered())); -        QObject::connect(sc.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled())); -        QObject::connect(sc.get(), SIGNAL(zero()), recv, SLOT(shortcutZeroed())); -#endif -        tracker->start(); +        reload_shortcuts(); +        tracker->start();         }      void reload_shortcuts()      { -        sc->reload(); +        sc->reload(keys);      }      ~Work()      { +        sc = nullptr;          // order matters, otherwise use-after-free -sh          tracker = nullptr;          libs = SelectedLibraries(); diff --git a/pose-widget/CMakeLists.txt b/pose-widget/CMakeLists.txt index 66cafef7..e48660d7 100644 --- a/pose-widget/CMakeLists.txt +++ b/pose-widget/CMakeLists.txt @@ -1 +1 @@ -opentrack_boilerplate(opentrack-pose-widget NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-pose-widget NO-LINKER-SCRIPT LINKAGE) diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp index 3ee480a1..1b30e585 100644 --- a/pose-widget/glwidget.cpp +++ b/pose-widget/glwidget.cpp @@ -98,16 +98,18 @@ inline GLWidget::vec3 GLWidget::normal(const vec3& p1, const vec3& p2, const vec  void GLWidget::project_quad_texture() {      const int sx = width(), sy = height(); -    vec2 pt[4]; +    const int ow = front.width(), oh = front.height();      const vec3 corners[] = { -        vec3(0., 0, 0), -        vec3(sx-1, 0, 0), -        vec3(0, sy-1, 0), -        vec3(sx-1, sy-1, 0.) +        vec3(-ow/2., -oh/2, 0), +        vec3(ow/2, -oh/2, 0), +        vec3(-ow/2, oh/2, 0), +        vec3(ow/2, oh/2, 0.)      }; +    vec2 pt[4]; +    vec2 sz((sx-ow)/2, (sy-oh)/2);      for (int i = 0; i < 4; i++) -        pt[i] = project(vec3(corners[i].x() - sx/2, corners[i].y() - sy/2, 0)) + vec2(sx/2, sy/2); +        pt[i] = project(corners[i]) + vec2(sx/2, sy/2);      vec3 normal1(0, 0, 1);      vec3 normal2; @@ -122,9 +124,7 @@ void GLWidget::project_quad_texture() {      QImage& tex = dir < 0 ? back : front; -    int ow = tex.width(), oh = tex.height(); - -    QImage texture(QSize(sx, sy), QImage::Format_RGB888); +    QImage texture(QSize(sx, sy), QImage::Format_RGBA8888);      QColor bgColor = palette().color(QPalette::Current, QPalette::Window);      texture.fill(bgColor); @@ -199,6 +199,11 @@ void GLWidget::project_quad_texture() {                      const unsigned char r___ = orig[orig_pos___ + 2];                      const unsigned char g___ = orig[orig_pos___ + 1];                      const unsigned char b___ = orig[orig_pos___ + 0]; +                     +                    const unsigned char a1 = orig[orig_pos + 3]; +                    const unsigned char a2 = orig[orig_pos_ + 3]; +                    const unsigned char a3 = orig[orig_pos__ + 3]; +                    const unsigned char a4 = orig[orig_pos___ + 3];                      const int pos = y * dest_pitch + x * dest_depth; @@ -207,6 +212,7 @@ void GLWidget::project_quad_texture() {                      dest[pos + 0] = (r * ax + r__ * ax_) * ay + (r___ * ax + r_ * ax_) * ay_;                      dest[pos + 1] = (g * ax + g__ * ax_) * ay + (g___ * ax + g_ * ax_) * ay_;                      dest[pos + 2] = (b * ax + b__ * ax_) * ay + (b___ * ax + b_ * ax_) * ay_; +                    dest[pos + 3] = (a1 * ax + a3 * ax_) * ay + (a4 * ax + a2 * ax_) * ay_;                      break;                  } diff --git a/pose-widget/glwidget.h b/pose-widget/glwidget.h index fca3502d..8896a3cf 100644 --- a/pose-widget/glwidget.h +++ b/pose-widget/glwidget.h @@ -13,7 +13,7 @@  #include "opentrack/plugin-api.hpp"  #include "opentrack/simple-mat.hpp" -#ifdef BUILD_opentrack_pose_widget +#ifdef BUILD_pose_widget  #   define POSE_WIDGET_EXPORT Q_DECL_EXPORT  #else  #   define POSE_WIDGET_EXPORT Q_DECL_IMPORT diff --git a/pose-widget/images/side1.png b/pose-widget/images/side1.png Binary files differindex 1424faa3..e85a3205 100755 --- a/pose-widget/images/side1.png +++ b/pose-widget/images/side1.png diff --git a/pose-widget/images/side6.png b/pose-widget/images/side6.png Binary files differindex 1424faa3..e85a3205 100755 --- a/pose-widget/images/side6.png +++ b/pose-widget/images/side6.png diff --git a/proto-fg/ftnoir_protocol_fg.h b/proto-fg/ftnoir_protocol_fg.h index de528270..5b1cbc81 100644 --- a/proto-fg/ftnoir_protocol_fg.h +++ b/proto-fg/ftnoir_protocol_fg.h @@ -15,7 +15,7 @@  #include <QUdpSocket>  #include <QMessageBox>  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/proto-fsuipc/ftnoir_protocol_fsuipc.h b/proto-fsuipc/ftnoir_protocol_fsuipc.h index c8e91a42..af59e988 100644 --- a/proto-fsuipc/ftnoir_protocol_fsuipc.h +++ b/proto-fsuipc/ftnoir_protocol_fsuipc.h @@ -24,7 +24,7 @@  #include <QDebug>  #include <QFile>  #include <QFileDialog> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll" diff --git a/proto-ft/ftnoir_protocol_ft.h b/proto-ft/ftnoir_protocol_ft.h index 8e50f1cb..9cf16f03 100644 --- a/proto-ft/ftnoir_protocol_ft.h +++ b/proto-ft/ftnoir_protocol_ft.h @@ -19,7 +19,7 @@  #include <QMutex>  #include <QMutexLocker>  #include "opentrack-compat/shm.h" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "freetrackclient/fttypes.h"  using namespace options; diff --git a/proto-ftn/ftnoir_protocol_ftn.h b/proto-ftn/ftnoir_protocol_ftn.h index 7fe6c225..d8b8aff0 100644 --- a/proto-ftn/ftnoir_protocol_ftn.h +++ b/proto-ftn/ftnoir_protocol_ftn.h @@ -16,7 +16,7 @@  #include <QMessageBox>  #include <cmath>  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/proto-mouse/ftnoir_protocol_mouse.h b/proto-mouse/ftnoir_protocol_mouse.h index 595be393..f1730777 100644 --- a/proto-mouse/ftnoir_protocol_mouse.h +++ b/proto-mouse/ftnoir_protocol_mouse.h @@ -10,7 +10,7 @@  #include "ui_ftnoir_mousecontrols.h"  #include <QDebug>  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/proto-sc/ftnoir_protocol_sc.h b/proto-sc/ftnoir_protocol_sc.h index 671a3500..dcc0ca77 100644 --- a/proto-sc/ftnoir_protocol_sc.h +++ b/proto-sc/ftnoir_protocol_sc.h @@ -20,7 +20,7 @@  #include <QProcess>  #include <QDebug>  #include <QFile> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #include <windows.h> diff --git a/qxt-mini/CMakeLists.txt b/qxt-mini/CMakeLists.txt index 5de29cd1..a8b8fb1d 100644 --- a/qxt-mini/CMakeLists.txt +++ b/qxt-mini/CMakeLists.txt @@ -1,5 +1,5 @@  if(UNIX OR APPLE) -    opentrack_boilerplate(opentrack-qxt-mini NO-LINKER-SCRIPT NO-COMPAT) +    opentrack_boilerplate(opentrack-qxt-mini NO-LINKER-SCRIPT NO-COMPAT LINKAGE)      if(NOT APPLE)          target_link_libraries(opentrack-qxt-mini X11)      else() diff --git a/qxt-mini/QxtGlobalShortcut b/qxt-mini/QxtGlobalShortcut index d673035b..c2827bc2 100644 --- a/qxt-mini/QxtGlobalShortcut +++ b/qxt-mini/QxtGlobalShortcut @@ -1,2 +1,4 @@ -#include "qxtglobalshortcut.h" +#ifndef _WIN32 +#   include "qxtglobalshortcut.h" +#endif diff --git a/qxt-mini/qxtglobal.h b/qxt-mini/qxtglobal.h index 64fd35dc..913da556 100644 --- a/qxt-mini/qxtglobal.h +++ b/qxt-mini/qxtglobal.h @@ -51,7 +51,7 @@  #define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE -#ifdef BUILD_opentrack_qxt_mini +#ifdef BUILD_qxt_mini  #   define QXT_BUILD  #   define BUILD_QXT_GUI  #   define BUILD_QXT diff --git a/settings/facetracknoir supported games.csv b/settings/facetracknoir supported games.csv index cf43d7f6..55b38a47 100644 --- a/settings/facetracknoir supported games.csv +++ b/settings/facetracknoir supported games.csv @@ -5,13 +5,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  3;3D Instructor;FreeTrack20;V160;;;20490;00034B0FC367116611B100  4;3D Interactive;FreeTrack20;V160;;;20425;0004C6371D77135815A600  505;3D Interieur Visualisation;FreeTrack20;V160;;;20815;01F9EDEE75DAC2968D9A00 -5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00  6;3D-Fahrschule Driving Simulator;FreeTrack20;V160;;;20020;000601075146E0E9625B00 +5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00  7;3ds Max;FreeTrack20;V160;;;8601;00077A32A1A7523A4DE700 +11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400 +20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300 +498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200 +32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 +33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00  8;Aaaaa!;FreeTrack20;V160;;;1775;00085485D831DA62CA7E00  9;Accessible Computer Games;FreeTrack20;V160;;;4301;000916BC07A2F9B35B6300  10;Aces High II;FreeTrack20;V160;V;bash1;2701;000A4B798B7221A72E5800 -11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400  12;Aerofly FS;FreeTrack20;V160;V;V4Friend;2025;000C3797169752CAB39A00  13;Affineon;FreeTrack20;V160;;;20405;000D662B0374339635A000  14;Air Battles: Sky Defender;FreeTrack20;V160;;;7003;000E7C822098630A2ED700 @@ -20,12 +24,10 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  17;AirBook;FreeTrack20;V160;;;15201;0011D615A9C8430A201A00  18;America's Army;FreeTrack20;V160;;;4101;00120BCF5753D98399E200  19;America's Army 3;FreeTrack20;V170;;;14203;00133F3206BCEA252BB700 -20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300  21;Apache: Air Assault;FreeTrack20;V160;V;paleta77;1875;001591D997A2D912AAA200  519;Apex Motorsports;FreeTrack20;V160;;;3675;02078F3159271BBE676800  22;Aprisoft Gartenplaner;FreeTrack20;V160;;;20014;0016F2F27A5762FA937A00  23;Aprisoft Traumhaus Designer;FreeTrack20;V160;;;20013;00174655E792BB825B9300 -498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200  24;ArmA;FreeTrack20;V160;V;EmBeES;10601;0018F2F27A57631A40F200  25;ArmA 2;FreeTrack20;V170;V;V4Friend Ronski;7502;0019EB3616B3A44F05B900  26;ArmA 2 Operation Arrowhead;FreeTrack20;V160;V;vn88holden;0;001ABC224B7783DAF0D500 @@ -36,22 +38,20 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  30;Arvoch Conflict;FreeTrack20;V160;;;14901;001E5C1FDE722DAE2BA900  31;Auditory Displays for the blind;FreeTrack20;V160;;;20035;001F0FC9FF862F9D34BA00  486;Autodesk;FreeTrack20;V160;;;20755;01E6953FA7F759AF33AC00 -32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 -33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00  482;B.O.M.B.;FreeTrack20;V160;;;3325;01E248ECCB81191AD49F00  34;BAE Systems HILAS cockpit;FreeTrack20;V160;;;20019;00220D9C887FD88E98B300 +45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000  35;Battle of Britain (iENT);FreeTrack20;V170;;;1305;00230BA119195B701AED00  36;Battle of Britain II - Wings of Victory;FreeTrack20;V160;V;Normalguy;7001;002452135882CA6419E200  37;Battlecruiser;FreeTrack20;V160;;;6101;00257C822098728A442900  38;Battlefield 2;FreeTrack20;V170;;;9601;0026B1560A2A7327659200  39;Battlefield 2 Trauma Studios;FreeTrack20;V160;;;6501;002720C7529B733AE2EA00  40;Battlefield 2142;FreeTrack20;V170;;;9602;00281C739AD3817FD43300 -41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00  42;Battleground Europe : WWII Online;FreeTrack20;V160;;;11201;002A985017330A844A1200 +41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00  573;Beamng.drive;FreeTrack20;V160;;;4525;023D0291C9C05323AC9500  43;Beckman Institute UIUC;FreeTrack20;V160;;;20012;002BB59DEFA8322A926A00  44;Beyond The Red Line;FreeTrack20;V160;;;13301;002CE7A7FAA27424BA2A00 -45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000  46;Big Scale Racing;FreeTrack20;V160;;;8301;002E4655E7A24ADDB99200  47;Birds of Prey;FreeTrack20;V160;;;1601;002FBF8C4EAA57730B3200  48;Birds of Steel;FreeTrack20;V160;;;1878;0030D7690F607233A21E00 @@ -63,15 +63,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  82;C-Spine;FreeTrack20;V160;;;4901;00525FD692C188FB8B2D00  54;C.A.R.S.;FreeTrack20;V170;;;2825;003698EFE2EB6EE8E11300  55;C.U.B.;FreeTrack20;V160;;;20505;0037848174F986FD85F500 -56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 -57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100  58;CCG Metamedia;FreeTrack20;V160;;;20009;003A6FA8A8DD86FE8BDB00  547;CDF Ghostship;FreeTrack20;V160;;;4150;02230A04C45292CC5DA400  568;CDF Starfighter;FreeTrack20;V160;;;4153;0238E7D9A14B2A1AE98900  59;CEWIT Immersive Cabin;FreeTrack20;V160;;;20370;003B90B5780C90078DEE00 +62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000 +555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00 +571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500 +56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 +57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100  60;Chopper;FreeTrack20;V160;;;3150;003CC166C8632A32EA2300  61;Clearbox;FreeTrack20;V160;;;20565;003D5C1FDE74279D1DB800 -62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000  558;Code 10;FreeTrack20;V160;;;2975;022E45423D22193FF81900  487;Cognitics;FreeTrack20;V160;;;20760;01E715A96D19515BFC1500  63;Colin McRae DiRT 2;FreeTrack20;V170;V;V4Friend;8107;003F7815C5379491C73300 @@ -82,7 +84,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  67;Combat Helo;FreeTrack20;V160;;;2001;004329DFA863FAE1EA7300  515;Combined Arms;FreeTrack20;V160;;;1309;0203387EDB1A5AFEADB600  68;Commandos Strike Force;FreeTrack20;V160;;;8801;0044C1BBF892DB037A7200 -555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00  69;Concept RS;FreeTrack20;V160;;;10701;004537971697736A72DA00  70;Condor: The Competitive Soaring Simulator;FreeTrack20;V160;V;MicheleF;5901;004670A8B762DA623A1300  71;Conflict Taiwan;FreeTrack20;V160;;;1950;0047D7690F6073399E2000 @@ -97,16 +98,17 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  79;Crysis Mod;FreeTrack20;V160;;;1625;004F90B57839B231A24200  80;Crystal Growth Simulation;FreeTrack20;V160;;;20029;005026F79742FB241A6200  81;Crytek;FreeTrack20;V170;;;2775;0051D5F1EBBAD81C714600 -571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500  562;Cypher City;FreeTrack20;V160;;;4250;023259070AE238A9E78100  83;D2x-XL;FreeTrack20;V160;;;16001;00532E20237BEDABEB8A00 +87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 +88;DCS:  Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 +89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500 +101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500 +103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00  84;Dark Horizons Lore;FreeTrack20;V160;;;7901;005487801A852AA7385200  85;Dawn of Aces - Gold Edition;FreeTrack20;V170;;;1304;0055A9ED7700814190DE00  86;Dawn of Aces II;FreeTrack20;V160;;;1302;00566925967C2BB0285500  513;Dawn of Aces/Red Baron;FreeTrack20;V160;;;1307;0201916C14F32918D9B800 -87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 -88;DCS:  Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 -89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500  90;Dead Reckoning;FreeTrack20;V160;;;10401;005A4C2F6752F912D66200  91;Delivery;FreeTrack20;V160;;;15901;005BF3E85B1A8534AE3400  471;Demon Core;FreeTrack20;V160;;;3225;01D7D1DC6052A165A7AC00 @@ -117,40 +119,36 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  528;Dovetail Games;FreeTrack20;V160;;;3850;0210EE3E0DA9BC1B888100  534;Dovetail Train Simulator 2015;FreeTrack20;V160;;;3851;02160B238D555F3D389E00  95;Down In Flames;FreeTrack20;V160;;;1025;005F29DFA873FB82A66000 +98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400  96;Driver Test;FreeTrack20;V160;;;20265;00609343487C3FAA429D00  97;Driver's Republic;FreeTrack20;V160;;;14001;0061D24C3F8A3F9C33AB00 -98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400  99;Driving Simulator;FreeTrack20;V160;;;13001;00630AC67539AC3F9F3A00 -100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 -101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500  102;Dungeons and Dragons Online;FreeTrack20;V170;;;1575;0066BD4D4DDC6BB6818800 -103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00  104;EADS Testing;FreeTrack20;V160;;;20303;00680288709760D5512900  504;EAFIT;FreeTrack20;V160;;;20810;01F8D2675ABC163E99B000 +107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500 +108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500 +112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 +115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 +550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200 +117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200 +122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 +572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000  105;Eagle Lander 3D;FreeTrack20;V160;;;11901;00697686E5A7B209C27900  106;EasyVR;FreeTrack20;V160;;;20220;006A68292872FAC4588100 -107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500  508;Elite: Dangerous;FreeTrack20;V170;;;3475;0D93A9485EECA12E18BE00  481;Embers of Caerus;FreeTrack20;V170;;;3275;0CCB4134258D7E10119E00 -108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500  109;Enemy Engaged 2;FreeTrack20;V160;;;2102;006D010873EA635AEDC800  110;Enemy Engaged: Commanche vs Hokum;FreeTrack20;V160;;;2101;006E157D789379636AED00  524;Enemy Starfighter;FreeTrack20;V160;;;3725;020C7EF3AC4F08C8787600  111;Envision TE;FreeTrack20;V160;;;20320;006FD13C2A863CAF26AB00 -112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 -113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00  114;Euro Truck Simulator;FreeTrack20;V160;V;mamsa;13602;00721B4BFF8B3EA3296600 -115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 -550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200  116;Eventology;FreeTrack20;V160;;;12201;0074849F8B469C2BAC3600 -117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200  118;Evochron Alliance 2.0;FreeTrack20;V160;;;14904;00767A32A1A8735A022900  557;Evochron Legacy;FreeTrack20;V160;;;14909;022D84A6946770E4EFD800  119;Evochron Legends;FreeTrack20;V160;;;14906;0077D6E585F8B41A12BA00  120;Evochron Mercenary;FreeTrack20;V160;V;Scavenger4711 ;14907;00783752FBC7B42B221A00  121;Evochron Renegades;FreeTrack20;V160;;;14905;0079621E7763FB421A1300 -122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 -572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000  125;F-22 Total Air War;FreeTrack20;V160;;;1750;007D20C79F475F0621DB00  126;F-35 PTA;FreeTrack20;V160;;;20185;007E26F7977E96C0352100  148;F-Trainer;FreeTrack20;V160;;;20615;0094C6371D8AFB8C3E9900 @@ -158,11 +156,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  531;F1 2015;FreeTrack20;V170;;;8110;1FAE39C238A4D2D6541200  124;F1 Challenge 99-02;FreeTrack20;V160;;;4401;007CA15F278FB660C9D210  127;FAAC;FreeTrack20;V160;;;20500;007F0F00F489118300C000 +132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00 +552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 +147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900  128;Farmer Simulator 2009;FreeTrack20;V160;;;1725;0080926ED8A1EB628AB300  129;Faros Driving Simulator;FreeTrack20;V160;;;8001;0081B1C6647A1EA839A800  130;Faubert Lab Car Simulator;FreeTrack20;V160;;;20480;00822E542A7F2DB61F9700  131;Ferrari Virtual Academy;FreeTrack20;V160;V;sosna1983 ;0;0083C0AF8C24B62D974000 -132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00  133;Fighter Ace;FreeTrack20;V160;;;8401;0085E2D1D77D259837B700  134;Fighter Ops;FreeTrack20;V160;;;9301;00860FC9FF8B23A033BA00  135;Fighter Squadron: Screamin Demons Over Europe;FreeTrack20;V160;;;1675;00872E20237D259A27A600 @@ -183,10 +183,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  144;Free Falcon 4.0: Allied Force;FreeTrack20;V160;;;8901;0090656DD6793CA9325900  145;Free Falcon 5;FreeTrack20;V160;V;V4Friend;1902;00911038C3AAB32590E900  146;FreeSpace2;FreeTrack20;V160;;;13302;0092C8CDF8C2EA63496300 -552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 -147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900  149;Full Out;FreeTrack20;V160;;;1701;009527D5047C31A0375800  150;Future Pinball;FreeTrack20;V160;V;V4Friend;13101;00969343487E42B541AA00 +159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 +160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 +161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 +162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 +163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300  151;Game VR;FreeTrack20;V160;;;20325;009756BA018030B0355500  152;GameLab;FreeTrack20;V160;;;20555;00985485D891DB23092200  472;Games Farm;FreeTrack20;V160;;;3250;01D875C0981E627E5C7600 @@ -202,38 +205,34 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  156;Gothic 3;FreeTrack20;V160;;;14401;009C37971697B36AD32A00  157;Grand Prix Legends;FreeTrack20;V160;;;6701;009D521358D3D933B96E01  158;Grand Theft Auto: San Andreas;FreeTrack20;V160;;;7808;009E5F3D95777D3BA23700 -159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 -160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 -161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 -162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 -163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300  164;Gun Commander;FreeTrack20;V160;;;2675;00A4E2D1D77E319FEE8600  520;H1Z1;FreeTrack20;V170;;;6004;1774F090B1BA9E782D0800 +169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000 +171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900 +173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 +174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 +175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00  165;Half Life 2;FreeTrack20;V160;;;7806;00A556BA018130AF365500  166;Halo;FreeTrack20;V160;;;3801;00A656BA018130AF3F9C00 -502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00  167;Hardware Control Simulator Railway Electronics;FreeTrack20;V160;;;20705;00A7F3E85B1A8930B42F00  168;Harrier Attack II;FreeTrack20;V160;;;1175;00A8F2F27A57D20A940900  499;Harry's Hard Choices Interactive;FreeTrack20;V160;;;20800;01F33A21BAE3DB6D48A000 -169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000  170;Herissons (Paris France);FreeTrack20;V160;;;20001;00AAEA1CBED8C20B430B00 -523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 -171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900  172;HoverAssault;FreeTrack20;V160;;;5303;00AC521358E3AA832A4000 -173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 -174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 -175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00  176;Huawei Software;FreeTrack20;V160;;;20660;00B04655E8030A733AB300  177;HueSpace;FreeTrack20;V160;;;20510;00B1231517C44960FB6300  178;Hyper Vision;FreeTrack20;V160;;;15101;00B2DB242B657D43B32300 -179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 -180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700  181;IESA;FreeTrack20;V160;;;20037;00B5157D78D0E840AD7100  182;IL-2 Cliffs of Dover;FreeTrack20;V160;V;V4Friend;0;00B6282282095F00521000  183;IL-2 Forgotten Battles ACE Pacific Fighters;FreeTrack20;V160;V;Glenn;1001;00B722FD79137100621100  484;IL-2 Sturmovik: Battle of Stalingrad;FreeTrack20;V170;;;1008;03F04D5368D1FD2DF2AE00 -184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400  185;ILP;FreeTrack20;V160;;;20310;00B9F07957801789C9A600 +193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 +536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 +194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 +506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 +195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00 +184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400  186;Imagine 3D ATC Tower Simulation;FreeTrack20;V160;;;20032;00BAEF7A8F4B8812B95300  187;In Touch Technologies Inc.;FreeTrack20;V160;;;20006;00BB84817A3A5124B23D00  188;Inglobe;FreeTrack20;V160;;;20360;00BCE7A7FAA27B2DA82700 @@ -242,19 +241,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  575;Interstellar Rift;FreeTrack20;V160;;;4550;023FF83230A370CBC6AC00  191;Intific;FreeTrack20;V160;;;20655;00BF2BCA747F2AA8309D00  566;Into the Dungeon;FreeTrack20;V160;;;4375;0236B346990ACCFC047A00 -192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 -193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 -536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 -194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 -506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 -195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00  196;J.J. Keller and Associates;FreeTrack20;V160;;;20002;00C4E482F57FE77CF46300 +199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900 +202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600  197;Janes F18;FreeTrack20;V160;;;9001;00C55F3D9577802AAF2E00  198;Javal Ent.;FreeTrack20;V160;;;2650;00C622FD7A28BA2FAEEA00 -199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900  200;Jet Thunder;FreeTrack20;V160;;;4501;00C82100801FA4EA9A3500  201;Jetfighter V;FreeTrack20;V160;;;2501;00C9F52E42217B33A63200 -202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600  203;John Deere Vehicle Simulator;FreeTrack20;V160;;;20175;00CB29DFA8D3FA92A66000  204;Jump to Lightspeed;FreeTrack20;V160;;;6001;00CCC166C8D3FA12E52400  205;Jumpgate;FreeTrack20;V160;;;15001;00CD26F797B32A63E99200 @@ -263,70 +256,69 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  476;KAI FLight Simulator;FreeTrack20;V160;;;20725;01DCC522132A5C01EDE500  560;Keita Head Tracking;FreeTrack20;V160;;;20385;02307E33478667072B0800  208;Key Macro View;FreeTrack20;V160;;;12001;00D016BC08431B1EF90100 -209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900  521;Kongsberg GlobalSim;FreeTrack20;V160;;;20825;0209B2C573D990BF764700  210;L-3;FreeTrack20;V160;;;20465;00D2F885EFA8DE67878B00  211;L-3 Communications;FreeTrack20;V160;;;20051;00D3D6E585F92F765E7800  522;LG Electronics;FreeTrack20;V160;;;20830;020A3678F5833D513DCA00 +577;Limb;FreeTrack20;V160;;;4650;0241D999E2E247B1DFDD00  212;Lionhead MGS Game Research;FreeTrack20;V160;;;15301;00D4C1BBF9227B238AE200  213;Live For Speed;FreeTrack20;V160;V;zild1221 ;7101;00D528228526A833521300  214;Live for Speed S2;FreeTrack20;V160;;;11601;00D63752FBC8235B923500  218;Lock-On: Modern Air Combat;FreeTrack20;V160;;;1002;00DAAC156D903C993B6200 +217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200  215;Lockheed Martin Littoral Combat Ship simulator;FreeTrack20;V160;;;20025;00D771ED5E802A9827A000  216;Lockheed Martin Prepar3D;SimConnect;V130;V;elelbe ;0;00D8D615A9C8F36932AA00 -217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200  219;London NHS;FreeTrack20;V160;;;20640;00DB2E2023832BA123A100  220;Lore (Dark Horizons);FreeTrack20;V160;;;5302;00DCF478D27833DB62D500  221;Love;FreeTrack20;V160;;;3125;00DD71ED5E802AAB214800  222;Lucid Engine;FreeTrack20;V160;;;10501;00DE71ED5E803098259C00  514;M4 Tank Brigade;FreeTrack20;V160;;;1308;02024ED5A3A26741604300  223;M4 Tank Platoon;FreeTrack20;V160;;;1306;00DFDCC441A8E036320900 -224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000  549;MAG WIP;FreeTrack20;V160;;;4152;02252A1C82FD29D9FFB900 +244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200 +250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 +251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 +224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000  225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800  226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700 +233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700  227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300 -228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200  516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400 +228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200  229;Medical Image Visualization;FreeTrack20;V160;;;20295;00E59343488532A5359B00  230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300  231;MetaVR;FreeTrack20;V160;;;20545;00E7C5BEE48120A8308800  232;Meteoroid Maze;FreeTrack20;V160;;;13003;00E8F079578430AD2EB200 -233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700  234;Micro Flight;FreeTrack20;V160;V;V4Friend;5101;00EABA89D078439932EA00  235;Microsoft ESP;FreeTrack20;V160;;;2306;00EB0AC67E30A63BA53F00 -236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 -237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810  238;Microsoft FS2002/2004;FSUIPC;V130;V;V4Friend;0;00EE44958F34992CB43A00  239;Microsoft FSX;SimConnect;V130;V;V4Friend;0;00EFF478D278437A73AA00 +236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 +237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810  240;Microsoft Train Simulator;FreeTrack20;V160;;;7805;00F00449225A439A13FB00  494;MiddleVR;FreeTrack20;V160;;;20785;01EE1227DF43CA90C26100  241;Mig Alley;FreeTrack20;V160;;;1501;00F17686E5A83289CDA700  242;Mimik Vehicle Simulator;FreeTrack20;V160;;;20585;00F2AB1D58A8E35A531A00  243;Miner Wars;FreeTrack20;V160;;;2550;00F3C5BEE48124A234A400 -244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200  245;ModelSim;FreeTrack20;V160;;;20540;00F544958F3A9A1FB11A00  246;Morgan State University;FreeTrack20;V160;;;20010;00F65909437D3CA5339A00  247;Motor Company;FreeTrack20;V160;;;11501;00F70288F37A629A7DD700  248;Motorsport Simulators;FreeTrack20;V160;;;4201;00F8F52E42217E3DA63B00  249;Mouse Emulation;FreeTrack20;V160;;;8501;00F9950F9A8E29B93A9700 -250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 -251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 -252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800  253;NASA Crew Exploration Vehicle;FreeTrack20;V160;;;20017;00FD028900985FA5501A00  254;NASCAR Heat;FreeTrack20;V160;;;2602;00FE311857E10880B84100  255;NASCAR Racing 2003 season;FreeTrack20;V160;;;7804;00FFDE661F6D920B87FC10  256;NASCAR SimRacing;FreeTrack20;V160;;;6201;01004098708870D761A500 +262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500  535;Navi Trainer Professional;FreeTrack20;V160;;;20855;0217C0E0793305EE8D5200  257;NecroVisioN;FreeTrack20;V160;;;15601;0101621E77F2EA830A8100  258;NetKar Pro;FreeTrack20;V160;V;sosna1983 ;10901;01028C3958334A5169A300  259;Nitro Stunt Racing;FreeTrack20;V160;;;13901;0103C0AF9428B82DA5ED00  260;North Eastern University;FreeTrack20;V160;;;20003;0104A2AE4823BB7449DE00  261;Novint;FreeTrack20;V160;;;2725;01051C76F8137B823A4300 -262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500  479;OHJCH;FreeTrack20;V160;;;20740;01DF992E6C0DA43A703600 -551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00  263;OMSI Bus Simulator;FreeTrack20;V160;V;Thiago ;2225;0107F47CC37861A9606600 +551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00  264;Onadime - Realtime Animation;FreeTrack20;V160;;;20049;010853FE1E9229A3339B00  265;Open Falcon 4.5;FreeTrack20;V160;V;muplex ;0;0109B1C664832D9B385500  266;Operation Air Assault 2;FreeTrack20;V160;;;5401;010ABB5BF72C9238973B00 @@ -340,6 +332,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  274;Oryx Vehicle Simulators;FreeTrack20;V160;;;20028;0112C8CDF952EBA4763100  275;Outer Conflict: Frontiers;FreeTrack20;V160;;;1900;01136C6967883EAA23AB00  276;Over Flanders Fields;FreeTrack20;V160;V;Summelar ;2325;0114A59E68873E9B315210 +545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400  277;PanoPro;FreeTrack20;V160;;;20525;0115B6C61428231A23E900  278;Paraworld;FreeTrack20;V160;;;14501;0116656DD6832BB62EB000  279;Phoenix R/C;FreeTrack20;V160;;;3075;0117B6C61428238A334B00 @@ -355,7 +348,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  286;Project Torque (Invictus);FreeTrack20;V160;;;4802;011E612F28540B52797100  287;Project X;FreeTrack20;V160;;;20022;011FE9D85E4842DA439900  529;Puegeot PSA Simulator;FreeTrack20;V160;;;20840;021127A7344E7C044E9500 -545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400  553;QSTP;FreeTrack20;V160;;;20875;0229A3C108BE55FFF2BC00  288;Quanser;FreeTrack20;V160;;;20435;0120950F9A922FA535A500  289;QuantaDyn;FreeTrack20;V160;;;20575;012199BB5C9433A739B600 @@ -366,30 +358,31 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  293;R.U.D.O. Tools;FreeTrack20;V160;;;20039;0125612F287FB9BEA76E00  294;RACE (the WTCC game);FreeTrack20;V160;;;3904;01263C2C1C94FA86146300  295;RACE 07 RACE GTR 2;FreeTrack20;V160;V;zild1221 TrickyDee ;3903;0127C0AF9800870056FD00 +574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00 +312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300 +492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 +327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00 +329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 +330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 +331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400  296;RaceOn;FreeTrack20;V160;V;zild1221 ;0;0128621E7832AA82388200 +490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500  297;Racer;FreeTrack20;V160;;;2401;01296D2D103862E932EA00  298;Racer S;FreeTrack20;V160;;;20030;012AEA1CBED961CA52CB00 -490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500  299;Rail Simulator 1;FreeTrack20;V160;;;1550;012BB253778929A0395900 -300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100  301;RailWorks 2;FreeTrack20;V160;;;2750;012D3919C4972D9D299000  507;RailWorks 5 (TS2014);FreeTrack20;V160;;;1551;01FB8B5232CB1502C95A00 +300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100  302;Raydon Driving Simulator;FreeTrack20;V160;;;3701;012E5485D941DBE2FB5300 -574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00  304;Real Time Visual;FreeTrack20;V160;;;9901;0130B1C664862297365500  305;RealFlight;FreeTrack20;V160;;;4001;0131AC6E87892E993A8B00 -306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00  307;RealWorld;FreeTrack20;V160;;;20215;0133B59DEFA9322A727800 +306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00  308;Red Baron 3D;FreeTrack20;V160;;;1125;0134C6371D96349CEB7A00  309;Red Orchestra: Heroes of Stalingrad;FreeTrack20;V170;;;12602;013521F9121056CD997300  310;Red Orchestra: Ostfront;FreeTrack20;V170;;;12601;01369A9A2BE97252BB9000  311;Redline Monitor;FreeTrack20;V160;;;20210;01373752FBC8831A72AA00 -312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300  313;Remote Presence;FreeTrack20;V160;;;20710;01399BC3BDA93229D2BB00 -314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 -315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 -316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 -533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00  317;Richard Burns Rally;FreeTrack20;V160;V;zild1221;3401;013D42868B339A31A73C10  318;RidingStar;FreeTrack20;V160;;;1475;013E3919C497359826A700  544;Rift's Cave;FreeTrack20;V160;;;4050;02209C681EAD3B06D15A00 @@ -398,41 +391,40 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  321;Rise of Flight;FreeTrack20;V160;V;Seborgarsen ;11401;0141AA71218335A51F5100  322;Rise: The Vieneo Province;FreeTrack20;V160;;;6301;0142DEE3582F9837A82D00  323;Rising Conflicts;FreeTrack20;V160;;;12101;014384818335A439B12F00 -492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 +530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700  324;Road Legends;FreeTrack20;V160;;;1876;0144379716986369A2E600  325;Rogue Space;FreeTrack20;V160;;;3050;014588F5872C9C30ABE900  326;Rogue Warrior;FreeTrack20;V160;;;14202;0146432C2973D9D45A8E00 -530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700 -327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00  328;Rowan's Battle Of Britain;FreeTrack20;V160;;;1502;014821008829A72CB4F300 -329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 -330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 -331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400  540;Rust;FreeTrack20;V170;;;3950;0F6EF7CEF7DFA93405D700 +335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 +336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000 +338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 +343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200 +358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100 +495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00 +367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600 +371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000  511;Sail;FreeTrack20;V160;;;3575;01FF2916D764159099F800  332;Sail Simulator 5;FreeTrack20;V160;;;1975;014CE2D1D78A1D9A3B6300  333;Sailors of the Sky;FreeTrack20;V160;;;10201;014D17BE02961FAF3AB100  334;Santa Cruz Watermill;FreeTrack20;V160;;;20290;014E88F5881EA32FA7E900 -335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 -336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000  337;Seven-G;FreeTrack20;V160;;;2350;01510F00F49635B822A200 -338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 +554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00  339;Ship Simulator 2006;FreeTrack20;V160;;;5002;015329DFA9638AA2C66100  340;Ship Simulator 2008;FreeTrack20;V160;V;djj3ff ;5003;01545213599339B3D52100  341;Shiphandling Simulator;FreeTrack20;V160;;;20570;01553FD0FC9D8B37AD3700 -554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00  342;Shooting Simulator;FreeTrack20;V160;;;20047;0156F2F27A58827A63DA00 -343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200  344;Silent Wings;FreeTrack20;V160;;;8701;0158D615A9C96309C24A00  345;SilverHat;FreeTrack20;V160;;;12401;0159D8175F99349F3F9600 -346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 -347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 -348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00  518;SimCraft;FreeTrack20;V160;;;3650;02065BA013963203CB1900  349;SimCreator;FreeTrack20;V160;;;20520;015D3752FBC8935B001A00 -350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100  351;SimQuest immersion system;FreeTrack20;V160;;;20023;015F6C69678C32A30FAE00  352;SimSol;FreeTrack20;V160;;;20034;01602315187389E0FB5300 +346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 +347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 +348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00 +350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100  491;Simumak;FreeTrack20;V160;;;20770;01EB119629980784DCE600  510;Sir You Are Being Hunted;FreeTrack20;V160;;;3550;01FEDAB345FA104ED4A100  353;Sirocco Racing;FreeTrack20;V160;;;5801;01612BCA748925A6369A00 @@ -442,7 +434,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  356;Source Engine (Half-Life 2);FreeTrack20;V160;;;12502;0164E482F58829A739A600  357;Space Shuttle Mission 2007;FreeTrack20;V160;V;purewhitewings ;1225;0165662B03863D912F9700  517;Spaze;FreeTrack20;V160;;;3625;020573F9D3ED8C43B8DC00 -358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100  359;Stanford University;FreeTrack20;V160;;;20004;0167CE35BAF9933A62AA00  500;Star Citizen;FreeTrack20;V170;;;3450;0D7AF4CE4E343EC6B4A200  360;Starshatter;FreeTrack20;V160;;;6401;0168F079578A3F9A3BB600 @@ -452,38 +443,33 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  565;Steel Beasts Professional;FreeTrack20;V160;;;4350;02356C64A9AFBB37E56E00  364;Stoked Rider;FreeTrack20;V160;;;14701;016CC166C963EA32997300  365;Storm of War: the Battle of Britain;FreeTrack20;V170;;;11001;016D8F54A68B71F25D0200 -495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00  366;Stride;FreeTrack20;V170;;;2310;016EC784B21E4B21984400  541;Strike Suit Zero;FreeTrack20;V170;;;3975;0F87E77F3BD3DB8821A200 -367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600  368;Sunaerosys;FreeTrack20;V160;;;20475;01700449831AF28973EB00 -369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00  370;SuperX Research;FreeTrack20;V160;;;15401;0172BA89D078A45A021A00 -371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000 +369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00  372;Syncon Robot Control;FreeTrack20;V160;;;20415;0174C1BBF9937B12DB5200  373;Synergy Simulation;FreeTrack20;V160;;;20595;0175926ED9736B220B8200  374;T and TS Corp.;FreeTrack20;V160;;;20005;017617BE0297DDA73CA600 +379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700 +389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 +390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900 +399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00  539;Tacview;FreeTrack20;V160;;;20865;021B1F0CFB651B91405C00  375;Take On Helicopters;FreeTrack20;V170;;;7504;0177513CB40C0623B96A00  376;Target: Korea;FreeTrack20;V160;;;1201;0178F52E4221852FA43300  377;Target: Rabaul;FreeTrack20;V160;;;1202;0179E9D85E4881CA736900  378;Targeting Demo;FreeTrack20;V160;;;13002;017AAB1D58A952DAA2F900 -379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700  489;TeachLive;FreeTrack20;V160;;;20765;01E905245B5AC5484FC100  380;Telepresence;FreeTrack20;V160;;;20450;017CF478D278B33B02DA00  381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200  382;Test Drive Unlimited;FreeTrack20;V160;;;13201;017E6F2699559730A84000  509;Tetrahedral;FreeTrack20;V160;;;3525;01FDCFF1C56D6F757E8200 +576;The Battle of Sol;FreeTrack20;V160;;;4575;02408ED99EB5DF5D79A800  501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100  488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700  383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200 -384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 -385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 -386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800  387;ThriXXX Technology;FreeTrack20;V160;;;13402;0183F47CC378B35B526900 -388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 -389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 -390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900  391;ToCA Race Driver 2;FreeTrack20;V160;;;8102;0187FFE9E886F286297910  392;Toca Race Driver 3;FreeTrack20;V160;;;8101;01884098D36972B551A900  393;Tom Clancy's H.A.W.X.;FreeTrack20;V170;V;EmBeES ;1004;0189AA4D48E85966FBAA00 @@ -492,8 +478,6 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  396;Total War;FreeTrack20;V160;;;1375;018C72456F8529AA2CA400  397;Tower Crane Simulator;FreeTrack20;V160;;;20670;018D03FB9929B034A7D900  398;Tower I;FreeTrack20;V160;;;1325;018E662B03873CA731A400 -399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00 -400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00  401;TrackMapper2;FreeTrack20;V160;;;2175;0191CE35BAF9A31A61FA00  402;TrainMaster;FreeTrack20;V160;;;20042;01925C1FDE852D9925B400  403;Trainz;FreeTrack20;V160;;;4701;0193D1C9F2862C9630A100 @@ -501,6 +485,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  405;Turismo Carretera;FreeTrack20;V160;;;15801;01956F2699559740A73500  406;UK Rally Champion;FreeTrack20;V160;;;5701;019679EC0E28B196522A00  407;ULAN;FreeTrack20;V160;;;20645;01974ADE68E16780D97A00 +422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 +423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100  473;Underwater Navigation;FreeTrack20;V160;;;20715;01D9FE2B94FB03772DE200  408;Unity 3D Plugin;FreeTrack20;V160;;;20430;0198D24C3F9B3B9C31BF00  525;Unity 64-bit;FreeTrack20;V160;;;3750;020DC8AB18AF3539FA5200 @@ -518,17 +504,20 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  419;Untitled Simbin;FreeTrack20;V160;;;3902;01A36C69678E37AA27AD00  420;Untitled WorkShield;FreeTrack20;V160;;;4601;01A442868E38AB32BA3600  421;Untitled ZootFly;FreeTrack20;V160;;;12701;01A5348B1863AA527A6300 -422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 -423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100  424;VAR;FreeTrack20;V160;;;20460;01A8950F9A97FA96FD2E00  425;VBS2;FreeTrack20;V160;;;7501;01A999BB5C990099FCBF00  485;VBS2 2.0;FreeTrack20;V170;;;7505;1D51EB3616B3A44F05B900  527;VCORP RBR2 MOD;FreeTrack20;V160;;;3825;020FEE9EA847F2ADB45800 +429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300 +564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 +477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 +439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 +440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 +441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00  426;Vehicle Simulator (Quality Simulations);FreeTrack20;V160;;;5102;01AA0FC9FF9B1FA134A900  478;Vehicle Simulator Direction;FreeTrack20;V160;;;20735;01DEB88CF58E570F1CEF00  427;Vestibular Ocular Reflex;FreeTrack20;V160;;;20008;01AB3919C49B31A731A200  428;Viper Arena;FreeTrack20;V160;;;3501;01AC6F2699559934A53100 -429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300  430;Virtools Plugin;FreeTrack20;V160;;;20200;01AE03FB9B23AB43A42900  431;Virtual Driving;FreeTrack20;V160;;;20245;01AF99BB5C9927B83FB700  432;Virtual Heroes;FreeTrack20;V160;;;20375;01B0621E78732B732AE200 @@ -537,18 +526,14 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  435;Virtual Shopper;FreeTrack20;V160;;;20610;01B3B78B06EC9927B73E00  436;Virtual Supermarket;FreeTrack20;V160;;;20280;01B4849F9C39A931AD2800  496;VirtualiTeach;FreeTrack20;V160;;;20790;01F062AE1CAB33B52D0700 -480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300  437;VizRD;FreeTrack20;V160;;;20031;01B55485D9825BF1D8AB00 +480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300  438;Void War;FreeTrack20;V160;;;10001;01B65C1FDE872AA1206600 -564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 -477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 -439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 -440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 -441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00 +445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00 +453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100  442;Walkabout3d;FreeTrack20;V160;;;20125;01BA2822901E9E39932F00  443;Wallbusters;FreeTrack20;V160;;;1450;01BB88F58C1EA127A83F00  444;War Thunder;FreeTrack20;V160;;;0;01BC17BE029A1FB8ED9600 -445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00  446;Welding Simulator;FreeTrack20;V160;;;2625;01BE348B188319D229B300  447;West Racing;FreeTrack20;V160;;;1801;01BF91D999022A33B62000  448;Whirlwind of Vietnam;FreeTrack20;V160;;;11101;01C0054E9935A03AAF3200 @@ -557,9 +542,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  451;Wings of War;FreeTrack20;V160;;;7807;01C34B0FC38B36B42FB610  512;Wings: Over Flanders Fields;FreeTrack20;V160;;;2326;02008AE39AAA4624B33C00  570;Wingsuit Simulator;FreeTrack20;V160;;;4450;023A472FA37FCD7427D900 -543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300  452;World Racing 2;FreeTrack20;V160;;;7201;01C41AAF68A2BA836AAE00 -453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100 +543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300  454;X Motor Racing;FreeTrack20;V160;;;1150;01C669259690E98629A900  526;X-Camera;FreeTrack20;V160;;;3775;020E1C4055DE39CBC03D00  458;X-Cockpit for X-Plane;FreeTrack20;V160;;;2901;01CA1C76F8BF4852999300 @@ -571,6 +555,24 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID  456;X2: The Threat;FreeTrack20;V160;;;5501;01C81039EF980EC8D30900  457;X3: Albion Prelude and Reunion;FreeTrack20;V170;V;V4Friend;5502;01C97E101A708F8524E300  463;Xyphoid;FreeTrack20;V160;;;14301;01CF656DD68B43B435A800 -464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00  493;ZKT;FreeTrack20;V160;;;20780;01ED2BAA723F3C097EE800  465;Zombie AA Research;FreeTrack20;V160;;;14201;01D1AA71218B3B9F1C9A00 +100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 +113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00 +502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00 +523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 +179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 +192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 +180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700 +209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900 +252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800 +533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00 +314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 +315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 +316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 +384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 +385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 +386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800 +388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 +400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00 +464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00 diff --git a/spline-widget/CMakeLists.txt b/spline-widget/CMakeLists.txt index 03706d91..651a7874 100644 --- a/spline-widget/CMakeLists.txt +++ b/spline-widget/CMakeLists.txt @@ -1 +1,2 @@ -opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-spline-widget NO-LINKER-SCRIPT NO-COMPAT LINKAGE) +target_link_libraries(opentrack-spline-widget opentrack-compat) diff --git a/spline-widget/functionconfig.cpp b/spline-widget/functionconfig.cpp index dcc9ca65..777b4f6f 100644 --- a/spline-widget/functionconfig.cpp +++ b/spline-widget/functionconfig.cpp @@ -62,7 +62,7 @@ float Map::getValueInternal(int x) {      return ret * sign;  } -static QPointF ensureInBounds(QList<QPointF> points, int i) { +static QPointF ensureInBounds(const QList<QPointF>& points, int i) {      int siz = points.size();      if (siz == 0 || i < 0)          return QPointF(0, 0); @@ -219,7 +219,11 @@ void Map::loadSettings(QSettings& settings, const QString& title) {  void Map::saveSettings(QSettings& settings, const QString& title) {      QMutexLocker foo(&_mutex);      settings.beginGroup(QString("Curves-%1").arg(title)); -    int max = cur.input.size(); + +    if (cur.input.size() == 0) +        cur.input.push_back(QPointF(max_x, max_y)); + +    const int max = cur.input.size();      settings.setValue("point-count", max);      for (int i = 0; i < max; i++) { diff --git a/spline-widget/functionconfig.h b/spline-widget/functionconfig.h index 3d2fc23c..145ee14e 100644 --- a/spline-widget/functionconfig.h +++ b/spline-widget/functionconfig.h @@ -18,7 +18,7 @@  #include <limits>  #include "opentrack-compat/qcopyable-mutex.hpp" -#ifdef BUILD_opentrack_spline_widget +#ifdef BUILD_spline_widget  #   define SPLINE_WIDGET_EXPORT Q_DECL_EXPORT  #else  #   define SPLINE_WIDGET_EXPORT Q_DECL_IMPORT @@ -30,7 +30,7 @@ private:      struct State {          QList<QPointF> input; -        std::vector<float> data;         +        std::vector<float> data;      };      int precision() const; @@ -52,6 +52,8 @@ public:      {          setMaxInput(maxx);          setMaxOutput(maxy); +        if (cur.input.size() == 0) +            cur.input.push_back(QPointF(maxx, maxy));          reload();      } diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp index 7ab1e360..256bf45e 100644 --- a/spline-widget/qfunctionconfigurator.cpp +++ b/spline-widget/qfunctionconfigurator.cpp @@ -5,7 +5,7 @@   * copyright notice and this permission notice appear in all copies.   */ -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  #include "spline-widget/qfunctionconfigurator.h"  #include <QPainter> @@ -15,13 +15,13 @@ using namespace options;  #include <cmath>  #include <algorithm> -static const int pointSize = 5; -  QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) :      QWidget(parent),      _config(nullptr),      moving_control_point_idx(-1), -    _draw_function(true) +    _draw_function(true), +    snap_x(0), +    snap_y(0)  {      update_range();      setMouseTracking(true); @@ -358,7 +358,7 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)          }          if (is_on_point) { -            setCursor(Qt::OpenHandCursor); +            setCursor(Qt::CrossCursor);          }          else {              setCursor(Qt::ArrowCursor); @@ -402,9 +402,8 @@ void QFunctionConfigurator::update_range()  bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel)  { -    QPointF pixel2 = point_to_pixel(pt); -    return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize && -           pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize; +    QPointF tmp = pixel - point_to_pixel(pt); +    return sqrt(QPointF::dotProduct(tmp, tmp)) < pointSize;  }  QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point) @@ -412,8 +411,13 @@ QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point)      if (!_config)          return QPointF(-1, -1); -    double x = (point.x() - pixel_bounds.x()) / c.x(); -    double y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); +    int x = (point.x() - pixel_bounds.x()) / c.x(); +    int y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); +     +    if (snap_x > 0) +        x -= x % snap_x; +    if (snap_y > 0) +        y -= y % snap_y;      if (x < 0)          x = 0; diff --git a/spline-widget/qfunctionconfigurator.h b/spline-widget/qfunctionconfigurator.h index 4a9cb5f1..ce8208a8 100644 --- a/spline-widget/qfunctionconfigurator.h +++ b/spline-widget/qfunctionconfigurator.h @@ -19,6 +19,7 @@ class SPLINE_WIDGET_EXPORT QFunctionConfigurator : public QWidget  {      Q_OBJECT      Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier) +    enum { pointSize = 5 };  public:      QFunctionConfigurator(QWidget *parent = 0); @@ -39,6 +40,8 @@ public:          _background = QPixmap();          update();      } +    void set_snap(int x, int y) { snap_x = x; snap_y = y; } +    void get_snap(int& x, int& y) const { x = snap_x; y = snap_y; }  protected slots:      void paintEvent(QPaintEvent *e) override;      void mousePressEvent(QMouseEvent *e) override; @@ -72,4 +75,5 @@ private:      QPixmap _background;      QPixmap _function;      bool _draw_function; +    int snap_x, snap_y;  }; diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp index 570c2e0d..316c7e13 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.cpp +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -16,7 +16,7 @@  #include <opencv2/core/core.hpp>  #include <opencv2/highgui/highgui.hpp>  #include <opencv2/videoio.hpp> -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp"  #include "opentrack-compat/sleep.hpp"  typedef struct { @@ -43,6 +43,8 @@ Tracker::~Tracker()          delete videoWidget;      if(layout)          delete layout; +    // fast start/stop causes breakage +    portable::sleep(1000);      camera.release();  } @@ -121,20 +123,17 @@ void Tracker::run()      aruco::MarkerDetector detector;      detector.setDesiredSpeed(3); +    detector._thresMethod = aruco::MarkerDetector::FIXED_THRES;      cv::Rect last_roi(65535, 65535, 0, 0); +    // XXX change to timer.hpp      auto freq = cv::getTickFrequency();      auto last_time = cv::getTickCount();      double cur_fps = 0; -    std::vector<int> box_sizes { 5, 7, 9, 11 }; -    int box_idx = 0; -    double failed = 0; -    const double max_failed = 1.25;      cv::Vec3d rvec, tvec;      cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1);      cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); -    bool otsu = false;      while (!stop)      { @@ -145,12 +144,12 @@ void Tracker::run()              if (!camera.read(color))                  continue;          } -        static constexpr int thres_param2 = 5;          cv::Mat grayscale;          cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY);          const int scale = grayscale.cols > 480 ? 2 : 1; -        detector.setThresholdParams(box_sizes[box_idx], thres_param2); +        // param 2 ignored for Otsu thresholding. it's required to use our fork of Aruco. +        detector.setThresholdParams(5, -1);          static constexpr double pi = 3.1415926f;          const int w = grayscale.cols, h = grayscale.rows; @@ -180,7 +179,6 @@ void Tracker::run()          if (last_roi.width > 0 && last_roi.height)          { -            detector.setThresholdParams(box_sizes[box_idx], thres_param2);              detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width),                                     std::min(1.0, size_max * grayscale.cols / last_roi.width)); @@ -188,7 +186,6 @@ void Tracker::run()              if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false),                  markers.size() == 1 && markers[0].size() == 4)              { -                failed = std::max(0., failed - dt);                  auto& m = markers.at(0);                  for (int i = 0; i < 4; i++)                  { @@ -202,17 +199,6 @@ void Tracker::run()          if (!roi_valid)          { -            otsu = !otsu; -            detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; -            failed += dt; -            if (failed > max_failed) -            { -                box_idx++; -                box_idx %= box_sizes.size(); -                qDebug() << "aruco: box size now" << box_sizes[box_idx]; -                failed = 0; -            } -            detector.setThresholdParams(box_sizes[box_idx], thres_param2);              detector.setMinMaxSize(size_min, size_max);              detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false);          } diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h index f827da77..b9503c6e 100644 --- a/tracker-aruco/ftnoir_tracker_aruco.h +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -15,7 +15,7 @@  #include <QHBoxLayout>  #include <QDialog>  #include <QTimer> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "trans_calib.h"  #include "opentrack/plugin-api.hpp"  #include "opentrack/opencv-camera-dialog.hpp" @@ -48,7 +48,7 @@ class Tracker : protected QThread, public ITracker  {      Q_OBJECT      friend class TrackerControls; -    static constexpr double c_search_window = 2.65; +    static constexpr double c_search_window = 1.3;  public:      Tracker();      ~Tracker() override; diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h index 7cff2ec9..9d18c7d1 100644 --- a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h @@ -10,7 +10,7 @@  #include <QThread>  #include "ui_freepie-udp-controls.h"  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/tracker-hatire/ftnoir_tracker_hat_dialog.h b/tracker-hatire/ftnoir_tracker_hat_dialog.h index ebaffc6d..bd225b3e 100644 --- a/tracker-hatire/ftnoir_tracker_hat_dialog.h +++ b/tracker-hatire/ftnoir_tracker_hat_dialog.h @@ -29,8 +29,8 @@ public:      ~TrackerControls() override;  #ifdef OPENTRACK_API      void Initialize(QWidget *parent) ; // unused -    void register_tracker(ITracker *tracker); -    void unregister_tracker(); +    void register_tracker(ITracker *tracker) override; +    void unregister_tracker() override;  #else      void Initialize(QWidget *parent) ;      void registerTracker(ITracker *tracker) ; diff --git a/tracker-hatire/ftnoir_tracker_hat_settings.cpp b/tracker-hatire/ftnoir_tracker_hat_settings.cpp index e6b32047..df0480a1 100644 --- a/tracker-hatire/ftnoir_tracker_hat_settings.cpp +++ b/tracker-hatire/ftnoir_tracker_hat_settings.cpp @@ -14,7 +14,7 @@  #include "ftnoir_tracker_hat_settings.h"  #ifdef OPENTRACK_API -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #endif  void TrackerSettings::load_ini() diff --git a/tracker-ht/CMakeLists.txt b/tracker-ht/CMakeLists.txt index 248a113e..cbbda108 100644 --- a/tracker-ht/CMakeLists.txt +++ b/tracker-ht/CMakeLists.txt @@ -1,3 +1,4 @@ +if(FALSE)  set(SDK_HT "" CACHE FILEPATH "Path to headtracker library")  set(SDK_HT_FLANDMARK "" CACHE FILEPATH "Path to flandmark library for headtracker")  find_package(OpenCV 3.0 QUIET) @@ -9,3 +10,4 @@ if(OpenCV_FOUND)          target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})      endif()  endif() +endif() diff --git a/tracker-ht/ftnoir_tracker_ht.h b/tracker-ht/ftnoir_tracker_ht.h index 1e364456..0563fe1c 100644 --- a/tracker-ht/ftnoir_tracker_ht.h +++ b/tracker-ht/ftnoir_tracker_ht.h @@ -12,7 +12,7 @@  #include "ht_video_widget.h"  #include "opentrack-compat/shm.h"  #include <QObject> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  #include "opentrack/plugin-api.hpp"  #include "opentrack/opencv-camera-dialog.hpp" diff --git a/tracker-hydra/ftnoir_tracker_hydra.h b/tracker-hydra/ftnoir_tracker_hydra.h index 47a1eb9a..94396b7c 100644 --- a/tracker-hydra/ftnoir_tracker_hydra.h +++ b/tracker-hydra/ftnoir_tracker_hydra.h @@ -1,6 +1,6 @@  #include "ui_ftnoir_hydra_clientcontrols.h"  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 77fd7241..d10b15ca 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -8,220 +8,29 @@  #include "opentrack/plugin-api.hpp"  #include <QMutexLocker> -FTNoIR_Tracker::FTNoIR_Tracker() : -    g_pDI(nullptr), -    g_pJoystick(nullptr), -    mtx(QMutex::Recursive), -    iter(-1) +FTNoIR_Tracker::FTNoIR_Tracker()  { -} - -void FTNoIR_Tracker::reload() -{ -    s.b->reload(); -    QMutexLocker foo(&mtx); -    if (g_pJoystick) +    if (static_cast<QString>(s.guid) == "")      { -        g_pJoystick->Unacquire(); -        g_pJoystick->Release(); +        std::vector<win32_joy_ctx::joy_info> info = joy_ctx.get_joy_info(); +        if (info.size()) +        { +            s.guid = info[0].guid; +            s.b->save(); +        }      } -    if (g_pDI) -        g_pDI->Release(); - -    g_pJoystick = nullptr; -    g_pDI = nullptr; - -    start_tracker(frame);  }  FTNoIR_Tracker::~FTNoIR_Tracker()  { -    if (g_pJoystick) -    { -        g_pJoystick->Unacquire(); -        g_pJoystick->Release(); -    } -    if (g_pDI) -    { -        g_pDI->Release(); -    }  } -#ifdef __GNUC__ -#	pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, -                                   VOID* pContext ) +void FTNoIR_Tracker::start_tracker(QFrame*)  { -    auto self = (FTNoIR_Tracker*) pContext; - -    if( pdidoi->dwType & DIDFT_AXIS ) -    { -        DIPROPRANGE diprg = {0}; -        diprg.diph.dwSize = sizeof( DIPROPRANGE ); -        diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); -        diprg.diph.dwHow = DIPH_BYID; -        diprg.diph.dwObj = pdidoi->dwType; -        diprg.lMax = FTNoIR_Tracker::AXIS_MAX; -        diprg.lMin = -FTNoIR_Tracker::AXIS_MAX; - -        if( FAILED( self->g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) -            return DIENUM_STOP; - -        self->iter++; -    } - -    return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE; -} - -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ -    auto self = reinterpret_cast<FTNoIR_Tracker*>(pContext); -    bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid; - -    if (stop) -    { -        if (self->guid_to_check.size()) -        { -            QString guid = guid_to_string(pdidInstance->guidInstance); -            if (guid != self->guid_to_check) -            { -                return DIENUM_CONTINUE; -            } -            else -                qDebug() << "guid ok" << self->guid_to_check; -        } - -        (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL); -        qDebug() << "device" << static_cast<QString>(self->s.joyid); -    } - -    return stop ? DIENUM_STOP : DIENUM_CONTINUE; -} - -void FTNoIR_Tracker::start_tracker(QFrame* frame) -{ -    QMutexLocker foo(&mtx); -    this->frame = frame; -    iter = 0; -    auto hr = CoInitialize( nullptr ); - -    if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, -                                         IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) -    { -        qDebug() << "create"; -        goto fail; -    } - -    guid_to_check = s.guid; - -    if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, -                                         EnumJoysticksCallback, -                                         this, -                                         DIEDFL_ATTACHEDONLY))) -    { -        qDebug() << "enum1"; -        goto fail; -    } - -    if (!g_pJoystick && guid_to_check.size()) -    { -        guid_to_check = ""; - -        if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, -                                             EnumJoysticksCallback, -                                             this, -                                             DIEDFL_ATTACHEDONLY))) -        { -            qDebug() << "enum2"; -            goto fail; -        } -    } - -    if (!g_pJoystick) -    { -        qDebug() << "ENODEV"; -        goto fail; -    } - -    if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick))) -    { -        qDebug() << "format"; -        goto fail; -    } - -    if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) -    { -        qDebug() << "coop"; -        goto fail; -    } - -    iter = 0; - -    if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback, -                                               ( VOID* )this, DIDFT_ALL ))) -    { -        qDebug() << "enum axes"; -        goto fail; -    } - -    return; - -fail: -    if (g_pJoystick) -        g_pJoystick->Release(); -    if (g_pDI) -        g_pDI->Release(); -    g_pJoystick = nullptr; -    g_pDI = nullptr; - -    qDebug() << "joy init failure";  }  void FTNoIR_Tracker::data(double *data)  { -    QMutexLocker foo(&mtx); -    DIJOYSTATE js = {0}; - -    if( !g_pDI || !g_pJoystick) -        return; - -    bool ok = false; - -    for (int i = 0; i < 100; i++) -    { -        if (!FAILED(g_pJoystick->Poll())) -        { -                ok = true; -                break; -        } -        if (g_pJoystick->Acquire() != DI_OK) -                continue; -        else -                ok = true; -        break; -    } - -    if (!ok) -            return; - -    HRESULT hr = 0; - -    if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) ) -        return; - -    const LONG values[] = { -        js.lX, -        js.lY, -        js.lZ, -        js.lRx, -        js.lRy, -        js.lRz, -        js.rglSlider[0], -        js.rglSlider[1] -    }; -      int map[6] = {          s.joy_1 - 1,          s.joy_2 - 1, @@ -239,14 +48,21 @@ void FTNoIR_Tracker::data(double *data)          180,          180      }; - -    for (int i = 0; i < 6; i++) +     +    const QString guid = s.guid; +    int axes[8]; +    const bool ret = joy_ctx.poll_axis(guid, axes); +     +    if (ret)      { -        int k = map[i] - 1; -        if (k < 0 || k >= 8) -            data[i] = 0; -        else -            data[i] = values[k] * limits[i] / AXIS_MAX; +        for (int i = 0; i < 6; i++) +        { +            int k = map[i] - 1; +            if (k < 0 || k >= 8) +                data[i] = 0; +            else +                data[i] = axes[k] * limits[i] / AXIS_MAX; +        }      }  } diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 75305f07..1f940b63 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -12,30 +12,20 @@  #include <QMessageBox>  #include <QSettings>  #include <QList> -#include <QMutex>  #include <QFrame>  #include <QStringList>  #include <cmath>  #include "opentrack/plugin-api.hpp" -#ifndef DIRECTINPUT_VERSION -#   define DIRECTINPUT_VERSION 0x800 -#endif -#include <windows.h> -#include <commctrl.h> -#include <basetsd.h> -#include <dinput.h> -#include <oleauto.h> -#include <shellapi.h> -#include "opentrack/options.hpp" +#include "opentrack/win32-joystick.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { -    value<QString> joyid, guid; +    value<QString> guid;      value<int> joy_1, joy_2, joy_3, joy_4, joy_5, joy_6;      settings() :          opts("tracker-joystick"), -        joyid(b, "joy-id", ""),          guid(b, "joy-guid", ""),          joy_1(b, "axis-map-1", 1),          joy_2(b, "axis-map-2", 2), @@ -46,35 +36,17 @@ struct settings : opts {      {}  }; -template<typename = void> -QString guid_to_string(const GUID guid) -{ -    char buf[40] = {0}; -    wchar_t szGuidW[40] = {0}; - -    StringFromGUID2(guid, szGuidW, 40); -    WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - -    return QString(buf); -} -  class FTNoIR_Tracker : public ITracker  {  public:      FTNoIR_Tracker();      ~FTNoIR_Tracker(); -    void start_tracker(QFrame *frame); +    void start_tracker(QFrame *);      void data(double *data); -    void reload(); -    LPDIRECTINPUT8          g_pDI; -    LPDIRECTINPUTDEVICE8    g_pJoystick; -    QMutex mtx; -    QFrame* frame; -    DIDEVICEINSTANCE def; -    int iter; // XXX bad style      settings s; -    QString guid_to_check; -    static constexpr int AXIS_MAX = 65535; +    QString guid; +    static constexpr int AXIS_MAX = win32_joy_ctx::joy_axis_size - 1; +    win32_joy_ctx joy_ctx;  };  class TrackerControls: public ITrackerDialog diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 0463933f..a6fa6605 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -1,19 +1,6 @@  #include "ftnoir_tracker_joystick.h"  #include "opentrack/plugin-api.hpp" -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ -    auto self = ( TrackerControls* )pContext; -    auto name = QString(pdidInstance->tszInstanceName); -    auto guid = guid_to_string(pdidInstance->guidInstance); -    TrackerControls::joys cur { name, guid }; -    self->_joys.append(cur); - -    self->ui.joylist->addItem(name + " " + guid); - -    return DIENUM_CONTINUE; -} -  TrackerControls::TrackerControls() : tracker(nullptr)  {      ui.setupUi( this ); @@ -23,22 +10,25 @@ TrackerControls::TrackerControls() : tracker(nullptr)      connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));      { -        auto hr = CoInitialize( nullptr ); -        LPDIRECTINPUT8 g_pDI = nullptr; - -        if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, -                                             IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) -            goto fin; - -        if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, -                                             EnumJoysticksCallback, -                                             this, -                                             DIEDFL_ATTACHEDONLY ))) -            goto fin; - -fin: -        if (g_pDI) -            g_pDI->Release(); +        win32_joy_ctx joy_ctx; +         +        _joys = QList<joys>(); +         +        for (auto j : joy_ctx.get_joy_info()) +            _joys.push_back(joys { j.name, j.guid }); +    } +     +    { +        const QString guid = s.guid; +        int idx = 0; +        for (int i = 0; i < _joys.size(); i++) +        { +            const joys& j = _joys[i]; +            if (j.guid == guid) +                idx = i; +            ui.joylist->addItem(j.name + " " + j.guid); +        } +        ui.joylist->setCurrentIndex(idx);      }      tie_setting(s.joy_1, ui.joy_1); @@ -54,10 +44,7 @@ void TrackerControls::doOK() {      joys def { "", "" };      auto val = _joys.value(idx, def);      s.guid = val.guid; -    s.joyid = val.name;      s.b->save(); -    if (tracker) -        tracker->reload();      this->close();  } @@ -65,5 +52,3 @@ void TrackerControls::doCancel() {      s.b->reload();      this->close();  } - - diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp index 63b401a8..600ab26a 100644 --- a/tracker-pt/camera.cpp +++ b/tracker-pt/camera.cpp @@ -110,16 +110,14 @@ bool CVCamera::_get_frame(cv::Mat* frame)  {      if (cap && cap->isOpened())      { -        cv::Mat img; -        for (int i = 0; i < 100 && !cap->read(img); i++) +        for (int i = 0; i < 100 && !cap->read(*frame); i++)              ;; -        if (img.empty()) +        if (frame->empty())              return false; -        *frame = img; -        cam_info.res_x = img.cols; -        cam_info.res_y = img.rows; +        cam_info.res_x = frame->cols; +        cam_info.res_y = frame->rows;          return true;      }      return false; diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp index 956f639e..a85e3bc0 100644 --- a/tracker-pt/ftnoir_tracker_pt.cpp +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -12,14 +12,15 @@  #include <QDebug>  #include <QFile>  #include <QCoreApplication> -#include "opentrack/camera-names.hpp" +#include "opentrack-compat/camera-names.hpp" +#include "opentrack-compat/sleep.hpp" +#include <functional>  //#define PT_PERF_LOG	//log performance  //-----------------------------------------------------------------------------  Tracker_PT::Tracker_PT() -    : mutex(QMutex::Recursive), -      commands(0), +    : commands(0),        video_widget(NULL),        video_frame(NULL),        ever_success(false) @@ -34,6 +35,8 @@ Tracker_PT::~Tracker_PT()      delete video_widget;      video_widget = NULL;      if (video_frame->layout()) delete video_frame->layout(); +    // fast start/stop causes breakage +    portable::sleep(1000);      camera.stop();  } @@ -88,44 +91,40 @@ void Tracker_PT::run()  #endif      apply_settings(); +    cv::Mat frame_;      while((commands & ABORT) == 0)      {          const double dt = time.elapsed() * 1e-9;          time.start(); -        cv::Mat frame;          bool new_frame;          {              QMutexLocker l(&camera_mtx);              new_frame = camera.get_frame(dt, &frame); +            if (frame.rows != frame_.rows || frame.cols != frame_.cols) +                frame_ = cv::Mat(frame.rows, frame.cols, CV_8UC3); +            frame.copyTo(frame_);          } -        if (new_frame && !frame.empty()) +        if (new_frame && !frame_.empty())          { -            QMutexLocker lock(&mutex); - -            std::vector<cv::Vec2f> points = point_extractor.extract_points(frame); - -            // blobs are sorted in order of circularity -            if (points.size() > PointModel::N_POINTS) -                points.resize(PointModel::N_POINTS); - -            bool success = points.size() == PointModel::N_POINTS; +            const auto& points = point_extractor.extract_points(frame_);              float fx;              if (!get_focal_length(fx))                  continue; +             +            const bool success = points.size() >= PointModel::N_POINTS;              if (success)              {                  point_tracker.track(points, PointModel(s), fx, s.dynamic_pose, s.init_phase_timeout); +                ever_success = true;              }              Affine X_CM = pose(); -            ever_success |= success; -              {                  Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below                  if (X_MH.t[0] == 0 && X_MH.t[1] == 0 && X_MH.t[2] == 0) @@ -142,38 +141,39 @@ void Tracker_PT::run()                      case 2: X_MH.t[0] = -135; X_MH.t[1] = 0; X_MH.t[2] = 0; break;                      }                  } -                Affine X_GH = X_CM * X_MH; -                cv::Vec3f p = X_GH.t; // head (center?) position in global space -                cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx);  // projected to screen -                points.push_back(p_);              } -            for (unsigned i = 0; i < points.size(); i++) +             +            std::function<void(const cv::Vec2f&, const cv::Scalar)> fun = [&](const cv::Vec2f& p, const cv::Scalar color)              { -                auto& p = points[i]; -                auto p2 = cv::Point(p[0] * frame.cols + frame.cols/2, -p[1] * frame.cols + frame.rows/2); -                cv::Scalar color(0, 255, 0); -                if (i == points.size()-1) -                    color = cv::Scalar(0, 0, 255); -                cv::line(frame, +                auto p2 = cv::Point(p[0] * frame_.cols + frame_.cols/2, -p[1] * frame_.cols + frame_.rows/2); +                cv::line(frame_,                           cv::Point(p2.x - 20, p2.y),                           cv::Point(p2.x + 20, p2.y),                           color,                           4); -                cv::line(frame, +                cv::line(frame_,                           cv::Point(p2.x, p2.y - 20),                           cv::Point(p2.x, p2.y + 20),                           color, -                         4); +                         4);                 +            }; + +            for (unsigned i = 0; i < points.size(); i++) +            { +                fun(points[i], cv::Scalar(0, 255, 0)); +            } +             +            { +                Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below +                Affine X_GH = X_CM * X_MH; +                cv::Vec3f p = X_GH.t; // head (center?) position in global space +                cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx);  // projected to screen +                fun(p_, cv::Scalar(0, 0, 255));              } -            video_widget->update_image(frame); +            video_widget->update_image(frame_);          } -#ifdef PT_PERF_LOG -        log_stream<<"dt: "<<dt; -        if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps; -        log_stream<<"\n"; -#endif      }      qDebug()<<"Tracker:: Thread stopping";  } @@ -213,6 +213,7 @@ void Tracker_PT::apply_settings()      camera.set_fps(cam_fps);      qDebug() << "camera start";      camera.start(); +    frame = cv::Mat();      qDebug()<<"Tracker::apply ends";  } diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h index f73d106b..dff0c30a 100644 --- a/tracker-pt/ftnoir_tracker_pt.h +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -40,15 +40,14 @@ public:      void start_tracker(QFrame* parent_window) override;      void data(double* data) override; -    Affine pose() { QMutexLocker lock(&mutex); return point_tracker.pose(); } -    int  get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } +    Affine pose() { return point_tracker.pose(); } +    int  get_n_points() { return point_extractor.get_points().size(); }      bool get_cam_info(CamInfo* info) { QMutexLocker lock(&camera_mtx); return camera.get_info(*info); }  public slots:      void apply_settings();  protected:      void run() override;  private: -    QMutex mutex;      // thread commands      enum Command {          ABORT = 1<<0 @@ -70,6 +69,7 @@ private:      settings_pt s;      Timer time; +    cv::Mat frame;      volatile bool ever_success; diff --git a/tracker-pt/ftnoir_tracker_pt_settings.h b/tracker-pt/ftnoir_tracker_pt_settings.h index 78626468..85f068fe 100644 --- a/tracker-pt/ftnoir_tracker_pt_settings.h +++ b/tracker-pt/ftnoir_tracker_pt_settings.h @@ -9,7 +9,7 @@  #ifndef FTNOIR_TRACKER_PT_SETTINGS_H  #define FTNOIR_TRACKER_PT_SETTINGS_H -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings_pt : opts diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp index ec37dd00..0208b11d 100644 --- a/tracker-pt/point_extractor.cpp +++ b/tracker-pt/point_extractor.cpp @@ -13,20 +13,22 @@  #   include "opentrack-compat/timer.hpp"  #endif -PointExtractor::PointExtractor(){ -	//if (!AllocConsole()){} -	//else SetConsoleTitle("debug"); -	//freopen("CON", "w", stdout); -	//freopen("CON", "w", stderr); +PointExtractor::PointExtractor() +{  } -// ---------------------------------------------------------------------------- -std::vector<cv::Vec2f> PointExtractor::extract_points(cv::Mat& frame) + +const std::vector<cv::Vec2f>& PointExtractor::extract_points(cv::Mat& frame)  {      const int W = frame.cols;      const int H = frame.rows; +     +    if (frame_gray.rows != frame.rows || frame_gray.cols != frame.cols) +    { +        frame_gray = cv::Mat(frame.rows, frame.cols, CV_8U); +        frame_bin = cv::Mat(frame.rows, frame.cols, CV_8U);; +    }      // convert to grayscale -    cv::Mat frame_gray;      cv::cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY);      const double region_size_min = s.min_point_size; @@ -51,7 +53,6 @@ std::vector<cv::Vec2f> PointExtractor::extract_points(cv::Mat& frame)      };      // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) -    cv::Mat frame_bin = cv::Mat::zeros(H, W, CV_8U);      std::vector<blob> blobs;      std::vector<std::vector<cv::Point>> contours; @@ -59,42 +60,39 @@ std::vector<cv::Vec2f> PointExtractor::extract_points(cv::Mat& frame)      const int thres = s.threshold;      if (!s.auto_threshold)      { -        cv::Mat frame_bin_; -        cv::threshold(frame_gray, frame_bin_, thres, 255, cv::THRESH_BINARY); -        frame_bin.setTo(170, frame_bin_); -        cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); +        cv::threshold(frame_gray, frame_bin, thres, 255, cv::THRESH_BINARY); +        cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);      }      else      { -        cv::Mat hist;          cv::calcHist(std::vector<cv::Mat> { frame_gray },                       std::vector<int> { 0 },                       cv::Mat(),                       hist, -                     std::vector<int> { 256 }, -                     std::vector<float> { 0, 256 }, +                     std::vector<int> { 256/hist_c }, +                     std::vector<float> { 0, 256/hist_c },                       false); -        const int sz = hist.rows*hist.cols; +        const int sz = hist.cols * hist.rows;          int val = 0;          int cnt = 0;          constexpr int min_pixels = 250;          const auto pixels_to_include = std::max<int>(0, min_pixels * s.threshold/100.); +        auto ptr = reinterpret_cast<const float*>(hist.ptr(0));          for (int i = sz-1; i >= 0; i--)          { -            cnt += hist.at<float>(i); +            cnt += ptr[i];              if (cnt >= pixels_to_include)              {                  val = i;                  break;              }          } +        val *= hist_c;          val *= 240./256.;          //qDebug() << "val" << val; -        cv::Mat frame_bin_; -        cv::threshold(frame_gray, frame_bin_, val, 255, CV_THRESH_BINARY); -        frame_bin.setTo(170, frame_bin_); -        cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); +        cv::threshold(frame_gray, frame_bin, val, 255, CV_THRESH_BINARY); +        cv::findContours(frame_bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);      }      int cnt = 0; @@ -150,31 +148,27 @@ std::vector<cv::Vec2f> PointExtractor::extract_points(cv::Mat& frame)          }          blobs.push_back(blob(radius, pos, confid, area)); +         +        enum { max_blobs = 16 }; +         +        if (blobs.size() == max_blobs) +            break;      } -    // clear old points -	points.clear(); -      using b = const blob;      std::sort(blobs.begin(), blobs.end(), [](b& b1, b& b2) {return b1.confid > b2.confid;}); +    points.reserve(blobs.size()); +     +    QMutexLocker l(&mtx); +     +    points.clear(); +          for (auto& b : blobs)      {          cv::Vec2f p((b.pos[0] - W/2)/W, -(b.pos[1] - H/2)/W);          points.push_back(p);      } -    // draw output image -    std::vector<cv::Mat> channels_; -    cv::split(frame, channels_); -    std::vector<cv::Mat> channels; -    { -        cv::Mat frame_bin__ = frame_bin * .5; -        channels.push_back(channels_[0] + frame_bin__); -        channels.push_back(channels_[1] - frame_bin__); -        channels.push_back(channels_[2] - frame_bin__); -        cv::merge(channels, frame); -    } -      return points;  } diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h index b9368ab6..030251ff 100644 --- a/tracker-pt/point_extractor.h +++ b/tracker-pt/point_extractor.h @@ -13,21 +13,26 @@  #include "ftnoir_tracker_pt_settings.h" -// ---------------------------------------------------------------------------- -// Extracts points from an opencv image +#include <QMutex> +  class PointExtractor  {  public:      // extracts points from frame and draws some processing info into frame, if draw_output is set      // dt: time since last call in seconds      // WARNING: returned reference is valid as long as object -    std::vector<cv::Vec2f> extract_points(cv::Mat &frame); -    const std::vector<cv::Vec2f>& get_points() { return points; } +    const std::vector<cv::Vec2f> &extract_points(cv::Mat &frame); +    const std::vector<cv::Vec2f>& get_points() { QMutexLocker l(&mtx); return points; }      PointExtractor();      settings_pt s;  private: +    enum { hist_c = 2 };      std::vector<cv::Vec2f> points; +    QMutex mtx; +    cv::Mat frame_gray; +    cv::Mat frame_bin; +    cv::Mat hist;  };  #endif //POINTEXTRACTOR_H diff --git a/tracker-pt/point_tracker.cpp b/tracker-pt/point_tracker.cpp index 924b75de..aa6feb5b 100644 --- a/tracker-pt/point_tracker.cpp +++ b/tracker-pt/point_tracker.cpp @@ -249,6 +249,7 @@ int PointTracker::POSIT(const PointModel& model, const PointOrder& order_, float          old_epsilon_2 = epsilon_2;      } +    QMutexLocker l(&mtx);      // apply results      X_CM.R = *R_current;      X_CM.t[0] = order[0][0] * Z0/focal_length; diff --git a/tracker-pt/point_tracker.h b/tracker-pt/point_tracker.h index 8c754718..48c7617e 100644 --- a/tracker-pt/point_tracker.h +++ b/tracker-pt/point_tracker.h @@ -15,9 +15,8 @@  #include "ftnoir_tracker_pt_settings.h"  #include <QObject> +#include <QMutex> -// ---------------------------------------------------------------------------- -// Affine frame trafo  class Affine  {  public: @@ -120,12 +119,8 @@ public:      // f : (focal length)/(sensor width)      // dt : time since last call      void track(const std::vector<cv::Vec2f>& projected_points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout); -    Affine pose() const { return X_CM; } +    Affine pose() { QMutexLocker l(&mtx); return X_CM; }      cv::Vec2f project(const cv::Vec3f& v_M, float f); -    void reset(const Affine& pose) -    { -        X_CM = pose; -    }  private:      // the points in model order      struct PointOrder @@ -146,6 +141,7 @@ private:      Timer t;      bool init_phase; +    QMutex mtx;  };  #endif //POINTTRACKER_H diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp index cbb7c268..99f86eb2 100644 --- a/tracker-pt/pt_video_widget.cpp +++ b/tracker-pt/pt_video_widget.cpp @@ -9,6 +9,7 @@   */  #include "pt_video_widget.h" +#include <opencv2/imgproc.hpp>  void PTVideoWidget::update_image(const cv::Mat& frame)  { @@ -16,40 +17,32 @@ void PTVideoWidget::update_image(const cv::Mat& frame)      if (!freshp)      { -        _frame = frame.clone(); +        if (_frame.cols != frame.cols || _frame.rows != frame.rows) +        { +            _frame = cv::Mat(frame.rows, frame.cols, CV_8U); +            _frame2 = cv::Mat(frame.rows, frame.cols, CV_8U); +        } +        frame.copyTo(_frame);          freshp = true;      }  }  void PTVideoWidget::update_and_repaint()  { -    QImage qframe; +    if (static_cast<QWidget*>(parent())->isEnabled())      {          QMutexLocker foo(&mtx);          if (_frame.empty() || !freshp)              return; -        qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); +        cv::cvtColor(_frame, _frame2, cv::COLOR_RGB2BGR); +         +        if (_frame3.cols != width() || _frame3.rows != height()) +            _frame3 = cv::Mat(height(), width(), CV_8U); + +        cv::resize(_frame2, _frame3, cv::Size(width(), height()), 0, 0, cv::INTER_NEAREST); +         +        texture = QImage((const unsigned char*) _frame3.data, _frame3.cols, _frame3.rows, QImage::Format_RGB888);          freshp = false; -        uchar* data = qframe.bits(); -        const int pitch = qframe.bytesPerLine(); -        unsigned char *input = (unsigned char*) _frame.data; -        const int chans = _frame.channels(); -        for (int y = 0; y < _frame.rows; y++) -        { -            const int step = y * _frame.step; -            const int pitch_ = y * pitch; -            for (int x = 0; x < _frame.cols; x++) -            { -                data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; -                data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; -                data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; -            } -        } -    } -    qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); -    { -        QMutexLocker foo(&mtx); -        texture = qframe; +        update();      } -    update();  } diff --git a/tracker-pt/pt_video_widget.h b/tracker-pt/pt_video_widget.h index af1d60fd..d9144ac0 100644 --- a/tracker-pt/pt_video_widget.h +++ b/tracker-pt/pt_video_widget.h @@ -17,6 +17,7 @@  #include <QTimer>  #include <QMutex>  #include <QMutexLocker> +#include <QDebug>  class PTVideoWidget : public QWidget  { @@ -28,7 +29,7 @@ public:          freshp(false)      {          connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); -        timer.start(40); +        timer.start(50);      }      void update_image(const cv::Mat &frame);  protected slots: @@ -42,6 +43,6 @@ private:      QMutex mtx;      QImage texture;      QTimer timer; -    cv::Mat _frame; +    cv::Mat _frame, _frame2, _frame3;      bool freshp;  }; diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.h b/tracker-rift-025/ftnoir_tracker_rift_025.h index 2bd5024b..8333e092 100644 --- a/tracker-rift-025/ftnoir_tracker_rift_025.h +++ b/tracker-rift-025/ftnoir_tracker_rift_025.h @@ -6,7 +6,7 @@  #include "opentrack/plugin-api.hpp"  #include "OVR.h"  #include <memory> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.h b/tracker-rift-042/ftnoir_tracker_rift_042.h index 437a2a39..77e7ffa6 100644 --- a/tracker-rift-042/ftnoir_tracker_rift_042.h +++ b/tracker-rift-042/ftnoir_tracker_rift_042.h @@ -6,7 +6,7 @@  #include "opentrack/plugin-api.hpp"  #include "OVR.h"  #include <memory> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_080.cpp index 889ac8c3..ea77b6d1 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.cpp +++ b/tracker-rift-080/ftnoir_tracker_rift_080.cpp @@ -21,11 +21,8 @@ Rift_Tracker::~Rift_Tracker()  void Rift_Tracker::start_tracker(QFrame*)  { -    { -        ovrInitParams args = {0}; -        if (!OVR_SUCCESS(ovr_Initialize(&args))) -            goto error; -    } +    if (!OVR_SUCCESS(ovr_Initialize(nullptr))) +        goto error;      {          ovrGraphicsLuid luid = {0};          ovrResult res = ovr_Create(&hmd, &luid); diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.h b/tracker-rift-080/ftnoir_tracker_rift_080.h index 08684dd2..879d31d2 100644 --- a/tracker-rift-080/ftnoir_tracker_rift_080.h +++ b/tracker-rift-080/ftnoir_tracker_rift_080.h @@ -6,7 +6,7 @@  #include "opentrack/plugin-api.hpp"  #include "OVR.h"  #include <memory> -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts { diff --git a/tracker-rs/CMakeLists.txt b/tracker-rs/CMakeLists.txt index f4f6d4b9..901d68bb 100644 --- a/tracker-rs/CMakeLists.txt +++ b/tracker-rs/CMakeLists.txt @@ -1,5 +1,5 @@  if(WIN32)      opentrack_boilerplate(opentrack-tracker-rs)      install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe" DESTINATION . ${opentrack-perms}) -    install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe" DESTINATION ./contrib/ ${opentrack-perms}) +    install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe" DESTINATION ./contrib/ ${opentrack-perms})  endif() diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp index 3e9b23c8..e073fa3f 100644 --- a/tracker-rs/ftnoir_tracker_rs.cpp +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -71,17 +71,17 @@ void RSTracker::rsImplProcessFinished(int exitCode){          msgBox.setIcon(QMessageBox::Critical);          msgBox.setText("RealSense Tracking Error");          if(exitCode==-101){ //The implementation got an invalid handle from the RealSense SDK session/modules -            msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R4."); +            msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R5.");          }          else { -            msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R4 to be installed."); +            msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R5 to be installed.");          }          QPushButton* triggerSdkInstallation = msgBox.addButton("Install Runtime", QMessageBox::ActionRole);          msgBox.addButton(QMessageBox::Ok);          msgBox.exec();          if(msgBox.clickedButton() == triggerSdkInstallation){ -            bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); +            bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.8048.exe --finstall=core,face3d --fnone=all");              if(!pStarted){                  QMessageBox::warning(0, "Intel® RealSense™ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok);              } diff --git a/tracker-rs/ftnoir_tracker_rs_controls.cpp b/tracker-rs/ftnoir_tracker_rs_controls.cpp index 6c71d58f..be18b3f8 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.cpp +++ b/tracker-rs/ftnoir_tracker_rs_controls.cpp @@ -20,7 +20,7 @@ RSTrackerControls::RSTrackerControls()  void RSTrackerControls::doInstallRSRuntime()  { -    bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); +    bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_7.0.23.8048.exe --finstall=core,face3d --fnone=all");      if(processStarted){          this->close();      } diff --git a/tracker-rs/ftnoir_tracker_rs_controls.ui b/tracker-rs/ftnoir_tracker_rs_controls.ui index 834803d1..023e14d3 100644 --- a/tracker-rs/ftnoir_tracker_rs_controls.ui +++ b/tracker-rs/ftnoir_tracker_rs_controls.ui @@ -37,14 +37,14 @@ Intel® RealSense™ SDK. By design, the application has no direct access  to any camera images.  In order to use this tracker, you need a PC equipped with -an Intel® RealSense™ R200 camera and the RealSense™ SDK R4 runtime.</string> +an Intel® RealSense™ R200 camera and the RealSense™ SDK R5 runtime.</string>       </property>      </widget>     </item>     <item alignment="Qt::AlignHCenter|Qt::AlignVCenter">      <widget class="QPushButton" name="triggerSDKInstallButton">       <property name="text"> -      <string>Install SDK Runtime R4</string> +      <string>Install SDK Runtime R5</string>       </property>      </widget>     </item> diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe Binary files differdeleted file mode 100644 index 34ecc9df..00000000 --- a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe +++ /dev/null diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe Binary files differnew file mode 100644 index 00000000..2e2b365c --- /dev/null +++ b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe diff --git a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe Binary files differindex 1e2a57f1..e00ed69c 100644 --- a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe +++ b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe diff --git a/tracker-rs/rs_impl/build.bat b/tracker-rs/rs_impl/build.bat index 15206431..3a44fed5 100644 --- a/tracker-rs/rs_impl/build.bat +++ b/tracker-rs/rs_impl/build.bat @@ -1,2 +1,6 @@ -cd "%VS120COMNTOOLS%\..\..\VC" +IF DEFINED %VS120COMNTOOLS%] ( +	cd "%VS120COMNTOOLS%\..\..\VC" +	) ELSE ( +	cd "%VS140COMNTOOLS%\..\..\VC" +	)  vcvarsall x64 && cd %~dp0 && CL /nologo /Ox /DUNICODE /D_UNICODE /MT /I"%RSSDK_DIR%\opensource\include" ftnoir_tracker_rs_impl.cpp udp_sender.cpp "%RSSDK_DIR%\opensource\src\libpxc\libpxc.cpp" /link ADVAPI32.LIB Ws2_32.lib /SUBSYSTEM:CONSOLE /OUT:bin\opentrack-tracker-rs-impl.exe 
\ No newline at end of file diff --git a/tracker-udp/ftnoir_tracker_udp.h b/tracker-udp/ftnoir_tracker_udp.h index 6de5b295..3f0e6d8c 100644 --- a/tracker-udp/ftnoir_tracker_udp.h +++ b/tracker-udp/ftnoir_tracker_udp.h @@ -4,7 +4,7 @@  #include <QThread>  #include <cmath>  #include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" +#include "opentrack-compat/options.hpp"  using namespace options;  struct settings : opts {  | 
