diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-05-09 15:34:38 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-05-09 15:34:38 +0200 |
commit | 780aca2622d907320a1cf462390f192fb3ae4b31 (patch) | |
tree | c7843a5ebe0620d8f97ae7ba86ba6f5d06ffc167 | |
parent | c1de1499775d47a574bd52d07acbb269845fb75b (diff) | |
parent | 051fb2f94f6364b80219a3c671bb953d2e54a140 (diff) |
Merge branch 'master' into trackhat-sensor-v2
61 files changed, 1492 insertions, 262 deletions
diff --git a/.clang-tidy b/.clang-tidy index 28fe3584..a29d0ffd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -19,6 +19,8 @@ clang-analyzer-core.CallAndMessage, clang-analyzer-deadcode.DeadStores, -clang-diagnostic-nonportable-include-path, -cppcoreguidelines-avoid-c-arrays, +-cppcoreguidelines-avoid-capture-default-when-capturing-this, +-cppcoreguidelines-avoid-do-while, -cppcoreguidelines-avoid-goto, -cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-c-copy-assignment-signature, @@ -61,6 +63,7 @@ clang-analyzer-deadcode.DeadStores, -hicpp-use-override, -hicpp-vararg, -misc-non-private-member-variables-in-classes, +-misc-use-anonymous-namespace, -modernize-avoid-c-arrays, -modernize-loop-convert, -modernize-pass-by-value, diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ce47a3db..c24e9c99 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -36,7 +36,7 @@ jobs: - uses: seanmiddleditch/gha-setup-ninja@master - name: Install Linux Dependencies - run: sudo apt update && sudo apt install libprocps-dev libopencv-dev libopencv-dev + run: sudo apt update && sudo apt install libprocps-dev libopencv-dev libopencv-dev wine64-tools if: matrix.os == 'ubuntu-latest' - name: Cache Qt diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c6613bd..bb1cfff2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,24 +110,24 @@ otr_merge_translations() include(opentrack-install) string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE) -message(STATUS "-- Compile flags:") +message("Compile flags:") #foreach(j C CXX) foreach(j CXX) foreach(i "" "_${CMAKE_BUILD_TYPE}") - message(STATUS " ${j}${i}: ${CMAKE_${j}_FLAGS${i}}") + message(" ${j}${i}: ${CMAKE_${j}_FLAGS${i}}") endforeach() endforeach() -message(STATUS "-- Link flags:") +message("Link flags:") foreach(j "" "_${CMAKE_BUILD_TYPE}") #foreach(i EXE SHARED) foreach(i SHARED) - message(STATUS " LINK_${i}${j}: ${CMAKE_${i}_LINKER_FLAGS${j}}") + message(" LINK_${i}${j}: ${CMAKE_${i}_LINKER_FLAGS${j}}") endforeach() endforeach() -message(STATUS "-- Static archive flags:") +message("Static archive flags:") foreach(k "" "_${CMAKE_BUILD_TYPE}") - message(STATUS " STATIC${k}: ${CMAKE_STATIC_LINKER_FLAGS${k}}") + message(" STATIC${k}: ${CMAKE_STATIC_LINKER_FLAGS${k}}") endforeach() -message(STATUS "--") +message("--") @@ -1,6 +1,6 @@ ## Intro -[<img src="https://ci.appveyor.com/api/projects/status/n0j9h38jnif5qbe9/branch/unstable?svg=true"/>](https://ci.appveyor.com/project/sthalik/opentrack/branch/unstable) +[<img src="https://github.com/opentrack/opentrack/actions/workflows/cmake.yml/badge.svg">](https://github.com/opentrack/opentrack/actions/workflows/cmake.yml) opentrack project home is located at <<http://github.com/opentrack/opentrack>>. @@ -40,6 +40,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems! - BBC micro:bit, LEGO, sensortag support via Smalltalk<sup>[(1)](https://en.wikipedia.org/wiki/Smalltalk)[(2)](https://en.wikipedia.org/wiki/Alan_Kay)</sup> [S2Bot](http://www.picaxe.com/Teaching/Other-Software/Scratch-Helper-Apps/) - Wiimote (Windows) +- Eyeware Beam<sup>[[1](https://beam.eyeware.tech/)]</sup> ## Output protocols @@ -69,6 +70,7 @@ Don't be afraid to submit an **issue/feature request** if you have any problems! - Wei Shuai (Wiimote tracker) - Stéphane Lenclud (Kinect Face Tracker, Easy Tracker) - GO63-samara (Hamilton Filter, Pose-widget improvement) +- Davide Mameli (Eyeware Beam tracker) ## Thanks diff --git a/api/plugin-api.cpp b/api/plugin-api.cpp index 6a43b55d..4d8d90e9 100644 --- a/api/plugin-api.cpp +++ b/api/plugin-api.cpp @@ -21,7 +21,7 @@ void BaseDialog::done(int) bool BaseDialog::embeddable() noexcept { return false; } void BaseDialog::save() {} void BaseDialog::reload() {} -void BaseDialog::set_buttons_visible(bool x) {} +void BaseDialog::set_buttons_visible(bool) {} } // ns plugin_api::detail @@ -36,13 +36,13 @@ IFilter::IFilter() = default; IFilter::~IFilter() = default; IFilterDialog::IFilterDialog() = default; IFilterDialog::~IFilterDialog() = default; -void IFilterDialog::register_filter(IFilter* filter) {} +void IFilterDialog::register_filter(IFilter*) {} void IFilterDialog::unregister_filter() {} IProtocol::IProtocol() = default; IProtocol::~IProtocol() = default; IProtocolDialog::IProtocolDialog() = default; IProtocolDialog::~IProtocolDialog() = default; -void IProtocolDialog::register_protocol(IProtocol* protocol){} +void IProtocolDialog::register_protocol(IProtocol*){} void IProtocolDialog::unregister_protocol() {} ITracker::ITracker() = default; ITracker::~ITracker() = default; diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index 12470eef..cf3bb0cb 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -37,7 +37,7 @@ add_definitions(-D_HAS_EXCEPTIONS=0) if(DEFINED CMAKE_TOOLCHAIN_FILE) # ignore cmake warning: Manually-specified variable not used by the project - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}}") + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}") endif() include("${CMAKE_CURRENT_LIST_DIR}/opentrack-policy.cmake" NO_POLICY_SCOPE) @@ -106,29 +106,42 @@ if(CMAKE_PROJECT_NAME STREQUAL "OpenCV") set(BUILD_opencv_gapi OFF) endif() +if(CMAKE_PROJECT_NAME STREQUAL "TestOscpack") + add_compile_definitions(OSC_HOST_LITTLE_ENDIAN) +endif() + set(opentrack-simd "SSE2") if(CMAKE_PROJECT_NAME STREQUAL "onnxruntime") set(opentrack-simd "AVX") + if(opentrack-no-static-crt) + sets(BOOL + ONNX_USE_MSVC_STATIC_RUNTIME OFF + protobuf_MSVC_STATIC_RUNTIME OFF + ) + else() + sets(BOOL + ONNX_USE_MSVC_STATIC_RUNTIME ON + protobuf_MSVC_STATIC_RUNTIME ON + ) + endif() sets(BOOL - onnxruntime_USE_AVX ON - onnxruntime_USE_AVX2 OFF - onnxruntime_USE_AVX512 OFF - ONNX_USE_MSVC_STATIC_RUNTIME ON - protobuf_MSVC_STATIC_RUNTIME ON - onnxruntime_BUILD_BENCHMARKS OFF - onnxruntime_BUILD_FOR_NATIVE_MACHINE OFF - onnxruntime_BUILD_SHARED_LIB ON - onnxruntime_BUILD_UNIT_TESTS OFF - protobuf_BUILD_EXAMPLES OFF - protobuf_BUILD_SHARED_LIBS OFF - ONNX_BUILD_BENCHMARKS OFF - ONNX_BUILD_TESTS OFF - ONNX_DISABLE_EXCEPTIONS OFF # important! - ONNX_GEN_PB_TYPE_STUBS OFF - onnxruntime_DISABLE_CONTRIB_OPS ON - BUILD_TESTING OFF + onnxruntime_USE_AVX ON + onnxruntime_USE_AVX2 OFF + onnxruntime_USE_AVX512 OFF + onnxruntime_BUILD_BENCHMARKS OFF + onnxruntime_BUILD_FOR_NATIVE_MACHINE OFF + onnxruntime_BUILD_SHARED_LIB ON + onnxruntime_BUILD_UNIT_TESTS OFF + protobuf_BUILD_EXAMPLES OFF + protobuf_BUILD_SHARED_LIBS OFF + ONNX_BUILD_BENCHMARKS OFF + ONNX_BUILD_TESTS OFF + ONNX_DISABLE_EXCEPTIONS OFF # important! + ONNX_GEN_PB_TYPE_STUBS OFF + onnxruntime_DISABLE_CONTRIB_OPS ON + BUILD_TESTING OFF ) elseif(opentrack-64bit) set(opentrack-simd "AVX") diff --git a/cmake/opentrack-load-user-settings.cmake b/cmake/opentrack-load-user-settings.cmake index 1baf3702..fdb63936 100644 --- a/cmake/opentrack-load-user-settings.cmake +++ b/cmake/opentrack-load-user-settings.cmake @@ -26,12 +26,11 @@ else() set(__sdk_host_os "") endif() -set(__sdk_paths_basename "sdk-paths-${__sdk_username}@${CMAKE_CXX_COMPILER_ID}-${__sdk_host_os}${__sdk_target_os}.cmake") -set(__sdk_paths_filename "${CMAKE_SOURCE_DIR}/${__sdk_paths_basename}") +set(__sdk_paths_filename "${CMAKE_CURRENT_SOURCE_DIR}/sdk-paths-${__sdk_username}@${CMAKE_CXX_COMPILER_ID}-${__sdk_host_os}${__sdk_target_os}.cmake") if(EXISTS "${__sdk_paths_filename}") - message(STATUS "Loading user settings '${__sdk_paths_basename}'") + message(STATUS "Loading user settings '${__sdk_paths_filename}'") include("${__sdk_paths_filename}") else() - message(STATUS "User settings file '${__sdk_paths_basename}' doesn't exist") + message(STATUS "User settings file '${__sdk_paths_filename}' doesn't exist") endif() diff --git a/cmake/opentrack-platform.cmake b/cmake/opentrack-platform.cmake index fd82c1b5..7aceb17a 100644 --- a/cmake/opentrack-platform.cmake +++ b/cmake/opentrack-platform.cmake @@ -34,8 +34,6 @@ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "" FORCE) include_directories("${CMAKE_SOURCE_DIR}") -set(opentrack_maintainer-mode FALSE CACHE INTERNAL "Select if developing core code (not modules)") - set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_CXX_STANDARD 20) diff --git a/cmake/opentrack-qt.cmake b/cmake/opentrack-qt.cmake index 800e9096..1735e836 100644 --- a/cmake/opentrack-qt.cmake +++ b/cmake/opentrack-qt.cmake @@ -51,7 +51,7 @@ function(otr_qt n) endfunction() function(otr_qt2 n) - target_include_directories("${n}" PRIVATE SYSTEM + target_include_directories("${n}" SYSTEM PRIVATE ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ) target_compile_definitions("${n}" PRIVATE diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index ac4117bc..9cd416ee 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -172,7 +172,7 @@ options_dialog::options_dialog(std::unique_ptr<ITrackerDialog>& tracker_dialog_, val.label, [=](const QString&) { val.label->setText(kopts_to_string(val.opt)); }); { - connect(val.button, &QPushButton::clicked, this, [=] { bind_key(val.opt, val.label); }); + connect(val.button, &QPushButton::clicked, this, [=, this] { bind_key(val.opt, val.label); }); } } diff --git a/opentrack/main-window.cpp b/opentrack/main-window.cpp index 754d7e7c..f449845b 100644 --- a/opentrack/main-window.cpp +++ b/opentrack/main-window.cpp @@ -18,7 +18,6 @@ #include "compat/math.hpp" #include "compat/sysexits.hpp" #include "opentrack/defs.hpp" -#include "software-update-dialog.hpp" #include <cstring> #include <utility> @@ -34,7 +33,6 @@ #include <QDateTime> extern "C" const char* const opentrack_version; -extern "C" OTR_GENERIC_IMPORT bool opentrack_using_dark_theme; using namespace options::globals; using namespace options; @@ -60,8 +58,6 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) setVisible(!start_in_tray()); ensure_tray(); - ui.pose_display->set_grid_background(opentrack_using_dark_theme); - connect(&pose_update_timer, &QTimer::timeout, this, &main_window::show_pose, Qt::DirectConnection); connect(&det_timer, &QTimer::timeout, @@ -74,13 +70,7 @@ main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) #ifdef UI_NO_VIDEO_FEED fake_video_frame.resize(640, 480); fake_video_frame_parent.setVisible(false); -#elif defined UI_COMPACT_VIDEO_FEED - connect(ui.preview_checkbox, &QCheckBox::toggled, this, &main_window::toggle_video_preview); #endif - - updater = std::make_unique<update_query>(this); - updater->maybe_show_dialog(); - } void main_window::init_shortcuts() @@ -429,12 +419,7 @@ void main_window::update_button_state(bool running, bool inertialp) ui.iconcomboTrackerSource->setEnabled(not_running); #endif ui.profile_button->setEnabled(not_running); -#ifdef UI_COMPACT_VIDEO_FEED - ui.preview_checkbox->setChecked(false); - ui.preview_checkbox->raise(); - ui.preview_checkbox->setVisible(running && !inertialp); - toggle_video_preview(false); -#elif !defined UI_NO_VIDEO_FEED +#ifndef UI_NO_VIDEO_FEED ui.video_frame_label->setVisible(not_running || inertialp); if(not_running) { @@ -446,22 +431,6 @@ void main_window::update_button_state(bool running, bool inertialp) #endif } -#ifdef UI_COMPACT_VIDEO_FEED -void main_window::toggle_video_preview(bool value) -{ - value &= ui.video_frame->layout() != nullptr; - ui.video_frame_parent->setVisible(value); - ui.video_frame_parent->raise(); - ui.video_frame->raise(); - ui.pose_display->setVisible(!value); - ui.preview_checkbox->raise(); - if (value) - ui.preview_checkbox->setStyleSheet("QCheckBox { color: #32CD32 }"); - else - ui.preview_checkbox->setStyleSheet(""); -} -#endif - void main_window::start_tracker_() { if (work) @@ -502,7 +471,7 @@ void main_window::start_tracker_() options_widget->register_filter(&*work->libs.pFilter); } - pose_update_timer.start((int)(1000./30)); + pose_update_timer.start(1000/30); // NB check valid since SelectedLibraries ctor called // trackers take care of layout state updates @@ -714,7 +683,6 @@ static void show_module_settings(std::shared_ptr<Instance> instance, void(Dialog::*register_fun)(Instance*), void(options_dialog::*switch_tab_fun)()) { - using BaseDialog = plugin_api::detail::BaseDialog; if (!lib || !lib->Dialog) return; diff --git a/options/base-value.cpp b/options/base-value.cpp index 9ccbbdf8..950629d0 100644 --- a/options/base-value.cpp +++ b/options/base-value.cpp @@ -29,5 +29,5 @@ value_::~value_() void value_::maybe_trace(const char* str) const { if (TRACE_NOTIFY) - qDebug().noquote() << str << QThread::currentThreadId() << b->name() << self_name; + qDebug().noquote() << str << QThread::currentThreadId() << b->name() << self_name << get_variant(); } diff --git a/options/tie.cpp b/options/tie.cpp index c2976217..adf26b53 100644 --- a/options/tie.cpp +++ b/options/tie.cpp @@ -28,8 +28,12 @@ void tie_setting(value<QString>& v, QComboBox* cb) { cb->setCurrentText(v); v = cb->currentText(); - value_::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(const QString&)), v.DIRECT_CONNTYPE); - value_::connect(&v, SIGNAL(valueChanged(const QString&)), cb, SLOT(setCurrentText(const QString&)), v.SAFE_CONNTYPE); + auto set_current_text = [cb, &v](const QString& str) { + cb->setCurrentText(str); + v = cb->currentText(); + }; + value_::connect(cb, &QComboBox::currentTextChanged, &v, v.value_changed<QString>(), v.DIRECT_CONNTYPE); + value_::connect(&v, v.value_changed<QString>(), cb, set_current_text, v.SAFE_CONNTYPE); } void tie_setting(value<QVariant>& v, QComboBox* cb) diff --git a/options/value.hpp b/options/value.hpp index dacd0ea9..9a7487b8 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -137,6 +137,7 @@ public: return *this; store_variant(traits::qvariant_from_value(traits::pass_value(datum))); + maybe_trace("set-value"); return *this; } diff --git a/proto-osc/CMakeLists.txt b/proto-osc/CMakeLists.txt new file mode 100644 index 00000000..eeaf206c --- /dev/null +++ b/proto-osc/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SDK_OSCPACK "" CACHE PATH "oscpack build directory") +if(SDK_OSCPACK) + if(WIN32) + if(NOT EXISTS "${SDK_OSCPACK}/include/.") + message(FATAL_ERROR "SDK_OSCPACK should have 'include' subdirectory (or symlink) to src dir") + endif() + link_directories("${SDK_OSCPACK}") + include_directories("${SDK_OSCPACK}/include" "${SDK_OSCPACK}/include/oscpack") + else() + link_directories("${SDK_OSCPACK}/lib" "${SDK_OSCPACK}/lib32") + include_directories("${SDK_OSCPACK}/include/oscpack") + endif() + link_libraries(oscpack) + otr_module(proto-osc) +endif() diff --git a/proto-osc/dialog.cpp b/proto-osc/dialog.cpp new file mode 100644 index 00000000..54bf6885 --- /dev/null +++ b/proto-osc/dialog.cpp @@ -0,0 +1,38 @@ +#include "dialog.hpp" +#include <QHostAddress> +#include <QPalette> + +void osc_dialog::host_address_edited(const QString& str) +{ + bool bad = QHostAddress{str}.isNull(); + auto pal = pal_; + for (auto role : { QPalette::Highlight, QPalette::Window }) + if (bad) + pal.setColor(role, Qt::red); + ui.address->setPalette(pal); +} + +osc_dialog::osc_dialog() : + pal_{palette()} +{ + ui.setupUi( this ); + + tie_setting(s.address, ui.address); + tie_setting(s.port, ui.port); + connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &osc_dialog::doOK); + connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &osc_dialog::doCancel); + connect(ui.address, &QLineEdit::textChanged, this, &osc_dialog::host_address_edited); + host_address_edited(ui.address->text()); +} + +void osc_dialog::save() { s.b->save(); } +void osc_dialog::reload() { s.b->reload(); } + +void osc_dialog::doOK() { s.b->save(); close(); } +void osc_dialog::doCancel() { close(); } + +void osc_dialog::register_protocol(IProtocol*) {} +void osc_dialog::unregister_protocol() {} + +bool osc_dialog::embeddable() noexcept { return true; } +void osc_dialog::set_buttons_visible(bool x) noexcept { ui.buttonBox->setVisible(x); } diff --git a/proto-osc/dialog.hpp b/proto-osc/dialog.hpp new file mode 100644 index 00000000..29682843 --- /dev/null +++ b/proto-osc/dialog.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "settings.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" + +class osc_dialog: public IProtocolDialog +{ + Q_OBJECT + +public: + osc_dialog(); + void register_protocol(IProtocol*) override; + void unregister_protocol() override; +private: + void set_buttons_visible(bool x) noexcept override; + bool embeddable() noexcept override; + void save() override; + void reload() override; + + Ui_OSC_Dialog ui; + osc_settings s; + const QPalette pal_; + +private slots: + void doOK(); + void doCancel(); + void host_address_edited(const QString& str); +}; diff --git a/proto-osc/dialog.ui b/proto-osc/dialog.ui new file mode 100644 index 00000000..5a078bbd --- /dev/null +++ b/proto-osc/dialog.ui @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>OSC_Dialog</class> + <widget class="QWidget" name="OSC_Dialog"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>284</width> + <height>102</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>284</width> + <height>102</height> + </size> + </property> + <property name="windowTitle"> + <string>OSC protocol settings</string> + </property> + <property name="windowIcon"> + <iconset resource="osc-res.qrc"> + <normaloff>:/images/osc-icon.png</normaloff>:/images/osc-icon.png</iconset> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Destination address</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="address"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + <property name="maxLength"> + <number>256</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Port</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="port"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../gui/opentrack-res.qrc"/> + <include location="osc-res.qrc"/> + </resources> + <connections/> + <designerdata> + <property name="gridDeltaX"> + <number>5</number> + </property> + <property name="gridDeltaY"> + <number>5</number> + </property> + <property name="gridSnapX"> + <bool>true</bool> + </property> + <property name="gridSnapY"> + <bool>true</bool> + </property> + <property name="gridVisible"> + <bool>false</bool> + </property> + </designerdata> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/proto-osc/images/osc-icon.png b/proto-osc/images/osc-icon.png Binary files differnew file mode 100644 index 00000000..3ef546e9 --- /dev/null +++ b/proto-osc/images/osc-icon.png diff --git a/proto-osc/lang/nl_NL.ts b/proto-osc/lang/nl_NL.ts new file mode 100644 index 00000000..260b7adc --- /dev/null +++ b/proto-osc/lang/nl_NL.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/ru_RU.ts b/proto-osc/lang/ru_RU.ts new file mode 100644 index 00000000..498d68d6 --- /dev/null +++ b/proto-osc/lang/ru_RU.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/stub.ts b/proto-osc/lang/stub.ts new file mode 100644 index 00000000..20828cbd --- /dev/null +++ b/proto-osc/lang/stub.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/lang/zh_CN.ts b/proto-osc/lang/zh_CN.ts new file mode 100644 index 00000000..e0d49844 --- /dev/null +++ b/proto-osc/lang/zh_CN.ts @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> + <name>OSC_Dialog</name> + <message> + <source>OSC protocol settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Destination address</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_metadata</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>osc_proto</name> + <message> + <source>Open Sound Control</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Error binding socket to INADDR_ANY</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>%1: %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid destination address '%1'</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/proto-osc/metadata.cpp b/proto-osc/metadata.cpp new file mode 100644 index 00000000..9d69347d --- /dev/null +++ b/proto-osc/metadata.cpp @@ -0,0 +1,8 @@ +#include "metadata.hpp" +#include "proto.hpp" +#include "dialog.hpp" + +QString osc_metadata::name() { return tr("Open Sound Control"); } +QIcon osc_metadata::icon() { return QIcon(":/images/osc-icon.png"); } + +OPENTRACK_DECLARE_PROTOCOL(osc_proto, osc_dialog, osc_metadata) diff --git a/proto-osc/metadata.hpp b/proto-osc/metadata.hpp new file mode 100644 index 00000000..c0a947aa --- /dev/null +++ b/proto-osc/metadata.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "api/plugin-api.hpp" + +class osc_metadata : public Metadata +{ + Q_OBJECT + + QString name() override; + QIcon icon() override; +}; diff --git a/proto-osc/osc-res.qrc b/proto-osc/osc-res.qrc new file mode 100644 index 00000000..ade4c629 --- /dev/null +++ b/proto-osc/osc-res.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>images/osc-icon.png</file> + </qresource> +</RCC> diff --git a/proto-osc/proto.cpp b/proto-osc/proto.cpp new file mode 100644 index 00000000..2f90957c --- /dev/null +++ b/proto-osc/proto.cpp @@ -0,0 +1,54 @@ +#include "proto.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" +#include <QQuaternion> +#include <QHostAddress> +#include "osc/OscOutboundPacketStream.h" + +osc_proto::osc_proto() +{ + auto reload_fn = [this] { + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + }; + connect(&*s.b, &bundle_::changed, this, reload_fn); + connect(&*s.b, &bundle_::reloading, this, reload_fn); +} + +void osc_proto::pose(const double* data, const double*) +{ + if (dest.isNull()) + return; + + static constexpr unsigned buffer_size = 1024; + char buffer[buffer_size] = {}; + osc::OutboundPacketStream p{buffer, buffer_size}; + auto q = QQuaternion::fromEulerAngles((float)data[Pitch], (float)data[Yaw], (float)-data[Roll]).normalized(); + p << osc::BeginMessage("/bridge/quat") << q.scalar() << q.x() << q.y() << q.z() << osc::EndMessage; + sock.writeDatagram(p.Data(), (int)p.Size(), dest, port); +} + +module_status osc_proto::initialize() +{ + QString error; + + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + + if (dest.isNull()) + { + error = tr("Invalid destination address '%1'").arg(s.address); + goto fail; + } + + if (!sock.bind()) + { + error = tr("Error binding socket to INADDR_ANY"); + goto fail; + } + + return status_ok(); + +fail: + return { tr("%1: %2").arg(error, sock.errorString()) }; +} diff --git a/proto-osc/proto.hpp b/proto-osc/proto.hpp new file mode 100644 index 00000000..53a5dee4 --- /dev/null +++ b/proto-osc/proto.hpp @@ -0,0 +1,29 @@ +#pragma once + +/* Copyright (c) 2023 Stanislaw Halik <sthalik@misaki.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "settings.hpp" +#include "api/plugin-api.hpp" +#include <QUdpSocket> +#include <QHostAddress> + +class osc_proto : public QObject, public IProtocol +{ + Q_OBJECT + + osc_settings s; + QUdpSocket sock; + QHostAddress dest; + unsigned short port = 0; + +public: + osc_proto(); + module_status initialize() override; + void pose(const double *headpose, const double*) override; + QString game_name() override { return tr("Open Sound Control"); } +}; diff --git a/proto-osc/settings.hpp b/proto-osc/settings.hpp new file mode 100644 index 00000000..edeb45c6 --- /dev/null +++ b/proto-osc/settings.hpp @@ -0,0 +1,14 @@ +#pragma once +#include <QString> +#include "options/options.hpp" + +using namespace options; + +struct osc_settings : opts +{ + value<QString> address; + value<int> port; + osc_settings() : opts("proto-osc"), address{b, "address", "127.0.0.1"}, + port(b, "port", 53101) + {} +}; diff --git a/proto-wine/CMakeLists.txt b/proto-wine/CMakeLists.txt index 0beb50e1..ff4932cc 100644 --- a/proto-wine/CMakeLists.txt +++ b/proto-wine/CMakeLists.txt @@ -17,10 +17,14 @@ if(NOT WIN32) endif() file(GLOB wine-deps "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx") #install(FILES ${wine-deps} DESTINATION "${opentrack-src}/proto-wine") + set(winegxx-multilib "-m32") + if (NOT OPENTRACK_WINE_ARCH STREQUAL "") + set(winegxx-multilib "${OPENTRACK_WINE_ARCH}") + endif() add_custom_command( OUTPUT opentrack-wrapper-wine.exe.so DEPENDS ${wine-deps} - COMMAND wineg++ -mconsole -g -DNOMINMAX -O2 -m32 -std=c++17 -fPIC -o + COMMAND wineg++ -mconsole -g -DNOMINMAX -O2 ${winegxx-multilib} -std=c++17 -fPIC -o opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}" -I "${CMAKE_BINARY_DIR}" ${wine-deps} -Wall -Wextra -Wpedantic ${my-rt}) diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index af53ff1f..75526c54 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -44,6 +44,7 @@ void wine::pose(const double *headpose, const double*) #ifndef OTR_WINE_NO_WRAPPER if (shm->gameid != gameid) { + //qDebug() << "proto/wine: looking up gameData"; QString gamename; QMutexLocker foo(&game_name_mutex); /* only EZCA for FSX requires dummy process, and FSX doesn't work on Linux */ @@ -63,6 +64,22 @@ module_status wine::initialize() static const QString library_path(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH); QString wine_path = "wine"; + if (s.wine_select_path().toString() != "WINE") { + // if we are not supposed to use system wine then: + if (s.wine_select_path().toString() != "CUSTOM") { + // if we don't have a custom path then change the wine_path to the path corresponding to the selected version + wine_path = s.wine_select_path().toString(); + } + else if (!s.wine_custom_path->isEmpty()) { + // if we do have a custom path and it is not empty then + wine_path = s.wine_custom_path; + } + } + if (wine_path[0] == '~') + wine_path = qgetenv("HOME") + wine_path.mid(1); + + qDebug() << "proto/wine: wine_path:" << wine_path; + auto env = QProcessEnvironment::systemEnvironment(); if (s.variant_proton) @@ -91,6 +108,8 @@ module_status wine::initialize() if (wineprefix[0] != '/') return error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix)); + qDebug() << "proto/wine: wineprefix:" << wineprefix; + env.insert("WINEPREFIX", wineprefix); } @@ -104,12 +123,24 @@ module_status wine::initialize() wrapper.setProcessEnvironment(env); wrapper.setWorkingDirectory(OPENTRACK_BASE_PATH); wrapper.start(wine_path, { library_path + "opentrack-wrapper-wine.exe.so" }); + wrapper.waitForStarted(); + if (wrapper.state() == QProcess::ProcessState::NotRunning) { + return error(tr("Failed to start Wine! Make sure the binary is set correctly.")); + } #endif if (lck_shm.success()) { shm = (WineSHM*) lck_shm.ptr(); memset(shm, 0, sizeof(*shm)); + + qDebug() << "proto/wine: shm success"; + + // display "waiting for game message" (overwritten once a game is detected) + connected_game = "waiting for game..."; + } + else { + qDebug() << "proto/wine: shm no success"; } if (lck_shm.success()) diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h index f7346be9..f79f65dc 100644 --- a/proto-wine/ftnoir_protocol_wine.h +++ b/proto-wine/ftnoir_protocol_wine.h @@ -26,7 +26,9 @@ struct settings : opts value<int> proton_appid{b, "proton-appid", 0}; value<QVariant> proton_path{b, "proton-version", {} }; - value<QString> wineprefix{b, "wineprefix", "~/.wine"}; + value<QVariant> wine_select_path{b, "wine-select-version", {"WINE"}}; + value<QString> wine_custom_path{b, "wine-custom-version", ""}; + value<QString> wineprefix{b, "wineprefix", "~/.wine/"}; value<int> protocol{b, "protocol", 2}; }; @@ -77,6 +79,11 @@ private: settings s; private slots: + void onWinePathComboUpdated(QString selection); + + void doBrowseWine(); + void doBrowsePrefix(); + void doOK(); void doCancel(); }; diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp index a954a752..07dc1469 100644 --- a/proto-wine/ftnoir_protocol_wine_dialog.cpp +++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp @@ -1,9 +1,20 @@ #include "ftnoir_protocol_wine.h" #include <QDebug> +#include <QFileDialog> #include <QDir> #include "api/plugin-api.hpp" +/* + * 0: path to the directory with wine versions + * 1: path from a wine version to the exectuable + * 2: name of the application using the wine versions + */ +static const char* wine_paths[][3] = { + {"/.local/share/lutris/runners/wine/", "/bin/wine", "Lutris"}, + {"/.var/app/net.lutris.Lutris/data/lutris/runners/wine/", "/bin/wine", "Flatpak Lutris"} +}; + static const char* proton_paths[] = { "/.steam/steam/steamapps/common", "/.steam/root/compatibilitytools.d", @@ -14,6 +25,23 @@ FTControls::FTControls() { ui.setupUi(this); + //populate wine select + ui.wine_path_combo->addItem("System Wine", QVariant{"WINE"}); + for (const char** path : wine_paths) { + QDir dir(QDir::homePath() + path[0]); + dir.setFilter(QDir::Dirs); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.fileName() == "." || fileInfo.fileName() == "..") continue; + + QString name = fileInfo.fileName() + " (" + path[2] + ")"; + ui.wine_path_combo->addItem(name, QVariant{fileInfo.filePath() + path[1]}); + } + } + ui.wine_path_combo->addItem("Custom path to Wine executable", QVariant{"CUSTOM"}); + + //populate proton select for (const char* path : proton_paths) { QDir dir(QDir::homePath() + path); dir.setFilter(QDir::Dirs); @@ -24,17 +52,62 @@ FTControls::FTControls() ui.proton_version->addItem(fileInfo.fileName(), QVariant{fileInfo.filePath()}); } } + tie_setting(s.proton_path, ui.proton_version); tie_setting(s.variant_wine, ui.variant_wine); tie_setting(s.variant_proton, ui.variant_proton); tie_setting(s.esync, ui.esync); tie_setting(s.fsync, ui.fsync); tie_setting(s.proton_appid, ui.proton_appid); + tie_setting(s.wine_select_path, ui.wine_path_combo); + tie_setting(s.wine_custom_path, ui.wine_path); tie_setting(s.wineprefix, ui.wineprefix); tie_setting(s.protocol, ui.protocol_selection); + connect(ui.wine_path_combo, &QComboBox::currentTextChanged, this, &FTControls::onWinePathComboUpdated); + connect(ui.browse_wine_path_button, &QPushButton::clicked, this, &FTControls::doBrowseWine); + connect(ui.browse_wine_prefix_button, &QPushButton::clicked, this, &FTControls::doBrowsePrefix); connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &FTControls::doOK); connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &FTControls::doCancel); + + // update state of the combo box and associated ui elements + onWinePathComboUpdated(ui.wine_path_combo->currentText()); +} + +void FTControls::onWinePathComboUpdated(QString selection) { + // enable the custom text field if required + if (selection == "Custom path to Wine executable") { + ui.wine_path->setEnabled(true); + ui.browse_wine_path_button->setEnabled(true); + } + else { + ui.wine_path->setEnabled(false); + ui.browse_wine_path_button->setEnabled(false); + } +} + +void FTControls::doBrowseWine() { + QFileDialog d(this); + d.setFileMode(QFileDialog::FileMode::ExistingFile); + d.setWindowTitle(tr("Select path to Wine Binary")); + if (s.wine_custom_path->startsWith("~/.local/share/lutris/runners")) { + d.selectFile(s.wine_custom_path); + } + if (d.exec()) { + s.wine_custom_path = d.selectedFiles()[0]; + } +} +void FTControls::doBrowsePrefix() { + QFileDialog d(this); + d.setFileMode(QFileDialog::FileMode::Directory); + d.setOption(QFileDialog::Option::ShowDirsOnly, true); + d.setWindowTitle(tr("Select Wine Prefix")); + if (s.wineprefix->startsWith("/") || s.wineprefix->startsWith("~")) { + d.selectFile(s.wineprefix); + } + if (d.exec()) { + s.wineprefix = d.selectedFiles()[0]; + } } void FTControls::doOK() diff --git a/proto-wine/ftnoir_winecontrols.ui b/proto-wine/ftnoir_winecontrols.ui index e9541447..365922ca 100644 --- a/proto-wine/ftnoir_winecontrols.ui +++ b/proto-wine/ftnoir_winecontrols.ui @@ -9,7 +9,7 @@ <rect> <x>0</x> <y>0</y> - <width>528</width> + <width>951</width> <height>424</height> </rect> </property> @@ -33,8 +33,8 @@ <string>Wine variant</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QRadioButton" name="variant_wine"> + <item row="10" column="0"> + <widget class="QRadioButton" name="variant_proton"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -42,55 +42,120 @@ </sizepolicy> </property> <property name="text"> - <string>Wine (system)</string> + <string>Proton (Steam Play)</string> </property> </widget> </item> - <item row="2" column="1" alignment="Qt::AlignRight"> - <widget class="QComboBox" name="proton_version"> + <item row="0" column="0"> + <widget class="QRadioButton" name="variant_wine"> <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize"> - <size> - <width>120</width> - <height>0</height> - </size> + <property name="text"> + <string>Wine (select path and prefix)</string> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="wineprefix"> + <item row="10" column="1"> + <widget class="QComboBox" name="proton_version"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>286</width> + <width>120</width> <height>0</height> </size> </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QRadioButton" name="variant_proton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Proton (Steam Play)</string> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> </property> </widget> </item> + <item row="9" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLineEdit" name="wineprefix"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>450</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string><html><head/><body><p>prefix</p></body></html></string> + </property> + <property name="placeholderText"> + <string>/path_to_the_prefix/</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="browse_wine_prefix_button"> + <property name="text"> + <string>Browse Prefix</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="8" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLineEdit" name="wine_path"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>450</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string><html><head/><body><p>wine/runner exectuable path</p></body></html></string> + </property> + <property name="inputMask"> + <string/> + </property> + <property name="placeholderText"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="browse_wine_path_button"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Browse Wine Path</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="wine_path_combo"/> + </item> </layout> </widget> </item> diff --git a/proto-wine/lang/nl_NL.ts b/proto-wine/lang/nl_NL.ts index e2183cc8..0298092b 100644 --- a/proto-wine/lang/nl_NL.ts +++ b/proto-wine/lang/nl_NL.ts @@ -2,17 +2,24 @@ <!DOCTYPE TS> <TS version="2.1" language="nl_NL"> <context> - <name>UICFTControls</name> + <name>FTControls</name> <message> - <source>Wine settings</source> + <source>Select path to Wine Binary</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine variant</source> + <source>Select Wine Prefix</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>UICFTControls</name> + <message> + <source>Wine settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine (system)</source> + <source>Wine variant</source> <translation type="unfinished"></translation> </message> <message> @@ -55,6 +62,30 @@ <source>Both</source> <translation type="unfinished"></translation> </message> + <message> + <source>Wine (select path and prefix)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>prefix</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>/path_to_the_prefix/</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Prefix</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>wine/runner exectuable path</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Wine Path</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> @@ -70,6 +101,10 @@ <source>Wine prefix must be an absolute path (given '%1')</source> <translation type="unfinished"></translation> </message> + <message> + <source>Failed to start Wine! Make sure the binary is set correctly.</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine_metadata</name> diff --git a/proto-wine/lang/ru_RU.ts b/proto-wine/lang/ru_RU.ts index f3b44bd2..c7e9c52e 100644 --- a/proto-wine/lang/ru_RU.ts +++ b/proto-wine/lang/ru_RU.ts @@ -2,17 +2,24 @@ <!DOCTYPE TS> <TS version="2.1" language="ru_RU"> <context> - <name>UICFTControls</name> + <name>FTControls</name> <message> - <source>Wine settings</source> + <source>Select path to Wine Binary</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine variant</source> + <source>Select Wine Prefix</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>UICFTControls</name> + <message> + <source>Wine settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine (system)</source> + <source>Wine variant</source> <translation type="unfinished"></translation> </message> <message> @@ -55,6 +62,30 @@ <source>Both</source> <translation type="unfinished"></translation> </message> + <message> + <source>Wine (select path and prefix)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>prefix</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>/path_to_the_prefix/</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Prefix</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>wine/runner exectuable path</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Wine Path</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> @@ -70,6 +101,10 @@ <source>Wine prefix must be an absolute path (given '%1')</source> <translation type="unfinished"></translation> </message> + <message> + <source>Failed to start Wine! Make sure the binary is set correctly.</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine_metadata</name> diff --git a/proto-wine/lang/stub.ts b/proto-wine/lang/stub.ts index dd4f946f..3366b44b 100644 --- a/proto-wine/lang/stub.ts +++ b/proto-wine/lang/stub.ts @@ -2,17 +2,24 @@ <!DOCTYPE TS> <TS version="2.1"> <context> - <name>UICFTControls</name> + <name>FTControls</name> <message> - <source>Wine settings</source> + <source>Select path to Wine Binary</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine variant</source> + <source>Select Wine Prefix</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>UICFTControls</name> + <message> + <source>Wine settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine (system)</source> + <source>Wine variant</source> <translation type="unfinished"></translation> </message> <message> @@ -55,6 +62,30 @@ <source>Both</source> <translation type="unfinished"></translation> </message> + <message> + <source>Wine (select path and prefix)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>prefix</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>/path_to_the_prefix/</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Prefix</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>wine/runner exectuable path</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Wine Path</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> @@ -70,6 +101,10 @@ <source>Wine prefix must be an absolute path (given '%1')</source> <translation type="unfinished"></translation> </message> + <message> + <source>Failed to start Wine! Make sure the binary is set correctly.</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine_metadata</name> diff --git a/proto-wine/lang/zh_CN.ts b/proto-wine/lang/zh_CN.ts index b7c9ea7d..0d285c7c 100644 --- a/proto-wine/lang/zh_CN.ts +++ b/proto-wine/lang/zh_CN.ts @@ -2,17 +2,24 @@ <!DOCTYPE TS> <TS version="2.1" language="zh_CN"> <context> - <name>UICFTControls</name> + <name>FTControls</name> <message> - <source>Wine settings</source> + <source>Select path to Wine Binary</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine variant</source> + <source>Select Wine Prefix</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>UICFTControls</name> + <message> + <source>Wine settings</source> <translation type="unfinished"></translation> </message> <message> - <source>Wine (system)</source> + <source>Wine variant</source> <translation type="unfinished"></translation> </message> <message> @@ -55,6 +62,30 @@ <source>Both</source> <translation type="unfinished"></translation> </message> + <message> + <source>Wine (select path and prefix)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>prefix</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>/path_to_the_prefix/</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Prefix</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><html><head/><body><p>wine/runner exectuable path</p></body></html></source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Browse Wine Path</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine</name> @@ -70,6 +101,10 @@ <source>Wine prefix must be an absolute path (given '%1')</source> <translation type="unfinished"></translation> </message> + <message> + <source>Failed to start Wine! Make sure the binary is set correctly.</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>wine_metadata</name> diff --git a/sdk-paths-runner@GNU-Linux.cmake b/sdk-paths-runner@GNU-Linux.cmake new file mode 100644 index 00000000..03c87ce4 --- /dev/null +++ b/sdk-paths-runner@GNU-Linux.cmake @@ -0,0 +1,3 @@ +set(SDK_WINE ON CACHE BOOL "" FORCE) +set(OPENTRACK_WINE_ARCH -m64 CACHE STRING "" FORCE) +set(ENV{PATH} "/usr/lib/wine:$ENV{PATH}") diff --git a/sdk-paths-sthalik@MSVC-windows.cmake b/sdk-paths-sthalik@MSVC-windows.cmake index 7df31152..340b78ad 100644 --- a/sdk-paths-sthalik@MSVC-windows.cmake +++ b/sdk-paths-sthalik@MSVC-windows.cmake @@ -18,27 +18,39 @@ function(setq name value) endfunction() set(opentrack_install-debug-info TRUE CACHE INTERNAL "" FORCE) -set(opentrack_maintainer-mode TRUE CACHE INTERNAL "" FORCE) setq(EIGEN3_INCLUDE_DIR "eigen") -setq(OpenCV_DIR "opencv/build/install") -setq(SDL2_DIR "SDL2-win32") -setq(SDK_ARUCO_LIBPATH "aruco/build/src/aruco.lib") -setq(SDK_FSUIPC "fsuipc") -setq(SDK_HYDRA "SixenseSDK") +setq(SDK_RIFT_140 "ovr_sdk_win_23.0.0/LibOVR") setq(SDK_KINECT20 "Kinect-v2.0") -setq(SDK_LIBUSB "libusb-msvc-x86") +setq(SDK_VJOYSTICK "vjoystick") setq(SDK_PS3EYEDRIVER "PS3EYEDriver") setq(SDK_REALSENSE "RSSDK-R2") -setq(SDK_RIFT_140 "ovr_sdk_win_23.0.0/LibOVR") setq(SDK_VALVE_STEAMVR "steamvr") -setq(SDK_VJOYSTICK "vjoystick") -setq(ONNXRuntime_DIR "onnxruntime-1.12.1") -setq(SDK_TRACKHAT_SENSOR "../trackhat/trackhat-c-library-driver/build/install") +setq(SDK_FSUIPC "fsuipc") +setq(SDK_HYDRA "SixenseSDK") +setq(SDK_EYEWARE_BEAM "eyeware-beam-sdk") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) +setq(Qt5_DIR "../qt-5.15-kde-amd64/lib/cmake/Qt5") +setq(OpenCV_DIR "opencv/build-amd64/install") +setq(SDK_ARUCO_LIBPATH "aruco/build-amd64/src/aruco.lib") +setq(SDK_LIBUSB "libusb-msvc-amd64") +setq(ONNXRuntime_DIR "onnxruntime-1.14.1-amd64") +setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build-amd64/install") +setq(SDK_OSCPACK "oscpack/build-amd64") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) +setq(Qt5_DIR "../qt-5.15-kde/lib/cmake/Qt5") +setq(OpenCV_DIR "opencv/build/install") +setq(SDK_ARUCO_LIBPATH "aruco/build/src/aruco.lib") +setq(SDK_LIBUSB "libusb-msvc-x86") +setq(ONNXRuntime_DIR "onnxruntime-1.14.1") +setq(SDK_TRACKHAT_SENSOR "trackhat-c-library-driver/build/install") +setq(SDK_OSCPACK "oscpack/build") +else() + message(FATAL_ERROR "unknown word size ${CMAKE_SIZEOF_VOID_P}b") +endif() set(CMAKE_ASM_NASM_COMPILER nasm.exe CACHE FILEPATH "" FORCE) -setq(Qt5_DIR "../qt-5.15-kde/lib/cmake/Qt5") set(Qt5Core_DIR "${Qt5_DIR}Core" CACHE PATH "" FORCE) set(Qt5Gui_DIR "${Qt5_DIR}Gui" CACHE PATH "" FORCE) diff --git a/tracker-eyeware-beam/CMakeLists.txt b/tracker-eyeware-beam/CMakeLists.txt new file mode 100644 index 00000000..e041c131 --- /dev/null +++ b/tracker-eyeware-beam/CMakeLists.txt @@ -0,0 +1,27 @@ +# The Eyeware Beam SDK can be found at https://beam.eyeware.tech/developers/ +# The latest version can be downloaded at https://eyewarecistorage.blob.core.windows.net/beam-sdk/BeamSDK-Windows64-1.1.0.zip +set(SDK_EYEWARE_BEAM "" CACHE PATH "Eyeware Beam SDK path") +if(WIN32 AND SDK_EYEWARE_BEAM) + if(MSVC) + add_compile_options(-EHsc) + endif() + otr_module(tracker-eyeware-beam) + + if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(arch "x86") + else() + set(arch "x64") + endif() + + target_include_directories(${self} SYSTEM PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/include") + target_link_directories(${self} PRIVATE "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}") + set(dll "${SDK_EYEWARE_BEAM}/API/cpp/lib/${arch}/tracker_client.dll") + set(lib tracker_client.lib) + + #message(${self}) + #message(${dll}) + #message(${lib}) + + target_link_libraries(${self} ${lib}) + install(FILES ${dll} DESTINATION ${opentrack-libexec}) +endif() diff --git a/tracker-eyeware-beam/eyeware_beam.cpp b/tracker-eyeware-beam/eyeware_beam.cpp new file mode 100644 index 00000000..f48b5d4d --- /dev/null +++ b/tracker-eyeware-beam/eyeware_beam.cpp @@ -0,0 +1,116 @@ +/* Copyright (c) 2023 Eyeware Tech SA https://www.eyeware.tech + * + * 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 "eyeware_beam.h" + +#include <QMutexLocker> + +static constexpr double rad_to_deg = 180.0 / M_PI; +static constexpr double m_to_cm = 100.0; +static constexpr double epsilon = 0.000001; + +eyeware_beam_tracker::eyeware_beam_tracker() +{ +} + +eyeware_beam_tracker::~eyeware_beam_tracker() +{ + QMutexLocker lck(&mtx); + release_tracker_instance(tracker_client); + tracker_client = nullptr; +} + +module_status eyeware_beam_tracker::start_tracker(QFrame* videoframe) +{ + QMutexLocker lck(&mtx); + try + { + tracker_client = create_tracker_instance("127.0.0.1", 12010); + } + catch (...) + { + return error("Eyeware Beam initialization has failed"); + } + + return status_ok(); +} + +void eyeware_beam_tracker::extract_translation(const eyeware::Vector3D& t, + double& translation_x_cm, + double& translation_y_cm, + double& translation_z_cm) +{ + translation_x_cm = +t.x * m_to_cm; + translation_y_cm = -t.y * m_to_cm; + translation_z_cm = +t.z * m_to_cm; +} + +void eyeware_beam_tracker::extract_rotation_angles(const eyeware::Matrix3x3& R, + double& pitch_deg, + double& roll_deg, + double& yaw_deg) +{ + double r00 = static_cast<double>(R[0][0]); + double r01 = static_cast<double>(R[0][1]); + double r02 = static_cast<double>(R[0][2]); + double r10 = static_cast<double>(R[1][0]); + double r11 = static_cast<double>(R[1][1]); + double r12 = static_cast<double>(R[1][2]); + double r20 = static_cast<double>(R[2][0]); + double r21 = static_cast<double>(R[2][1]); + double r22 = static_cast<double>(R[2][2]); + + double dy = std::sqrt(r00 * r00 + r10 * r10); + last_yaw_deg = -std::atan2(-r20, dy) * rad_to_deg; + last_roll_deg = 0.0; + if (dy > epsilon) + { + last_pitch_deg = -std::atan2(r21, r22) * rad_to_deg; + last_roll_deg = +std::atan2(r10, r00) * rad_to_deg; + } + else + { + last_pitch_deg = -std::atan2(-r12, r11) * rad_to_deg; + } +} + +void eyeware_beam_tracker::data(double *data) +{ + QMutexLocker lck(&mtx); + + if (connected(tracker_client)) + { + eyeware::HeadPoseInfo head_pose_info = get_head_pose_info(tracker_client); + if (!head_pose_info.is_lost) + { + extract_translation(head_pose_info.transform.translation, last_translation_x_cm, + last_translation_y_cm, last_translation_z_cm); + extract_rotation_angles(head_pose_info.transform.rotation, last_pitch_deg, last_roll_deg, last_yaw_deg); + } + } + + data[TX] = last_translation_x_cm; + data[TY] = last_translation_y_cm; + data[TZ] = last_translation_z_cm; + data[Yaw] = last_yaw_deg; + data[Pitch] = last_pitch_deg; + data[Roll] = last_roll_deg; +} + +eyeware_beam_dialog::eyeware_beam_dialog() +{ + ui.setupUi(this); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); +} + +void eyeware_beam_dialog::doOK() +{ + close(); +} + +OPENTRACK_DECLARE_TRACKER(eyeware_beam_tracker, eyeware_beam_dialog, eyeware_beam_metadata) diff --git a/tracker-eyeware-beam/eyeware_beam.h b/tracker-eyeware-beam/eyeware_beam.h new file mode 100644 index 00000000..9ebf1f3c --- /dev/null +++ b/tracker-eyeware-beam/eyeware_beam.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2023 Eyeware Tech SA https://www.eyeware.tech + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#include "api/plugin-api.hpp" + +#include "ui_eyeware_beam.h" + +#include "eyeware/tracker_client.h" + +#include <QObject> +#include <QMutex> + +class eyeware_beam_tracker : public QObject, public ITracker +{ + Q_OBJECT + +public: + eyeware_beam_tracker(); + ~eyeware_beam_tracker() override; + module_status start_tracker(QFrame* frame) override; + void data(double *data) override; + +private: + void extract_translation(const eyeware::Vector3D& t, + double& translation_x_cm, + double& translation_y_cm, + double& translation_z_cm); + void extract_rotation_angles(const eyeware::Matrix3x3& R, double& pitch_deg, double& roll_deg, double& yaw_deg); + + eyeware::TrackerClient* tracker_client = nullptr; + + QMutex mtx; + + double last_pitch_deg = 0.0; + double last_roll_deg = 0.0; + double last_yaw_deg = 0.0; + double last_translation_x_cm = 0.0; + double last_translation_y_cm = 0.0; + double last_translation_z_cm = 0.0; +}; + +class eyeware_beam_dialog : public ITrackerDialog +{ + Q_OBJECT + +public: + eyeware_beam_dialog(); + void register_tracker(ITracker * x) override { tracker = static_cast<eyeware_beam_tracker*>(x); } + void unregister_tracker() override { tracker = nullptr; } + +private: + Ui::eyeware_beam_ui ui; + eyeware_beam_tracker* tracker = nullptr; + +private Q_SLOTS: + void doOK(); +}; + +class eyeware_beam_metadata : public Metadata +{ + Q_OBJECT + QString name() override { return QString("Eyeware Beam"); } + QIcon icon() override { return QIcon(":/images/eyeware_beam_logo.png"); } +}; diff --git a/tracker-eyeware-beam/eyeware_beam.qrc b/tracker-eyeware-beam/eyeware_beam.qrc new file mode 100644 index 00000000..ae20865e --- /dev/null +++ b/tracker-eyeware-beam/eyeware_beam.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/images"> + <file>eyeware_beam_logo.png</file> + </qresource> +</RCC> diff --git a/tracker-eyeware-beam/eyeware_beam.ui b/tracker-eyeware-beam/eyeware_beam.ui new file mode 100644 index 00000000..475db6a0 --- /dev/null +++ b/tracker-eyeware-beam/eyeware_beam.ui @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>eyeware_beam_ui</class> + <widget class="QWidget" name="eyeware_beam_ui"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>433</width> + <height>180</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Eyeware Beam</string> + </property> + <property name="windowIcon"> + <iconset resource="eyeware_beam.qrc"> + <normaloff>:/images/eyeware_beam_logo.png</normaloff>:/images/eyeware_beam_logo.png</iconset> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QFrame" name="frame_2"> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please make sure the Eyeware Beam application is running and tracking is active.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To download, visit <a href="https://beam.eyeware.tech/opentrack"><span style=" text-decoration: underline; color:#0000ff;">https://beam.eyeware.tech/opentrack</span></a>.</p></body></html></string> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="eyeware_beam.qrc"/> + </resources> + <connections/> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/tracker-eyeware-beam/eyeware_beam_logo.png b/tracker-eyeware-beam/eyeware_beam_logo.png Binary files differnew file mode 100644 index 00000000..6a611cac --- /dev/null +++ b/tracker-eyeware-beam/eyeware_beam_logo.png diff --git a/tracker-eyeware-beam/lang/nl_NL.ts b/tracker-eyeware-beam/lang/nl_NL.ts new file mode 100644 index 00000000..d70f58ed --- /dev/null +++ b/tracker-eyeware-beam/lang/nl_NL.ts @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>eyeware_beam_ui</name> + <message> + <source>Eyeware Beam</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please make sure the Eyeware Beam application is running and tracking is active.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To download, visit <a href="https://beam.eyeware.tech/opentrack"><span style=" text-decoration: underline; color:#0000ff;">https://beam.eyeware.tech/opentrack</span></a>.</p></body></html></source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-eyeware-beam/lang/ru_RU.ts b/tracker-eyeware-beam/lang/ru_RU.ts new file mode 100644 index 00000000..0bff47ae --- /dev/null +++ b/tracker-eyeware-beam/lang/ru_RU.ts @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>eyeware_beam_ui</name> + <message> + <source>Eyeware Beam</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please make sure the Eyeware Beam application is running and tracking is active.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To download, visit <a href="https://beam.eyeware.tech/opentrack"><span style=" text-decoration: underline; color:#0000ff;">https://beam.eyeware.tech/opentrack</span></a>.</p></body></html></source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-eyeware-beam/lang/stub.ts b/tracker-eyeware-beam/lang/stub.ts new file mode 100644 index 00000000..c64ff83e --- /dev/null +++ b/tracker-eyeware-beam/lang/stub.ts @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>eyeware_beam_ui</name> + <message> + <source>Eyeware Beam</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please make sure the Eyeware Beam application is running and tracking is active.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To download, visit <a href="https://beam.eyeware.tech/opentrack"><span style=" text-decoration: underline; color:#0000ff;">https://beam.eyeware.tech/opentrack</span></a>.</p></body></html></source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-eyeware-beam/lang/zh_CN.ts b/tracker-eyeware-beam/lang/zh_CN.ts new file mode 100644 index 00000000..aed44317 --- /dev/null +++ b/tracker-eyeware-beam/lang/zh_CN.ts @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> + <name>eyeware_beam_ui</name> + <message> + <source>Eyeware Beam</source> + <translation type="unfinished"></translation> + </message> + <message> + <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please make sure the Eyeware Beam application is running and tracking is active.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To download, visit <a href="https://beam.eyeware.tech/opentrack"><span style=" text-decoration: underline; color:#0000ff;">https://beam.eyeware.tech/opentrack</span></a>.</p></body></html></source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/tracker-neuralnet/CMakeLists.txt b/tracker-neuralnet/CMakeLists.txt index f414c920..db568fae 100644 --- a/tracker-neuralnet/CMakeLists.txt +++ b/tracker-neuralnet/CMakeLists.txt @@ -1,4 +1,9 @@ include(opentrack-opencv) +set(host-spec "${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_SIZEOF_VOID_P}") +if(host-spec MATCHES "^Linux i[3-6]86 4$") + return() +endif() + find_package(OpenCV QUIET) find_package(OpenMP QUIET) # Used to control number of onnx threads. find_package(ONNXRuntime QUIET) @@ -11,16 +16,21 @@ if(OpenCV_FOUND AND ONNXRuntime_FOUND AND OpenMP_FOUND) otr_module(tracker-neuralnet) - target_link_libraries(${self} + target_link_libraries(${self} opentrack-cv onnxruntime::onnxruntime opencv_calib3d opencv_imgproc opencv_imgcodecs opencv_core - OpenMP::OpenMP_C + OpenMP::OpenMP_CXX ) + # OpenMP::OpenMP_CXX doesn't set up the -fopenmp linking option, so set it up ourselves. + if(NOT MSVC) + target_link_options(${self} PUBLIC ${OpenMP_CXX_FLAGS}) + endif() + install( FILES "models/head-localizer.onnx" "models/head-pose.onnx" diff --git a/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp b/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp index a1a3526b..59e17063 100644 --- a/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp +++ b/tracker-neuralnet/ftnoir_tracker_neuralnet.cpp @@ -13,7 +13,6 @@ #include "compat/math-imports.hpp" #include "compat/timer.hpp" #include "compat/check-visible.hpp" -#include "compat/camera-names.hpp" #include "cv/init.hpp" #include <omp.h> @@ -84,8 +83,7 @@ struct OnScopeExit CamIntrinsics make_intrinsics(const cv::Mat& img, const Settings& settings) { const int w = img.cols, h = img.rows; - //const double diag_fov = settings.fov * M_PI / 180.; - const double diag_fov = 60 * M_PI / 180.; (void)settings; + const double diag_fov = settings.fov * M_PI / 180.; const double fov_w = 2.*atan(tan(diag_fov/2.)/sqrt(1. + h/(double)w * h/(double)w)); const double fov_h = 2.*atan(tan(diag_fov/2.)/sqrt(1. + w/(double)h * w/(double)h)); const double focal_length_w = 1. / tan(.5 * fov_w); @@ -353,7 +351,7 @@ bool NeuralNetTracker::detect() last_pose_affine_ = pose_affine; } - draw_gizmos(*face, pose_affine); + draw_gizmos(*face, last_pose_affine_); return true; } @@ -503,38 +501,17 @@ bool NeuralNetTracker::load_and_initialize_model() bool NeuralNetTracker::open_camera() { -#if 0 int rint = std::clamp(*settings_.resolution, 0, (int)std::size(resolution_choices)-1); resolution_tuple res = resolution_choices[rint]; int fps = enum_to_fps(settings_.force_fps); -#endif - - video::impl::camera::info args {}; - args.width = 640; - args.height = 480; - args.fps = 60; - args.use_mjpeg = true; QMutexLocker l(&camera_mtx_); - camera_ = nullptr; - const QString name = settings_.camera_name; - - if (name.isEmpty() || name == "TrackHat sensor") - { - camera_ = video::make_camera_("TrackHat sensor"); - if (camera_ && camera_->start(args)) - return true; - if (!name.isEmpty()) - return false; - } - - camera_ = video::make_camera(name); + camera_ = video::make_camera(settings_.camera_name); if (!camera_) return false; -#if 0 video::impl::camera::info args {}; if (res.width) @@ -546,7 +523,6 @@ bool NeuralNetTracker::open_camera() args.fps = fps; args.use_mjpeg = settings_.use_mjpeg; -#endif if (!camera_->start(args)) { @@ -624,8 +600,6 @@ void NeuralNetTracker::run() std::chrono::duration_cast<std::chrono::milliseconds>( clk.now() - t).count()*1.e-3); } - - camera_ = nullptr; } @@ -670,23 +644,19 @@ void NeuralNetTracker::update_fps(double dt) void NeuralNetTracker::data(double *data) { - auto tmp2 = [&]() + Affine tmp = [&]() { QMutexLocker lck(&mtx_); return last_pose_affine_; }(); - if (!tmp2) - return; - const auto& tmp = *tmp2; - const auto& mx = tmp.R.col(0); const auto& my = tmp.R.col(1); const auto& mz = -tmp.R.col(2); const float yaw = std::atan2(mx(2), mx(0)); const float pitch = -std::atan2(-mx(1), std::sqrt(mx(2)*mx(2)+mx(0)*mx(0))); - const float roll = -std::atan2(-my(2), mz(2)); + const float roll = std::atan2(-my(2), mz(2)); { constexpr double rad2deg = 180/M_PI; data[Yaw] = rad2deg * yaw; @@ -704,7 +674,7 @@ void NeuralNetTracker::data(double *data) Affine NeuralNetTracker::pose() { QMutexLocker lck(&mtx_); - return last_pose_affine_ ? *last_pose_affine_ : Affine{}; + return last_pose_affine_; } std::tuple<cv::Size,double, double> NeuralNetTracker::stats() const @@ -715,19 +685,16 @@ std::tuple<cv::Size,double, double> NeuralNetTracker::stats() const void NeuralNetDialog::make_fps_combobox() { -#if 0 for (int k = 0; k < fps_MAX; k++) { const int hz = enum_to_fps(k); const QString name = (hz == 0) ? tr("Default") : QString::number(hz); ui_.cameraFPS->addItem(name, k); } -#endif } void NeuralNetDialog::make_resolution_combobox() { -#if 0 int k=0; for (const auto [w, h] : resolution_choices) { @@ -736,7 +703,6 @@ void NeuralNetDialog::make_resolution_combobox() : QString::number(w) + " x " + QString::number(h); ui_.resolution->addItem(s, k++); } -#endif } @@ -748,44 +714,21 @@ NeuralNetDialog::NeuralNetDialog() : make_fps_combobox(); make_resolution_combobox(); - ui_.cameraName->addItem(QString{}); for (const auto& str : video::camera_names()) ui_.cameraName->addItem(str); tie_setting(settings_.camera_name, ui_.cameraName); -#if 0 tie_setting(settings_.fov, ui_.cameraFOV); -#endif tie_setting(settings_.offset_fwd, ui_.tx_spin); tie_setting(settings_.offset_up, ui_.ty_spin); tie_setting(settings_.offset_right, ui_.tz_spin); tie_setting(settings_.show_network_input, ui_.showNetworkInput); tie_setting(settings_.roi_filter_alpha, ui_.roiFilterAlpha); -#if 0 tie_setting(settings_.use_mjpeg, ui_.use_mjpeg); -#endif tie_setting(settings_.roi_zoom, ui_.roiZoom); tie_setting(settings_.num_threads, ui_.threadCount); -#if 0 tie_setting(settings_.resolution, ui_.resolution); tie_setting(settings_.force_fps, ui_.cameraFPS); -#endif - - { - const struct { - QString label; - exposure_preset preset; - } presets[] = { - { QStringLiteral("Near (1-4ft)"), exposure_preset::near }, - { QStringLiteral("Far (4-8ft)"), exposure_preset::far }, - { QStringLiteral("Custom"), exposure_preset::ignored }, - }; - - for (const auto& [label, preset] : presets) - ui_.exposure_preset->addItem(label, int(preset)); - - tie_setting(cs_.exposure, ui_.exposure_preset); - } connect(ui_.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui_.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); @@ -807,13 +750,11 @@ NeuralNetDialog::NeuralNetDialog() : void NeuralNetDialog::save() { settings_.b->save(); - cs_.b->save(); } void NeuralNetDialog::reload() { settings_.b->reload(); - cs_.b->reload(); } void NeuralNetDialog::doOK() diff --git a/tracker-neuralnet/lang/ru_RU.ts b/tracker-neuralnet/lang/ru_RU.ts index 4c9cec04..b191e769 100644 --- a/tracker-neuralnet/lang/ru_RU.ts +++ b/tracker-neuralnet/lang/ru_RU.ts @@ -5,123 +5,150 @@ <name>Form</name> <message> <source>Tracker settings</source> - <translation type="unfinished"></translation> + <translation>Настройки трекера</translation> + </message> + <message> + <source>Diagonal FOV</source> + <translation>Угол обзора</translation> </message> <message> <source>Camera settings</source> - <translation type="unfinished"></translation> + <translation>Настройки камеры</translation> + </message> + <message> + <source>Frames per second</source> + <translation>Кадры в секунду</translation> + </message> + <message> + <source>Camera name</source> + <translation>Камера</translation> + </message> + <message> + <source>Camera Configuration</source> + <translation>Конфигурация камеры</translation> </message> <message> <source>Head Center Offset</source> - <translation type="unfinished"></translation> + <translation>Смещение центра головы</translation> </message> <message> <source> mm</source> - <translation type="unfinished"></translation> + <translation> мм</translation> </message> <message> <source>Use only yaw and pitch while calibrating. Don't roll or change position.</source> - <translation type="unfinished"></translation> + <translation>Поворачивайте голову влево-вправо и наклоняйте вверх-вниз. +Не наклоняйте набок и не смещайте голову в сторону.</translation> </message> <message> <source>Start calibration</source> - <translation type="unfinished"></translation> + <translation>Начать калибровку</translation> </message> <message> <source>Right</source> - <translation type="unfinished"></translation> + <translation>Вправо</translation> </message> <message> <source>Forward</source> - <translation type="unfinished"></translation> + <translation>Вперед</translation> </message> <message> <source>Up</source> - <translation type="unfinished"></translation> + <translation>Вверх</translation> </message> <message> - <source>Exposure preset</source> - <translation type="unfinished"></translation> + <source>Show Network Input</source> + <translation>Показать входные данные</translation> </message> <message> - <source>Camera Configuration</source> - <translation type="unfinished"></translation> + <source>MJPEG</source> + <translation>Использовать MJPEG</translation> </message> <message> <source>Tuning / Debug</source> - <translation type="unfinished"></translation> - </message> - <message> - <source>Number of threads. Can be used to balance the CPU load between the game and the tracker.</source> - <translation type="unfinished"></translation> + <translation>Тонкая настройка</translation> </message> <message> <source>ROI Smoothing Alpha</source> - <translation type="unfinished"></translation> + <translation>Сглаживание ROI</translation> </message> <message> <source>ROI Zoom</source> - <translation type="unfinished"></translation> + <translation>Масштабирование ROI</translation> </message> <message> - <source>Show the image patch that the pose estimation model sees.</source> - <translation type="unfinished"></translation> + <source>Thread Count</source> + <translation>Количество потоков</translation> </message> <message> - <source>Show Network Input</source> - <translation type="unfinished"></translation> + <source>Resolution</source> + <translation>Разрешение</translation> </message> <message> - <source>Amount of smoothing of the face region coordinates. Can help stabilize the pose.</source> - <translation type="unfinished"></translation> + <source>Field of view. Needed to transform the pose to world coordinates.</source> + <translation>Угол обзора камеры. Требуется для преобразования положения головы в глобальные координаты</translation> </message> <message> - <source>Thread Count</source> - <translation type="unfinished"></translation> + <source>Requested video frame rate. Actual setting may not be supported by the camera.</source> + <translation>Частота кадров. Реальные значения могут не поддерживаться камерой.</translation> </message> <message> - <source>Zoom factor for the face region. Applied before the patch is fed into the pose estimation model. There is a sweet spot near 1.</source> - <translation type="unfinished"></translation> + <source>The requested resolution for cases where the camera delivers maximum frame rate only for a particular resolution. The image may still be downscaled to the internal resolution.</source> + <translation>Разрешение камеры, для тех случаев, когда быстродействие камеры максимально в определенном разрешении. Может быть масштабировано до внутреннего разрешения.</translation> + </message> + <message> + <source>Number of threads. Can be used to balance the CPU load between the game and the tracker.</source> + <translation>Количество потоков. Используется для балансировки нагрузки на процессор между игрой и трекером.</translation> </message> <message> - <source>Camera override</source> - <translation type="unfinished"></translation> + <source>Show the image patch that the pose estimation model sees.</source> + <translation>Показать изображение, используемое моделью определения позиции</translation> + </message> + <message> + <source>Amount of smoothing of the face region coordinates. Can help stabilize the pose.</source> + <translation>Сглаживание координат области лица. Может помочь стабилизировать позицию.</translation> + </message> + <message> + <source>Zoom factor for the face region. Applied before the patch is fed into the pose estimation model. There is a sweet spot near 1.</source> + <translation>Фактор масштабирования области лица. Применяется перед передачей кадра в модель определения позиции. Наилучшие результаты близки к 1</translation> </message> </context> <context> <name>neuralnet_tracker_ns::NeuralNetDialog</name> <message> <source>Default</source> - <translation type="unfinished"></translation> + <translation>По умолчанию</translation> </message> <message> <source>Tracker Offline</source> - <translation type="unfinished"></translation> + <translation>Трекер выключен</translation> </message> <message> <source>%1x%2 @ %3 FPS / Inference: %4 ms</source> - <translation type="unfinished"></translation> + <translation>%1x%2 @ %3 FPS; Время оценки: %4 мс</translation> </message> <message> <source>%1 yaw samples. Yaw more to %2 samples for stable calibration.</source> - <translation type="unfinished"></translation> + <translation>Сэмплов поворота: %1. +Поворачивайте голову в стороны до %2 сэмплов для стабильной калибрации.</translation> </message> <message> <source>%1 pitch samples. Pitch more to %2 samples for stable calibration.</source> - <translation type="unfinished"></translation> + <translation>Сэмплов наклона: %1. +Наклоняйте голову вниз/вверх до %2 сэмплов для стабильной калибрации.</translation> </message> <message> <source>%1 samples. Over %2, good!</source> - <translation type="unfinished"></translation> + <translation>%1 сэмплов. Более %2, достаточно.</translation> </message> <message> <source>Stop calibration</source> - <translation type="unfinished"></translation> + <translation>Остановить калибровку</translation> </message> <message> <source>Start calibration</source> - <translation type="unfinished"></translation> + <translation>Начать калибровку</translation> </message> </context> </TS> diff --git a/tracker-neuralnet/model_adapters.cpp b/tracker-neuralnet/model_adapters.cpp index af599321..a8580a89 100644 --- a/tracker-neuralnet/model_adapters.cpp +++ b/tracker-neuralnet/model_adapters.cpp @@ -8,7 +8,6 @@ #include <QDebug> - namespace neuralnet_tracker_ns { @@ -165,6 +164,24 @@ double Localizer::last_inference_time_millis() const } +std::string PoseEstimator::get_network_input_name(size_t i) const +{ +#if ORT_API_VERSION >= 12 + return std::string(&*session_.GetInputNameAllocated(i, allocator_)); +#else + return std::string(session_.GetInputName(i, allocator_)); +#endif +} + +std::string PoseEstimator::get_network_output_name(size_t i) const +{ +#if ORT_API_VERSION >= 12 + return std::string(&*session_.GetOutputNameAllocated(i, allocator_)); +#else + return std::string(session_.GetOutputName(i, allocator_)); +#endif +} + PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&session) : model_version_{session.GetModelMetadata().GetVersion()} , session_{std::move(session)} @@ -215,14 +232,16 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses qDebug() << "Pose model inputs (" << session_.GetInputCount() << ")"; qDebug() << "Pose model outputs (" << session_.GetOutputCount() << "):"; + output_names_.resize(session_.GetOutputCount()); + output_c_names_.resize(session_.GetOutputCount()); for (size_t i=0; i<session_.GetOutputCount(); ++i) { - const char* name = session_.GetOutputName(i, allocator_); + std::string name = get_network_output_name(i); const auto& output_info = session_.GetOutputTypeInfo(i); const auto& onnx_tensor_spec = output_info.GetTensorTypeAndShapeInfo(); auto my_tensor_spec = understood_outputs.find(name); - qDebug() << "\t" << name << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " << + qDebug() << "\t" << name.c_str() << " (" << onnx_tensor_spec.GetShape() << ") dtype: " << onnx_tensor_spec.GetElementType() << " " << (my_tensor_spec != understood_outputs.end() ? "ok" : "unknown"); if (my_tensor_spec != understood_outputs.end()) @@ -240,7 +259,8 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses // Create tensor regardless and ignore output output_val_.push_back(create_tensor(output_info, allocator_)); } - output_names_.push_back(name); + output_names_[i] = name; + output_c_names_[i] = output_names_[i].c_str(); } has_uncertainty_ = understood_outputs.at("rotaxis_scales_tril").available || @@ -270,9 +290,12 @@ PoseEstimator::PoseEstimator(Ort::MemoryInfo &allocator_info, Ort::Session &&ses // output_val_.push_back(create_tensor(output_info, allocator_)); // } + input_names_.resize(session_.GetInputCount()); + input_c_names_.resize(session_.GetInputCount()); for (size_t i = 0; i < session_.GetInputCount(); ++i) { - input_names_.push_back(session_.GetInputName(i, allocator_)); + input_names_[i] = get_network_input_name(i); + input_c_names_[i] = input_names_[i].c_str(); } assert (input_names_.size() == input_val_.size()); @@ -312,11 +335,11 @@ std::optional<PoseEstimator::Face> PoseEstimator::run( { session_.Run( Ort::RunOptions{ nullptr }, - input_names_.data(), + input_c_names_.data(), input_val_.data(), input_val_.size(), - output_names_.data(), - output_val_.data(), + output_c_names_.data(), + output_val_.data(), output_val_.size()); } catch (const Ort::Exception &e) @@ -430,4 +453,4 @@ double PoseEstimator::last_inference_time_millis() const -} // namespace neuralnet_tracker_ns
\ No newline at end of file +} // namespace neuralnet_tracker_ns diff --git a/tracker-neuralnet/model_adapters.h b/tracker-neuralnet/model_adapters.h index 3fbfb861..820330cf 100644 --- a/tracker-neuralnet/model_adapters.h +++ b/tracker-neuralnet/model_adapters.h @@ -3,6 +3,7 @@ #include <optional> #include <array> #include <vector> +#include <string> #include <onnxruntime_cxx_api.h> #include <opencv2/core.hpp> @@ -21,7 +22,7 @@ class Localizer public: Localizer(Ort::MemoryInfo &allocator_info, Ort::Session &&session); - + // Returns bounding wrt image coordinate of the input image // The preceeding float is the score for being a face normalized to [0,1]. std::pair<float, cv::Rect2f> run( @@ -68,13 +69,16 @@ class PoseEstimator bool has_uncertainty() const { return has_uncertainty_; } private: + std::string get_network_input_name(size_t i) const; + std::string get_network_output_name(size_t i) const; int64_t model_version_ = 0; // Queried meta data from the ONNX file Ort::Session session_{nullptr}; // ONNX's runtime context for running the model Ort::Allocator allocator_; // Memory allocator for tensors // Inputs cv::Mat scaled_frame_{}, input_mat_{}; // Input. One is the original crop, the other is rescaled (?) std::vector<Ort::Value> input_val_; // Tensors to put into the model - std::vector<const char*> input_names_; // Refers to the names in the onnx model. + std::vector<std::string> input_names_; // Refers to the names in the onnx model. + std::vector<const char *> input_c_names_; // Refers to the C names in the onnx model. // Outputs cv::Vec<float, 3> output_coord_{}; // 2d Coordinate and head size output. cv::Vec<float, 4> output_quat_{}; // Quaternion output @@ -83,7 +87,8 @@ class PoseEstimator cv::Vec<float, 2> output_eyes_{}; cv::Vec<float, 3> output_coord_scales_{}; std::vector<Ort::Value> output_val_; // Tensors to put the model outputs in. - std::vector<const char*> output_names_; // Refers to the names in the onnx model. + std::vector<std::string> output_names_; // Refers to the names in the onnx model. + std::vector<const char *> output_c_names_; // Refers to the C names in the onnx model. // More bookkeeping size_t num_recurrent_states_ = 0; double last_inference_time_ = 0; @@ -99,4 +104,4 @@ int find_input_intensity_quantile(const cv::Mat& frame, float percentage); void normalize_brightness(const cv::Mat& frame, cv::Mat& out); -} // namespace neuralnet_tracker_ns
\ No newline at end of file +} // namespace neuralnet_tracker_ns diff --git a/tracker-trackhat/lang/nl_NL.ts b/tracker-trackhat/lang/nl_NL.ts index 9cc67677..ebc53a27 100644 --- a/tracker-trackhat/lang/nl_NL.ts +++ b/tracker-trackhat/lang/nl_NL.ts @@ -147,7 +147,7 @@ <context> <name>trackhat_module</name> <message> - <source>TrackHat Point Tracker</source> + <source>TrackHat v1 Sensor</source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-trackhat/lang/ru_RU.ts b/tracker-trackhat/lang/ru_RU.ts index 844c5519..49d247be 100644 --- a/tracker-trackhat/lang/ru_RU.ts +++ b/tracker-trackhat/lang/ru_RU.ts @@ -147,7 +147,7 @@ <context> <name>trackhat_module</name> <message> - <source>TrackHat Point Tracker</source> + <source>TrackHat v1 Sensor</source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-trackhat/lang/stub.ts b/tracker-trackhat/lang/stub.ts index 127d0691..adb23557 100644 --- a/tracker-trackhat/lang/stub.ts +++ b/tracker-trackhat/lang/stub.ts @@ -147,7 +147,7 @@ <context> <name>trackhat_module</name> <message> - <source>TrackHat Point Tracker</source> + <source>TrackHat v1 Sensor</source> <translation type="unfinished"></translation> </message> </context> diff --git a/tracker-trackhat/lang/zh_CN.ts b/tracker-trackhat/lang/zh_CN.ts index 179d4261..5837eeb1 100644 --- a/tracker-trackhat/lang/zh_CN.ts +++ b/tracker-trackhat/lang/zh_CN.ts @@ -147,7 +147,7 @@ <context> <name>trackhat_module</name> <message> - <source>TrackHat Point Tracker</source> + <source>TrackHat v1 Sensor</source> <translation type="unfinished"></translation> </message> </context> diff --git a/video-ps3eye/shm-layout.hpp b/video-ps3eye/shm-layout.hpp index 9eee6db4..0b6c132e 100644 --- a/video-ps3eye/shm-layout.hpp +++ b/video-ps3eye/shm-layout.hpp @@ -31,12 +31,8 @@ struct shm_out }; struct shm { - static constexpr unsigned _cacheline_len = 64; - static constexpr unsigned _padding_len = - (_cacheline_len - (sizeof(shm_in) & (_cacheline_len - 1))) & (_cacheline_len - 1); - shm_out out; - const char* _padding[_padding_len]; + [[maybe_unused]] const char _padding[128 - sizeof(shm_out) % 128]; // NOLINT shm_in in; }; diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c index ed72e50e..e43ee0ef 100644 --- a/x-plane-plugin/plugin.c +++ b/x-plane-plugin/plugin.c @@ -134,6 +134,8 @@ static int TrackToggleHandler(XPLMCommandRef inCommand, XPLMCommandPhase inPhase, void* inRefCon) { + if (inPhase != xplm_CommandBegin) return 0; + if (track_disabled) { //Enable @@ -156,6 +158,8 @@ static int TranslationToggleHandler(XPLMCommandRef inCommand, XPLMCommandPhase inPhase, void* inRefCon) { + if (inPhase != xplm_CommandBegin) return 0; + translation_disabled = !translation_disabled; if (!translation_disabled) { |