diff options
Diffstat (limited to 'ftnoir_tracker_joystick')
5 files changed, 867 insertions, 0 deletions
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp new file mode 100644 index 00000000..f9789dce --- /dev/null +++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp @@ -0,0 +1,230 @@ +#include "ftnoir_tracker_joystick.h" +#include "facetracknoir/global-settings.h" +#undef NDEBUG +#include <QMutexLocker> + +FTNoIR_Tracker::FTNoIR_Tracker() : + g_pDI(nullptr), + g_pJoystick(nullptr), + iter(-1), + mtx(QMutex::Recursive) +{ + for (int i = 0; i < 6; i++) + min_[i] = max_[i] = 0; + GUID bar = {0}; +} + +void FTNoIR_Tracker::reload() +{ + s.b->reload(); + QMutexLocker foo(&mtx); + if (g_pJoystick) + { + g_pJoystick->Unacquire(); + g_pJoystick->Release(); + } + if (g_pDI) + g_pDI->Release(); + + g_pJoystick = nullptr; + g_pDI = nullptr; + + StartTracker(frame); +} + +FTNoIR_Tracker::~FTNoIR_Tracker() +{ + if (g_pJoystick) + { + g_pJoystick->Unacquire(); + g_pJoystick->Release(); + } + if (g_pDI) + { + g_pDI->Release(); + } +} + +static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + auto self = (FTNoIR_Tracker*) pContext; + + // For axes that are returned, set the DIPROP_RANGE property for the + // enumerated axis in order to scale min/max values. + if( pdidoi->dwType & DIDFT_AXIS ) + { + DIPROPRANGE diprg = {0}; + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + + // Set the range for the axis + + if( FAILED( self->g_pJoystick->GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) + return DIENUM_STOP; + + self->min_[self->iter] = diprg.lMin; + self->max_[self->iter] = diprg.lMax; + qDebug() << "axis" << self->iter << diprg.lMin << diprg.lMax; + self->iter++; + } + + return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE; +} + +static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) +{ + auto self = reinterpret_cast<FTNoIR_Tracker*>(pContext); + bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid; + + if (stop) + { + (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL); + qDebug() << "device" << static_cast<QString>(self->s.joyid); + } + + return stop ? DIENUM_STOP : DIENUM_CONTINUE; +} + +void FTNoIR_Tracker::StartTracker(QFrame* frame) +{ + QMutexLocker foo(&mtx); + this->frame = frame; + iter = 0; + auto hr = CoInitialize( nullptr ); + + if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, + IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) + { + qDebug() << "create"; + goto fail; + } + + if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "enum2"; + goto fail; + } + + if (!g_pJoystick) + { + qDebug() << "ENODEV"; + goto fail; + } + + if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick))) + { + qDebug() << "format"; + goto fail; + } + + if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + goto fail; + } + + iter = 0; + + if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback, + ( VOID* )this, DIDFT_ALL ))) + { + qDebug() << "enum axes"; + goto fail; + } + + qDebug() << "joy init success"; + + return; + +fail: + if (g_pJoystick) + g_pJoystick->Release(); + if (g_pDI) + g_pDI->Release(); + g_pJoystick = nullptr; + g_pDI = nullptr; + + qDebug() << "joy init failure"; +} + +void FTNoIR_Tracker::GetHeadPoseData(double *data) +{ + QMutexLocker foo(&mtx); + DIJOYSTATE js = {0}; + + if( !g_pDI || !g_pJoystick) + return; + + auto hr = g_pJoystick->Poll(); + if( FAILED( hr )) + { + hr = g_pJoystick->Acquire(); + for (int i = 0; hr == DIERR_INPUTLOST && i < 200; i++) + hr = g_pJoystick->Acquire(); + if (hr != DI_OK) + { + qDebug() << "joy read failure" << hr; + return; + } + } + + if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) ) + return; + + const LONG values[] = { + js.lRx, + js.lRy, + js.lRz, + js.lX, + js.lY, + js.lZ, + js.rglSlider[0], + js.rglSlider[1] + }; + + const double limits[] = { + 100, + 100, + 100, + 180, + 90, + 180 + }; + + int axes[] = { + s.axis_0, + s.axis_1, + s.axis_2, + s.axis_3, + s.axis_4, + s.axis_5 + }; + + for (int i = 0; i < 6; i++) + { + auto idx = axes[i] - 1; + if (idx < 0 || idx > 7) + { + data[i] = 0; + } + else { + auto mid = (min_[idx] + max_[idx]) / 2; + auto val = values[idx] - mid; + + auto max = (max_[idx] - min_[idx]) / 2; + auto min = (min_[idx] - max_[idx]) / -2; + data[i] = val * limits[i] / (double) (val >= 0 ? max : min); + } + } +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor() +{ + return new FTNoIR_Tracker; +} diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h new file mode 100644 index 00000000..06d06186 --- /dev/null +++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#pragma once +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ui_ftnoir_tracker_joystick_controls.h" +#include <QComboBox> +#include <QCheckBox> +#include <QSpinBox> +#include <QMessageBox> +#include <QSettings> +#include <QList> +#include <QMutex> +#include <QFrame> +#include <cmath> +#include "facetracknoir/global-settings.h" +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include <windows.h> +#include <commctrl.h> +#include <basetsd.h> +#include <dinput.h> +#include <oleauto.h> +#include <shellapi.h> + +#include "facetracknoir/options.h" +using namespace options; + +struct settings { + pbundle b; + value<int> axis_0; + value<int> axis_1; + value<int> axis_2; + value<int> axis_3; + value<int> axis_4; + value<int> axis_5; + value<QString> joyid; + settings() : + b(bundle("tracker-joystick")), + axis_0(b, "axis-0", 0), + axis_1(b, "axis-1", 0), + axis_2(b, "axis-2", 0), + axis_3(b, "axis-3", 0), + axis_4(b, "axis-4", 0), + axis_5(b, "axis-5", 0), + joyid(b, "joy-id", "") + {} +}; + +class FTNoIR_Tracker : public ITracker +{ +public: + FTNoIR_Tracker(); + ~FTNoIR_Tracker(); + void StartTracker(QFrame *frame); + void GetHeadPoseData(double *data); + void reload(); + LPDIRECTINPUT8 g_pDI; + LPDIRECTINPUTDEVICE8 g_pJoystick; + int min_[8], max_[8]; + QMutex mtx; + QFrame* frame; + DIDEVICEINSTANCE def; + int iter; // XXX bad style + settings s; +}; + +class TrackerControls: public QWidget, public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + void registerTracker(ITracker *foo) { + tracker = dynamic_cast<FTNoIR_Tracker*>(foo); + } + void unRegisterTracker() { + tracker = NULL; + } + QList<GUID> guids; + Ui::UIJoystickControls ui; + FTNoIR_Tracker* tracker; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + void getFullName(QString *strToBeFilled); + void getShortName(QString *strToBeFilled); + void getDescription(QString *strToBeFilled); + void getIcon(QIcon *icon); +private: + QString trackerFullName; // Trackers' name and description + QString trackerShortName; + QString trackerDescription; +}; + diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui new file mode 100644 index 00000000..5d349169 --- /dev/null +++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui @@ -0,0 +1,439 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UIJoystickControls</class> + <widget class="QWidget" name="UIJoystickControls"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>216</width> + <height>259</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Joystick protocol settings</string> + </property> + <property name="windowIcon"> + <iconset> + <normaloff>../facetracknoir/images/facetracknoir.png</normaloff>../facetracknoir/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> + <widget class="QGroupBox" name="groupBox_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>85</height> + </size> + </property> + <property name="title"> + <string>Axis enablement</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>X</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Y</string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Roll</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QComboBox" name="comboBox_5"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="7" column="1"> + <widget class="QComboBox" name="comboBox_6"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="5" column="1"> + <widget class="QComboBox" name="comboBox_4"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="comboBox_2"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBox"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Yaw</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QComboBox" name="comboBox_3"> + <item> + <property name="text"> + <string/> + </property> + </item> + <item> + <property name="text"> + <string>#1</string> + </property> + </item> + <item> + <property name="text"> + <string>#2</string> + </property> + </item> + <item> + <property name="text"> + <string>#3</string> + </property> + </item> + <item> + <property name="text"> + <string>#4</string> + </property> + </item> + <item> + <property name="text"> + <string>#5</string> + </property> + </item> + <item> + <property name="text"> + <string>#6</string> + </property> + </item> + <item> + <property name="text"> + <string>#7</string> + </property> + </item> + <item> + <property name="text"> + <string>#8</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Z</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Pitch</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Joy Id</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="joylist"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>joylist</tabstop> + <tabstop>comboBox</tabstop> + <tabstop>comboBox_2</tabstop> + <tabstop>comboBox_3</tabstop> + <tabstop>comboBox_4</tabstop> + <tabstop>comboBox_5</tabstop> + <tabstop>comboBox_6</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections/> + <slots> + <slot>startEngineClicked()</slot> + <slot>stopEngineClicked()</slot> + <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp new file mode 100644 index 00000000..b0766634 --- /dev/null +++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp @@ -0,0 +1,66 @@ +#include "ftnoir_tracker_joystick.h" +#include "facetracknoir/global-settings.h" + +static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) +{ + auto self = ( TrackerControls* )pContext; + + self->guids.push_back(pdidInstance->guidInstance); + self->ui.joylist->addItem(QString(pdidInstance->tszInstanceName)); + + return DIENUM_CONTINUE; +} + +TrackerControls::TrackerControls() : tracker(nullptr) +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.axis_0, ui.comboBox); + tie_setting(s.axis_1, ui.comboBox_2); + tie_setting(s.axis_2, ui.comboBox_3); + tie_setting(s.axis_3, ui.comboBox_4); + tie_setting(s.axis_4, ui.comboBox_5); + tie_setting(s.axis_5, ui.comboBox_6); + + { + auto hr = CoInitialize( nullptr ); + LPDIRECTINPUT8 g_pDI = nullptr; + + if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, + IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) + goto fin; + + if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY ))) + goto fin; + +fin: + if (g_pDI) + g_pDI->Release(); + } + + tie_setting(s.joyid, ui.joylist); +} + +void TrackerControls::doOK() { + s.b->save(); + if (tracker) + tracker->reload(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->revert(); + this->close(); +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( ) +{ + return new TrackerControls; +} diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp new file mode 100644 index 00000000..325d24a4 --- /dev/null +++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp @@ -0,0 +1,28 @@ +#include "ftnoir_tracker_joystick.h" +#include <QDebug> +#include "facetracknoir/global-settings.h" + +void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled) +{ + *strToBeFilled = "Joystick"; +} + +void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled) +{ + *strToBeFilled = "Joystick"; +} + +void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled) +{ + *strToBeFilled = "Joystick"; +} + +void FTNoIR_TrackerDll::getIcon(QIcon *icon) +{ + *icon = QIcon(":/images/facetracknoir.png"); +} + +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() +{ + return new FTNoIR_TrackerDll; +} |