summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2016-01-06 20:07:13 +0100
committerStanislaw Halik <sthalik@misaki.pl>2016-01-06 20:16:18 +0100
commit82f3d7373234cc0db79a22d476cb54b5eda7a0ea (patch)
tree65ee0194ad064cc470f95f7ca8efd533b089ca96
parent7e3807d048c5e0a8e0aa64fb49807bf5dfd11fc1 (diff)
parentf02baa0868f219076a641634625f7c032d3a9eef (diff)
Merge branch 'unstable' into trackhat
* unstable: (140 commits) tracker/pt: increase auto threshold bucket size again tracker/pt: limit max amount of extracted blobs gui: don't update main window if we're minimized tracker/pt: only show widget if the frame is visible tracker/pt: don't resize twice in widget freetrack/games: regen contrib/make-csv: perl sort isn't stable, don't ignore case tracker/pt: avoid widget temp QImage allocation spline-widget: oops, pass by reference tracker/pt: don't allocate temporary dynamic size arrays tracker/pt: don't copy points array needlessly tracker/pt: don't allocate temporary frame tracker/pt: cv::Mat::at<T> is slow, use cv::Mat::ptr tracker/pt: avoid widget malloc when able tracker/pt: optimize widget tracker/pt: update video widget at 40 -> 50 ms cmake/mingw-w64: update tracker/pt: reduce mutex contention gui: fix left margin tracker/pt: remove krap tracker/pt: move ctor out of the loop tracker/pt: nix unused tracker/pt: don't fill mask on frame pose-widget: also bilinear interpolation of alpha value ui: adjust margin ui: make more compact glwidget: use transparent octopus background api/mat: fix typos/breakage api/joy: refresh only manually on certain events pt: histogram more granular 6 -> 8 cmake/api: link with strmiids.lib on win32 tracker/pt: reduce auto thresholding histogram bucket size api/keys: prevent idempotent keys api/joy: move from header api/joy: prevent idempotent keypressed passed to receiver compat/options: get rid of std::string usage compat/options: move from header gui/settings: set parent, otherwise not modal gui/settings: don't forget to show a modal dialog before executing gui/main: don't raise a new window, it's enough to set visible api/joy: speed up poll_axis path api/joy: nix static, now that we're not a singleton tracker/joy: adapt to non-singleton joy worker joystick: no longer singleton, use fake window handle api/keys: use a fake window for DirectInput handle gui/keys: allow for pausing global keystrokes for options dialog api/keys: nix tautological #ifdef contrib/aruco: oops, right extension contrib/aruco: use @frost555's marker image api/camera-names: move to compat/ ...
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md2
-rw-r--r--cmake/mingw-w64.cmake2
-rw-r--r--cmake/opentrack-macros.cmake33
-rw-r--r--contrib/aruco/test3.jpgbin2145 -> 0 bytes
-rw-r--r--contrib/aruco/test3.pngbin0 -> 53101 bytes
-rw-r--r--contrib/very-important-source-code/make-csv.pl2
-rw-r--r--csv/CMakeLists.txt2
-rw-r--r--csv/csv.h2
-rw-r--r--filter-accela/ftnoir_filter_accela.cpp8
-rw-r--r--filter-accela/ftnoir_filter_accela.h2
-rw-r--r--filter-ewma2/ftnoir_filter_ewma2.h2
-rw-r--r--filter-kalman/ftnoir_filter_kalman.h2
-rw-r--r--gui/CMakeLists.txt14
-rw-r--r--gui/curve-config.cpp6
-rw-r--r--gui/keyboard.h32
-rw-r--r--gui/main.cpp2
-rw-r--r--gui/main.ui1526
-rw-r--r--gui/new_file_dialog.h2
-rw-r--r--gui/options-dialog.cpp138
-rw-r--r--gui/options-dialog.hpp13
-rw-r--r--gui/process_detector.h2
-rw-r--r--gui/settings.ui192
-rw-r--r--gui/software-update-dialog.hpp2
-rw-r--r--gui/ui.cpp108
-rw-r--r--gui/ui.h23
-rw-r--r--gui/wizard.h2
-rw-r--r--make-tar.sh2
-rw-r--r--opentrack-compat/CMakeLists.txt3
-rw-r--r--opentrack-compat/camera-names.cpp (renamed from opentrack/camera-names.hpp)40
-rw-r--r--opentrack-compat/camera-names.hpp22
-rw-r--r--opentrack-compat/compat-export.hpp15
-rw-r--r--opentrack-compat/compat-import.hpp15
-rw-r--r--opentrack-compat/export.hpp22
-rw-r--r--opentrack-compat/import.hpp15
-rw-r--r--opentrack-compat/options.cpp199
-rw-r--r--opentrack-compat/options.hpp (renamed from opentrack/options.hpp)276
-rw-r--r--opentrack-compat/shm.cpp121
-rw-r--r--opentrack-compat/shm.h30
-rw-r--r--opentrack/CMakeLists.txt4
-rw-r--r--opentrack/keybinding-worker.cpp192
-rw-r--r--opentrack/keybinding-worker.hpp81
-rw-r--r--opentrack/main-settings.hpp30
-rw-r--r--opentrack/mappings.hpp2
-rw-r--r--opentrack/opencv-camera-dialog.hpp2
-rw-r--r--opentrack/plugin-api.hpp40
-rw-r--r--opentrack/plugin-support.hpp2
-rw-r--r--opentrack/selected-libraries.hpp9
-rw-r--r--opentrack/shortcuts.cpp194
-rw-r--r--opentrack/shortcuts.h126
-rw-r--r--opentrack/simple-mat.hpp30
-rw-r--r--opentrack/state.hpp2
-rw-r--r--opentrack/tracker.h16
-rw-r--r--opentrack/win32-joystick.cpp299
-rw-r--r--opentrack/win32-joystick.hpp100
-rw-r--r--opentrack/win32-shortcuts.cpp1
-rw-r--r--opentrack/win32-shortcuts.h8
-rw-r--r--opentrack/work.hpp34
-rw-r--r--pose-widget/CMakeLists.txt2
-rw-r--r--pose-widget/glwidget.cpp24
-rw-r--r--pose-widget/glwidget.h2
-rwxr-xr-xpose-widget/images/side1.pngbin4100 -> 4039 bytes
-rwxr-xr-xpose-widget/images/side6.pngbin4100 -> 4039 bytes
-rw-r--r--proto-fg/ftnoir_protocol_fg.h2
-rw-r--r--proto-fsuipc/ftnoir_protocol_fsuipc.h2
-rw-r--r--proto-ft/ftnoir_protocol_ft.h2
-rw-r--r--proto-ftn/ftnoir_protocol_ftn.h2
-rw-r--r--proto-mouse/ftnoir_protocol_mouse.h2
-rw-r--r--proto-sc/ftnoir_protocol_sc.h2
-rw-r--r--qxt-mini/CMakeLists.txt2
-rw-r--r--qxt-mini/QxtGlobalShortcut4
-rw-r--r--qxt-mini/qxtglobal.h2
-rw-r--r--settings/facetracknoir supported games.csv242
-rw-r--r--spline-widget/CMakeLists.txt3
-rw-r--r--spline-widget/functionconfig.cpp8
-rw-r--r--spline-widget/functionconfig.h6
-rw-r--r--spline-widget/qfunctionconfigurator.cpp24
-rw-r--r--spline-widget/qfunctionconfigurator.h4
-rw-r--r--tracker-aruco/ftnoir_tracker_aruco.cpp28
-rw-r--r--tracker-aruco/ftnoir_tracker_aruco.h4
-rw-r--r--tracker-freepie-udp/ftnoir_tracker_freepie-udp.h2
-rw-r--r--tracker-hatire/ftnoir_tracker_hat_dialog.h4
-rw-r--r--tracker-hatire/ftnoir_tracker_hat_settings.cpp2
-rw-r--r--tracker-ht/CMakeLists.txt2
-rw-r--r--tracker-ht/ftnoir_tracker_ht.h2
-rw-r--r--tracker-hydra/ftnoir_tracker_hydra.h2
-rw-r--r--tracker-joystick/ftnoir_tracker_joystick.cpp230
-rw-r--r--tracker-joystick/ftnoir_tracker_joystick.h42
-rw-r--r--tracker-joystick/ftnoir_tracker_joystick_dialog.cpp53
-rw-r--r--tracker-pt/camera.cpp10
-rw-r--r--tracker-pt/ftnoir_tracker_pt.cpp71
-rw-r--r--tracker-pt/ftnoir_tracker_pt.h6
-rw-r--r--tracker-pt/ftnoir_tracker_pt_settings.h2
-rw-r--r--tracker-pt/point_extractor.cpp68
-rw-r--r--tracker-pt/point_extractor.h13
-rw-r--r--tracker-pt/point_tracker.cpp1
-rw-r--r--tracker-pt/point_tracker.h10
-rw-r--r--tracker-pt/pt_video_widget.cpp41
-rw-r--r--tracker-pt/pt_video_widget.h5
-rw-r--r--tracker-rift-025/ftnoir_tracker_rift_025.h2
-rw-r--r--tracker-rift-042/ftnoir_tracker_rift_042.h2
-rw-r--r--tracker-rift-080/ftnoir_tracker_rift_080.cpp7
-rw-r--r--tracker-rift-080/ftnoir_tracker_rift_080.h2
-rw-r--r--tracker-rs/CMakeLists.txt2
-rw-r--r--tracker-rs/ftnoir_tracker_rs.cpp6
-rw-r--r--tracker-rs/ftnoir_tracker_rs_controls.cpp2
-rw-r--r--tracker-rs/ftnoir_tracker_rs_controls.ui4
-rw-r--r--tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exebin780456 -> 0 bytes
-rw-r--r--tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exebin0 -> 1203240 bytes
-rw-r--r--tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exebin83968 -> 93696 bytes
-rw-r--r--tracker-rs/rs_impl/build.bat6
-rw-r--r--tracker-udp/ftnoir_tracker_udp.h2
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)
diff --git a/README.md b/README.md
index 82327af9..f837b847 100644
--- a/README.md
+++ b/README.md
@@ -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
deleted file mode 100644
index 2ff6dbd0..00000000
--- a/contrib/aruco/test3.jpg
+++ /dev/null
Binary files differ
diff --git a/contrib/aruco/test3.png b/contrib/aruco/test3.png
new file mode 100644
index 00000000..81f2d201
--- /dev/null
+++ b/contrib/aruco/test3.png
Binary files differ
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)
diff --git a/csv/csv.h b/csv/csv.h
index 7ae1ad5c..e5a37793 100644
--- a/csv/csv.h
+++ b/csv/csv.h
@@ -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;
diff --git a/gui/ui.cpp b/gui/ui.cpp
index 86c9fa9c..83ef523a 100644
--- a/gui/ui.cpp
+++ b/gui/ui.cpp
@@ -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)
diff --git a/gui/ui.h b/gui/ui.h
index c1e71ca9..42a85e47 100644
--- a/gui/ui.h
+++ b/gui/ui.h
@@ -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
index 1424faa3..e85a3205 100755
--- a/pose-widget/images/side1.png
+++ b/pose-widget/images/side1.png
Binary files differ
diff --git a/pose-widget/images/side6.png b/pose-widget/images/side6.png
index 1424faa3..e85a3205 100755
--- a/pose-widget/images/side6.png
+++ b/pose-widget/images/side6.png
Binary files differ
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
deleted file mode 100644
index 34ecc9df..00000000
--- a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe
+++ /dev/null
Binary files differ
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
new file mode 100644
index 00000000..2e2b365c
--- /dev/null
+++ b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_7.0.23.8048.exe
Binary files differ
diff --git a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe
index 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
Binary files differ
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 {