summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.md10
-rwxr-xr-xCMakeLists.txt5
-rw-r--r--OPENTRACK-LICENSING.txt78
-rw-r--r--api/plugin-api.hpp4
-rw-r--r--cmake/opentrack-boilerplate.cmake27
-rw-r--r--cmake/opentrack-install.cmake15
-rw-r--r--cmake/opentrack-qt.cmake2
-rw-r--r--compat/make-unique.hpp9
-rw-r--r--compat/ndebug-guard.hpp3
-rw-r--r--compat/run-in-thread.hpp22
-rw-r--r--compat/util.hpp17
-rw-r--r--contrib/translation-stub.sh17
-rw-r--r--filter-accela/accela-settings.hpp4
-rw-r--r--filter-accela/ftnoir_accela_filtercontrols.ui126
-rw-r--r--filter-accela/ftnoir_filter_accela.cpp31
-rw-r--r--filter-accela/ftnoir_filter_accela_dialog.cpp47
-rw-r--r--filter-accela/lang/ru_RU.ts89
-rw-r--r--gui/images/english.pngbin0 -> 283 bytes
-rw-r--r--gui/lang/ru_RU.ts97
-rw-r--r--gui/main-window.cpp41
-rw-r--r--gui/main-window.ui24
-rw-r--r--gui/main.cpp9
-rw-r--r--gui/mapping-window.hpp3
-rw-r--r--gui/new_file_dialog.h3
-rw-r--r--gui/opentrack-res.qrc1
-rw-r--r--gui/options-dialog.cpp15
-rw-r--r--gui/options-dialog.hpp5
-rw-r--r--gui/options-dialog.ui92
-rw-r--r--logic/tracker.cpp45
-rw-r--r--logic/tracker.h8
-rw-r--r--migration/20160917_00-accela.cpp2
-rw-r--r--options/bundle.cpp4
-rw-r--r--options/bundle.hpp6
-rw-r--r--options/options.hpp4
-rw-r--r--options/tie.hpp66
-rw-r--r--options/value.hpp23
-rw-r--r--pose-widget/glwidget.cpp2
-rw-r--r--pose-widget/glwidget.h4
-rw-r--r--proto-ft/lang/ru_RU.ts92
-rw-r--r--settings/facetracknoir supported games.csv5
-rw-r--r--spline-widget/spline-widget.cpp26
-rw-r--r--spline-widget/spline-widget.hpp11
-rw-r--r--spline-widget/spline.cpp29
-rw-r--r--spline-widget/spline.hpp6
-rw-r--r--tracker-aruco/CMakeLists.txt14
-rw-r--r--tracker-aruco/aruco-trackercontrols.ui15
-rw-r--r--tracker-aruco/ftnoir_tracker_aruco.cpp184
-rw-r--r--tracker-aruco/ftnoir_tracker_aruco.h60
-rw-r--r--tracker-aruco/trans_calib.cpp41
-rw-r--r--tracker-aruco/trans_calib.h39
-rw-r--r--tracker-hatire/ftnoir_tracker_hat.cpp4
-rw-r--r--tracker-hydra/ftnoir_tracker_hydra.cpp16
-rw-r--r--tracker-pt/camera.cpp128
-rw-r--r--tracker-pt/camera.h85
-rw-r--r--tracker-pt/ftnoir_tracker_pt.cpp56
-rw-r--r--tracker-pt/ftnoir_tracker_pt.h8
-rw-r--r--tracker-pt/ftnoir_tracker_pt_dialog.cpp10
-rw-r--r--tracker-pt/lang/ru_RU.ts294
-rw-r--r--tracker-qt-gamepad/CMakeLists.txt3
-rw-r--r--tracker-qt-gamepad/test.cpp99
-rw-r--r--tracker-qt-gamepad/test.h45
-rw-r--r--tracker-qt-gamepad/test.ui59
-rw-r--r--tracker-qt-gamepad/test_dialog.cpp3
-rw-r--r--tracker-rift-025/ftnoir_tracker_rift_025.cpp41
-rw-r--r--tracker-rift-025/ftnoir_tracker_rift_025.h6
-rw-r--r--tracker-rift-042/ftnoir_tracker_rift_042.cpp28
-rw-r--r--tracker-rift-042/ftnoir_tracker_rift_042.h6
-rw-r--r--tracker-rift-080/ftnoir_tracker_rift_080.cpp26
-rw-r--r--tracker-rift-080/ftnoir_tracker_rift_080.h6
-rw-r--r--tracker-rift-140/impl.cpp28
-rw-r--r--tracker-rift-140/rift-140.hpp6
-rw-r--r--tracker-rs/ftnoir_tracker_rs.cpp13
-rw-r--r--tracker-steamvr/dialog.cpp6
-rw-r--r--tracker-steamvr/steamvr.cpp15
-rw-r--r--tracker-steamvr/steamvr.hpp8
-rw-r--r--tracker-test/test.cpp8
-rw-r--r--tracker-test/test.h8
-rw-r--r--tracker-tobii-eyex/CMakeLists.txt6
-rw-r--r--tracker-tobii-eyex/tobii-eyex-dialog.cpp25
-rw-r--r--tracker-tobii-eyex/tobii-eyex-dialog.ui210
-rw-r--r--tracker-tobii-eyex/tobii-eyex.cpp173
-rw-r--r--tracker-tobii-eyex/tobii-eyex.hpp22
82 files changed, 2035 insertions, 898 deletions
diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 00000000..ca3ba840
--- /dev/null
+++ b/AUTHORS.md
@@ -0,0 +1,10 @@
+The following people contributed parts of the codebase to the project, in
+chronological order:
+
+- Stanislaw Halik <<sthalik@misaki.pl>>
+- Chris Thompson <<mm0zct@gmail.com>>
+- Donovan Baarda <<abo@minkirri.apana.org.au>>
+- Xavier Hallade <<xavier.hallade@intel.com>>
+- Michael Welter <<mw.pub@welter-4d.de>>
+
+See OPENTRACK-LICENSING.txt for licensing information.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a953c1e7..e3d12828 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ cmake_minimum_required(VERSION 2.8.11)
set_property(GLOBAL PROPERTY opentrack-all-modules "")
set_property(GLOBAL PROPERTY opentrack-all-source-dirs "")
-set(opentrack-all-translations pl_PL ru_RU)
+set(opentrack-all-translations nl_NL ru_RU stub)
include(opentrack-policy)
include(opentrack-word-size)
@@ -38,6 +38,7 @@ include(opentrack-hier)
include(opentrack-qt)
include(opentrack-platform)
include(opentrack-boilerplate)
+
include(opentrack-version)
include(opentrack-install)
@@ -45,7 +46,7 @@ if(WIN32)
enable_language(RC)
endif()
-add_custom_target(mrproper COMMAND cmake -P "${CMAKE_SOURCE_DIR}/cmake/opentrack-clean-build-directory.cmake" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
+add_custom_target(mrproper COMMAND ${CMAKE_COMMAND} -P "${CMAKE_SOURCE_DIR}/cmake/opentrack-clean-build-directory.cmake" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
set(C CMakeLists.txt)
file(GLOB opentrack-subprojects
diff --git a/OPENTRACK-LICENSING.txt b/OPENTRACK-LICENSING.txt
new file mode 100644
index 00000000..068fb101
--- /dev/null
+++ b/OPENTRACK-LICENSING.txt
@@ -0,0 +1,78 @@
+# Code licensing
+
+The following modules are licensed as part of the opentrack project. See
+3rdparty-notices/ for third-party code.
+
+# Lack of warranty
+
+Unless warranty terms are specified in particular licensing terms, the
+following warranty disclaimer terms apply:
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+# core, various modules
+
+Copyright (c) 2012-2016 Stanislaw Halik
+
+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.
+
+# Rift modules, Sixense Hydra module
+
+Copyright (c) 2013 mm0zct
+
+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.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+# EWMA filter
+
+Copyright (c) 2014 Donovan Baarda <abo@minkirri.apana.org.au>
+
+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.
+
+# Kalman filter
+
+Copyright (c) 2016 Michael Welter <mw.pub@welter-4d.de>
+
+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.
+
+# Intel RealSense tracker
+
+Copyright (c) 2015, Intel Corporation
+Author: Xavier Hallade <xavier.hallade@intel.com>
+
+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.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+# EOF
+
+# vim: noai:ts=4:sw=4:tw=79
diff --git a/api/plugin-api.hpp b/api/plugin-api.hpp
index 996d32d3..e9de9dad 100644
--- a/api/plugin-api.hpp
+++ b/api/plugin-api.hpp
@@ -12,6 +12,8 @@
#include <QWidget>
#include <QFrame>
#include <QIcon>
+#include <QWidget>
+#include <QDialog>
#include "export.hpp"
@@ -37,7 +39,7 @@ enum Axis {
namespace plugin_api {
namespace detail {
-class OPENTRACK_API_EXPORT BaseDialog : public QWidget
+class OPENTRACK_API_EXPORT BaseDialog : public QDialog
{
Q_OBJECT
protected:
diff --git a/cmake/opentrack-boilerplate.cmake b/cmake/opentrack-boilerplate.cmake
index 8d23ad19..9ca382e8 100644
--- a/cmake/opentrack-boilerplate.cmake
+++ b/cmake/opentrack-boilerplate.cmake
@@ -199,7 +199,7 @@ function(opentrack_boilerplate n)
if(NOT arg_STATIC)
string(REGEX REPLACE "^opentrack-" "" n_ "${n}")
- string(REGEX REPLACE "^(tracker|filter-proto)-" "" n_ "${n_}")
+ string(REGEX REPLACE "^(tracker|filter|proto)-" "" n_ "${n_}")
string(REPLACE "-" "_" n_ ${n_})
target_compile_definitions(${n} PRIVATE "BUILD_${n_}")
@@ -215,23 +215,30 @@ function(opentrack_boilerplate n)
endif()
endif()
+ set(SDK_REGEN_TRANSLATIONS FALSE CACHE BOOL "Regenerate translation files on build")
+
set(langs "")
foreach(i ${opentrack-all-translations})
set(t "${CMAKE_CURRENT_SOURCE_DIR}/lang/${i}.ts")
- list(APPEND langs "${t}")
- get_property(tt GLOBAL PROPERTY opentrack-${i}-ts)
- set(tt ${tt} ${t})
- set_property(GLOBAL PROPERTY opentrack-${i}-ts ${tt})
+ if(SDK_REGEN_TRANSLATIONS OR NOT EXISTS "${t}")
+ list(APPEND langs "${t}")
+ get_property(tt GLOBAL PROPERTY opentrack-${i}-ts)
+ set(tt ${tt} ${t})
+ set_property(GLOBAL PROPERTY opentrack-${i}-ts ${tt})
+ endif()
endforeach()
get_property(modules GLOBAL PROPERTY opentrack-all-modules)
list(APPEND modules "${n}")
set_property(GLOBAL PROPERTY opentrack-all-modules "${modules}")
- add_custom_target(${n}-i18n
- COMMAND cmake -E make_directory "${CMAKE_CURRENT_SOURCE_DIR}/lang"
- COMMAND "${Qt5_DIR}/../../../bin/lupdate" -silent -recursive -no-obsolete -locations relative . -ts ${langs}
- WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
- )
+ if(NOT langs STREQUAL "")
+ add_custom_target(i18n-module-${n}
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_SOURCE_DIR}/lang"
+ COMMAND "${Qt5_DIR}/../../../bin/lupdate" -silent -recursive -no-obsolete -locations relative . -ts ${langs}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+ else()
+ add_custom_target(i18n-module-${n})
+ endif()
endfunction()
diff --git a/cmake/opentrack-install.cmake b/cmake/opentrack-install.cmake
index 3e77e396..3406007b 100644
--- a/cmake/opentrack-install.cmake
+++ b/cmake/opentrack-install.cmake
@@ -36,6 +36,8 @@ opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/CMakeLists
opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/README.md")
opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/CONTRIBUTING.md")
opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/WARRANTY.txt")
+opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/OPENTRACK-LICENSING.txt")
+opentrack_inst2("${opentrack-doc-src-pfx}" FILES "${CMAKE_SOURCE_DIR}/AUTHORS.md")
function(opentrack_install_sources n)
opentrack_sources(${n} sources)
@@ -60,13 +62,16 @@ function(merge_translations)
set(deps "")
foreach(k ${modules})
- list(APPEND deps "${k}-i18n")
+ list(APPEND deps "i18n-module-${k}")
endforeach()
- add_custom_target(i18n-lang-${i}
- COMMAND "${Qt5_DIR}/../../../bin/lrelease" -nounfinished -silent ${ts} -qm "${qm-output}"
- DEPENDS ${deps}
- )
+ if(NOT "${ts}" STREQUAL "")
+ add_custom_target(i18n-lang-${i}
+ COMMAND "${Qt5_DIR}/../../../bin/lrelease" -nounfinished -silent ${ts} -qm "${qm-output}"
+ DEPENDS ${deps})
+ else()
+ add_custom_target(i18n-lang-${i} DEPENDS ${deps})
+ endif()
list(APPEND all-deps "i18n-lang-${i}")
install(FILES "${qm-output}" DESTINATION "${opentrack-i18n-pfx}" RENAME "${i}.qm" ${opentrack-perms})
endforeach()
diff --git a/cmake/opentrack-qt.cmake b/cmake/opentrack-qt.cmake
index bb492eda..c6ab2673 100644
--- a/cmake/opentrack-qt.cmake
+++ b/cmake/opentrack-qt.cmake
@@ -1,5 +1,5 @@
find_package(Qt5 REQUIRED COMPONENTS Core Network Widgets Gui QUIET)
-find_package(Qt5 COMPONENTS SerialPort QUIET)
+find_package(Qt5 COMPONENTS SerialPort Gamepad QUIET)
include_directories(SYSTEM ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS})
add_definitions(${Qt5Core_DEFINITIONS} ${Qt5Gui_DEFINITIONS} ${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS})
set(MY_QT_LIBS ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES})
diff --git a/compat/make-unique.hpp b/compat/make-unique.hpp
index bb5315c5..64c647b1 100644
--- a/compat/make-unique.hpp
+++ b/compat/make-unique.hpp
@@ -8,7 +8,7 @@
#include <utility>
#include <cstddef>
-namespace detail {
+namespace raii_detail {
template<class T> struct Unique_if
{
typedef std::unique_ptr<T> Single_object;
@@ -26,18 +26,19 @@ template<class T, size_t N> struct Unique_if<T[N]>
}
template<class T, class... Args>
- typename detail::Unique_if<T>::Single_object
+ typename ::raii_detail::Unique_if<T>::Single_object
make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template<class T>
- typename detail::Unique_if<T>::Unknown_bound
+ typename ::raii_detail::Unique_if<T>::Unknown_bound
make_unique(std::size_t n) {
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[n]());
}
template<class T, class... Args>
- typename detail::Unique_if<T>::Known_bound
+ typename ::raii_detail::Unique_if<T>::Known_bound
make_unique(Args&&...) = delete;
+
diff --git a/compat/ndebug-guard.hpp b/compat/ndebug-guard.hpp
new file mode 100644
index 00000000..209177b3
--- /dev/null
+++ b/compat/ndebug-guard.hpp
@@ -0,0 +1,3 @@
+#ifdef NDEBUG
+# error "NDEBUG defined, don't define it"
+#endif
diff --git a/compat/run-in-thread.hpp b/compat/run-in-thread.hpp
index d377f625..90aa143b 100644
--- a/compat/run-in-thread.hpp
+++ b/compat/run-in-thread.hpp
@@ -1,12 +1,16 @@
#pragma once
-#include <QObject>
+#include "ndebug-guard.hpp"
+#include <cassert>
#include <thread>
#include <condition_variable>
#include <utility>
-namespace detail {
+#include <QObject>
+#include <QThread>
+
+namespace qt_impl_detail {
template<typename t>
struct run_in_thread_traits
@@ -25,14 +29,14 @@ struct run_in_thread_traits<void>
using ret_type = void;
static inline void assign(unsigned char&, unsigned char&&) {}
static inline void pass(type&&) {}
- template<typename F> static type&& call(F& fun) { fun(); return std::move(type(0)); }
+ template<typename F> static type call(F& fun) { fun(); return type(0); }
};
}
template<typename F>
auto run_in_thread_sync(QObject* obj, F&& fun)
- -> typename detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>::ret_type
+ -> typename qt_impl_detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>::ret_type
{
using lock_guard = std::unique_lock<std::mutex>;
@@ -42,7 +46,7 @@ auto run_in_thread_sync(QObject* obj, F&& fun)
std::thread::id waiting_thread = std::this_thread::get_id();
- using traits = detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>;
+ using traits = qt_impl_detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>;
typename traits::type ret;
@@ -50,7 +54,9 @@ auto run_in_thread_sync(QObject* obj, F&& fun)
{
QObject src;
- src.moveToThread(obj->thread());
+ QThread* t(obj->thread());
+ assert(t);
+ src.moveToThread(t);
QObject::connect(&src,
&QObject::destroyed,
obj,
@@ -80,6 +86,8 @@ template<typename F>
void run_in_thread_async(QObject* obj, F&& fun)
{
QObject src;
- src.moveToThread(obj->thread());
+ QThread* t(obj->thread());
+ assert(t);
+ src.moveToThread(t);
QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection);
}
diff --git a/compat/util.hpp b/compat/util.hpp
index 7a6858a3..5b9e2c69 100644
--- a/compat/util.hpp
+++ b/compat/util.hpp
@@ -1,10 +1,15 @@
#pragma once
+#include "ndebug-guard.hpp"
+
#include "make-unique.hpp"
#include "run-in-thread.hpp"
#include <memory>
#include <cmath>
+#include <utility>
+
+#include <QSharedPointer>
#define progn(...) ([&]() { __VA_ARGS__ }())
template<typename t> using mem = std::shared_ptr<t>;
@@ -22,7 +27,7 @@ int iround(const t& val)
return int(std::round(val));
}
-namespace detail {
+namespace util_detail {
template<typename n>
inline auto clamp_(n val, n min, n max) -> n
@@ -39,5 +44,13 @@ inline auto clamp_(n val, n min, n max) -> n
template<typename t, typename u, typename w>
inline auto clamp(const t& val, const u& min, const w& max) -> decltype(val * min * max)
{
- return ::detail::clamp_<decltype(val * min * max)>(val, min, max);
+ return ::util_detail::clamp_<decltype(val * min * max)>(val, min, max);
+}
+
+template<typename t, typename... xs>
+auto qptr(xs... args)
+{
+ return QSharedPointer<t>(new t(std::forward<xs>(args)...));
}
+
+template<typename t> using qshared = QSharedPointer<t>;
diff --git a/contrib/translation-stub.sh b/contrib/translation-stub.sh
new file mode 100644
index 00000000..bb5ed51d
--- /dev/null
+++ b/contrib/translation-stub.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+build_dir=build-msvc15
+
+set -e
+
+dir="$(dirname -- "$0")"
+cd "$dir/.."
+
+pushd "./$build_dir" >/dev/null
+cmake --build . --target i18n >/dev/null
+popd >/dev/null
+
+rel="$(git describe --tag --alw)"
+
+rm -f "$rel"
+find . -wholename "?*/lang/stub.ts" | zip -q9 "$build_dir/$rel-i18n-stub.zip" -@
diff --git a/filter-accela/accela-settings.hpp b/filter-accela/accela-settings.hpp
index b012fc07..2ecd8bbc 100644
--- a/filter-accela/accela-settings.hpp
+++ b/filter-accela/accela-settings.hpp
@@ -50,11 +50,11 @@ struct settings_accela : opts
value<slider_value> rot_nonlinearity;
settings_accela() :
opts("accela-sliders"),
- rot_sensitivity(b, "rotation-sensitivity", slider_value(1.8, .05, 5)),
+ rot_sensitivity(b, "rotation-sensitivity", slider_value(1.5, .05, 5)),
trans_sensitivity(b, "translation-sensitivity", slider_value(1., .05, 1.5)),
rot_deadzone(b, "rotation-deadzone", slider_value(.03, 0, 2)),
trans_deadzone(b, "translation-deadzone", slider_value(.1, 0, 1)),
ewma(b, "ewma", slider_value(0, 0, 30)),
- rot_nonlinearity(b, "rotation-nonlinearity", slider_value(1.05, 1, 1.5))
+ rot_nonlinearity(b, "rotation-nonlinearity", slider_value(1.2, 1, 1.5))
{}
};
diff --git a/filter-accela/ftnoir_accela_filtercontrols.ui b/filter-accela/ftnoir_accela_filtercontrols.ui
index 4ed91099..4649bcd6 100644
--- a/filter-accela/ftnoir_accela_filtercontrols.ui
+++ b/filter-accela/ftnoir_accela_filtercontrols.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>550</width>
- <height>412</height>
+ <height>435</height>
</rect>
</property>
<property name="sizePolicy">
@@ -308,55 +308,89 @@
<property name="title">
<string>Rotation nonlinearity</string>
</property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="1">
- <widget class="QLabel" name="rot_nl">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>0</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- </font>
- </property>
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;x&lt;span style=&quot; vertical-align:super;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_5">
<property name="text">
- <string>Value</string>
+ <string>Setting it higher will filter out rotation noise but may cause sudden jumps on very high settings.</string>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="QSlider" name="rot_nl_slider">
- <property name="minimum">
- <number>0</number>
- </property>
- <property name="maximum">
- <number>20</number>
- </property>
- <property name="pageStep">
- <number>2</number>
- </property>
- <property name="value">
- <number>1</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- <property name="tickInterval">
- <number>3</number>
- </property>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <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>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="rot_nl">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;x&lt;span style=&quot; vertical-align:super;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="rot_nl_slider">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="pageStep">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
</layout>
diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp
index 4fec74b2..dea39eb7 100644
--- a/filter-accela/ftnoir_filter_accela.cpp
+++ b/filter-accela/ftnoir_filter_accela.cpp
@@ -35,45 +35,46 @@ void accela::filter(const double* input, double *output)
return;
}
- const double rot_t = s.rot_sensitivity->cur();
- const double trans_t = s.trans_sensitivity->cur();
+#define cast(x) (static_cast<slider_value&&>((x)))
+
+ const double rot_t = cast(s.rot_sensitivity).cur();
+ const double trans_t = cast(s.trans_sensitivity).cur();
const double dt = t.elapsed_seconds();
t.start();
- const double RC = s.ewma->cur() / 1000.; // seconds
+ const double RC = cast(s.ewma).cur() / 1000.; // seconds
const double alpha = dt/(dt+RC);
- const double rot_dz = s.rot_deadzone->cur();
- const double trans_dz = s.trans_deadzone->cur();
- const slider_value rot_nl_ = s.rot_nonlinearity;
- const double rot_nl = rot_nl_.cur();
+ const double rot_dz = cast(s.rot_deadzone).cur();
+ const double trans_dz = cast(s.trans_deadzone).cur();
+ const slider_value nl = s.rot_nonlinearity;
for (int i = 0; i < 6; i++)
{
spline& m = i >= 3 ? rot : trans;
- smoothed_input[i] = smoothed_input[i] * (1.-alpha) + input[i] * alpha;
+ smoothed_input[i] = smoothed_input[i] * (1-alpha) + input[i] * alpha;
const double in = smoothed_input[i];
- const double vec = in - last_output[i];
+ const double vec_ = in - last_output[i];
const double dz = i >= 3 ? rot_dz : trans_dz;
- const double vec_ = std::max(0., fabs(vec) - dz);
+ const double vec = std::max(0., fabs(vec_) - dz);
const double thres = i >= 3 ? rot_t : trans_t;
- const double out_ = vec_ / thres;
+ const double out_ = vec / thres;
const double out = progn(
const bool should_apply_rot_nonlinearity =
i >= 3 &&
- std::fabs(rot_nl - 1) > 5e-3 &&
- vec_ < rot_nl_.max();
+ std::fabs(nl.cur() - 1) > 5e-3 &&
+ vec < nl.max();
if (should_apply_rot_nonlinearity)
- return std::pow(out_/rot_nl_.max(), rot_nl);
+ return std::pow(out_/nl.max(), nl.cur()) * nl.max();
else
return out_;
);
const double val = double(m.getValue(out));
- last_output[i] = output[i] = last_output[i] + signum(vec) * dt * val;
+ last_output[i] = output[i] = last_output[i] + signum(vec_) * dt * val;
}
}
diff --git a/filter-accela/ftnoir_filter_accela_dialog.cpp b/filter-accela/ftnoir_filter_accela_dialog.cpp
index 79db1ffa..f0ee8391 100644
--- a/filter-accela/ftnoir_filter_accela_dialog.cpp
+++ b/filter-accela/ftnoir_filter_accela_dialog.cpp
@@ -41,33 +41,36 @@ dialog_accela::dialog_accela()
update_trans_dz_display(s.trans_deadzone);
update_rot_nl_slider(s.rot_nonlinearity);
- {
//#define SPLINE_ROT_DEBUG
//#define SPLINE_TRANS_DEBUG
-#if defined(SPLINE_ROT_DEBUG) || defined(SPLINE_TRANS_DEBUG)
- spline rot, trans;
- s.make_splines(rot, trans);
- QDialog d;
-
- spline_widget r(&d);
- r.set_preview_only(true);
- r.setEnabled(false);
- r.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-
-#if defined(SPLINE_TRANS_DEBUG)
-# if defined(SPLINE_ROT_DEBUG)
-# error "rot xor trans"
-# endif
- r.setConfig(&trans);
-#else
-
- r.setConfig(&rot);
+
+#if defined SPLINE_ROT_DEBUG || defined SPLINE_TRANS_DEBUG
+ {
+ spline rot, trans;
+ s.make_splines(rot, trans);
+ QDialog dr, dt;
+ spline_widget r(&dr);
+ spline_widget t(&dt);
+ dr.setWindowTitle("Accela rotation gain"); r.set_preview_only(true); r.setEnabled(false);
+ r.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); r.setConfig(&rot);
+ dt.setWindowTitle("Accela translation gain"); t.set_preview_only(true); t.setEnabled(false);
+ r.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); t.setConfig(&trans);
+ r.setFixedSize(1024, 600); t.setFixedSize(1024, 600);
+
+#ifdef SPLINE_ROT_DEBUG
+ dr.show();
#endif
- r.setFixedSize(1024, 600);
- d.show();
- d.exec();
+
+#ifdef SPLINE_TRANS_DEBUG
+ dt.show();
#endif
+
+ if (dr.isVisible())
+ dr.exec();
+ if (dt.isVisible())
+ dt.exec();
}
+#endif
}
void dialog_accela::doOK()
diff --git a/filter-accela/lang/ru_RU.ts b/filter-accela/lang/ru_RU.ts
new file mode 100644
index 00000000..c6dc44cf
--- /dev/null
+++ b/filter-accela/lang/ru_RU.ts
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>AccelaUICdialog_accela</name>
+ <message>
+ <location filename="../ftnoir_accela_filtercontrols.ui" line="+23"/>
+ <source>Filter settings</source>
+ <translation>Настройка фильтра</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>General</source>
+ <translation>Основные настройки</translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Smoothing</source>
+ <translation>Сглаживание</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>0 ms</source>
+ <translation>0 мс</translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Position filtering (X, Y, Z - translation)</source>
+ <translation>Фильтрация смещений (X, Y, Z)</translation>
+ </message>
+ <message>
+ <location line="+24"/>
+ <location line="+111"/>
+ <source>Sensitivity</source>
+ <translation>Чувствительность</translation>
+ </message>
+ <message>
+ <location line="-98"/>
+ <location line="+29"/>
+ <source>0mm</source>
+ <translation>0мм</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <location line="+104"/>
+ <source>Deadzone</source>
+ <translation>Мертвая зона</translation>
+ </message>
+ <message>
+ <location line="-66"/>
+ <source>Rotation filtering (Yaw, pitch, and roll)</source>
+ <translation>Фильтрация поворотов (Рысканье, тангаж, крен)</translation>
+ </message>
+ <message>
+ <location line="+37"/>
+ <location line="+42"/>
+ <source>0°</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>Rotation nonlinearity</source>
+ <translation>Нелинейность поворотов</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;x&lt;span style=&quot; vertical-align:super;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Value</source>
+ <translation>Значение</translation>
+ </message>
+ <message>
+ <location line="+49"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;right&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Accela by &lt;/span&gt;&lt;a href=&quot;https://github.com/sthalik&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Stanisław Halik&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;Thanks to &lt;/span&gt;&lt;a href=&quot;https://github.com/dbaarda&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Donovan Baarda&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;2012-2015&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Visit &lt;/span&gt;&lt;a href=&quot;https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;our wiki&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; for description of the settings.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;right&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Accela-фильтр создан &lt;/span&gt;&lt;a href=&quot;https://github.com/sthalik&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Stanisław Halik&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&apos;ом&lt;br/&gt;Спасибо за помощь &lt;/span&gt;&lt;a href=&quot;https://github.com/dbaarda&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Donovan Baarda&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;2012-2016&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Посетите &lt;/span&gt;&lt;a href=&quot;https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;нашу вики&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; для понимания процесса настройки.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>accelaDll</name>
+ <message>
+ <location filename="../ftnoir_filter_accela.h" line="+63"/>
+ <source>Accela</source>
+ <translation></translation>
+ </message>
+</context>
+</TS>
diff --git a/gui/images/english.png b/gui/images/english.png
new file mode 100644
index 00000000..187aabf9
--- /dev/null
+++ b/gui/images/english.png
Binary files differ
diff --git a/gui/lang/ru_RU.ts b/gui/lang/ru_RU.ts
index fd7842af..9f5e0463 100644
--- a/gui/lang/ru_RU.ts
+++ b/gui/lang/ru_RU.ts
@@ -50,7 +50,7 @@
<context>
<name>MainWindow</name>
<message>
- <location filename="../main-window.cpp" line="+90"/>
+ <location filename="../main-window.cpp" line="+97"/>
<source>Create new empty config</source>
<translation>Создать новый пустой профиль</translation>
</message>
@@ -77,18 +77,18 @@
</message>
<message>
<location line="+8"/>
- <location line="+555"/>
+ <location line="+559"/>
<source>Show the Octopus</source>
<translation>Показать осьминожка</translation>
</message>
<message>
- <location line="-555"/>
- <location line="+555"/>
+ <location line="-559"/>
+ <location line="+559"/>
<source>Hide the Octopus</source>
<translation>Спрятать осьминожка</translation>
</message>
<message>
- <location line="-548"/>
+ <location line="-552"/>
<source>Tracker settings</source>
<translation>Настройка источника данных</translation>
</message>
@@ -153,6 +153,19 @@ Exiting now.</source>
</message>
</context>
<context>
+ <name>OptionsDialog</name>
+ <message>
+ <location filename="../options-dialog.cpp" line="+27"/>
+ <source>Joy button %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>None</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>UI_new_config</name>
<message>
<location filename="../new_config.ui" line="+17"/>
@@ -188,38 +201,38 @@ Exiting now.</source>
<message>
<location line="+67"/>
<location line="+479"/>
- <source>TZ</source>
- <translation>Смещение по Z</translation>
+ <source>Z</source>
+ <translation>Смещение по оси Z</translation>
</message>
<message>
<location line="-463"/>
<location line="+409"/>
- <source>pitch</source>
- <translation>тангаж</translation>
+ <source>Pitch</source>
+ <translation>Тангаж</translation>
</message>
<message>
<location line="-356"/>
<location line="+315"/>
- <source>TY</source>
- <translation>Смещение по Y</translation>
+ <source>Y</source>
+ <translation>Смещение по оси Y</translation>
</message>
<message>
<location line="-299"/>
<location line="+277"/>
- <source>TX</source>
- <translation>Смещение по X</translation>
+ <source>X</source>
+ <translation>Смещение по оси X</translation>
</message>
<message>
<location line="-230"/>
<location line="+309"/>
- <source>roll</source>
- <translation>крен</translation>
+ <source>Roll</source>
+ <translation>Крен</translation>
</message>
<message>
<location line="-293"/>
<location line="+309"/>
- <source>yaw</source>
- <translation>рысканье</translation>
+ <source>Yaw</source>
+ <translation>Рысканье</translation>
</message>
<message>
<location line="-200"/>
@@ -328,9 +341,22 @@ Exiting now.</source>
</message>
</context>
<context>
+ <name>new_file_dialog</name>
+ <message>
+ <location filename="../new_file_dialog.h" line="+42"/>
+ <source>File exists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This file already exists. Pick another name.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>options_dialog</name>
<message>
- <location filename="../options-dialog.ui" line="+14"/>
+ <location filename="../options-dialog.ui" line="+20"/>
<source>Options</source>
<translation>Настройки</translation>
</message>
@@ -420,12 +446,17 @@ Exiting now.</source>
<translation>Центрирование при запуске</translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+34"/>
+ <source>Never translate the application interface</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+20"/>
<source>Minimize to tray</source>
<translation>Настройка трея</translation>
</message>
<message>
- <location line="+220"/>
+ <location line="+234"/>
<location line="+69"/>
<location line="+53"/>
<source>°</source>
@@ -437,17 +468,17 @@ Exiting now.</source>
<translation>Включить</translation>
</message>
<message>
- <location line="-486"/>
+ <location line="-488"/>
<source>Minimize to tray on startup when enabled</source>
<translation>Сворачивать в трей при запуске</translation>
</message>
<message>
- <location line="-7"/>
+ <location line="-13"/>
<source>Enable tray</source>
<translation>Добавлять opentrack в трей</translation>
</message>
<message>
- <location line="+34"/>
+ <location line="+40"/>
<source>Camera</source>
<translation>Камера</translation>
</message>
@@ -462,20 +493,12 @@ Exiting now.</source>
<translation>Использование функции коррекции камеры</translation>
</message>
<message>
- <location line="+7"/>
- <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Specify an angle for off-center camera as a basis for which direction is which, avoiding axis interconnect.&lt;/p&gt;
-
-&lt;p&gt;You can derive it from the center pose as per the checkbox or specify it manually.&lt;/p&gt;
-
-&lt;p&gt;You can specify both, and it can be helpful to specify pitch when moving toward the screen results in translating upward.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Используйте данную настройку для того, чтобы скорректировать работу камеры в случае, когда она у Вас расположена не четко напротив клипсы.&lt;/p&gt;
-
-&lt;p&gt;Если у вас при зуме осьминожек убегает - то это то, что Вам нужно! Например: при &quot;убегании&quot; вниз добавьте тангажа.&lt;/p&gt;
-
-&lt;p&gt;You can specify both, and it can be helpful to specify pitch when moving toward the screen results in translating upward.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ <location line="+13"/>
+ <source>Specify an angle to rotate position tracking. It lets the tracker avoid moving on the X and Y axes when zooming, since camera isn&apos;t mounted perfectly in front of the model, but above or below.</source>
+ <translation>Используйте данную настройку для того, чтобы скорректировать работу камеры в случае, когда она у Вас расположена не четко напротив клипсы. Если у вас при зуме осьминожек убегает - то это то, что Вам нужно! Например: при &quot;убегании&quot; вниз добавьте тангажа.</translation>
</message>
<message>
- <location line="+38"/>
+ <location line="+34"/>
<location line="+206"/>
<location line="+381"/>
<location line="+47"/>
@@ -681,12 +704,12 @@ Exiting now.</source>
<message>
<location line="-158"/>
<source>Destination</source>
- <translation>Игровая ось:</translation>
+ <translation>Игровая ось</translation>
</message>
<message>
<location line="+28"/>
<source>Source</source>
- <translation>Исходная ось:</translation>
+ <translation>Исходная ось</translation>
</message>
<message>
<location line="+184"/>
diff --git a/gui/main-window.cpp b/gui/main-window.cpp
index d3e0baa8..d760783b 100644
--- a/gui/main-window.cpp
+++ b/gui/main-window.cpp
@@ -42,7 +42,14 @@ MainWindow::MainWindow() :
menu_action_mappings(&tray_menu)
{
ui.setupUi(this);
- setFixedSize(size());
+
+ {
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ adjustSize();
+ setFixedSize(size());
+ setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | windowFlags());
+ }
+
updateButtonState(false, false);
if (group::ini_directory().size() == 0)
@@ -566,19 +573,21 @@ bool mk_dialog(mem<dylib> lib, ptr<t>& orig)
{
if (orig && orig->isVisible())
{
- orig->show();
- orig->raise();
+ QDialog& d = *orig;
+ d.show();
+ d.raise();
return false;
}
if (lib && lib->Dialog)
{
t* dialog = reinterpret_cast<t*>(lib->Dialog());
- dialog->setWindowFlags(Qt::Dialog);
- // HACK: prevent stderr whining by adding a few pixels
- dialog->setFixedSize(dialog->size() + QSize(4, 4));
- dialog->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- dialog->show();
+ QDialog& d = *dialog;
+ d.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ d.adjustSize();
+ d.setFixedSize(d.size());
+ d.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | d.windowFlags());
+ d.show();
orig.reset(dialog);
@@ -613,18 +622,20 @@ static bool mk_window(ptr<t>* place, Args&&... params)
{
if (*place && (*place)->isVisible())
{
- (*place)->show();
- (*place)->raise();
+ QDialog& d = **place;
+ d.show();
+ d.raise();
return false;
}
else
{
*place = make_unique<t>(std::forward<Args>(params)...);
- (*place)->setWindowFlags(Qt::Dialog);
- // HACK: prevent stderr whining by adding a few pixels
- (*place)->setFixedSize((*place)->size() + QSize(4, 4));
- (*place)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- (*place)->show();
+ QDialog& d = **place;
+ d.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ d.adjustSize();
+ d.setFixedSize(d.size());
+ d.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | d.windowFlags());
+ d.show();
return true;
}
}
diff --git a/gui/main-window.ui b/gui/main-window.ui
index 8bf78efd..33ee99d3 100644
--- a/gui/main-window.ui
+++ b/gui/main-window.ui
@@ -342,7 +342,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TZ</string>
+ <string>Z</string>
</property>
</widget>
</item>
@@ -358,7 +358,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>pitch</string>
+ <string>Pitch</string>
</property>
</widget>
</item>
@@ -411,7 +411,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TY</string>
+ <string>Y</string>
</property>
</widget>
</item>
@@ -427,7 +427,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TX</string>
+ <string>X</string>
</property>
</widget>
</item>
@@ -474,7 +474,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>roll</string>
+ <string>Roll</string>
</property>
</widget>
</item>
@@ -490,7 +490,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>yaw</string>
+ <string>Yaw</string>
</property>
</widget>
</item>
@@ -704,7 +704,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TX</string>
+ <string>X</string>
</property>
</widget>
</item>
@@ -726,7 +726,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TY</string>
+ <string>Y</string>
</property>
</widget>
</item>
@@ -767,7 +767,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>pitch</string>
+ <string>Pitch</string>
</property>
</widget>
</item>
@@ -783,7 +783,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>roll</string>
+ <string>Roll</string>
</property>
</widget>
</item>
@@ -799,7 +799,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>yaw</string>
+ <string>Yaw</string>
</property>
</widget>
</item>
@@ -821,7 +821,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="text">
- <string>TZ</string>
+ <string>Z</string>
</property>
</widget>
</item>
diff --git a/gui/main.cpp b/gui/main.cpp
index de904f94..5cc041fb 100644
--- a/gui/main.cpp
+++ b/gui/main.cpp
@@ -141,10 +141,13 @@ main(int argc, char** argv)
add_win32_path();
#endif
- // QLocale::setDefault(QLocale("pl_PL")); // force i18n for testing
+ // QLocale::setDefault(QLocale("ru_RU")); // force i18n for testing
- (void) t.load(QLocale(), "", "", QCoreApplication::applicationDirPath() + "/i18n", ".qm");
- (void) QCoreApplication::installTranslator(&t);
+ if (!QSettings(OPENTRACK_ORG).value("disable-translation", false).toBool())
+ {
+ (void) t.load(QLocale(), "", "", QCoreApplication::applicationDirPath() + "/i18n", ".qm");
+ (void) QCoreApplication::installTranslator(&t);
+ }
do
{
diff --git a/gui/mapping-window.hpp b/gui/mapping-window.hpp
index 7648c994..06d969cc 100644
--- a/gui/mapping-window.hpp
+++ b/gui/mapping-window.hpp
@@ -4,11 +4,12 @@
#include "ui_mapping-window.h"
#include <QWidget>
+#include <QDialog>
#include <QShowEvent>
#include <QCloseEvent>
#include <QCheckBox>
-class MapWidget final : public QWidget
+class MapWidget final : public QDialog
{
Q_OBJECT
public:
diff --git a/gui/new_file_dialog.h b/gui/new_file_dialog.h
index 6ba3ede3..cd5ca528 100644
--- a/gui/new_file_dialog.h
+++ b/gui/new_file_dialog.h
@@ -39,7 +39,8 @@ private slots:
if (text == "" || text == ".ini" || QFile(options::group::ini_directory() + "/" + text).exists())
{
QMessageBox::warning(this,
- "File exists", "This file already exists. Pick another name.",
+ tr("File exists"),
+ tr("This file already exists. Pick another name."),
QMessageBox::Ok, QMessageBox::NoButton);
return;
}
diff --git a/gui/opentrack-res.qrc b/gui/opentrack-res.qrc
index 7b7fee54..1a3728cd 100644
--- a/gui/opentrack-res.qrc
+++ b/gui/opentrack-res.qrc
@@ -7,5 +7,6 @@
<file>images/no-feed.png</file>
<file>images/filter-16.png</file>
<file>images/tracking-not-started.png</file>
+ <file>images/english.png</file>
</qresource>
</RCC>
diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp
index 2f40e39f..bafddb57 100644
--- a/gui/options-dialog.cpp
+++ b/gui/options-dialog.cpp
@@ -14,7 +14,7 @@
#include <QDialog>
#include <QFileDialog>
-static QString kopts_to_string(const key_opts& kopts)
+QString OptionsDialog::kopts_to_string(const key_opts& kopts)
{
if (static_cast<QString>(kopts.guid) != "")
{
@@ -24,13 +24,18 @@ static QString kopts_to_string(const key_opts& kopts)
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);
+ return mm + tr("Joy button %1").arg(QString::number(btn));
}
if (static_cast<QString>(kopts.keycode) == "")
- return "None";
+ return tr("None");
return kopts.keycode;
}
+void OptionsDialog::set_disable_translation_state(bool value)
+{
+ QSettings(OPENTRACK_ORG).setValue("disable-translation", value);
+}
+
OptionsDialog::OptionsDialog(std::function<void(bool)> pause_keybindings) :
pause_keybindings(pause_keybindings)
{
@@ -84,6 +89,8 @@ OptionsDialog::OptionsDialog(std::function<void(bool)> pause_keybindings) :
tie_setting(main.tracklogging_enabled, ui.tracklogging_enabled);
+ ui.disable_translation->setChecked(QSettings(OPENTRACK_ORG).value("disable-translation", false).toBool());
+
struct tmp
{
key_opts& opt;
@@ -130,6 +137,7 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label)
d.setLayout(&l);
d.setFixedSize(QSize(500, 300));
d.setWindowFlags(Qt::Dialog);
+ setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | windowFlags());
d.setWindowModality(Qt::ApplicationModal);
connect(&k,
&KeyboardListener::key_pressed,
@@ -165,6 +173,7 @@ void OptionsDialog::doOK()
{
main.b->save();
ui.game_detector->save();
+ set_disable_translation_state(ui.disable_translation->isChecked());
close();
emit closing();
}
diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp
index b0e285e8..8c62b278 100644
--- a/gui/options-dialog.hpp
+++ b/gui/options-dialog.hpp
@@ -3,10 +3,11 @@
#include "ui_options-dialog.h"
#include "logic/shortcuts.h"
#include <QObject>
+#include <QDialog>
#include <QWidget>
#include <functional>
-class OptionsDialog : public QWidget
+class OptionsDialog : public QDialog
{
Q_OBJECT
signals:
@@ -18,8 +19,10 @@ private:
std::function<void(bool)> pause_keybindings;
Ui::options_dialog ui;
void closeEvent(QCloseEvent *) override { doCancel(); }
+ static QString kopts_to_string(const key_opts& opts);
private slots:
void doOK();
void doCancel();
void bind_key(key_opts &kopts, QLabel* label);
+ void set_disable_translation_state(bool value);
};
diff --git a/gui/options-dialog.ui b/gui/options-dialog.ui
index f6b8e3d6..2168fa8d 100644
--- a/gui/options-dialog.ui
+++ b/gui/options-dialog.ui
@@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
- <width>459</width>
- <height>615</height>
+ <width>450</width>
+ <height>599</height>
</rect>
</property>
+ <property name="minimumSize">
+ <size>
+ <width>450</width>
+ <height>0</height>
+ </size>
+ </property>
<property name="windowTitle">
<string>Options</string>
</property>
@@ -27,7 +33,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -337,6 +343,53 @@
</widget>
</item>
<item>
+ <widget class="QFrame" name="frame_3">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <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>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="disable_translation">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Never translate the application interface</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="opentrack-res.qrc">:/images/english.png</pixmap>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Minimize to tray</string>
@@ -353,6 +406,12 @@
</property>
<item>
<widget class="QCheckBox" name="trayp">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Enable tray</string>
</property>
@@ -360,6 +419,12 @@
</item>
<item>
<widget class="QCheckBox" name="tray_start">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Minimize to tray on startup when enabled</string>
</property>
@@ -378,7 +443,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>0</width>
+ <width>10</width>
<height>0</height>
</size>
</property>
@@ -406,12 +471,14 @@
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_17">
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Specify an angle for off-center camera as a basis for which direction is which, avoiding axis interconnect.&lt;/p&gt;
-
-&lt;p&gt;You can derive it from the center pose as per the checkbox or specify it manually.&lt;/p&gt;
-
-&lt;p&gt;You can specify both, and it can be helpful to specify pitch when moving toward the screen results in translating upward.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>Specify an angle to rotate position tracking. It lets the tracker avoid moving on the X and Y axes when zooming, since camera isn't mounted perfectly in front of the model, but above or below.</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
@@ -810,7 +877,7 @@
<item>
<widget class="QGroupBox" name="groupBox_">
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -1514,7 +1581,6 @@
<tabstop>bind_toggle_tracking</tabstop>
<tabstop>bind_restart_tracking</tabstop>
<tabstop>bind_tcomp_off_held</tabstop>
- <tabstop>center_at_startup</tabstop>
<tabstop>trayp</tabstop>
<tabstop>tray_start</tabstop>
<tabstop>use_center_as_translation_camera_offset</tabstop>
@@ -1549,7 +1615,9 @@
<tabstop>tcomp_src_pitch_disable</tabstop>
<tabstop>tcomp_src_roll_disable</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="opentrack-res.qrc"/>
+ </resources>
<connections/>
<slots>
<slot>startEngineClicked()</slot>
diff --git a/logic/tracker.cpp b/logic/tracker.cpp
index 8757e98e..a5892dd0 100644
--- a/logic/tracker.cpp
+++ b/logic/tracker.cpp
@@ -26,6 +26,7 @@
#endif
using namespace euler;
+using namespace gui_tracker_impl;
constexpr double Tracker::r2d;
constexpr double Tracker::d2r;
@@ -34,7 +35,8 @@ Tracker::Tracker(Mappings& m, SelectedLibraries& libs, TrackLogger& logger) :
m(m),
libs(libs),
logger(logger),
- backlog_time(0)
+ backlog_time(0),
+ tracking_started(false)
{
set(f_center, s.center_at_startup);
}
@@ -169,28 +171,23 @@ void Tracker::logic()
scaled_rotation.camera = get_camera_offset_matrix(c_div);
real_rotation.camera = get_camera_offset_matrix(1);
- scaled_rotation.rotation = scaled_rotation.camera * scaled_rotation.rotation;
- real_rotation.rotation = real_rotation.camera * real_rotation.rotation;
-
bool nanp = is_nan(value) || is_nan(scaled_rotation.rotation) || is_nan(real_rotation.rotation);
if (!nanp)
{
- bool can_center = false;
-
- if (get(f_center))
+ if (!tracking_started)
{
using std::fabs;
for (int i = 0; i < 6; i++)
if (fabs(newpose(i)) != 0)
{
- can_center = true;
+ tracking_started = true;
break;
}
}
- if (can_center)
+ if (get(f_center) && tracking_started)
{
set(f_center, false);
@@ -260,10 +257,7 @@ void Tracker::logic()
const euler_t rot = r2d * c_mult * rmat_to_euler(rotation);
euler_t pos = euler_t(&value[TX]) - t_center;
- if (s.use_camera_offset_from_centering)
- t_compensate((real_rotation.camera * real_rotation.rot_center).t(), pos, pos, false, false, false);
- else
- t_compensate(real_rotation.camera.t(), pos, pos, false, false, false);
+ t_compensate(real_rotation.camera.t(), pos, pos, false, false, false);
for (int i = 0; i < 3; i++)
{
@@ -452,25 +446,34 @@ void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const
void bits::set(bits::flags flag_, bool val_)
{
- unsigned b_(b);
const unsigned flag = unsigned(flag_);
- const unsigned val = unsigned(!!val_);
- while (!b.compare_exchange_weak(b_,
+ const unsigned val = unsigned(val_);
+
+ for (;;)
+ {
+ unsigned b_(b);
+ if (b.compare_exchange_weak(b_,
unsigned((b_ & ~flag) | (flag * val)),
std::memory_order_seq_cst,
std::memory_order_seq_cst))
- { /* empty */ }
+ break;
+ }
}
void bits::negate(bits::flags flag_)
{
- unsigned b_(b);
const unsigned flag = unsigned(flag_);
- while (!b.compare_exchange_weak(b_,
- (b_ & ~flag) | (flag & ~b_),
+
+ for (;;)
+ {
+ unsigned b_(b);
+
+ if (b.compare_exchange_weak(b_,
+ b_ ^ flag,
std::memory_order_seq_cst,
std::memory_order_seq_cst))
- { /* empty */ }
+ break;
+ }
}
bool bits::get(bits::flags flag)
diff --git a/logic/tracker.h b/logic/tracker.h
index b9012910..4a5bdf50 100644
--- a/logic/tracker.h
+++ b/logic/tracker.h
@@ -29,6 +29,8 @@
#include "export.hpp"
+namespace gui_tracker_impl {
+
using Pose = Mat<double, 6, 1>;
struct bits
@@ -86,6 +88,8 @@ private:
long backlog_time;
+ bool tracking_started;
+
double map(double pos, Map& axis);
void logic();
void t_compensate(const rmat& rmat, const euler_t& ypr, euler_t& output,
@@ -115,3 +119,7 @@ public:
void zero() { negate(f_zero); }
void toggle_enabled() { negate(f_enabled); }
};
+
+} // ns impl
+
+using gui_tracker_impl::Tracker;
diff --git a/migration/20160917_00-accela.cpp b/migration/20160917_00-accela.cpp
index 60104c24..aefe6dda 100644
--- a/migration/20160917_00-accela.cpp
+++ b/migration/20160917_00-accela.cpp
@@ -94,7 +94,7 @@ struct move_accela_to_sliders : migration
tmp = val;
}
- value<slider_value> tmp(new_b, slider_name, slider_value(-1e6, s.rot_nonlinearity->min(), s.rot_nonlinearity->max()));
+ value<slider_value> tmp(new_b, slider_name, slider_value(-1e6, s.rot_nonlinearity().min(), s.rot_nonlinearity().max()));
tmp = old_b->contains(slider_name)
? old_b->get<slider_value>(slider_name)
: slider_value(1.1, 1, 1.75);
diff --git a/options/bundle.cpp b/options/bundle.cpp
index 96291476..74e08eb9 100644
--- a/options/bundle.cpp
+++ b/options/bundle.cpp
@@ -199,12 +199,12 @@ OPENTRACK_OPTIONS_EXPORT bundler& singleton()
} // end options::detail
-OPENTRACK_OPTIONS_EXPORT std::shared_ptr<bundle_type> make_bundle(const QString& name)
+OPENTRACK_OPTIONS_EXPORT std::shared_ptr<bundle_> make_bundle(const QString& name)
{
if (name.size())
return detail::singleton().make_bundle(name);
else
- return std::make_shared<bundle_type>(QStringLiteral(""));
+ return std::make_shared<bundle_>(QStringLiteral(""));
}
QMutex* options::detail::bundle::get_mtx() const { return mtx; }
diff --git a/options/bundle.hpp b/options/bundle.hpp
index 2d7fa7f4..5bbe6f60 100644
--- a/options/bundle.hpp
+++ b/options/bundle.hpp
@@ -103,9 +103,9 @@ public:
OPENTRACK_OPTIONS_EXPORT bundler& singleton();
}
-using bundle_type = detail::bundle;
-using bundle = std::shared_ptr<bundle_type>;
+using bundle_ = detail::bundle;
+using bundle = std::shared_ptr<bundle_>;
-OPENTRACK_OPTIONS_EXPORT std::shared_ptr<bundle_type> make_bundle(const QString& name);
+OPENTRACK_OPTIONS_EXPORT std::shared_ptr<bundle_> make_bundle(const QString& name);
}
diff --git a/options/options.hpp b/options/options.hpp
index ebc480f3..c1eed97c 100644
--- a/options/options.hpp
+++ b/options/options.hpp
@@ -6,6 +6,10 @@
*/
#pragma once
+#include "compat/ndebug-guard.hpp"
+
+#include "compat/util.hpp"
+
#include "defs.hpp"
#include "bundle.hpp"
#include "group.hpp"
diff --git a/options/tie.hpp b/options/tie.hpp
index accd958e..942c6098 100644
--- a/options/tie.hpp
+++ b/options/tie.hpp
@@ -31,40 +31,23 @@ inline
typename std::enable_if<std::is_enum<t>::value>::type
tie_setting(value<t>& v, QComboBox* cb)
{
- cb->setCurrentIndex(cb->findData((unsigned)static_cast<t>(v)));
+ cb->setCurrentIndex(cb->findData(int(static_cast<t>(v))));
v = static_cast<t>(cb->currentData().toInt());
- std::vector<int> enum_cases(unsigned(cb->count()));
-
- for (int i = 0; i < cb->count(); i++)
- enum_cases[i] = cb->itemData(i).toInt();
-
base_value::connect(cb,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
&v,
- [&, enum_cases](int idx) {
- if (idx < 0 || idx >= (int)enum_cases.size())
- v = static_cast<t>(-1);
- else
- v = static_cast<t>(enum_cases[idx]);
+ [&v, cb](int idx)
+ {
+ run_in_thread_sync(cb,
+ [&]() {
+ v = static_cast<t>(cb->itemData(idx).toInt());
+ });
},
v.DIRECT_CONNTYPE);
- base_value::connect(&v,
- static_cast<void (base_value::*)(int) const>(&base_value::valueChanged),
- cb,
- [&, enum_cases](int val) {
- for (unsigned i = 0; i < enum_cases.size(); i++)
- {
- if (val == enum_cases[i])
- {
- cb->setCurrentIndex(i);
- return;
- }
- }
- cb->setCurrentIndex(-1);
- },
- // don't change or else hatire crashes -sh 20160917
- Qt::QueuedConnection);
+ base_value::connect(&v, static_cast<void (base_value::*)(int) const>(&base_value::valueChanged),
+ cb, [cb](int x) { cb->setCurrentIndex(cb->findData(x)); },
+ v.SAFE_CONNTYPE);
}
template<>
@@ -144,27 +127,36 @@ inline void tie_setting(value<int>& v, QTabWidget* t)
template<>
inline void tie_setting(value<slider_value>& v, QSlider* w)
{
- // we can't get these at runtime since signals cross threads
- const int q_min = w->minimum();
- const int q_max = w->maximum();
+ {
+ const int q_min = w->minimum();
+ const int q_max = w->maximum();
- w->setValue(v->to_slider_pos(q_min, q_max));
- v = v->update_from_slider(w->value(), q_min, q_max);
+ w->setValue(v().to_slider_pos(q_min, q_max));
+ v = v().update_from_slider(w->value(), q_min, q_max);
+ }
base_value::connect(w,
&QSlider::valueChanged,
&v,
- [=, &v](int pos) {
- v = v->update_from_slider(pos, q_min, q_max);
- w->setValue(v->to_slider_pos(q_min, q_max));
+ [=, &v](int pos)
+ {
+ run_in_thread_sync(w, [&]()
+ {
+ const int q_min = w->minimum();
+ const int q_max = w->maximum();
+ v = v().update_from_slider(pos, q_min, q_max);
+ w->setValue(v().to_slider_pos(q_min, q_max));
+ });
},
v.DIRECT_CONNTYPE);
base_value::connect(&v,
static_cast<void(base_value::*)(double) const>(&base_value::valueChanged),
w,
[=, &v](double) {
- w->setValue(v->to_slider_pos(q_min, q_max));
- v = v->update_from_slider(w->value(), q_min, q_max);
+ const int q_min = w->minimum();
+ const int q_max = w->maximum();
+ w->setValue(v().to_slider_pos(q_min, q_max));
+ v = v().update_from_slider(w->value(), q_min, q_max);
},
v.SAFE_CONNTYPE);
}
diff --git a/options/value.hpp b/options/value.hpp
index 3c45bf15..01746d67 100644
--- a/options/value.hpp
+++ b/options/value.hpp
@@ -166,14 +166,6 @@ public:
{
}
- t get() const
- {
- t val = b->contains(self_name)
- ? static_cast<t>(b->get<element_type>(self_name))
- : def;
- return detail::value_get_traits<t>::get(val, def);
- }
-
t default_value() const
{
return def;
@@ -191,13 +183,20 @@ public:
emit valueChanged(static_cast<detail::value_type_t<t>>(get()));
}
- element_type const* operator->() const
+ element_type operator()() const
{
- static thread_local element_type last;
- last = get();
- return &last;
+ return get();
}
+
private:
+ t get() const
+ {
+ t val = b->contains(self_name)
+ ? static_cast<t>(b->get<element_type>(self_name))
+ : def;
+ return detail::value_get_traits<t>::get(val, def);
+ }
+
const t def;
};
diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp
index 01a6b74b..023e1926 100644
--- a/pose-widget/glwidget.cpp
+++ b/pose-widget/glwidget.cpp
@@ -15,7 +15,7 @@
#include <QDebug>
using namespace euler;
-using namespace impl;
+using namespace pose_widget_impl;
GLWidget::GLWidget(QWidget *parent) : QWidget(parent)
{
diff --git a/pose-widget/glwidget.h b/pose-widget/glwidget.h
index f98b4628..ae06e5c5 100644
--- a/pose-widget/glwidget.h
+++ b/pose-widget/glwidget.h
@@ -19,7 +19,7 @@
# define POSE_WIDGET_EXPORT Q_DECL_IMPORT
#endif
-namespace impl {
+namespace pose_widget_impl {
using num = float;
using vec3 = Mat<num, 3, 1>;
@@ -52,4 +52,4 @@ private:
}
-using impl::GLWidget;
+using pose_widget_impl::GLWidget;
diff --git a/proto-ft/lang/ru_RU.ts b/proto-ft/lang/ru_RU.ts
new file mode 100644
index 00000000..e5984c77
--- /dev/null
+++ b/proto-ft/lang/ru_RU.ts
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>FTControls</name>
+ <message>
+ <location filename="../ftnoir_protocol_ft_dialog.cpp" line="+53"/>
+ <source>Select the desired NPClient DLL</source>
+ <translation>Укажите путь до файла NPClient DLL </translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Dll file (*.dll);;All Files (*)</source>
+ <translation></translation>
+ </message>
+</context>
+<context>
+ <name>UICFTControls</name>
+ <message>
+ <location filename="../ftnoir_ftcontrols.ui" line="+32"/>
+ <source>freetrack protocol settings</source>
+ <translation>Настройки протокола Freetrack</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Select interface</source>
+ <translation>Выберите интерфейс</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Disable one of the protocols if game is confused by presence of both at the same time.</source>
+ <translation>Отключите один из протоколов в случае, если при включении обоих интерфейсов игра не корректно определяет их.</translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>TIRViews</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>Memory hacks</source>
+ <translation>Взлом памяти</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Only for very old and buggy old games such as CFS3.</source>
+ <translation>Только для очень старых игр, например таких как CFS3 </translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Repair NPClient location</source>
+ <translation>Решение проблем с расположением NPClient&apos;а </translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Locate DLL</source>
+ <translation>Укажите DLL</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Replace the registry entry if you want to use other software with the NPClient protocol and it doesn&apos;t work automatically.
+
+Starting tracking will again overwrite the DLL locations.</source>
+ <translation>Заменить запись в реестре расположения библиотеки NPClient.dll если протокол не работает в автоматическом режиме.
+
+Запуск отслеживания в opentrack приведет к перезаписи расположения DLL-файла.</translation>
+ </message>
+ <message>
+ <location line="+28"/>
+ <source>Disable tracking for games on exit</source>
+ <translation>Отключить работы интерфейсов после закрытия Opentrack </translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Disable on program exit</source>
+ <translation>Отключить по закрытию</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Use this for games that disable mouselook when opentrack isn&apos;t running, and you&apos;re not running opentrack that much. To use opentrack with this option you need to start it before the games to have it work at all.</source>
+ <translation>По умолчанию протокол opentrack&apos;а работает постоянно, благодаря чему возможно запускать opentrack на любой стадии загрузки игр. При активации данного пункта необходимо запускать opentrack перед запуском игры.</translation>
+ </message>
+</context>
+<context>
+ <name>freetrackDll</name>
+ <message>
+ <location filename="../ftnoir_protocol_ft.h" line="+96"/>
+ <source>freetrack 2.0 Enhanced</source>
+ <translation></translation>
+ </message>
+</context>
+</TS>
diff --git a/settings/facetracknoir supported games.csv b/settings/facetracknoir supported games.csv
index a4b68554..1be3b350 100644
--- a/settings/facetracknoir supported games.csv
+++ b/settings/facetracknoir supported games.csv
@@ -619,3 +619,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
753;Synergy Integration;FreeTrack20;V160;;;20140;02F185EAE564E30DA1B600
754;Bus Simulator 16;FreeTrack20;V170;;;4775;02F2E24441D3178B43DB00
755;Subnautica;FreeTrack20;V170;;;4850;02F3F92B360B97FA550A00
+756;DGA;FreeTrack20;V160;;;20145;02F4106F2B3FE0E58AE000
+757;ED Science Lab;FreeTrack20;V160;;;20160;02F518B03B53A0A9A32600
+758;F1 2016;FreeTrack20;V160;;;8111;02F62FF3D6F90370C8A300
+759;SW Plugin;FreeTrack20;V160;;;20155;02F7E45153116EF485A500
+760;Vector 36;FreeTrack20;V160;;;5325;02F8C318595317B9FF3B00
diff --git a/spline-widget/spline-widget.cpp b/spline-widget/spline-widget.cpp
index 45a90c6a..f10995d4 100644
--- a/spline-widget/spline-widget.cpp
+++ b/spline-widget/spline-widget.cpp
@@ -101,7 +101,8 @@ void spline_widget::drawBackground()
_background = QPixmap(width(), height());
QPainter painter(&_background);
- painter.fillRect(rect(), QColor::fromRgb(204, 204, 204));
+
+ painter.fillRect(rect(), QWidget::palette().color(QWidget::backgroundRole()));
QColor bg_color(112, 154, 209);
if (!isEnabled() && !_preview_only)
@@ -308,11 +309,11 @@ void spline_widget::drawLine(QPainter& painter, const QPoint& start, const QPoin
void spline_widget::mousePressEvent(QMouseEvent *e)
{
- if (!_config || !isEnabled())
- return;
-
- if (!is_in_bounds(e->pos()))
+ if (!_config || !isEnabled() || !is_in_bounds(e->pos()))
+ {
+ clearFocus();
return;
+ }
const int point_pixel_closeness_limit = get_closeness_limit();
@@ -384,6 +385,13 @@ void spline_widget::mousePressEvent(QMouseEvent *e)
void spline_widget::mouseMoveEvent(QMouseEvent *e)
{
+ if (_preview_only && _config)
+ {
+ show_tooltip(e->pos());
+ clearFocus();
+ return;
+ }
+
if (!_config || !isEnabled() || !isActiveWindow() || (moving_control_point_idx != -1 && !hasFocus()))
{
clearFocus();
@@ -488,11 +496,15 @@ int spline_widget::get_closeness_limit()
return std::max(iround(snap_x * c.x()), 1);
}
-void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_, const QString& prefix)
+void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_)
{
const QPointF value = QPoint(0, 0) == value_ ? pixel_coord_to_point(pos) : value_;
double x = value.x(), y = value.y();
+
+ if (_preview_only)
+ y = _config->get_value_no_save(x);
+
const int x_ = iround(x), y_ = iround(y);
using std::fabs;
@@ -508,7 +520,7 @@ void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_, const
const QPoint pix(int(pos.x()) + add_x, int(pos.y()) + add_y);
QToolTip::showText(mapToGlobal(pix),
- QStringLiteral("value: %1%2x%3").arg(prefix).arg(x).arg(y),
+ QStringLiteral("value: %1x%2").arg(x).arg(y),
this,
rect(),
0);
diff --git a/spline-widget/spline-widget.hpp b/spline-widget/spline-widget.hpp
index d52e249c..921f44a2 100644
--- a/spline-widget/spline-widget.hpp
+++ b/spline-widget/spline-widget.hpp
@@ -32,6 +32,8 @@ class OPENTRACK_SPLINE_EXPORT spline_widget final : public QWidget
Q_OBJECT
Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
Q_PROPERTY(bool is_preview_only READ is_preview_only WRITE set_preview_only)
+ Q_PROPERTY(int x_step READ x_step WRITE set_x_step)
+ Q_PROPERTY(int y_step READ y_step WRITE set_y_step)
using points_t = spline::points_t;
public:
@@ -47,6 +49,12 @@ public:
void force_redraw();
void set_preview_only(bool val);
bool is_preview_only() const;
+
+ double x_step() { return _x_step; }
+ double y_step() { return _y_step; }
+ void set_x_step(double val) { _x_step = val; }
+ void set_y_step(double val) { _y_step = val; }
+
void set_snap(double x, double y) { snap_x = x; snap_y = y; }
void get_snap(double& x, double& y) const { x = snap_x; y = snap_y; }
protected slots:
@@ -57,7 +65,7 @@ protected slots:
void reload_spline();
private:
int get_closeness_limit();
- void show_tooltip(const QPoint& pos, const QPointF& value = QPointF(0, 0), const QString& prefix = QStringLiteral(""));
+ void show_tooltip(const QPoint& pos, const QPointF& value = QPointF(0, 0));
bool is_in_bounds(const QPoint& pos) const;
void drawBackground();
@@ -89,6 +97,7 @@ private:
QMetaObject::Connection connection;
double snap_x, snap_y;
+ double _x_step, _y_step;
int moving_control_point_idx;
bool _draw_function, _preview_only;
diff --git a/spline-widget/spline.cpp b/spline-widget/spline.cpp
index 4742bdc8..57817d40 100644
--- a/spline-widget/spline.cpp
+++ b/spline-widget/spline.cpp
@@ -29,7 +29,8 @@ spline::spline(qreal maxx, qreal maxy, const QString& name) :
_mutex(QMutex::Recursive),
max_x(maxx),
max_y(maxy),
- activep(false)
+ activep(false),
+ validp(false)
{
set_bundle(options::make_bundle(name));
}
@@ -62,7 +63,7 @@ void spline::removeAllPoints()
{
QMutexLocker l(&_mutex);
s->points = points_t();
- update_interp_data();
+ validp = false;
}
void spline::setMaxInput(qreal max_input)
@@ -123,6 +124,12 @@ bool spline::getLastPoint(QPointF& point)
float spline::getValueInternal(int x)
{
+ if (!validp)
+ {
+ update_interp_data();
+ validp = true;
+ }
+
float sign = x < 0 ? -1 : 1;
x = std::abs(x);
float ret;
@@ -247,7 +254,7 @@ void spline::removePoint(int i)
{
points.erase(points.begin() + i);
s->points = points;
- update_interp_data();
+ validp = false;
}
}
@@ -259,7 +266,12 @@ void spline::addPoint(QPointF pt)
points.push_back(pt);
std::stable_sort(points.begin(), points.end(), sort_fn);
s->points = points;
- update_interp_data();
+ validp = false;
+}
+
+void spline::addPoint(double x, double y)
+{
+ addPoint(QPointF(x, y));
}
void spline::movePoint(int idx, QPointF pt)
@@ -274,7 +286,7 @@ void spline::movePoint(int idx, QPointF pt)
// we don't allow points to be reordered, but sort due to possible caller logic error
std::stable_sort(points.begin(), points.end(), sort_fn);
s->points = points;
- update_interp_data();
+ validp = false;
}
}
@@ -287,7 +299,7 @@ QList<QPointF> spline::getPoints() const
int spline::get_point_count() const
{
QMutexLocker foo(&_mutex);
- return s->points.get().size();
+ return s->points().size();
}
void spline::reload()
@@ -322,7 +334,7 @@ void spline::set_bundle(bundle b)
if (b)
{
- connection = QObject::connect(b.get(), &bundle_type::changed,
+ connection = QObject::connect(b.get(), &bundle_::changed,
s.get(), [&]() {
// we're holding the mutex to allow signal disconnection in spline dtor
// before this slot gets called for the next time
@@ -389,8 +401,7 @@ void spline::recompute()
last_input_value = QPointF(0, 0);
activep = false;
-
- update_interp_data();
+ validp = false;
}
// the return value is only safe to use with no spline::set_bundle calls
diff --git a/spline-widget/spline.hpp b/spline-widget/spline.hpp
index b79263ec..adabd33c 100644
--- a/spline-widget/spline.hpp
+++ b/spline-widget/spline.hpp
@@ -56,12 +56,13 @@ class OPENTRACK_SPLINE_EXPORT spline final
std::vector<float> data;
using interp_data_t = decltype(data);
- static constexpr int value_count = 2048;
+ static constexpr int value_count = 4096;
MyMutex _mutex;
QPointF last_input_value;
qreal max_x, max_y;
volatile bool activep;
+ bool validp;
public:
using settings = spline_detail::settings;
@@ -87,6 +88,7 @@ public:
void removeAllPoints();
void addPoint(QPointF pt);
+ void addPoint(double x, double y);
void movePoint(int idx, QPointF pt);
QList<QPointF> getPoints() const;
void setMaxInput(qreal MaxInput);
@@ -99,6 +101,6 @@ public:
mem<settings> get_settings();
mem<const settings> get_settings() const;
- using points_t = decltype(s->points.get());
+ using points_t = decltype(s->points());
int get_point_count() const;
};
diff --git a/tracker-aruco/CMakeLists.txt b/tracker-aruco/CMakeLists.txt
index c0b50bee..d68b8f59 100644
--- a/tracker-aruco/CMakeLists.txt
+++ b/tracker-aruco/CMakeLists.txt
@@ -1,7 +1,9 @@
-find_package(OpenCV 3.0 QUIET COMPONENTS ${opencv-modules})
-set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Aruco paper marker tracker static library path")
-if(SDK_ARUCO_LIBPATH AND OpenCV_FOUND)
- opentrack_boilerplate(opentrack-tracker-aruco)
- target_link_libraries(opentrack-tracker-aruco opentrack-cv ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
- target_include_directories(opentrack-tracker-aruco SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})
+find_package(OpenCV 3.0 QUIET)
+if(OpenCV_FOUND)
+ set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Aruco paper marker tracker static library path")
+ if(SDK_ARUCO_LIBPATH)
+ opentrack_boilerplate(opentrack-tracker-aruco)
+ target_link_libraries(opentrack-tracker-aruco opentrack-cv ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
+ target_include_directories(opentrack-tracker-aruco SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})
+ endif()
endif()
diff --git a/tracker-aruco/aruco-trackercontrols.ui b/tracker-aruco/aruco-trackercontrols.ui
index 1479b2e7..7d7be812 100644
--- a/tracker-aruco/aruco-trackercontrols.ui
+++ b/tracker-aruco/aruco-trackercontrols.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>dialog_aruco</class>
- <widget class="QWidget" name="dialog_aruco">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
@@ -103,7 +103,7 @@
</property>
<item>
<property name="text">
- <string notr="true">Default</string>
+ <string>Default</string>
</property>
</item>
<item>
@@ -145,10 +145,10 @@
<locale language="English" country="UnitedStates"/>
</property>
<property name="minimum">
- <number>10</number>
+ <number>35</number>
</property>
<property name="maximum">
- <number>180</number>
+ <number>90</number>
</property>
</widget>
</item>
@@ -172,11 +172,6 @@
</item>
<item>
<property name="text">
- <string>320x200</string>
- </property>
- </item>
- <item>
- <property name="text">
<string>Default (not recommended!)</string>
</property>
</item>
diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp
index 8edb8cf5..02b1f830 100644
--- a/tracker-aruco/ftnoir_tracker_aruco.cpp
+++ b/tracker-aruco/ftnoir_tracker_aruco.cpp
@@ -5,13 +5,13 @@
* copyright notice and this permission notice appear in all copies.
*/
+#include "cv/video-widget.hpp"
#include "ftnoir_tracker_aruco.h"
-#include "api/plugin-api.hpp"
-#include "compat/camera-names.hpp"
#include "cv/video-property-page.hpp"
+#include "compat/camera-names.hpp"
+#include "compat/sleep.hpp"
#include <opencv2/core.hpp>
-#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
@@ -30,64 +30,56 @@ struct resolution_tuple
int height;
};
-static resolution_tuple resolution_choices[] =
+static constexpr const resolution_tuple resolution_choices[] =
{
{ 640, 480 },
{ 320, 240 },
- { 320, 200 },
{ 0, 0 }
};
-tracker_aruco::tracker_aruco() :
- stop(false),
- layout(nullptr),
- videoWidget(nullptr),
+constexpr const double aruco_tracker::RC;
+constexpr const float aruco_tracker::size_min;
+constexpr const float aruco_tracker::size_max;
+
+aruco_tracker::aruco_tracker() :
+ fps(0),
obj_points(4),
- intrinsics(decltype(intrinsics)::eye()),
- dist_coeffs(decltype(dist_coeffs)::zeros()),
- rmat(decltype(rmat)::eye()),
+ intrinsics(cv::Matx33d::eye()),
+ rmat(cv::Matx33d::eye()),
roi_points(4),
last_roi(65535, 65535, 0, 0),
- freq(cv::getTickFrequency()), // XXX change to timer.hpp
- cur_fps(0)
+ stop(false)
{
// param 2 ignored for Otsu thresholding. it's required to use our fork of Aruco.
- detector.setThresholdParams(5, -1);
+ detector.setThresholdParams(7, -1);
detector.setDesiredSpeed(3);
detector._thresMethod = aruco::MarkerDetector::FIXED_THRES;
}
-tracker_aruco::~tracker_aruco()
+aruco_tracker::~aruco_tracker()
{
stop = true;
wait();
- if (videoWidget)
- delete videoWidget;
- if(layout)
- delete layout;
+ // fast start/stop causes breakage
+ portable::sleep(1000);
camera.release();
}
-void tracker_aruco::start_tracker(QFrame* videoframe)
+void aruco_tracker::start_tracker(QFrame* videoframe)
{
videoframe->show();
- videoWidget = new cv_video_widget(videoframe);
- QHBoxLayout* layout_ = new QHBoxLayout();
- layout_->setContentsMargins(0, 0, 0, 0);
- layout_->addWidget(videoWidget);
- if (videoframe->layout())
- delete videoframe->layout();
- videoframe->setLayout(layout_);
+ videoWidget = qptr<cv_video_widget>(videoframe);
+ layout = qptr<QHBoxLayout>();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(videoWidget.data());
+ videoframe->setLayout(layout.data());
videoWidget->show();
start();
for (int i = 0; i < 6; i++)
pose[i] = 0;
- layout = layout_;
}
-#define HT_PI M_PI
-
-void tracker_aruco::getRT(cv::Matx33d& r_, cv::Vec3d& t_)
+void aruco_tracker::getRT(cv::Matx33d& r_, cv::Vec3d& t_)
{
QMutexLocker l(&mtx);
@@ -95,17 +87,14 @@ void tracker_aruco::getRT(cv::Matx33d& r_, cv::Vec3d& t_)
t_ = t;
}
-bool tracker_aruco::detect_with_roi()
+bool aruco_tracker::detect_with_roi()
{
if (last_roi.width > 1 && last_roi.height > 1)
{
- float min = std::min(1.f, std::max(.01f, size_min * grayscale.cols / last_roi.width));
- float max = std::max(.01f, std::min(1.f, size_max * grayscale.cols / last_roi.width));
- detector.setMinMaxSize(min, max);
+ detector.setMinMaxSize(clamp(size_min * grayscale.cols / last_roi.width, .01f, 1.f),
+ clamp(size_max * grayscale.cols / last_roi.width, .01f, 1.f));
- cv::Mat grayscale_ = grayscale(last_roi);
-
- detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false);
+ detector.detect(grayscale(last_roi), markers, cv::Mat(), cv::Mat(), -1, false);
if (markers.size() == 1 && markers[0].size() == 4)
{
@@ -124,14 +113,14 @@ bool tracker_aruco::detect_with_roi()
return false;
}
-bool tracker_aruco::detect_without_roi()
+bool aruco_tracker::detect_without_roi()
{
detector.setMinMaxSize(size_min, size_max);
detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false);
return markers.size() == 1 && markers[0].size() == 4;
}
-bool tracker_aruco::open_camera()
+bool aruco_tracker::open_camera()
{
int rint = s.resolution;
if (rint < 0 || rint >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
@@ -180,7 +169,7 @@ bool tracker_aruco::open_camera()
return true;
}
-void tracker_aruco::set_intrinsics()
+void aruco_tracker::set_intrinsics()
{
const int w = grayscale.cols, h = grayscale.rows;
const double diag_fov = static_cast<int>(s.fov) * M_PI / 180.;
@@ -195,16 +184,20 @@ void tracker_aruco::set_intrinsics()
intrinsics(1, 2) = grayscale.rows/2;
}
-void tracker_aruco::update_fps(double alpha)
+void aruco_tracker::update_fps()
{
- std::uint64_t time = std::uint64_t(cv::getTickCount());
- const double dt = std::max(0., (time - last_time) / freq);
- last_time = time;
+ const double dt = fps_timer.elapsed_seconds();
+ fps_timer.start();
+ const double alpha = dt/(dt + RC);
- cur_fps = cur_fps * alpha + (1-alpha) * (fabs(dt) < 1e-6 ? 0 : 1./dt);
+ if (dt > 1e-3)
+ {
+ fps *= 1 - alpha;
+ fps += alpha * (1./dt + .8);
+ }
}
-void tracker_aruco::draw_ar(bool ok)
+void aruco_tracker::draw_ar(bool ok)
{
if (ok)
{
@@ -213,13 +206,13 @@ void tracker_aruco::draw_ar(bool ok)
cv::line(frame, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), 2, 8);
}
- char buf[32];
- ::snprintf(buf, sizeof(buf)-1, "Hz: %d", (int)(unsigned short)cur_fps);
+ char buf[9];
+ ::snprintf(buf, sizeof(buf)-1, "Hz: %d", clamp(int(fps), 0, 9999));
buf[sizeof(buf)-1] = '\0';
cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar(0, 255, 0), 1);
}
-void tracker_aruco::clamp_last_roi()
+void aruco_tracker::clamp_last_roi()
{
if (last_roi.x < 0)
last_roi.x = 0;
@@ -242,7 +235,7 @@ void tracker_aruco::clamp_last_roi()
last_roi.height -= last_roi.y;
}
-void tracker_aruco::set_points()
+void aruco_tracker::set_points()
{
using f = float;
const f hx = f(s.headpos_x), hy = f(s.headpos_y), hz = f(s.headpos_z);
@@ -257,19 +250,18 @@ void tracker_aruco::set_points()
obj_points[x4] = cv::Point3f(-size + hx, size + hy, 0 + hz);
}
-void tracker_aruco::draw_centroid()
+void aruco_tracker::draw_centroid()
{
repr2.clear();
static const std::vector<cv::Point3f> centroid { cv::Point3f(0, 0, 0) };
- cv::projectPoints(centroid, rvec, tvec, intrinsics, dist_coeffs, repr2);
+ cv::projectPoints(centroid, rvec, tvec, intrinsics, cv::noArray(), repr2);
- auto s = cv::Scalar(255, 0, 255);
- cv::circle(frame, repr2[0], 4, s, -1);
+ cv::circle(frame, repr2[0], 4, cv::Scalar(255, 0, 255), -1);
}
-void tracker_aruco::set_last_roi()
+void aruco_tracker::set_last_roi()
{
roi_projection.clear();
@@ -281,12 +273,12 @@ void tracker_aruco::set_last_roi()
roi_points[i] = pt * c_search_window;
}
- cv::projectPoints(roi_points, rvec, tvec, intrinsics, dist_coeffs, roi_projection);
+ cv::projectPoints(roi_points, rvec, tvec, intrinsics, cv::noArray(), roi_projection);
set_roi_from_projection();
}
-void tracker_aruco::set_rmat()
+void aruco_tracker::set_rmat()
{
cv::Rodrigues(rvec, rmat);
@@ -305,7 +297,7 @@ void tracker_aruco::set_rmat()
t = cv::Vec3d(tvec[0], -tvec[1], tvec[2]);
}
-void tracker_aruco::set_roi_from_projection()
+void aruco_tracker::set_roi_from_projection()
{
last_roi = cv::Rect(color.cols-1, color.rows-1, 0, 0);
@@ -328,7 +320,7 @@ void tracker_aruco::set_roi_from_projection()
clamp_last_roi();
}
-void tracker_aruco::run()
+void aruco_tracker::run()
{
cv::setNumThreads(0);
@@ -340,7 +332,7 @@ void tracker_aruco::run()
if (!open_camera())
return;
- last_time = std::uint64_t(cv::getTickCount());
+ fps_timer.start();
while (!stop)
{
@@ -357,7 +349,7 @@ void tracker_aruco::run()
set_intrinsics();
- update_fps(alpha_);
+ update_fps();
markers.clear();
@@ -367,10 +359,7 @@ void tracker_aruco::run()
{
set_points();
- if (!cv::solvePnP(obj_points, markers[0], intrinsics, dist_coeffs, rvec, tvec, false, cv::SOLVEPNP_DLS))
- goto fail;
-
- if (!cv::solvePnP(obj_points, markers[0], intrinsics, dist_coeffs, rvec, tvec, true, cv::SOLVEPNP_ITERATIVE))
+ if (!cv::solvePnP(obj_points, markers[0], intrinsics, cv::noArray(), rvec, tvec, false, cv::SOLVEPNP_ITERATIVE))
goto fail;
set_last_roi();
@@ -389,19 +378,19 @@ fail:
}
}
-void tracker_aruco::data(double *data)
+void aruco_tracker::data(double *data)
{
QMutexLocker lck(&mtx);
data[Yaw] = pose[Yaw];
data[Pitch] = pose[Pitch];
data[Roll] = pose[Roll];
- data[TX] = pose[TX] * .5;
- data[TY] = pose[TY] * .5;
+ data[TX] = pose[TX];
+ data[TY] = pose[TY];
data[TZ] = pose[TZ];
}
-dialog_aruco::dialog_aruco()
+aruco_dialog::aruco_dialog()
{
tracker = nullptr;
calib_timer.setInterval(250);
@@ -419,34 +408,15 @@ dialog_aruco::dialog_aruco()
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
connect(ui.btn_calibrate, SIGNAL(clicked()), this, SLOT(toggleCalibrate()));
connect(this, SIGNAL(destroyed()), this, SLOT(cleanupCalib()));
-
connect(&calib_timer, SIGNAL(timeout()), this, SLOT(update_tracker_calibration()));
- connect(ui.cameraName, &QComboBox::currentTextChanged, this, &dialog_aruco::set_camera_settings_available);
- set_camera_settings_available(ui.cameraName->currentText());
- connect(ui.camera_settings, &QPushButton::clicked, this, &dialog_aruco::show_camera_settings);
-}
+ connect(ui.camera_settings, SIGNAL(clicked()), this, SLOT(camera_settings()));
+ connect(&s.camera_name, SIGNAL(valueChanged(const QString&)), this, SLOT(update_camera_settings_state(const QString&)));
-void dialog_aruco::set_camera_settings_available(const QString& camera_name)
-{
- const bool avail = video_property_page::should_show_dialog(camera_name);
- ui.camera_settings->setEnabled(avail);
+ update_camera_settings_state(s.camera_name);
}
-void dialog_aruco::show_camera_settings()
-{
- const int idx = ui.cameraName->currentIndex();
- if (tracker)
- {
- cv::VideoCapture& cap = tracker->camera;
- if (cap.isOpened())
- video_property_page::show_from_capture(cap, idx);
- }
- else
- video_property_page::show(idx);
-}
-
-void dialog_aruco::toggleCalibrate()
+void aruco_dialog::toggleCalibrate()
{
if (!calib_timer.isActive())
{
@@ -467,13 +437,13 @@ void dialog_aruco::toggleCalibrate()
}
}
-void dialog_aruco::cleanupCalib()
+void aruco_dialog::cleanupCalib()
{
if (calib_timer.isActive())
calib_timer.stop();
}
-void dialog_aruco::update_tracker_calibration()
+void aruco_dialog::update_tracker_calibration()
{
if (calib_timer.isActive() && tracker)
{
@@ -484,15 +454,31 @@ void dialog_aruco::update_tracker_calibration()
}
}
-void dialog_aruco::doOK()
+void aruco_dialog::doOK()
{
s.b->save();
close();
}
-void dialog_aruco::doCancel()
+void aruco_dialog::doCancel()
{
close();
}
-OPENTRACK_DECLARE_TRACKER(tracker_aruco, dialog_aruco, aruco_metadata)
+void aruco_dialog::camera_settings()
+{
+ if (tracker)
+ {
+ QMutexLocker l(&tracker->camera_mtx);
+ video_property_page::show_from_capture(tracker->camera, camera_name_to_index(s.camera_name));
+ }
+ else
+ video_property_page::show(camera_name_to_index(s.camera_name));
+}
+
+void aruco_dialog::update_camera_settings_state(const QString& name)
+{
+ ui.camera_settings->setEnabled(video_property_page::should_show_dialog(name));
+}
+
+OPENTRACK_DECLARE_TRACKER(aruco_tracker, aruco_dialog, aruco_metadata)
diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h
index ccb1ad21..cdea1e42 100644
--- a/tracker-aruco/ftnoir_tracker_aruco.h
+++ b/tracker-aruco/ftnoir_tracker_aruco.h
@@ -8,14 +8,13 @@
#pragma once
#include "ui_aruco-trackercontrols.h"
+#include "options/options.hpp"
+#include "trans_calib.h"
#include "api/plugin-api.hpp"
-#include "include/markerdetector.h"
-
#include "cv/video-widget.hpp"
-#include "cv/translation-calibrator.hpp"
+#include "compat/timer.hpp"
-#include <opencv2/core.hpp>
-#include <opencv2/videoio.hpp>
+#include "include/markerdetector.h"
#include <QObject>
#include <QThread>
@@ -26,7 +25,9 @@
#include <cinttypes>
-#include "options/options.hpp"
+#include <opencv2/core.hpp>
+#include <opencv2/videoio.hpp>
+
using namespace options;
struct settings : opts {
@@ -46,16 +47,16 @@ struct settings : opts {
{}
};
-class dialog_aruco;
+class aruco_dialog;
-class tracker_aruco : protected QThread, public ITracker
+class aruco_tracker : protected QThread, public ITracker
{
Q_OBJECT
- friend class dialog_aruco;
+ friend class aruco_dialog;
static constexpr float c_search_window = 1.3f;
public:
- tracker_aruco();
- ~tracker_aruco() override;
+ aruco_tracker();
+ ~aruco_tracker() override;
void start_tracker(QFrame* frame) override;
void data(double *data) override;
void run() override;
@@ -65,7 +66,7 @@ private:
bool detect_without_roi();
bool open_camera();
void set_intrinsics();
- void update_fps(double dt);
+ void update_fps();
void draw_ar(bool ok);
void clamp_last_roi();
void set_points();
@@ -77,16 +78,14 @@ private:
cv::VideoCapture camera;
QMutex camera_mtx;
QMutex mtx;
- volatile bool stop;
- QHBoxLayout* layout;
- cv_video_widget* videoWidget;
+ qshared<cv_video_widget> videoWidget;
+ qshared<QHBoxLayout> layout;
settings s;
- double pose[6];
+ double pose[6], fps;
cv::Mat frame, grayscale, color;
cv::Matx33d r;
std::vector<cv::Point3f> obj_points;
cv::Matx33d intrinsics;
- cv::Matx14f dist_coeffs;
aruco::MarkerDetector detector;
std::vector<aruco::Marker> markers;
cv::Vec3d t;
@@ -97,25 +96,26 @@ private:
cv::Vec3d euler;
std::vector<cv::Point3f> roi_points;
cv::Rect last_roi;
- double freq, cur_fps;
- std::uint64_t last_time;
+ Timer fps_timer;
+
+ volatile bool stop;
- static constexpr float size_min = 0.05f;
- static constexpr float size_max = 0.3f;
+ static constexpr const float size_min = 0.05;
+ static constexpr const float size_max = 0.3;
- static constexpr double alpha_ = .95;
+ static constexpr const double RC = .25;
};
-class dialog_aruco : public ITrackerDialog
+class aruco_dialog : public ITrackerDialog
{
Q_OBJECT
public:
- dialog_aruco();
- void register_tracker(ITracker * x) override { tracker = static_cast<tracker_aruco*>(x); }
+ aruco_dialog();
+ void register_tracker(ITracker * x) override { tracker = static_cast<aruco_tracker*>(x); }
void unregister_tracker() override { tracker = nullptr; }
private:
- Ui::dialog_aruco ui;
- tracker_aruco* tracker;
+ Ui::Form ui;
+ aruco_tracker* tracker;
settings s;
TranslationCalibrator calibrator;
QTimer calib_timer;
@@ -125,12 +125,12 @@ private slots:
void toggleCalibrate();
void cleanupCalib();
void update_tracker_calibration();
- void set_camera_settings_available(const QString& camera_name);
- void show_camera_settings();
+ void camera_settings();
+ void update_camera_settings_state(const QString& name);
};
class aruco_metadata : public Metadata
{
- QString name() { return QString(QCoreApplication::translate("aruco_metadata", "aruco -- paper marker tracker")); }
+ QString name() { return QString("aruco -- paper marker tracker"); }
QIcon icon() { return QIcon(":/images/aruco.png"); }
};
diff --git a/tracker-aruco/trans_calib.cpp b/tracker-aruco/trans_calib.cpp
new file mode 100644
index 00000000..b5148efd
--- /dev/null
+++ b/tracker-aruco/trans_calib.cpp
@@ -0,0 +1,41 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "trans_calib.h"
+
+TranslationCalibrator::TranslationCalibrator()
+{
+ reset();
+}
+
+void TranslationCalibrator::reset()
+{
+ P = cv::Matx66f::zeros();
+ y = cv::Vec6f(0,0,0, 0,0,0);
+}
+
+void TranslationCalibrator::update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k)
+{
+ cv::Matx<double, 6,3> H_k_T = cv::Matx<double, 6,3>::zeros();
+ for (int i=0; i<3; ++i) {
+ for (int j=0; j<3; ++j) {
+ H_k_T(i,j) = R_CM_k(j,i);
+ }
+ }
+ for (int i=0; i<3; ++i)
+ {
+ H_k_T(3+i,i) = 1.0;
+ }
+ P += H_k_T * H_k_T.t();
+ y += H_k_T * t_CM_k;
+}
+
+cv::Vec3f TranslationCalibrator::get_estimate()
+{
+ cv::Vec6f x = P.inv() * y;
+ return cv::Vec3f(x[0], x[1], x[2]);
+}
diff --git a/tracker-aruco/trans_calib.h b/tracker-aruco/trans_calib.h
new file mode 100644
index 00000000..3d1e56fa
--- /dev/null
+++ b/tracker-aruco/trans_calib.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * 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.
+ */
+
+#ifndef TRANSCALIB_H
+#define TRANSCALIB_H
+
+#include <opencv2/core/core.hpp>
+
+//-----------------------------------------------------------------------------
+// Calibrates the translation from head to model = t_MH
+// by recursive least squares /
+// kalman filter in information form with identity noise covariance
+// measurement equation when head position = t_CH is fixed:
+// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k
+
+class TranslationCalibrator
+{
+public:
+ TranslationCalibrator();
+
+ // reset the calibration process
+ void reset();
+
+ // update the current estimate
+ void update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k);
+
+ // get the current estimate for t_MH
+ cv::Vec3f get_estimate();
+
+private:
+ cv::Matx66f P; // normalized precision matrix = inverse covariance
+ cv::Vec6f y; // P*(-t_MH, t_CH)
+};
+
+#endif //TRANSCALIB_H
diff --git a/tracker-hatire/ftnoir_tracker_hat.cpp b/tracker-hatire/ftnoir_tracker_hat.cpp
index 421a0e26..e8da968f 100644
--- a/tracker-hatire/ftnoir_tracker_hat.cpp
+++ b/tracker-hatire/ftnoir_tracker_hat.cpp
@@ -56,10 +56,10 @@ void hatire::start_tracker(QFrame*)
case result_ok:
break;
case result_error:
- QMessageBox::warning(0,"Error", ret.error, QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(0, tr("Error"), ret.error, QMessageBox::Ok,QMessageBox::NoButton);
break;
case result_open_error:
- QMessageBox::warning(0,"Error", "Unable to open ComPort: " + ret.error, QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(0, tr("Error"), tr("Unable to open ComPort: %1").arg(ret.error), QMessageBox::Ok,QMessageBox::NoButton);
break;
}
diff --git a/tracker-hydra/ftnoir_tracker_hydra.cpp b/tracker-hydra/ftnoir_tracker_hydra.cpp
index 781339fa..77e62243 100644
--- a/tracker-hydra/ftnoir_tracker_hydra.cpp
+++ b/tracker-hydra/ftnoir_tracker_hydra.cpp
@@ -1,4 +1,18 @@
-/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */
+/* Copyright (c) 2013 mm0zct
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "ftnoir_tracker_hydra.h"
#include "api/plugin-api.hpp"
#include <cstdio>
diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp
index 82f4a6fe..60eb4bb8 100644
--- a/tracker-pt/camera.cpp
+++ b/tracker-pt/camera.cpp
@@ -6,60 +6,23 @@
*/
#include "camera.h"
-#include "compat/camera-names.hpp"
#include <string>
#include <QDebug>
-Camera::~Camera() {}
-
-void Camera::set_device(const QString& name)
-{
- const int index = camera_name_to_index(name);
-
- desired_name = name;
-
- if (desired_index != index)
- {
- desired_index = index;
- _set_device_index();
-
- // reset fps
- dt_valid = 0;
- dt_mean = 0;
- active_index = index;
- }
-}
-
QString Camera::get_desired_name() const
{
return desired_name;
}
-void Camera::set_fps(int fps)
-{
- if (cam_desired.fps != fps)
- {
- cam_desired.fps = fps;
- _set_fps();
- }
-}
-
-void Camera::set_res(int x_res, int y_res)
+QString Camera::get_active_name() const
{
- if (cam_desired.res_x != x_res || cam_desired.res_y != y_res)
- {
- cam_desired.res_x = x_res;
- cam_desired.res_y = y_res;
- _set_res();
- }
+ return active_name;
}
DEFUN_WARN_UNUSED bool Camera::get_info(CamInfo& ret)
{
if (cam_info.res_x == 0 || cam_info.res_y == 0)
- {
return false;
- }
ret = cam_info;
return true;
}
@@ -68,7 +31,7 @@ bool Camera::get_frame(double dt, cv::Mat* frame)
{
bool new_frame = _get_frame(frame);
// measure fps of valid frames
- static constexpr double RC = 1; // second
+ static constexpr double RC = .1; // seconds
const double alpha = dt/(dt + RC);
dt_valid += dt;
if (new_frame)
@@ -76,8 +39,8 @@ bool Camera::get_frame(double dt, cv::Mat* frame)
if (dt_mean < 2e-3)
dt_mean = dt;
else
- dt_mean = alpha * dt_mean + (1 - alpha) * dt_valid;
- cam_info.fps = int(std::round(dt_mean > 2e-3 ? 1 / dt_mean : 0));
+ dt_mean = (1-alpha) * dt_mean + alpha * dt_valid;
+ cam_info.fps = dt_mean > 2e-3 ? int(1 / dt_mean + .65) : 0;
dt_valid = 0;
}
else
@@ -85,40 +48,52 @@ bool Camera::get_frame(double dt, cv::Mat* frame)
return new_frame;
}
-void CVCamera::start()
+DEFUN_WARN_UNUSED bool Camera::start(int idx, int fps, int res_x, int res_y)
{
- stop();
- cap = new cv::VideoCapture(desired_index);
- _set_res();
- _set_fps();
- // extract camera info
- if (cap->isOpened())
+ if (idx >= 0 && fps >= 0 && res_x > 0 && res_y > 0)
{
- active_index = desired_index;
- cam_info.res_x = 0;
- cam_info.res_y = 0;
- } else {
- stop();
+ if (!cap || cap->isOpened() ||
+ cam_desired.idx != idx ||
+ cam_desired.fps != fps ||
+ cam_desired.res_x != res_x ||
+ cam_desired.res_y != res_y)
+ {
+ cam_desired.idx = idx;
+ cam_desired.fps = fps;
+ cam_desired.res_x = res_x;
+ cam_desired.res_y = res_y;
+
+ cap = camera_ptr(new cv::VideoCapture(cam_desired.idx));
+
+ cap->set(cv::CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
+ cap->set(cv::CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
+ cap->set(cv::CAP_PROP_FPS, cam_desired.fps);
+
+ if (cap->isOpened())
+ {
+ cam_info.idx = cam_desired.idx;
+ cam_info.res_x = 0;
+ cam_info.res_y = 0;
+ active_name = desired_name;
+
+ return true;
+ }
+ }
}
+
+ return stop(), false;
}
-void CVCamera::stop()
+void Camera::stop()
{
- if (cap)
- {
- const bool opened = cap->isOpened();
- if (opened)
- {
- qDebug() << "pt: freeing camera";
- cap->release();
- }
- delete cap;
- cap = nullptr;
- qDebug() << "pt camera: stopped";
- }
+ cap = nullptr;
+ desired_name = QString();
+ active_name = QString();
+ cam_info = CamInfo();
+ cam_desired = CamInfo();
}
-bool CVCamera::_get_frame(cv::Mat* frame)
+bool Camera::_get_frame(cv::Mat* frame)
{
if (cap && cap->isOpened())
{
@@ -135,21 +110,12 @@ bool CVCamera::_get_frame(cv::Mat* frame)
return false;
}
-void CVCamera::_set_fps()
-{
- if (cap) cap->set(cv::CAP_PROP_FPS, cam_desired.fps);
-}
-
-void CVCamera::_set_res()
+void Camera::camera_deleter::operator()(cv::VideoCapture* cap)
{
if (cap)
{
- cap->set(cv::CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
- cap->set(cv::CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
+ if (cap->isOpened())
+ cap->release();
+ std::default_delete<cv::VideoCapture>()(cap);
}
}
-void CVCamera::_set_device_index()
-{
- if (desired_index != active_index)
- stop();
-}
diff --git a/tracker-pt/camera.h b/tracker-pt/camera.h
index be7d35c4..3f5a8f43 100644
--- a/tracker-pt/camera.h
+++ b/tracker-pt/camera.h
@@ -7,6 +7,9 @@
#pragma once
+#undef NDEBUG
+#include <cassert>
+
#include "compat/util.hpp"
#include <opencv2/core/core.hpp>
@@ -17,81 +20,51 @@
struct CamInfo
{
- CamInfo() : res_x(0), res_y(0), fps(0) {}
+ CamInfo() : res_x(0), res_y(0), fps(-1), idx(-1) {}
int res_x;
int res_y;
int fps;
+ int idx;
};
-// ----------------------------------------------------------------------------
-// Base class for cameras, calculates the frame rate
-class Camera
+class Camera final
{
public:
- Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1) {}
- virtual ~Camera() = 0;
-
- // start/stop capturing
- virtual void start() = 0;
- virtual void stop() = 0;
- void restart() { stop(); start(); }
+ Camera() : dt_valid(0), dt_mean(0) {}
- // calls corresponding template methods and reinitializes frame rate calculation
- void set_device(const QString& name);
- void set_fps(int fps);
- void set_res(int x_res, int y_res);
+ DEFUN_WARN_UNUSED bool start(int idx, int fps, int res_x, int res_y);
+ void stop();
- // gets a frame from the camera, dt: time since last call in seconds
DEFUN_WARN_UNUSED bool get_frame(double dt, cv::Mat* frame);
-
- // WARNING: returned references are valid as long as object
DEFUN_WARN_UNUSED bool get_info(CamInfo &ret);
+
CamInfo get_desired() const { return cam_desired; }
QString get_desired_name() const;
-protected:
- // get a frame from the camera
- DEFUN_WARN_UNUSED virtual bool _get_frame(cv::Mat* frame) = 0;
-
- // update the camera using cam_desired, write res and f to cam_info if successful
- virtual void _set_device_index() = 0;
- virtual void _set_fps() = 0;
- virtual void _set_res() = 0;
+ QString get_active_name() const;
+
+ cv::VideoCapture& operator*() { assert(cap); return *cap; }
+ const cv::VideoCapture& operator*() const { assert(cap); return *cap; }
+ cv::VideoCapture* operator->() { assert(cap); return cap.get(); }
+ const cv::VideoCapture* operator->() const { return cap.get(); }
+ operator bool() const { return cap && cap->isOpened(); }
+
private:
+ DEFUN_WARN_UNUSED bool _get_frame(cv::Mat* frame);
+
double dt_valid;
double dt_mean;
-protected:
+
CamInfo cam_info;
CamInfo cam_desired;
- QString desired_name;
- int desired_index;
- int active_index;
-};
+ QString desired_name, active_name;
-// ----------------------------------------------------------------------------
-// camera based on OpenCV's videoCapture
-class CVCamera final : public Camera
-{
-public:
- CVCamera() : cap(NULL) {}
- ~CVCamera() { stop(); }
-
- void start() override;
- void stop() override;
-
- operator cv::VideoCapture*() { return cap; }
-protected:
- bool _get_frame(cv::Mat* frame) override;
- void _set_fps() override;
- void _set_res() override;
- void _set_device_index() override;
-private:
- cv::VideoCapture* cap;
-};
+ struct camera_deleter final
+ {
+ void operator()(cv::VideoCapture* cap);
+ };
-enum RotationType
-{
- CLOCKWISE = 0,
- ZERO = 1,
- COUNTER_CLOCKWISE = 2
+ using camera_ptr = std::unique_ptr<cv::VideoCapture, camera_deleter>;
+
+ camera_ptr cap;
};
diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp
index d13c5545..40293f56 100644
--- a/tracker-pt/ftnoir_tracker_pt.cpp
+++ b/tracker-pt/ftnoir_tracker_pt.cpp
@@ -19,8 +19,6 @@
//-----------------------------------------------------------------------------
Tracker_PT::Tracker_PT() :
- video_widget(nullptr),
- video_frame(nullptr),
point_count(0),
commands(0),
ever_success(false)
@@ -32,13 +30,7 @@ Tracker_PT::~Tracker_PT()
{
set_command(ABORT);
wait();
- if (video_widget)
- delete video_widget;
- video_widget = NULL;
- if (video_frame)
- {
- if (video_frame->layout()) delete video_frame->layout();
- }
+
// fast start/stop causes breakage
camera.stop();
}
@@ -65,12 +57,21 @@ bool Tracker_PT::get_focal_length(f& ret)
using std::tan;
using std::atan;
using std::sqrt;
-
+#if 1
const double w = info.res_x, h = info.res_y;
const double diag = sqrt(w/h*w/h + h/w*h/w);
const double diag_fov = static_cast<int>(s.fov) * M_PI / 180.;
const double fov = 2.*atan(tan(diag_fov/2.)/diag);
ret = .5 / tan(.5 * fov);
+#else
+ // the formula looks correct but doesn't work right regardless
+
+ const double diag_fov = s.fov * M_PI/180;
+ const double aspect = w / sqrt(w*w + h*h);
+ const double fov = 2*atan(tan(diag_fov*.5) * aspect);
+ ret = .5 / tan(fov * .5);
+ static bool once = false; if (!once) { once = true; qDebug() << "f" << ret << "fov" << (fov * 180/M_PI); }
+#endif
return true;
}
return false;
@@ -171,7 +172,7 @@ void Tracker_PT::run()
video_widget->update_image(frame_);
}
}
- qDebug() << "pt: Thread stopping";
+ qDebug() << "pt: thread stopped";
}
void Tracker_PT::apply_settings()
@@ -180,37 +181,26 @@ void Tracker_PT::apply_settings()
QMutexLocker l(&camera_mtx);
- CamInfo info = camera.get_desired();
- const QString name = camera.get_desired_name();
+ CamInfo info;
- if (s.cam_fps != info.fps ||
- s.cam_res_x != info.res_x ||
- s.cam_res_y != info.res_y ||
- s.camera_name != name)
- {
- qDebug() << "pt: starting camera";
- camera.stop();
- camera.set_device(s.camera_name);
- camera.set_res(s.cam_res_x, s.cam_res_y);
- camera.set_fps(s.cam_fps);
+ if (!camera.get_info(info) || frame.rows != info.res_y || frame.cols != info.res_x)
frame = cv::Mat();
- camera.start();
- }
+
+ camera.start(camera_name_to_index(s.camera_name), s.cam_fps, s.cam_res_x, s.cam_res_y);
qDebug() << "pt: done applying settings";
}
-void Tracker_PT::start_tracker(QFrame *parent_window)
+void Tracker_PT::start_tracker(QFrame* video_frame)
{
- video_frame = parent_window;
video_frame->setAttribute(Qt::WA_NativeWindow);
- video_frame->show();
- video_widget = new cv_video_widget(video_frame);
- QHBoxLayout* video_layout = new QHBoxLayout(parent_window);
- video_layout->setContentsMargins(0, 0, 0, 0);
- video_layout->addWidget(video_widget);
- video_frame->setLayout(video_layout);
+ video_widget = qptr<cv_video_widget>(video_frame);
+ layout = qptr<QHBoxLayout>(video_frame);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(video_widget.data());
+ video_frame->setLayout(layout.data());
video_widget->resize(video_frame->width(), video_frame->height());
+ video_frame->show();
start();
}
diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h
index 020694ae..66928655 100644
--- a/tracker-pt/ftnoir_tracker_pt.h
+++ b/tracker-pt/ftnoir_tracker_pt.h
@@ -18,12 +18,14 @@
#include "point_tracker.h"
#include "compat/timer.hpp"
#include "cv/video-widget.hpp"
+#include "compat/util.hpp"
#include <QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QTime>
+#include <QLayout>
#include <atomic>
#include <memory>
#include <vector>
@@ -65,12 +67,12 @@ private:
QMutex camera_mtx;
QMutex data_mtx;
- CVCamera camera;
+ Camera camera;
PointExtractor point_extractor;
PointTracker point_tracker;
- cv_video_widget* video_widget;
- QFrame* video_frame;
+ qshared<cv_video_widget> video_widget;
+ qshared<QLayout> layout;
settings_pt s;
Timer time;
diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp
index 749ea1ff..d3951bd9 100644
--- a/tracker-pt/ftnoir_tracker_pt_dialog.cpp
+++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp
@@ -142,12 +142,16 @@ void TrackerDialog_PT::set_camera_settings_available(const QString& camera_name)
void TrackerDialog_PT::show_camera_settings()
{
const int idx = ui.camdevice_combo->currentIndex();
+
if (tracker)
{
- cv::VideoCapture* cap = tracker->camera;
- if (cap && cap->isOpened())
+ if (tracker->camera)
{
- video_property_page::show_from_capture(*cap, idx);
+ cv::VideoCapture& cap = *tracker->camera;
+
+ CamInfo info;
+ if (tracker->camera.get_info(info))
+ video_property_page::show_from_capture(cap, info.idx);
}
}
else
diff --git a/tracker-pt/lang/ru_RU.ts b/tracker-pt/lang/ru_RU.ts
new file mode 100644
index 00000000..f6094d27
--- /dev/null
+++ b/tracker-pt/lang/ru_RU.ts
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+ <name>PT_metadata</name>
+ <message>
+ <location filename="../ftnoir_tracker_pt.h" line="+92"/>
+ <source>PointTracker 1.1</source>
+ <translation></translation>
+ </message>
+</context>
+<context>
+ <name>UICPTClientControls</name>
+ <message>
+ <location filename="../FTNoIR_PT_Controls.ui" line="+23"/>
+ <source>PointTracker Settings</source>
+ <translation>Настройки PointTracker</translation>
+ </message>
+ <message>
+ <location line="+38"/>
+ <source>Camera</source>
+ <translation>Камера</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Camera settings</source>
+ <translation>Настройка камеры</translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>°</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Diagonal field of view</source>
+ <translation>Угол обзора камеры</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Width</source>
+ <translation>Ширина</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>FPS</source>
+ <translation>FPS (Кадров в секунду)</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Desired capture height</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <location line="+55"/>
+ <location line="+175"/>
+ <location line="+16"/>
+ <source> px</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="-233"/>
+ <source>Dynamic pose timeout</source>
+ <translation>Динамическая поза (время ожидания)</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Desired capture framerate</source>
+ <translation>Желаемая частота кадров</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source> Hz</source>
+ <translation> Гц</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Desired capture width</source>
+ <translation>Желаемая ширина захвата</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Height</source>
+ <translation>Высота</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source> ms</source>
+ <translation> мс</translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Dynamic pose resolution</source>
+ <translation>Динамическая поза (активация) </translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Device</source>
+ <translation>Устройство</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Open</source>
+ <translation>Открыть</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Camera settings (when available)</source>
+ <translation>Параметры камеры (если доступно)</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Point extraction</source>
+ <translation>Извлечение точек</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Max size</source>
+ <translation>Макс.размер</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Threshold</source>
+ <translation>Порог</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Min size</source>
+ <translation>Мин.размер</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Intensity threshold for point extraction</source>
+ <translation>Порог интенсивности для извлечения точки</translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Automatic threshold</source>
+ <translation>Автоматич. порог</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Enable, slider sets point size</source>
+ <translation>Полузнок устанавливает размер точек</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Maximum point diameter</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Minimum point diameter</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>Model</source>
+ <translation>Модель</translation>
+ </message>
+ <message>
+ <location line="+28"/>
+ <source>Clip</source>
+ <translation>Клипса</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <location line="+154"/>
+ <location line="+129"/>
+ <source>Model Dimensions</source>
+ <translation>Размеры модели</translation>
+ </message>
+ <message>
+ <location line="-271"/>
+ <location line="+19"/>
+ <location line="+48"/>
+ <location line="+19"/>
+ <location line="+97"/>
+ <location line="+35"/>
+ <location line="+32"/>
+ <location line="+40"/>
+ <location line="+26"/>
+ <location line="+13"/>
+ <location line="+13"/>
+ <location line="+13"/>
+ <location line="+26"/>
+ <location line="+132"/>
+ <location line="+26"/>
+ <location line="+26"/>
+ <source> mm</source>
+ <translation> мм</translation>
+ </message>
+ <message>
+ <location line="-511"/>
+ <location line="+116"/>
+ <source>Side</source>
+ <translation>Сбоку</translation>
+ </message>
+ <message>
+ <location line="-65"/>
+ <location line="+132"/>
+ <source>Front</source>
+ <translation>Спереди</translation>
+ </message>
+ <message>
+ <location line="-107"/>
+ <source>Cap</source>
+ <translation>Кепка</translation>
+ </message>
+ <message>
+ <location line="+135"/>
+ <source>Custom</source>
+ <translation>Свой</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <location line="+169"/>
+ <location line="+106"/>
+ <source>z:</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="-249"/>
+ <location line="+104"/>
+ <location line="+93"/>
+ <source>x:</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="-132"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Location of the two remaining model points&lt;br/&gt;with respect to the reference point in default pose&lt;/p&gt;&lt;p&gt;Use any units you want, not necessarily centimeters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translatorcomment>Расположение двух оставшихся точек модели относительно опорной точки в стандартной позе. Возможно исп-ть любые единицы измерения, не обязательно сантиметры.</translatorcomment>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt; Расположение двух оставшихся точек модели&lt;br/&gt;относительно опорной точки в стандартной позе. &lt;/p&gt;&lt;p&gt;Возможно использовать любые единицы измерения.&lt;/p&gt;&lt;/body&gt;&lt;/html</translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <location line="+65"/>
+ <location line="+67"/>
+ <source>y:</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="-106"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:16pt;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot; font-size:16pt; vertical-align:sub;&quot;&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:16pt;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot; font-size:16pt; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location line="+46"/>
+ <source>Model position</source>
+ <translation>Положение модели</translation>
+ </message>
+ <message>
+ <location line="+105"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Instructions on the opentrack wiki&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Инструкция на opentrack-вики&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Start calibration</source>
+ <translation>Начать калибровку</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>About</source>
+ <translation>О программе</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;FTNoIR PointTracker Plugin&lt;br/&gt;Version 1.1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;by Patrick Ruoff&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://ftnoirpt.sourceforge.net/&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline; color:#0000ff;&quot;&gt;Manual (external)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;FTNoIR PointTracker Plugin&lt;br/&gt;Version 1.1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;by Patrick Ruoff&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://ftnoirpt.sourceforge.net/&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline; color:#0000ff;&quot;&gt;Руководство (PointTracker)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ </message>
+ <message>
+ <location line="+36"/>
+ <source>Status</source>
+ <translation>Статус</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Extracted Points:</source>
+ <translation>Извлечено точек:</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Camera Info:</source>
+ <translation>Параметры камеры:</translation>
+ </message>
+</context>
+</TS>
diff --git a/tracker-qt-gamepad/CMakeLists.txt b/tracker-qt-gamepad/CMakeLists.txt
new file mode 100644
index 00000000..c892c5c6
--- /dev/null
+++ b/tracker-qt-gamepad/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(FALSE AND Qt5Gamepad_FOUND)
+ opentrack_boilerplate(opentrack-tracker-qt-gamepad)
+endif()
diff --git a/tracker-qt-gamepad/test.cpp b/tracker-qt-gamepad/test.cpp
new file mode 100644
index 00000000..4f2c8daa
--- /dev/null
+++ b/tracker-qt-gamepad/test.cpp
@@ -0,0 +1,99 @@
+/* Copyright (c) 2014, Stanislaw Halik <sthalik@misaki.pl>
+
+ * Permission to use, copy, modify, and/or distribute this
+ * software for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice and this permission
+ * notice appear in all copies.
+ */
+
+#include "test.h"
+#include "api/plugin-api.hpp"
+#include <cmath>
+
+#include <QDebug>
+
+const double gamepad_tracker::incr[6] =
+{
+ 50, 40, 80,
+ 70, 5, 3
+};
+
+gamepad_tracker::gamepad_tracker() :
+ last_x { 0, 0, 0, 0, 0, 0 }
+{
+}
+
+gamepad_tracker::~gamepad_tracker()
+{
+}
+
+void gamepad_tracker::start_tracker(QFrame*)
+{
+ t.start();
+}
+
+#ifdef EMIT_NAN
+# include <cstdlib>
+#endif
+
+void gamepad_tracker::data(double *data)
+{
+ using std::fmod;
+ using std::sin;
+ using std::fabs;
+ using std::copysign;
+
+ const double dt = t.elapsed_seconds();
+ t.start();
+
+#ifdef EMIT_NAN
+ if ((rand()%4) == 0)
+ {
+ for (int i = 0; i < 6; i++)
+ data[i] = 0./0.;
+ }
+ else
+#endif
+ for (int i = 0; i < 6; i++)
+ {
+ double x = fmod(last_x[i] + incr[i] * d2r * dt, 2 * M_PI);
+ last_x[i] = x;
+
+ if (i >= 3)
+ {
+#ifdef DISCONTINUITY
+ if (x > pi + pi/2)
+ x -= M_PI;
+ else if (x > pi/2 && x < pi)
+ x += M_PI;
+#endif
+
+ data[i] = sin(x) * 180;
+ }
+ else
+ {
+ data[i] = sin(x) * 100;
+ }
+ }
+}
+
+gamepad_dialog::gamepad_dialog()
+{
+ ui.setupUi(this);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+}
+
+void gamepad_dialog::doOK()
+{
+ //s.b->save();
+ close();
+}
+
+void gamepad_dialog::doCancel()
+{
+ close();
+}
+
+OPENTRACK_DECLARE_TRACKER(gamepad_tracker, gamepad_dialog, gamepad_metadata)
diff --git a/tracker-qt-gamepad/test.h b/tracker-qt-gamepad/test.h
new file mode 100644
index 00000000..ffa9ac44
--- /dev/null
+++ b/tracker-qt-gamepad/test.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "ui_test.h"
+#include "api/plugin-api.hpp"
+#include "compat/timer.hpp"
+
+#include <cmath>
+
+class gamepad_tracker : public ITracker
+{
+public:
+ gamepad_tracker();
+ ~gamepad_tracker() override;
+ void start_tracker(QFrame *) override;
+ void data(double *data) override;
+
+private:
+ static constexpr double r2d = 180 / M_PI;
+ static constexpr double d2r = M_PI / 180;
+
+ static const double incr[6];
+ double last_x[6];
+ Timer t;
+};
+
+class gamepad_dialog : public ITrackerDialog
+{
+ Q_OBJECT
+
+ Ui::test_ui ui;
+public:
+ gamepad_dialog();
+ void register_tracker(ITracker *) override {}
+ void unregister_tracker() override {}
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class gamepad_metadata : public Metadata
+{
+public:
+ QString name() { return QString(QCoreApplication::translate("gamepad_metadata", "Gamepad input")); }
+ QIcon icon() { return QIcon(":/images/facetracknoir.png"); }
+};
+
diff --git a/tracker-qt-gamepad/test.ui b/tracker-qt-gamepad/test.ui
new file mode 100644
index 00000000..bdf2cd4e
--- /dev/null
+++ b/tracker-qt-gamepad/test.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>test_ui</class>
+ <widget class="QWidget" name="test_ui">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>352</width>
+ <height>224</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Gamepad input</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>../gui/images/facetracknoir.png</normaloff>../gui/images/facetracknoir.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <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>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/tracker-qt-gamepad/test_dialog.cpp b/tracker-qt-gamepad/test_dialog.cpp
new file mode 100644
index 00000000..5d33555b
--- /dev/null
+++ b/tracker-qt-gamepad/test_dialog.cpp
@@ -0,0 +1,3 @@
+#include "test.h"
+#include "api/plugin-api.hpp"
+
diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.cpp b/tracker-rift-025/ftnoir_tracker_rift_025.cpp
index 7c0b2a55..257b4502 100644
--- a/tracker-rift-025/ftnoir_tracker_rift_025.cpp
+++ b/tracker-rift-025/ftnoir_tracker_rift_025.cpp
@@ -1,4 +1,18 @@
-/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */
+/* Copyright (c) 2013 mm0zct
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "ftnoir_tracker_rift_025.h"
#include "api/plugin-api.hpp"
#include <OVR.h>
@@ -8,7 +22,7 @@
using namespace OVR;
-Rift_Tracker::Rift_Tracker()
+rift_tracker_025::rift_tracker_025()
{
pManager = NULL;
pSensor = NULL;
@@ -16,7 +30,7 @@ Rift_Tracker::Rift_Tracker()
old_yaw = 0;
}
-Rift_Tracker::~Rift_Tracker()
+rift_tracker_025::~rift_tracker_025()
{
if (pSensor)
pSensor->Release();
@@ -27,7 +41,7 @@ Rift_Tracker::~Rift_Tracker()
System::Destroy();
}
-void Rift_Tracker::start_tracker(QFrame*)
+void rift_tracker_025::start_tracker(QFrame*)
{
System::Init(Log::ConfigureDefaultLog(LogMask_All));
pManager = DeviceManager::Create();
@@ -46,23 +60,32 @@ void Rift_Tracker::start_tracker(QFrame*)
}
else
{
- QMessageBox::warning(0,"Error", "Unable to create Rift sensor",QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(nullptr,
+ QCoreApplication::translate("rift_tracker_025", "Error"),
+ QCoreApplication::translate("rift_tracker_025", "Unable to create Rift sensor"),
+ QMessageBox::Ok,QMessageBox::NoButton);
}
}
else
{
- QMessageBox::warning(0,"Error", "Unable to enumerate Rift tracker",QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(nullptr,
+ QCoreApplication::translate("rift_tracker_025", "Error"),
+ QCoreApplication::translate("rift_tracker_025", "Unable to enumerate Rift tracker"),
+ QMessageBox::Ok,QMessageBox::NoButton);
}
}
else
{
- QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(nullptr,
+ QCoreApplication::translate("rift_tracker_025", "Error"),
+ QCoreApplication::translate("rift_tracker_025", "Unable to start Rift tracker"),
+ QMessageBox::Ok,QMessageBox::NoButton);
}
}
-void Rift_Tracker::data(double *data)
+void rift_tracker_025::data(double *data)
{
if (pSFusion != NULL && pSensor != NULL)
{
@@ -100,4 +123,4 @@ void Rift_Tracker::data(double *data)
}
}
-OPENTRACK_DECLARE_TRACKER(Rift_Tracker, dialog_rift_025, rift_025Dll)
+OPENTRACK_DECLARE_TRACKER(rift_tracker_025, dialog_rift_025, rift_025Dll)
diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.h b/tracker-rift-025/ftnoir_tracker_rift_025.h
index 96331fd2..b65d3e56 100644
--- a/tracker-rift-025/ftnoir_tracker_rift_025.h
+++ b/tracker-rift-025/ftnoir_tracker_rift_025.h
@@ -21,11 +21,11 @@ struct settings : opts {
{}
};
-class Rift_Tracker : public ITracker
+class rift_tracker_025 : public ITracker
{
public:
- Rift_Tracker();
- virtual ~Rift_Tracker() override;
+ rift_tracker_025();
+ virtual ~rift_tracker_025() override;
void start_tracker(QFrame *) override;
void data(double *data) override;
private:
diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.cpp b/tracker-rift-042/ftnoir_tracker_rift_042.cpp
index af8a386f..a25288fa 100644
--- a/tracker-rift-042/ftnoir_tracker_rift_042.cpp
+++ b/tracker-rift-042/ftnoir_tracker_rift_042.cpp
@@ -1,4 +1,18 @@
-/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */
+/* Copyright (c) 2013 mm0zct
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "ftnoir_tracker_rift_042.h"
#include "api/plugin-api.hpp"
@@ -12,17 +26,17 @@
using namespace OVR;
-Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr)
+rift_tracker_042::rift_tracker_042() : old_yaw(0), hmd(nullptr)
{
}
-Rift_Tracker::~Rift_Tracker()
+rift_tracker_042::~rift_tracker_042()
{
ovrHmd_Destroy(hmd);
ovr_Shutdown();
}
-void Rift_Tracker::start_tracker(QFrame*)
+void rift_tracker_042::start_tracker(QFrame*)
{
ovr_Initialize();
hmd = ovrHmd_Create(0);
@@ -34,14 +48,14 @@ void Rift_Tracker::start_tracker(QFrame*)
{
QMessageBox::warning(nullptr,
"Error",
- QStringLiteral("Unable to start Rift tracker: %1").arg(ovrHmd_GetLastError(nullptr)),
+ QCoreApplication::translate("rift_tracker_042", "Unable to start Rift tracker: %1").arg(ovrHmd_GetLastError(nullptr)),
QMessageBox::Ok,
QMessageBox::NoButton);
}
}
-void Rift_Tracker::data(double *data)
+void rift_tracker_042::data(double *data)
{
if (hmd)
{
@@ -87,4 +101,4 @@ void Rift_Tracker::data(double *data)
}
}
-OPENTRACK_DECLARE_TRACKER(Rift_Tracker, dialog_rift_042, rift_042Dll)
+OPENTRACK_DECLARE_TRACKER(rift_tracker_042, dialog_rift_042, rift_042Dll)
diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.h b/tracker-rift-042/ftnoir_tracker_rift_042.h
index ed802da0..82081085 100644
--- a/tracker-rift-042/ftnoir_tracker_rift_042.h
+++ b/tracker-rift-042/ftnoir_tracker_rift_042.h
@@ -21,11 +21,11 @@ struct settings : opts {
{}
};
-class Rift_Tracker : public ITracker
+class rift_tracker_042 : public ITracker
{
public:
- Rift_Tracker();
- virtual ~Rift_Tracker() override;
+ rift_tracker_042();
+ virtual ~rift_tracker_042() override;
void start_tracker(QFrame *) override;
void data(double *data) override;
private:
diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_080.cpp
index 35a268f2..98edcb4f 100644
--- a/tracker-rift-080/ftnoir_tracker_rift_080.cpp
+++ b/tracker-rift-080/ftnoir_tracker_rift_080.cpp
@@ -1,4 +1,18 @@
-/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */
+/* Copyright (c) 2013 mm0zct
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "ftnoir_tracker_rift_080.h"
#include "api/plugin-api.hpp"
#include "compat/util.hpp"
@@ -10,18 +24,18 @@
using namespace OVR;
-Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr)
+rift_tracker_080::rift_tracker_080() : old_yaw(0), hmd(nullptr)
{
}
-Rift_Tracker::~Rift_Tracker()
+rift_tracker_080::~rift_tracker_080()
{
if (hmd)
ovr_Destroy(hmd);
ovr_Shutdown();
}
-void Rift_Tracker::start_tracker(QFrame*)
+void rift_tracker_080::start_tracker(QFrame*)
{
ovrResult code;
ovrGraphicsLuid luid = {{0}};
@@ -55,7 +69,7 @@ error:
QMessageBox::NoButton);
}
-void Rift_Tracker::data(double *data)
+void rift_tracker_080::data(double *data)
{
if (hmd)
{
@@ -100,4 +114,4 @@ void Rift_Tracker::data(double *data)
}
}
-OPENTRACK_DECLARE_TRACKER(Rift_Tracker, dialog_rift_080, rift_080Dll)
+OPENTRACK_DECLARE_TRACKER(rift_tracker_080, dialog_rift_080, rift_080Dll)
diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.h b/tracker-rift-080/ftnoir_tracker_rift_080.h
index 7868b2a2..e5ad9c3a 100644
--- a/tracker-rift-080/ftnoir_tracker_rift_080.h
+++ b/tracker-rift-080/ftnoir_tracker_rift_080.h
@@ -20,11 +20,11 @@ struct settings : opts {
{}
};
-class Rift_Tracker : public ITracker
+class rift_tracker_080 : public ITracker
{
public:
- Rift_Tracker();
- ~Rift_Tracker() override;
+ rift_tracker_080();
+ ~rift_tracker_080() override;
void start_tracker(QFrame *) override;
void data(double *data) override;
private:
diff --git a/tracker-rift-140/impl.cpp b/tracker-rift-140/impl.cpp
index 67d5bb47..45bfcc97 100644
--- a/tracker-rift-140/impl.cpp
+++ b/tracker-rift-140/impl.cpp
@@ -1,4 +1,18 @@
-/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */
+/* Copyright (c) 2013 mm0zct
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "rift-140.hpp"
#include "api/plugin-api.hpp"
#include "compat/util.hpp"
@@ -8,11 +22,11 @@
using namespace OVR;
-Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr)
+rift_tracker_140::rift_tracker_140() : old_yaw(0), hmd(nullptr)
{
}
-Rift_Tracker::~Rift_Tracker()
+rift_tracker_140::~rift_tracker_140()
{
if (hmd)
{
@@ -21,7 +35,7 @@ Rift_Tracker::~Rift_Tracker()
}
}
-void Rift_Tracker::start_tracker(QFrame*)
+void rift_tracker_140::start_tracker(QFrame*)
{
if (OVR_FAILURE(ovr_Initialize(nullptr)))
goto error;
@@ -44,12 +58,12 @@ error:
QMessageBox::warning(nullptr,
"Error",
- QStringLiteral("Unable to start Rift tracker: %1").arg(strerror),
+ QCoreApplication::translate("rift_tracker_140", "Unable to start Rift tracker: %1").arg(strerror),
QMessageBox::Ok,
QMessageBox::NoButton);
}
-void Rift_Tracker::data(double *data)
+void rift_tracker_140::data(double *data)
{
if (hmd)
{
@@ -94,4 +108,4 @@ void Rift_Tracker::data(double *data)
}
}
-OPENTRACK_DECLARE_TRACKER(Rift_Tracker, dialog_rift_140, rift_140Dll)
+OPENTRACK_DECLARE_TRACKER(rift_tracker_140, dialog_rift_140, rift_140Dll)
diff --git a/tracker-rift-140/rift-140.hpp b/tracker-rift-140/rift-140.hpp
index 23ec6fb3..47eb7cd2 100644
--- a/tracker-rift-140/rift-140.hpp
+++ b/tracker-rift-140/rift-140.hpp
@@ -20,11 +20,11 @@ struct settings : opts {
{}
};
-class Rift_Tracker : public ITracker
+class rift_tracker_140 : public ITracker
{
public:
- Rift_Tracker();
- ~Rift_Tracker() override;
+ rift_tracker_140();
+ ~rift_tracker_140() override;
void start_tracker(QFrame *) override;
void data(double *data) override;
private:
diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp
index 6eae0693..d2c77f12 100644
--- a/tracker-rs/ftnoir_tracker_rs.cpp
+++ b/tracker-rs/ftnoir_tracker_rs.cpp
@@ -87,7 +87,10 @@ bool RSTracker::startSdkInstallationProcess()
bool pStarted = QProcess::startDetached(contrib_path + "intel_rs_sdk_runtime_websetup_10.0.26.0396.exe --finstall=core,face3d --fnone=all");
if(!pStarted){
- QMessageBox::warning(0, "Intel® RealSense™ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok);
+ QMessageBox::warning(nullptr,
+ tr("Intel® RealSense™ Runtime Installation"),
+ tr("Installation process failed to start."),
+ QMessageBox::Ok);
}
return pStarted;
}
@@ -100,19 +103,19 @@ void RSTracker::showRealSenseErrorMessageBox(int exitCode)
switch(exitCode){
case -101: //The implementation got an invalid handle from the RealSense SDK session/modules
- msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed.");
+ msgBox.setInformativeText(tr("Couldn't initialize RealSense tracking. Please make sure SDK Runtime 2016 R2 is installed."));
break;
case -301: //RealSense SDK runtime execution aborted.
- msgBox.setInformativeText("Tracking stopped after the RealSense SDK Runtime execution has aborted.");
+ msgBox.setInformativeText(tr("Tracking stopped after the RealSense SDK Runtime execution has aborted."));
break;
case -601: //RealSense Camera stream configuration has changed.
- msgBox.setInformativeText("Tracking stopped after another program changed camera streams configuration.");
+ msgBox.setInformativeText(tr("Tracking stopped after another program changed camera streams configuration."));
break;
default:
msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime 2016 R2 to be installed.");
}
- QPushButton* triggerSdkInstallation = msgBox.addButton("Install Runtime", QMessageBox::ActionRole);
+ QPushButton* triggerSdkInstallation = msgBox.addButton(tr("Install Runtime"), QMessageBox::ActionRole);
msgBox.addButton(QMessageBox::Ok);
msgBox.exec();
diff --git a/tracker-steamvr/dialog.cpp b/tracker-steamvr/dialog.cpp
index 2e672ca4..bbb8866d 100644
--- a/tracker-steamvr/dialog.cpp
+++ b/tracker-steamvr/dialog.cpp
@@ -1,7 +1,7 @@
#include "steamvr.hpp"
#include "api/plugin-api.hpp"
-dialog::dialog()
+steamvr_dialog::steamvr_dialog()
{
ui.setupUi(this);
@@ -9,13 +9,13 @@ dialog::dialog()
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
}
-void dialog::doOK()
+void steamvr_dialog::doOK()
{
s.b->save();
close();
}
-void dialog::doCancel()
+void steamvr_dialog::doCancel()
{
close();
}
diff --git a/tracker-steamvr/steamvr.cpp b/tracker-steamvr/steamvr.cpp
index 9c357a7a..bab98f0d 100644
--- a/tracker-steamvr/steamvr.cpp
+++ b/tracker-steamvr/steamvr.cpp
@@ -54,7 +54,9 @@ void steamvr::start_tracker(QFrame*)
if (!vr)
{
- QMessageBox::warning(nullptr, "Valve SteamVR init error", strerror(e), QMessageBox::Close, QMessageBox::NoButton);
+ QMessageBox::warning(nullptr,
+ QCoreApplication::translate("steamvr", "Valve SteamVR init error"), strerror(e),
+ QMessageBox::Close, QMessageBox::NoButton);
return;
}
@@ -69,7 +71,10 @@ void steamvr::start_tracker(QFrame*)
if (!ok)
{
- QMessageBox::warning(nullptr, "Valve SteamVR init warning", "No HMD connected", QMessageBox::Close, QMessageBox::NoButton);
+ QMessageBox::warning(nullptr,
+ QCoreApplication::translate("steamvr", "Valve SteamVR init warning"),
+ QCoreApplication::translate("steamvr", "No HMD connected"),
+ QMessageBox::Close, QMessageBox::NoButton);
return;
}
}
@@ -125,7 +130,7 @@ done:
}
}
-void dialog::register_tracker(ITracker*) {}
-void dialog::unregister_tracker() {}
+void steamvr_dialog::register_tracker(ITracker*) {}
+void steamvr_dialog::unregister_tracker() {}
-OPENTRACK_DECLARE_TRACKER(steamvr, dialog, metadata)
+OPENTRACK_DECLARE_TRACKER(steamvr, steamvr_dialog, steamvr_metadata)
diff --git a/tracker-steamvr/steamvr.hpp b/tracker-steamvr/steamvr.hpp
index 2947f3f1..9b53979e 100644
--- a/tracker-steamvr/steamvr.hpp
+++ b/tracker-steamvr/steamvr.hpp
@@ -40,11 +40,11 @@ private:
static QString strerror(error_t error);
};
-class dialog : public ITrackerDialog
+class steamvr_dialog : public ITrackerDialog
{
Q_OBJECT
public:
- dialog();
+ steamvr_dialog();
void register_tracker(ITracker *) override;
void unregister_tracker() override;
@@ -57,10 +57,10 @@ private slots:
void doCancel();
};
-class metadata : public Metadata
+class steamvr_metadata : public Metadata
{
public:
- QString name() { return QString(QCoreApplication::translate("metadata", "Valve SteamVR")); }
+ QString name() { return QString(QCoreApplication::translate("steamvr_metadata", "Valve SteamVR")); }
QIcon icon() { return QIcon(":/images/rift_tiny.png"); }
};
diff --git a/tracker-test/test.cpp b/tracker-test/test.cpp
index eba1f603..78c72178 100644
--- a/tracker-test/test.cpp
+++ b/tracker-test/test.cpp
@@ -77,7 +77,7 @@ void test_tracker::data(double *data)
}
}
-dialog::dialog()
+test_dialog::test_dialog()
{
ui.setupUi(this);
@@ -85,15 +85,15 @@ dialog::dialog()
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
}
-void dialog::doOK()
+void test_dialog::doOK()
{
//s.b->save();
close();
}
-void dialog::doCancel()
+void test_dialog::doCancel()
{
close();
}
-OPENTRACK_DECLARE_TRACKER(test_tracker, dialog, metadata)
+OPENTRACK_DECLARE_TRACKER(test_tracker, test_dialog, test_metadata)
diff --git a/tracker-test/test.h b/tracker-test/test.h
index fd446f98..8338e8f3 100644
--- a/tracker-test/test.h
+++ b/tracker-test/test.h
@@ -22,13 +22,13 @@ private:
Timer t;
};
-class dialog: public ITrackerDialog
+class test_dialog : public ITrackerDialog
{
Q_OBJECT
Ui::test_ui ui;
public:
- dialog();
+ test_dialog();
void register_tracker(ITracker *) override {}
void unregister_tracker() override {}
private slots:
@@ -36,10 +36,10 @@ private slots:
void doCancel();
};
-class metadata : public Metadata
+class test_metadata : public Metadata
{
public:
- QString name() { return QString(QCoreApplication::translate("metadata", "Testing - sine wave")); }
+ QString name() { return QString(QCoreApplication::translate("test_metadata", "Testing - sine wave")); }
QIcon icon() { return QIcon(":/images/facetracknoir.png"); }
};
diff --git a/tracker-tobii-eyex/CMakeLists.txt b/tracker-tobii-eyex/CMakeLists.txt
index cfbe0160..20f4badd 100644
--- a/tracker-tobii-eyex/CMakeLists.txt
+++ b/tracker-tobii-eyex/CMakeLists.txt
@@ -1,7 +1,7 @@
if(WIN32)
set(SDK_TOBII_EYEX "" CACHE PATH "")
if(SDK_TOBII_EYEX)
- opentrack_boilerplate(opentrack-tracker-tobii-eyex NO-INSTALL)
+ opentrack_boilerplate(opentrack-tracker-tobii-eyex)
target_link_libraries(opentrack-tracker-tobii-eyex opentrack-spline-widget)
set(tobii-libdir ${SDK_TOBII_EYEX}/lib/x86/)
set(tobii-dll ${tobii-libdir}/Tobii.EyeX.Client.dll)
@@ -13,9 +13,7 @@ if(WIN32)
set(tobii-incdir ${SDK_TOBII_EYEX}/include/eyex)
target_include_directories(opentrack-tracker-tobii-eyex SYSTEM PUBLIC ${tobii-incdir})
- if(FALSE)
- install(FILES ${tobii-dll} DESTINATION ${opentrack-hier-pfx} ${opentrack-perms})
- endif()
+ install(FILES ${tobii-dll} DESTINATION ${opentrack-hier-pfx} ${opentrack-perms})
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
file(TO_CMAKE_PATH "$ENV{SystemRoot}" sysroot)
if (IS_DIRECTORY "${sysroot}/SysWOW64")
diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.cpp b/tracker-tobii-eyex/tobii-eyex-dialog.cpp
index bb9ffcea..7f69fa16 100644
--- a/tracker-tobii-eyex/tobii-eyex-dialog.cpp
+++ b/tracker-tobii-eyex/tobii-eyex-dialog.cpp
@@ -11,6 +11,31 @@ tobii_eyex_dialog::tobii_eyex_dialog()
ui.tracking_mode->addItem("Absolute", tobii_absolute);
tie_setting(s.mode, ui.tracking_mode);
+
+ ui.relative_mode_gain->setConfig(&rs.acc_mode_spline);
+ ui.relative_mode_gain->set_preview_only(true);
+
+ tie_setting(rs.dz_len, ui.deadzone);
+ tie_setting(rs.expt_slope, ui.exponent);
+ tie_setting(rs.expt_len, ui.exponent_len);
+ tie_setting(rs.expt_norm, ui.exponent_norm);
+
+ tie_setting(rs.log_slope, ui.log_base);
+ tie_setting(rs.log_len, ui.log_len);
+ tie_setting(rs.log_norm, ui.log_norm);
+
+ connect(rs.b.get(), &bundle_::changed, this, [this]() { rs.make_spline(); }, Qt::QueuedConnection);
+
+ // todo add specialization for label with traits
+#if 0
+ tie_setting(rs.dz_len, ui.deadzone_label);
+ tie_setting(rs.expt_slope, ui.exponent_label);
+ tie_setting(rs.expt_len, ui.exponent_len_label);
+ tie_setting(rs.expt_norm, ui.exponent_norm_label);
+ tie_setting(rs.log_slope, ui.log_base_label);
+ tie_setting(rs.log_len, ui.log_len_label);
+ tie_setting(rs.log_norm, ui.log_norm_label);
+#endif
}
void tobii_eyex_dialog::do_ok()
diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.ui b/tracker-tobii-eyex/tobii-eyex-dialog.ui
index 1a85f417..7a8c92aa 100644
--- a/tracker-tobii-eyex/tobii-eyex-dialog.ui
+++ b/tracker-tobii-eyex/tobii-eyex-dialog.ui
@@ -179,8 +179,8 @@
<property name="verticalSpacing">
<number>3</number>
</property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_11">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -188,7 +188,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Speed</string>
+ <string>Deadzone</string>
</property>
</widget>
</item>
@@ -208,21 +208,8 @@
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Deadzone</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="deadzone_label">
+ <item row="2" column="1">
+ <widget class="QLabel" name="exponent_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -256,21 +243,27 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_10">
+ <item row="2" column="2">
+ <widget class="QSlider" name="exponent">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Exponent</string>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QLabel" name="exponent_label">
+ <item row="1" column="1">
+ <widget class="QLabel" name="deadzone_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -285,27 +278,34 @@
</property>
</widget>
</item>
- <item row="2" column="2">
- <widget class="QSlider" name="exponent">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_11">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <property name="text">
+ <string>Speed</string>
</property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Log segment length</string>
</property>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_5">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -313,7 +313,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Exponential length</string>
+ <string>Exponent</string>
</property>
</widget>
</item>
@@ -333,8 +333,21 @@
</property>
</widget>
</item>
- <item row="3" column="2">
- <widget class="QSlider" name="exponent_len">
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Exponent segment length</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QSlider" name="log_len">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -352,8 +365,8 @@
</property>
</widget>
</item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_7">
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -361,12 +374,12 @@
</sizepolicy>
</property>
<property name="text">
- <string>Linear coefficient</string>
+ <string>Log slope</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QLabel" name="linear_c_label">
+ <item row="6" column="1">
+ <widget class="QLabel" name="log_base_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -381,8 +394,8 @@
</property>
</widget>
</item>
- <item row="4" column="2">
- <widget class="QSlider" name="linear_c">
+ <item row="6" column="2">
+ <widget class="QSlider" name="log_base">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -400,21 +413,27 @@
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_6">
+ <item row="0" column="2">
+ <widget class="QSlider" name="speed">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Linear length</string>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
<item row="5" column="1">
- <widget class="QLabel" name="linear_len_label">
+ <widget class="QLabel" name="log_len_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -429,56 +448,40 @@
</property>
</widget>
</item>
- <item row="5" column="2">
- <widget class="QSlider" name="linear_len">
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_6">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Exponent norm</string>
</property>
</widget>
</item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_8">
+ <item row="4" column="2">
+ <widget class="QSlider" name="exponent_norm">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Logarithm base</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QLabel" name="log_base_label">
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>0</height>
- </size>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- <property name="text">
- <string>0</string>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
- <item row="6" column="2">
- <widget class="QSlider" name="log_base">
+ <item row="3" column="2">
+ <widget class="QSlider" name="exponent_len">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -496,21 +499,24 @@
</property>
</widget>
</item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_9">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="4" column="1">
+ <widget class="QLabel" name="exponent_norm_label">
+ <property name="minimumSize">
+ <size>
+ <width>24</width>
+ <height>0</height>
+ </size>
</property>
<property name="text">
- <string>Logarithm coefficient</string>
+ <string>0</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
- <widget class="QLabel" name="log_c_label">
+ <widget class="QLabel" name="log_norm_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -526,7 +532,7 @@
</widget>
</item>
<item row="7" column="2">
- <widget class="QSlider" name="log_c">
+ <widget class="QSlider" name="log_norm">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -544,22 +550,16 @@
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="QSlider" name="speed">
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_12">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Log norm</string>
</property>
</widget>
</item>
diff --git a/tracker-tobii-eyex/tobii-eyex.cpp b/tracker-tobii-eyex/tobii-eyex.cpp
index 74c31240..1a2f922b 100644
--- a/tracker-tobii-eyex/tobii-eyex.cpp
+++ b/tracker-tobii-eyex/tobii-eyex.cpp
@@ -6,6 +6,8 @@
#include <vector>
#include <algorithm>
#include <iterator>
+#include <utility>
+#include <numeric>
#include <QDebug>
#include <QMutexLocker>
#include <QMessageBox>
@@ -36,51 +38,80 @@ static inline tobii_eyex_tracker& to_self(TX_USERPARAM param)
return *reinterpret_cast<tobii_eyex_tracker*>(param);
}
-template<typename t>
-static constexpr t clamp(t datum, t min, t max)
+// there's an underflow in spline code, can't use 1e0
+static constexpr const double spline_max = 1e2;
+
+void rel_settings::make_spline_(part* functors, unsigned len)
{
- return ((datum > max) ? max : ((datum < min) ? min : datum));
+ acc_mode_spline.removeAllPoints();
+
+ double lastx = 0, lasty = 0;
+
+ using std::accumulate;
+
+ const double inv_norm_y = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.norm; });
+ const double inv_norm_x = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.len; });
+
+ for (unsigned k = 0; k < len; k++)
+ {
+ part& fun = functors[k];
+
+ const double xscale = fun.len * spline_max * inv_norm_x;
+ const double maxx = fun.f(1);
+ const double yscale = fun.norm * spline_max * inv_norm_y * (maxx < 1e-3 ? 0 : 1./maxx);
+
+ for (unsigned i = 0; i <= fun.nparts; i++)
+ {
+ const double x = lastx + (fun.nparts == 0 ? 1 : i) / (1.+fun.nparts) * xscale;
+ const double y = lasty + clamp(fun.f(x) * yscale, 0, spline_max);
+ qDebug() << k << i << x << y;
+ acc_mode_spline.addPoint(x, y);
+ }
+
+ lastx += xscale;
+ lasty += yscale;
+ }
}
-void rel_settings::draw_spline()
+/*
+ def plot(f):
+ rng = arange(-1 + .01, 1, 1e-4)
+ plt.plot(rng, map(f, rng))
+*/
+
+double rel_settings::gain(double value)
{
- spline& spline = acc_mode_spline;
+ return acc_mode_spline.get_value_no_save(value * spline_max) / spline_max;
+}
- spline.removeAllPoints();
+void rel_settings::make_spline()
+{
+ const double log_c = 1./std::log(log_slope());
- static constexpr float std_norm_expt = 1.f/3;
- const float norm_expt = std_norm_expt * float(expt_norm->cur());
- static constexpr float std_norm_lin = 2.f/3;
- const float norm_lin = clamp((1-norm_expt) * lin_norm->cur() * std_norm_lin, 0., 1.);
+ part functors[]
+ {
+ { 1, dz_len(), 0, [](double) { return 0; } },
+ { 5, expt_len(), expt_norm(), [=](double x) { return std::pow(x, expt_slope()); } },
+ { 7, 1 - dz_len() - expt_len() - log_len(), std::max(0., 1 - expt_norm() - log_norm()), [](double x) { return x; } },
+ { 7, log_len(), log_norm(), [=](double x) { return std::log(1+x)*log_c; } },
+ };
+ make_spline_(functors, std::distance(std::begin(functors), std::end(functors)));
}
rel_settings::rel_settings() :
opts("tobii-eyex-relative-mode"),
- speed(b, "speed", s(5, .1, 10)),
- dz_end_pt(b, "deadzone-length", s(4, 0, 15)),
- expt_slope(b, "exponent-slope", s(1.5, 1.25, 3)),
- expt_norm(b, "exponent-norm", s(1, .25, 4)),
- lin_norm(b, "linear-norm", s(1, .25, 4)),
+ speed(b, "speed", s(3, .1, 10)),
+ dz_len(b, "deadzone-length", s(.04, 0, .2)),
+ expt_slope(b, "exponent-slope", s(1.75, 1.25, 3)),
+ expt_len(b, "exponent-length", s(.25, 0, .5)),
+ expt_norm(b, "exponent-norm", s(.3, .1, .5)),
+ log_slope(b, "log-slope", s(2.75, 1.25, 10)),
+ log_len(b, "log-len", s(.1, 0, .2)),
+ log_norm(b, "log-norm", s(.1, .05, .3)),
acc_mode_spline(100, 100, "")
{
- QObject::connect(&dz_end_pt,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&expt_slope,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&expt_norm,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&lin_norm,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- draw_spline();
+ make_spline();
}
tobii_eyex_tracker::tobii_eyex_tracker() :
@@ -287,67 +318,16 @@ void tobii_eyex_tracker::start_tracker(QFrame*)
dbg_verbose("api initialized");
}
-// the gain function was prototyped in python with jupyter qtconsole.
-// you can use qtconsole's inline matplotlib support to see the gain function.
-// the `piecewise' function assumes monotonic growth or constant value for all functions.
-/*
-
-from math import *
-from itertools import izip
-import matplotlib
-import matplotlib.pyplot as plt
-
-try:
- import IPython
- IPython.get_ipython().magic(u'matplotlib inline')
-except:
- pass
-
-def frange(from_, to_, step_=1e-4):
- i = from_
- while True:
- yield i
- i += step_
- if i >= to_:
- break
-
-def plot_fn(fn, from_=0., to_=1., step=None):
- if step is None:
- step = max(1e-4, (to_-from_)*1e-4)
- xs = [i for i in frange(from_, to_, step)]
- plt.plot(xs, map(fn, xs))
-
-def piecewise(x, funs, bounds):
- y = 0.
- last_bound = 0.
- norm = 0.
- for fun in funs:
- norm += fun(1.)
- for fun, bound in izip(funs, bounds):
- if x > bound:
- y += fun(1.)
- else:
- b = bound - last_bound
- x_ = (x - last_bound) / b
- y += fun(x_)
- break
- last_bound = bound
- return y / norm
-
-def f(x): return x**1.75
-def g(x): return 1.75*1.75*x
-def h(x): return log(1+x)/log(2.5)
-def zero(x): return 0.
-
-plot_fn(lambda x: piecewise(x, [zero, f, g, h], [.05, .25, .7, 1.]))
-
-*/
-
tobii_eyex_tracker::num tobii_eyex_tracker::gain(num x_)
{
return 1;
}
+static inline double signum(double x)
+{
+ return !(x < 0) - (x < 0);
+}
+
void tobii_eyex_tracker::data(double* data)
{
TX_REAL px, py, dw, dh, x_, y_;
@@ -378,20 +358,21 @@ void tobii_eyex_tracker::data(double* data)
{
const double dt = t.elapsed_seconds();
t.start();
- // XXX TODO make slider
- static constexpr double v = 300;
- const double x = gain(x_);
- const double y = gain(y_);
+ using std::fabs;
+
+ static constexpr double max_yaw = 45, max_pitch = 30;
+ static constexpr double c_yaw = 3;
+ static constexpr double c_pitch = c_yaw * max_pitch / max_yaw;
- const double yaw_delta = (x * v) * dt;
- const double pitch_delta = (y * -v) * dt;
+ const double yaw_delta = gain(fabs(x_)) * signum(x_) * c_yaw * dt;
+ const double pitch_delta = gain(fabs(y_)) * signum(y_) * c_pitch * dt;
yaw += yaw_delta;
pitch += pitch_delta;
- yaw = clamp(yaw, -180., 180.);
- pitch = clamp(pitch, -60., 60.);
+ yaw = clamp(yaw, -max_yaw, max_yaw);
+ pitch = clamp(pitch, -max_pitch, max_pitch);
}
if (do_center)
diff --git a/tracker-tobii-eyex/tobii-eyex.hpp b/tracker-tobii-eyex/tobii-eyex.hpp
index aeac4d89..68acb25c 100644
--- a/tracker-tobii-eyex/tobii-eyex.hpp
+++ b/tracker-tobii-eyex/tobii-eyex.hpp
@@ -18,9 +18,11 @@ using namespace options;
#include "spline-widget/spline.hpp"
#include "spline-widget/spline-widget.hpp"
+#include <functional>
#include <atomic>
#include <QObject>
#include <QMutex>
+#include <QTimer>
enum tobii_mode
{
@@ -31,13 +33,27 @@ enum tobii_mode
class rel_settings final : public QObject, public opts
{
Q_OBJECT
+
+ using functor = std::function<double(double)>;
+
+ struct part
+ {
+ int nparts;
+ double len, norm;
+ functor f;
+ };
+
+ void make_spline_(part* functors, unsigned len);
+
public:
using s = slider_value;
- value<slider_value> speed, dz_end_pt, expt_slope, expt_norm, lin_norm;
+ value<slider_value> speed, dz_len, expt_slope, expt_len, expt_norm, log_slope, log_len, log_norm;
spline acc_mode_spline;
rel_settings();
-private slots:
- void draw_spline();
+ double gain(double value);
+
+public slots:
+ void make_spline();
};
struct settings final : public opts