From 8303597a865400a363ae574ccde819302495f498 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 2 Apr 2013 18:41:01 +0200 Subject: Just put everything new in. Conflict resolution will be later --- compat/compat.cpp | 84 ++ compat/compat.h | 42 + faceapi/ftnoir-faceapi-wrapper.exe.manifest | 15 + faceapi/ftnoir-faceapi-wrapper.rc | 2 + faceapi/main.cpp | 11 +- faceapi/mutex.h | 4 +- faceapi/stdafx.h | 27 +- faceapi/utils.h | 5 +- .../ClientFiles/FlightGear/win32/start_fg.bat | 1 + facetracknoir/ClientFiles/Tir4Fun/readme.txt | 18 +- facetracknoir/facetracknoir.cpp | 1572 +++++++++----------- facetracknoir/facetracknoir.h | 177 ++- facetracknoir/facetracknoir.ico | Bin 0 -> 23558 bytes facetracknoir/facetracknoir.rc | 84 +- facetracknoir/ftnoir_curves.ui | 930 +++++++----- facetracknoir/ftnoir_fsuipccontrols.ui | 4 +- facetracknoir/ftnoir_ftnservercontrols.ui | 2 +- facetracknoir/ftnoir_keyboardshortcuts.ui | 316 +--- facetracknoir/ftnoir_preferences.ui | 2 +- facetracknoir/global-settings.cpp | 142 ++ facetracknoir/global-settings.h | 85 ++ facetracknoir/global-shortcuts.cpp | 135 ++ facetracknoir/images/facetracknoir.ico | Bin 0 -> 23558 bytes facetracknoir/main.cpp | 20 +- facetracknoir/posix-version-script.txt | 8 + facetracknoir/rotation.cpp | 2 +- facetracknoir/rotation.h | 2 +- facetracknoir/spot.h | 27 + facetracknoir/tracker.cpp | 1186 ++++----------- facetracknoir/tracker.h | 278 ++-- facetracknoir/tracker_types.h | 6 +- facetracknoir/uielements/facetracknoir.ico | Bin 0 -> 23558 bytes facetracknoir/uielements/setupfacetracknoir.jpg | Bin 0 -> 21508 bytes ftnoir_filter_accela/default-points.cpp | 38 + .../ftnoir_accela_filtercontrols.ui | 451 ++++++ ftnoir_filter_accela/ftnoir_filter_accela.cpp | 31 +- ftnoir_filter_accela/ftnoir_filter_accela.h | 65 +- .../ftnoir_filter_accela_dialog.cpp | 23 +- ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp | 9 +- ftnoir_filter_base/ftnoir_filter_base.h | 51 +- ftnoir_filter_base/ftnoir_filter_base_global.h | 2 +- ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui | 587 ++++++++ ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp | 19 +- ftnoir_filter_ewma2/ftnoir_filter_ewma2.h | 18 +- ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp | 12 +- ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp | 5 +- ftnoir_posewidget/glwidget.cpp | 22 +- ftnoir_posewidget/glwidget.h | 3 +- ftnoir_protocol_base/ftnoir_protocol_base.h | 54 +- ftnoir_protocol_base/ftnoir_protocol_base_global.h | 2 +- ftnoir_protocol_fg/fgtypes.h | 5 +- ftnoir_protocol_fg/ftnoir_fgcontrols.ui | 2 +- ftnoir_protocol_fg/ftnoir_protocol_fg.cpp | 20 +- ftnoir_protocol_fg/ftnoir_protocol_fg.h | 20 +- ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp | 14 +- ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp | 7 +- ftnoir_protocol_fg/images/flightgear.ico | Bin 0 -> 13094 bytes ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui | 2 +- ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp | 38 +- ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h | 11 +- .../ftnoir_protocol_fsuipc_dialog.cpp | 7 +- .../ftnoir_protocol_fsuipc_dll.cpp | 5 +- ftnoir_protocol_fsuipc/images/fs9.ico | Bin 0 -> 29926 bytes ftnoir_protocol_ft/FreeTrackClient.c | 330 ++++ ftnoir_protocol_ft/ftnoir_ftcontrols.ui | 302 +--- ftnoir_protocol_ft/ftnoir_protocol_ft.cpp | 321 +--- ftnoir_protocol_ft/ftnoir_protocol_ft.h | 42 +- ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp | 80 +- ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp | 7 +- ftnoir_protocol_ft/fttypes.h | 33 +- ftnoir_protocol_ft/images/freetrack.ico | Bin 0 -> 17542 bytes ftnoir_protocol_ftn/ftnoir_ftncontrols.ui | 2 +- ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp | 80 +- ftnoir_protocol_ftn/ftnoir_protocol_ftn.h | 40 +- ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp | 9 +- ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp | 5 +- ftnoir_protocol_ftn/images/facetracknoir.ico | Bin 0 -> 23558 bytes ftnoir_protocol_mouse/ftnoir_mousecontrols.ui | 2 +- ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp | 50 +- ftnoir_protocol_mouse/ftnoir_protocol_mouse.h | 16 +- .../ftnoir_protocol_mouse_dialog.cpp | 9 +- .../ftnoir_protocol_mouse_dll.cpp | 7 +- ftnoir_protocol_mouse/images/mouse.ico | Bin 0 -> 17542 bytes ftnoir_protocol_sc/ftnoir-protocol-sc.rc | 2 + ftnoir_protocol_sc/ftnoir_protocol_sc.cpp | 92 +- ftnoir_protocol_sc/ftnoir_protocol_sc.h | 20 +- ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp | 7 +- ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp | 3 +- ftnoir_protocol_sc/ftnoir_sccontrols.ui | 2 +- ftnoir_protocol_sc/images/fsx.ico | Bin 0 -> 87910 bytes ftnoir_protocol_wine/images/wine.ico | Bin 0 -> 36451 bytes ftnoir_tracker_base/ftnoir_tracker_base.h | 43 +- ftnoir_tracker_base/ftnoir_tracker_base_global.h | 2 +- ftnoir_tracker_base/ftnoir_tracker_sm_types.h | 7 +- ftnoir_tracker_base/ftnoir_tracker_types.h | 2 +- ftnoir_tracker_ht/ftnoir_tracker_ht.cpp | 106 +- ftnoir_tracker_ht/ftnoir_tracker_ht.h | 6 +- ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h | 4 +- ftnoir_tracker_ht/ht-api.h | 56 +- ftnoir_tracker_ht/images/ht.ico | Bin 0 -> 15086 bytes ftnoir_tracker_ht/trackercontrols.ui | 301 +++- ftnoir_tracker_ht/video_widget.cpp | 69 + ftnoir_tracker_ht/video_widget.h | 42 + ftnoir_tracker_pt/Resources/icon.ico | Bin 0 -> 4286 bytes ftnoir_tracker_pt/camera.cpp | 58 +- ftnoir_tracker_pt/camera.h | 20 +- ftnoir_tracker_pt/ftnoir_pt_controls.ui | 21 +- ftnoir_tracker_pt/ftnoir_tracker_pt.cpp | 82 +- ftnoir_tracker_pt/ftnoir_tracker_pt.h | 28 +- ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp | 11 +- ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h | 6 +- ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp | 8 +- ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h | 7 +- ftnoir_tracker_pt/point_extractor.cpp | 15 +- ftnoir_tracker_pt/point_tracker.cpp | 22 +- ftnoir_tracker_pt/point_tracker.h | 4 +- ftnoir_tracker_pt/timer.cpp | 3 +- ftnoir_tracker_pt/video_widget.cpp | 60 +- ftnoir_tracker_pt/video_widget.h | 17 +- ftnoir_tracker_sm/ftnoir_sm_controls.ui | 4 +- ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp | 88 +- .../ftnoir_tracker_faceapi_dialog.cpp | 7 +- ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp | 7 +- ftnoir_tracker_sm/ftnoir_tracker_sm.h | 8 +- ftnoir_tracker_sm/images/sm.ico | Bin 0 -> 37798 bytes ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui | 2 +- ftnoir_tracker_udp/ftnoir_tracker_udp.cpp | 105 +- ftnoir_tracker_udp/ftnoir_tracker_udp.h | 32 +- ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp | 7 +- ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp | 7 +- qfunctionconfigurator/functionconfig.cpp | Bin 17350 -> 9271 bytes qfunctionconfigurator/functionconfig.h | Bin 3888 -> 1964 bytes qfunctionconfigurator/qfunctionconfigurator.cpp | 1421 +++++++++--------- qfunctionconfigurator/qfunctionconfigurator.h | 413 ++--- x-plane-plugin/plugin.c | 185 +++ x-plane-plugin/version-script.txt | 10 + 136 files changed, 6147 insertions(+), 5320 deletions(-) create mode 100644 compat/compat.cpp create mode 100644 compat/compat.h create mode 100644 faceapi/ftnoir-faceapi-wrapper.exe.manifest create mode 100644 faceapi/ftnoir-faceapi-wrapper.rc create mode 100644 facetracknoir/ClientFiles/FlightGear/win32/start_fg.bat create mode 100644 facetracknoir/facetracknoir.ico create mode 100644 facetracknoir/global-settings.cpp create mode 100644 facetracknoir/global-settings.h create mode 100644 facetracknoir/global-shortcuts.cpp create mode 100644 facetracknoir/images/facetracknoir.ico create mode 100644 facetracknoir/posix-version-script.txt create mode 100644 facetracknoir/spot.h create mode 100644 facetracknoir/uielements/facetracknoir.ico create mode 100644 facetracknoir/uielements/setupfacetracknoir.jpg create mode 100644 ftnoir_filter_accela/default-points.cpp create mode 100644 ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui create mode 100644 ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui create mode 100644 ftnoir_protocol_fg/images/flightgear.ico create mode 100644 ftnoir_protocol_fsuipc/images/fs9.ico create mode 100644 ftnoir_protocol_ft/FreeTrackClient.c create mode 100644 ftnoir_protocol_ft/images/freetrack.ico create mode 100644 ftnoir_protocol_ftn/images/facetracknoir.ico create mode 100644 ftnoir_protocol_mouse/images/mouse.ico create mode 100644 ftnoir_protocol_sc/ftnoir-protocol-sc.rc create mode 100644 ftnoir_protocol_sc/images/fsx.ico create mode 100644 ftnoir_protocol_wine/images/wine.ico create mode 100644 ftnoir_tracker_ht/images/ht.ico create mode 100644 ftnoir_tracker_ht/video_widget.cpp create mode 100644 ftnoir_tracker_ht/video_widget.h create mode 100644 ftnoir_tracker_pt/Resources/icon.ico create mode 100644 ftnoir_tracker_sm/images/sm.ico create mode 100644 x-plane-plugin/plugin.c create mode 100644 x-plane-plugin/version-script.txt diff --git a/compat/compat.cpp b/compat/compat.cpp new file mode 100644 index 00000000..2263ea11 --- /dev/null +++ b/compat/compat.cpp @@ -0,0 +1,84 @@ +/* Copyright (c) 2013 StanisÅ‚aw Halik + + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#define IN_FTNOIR_COMPAT +#include "compat.h" + +#if defined(_WIN32) || defined(__WIN32) + +PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize) +{ + hMutex = CreateMutexA(NULL, false, mutexName); + hMapFile = CreateFileMappingA( + INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + mapSize, + shmName); + mem = MapViewOfFile(hMapFile, + FILE_MAP_READ | FILE_MAP_WRITE, + 0, + 0, + mapSize); +} + +PortableLockedShm::~PortableLockedShm() +{ + UnmapViewOfFile(mem); + CloseHandle(hMapFile); + CloseHandle(hMutex); +} + +void PortableLockedShm::lock() +{ + (void) WaitForSingleObject(hMutex, INFINITE); +} + +void PortableLockedShm::unlock() +{ + (void) ReleaseMutex(hMutex); +} + +#else +PortableLockedShm::PortableLockedShm(const char *shmName, const char *mutexName, int mapSize) : size(mapSize) +{ + char shm_filename[NAME_MAX]; + shm_filename[0] = '/'; + strncpy(shm_filename+1, shmName, NAME_MAX-2); + sprintf(shm_filename + strlen(shm_filename), "%ld\n", (long) getuid()); + shm_filename[NAME_MAX-1] = '\0'; + + //(void) shm_unlink(shm_filename); + + fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600); + if (ftruncate(fd, mapSize) == 0) + mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0); + else + mem = (void*) -1; +} + +PortableLockedShm::~PortableLockedShm() +{ + //(void) shm_unlink(shm_filename); + + (void) munmap(mem, size); + (void) close(fd); +} + +void PortableLockedShm::lock() +{ + flock(fd, LOCK_EX); +} + +void PortableLockedShm::unlock() +{ + flock(fd, LOCK_UN); +} + + + +#endif diff --git a/compat/compat.h b/compat/compat.h new file mode 100644 index 00000000..7692b38a --- /dev/null +++ b/compat/compat.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2013 StanisÅ‚aw Halik + + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#pragma once + +#if defined(_WIN32) || defined(__WIN32) +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(IN_FTNOIR_COMPAT) && (defined(_WIN32) || defined(__WIN32)) +# define COMPAT_EXPORT __declspec(dllexport) +#else +# define COMPAT_EXPORT +#endif + +class COMPAT_EXPORT PortableLockedShm { +public: + PortableLockedShm(const char *shmName, const char *mutexName, int mapSize); + ~PortableLockedShm(); + void lock(); + void unlock(); + void* mem; +private: +#if defined(_WIN32) || defined(__WIN32) + HANDLE hMutex, hMapFile; +#else + int fd, size; + //char shm_filename[NAME_MAX]; +#endif +}; diff --git a/faceapi/ftnoir-faceapi-wrapper.exe.manifest b/faceapi/ftnoir-faceapi-wrapper.exe.manifest new file mode 100644 index 00000000..b6c98376 --- /dev/null +++ b/faceapi/ftnoir-faceapi-wrapper.exe.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/faceapi/ftnoir-faceapi-wrapper.rc b/faceapi/ftnoir-faceapi-wrapper.rc new file mode 100644 index 00000000..54cbb863 --- /dev/null +++ b/faceapi/ftnoir-faceapi-wrapper.rc @@ -0,0 +1,2 @@ +#include "winuser.h" +2 RT_MANIFEST ftnoir-faceapi-wrapper.exe.manifest \ No newline at end of file diff --git a/faceapi/main.cpp b/faceapi/main.cpp index 46732cb3..64e721f4 100644 --- a/faceapi/main.cpp +++ b/faceapi/main.cpp @@ -36,8 +36,9 @@ //FaceAPI headers #include -#include "ftnoir_tracker_sm_types.h" +#include "ftnoir_tracker_base/ftnoir_tracker_sm_types.h" #include "utils.h" +#include //local headers #include "build_options.h" @@ -171,7 +172,7 @@ smCameraHandle createFirstCamera() if (info_list.num_cameras == 0) { - throw runtime_error("No cameras were detected"); + throw std::exception(); } else { @@ -211,7 +212,6 @@ smCameraHandle createFirstCamera() // The main function: setup a tracking engine and show a video window, then loop on the keyboard. void run() { - char msg[100]; int state; // Capture control-C @@ -377,11 +377,6 @@ void run() // if (ftnoirConnected && (pMemData != 0)) { - sprintf_s(msg, "Command: %d, \n", pMemData->command, pMemData->par_val_int); - OutputDebugStringA(msg); - std::cout << msg; - - // // // Determine the trackers' state and send it to FaceTrackNoIR. // diff --git a/faceapi/mutex.h b/faceapi/mutex.h index 11aabafc..a4f84705 100644 --- a/faceapi/mutex.h +++ b/faceapi/mutex.h @@ -1,6 +1,8 @@ #ifndef SM_API_TESTAPPCONSOLE_MUTEX_H #define SM_API_TESTAPPCONSOLE_MUTEX_H +#include + namespace sm { namespace faceapi @@ -16,7 +18,7 @@ namespace sm { if (!InitializeCriticalSectionAndSpinCount(&_cs,0x80000400)) { - throw std::runtime_error("Failed to initialize Mutex"); + throw std::exception(); } } ~Mutex() diff --git a/faceapi/stdafx.h b/faceapi/stdafx.h index d97c9353..1fdab0b1 100644 --- a/faceapi/stdafx.h +++ b/faceapi/stdafx.h @@ -1,8 +1,3 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - #pragma once #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. @@ -12,10 +7,30 @@ #include #include -// TODO: reference additional headers your program requires here +#ifndef _MSC_VER + +#include + +typedef uint64_t u_int64_t; +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; +typedef uint8_t u_int8_t; +#endif + #include #include #include #include #include +#include +#ifdef SM_API +# undef SM_API +#endif +#ifdef STDCALL +# undef STDCALL +#endif + +#define SM_API(type) type __declspec(dllimport) __stdcall +#define STDCALL __stdcall + #include diff --git a/faceapi/utils.h b/faceapi/utils.h index 1fdb35b5..5d25e9a7 100644 --- a/faceapi/utils.h +++ b/faceapi/utils.h @@ -2,6 +2,8 @@ #define SM_API_TESTAPPCONSOLE_UTILS_H #include "lock.h" +#include +#include #define THROW_ON_ERROR(x) \ { \ @@ -10,7 +12,8 @@ { \ std::stringstream s; \ s << "API error code: " << result; \ - throw std::runtime_error(s.str()); \ + std::cerr << s; \ + throw std::exception(); \ } \ } diff --git a/facetracknoir/ClientFiles/FlightGear/win32/start_fg.bat b/facetracknoir/ClientFiles/FlightGear/win32/start_fg.bat new file mode 100644 index 00000000..cd9829b5 --- /dev/null +++ b/facetracknoir/ClientFiles/FlightGear/win32/start_fg.bat @@ -0,0 +1 @@ +fgfs --generic=socket,in,25,localhost,5550,udp,headtracker --generic=socket,out,10,localhost,5551,udp,headtracker --prop:browser=/sim/headtracker "c:\Program Files\FlightGear\data\Nasal\headtracker.xml" \ No newline at end of file diff --git a/facetracknoir/ClientFiles/Tir4Fun/readme.txt b/facetracknoir/ClientFiles/Tir4Fun/readme.txt index 010510db..d64af301 100644 --- a/facetracknoir/ClientFiles/Tir4Fun/readme.txt +++ b/facetracknoir/ClientFiles/Tir4Fun/readme.txt @@ -1,9 +1,9 @@ -What is TIR4FUN? - -TIR4FUN is a free utility for dedicated gamers. It enables 6DOF POV control with mouse and joystick axes. - -Software is provided as it is. Configuration is straightforward. GUI says it all! - -Installation: - -Copy all files to a directory. Launch tir4fun.exe to bring up the GUI. +What is TIR4FUN? + +TIR4FUN is a free utility for dedicated gamers. It enables 6DOF POV control with mouse and joystick axes. + +Software is provided as it is. Configuration is straightforward. GUI says it all! + +Installation: + +Copy all files to a directory. Launch tir4fun.exe to bring up the GUI. diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp index cd4e0a4d..5afdbc6d 100644 --- a/facetracknoir/facetracknoir.cpp +++ b/facetracknoir/facetracknoir.cpp @@ -23,7 +23,6 @@ *********************************************************************************/ /* Modifications (last one on top): - 20130201 - WVR: Load FreeTrack 2.0 protocol instead of fake TrackIR (which is now obsolete). 20130101 - WVR: Added "None" to filter-listbox to remove "use advanced filtering". 20121209 - WVR: Pre-v170 DLLs will not be added to the Listbox. Initial selection was changed (made case-insensitive). 20121014 - WVR: Added second Tracker Source for Arduino solution. The two will be mutually exclusive. @@ -33,7 +32,7 @@ Also disable combo and buttons after 'Start'. 20120917 - WVR: Added Mouse-buttons to ShortKeys. 20120717 - WVR: FunctionConfig is now used for the Curves, instead of BezierConfig. - 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled ´statically´. Now, a Dir() of the + 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled 'statically'. Now, a Dir() of the EXE-folder is done, to locate Protocol-DLLs. The Icons were also moved to the DLLs 20120317 - WVR: The Filter and Tracker-code was moved to separate DLLs. The calling-method was changed accordingly. The save() and LoadSettings() functions were adapted. @@ -46,21 +45,158 @@ 20110207 - WVR: RadioButtons for 'Stop engine' added. It is now possible to choose Stop or Keep tracking. 20110109 - WVR: Added minimizeTaskBar option added. It is now possible to choose minimized or tray. */ -#include "FaceTrackNoIR.h" +#include "facetracknoir.h" #include "tracker.h" +#include +#include + +#if defined(__WIN32) || defined(_WIN32) +# include +#endif + +#if defined(__APPLE__) +# define SONAME "dylib" +#elif defined(_WIN32) || defined(__WIN32) +# define SONAME "dll" +#else +# define SONAME "so" +#endif + +#include + +#if defined(__WIN32) || defined(_WIN32) +#define DIRECTINPUT_VERSION 0x0800 +#include +#include + +KeybindingWorkerDummy::~KeybindingWorkerDummy() { + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } + if (din) + din->Release(); +} + +KeybindingWorkerDummy::KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter, Key keyInhibit, Key keyStartStop, Key keyZero) +: kCenter(keyCenter), kInhibit(keyInhibit), kStartStop(keyStartStop), kZero(keyZero), window(w), should_quit(true), din(0), dinkeyboard(0) +{ + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + return; + } + if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { + din->Release(); + din = 0; + qDebug() << "setup CreateDevice function failed!" << GetLastError(); + return; + } + if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { + qDebug() << "setup SetDataFormat function failed!" << GetLastError(); + dinkeyboard->Release(); + dinkeyboard = 0; + din->Release(); + din = 0; + } + + if (dinkeyboard->SetCooperativeLevel(window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); + return; + } + if (dinkeyboard->Acquire() != DI_OK) + { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); + return; + } + qDebug() << "keycodes bound:" << kCenter.keycode << kInhibit.keycode << kStartStop.keycode << kZero.keycode; + should_quit = false; +} + +#define PROCESS_KEY(k, s) \ + if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \ + window.s(); + +static bool isKeyPressed( const Key *key, const BYTE *keystate ) { + bool shift; + bool ctrl; + bool alt; + + if (keystate[key->keycode] & 0x80) { + shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) ); + ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) ); + alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) ); + + // + // If one of the modifiers is needed and not pressed, return false. + // + if (key->shift && !shift) return false; + if (key->ctrl && !ctrl) return false; + if (key->alt && !alt) return false; + + // + // All is well! + // + return true; + } + return false; +} -//#define USE_VISAGE +void KeybindingWorkerDummy::run() { + BYTE keystate[256]; + while (!should_quit) + { + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + + PROCESS_KEY(kCenter, shortcutRecentered); + PROCESS_KEY(kInhibit, shortcutInhibit); + PROCESS_KEY(kZero, shortcutZero); + PROCESS_KEY(kStartStop, shortcutStartStop); + + Sleep(25); + } +} +#else +#endif + +#ifdef _MSC_VER +# define LIB_PREFIX "" +#else +# define LIB_PREFIX "lib" +#endif // // Setup the Main Dialog // FaceTrackNoIR::FaceTrackNoIR(QWidget *parent, Qt::WFlags flags) : -QMainWindow(parent, flags), -pTrackerDialog(NULL), -pSecondTrackerDialog(NULL), -pProtocolDialog(NULL), -pFilterDialog(NULL) + QMainWindow(parent, flags), + pTrackerDialog(NULL), + pSecondTrackerDialog(NULL), + pProtocolDialog(NULL), + pFilterDialog(NULL), + trayIcon(NULL), + trayIconMenu(NULL), +#if defined(__WIN32) || defined(_WIN32) + keybindingWorker(NULL), +#endif + keyCenter(), + keyZero(), + keyStartStop(), + keyInhibit(), + looping(false) { + GlobalPose = new HeadPoseData(); cameraDetected = false; // @@ -86,7 +222,7 @@ pFilterDialog(NULL) startTracker(); } - Q_INIT_RESOURCE(PoseWidget); + //Q_INIT_RESOURCE(PoseWidget); _pose_display = new GLWidget(ui.widget4logo, 0); _pose_display->rotateBy(0, 0, 0); @@ -107,8 +243,11 @@ pFilterDialog(NULL) /** sets up all objects and connections to buttons */ void FaceTrackNoIR::setupFaceTrackNoIR() { - - ui.setupUi(this); + ui.setupUi(this); + + // if we simply place a global variable with THeadPoseData, + // it gets initialized and pulls in QSettings before + // main() starts. program can and will crash. ui.headPoseWidget->show(); ui.video_frame->hide(); @@ -152,9 +291,6 @@ void FaceTrackNoIR::setupFaceTrackNoIR() { connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); - // Connect slider for smoothing - connect(ui.slideSmoothing, SIGNAL(valueChanged(int)), this, SLOT(setSmoothing(int))); - //read the camera-name, using DirectShow GetCameraNameDX(); @@ -163,11 +299,14 @@ void FaceTrackNoIR::setupFaceTrackNoIR() { createActions(); createTrayIcon(); - connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); + if (trayIcon) + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); //Load the tracker-settings, from the INI-file loadSettings(); - trayIcon->show(); + + if (trayIcon) + trayIcon->show(); connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); @@ -183,7 +322,7 @@ void FaceTrackNoIR::setupFaceTrackNoIR() { connect(timUpdateHeadPose, SIGNAL(timeout()), this, SLOT(showHeadPose())); ui.txtTracking->setVisible(false); ui.txtAxisReverse->setVisible(false); - ui.gameName->setText(""); + settingsDirty = false; } /** destructor stops the engine and quits the faceapi **/ @@ -217,15 +356,6 @@ FaceTrackNoIR::~FaceTrackNoIR() { } } -// -// Get the ProgramName from a connected game and display it. -// -void FaceTrackNoIR::getGameProgramName() { - if ( tracker != NULL ) { - ui.gameName->setText( tracker->getGameProgramName() ); - } -} - // // Update the Settings, after a value has changed. This way, the Tracker does not have to re-start. // @@ -238,68 +368,14 @@ void FaceTrackNoIR::updateSettings() { // // Get a pointer to the video-widget, to use in the DLL // -QFrame *FaceTrackNoIR::getVideoWidget() { +QFrame *FaceTrackNoIR::get_video_widget() { return ui.video_frame; } -// -// Return the name of the Protocol-DLL -// -QString FaceTrackNoIR::getCurrentProtocolName() -{ - if (ui.iconcomboProtocol->currentIndex() < 0) { - return QString(""); - } - else { - return protocolFileList.at(ui.iconcomboProtocol->currentIndex()); - } -} - -// -// Return the name of the Filter-DLL -// -QString FaceTrackNoIR::getCurrentFilterName() -{ - qDebug() << "getCurrentFilterName says: " << ui.iconcomboFilter->currentIndex(); - if (ui.iconcomboFilter->currentIndex() <= 0) { - return QString("None"); - } - else { - return filterFileList.at(ui.iconcomboFilter->currentIndex() - 1 ); - } -} - -// -// Return the name of the Tracker-DLL -// -QString FaceTrackNoIR::getCurrentTrackerName() -{ - if (ui.iconcomboTrackerSource->currentIndex() < 0) { - return QString(""); - } - else { - qDebug() << "FaceTrackNoIR::getCurrentTrackerName libName = " << trackerFileList.at(ui.iconcomboTrackerSource->currentIndex()); - return trackerFileList.at(ui.iconcomboTrackerSource->currentIndex()); - } -} - -// -// Return the name of the second Tracker-DLL -// -QString FaceTrackNoIR::getSecondTrackerName() -{ - if (ui.cbxSecondTrackerSource->currentIndex() <= 0) { - return QString("None"); - } - else { - return trackerFileList.at(ui.cbxSecondTrackerSource->currentIndex() - 1 ); - } -} - /** read the name of the first video-capturing device at start up **/ /** FaceAPI can only use this first one... **/ void FaceTrackNoIR::GetCameraNameDX() { - +#if 0 //// ui.widget->setCameraName("No video-capturing device was found in your system: check if it's connected!"); ui.cameraName->setText("No video-capturing device was found in your system: check if it's connected!"); @@ -356,7 +432,7 @@ void FaceTrackNoIR::GetCameraNameDX() { pEnumCat->Release(); } pSysDevEnum->Release(); - +#endif } // @@ -364,26 +440,24 @@ void FaceTrackNoIR::GetCameraNameDX() { // If succesfull, the settings in it will be read // void FaceTrackNoIR::open() { - QFileDialog::Options options; - QFileDialog::FileMode mode; - - options |= QFileDialog::DontUseNativeDialog; - mode = QFileDialog::ExistingFile; - QString selectedFilter; - QStringList fileNames = QFileDialog::getOpenFileNames( + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::ExistingFile); + + QString fileName = dialog.getOpenFileName( this, tr("Select one FTNoir settings file"), - QCoreApplication::applicationDirPath() + "/Settings", - tr("Settings file (*.ini);;All Files (*)")); + QCoreApplication::applicationDirPath() + "/Settings/", + tr("Settings file (*.ini);;All Files (*)"), + NULL); // // If a file was selected, save it's name and read it's contents. // - if (! fileNames.isEmpty() ) { + if (! fileName.isEmpty() ) { QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) - settings.setValue ("SettingsFile", fileNames.at(0)); + settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath()); loadSettings(); - } + } } // @@ -397,7 +471,6 @@ void FaceTrackNoIR::save() { QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) iniFile.beginGroup ( "Tracking" ); - iniFile.setValue ( "Smooth", ui.slideSmoothing->value() ); iniFile.setValue ( "invertYaw", ui.chkInvertYaw->isChecked() ); iniFile.setValue ( "invertPitch", ui.chkInvertPitch->isChecked() ); iniFile.setValue ( "invertRoll", ui.chkInvertRoll->isChecked() ); @@ -407,21 +480,31 @@ void FaceTrackNoIR::save() { iniFile.endGroup (); iniFile.beginGroup ( "GameProtocol" ); - iniFile.setValue ( "Selection", ui.iconcomboProtocol->currentIndex() ); - iniFile.setValue ( "DLL", getCurrentProtocolName() ); + { + DynamicLibrary* proto = dlopen_protocols.value( ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", proto == NULL ? "" : proto->filename); + } iniFile.endGroup (); iniFile.beginGroup ( "TrackerSource" ); - iniFile.setValue ( "Selection", ui.iconcomboTrackerSource->currentIndex() ); - iniFile.setValue ( "DLL", getCurrentTrackerName() ); - iniFile.setValue ( "2ndDLL", getSecondTrackerName() ); + { + DynamicLibrary* tracker = dlopen_trackers.value( ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", tracker == NULL ? "" : tracker->filename); + } + { + DynamicLibrary* tracker = dlopen_trackers.value( ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); + iniFile.setValue ( "2ndDLL", tracker == NULL ? "" : tracker->filename); + } iniFile.endGroup (); // // Save the name of the filter in the INI-file. // iniFile.beginGroup ( "Filter" ); - iniFile.setValue ( "DLL", getCurrentFilterName() ); + { + DynamicLibrary* filter = dlopen_filters.value( ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", filter == NULL ? "" : filter->filename); + } iniFile.endGroup (); settingsDirty = false; @@ -484,18 +567,21 @@ void FaceTrackNoIR::saveAs() // Load the current Settings from the currently 'active' INI-file. // void FaceTrackNoIR::loadSettings() { - + if (looping) + return; + looping = true; qDebug() << "loadSettings says: Starting "; QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + qDebug() << "Config file now" << currentFile; QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) // // Put the filename in the window-title. // QFileInfo pathInfo ( currentFile ); - setWindowTitle ( "FaceTrackNoIR (1.7) - " + pathInfo.fileName() ); + setWindowTitle ( "FaceTrackNoIR (1.8 pre-alpha) - " + pathInfo.fileName() ); // // Get a List of all the INI-files in the (currently active) Settings-folder. @@ -509,22 +595,19 @@ void FaceTrackNoIR::loadSettings() { // // Add strings to the Listbox. // - disconnect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); ui.iconcomboProfile->clear(); for ( int i = 0; i < iniFileList.size(); i++) { - ui.iconcomboProfile->addItem(QIcon(":/images/Settings16.png"), iniFileList.at(i)); + ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), iniFileList.at(i)); if (iniFileList.at(i) == pathInfo.fileName()) { - ui.iconcomboProfile->setItemIcon(i, QIcon(":/images/SettingsOpen16.png")); + ui.iconcomboProfile->setItemIcon(i, QIcon(":/images/settingsopen16.png")); ui.iconcomboProfile->setCurrentIndex( i ); } } - connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); qDebug() << "loadSettings says: iniFile = " << currentFile; iniFile.beginGroup ( "Tracking" ); - ui.slideSmoothing->setValue (iniFile.value ( "Smooth", 10 ).toInt()); - ui.chkInvertYaw->setChecked (iniFile.value ( "invertYaw", 0 ).toBool()); + ui.chkInvertYaw->setChecked (iniFile.value ( "invertYaw", 0 ).toBool()); ui.chkInvertPitch->setChecked (iniFile.value ( "invertPitch", 0 ).toBool()); ui.chkInvertRoll->setChecked (iniFile.value ( "invertRoll", 0 ).toBool()); ui.chkInvertX->setChecked (iniFile.value ( "invertX", 0 ).toBool()); @@ -537,117 +620,61 @@ void FaceTrackNoIR::loadSettings() { // If the setting "DLL" isn't found (pre-1.7 version of INI), then the setting 'Selection' is evaluated. // iniFile.beginGroup ( "GameProtocol" ); + QString selectedProtocolName = iniFile.value ( "DLL", "" ).toString(); + iniFile.endGroup (); - QString selectedProtocolName = iniFile.value ( "DLL", "" ).toString(); - qDebug() << "loadSettings says: selectedProtocolName = " << selectedProtocolName; - - if (selectedProtocolName.length() == 0) { - int index = iniFile.value ( "Selection", 0 ).toInt(); - switch ( index ) { - case TRACKIR: - case FREE_TRACK: - selectedProtocolName = QString("FTNoIR_Protocol_FT.dll"); - break; - - case SIMCONNECT: - selectedProtocolName = QString("FTNoIR_Protocol_SC.dll"); - break; - - case PPJOY: - selectedProtocolName = QString("FTNoIR_Protocol_PPJOY.dll"); - break; - - case FSUIPC: - selectedProtocolName = QString("FTNoIR_Protocol_FSUIPC.dll"); - break; - - case FLIGHTGEAR: - selectedProtocolName = QString("FTNoIR_Protocol_FG.dll"); - break; - - case FTNOIR: - selectedProtocolName = QString("FTNoIR_Protocol_FTN.dll"); - break; - - case MOUSE: - selectedProtocolName = QString("FTNoIR_Protocol_MOUSE.dll"); - break; - - default: - selectedProtocolName = QString("FTNoIR_Protocol_MOUSE.dll"); - break; - } - } - iniFile.endGroup (); - - // + // // Find the Index of the DLL and set the selection. // - for ( int i = 0; i < protocolFileList.size(); i++) { - if (protocolFileList.at(i).compare( selectedProtocolName, Qt::CaseInsensitive ) == 0) { + for ( int i = 0; i < dlopen_protocols.size(); i++) { + if (dlopen_protocols.at(i)->filename.compare( selectedProtocolName, Qt::CaseInsensitive ) == 0) { ui.iconcomboProtocol->setCurrentIndex( i ); break; } } - // - // Read the currently selected Tracker from the INI-file. - // If the setting "DLL" isn't found (pre-1.7 version), then the setting 'Selection' is evaluated. - // - iniFile.beginGroup ( "TrackerSource" ); - QString selectedTrackerName = iniFile.value ( "DLL", "" ).toString(); - qDebug() << "loadSettings says: selectedTrackerName = " << selectedTrackerName; - if (selectedTrackerName.length() == 0) { - int index = iniFile.value ( "Selection", 0 ).toInt(); - switch ( index ) { - case 0: // Face API - selectedTrackerName = "FTNoIR_Tracker_SM.dll"; - break; - case 1: // FTNoir server - selectedTrackerName = "FTNoIR_Tracker_UDP.dll"; - break; - default: - selectedTrackerName = "FTNoIR_Tracker_SM.dll"; - break; - } - } - QString secondTrackerName = iniFile.value ( "2ndDLL", "None" ).toString(); - qDebug() << "loadSettings says: secondTrackerName = " << secondTrackerName; - - iniFile.endGroup (); - - disconnect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - disconnect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - for ( int i = 0; i < trackerFileList.size(); i++) { - if (trackerFileList.at(i).compare( selectedTrackerName, Qt::CaseInsensitive ) == 0) { + // + // Read the currently selected Tracker from the INI-file. + // If the setting "DLL" isn't found (pre-1.7 version), then the setting 'Selection' is evaluated. + // + iniFile.beginGroup ( "TrackerSource" ); + QString selectedTrackerName = iniFile.value ( "DLL", "" ).toString(); + qDebug() << "loadSettings says: selectedTrackerName = " << selectedTrackerName; + QString secondTrackerName = iniFile.value ( "2ndDLL", "None" ).toString(); + qDebug() << "loadSettings says: secondTrackerName = " << secondTrackerName; + iniFile.endGroup (); + + for ( int i = 0; i < dlopen_trackers.size(); i++) { + DynamicLibrary* foo = dlopen_trackers.at(i); + if (foo && foo->filename.compare( selectedTrackerName, Qt::CaseInsensitive ) == 0) { ui.iconcomboTrackerSource->setCurrentIndex( i ); } - if (trackerFileList.at(i).compare( secondTrackerName, Qt::CaseInsensitive ) == 0) { - ui.cbxSecondTrackerSource->setCurrentIndex( i + 1 ); // The first value = "None", so add 1 + if (foo && foo->filename.compare( secondTrackerName, Qt::CaseInsensitive ) == 0) { + ui.cbxSecondTrackerSource->setCurrentIndex( i + 1 ); } } - connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - connect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); // // Read the currently selected Filter from the INI-file. // iniFile.beginGroup ( "Filter" ); - QString selectedFilterName = iniFile.value ( "DLL", "FTNoIR_Filter_EWMA2.dll" ).toString(); + QString selectedFilterName = iniFile.value ( "DLL", "" ).toString(); qDebug() << "createIconGroupBox says: selectedFilterName = " << selectedFilterName; iniFile.endGroup (); // // Find the Index of the DLL and set the selection. // - for ( int i = 0; i < filterFileList.size(); i++) { - if (filterFileList.at(i).compare( selectedFilterName, Qt::CaseInsensitive ) == 0) { - ui.iconcomboFilter->setCurrentIndex( i + 1 ); // The first value = "None", so add 1 + for ( int i = 0; i < dlopen_filters.size(); i++) { + DynamicLibrary* foo = dlopen_filters.at(i); + if (foo && foo->filename.compare( selectedFilterName, Qt::CaseInsensitive ) == 0) { + ui.iconcomboFilter->setCurrentIndex( i ); break; } } settingsDirty = false; + looping = false; } /** show support page in web-browser **/ @@ -660,7 +687,6 @@ void FaceTrackNoIR::openurl_donation() { QDesktopServices::openUrl(QUrl("http://facetracknoir.sourceforge.net/information_links/donate.htm", QUrl::TolerantMode)); } - /** show about dialog **/ void FaceTrackNoIR::about() { @@ -676,11 +702,12 @@ void FaceTrackNoIR::about() { aboutDialog.setMinimumWidth(270); aboutDialog.setMinimumHeight(440); - aboutDialog.setStyleSheet("background:#fff url(:/UIElements/aboutFaceTrackNoIR.png) no-repeat;"); + aboutDialog.setStyleSheet("background:#fff url(:/uielements/aboutfacetracknoir.png) no-repeat;"); } /** start tracking the face **/ void FaceTrackNoIR::startTracker( ) { + bindKeyboardShortcuts(); // // Disable buttons @@ -694,14 +721,34 @@ void FaceTrackNoIR::startTracker( ) { // // Create the Tracker and setup // + + if (Libraries) + delete Libraries; + Libraries = new SelectedLibraries(this); + + if (!Libraries->correct) + { + QMessageBox::warning(this, "Something went wrong", "Tracking can't be initialized, probably protocol prerequisites missing", QMessageBox::Ok, QMessageBox::NoButton); + stopTracker(); + return; + } + +#if defined(_WIN32) || defined(__WIN32) + keybindingWorker = new KeybindingWorker(*this, keyCenter, keyInhibit, keyStartStop, keyZero); + keybindingWorker->start(); +#endif + + if (tracker) { + tracker->wait(); + delete tracker; + } + tracker = new Tracker ( this ); // // Setup the Tracker and send the settings. // This is necessary, because the events are only triggered 'on change' // - tracker->setup(); - tracker->setSmoothing ( ui.slideSmoothing->value() ); tracker->setInvertYaw (ui.chkInvertYaw->isChecked() ); tracker->setInvertPitch (ui.chkInvertPitch->isChecked() ); tracker->setInvertRoll (ui.chkInvertRoll->isChecked() ); @@ -709,13 +756,13 @@ void FaceTrackNoIR::startTracker( ) { tracker->setInvertY (ui.chkInvertY->isChecked() ); tracker->setInvertZ (ui.chkInvertZ->isChecked() ); - tracker->start( QThread::TimeCriticalPriority ); + tracker->start(); // // Register the Tracker instance with the Tracker Dialog (if open) // - if (pTrackerDialog) { - pTrackerDialog->registerTracker( tracker->getTrackerPtr() ); + if (pTrackerDialog && Libraries->pTracker) { + pTrackerDialog->registerTracker( Libraries->pTracker ); } ui.headPoseWidget->show(); @@ -728,7 +775,7 @@ void FaceTrackNoIR::startTracker( ) { ui.iconcomboTrackerSource->setEnabled ( false ); ui.cbxSecondTrackerSource->setEnabled ( false ); ui.iconcomboProtocol->setEnabled ( false ); -// ui.btnShowServerControls->setEnabled ( false ); + ui.btnShowServerControls->setEnabled ( false ); ui.iconcomboFilter->setEnabled ( false ); // @@ -736,7 +783,6 @@ void FaceTrackNoIR::startTracker( ) { // GetCameraNameDX(); - // // Get the TimeOut value for minimizing FaceTrackNoIR // Only start the Timer if value > 0 @@ -760,7 +806,7 @@ void FaceTrackNoIR::startTracker( ) { // // Start the timer to update the head-pose (digits and 'man in black') // - timUpdateHeadPose->start(50); + timUpdateHeadPose->start(40); ui.lblX->setVisible(true); ui.lblY->setVisible(true); @@ -780,13 +826,21 @@ void FaceTrackNoIR::startTracker( ) { /** stop tracking the face **/ void FaceTrackNoIR::stopTracker( ) { +#if defined(_WIN32) || defined(__WIN32) + if (keybindingWorker) + { + keybindingWorker->should_quit = true; + keybindingWorker->wait(); + delete keybindingWorker; + keybindingWorker = NULL; + } +#endif // // Stop displaying the head-pose. // timUpdateHeadPose->stop(); _pose_display->rotateBy(0, 0, 0); - ui.lblX->setVisible(false); ui.lblY->setVisible(false); ui.lblZ->setVisible(false); @@ -803,25 +857,33 @@ void FaceTrackNoIR::stopTracker( ) { ui.txtTracking->setVisible(false); ui.txtAxisReverse->setVisible(false); - // - // UnRegister the Tracker instance with the Tracker Dialog (if open) - // - if (pTrackerDialog) { - pTrackerDialog->unRegisterTracker(); - } - if (pProtocolDialog) { - pProtocolDialog->unRegisterProtocol(); - } - // // Delete the tracker (after stopping things and all). // - if ( tracker ) { + if ( tracker ) { + qDebug() << "Done with tracking"; + tracker->should_quit = true; + tracker->wait(); + qDebug() << "stopTracker says: Deleting tracker!"; delete tracker; qDebug() << "stopTracker says: Tracker deleted!"; tracker = 0; + if (Libraries) { + delete Libraries; + Libraries = NULL; + } } + + // + // UnRegister the Tracker instance with the Tracker Dialog (if open) + // + if (pTrackerDialog) { + pTrackerDialog->unRegisterTracker(); + } + if (pProtocolDialog) { + pProtocolDialog->unRegisterProtocol(); + } ui.btnStartTracker->setEnabled ( true ); ui.btnStopTracker->setEnabled ( false ); // ui.btnShowEngineControls->setEnabled ( false ); @@ -845,42 +907,47 @@ void FaceTrackNoIR::stopTracker( ) { // Stop the timer, so it won't go off again... // timMinimizeFTN->stop(); - } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertYaw( int invert ) { - Tracker::setInvertYaw ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertYaw ( (invert != 0)?true:false ); settingsDirty = true; } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertPitch( int invert ) { - Tracker::setInvertPitch ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertPitch ( (invert != 0)?true:false ); settingsDirty = true; } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertRoll( int invert ) { - Tracker::setInvertRoll ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertRoll ( (invert != 0)?true:false ); settingsDirty = true; } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertX( int invert ) { - Tracker::setInvertX ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertX ( (invert != 0)?true:false ); settingsDirty = true; } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertY( int invert ) { - Tracker::setInvertY ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertY ( (invert != 0)?true:false ); settingsDirty = true; } /** set the invert from the checkbox **/ void FaceTrackNoIR::setInvertZ( int invert ) { - Tracker::setInvertZ ( (invert != 0)?true:false ); + if (tracker) + tracker->setInvertZ ( (invert != 0)?true:false ); settingsDirty = true; } @@ -902,74 +969,39 @@ THeadPoseData newdata; ui.lcdNumOutputRotY->setVisible(true); ui.lcdNumOutputRotZ->setVisible(true); - if (!isMinimized()) { - - // - // Get the pose and also display it. - // Updating the pose from within the Tracker-class caused crashes... - // - Tracker::getHeadPose(&newdata); - ui.lcdNumX->display(QString("%1").arg(newdata.x, 0, 'f', 1)); - ui.lcdNumY->display(QString("%1").arg(newdata.y, 0, 'f', 1)); - ui.lcdNumZ->display(QString("%1").arg(newdata.z, 0, 'f', 1)); - - ui.lcdNumRotX->display(QString("%1").arg(newdata.yaw, 0, 'f', 1)); - ui.lcdNumRotY->display(QString("%1").arg(newdata.pitch, 0, 'f', 1)); - ui.lcdNumRotZ->display(QString("%1").arg(newdata.roll, 0, 'f', 1)); - - ui.txtTracking->setVisible(Tracker::getTrackingActive()); - ui.txtAxisReverse->setVisible(Tracker::getAxisReverse()); - - // - // Get the output-pose and also display it. - // - if (_pose_display) { - Tracker::getOutputHeadPose(&newdata); - _pose_display->rotateBy(newdata.pitch, newdata.yaw, newdata.roll); - - ui.lcdNumOutputPosX->display(QString("%1").arg(newdata.x, 0, 'f', 1)); - ui.lcdNumOutputPosY->display(QString("%1").arg(newdata.y, 0, 'f', 1)); - ui.lcdNumOutputPosZ->display(QString("%1").arg(newdata.z, 0, 'f', 1)); + // + // Get the pose and also display it. + // Updating the pose from within the Tracker-class caused crashes... + // + tracker->getHeadPose(&newdata); + ui.lcdNumX->display(QString("%1").arg(newdata.x, 0, 'f', 1)); + ui.lcdNumY->display(QString("%1").arg(newdata.y, 0, 'f', 1)); + ui.lcdNumZ->display(QString("%1").arg(newdata.z, 0, 'f', 1)); - ui.lcdNumOutputRotX->display(QString("%1").arg(newdata.yaw, 0, 'f', 1)); - ui.lcdNumOutputRotY->display(QString("%1").arg(newdata.pitch, 0, 'f', 1)); - ui.lcdNumOutputRotZ->display(QString("%1").arg(newdata.roll, 0, 'f', 1)); - } + ui.lcdNumRotX->display(QString("%1").arg(newdata.yaw, 0, 'f', 1)); + ui.lcdNumRotY->display(QString("%1").arg(newdata.pitch, 0, 'f', 1)); + ui.lcdNumRotZ->display(QString("%1").arg(newdata.roll, 0, 'f', 1)); - // - // Update the video-widget. - // Requested by Stanislaw - // - if (tracker) { - ITracker * theTracker = tracker->getTrackerPtr(); - if (theTracker) { - theTracker->refreshVideo(); - } - } - // Tracker::doRefreshVideo(); + ui.txtTracking->setVisible(tracker->getTrackingActive()); + ui.txtAxisReverse->setVisible(tracker->getAxisReverse()); - if (_curve_config) { - _curve_config->update(); - } - } - //else { - // qDebug() << "FaceTrackNoIR::showHeadPose status: window = minimized."; - //} -} - -/** set the smoothing from the slider **/ -void FaceTrackNoIR::setSmoothing( int smooth ) { - // - // Pass the smoothing setting, if the Tracker exists. + // Get the output-pose and also display it. // - if ( tracker ) { - tracker->setSmoothing ( smooth ); - settingsDirty = true; + if (_pose_display) { + tracker->getOutputHeadPose(&newdata); + _pose_display->rotateBy(newdata.pitch, newdata.yaw, newdata.roll); + + ui.lcdNumOutputPosX->display(QString("%1").arg(newdata.x, 0, 'f', 1)); + ui.lcdNumOutputPosY->display(QString("%1").arg(newdata.y, 0, 'f', 1)); + ui.lcdNumOutputPosZ->display(QString("%1").arg(newdata.z, 0, 'f', 1)); + + ui.lcdNumOutputRotX->display(QString("%1").arg(newdata.yaw, 0, 'f', 1)); + ui.lcdNumOutputRotY->display(QString("%1").arg(newdata.pitch, 0, 'f', 1)); + ui.lcdNumOutputRotZ->display(QString("%1").arg(newdata.roll, 0, 'f', 1)); } } - /** toggles Video Widget **/ void FaceTrackNoIR::showVideoWidget() { if(ui.video_frame->isHidden()) @@ -988,195 +1020,74 @@ void FaceTrackNoIR::showHeadPoseWidget() { /** toggles Engine Controls Dialog **/ void FaceTrackNoIR::showTrackerSettings() { -importGetTrackerDialog getIT; -QLibrary *trackerLib; -QString libName; - - qDebug() << "FaceTrackNoIR::showTrackerSettings started."; - - // - // Delete the existing QDialog - // if (pTrackerDialog) { delete pTrackerDialog; pTrackerDialog = NULL; } - // Show the appropriate Tracker Settings - libName.clear(); - libName = getCurrentTrackerName(); - - // - // Load the Server-settings dialog (if any) and show it. - // - if (!libName.isEmpty()) { - trackerLib = new QLibrary(libName); - -// qDebug() << "FaceTrackNoIR::showTrackerSettings Loaded trackerLib." << trackerLib; - - getIT = (importGetTrackerDialog) trackerLib->resolve("GetTrackerDialog"); - -// qDebug() << "FaceTrackNoIR::showTrackerSettings resolved." << getIT; - - if (getIT) { - ITrackerDialog *ptrXyz(getIT()); - if (ptrXyz) - { - pTrackerDialog = ptrXyz; - pTrackerDialog->Initialize( this ); -// qDebug() << "FaceTrackNoIR::showTrackerSettings GetTrackerDialog Function Resolved!"; - if (tracker) { - pTrackerDialog->registerTracker( tracker->getTrackerPtr() ); -// qDebug() << "FaceTrackNoIR::showTrackerSettings RegisterTracker Function Executed"; - } - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } + DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); + if (lib) { + pTrackerDialog = (ITrackerDialog*) lib->Dialog(); + if (pTrackerDialog) { + pTrackerDialog->Initialize(this); + if (Libraries && Libraries->pTracker) + pTrackerDialog->registerTracker(Libraries->pTracker); + } + } } // Show the Settings dialog for the secondary Tracker void FaceTrackNoIR::showSecondTrackerSettings() { -importGetTrackerDialog getIT; -QLibrary *trackerLib; -QString libName; - - qDebug() << "FaceTrackNoIR::showSecondTrackerSettings started."; - - // - // Delete the existing QDialog - // - if (pSecondTrackerDialog) { - delete pSecondTrackerDialog; - pSecondTrackerDialog = NULL; - } - - // Show the appropriate Tracker Settings - libName.clear(); - libName = getSecondTrackerName(); - - // - // Load the Server-settings dialog (if any) and show it. - // - if ((!libName.isEmpty()) && (libName != "None")) { - trackerLib = new QLibrary(libName); - -// qDebug() << "FaceTrackNoIR::showTrackerSettings Loaded trackerLib." << trackerLib; - - getIT = (importGetTrackerDialog) trackerLib->resolve("GetTrackerDialog"); - -// qDebug() << "FaceTrackNoIR::showTrackerSettings resolved." << getIT; + if (pSecondTrackerDialog) { + delete pSecondTrackerDialog; + pSecondTrackerDialog = NULL; + } - if (getIT) { - ITrackerDialog *ptrXyz(getIT()); - if (ptrXyz) - { - pSecondTrackerDialog = ptrXyz; - pSecondTrackerDialog->Initialize( this ); -// qDebug() << "FaceTrackNoIR::showTrackerSettings GetTrackerDialog Function Resolved!"; - if (tracker) { - pSecondTrackerDialog->registerTracker( tracker->getSecondTrackerPtr() ); -// qDebug() << "FaceTrackNoIR::showTrackerSettings RegisterTracker Function Executed"; - } - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } + DynamicLibrary* lib = dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); + if (lib) { + pSecondTrackerDialog = (ITrackerDialog*) lib->Dialog(); + if (pSecondTrackerDialog) { + pSecondTrackerDialog->Initialize(this); + if (Libraries && Libraries->pSecondTracker) + pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker); + } + } } /** toggles Server Controls Dialog **/ void FaceTrackNoIR::showServerControls() { -importGetProtocolDialog getIT; -QLibrary *protocolLib; -QString libName; - - // - // Delete the existing QDialog - // - if (pProtocolDialog) { - delete pProtocolDialog; - } - - // Show the appropriate Protocol-server Settings - libName.clear(); - libName = getCurrentProtocolName(); + if (pProtocolDialog) { + delete pProtocolDialog; + pProtocolDialog = NULL; + } - // - // Load the Server-settings dialog (if any) and show it. - // - if (!libName.isEmpty()) { - protocolLib = new QLibrary(libName); + DynamicLibrary* lib = dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); - getIT = (importGetProtocolDialog) protocolLib->resolve("GetProtocolDialog"); - if (getIT) { - IProtocolDialogPtr ptrXyz(getIT()); - if (ptrXyz) - { - pProtocolDialog = ptrXyz; - pProtocolDialog->Initialize( this ); - if (tracker) { - pProtocolDialog->registerProtocol( tracker->getProtocolPtr() ); - qDebug() << "FaceTrackNoIR::showServerControls RegisterProtocol Function Executed"; - } - qDebug() << "FaceTrackNoIR::showServerControls GetProtocolDialog Function Resolved!"; - } - else { - qDebug() << "FaceTrackNoIR::showServerControls Function NOT Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } + if (lib && lib->Dialog) { + pProtocolDialog = (IProtocolDialog*) lib->Dialog(); + if (pProtocolDialog) { + pProtocolDialog->Initialize(this); + } + } } /** toggles Filter Controls Dialog **/ void FaceTrackNoIR::showFilterControls() { -importGetFilterDialog getIT; -QLibrary *filterLib; -QString libName; - - // - // Delete the existing QDialog - // - if (pFilterDialog) { - delete pFilterDialog; - pFilterDialog = NULL; - } - - // Get the currently selected Filter - libName.clear(); - libName = getCurrentFilterName(); + if (pFilterDialog) { + delete pFilterDialog; + pFilterDialog = NULL; + } - // - // Load the Filter-settings dialog (if any) and show it. - // - if (!libName.isEmpty()) { - filterLib = new QLibrary(libName); + DynamicLibrary* lib = dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); - getIT = (importGetFilterDialog) filterLib->resolve("GetFilterDialog"); - if (getIT) { - IFilterDialogPtr ptrXyz(getIT()); - if (ptrXyz) - { - pFilterDialog = ptrXyz; - pFilterDialog->Initialize( this, Tracker::getFilterPtr() ); - qDebug() << "FaceTrackNoIR::showFilterControls GetFilterDialog Function Resolved!"; - } - else { - qDebug() << "FaceTrackNoIR::showFilterControls Function NOT Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } + if (lib && lib->Dialog) { + pFilterDialog = (IFilterDialog*) lib->Dialog(); + if (pFilterDialog) { + pFilterDialog->Initialize(this, Libraries ? Libraries->pFilter : NULL); + } + } } /** toggles FaceTrackNoIR Preferences Dialog **/ @@ -1237,160 +1148,84 @@ void FaceTrackNoIR::exit() { // void FaceTrackNoIR::createIconGroupBox() { -importGetProtocolDll getProtocol; -IProtocolDllPtr pProtocolDll; // Pointer to Protocol info instance (in DLL) -importGetFilterDll getFilter; -IFilterDllPtr pFilterDll; // Pointer to Filter info instance (in DLL) -importGetTrackerDll getTracker; -ITrackerDll *pTrackerDll; // Pointer to Tracker info instance (in DLL) -QStringList listDLLs; // List of specific DLLs - - QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - // - // Get a List of all the Protocol-DLL-files in the Program-folder. - // QDir settingsDir( QCoreApplication::applicationDirPath() ); - QStringList filters; - filters.clear(); - filters << "FTNoIR_Protocol_*.dll"; - protocolFileList.clear(); - listDLLs.clear(); - listDLLs = settingsDir.entryList( filters, QDir::Files, QDir::Name ); - - // - // Add strings to the Listbox. - // - disconnect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); - ui.iconcomboProtocol->clear(); - for ( int i = 0; i < listDLLs.size(); i++) { - - // Try to load the DLL and get the Icon and Name - QLibrary *protocolLib = new QLibrary(listDLLs.at(i)); - QString *protocolName = new QString(""); - QIcon *protocolIcon = new QIcon(); - - getProtocol = (importGetProtocolDll) protocolLib->resolve("GetProtocolDll"); - if (getProtocol) { - IProtocolDllPtr ptrXyz(getProtocol()); - if (ptrXyz) - { - pProtocolDll = ptrXyz; - pProtocolDll->getFullName( protocolName ); - pProtocolDll->getIcon( protocolIcon ); - - // - // Add the Icon and the Name to the Listbox and update the fileList - // - ui.iconcomboProtocol->addItem(*protocolIcon, *protocolName ); - protocolFileList.append(listDLLs.at(i)); - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Protocol-DLL not loaded, please check if the DLL is version 1.7 \nand all dependencies are installed. \n(" + listDLLs.at(i) + ")",QMessageBox::Ok,QMessageBox::NoButton); - } - - } - connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); - - // - // Get a List of all the Filter-DLL-files in the Program-folder. - // - filters.clear(); - filters << "FTNoIR_Filter_*.dll"; - filterFileList.clear(); - listDLLs.clear(); - listDLLs = settingsDir.entryList( filters, QDir::Files, QDir::Name ); - - // - // Add strings to the Listbox. - // - disconnect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); - ui.iconcomboFilter->clear(); - ui.iconcomboFilter->addItem("None"); - - for ( int i = 0; i < listDLLs.size(); i++) { - - // Try to load the DLL and get the Icon and Name - QLibrary *filterLib = new QLibrary(listDLLs.at(i)); - QString *filterName = new QString(""); - QIcon *filterIcon = new QIcon(); - - getFilter = (importGetFilterDll) filterLib->resolve("GetFilterDll"); - if (getFilter) { - IFilterDllPtr ptrXyz(getFilter()); - if (ptrXyz) - { - pFilterDll = ptrXyz; - pFilterDll->getFullName( filterName ); - pFilterDll->getIcon( filterIcon ); - - // - // Add the Icon and the Name to the Listbox and update the fileList - // - ui.iconcomboFilter->addItem(*filterIcon, *filterName ); - filterFileList.append(listDLLs.at(i)); - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Filter-DLL not loaded, please check if the DLL is version 1.7 \nand all dependencies are installed. \n(" + listDLLs.at(i) + ")",QMessageBox::Ok,QMessageBox::NoButton); - } - } - connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); - - // - // Get a List of all the Tracker-DLL-files in the Program-folder. - // - filters.clear(); - filters << "FTNoIR_Tracker_*.dll"; - trackerFileList.clear(); - listDLLs.clear(); - listDLLs = settingsDir.entryList( filters, QDir::Files, QDir::Name ); - - // - // Add strings to the Listbox(es). - // - disconnect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - ui.iconcomboTrackerSource->clear(); - - disconnect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - ui.cbxSecondTrackerSource->clear(); - ui.cbxSecondTrackerSource->addItem("None"); - - for ( int i = 0; i < listDLLs.size(); i++) { - - // Try to load the DLL and get the Icon and Name - QLibrary *trackerLib = new QLibrary(listDLLs.at(i)); - QString *trackerName = new QString(""); - QIcon *trackerIcon = new QIcon(); + { + QStringList protocols = settingsDir.entryList( QStringList() << (LIB_PREFIX "ftnoir-proto-*." SONAME), QDir::Files, QDir::Name ); + for ( int i = 0; i < protocols.size(); i++) { + QIcon icon; + QString longName; + QString str = protocols.at(i); + DynamicLibrary* lib = new DynamicLibrary(str.toLatin1().constData()); + qDebug() << "Loading" << str; + std::cout.flush(); + Metadata* meta; + if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) + { + delete lib; + continue; + } + meta->getFullName(&longName); + meta->getIcon(&icon); + delete meta; + dlopen_protocols.push_back(lib); + ui.iconcomboProtocol->addItem(icon, longName); + } + } - getTracker = (importGetTrackerDll) trackerLib->resolve("GetTrackerDll"); - if (getTracker) { - ITrackerDll *ptrXyz(getTracker()); - if (ptrXyz) - { - pTrackerDll = ptrXyz; - pTrackerDll->getFullName( trackerName ); - pTrackerDll->getIcon( trackerIcon ); + { + ui.cbxSecondTrackerSource->addItem(QIcon(), "None"); + QStringList trackers = settingsDir.entryList( QStringList() << (LIB_PREFIX "ftnoir-tracker-*." SONAME), QDir::Files, QDir::Name ); + for ( int i = 0; i < trackers.size(); i++) { + QIcon icon; + QString longName; + QString str = trackers.at(i); + DynamicLibrary* lib = new DynamicLibrary(str.toLatin1().constData()); + qDebug() << "Loading" << str; + std::cout.flush(); + Metadata* meta; + if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) + { + delete lib; + continue; + } + meta->getFullName(&longName); + meta->getIcon(&icon); + delete meta; + dlopen_trackers.push_back(lib); + ui.iconcomboTrackerSource->addItem(icon, longName); + ui.cbxSecondTrackerSource->addItem(icon, longName); + } + } - // - // Add the Icon and the Name to the Listbox and update the fileList - // - ui.iconcomboTrackerSource->addItem(*trackerIcon, *trackerName ); - ui.cbxSecondTrackerSource->addItem(*trackerIcon, *trackerName ); - trackerFileList.append(listDLLs.at(i)); - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Tracker-DLL not loaded, please check if the DLL is version 1.7 \nand all dependencies are installed. \n(" + listDLLs.at(i) + ")",QMessageBox::Ok,QMessageBox::NoButton); - } + { + dlopen_filters.push_back((DynamicLibrary*) NULL); + ui.iconcomboFilter->addItem(QIcon(), "None"); + QStringList filters = settingsDir.entryList( QStringList() << (LIB_PREFIX "ftnoir-filter-*." SONAME), QDir::Files, QDir::Name ); + for ( int i = 0; i < filters.size(); i++) { + QIcon icon; + QString fullName; + QString str = filters.at(i); + DynamicLibrary* lib = new DynamicLibrary(str.toLatin1().constData()); + qDebug() << "Loading" << str; + std::cout.flush(); + Metadata* meta; + if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) + { + delete lib; + continue; + } + meta->getFullName(&fullName); + meta->getIcon(&icon); + delete meta; + dlopen_filters.push_back(lib); + ui.iconcomboFilter->addItem(icon, fullName); + } + } - } - connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); + connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); + connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); + connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); connect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); } @@ -1427,7 +1262,7 @@ void FaceTrackNoIR::createTrayIcon() trayIcon = new QSystemTrayIcon(this); trayIcon->setContextMenu(trayIconMenu); - trayIcon->setIcon(QIcon(QCoreApplication::applicationDirPath() + "/images/FaceTrackNoIR.ico")); + //trayIcon->setIcon(QIcon(QCoreApplication::applicationDirPath() + "/images/FaceTrackNoIR.png")); } } @@ -1468,8 +1303,9 @@ void FaceTrackNoIR::protocolSelected(int index) trayIcon->show(); trayIcon->showMessage( "FaceTrackNoIR", ui.iconcomboProtocol->itemText(index)); } - setWindowIcon(QIcon(":/images/FaceTrackNoIR.ico")); - ui.btnShowServerControls->setIcon(icon); + //setWindowIcon(QIcon(":/images/FaceTrackNoIR.png")); + //breaks with transparency -sh + //ui.btnShowServerControls->setIcon(icon);] } // @@ -1496,7 +1332,7 @@ void FaceTrackNoIR::profileSelected(int index) // // Save the name of the INI-file in the Registry. // - settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + iniFileList.at(ui.iconcomboProfile->currentIndex())); + settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + iniFileList.value(ui.iconcomboProfile->currentIndex(), "")); loadSettings(); } @@ -1645,27 +1481,22 @@ QWidget( parent , f) connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); connect(ui.cbxCenterKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); - connect(ui.cbxCenterMouseKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); connect(ui.chkCenterShift, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkCenterCtrl, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkCenterAlt, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.cbxGameZeroKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); - connect(ui.cbxGameZeroMouseKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); connect(ui.chkGameZeroShift, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkGameZeroCtrl, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkGameZeroAlt, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.cbxStartStopKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); - connect(ui.cbxStartStopMouseKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); connect(ui.chkStartStopShift, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkStartStopCtrl, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkStartStopAlt, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.radioSetZero, SIGNAL(toggled(bool)), this, SLOT(keyChanged(bool))); - connect(ui.radioSetEngineStop, SIGNAL(toggled(bool)), this, SLOT(keyChanged(bool))); connect(ui.cbxInhibitKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); - connect(ui.cbxInhibitMouseKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int ))); connect(ui.chkInhibitShift, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkInhibitCtrl, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkInhibitAlt, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); @@ -1678,168 +1509,18 @@ QWidget( parent , f) connect(ui.chkInhibitY, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); connect(ui.chkInhibitZ, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int))); - // // Clear the Lists with key-descriptions and keycodes and build the Lists // The strings will all be added to the ListBoxes for each Shortkey // - stringList.clear(); - stringList.append("NONE"); - stringList.append("F1"); - stringList.append("F2"); - stringList.append("F3"); - stringList.append("F4"); - stringList.append("F5"); - stringList.append("F6"); - stringList.append("F7"); - stringList.append("F8"); - stringList.append("F9"); - stringList.append("F10"); - stringList.append("F11"); - stringList.append("F12"); - stringList.append("MINUS"); - stringList.append("EQUALS"); - stringList.append("BACK"); - stringList.append("A"); - stringList.append("B"); - stringList.append("C"); - stringList.append("D"); - stringList.append("E"); - stringList.append("F"); - stringList.append("G"); - stringList.append("H"); - stringList.append("I"); - stringList.append("J"); - stringList.append("K"); - stringList.append("L"); - stringList.append("M"); - stringList.append("N"); - stringList.append("O"); - stringList.append("P"); - stringList.append("Q"); - stringList.append("R"); - stringList.append("S"); - stringList.append("T"); - stringList.append("U"); - stringList.append("V"); - stringList.append("W"); - stringList.append("X"); - stringList.append("Y"); - stringList.append("Z"); - stringList.append("NUMPAD0"); - stringList.append("NUMPAD1"); - stringList.append("NUMPAD2"); - stringList.append("NUMPAD3"); - stringList.append("NUMPAD4"); - stringList.append("NUMPAD5"); - stringList.append("NUMPAD6"); - stringList.append("NUMPAD7"); - stringList.append("NUMPAD8"); - stringList.append("NUMPAD9"); - stringList.append("HOME"); - stringList.append("UP"); - stringList.append("PGUP"); /* PgUp on arrow keypad */ - stringList.append("LEFT"); - stringList.append("RIGHT"); - stringList.append("END"); - stringList.append("DOWN"); - stringList.append("PGDWN"); /* PgDn on arrow keypad */ - stringList.append("INSERT"); - stringList.append("DELETE"); - - keyList.clear(); - keyList.append(0); // NONE = 0 - keyList.append(DIK_F1); - keyList.append(DIK_F2); - keyList.append(DIK_F3); - keyList.append(DIK_F4); - keyList.append(DIK_F5); - keyList.append(DIK_F6); - keyList.append(DIK_F7); - keyList.append(DIK_F8); - keyList.append(DIK_F9); - keyList.append(DIK_F10); - keyList.append(DIK_F11); - keyList.append(DIK_F12); - keyList.append(DIK_MINUS); - keyList.append(DIK_EQUALS); - keyList.append(DIK_BACK); - keyList.append(DIK_A); - keyList.append(DIK_B); - keyList.append(DIK_C); - keyList.append(DIK_D); - keyList.append(DIK_E); - keyList.append(DIK_F); - keyList.append(DIK_G); - keyList.append(DIK_H); - keyList.append(DIK_I); - keyList.append(DIK_J); - keyList.append(DIK_K); - keyList.append(DIK_L); - keyList.append(DIK_M); - keyList.append(DIK_N); - keyList.append(DIK_O); - keyList.append(DIK_P); - keyList.append(DIK_Q); - keyList.append(DIK_R); - keyList.append(DIK_S); - keyList.append(DIK_T); - keyList.append(DIK_U); - keyList.append(DIK_V); - keyList.append(DIK_W); - keyList.append(DIK_X); - keyList.append(DIK_Y); - keyList.append(DIK_Z); - keyList.append(DIK_NUMPAD0); - keyList.append(DIK_NUMPAD1); - keyList.append(DIK_NUMPAD2); - keyList.append(DIK_NUMPAD3); - keyList.append(DIK_NUMPAD4); - keyList.append(DIK_NUMPAD5); - keyList.append(DIK_NUMPAD6); - keyList.append(DIK_NUMPAD7); - keyList.append(DIK_NUMPAD8); - keyList.append(DIK_NUMPAD9); - keyList.append(DIK_HOME); - keyList.append(DIK_UP); - keyList.append(DIK_PRIOR); /* PgUp on arrow keypad */ - keyList.append(DIK_LEFT); - keyList.append(DIK_RIGHT); - keyList.append(DIK_END); - keyList.append(DIK_DOWN); - keyList.append(DIK_NEXT); /* PgDn on arrow keypad */ - keyList.append(DIK_INSERT); - keyList.append(DIK_DELETE); - // // Add strings to the Listboxes. // - for ( int i = 0; i < stringList.size(); i++) { - ui.cbxCenterKey->addItem(stringList.at(i)); - ui.cbxGameZeroKey->addItem(stringList.at(i)); - ui.cbxStartStopKey->addItem(stringList.at(i)); - ui.cbxInhibitKey->addItem(stringList.at(i)); - } - - // - // Clear the Lists with key-descriptions and keycodes and build the Lists - // The strings will all be added to the ListBoxes for each Shortkey - // - stringListMouse.clear(); - stringListMouse.append("NONE"); - stringListMouse.append("LEFT"); - stringListMouse.append("RIGHT"); - stringListMouse.append("MIDDLE"); - stringListMouse.append("BACK"); - stringListMouse.append("FORWARD"); - // - // Add strings to the Listboxes. - // - for ( int i = 0; i < stringListMouse.size(); i++) { - ui.cbxCenterMouseKey->addItem(stringListMouse.at(i)); - ui.cbxGameZeroMouseKey->addItem(stringListMouse.at(i)); - ui.cbxStartStopMouseKey->addItem(stringListMouse.at(i)); - ui.cbxInhibitMouseKey->addItem(stringListMouse.at(i)); + for ( int i = 0; i < global_key_sequences.size(); i++) { + ui.cbxCenterKey->addItem(global_key_sequences.at(i)); + ui.cbxGameZeroKey->addItem(global_key_sequences.at(i)); + ui.cbxStartStopKey->addItem(global_key_sequences.at(i)); + ui.cbxInhibitKey->addItem(global_key_sequences.at(i)); } // Load the settings from the current .INI-file @@ -1859,6 +1540,7 @@ KeyboardShortcutDialog::~KeyboardShortcutDialog() { void KeyboardShortcutDialog::doOK() { save(); this->close(); + mainApp->bindKeyboardShortcuts(); } // override show event @@ -1899,12 +1581,140 @@ void KeyboardShortcutDialog::doCancel() { } } +void FaceTrackNoIR::bindKeyboardShortcuts() +{ + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + iniFile.beginGroup ( "KB_Shortcuts" ); + int idxCenter = iniFile.value("Key_index_Center", 0).toInt(); + int idxGameZero = iniFile.value("Key_index_GameZero", 0).toInt(); + int idxStartStop = iniFile.value("Key_index_StartStop", 0).toInt(); + int idxInhibit = iniFile.value("Key_index_Inhibit", 0).toInt(); + +#if !defined(_WIN32) && !defined(__WIN32) + if (keyCenter) { + delete keyCenter; + keyCenter = NULL; + } + + if (keyZero) { + delete keyZero; + keyZero = NULL; + } + + if (keyStartStop) { + delete keyStartStop; + keyStartStop = NULL; + } + + if (keyInhibit) { + delete keyInhibit; + keyInhibit = NULL; + } + + if (idxCenter > 0) + { + QString seq(global_key_sequences.value(idxCenter, "")); + if (!seq.isEmpty()) + { + if (iniFile.value("Shift_Center", false).toBool()) + seq = "Shift+" + seq; + if (iniFile.value("Alt_Center", false).toBool()) + seq = "Alt+" + seq; + if (iniFile.value("Ctrl_Center", false).toBool()) + seq = "Ctrl+" + seq; + keyCenter = new QxtGlobalShortcut(QKeySequence(seq)); + connect(keyCenter, SIGNAL(activated()), this, SLOT(shortcutRecentered())); + } + } + + if (idxGameZero > 0) + { + QString seq(global_key_sequences.value(idxGameZero, "")); + if (!seq.isEmpty()) + { + if (iniFile.value("Shift_GameZero", false).toBool()) + seq = "Shift+" + seq; + if (iniFile.value("Alt_GameZero", false).toBool()) + seq = "Alt+" + seq; + if (iniFile.value("Ctrl_GameZero", false).toBool()) + seq = "Ctrl+" + seq; + } + keyZero = new QxtGlobalShortcut(QKeySequence(seq)); + connect(keyZero, SIGNAL(activated()), this, SLOT(shortcutZero())); + } + + if (idxStartStop > 0) + { + QString seq(global_key_sequences.value(idxStartStop, "")); + if (!seq.isEmpty()) + { + if (iniFile.value("Shift_StartStop", false).toBool()) + seq = "Shift+" + seq; + if (iniFile.value("Alt_StartStop", false).toBool()) + seq = "Alt+" + seq; + if (iniFile.value("Ctrl_StartStop", false).toBool()) + seq = "Ctrl+" + seq; + } + keyStartStop = new QxtGlobalShortcut(QKeySequence(seq)); + connect(keyStartStop, SIGNAL(activated()), this, SLOT(shortcutStartStop())); + } + + if (idxInhibit > 0) + { + QString seq(global_key_sequences.value(idxInhibit, "")); + if (!seq.isEmpty()) + { + if (iniFile.value("Shift_Inhibit", false).toBool()) + seq = "Shift+" + seq; + if (iniFile.value("Alt_Inhibit", false).toBool()) + seq = "Alt+" + seq; + if (iniFile.value("Ctrl_Inhibit", false).toBool()) + seq = "Ctrl+" + seq; + } + keyInhibit = new QxtGlobalShortcut(QKeySequence(seq)); + connect(keyInhibit, SIGNAL(activated()), this, SLOT(shortcutInhibit())); + } +#else + keyCenter.keycode = keyZero.keycode = keyInhibit.keycode = keyStartStop.keycode = 0; + keyCenter.shift = keyCenter.alt = keyCenter.ctrl = 0; + keyZero.shift = keyZero.alt = keyZero.ctrl = 0; + keyInhibit.shift = keyInhibit.alt = keyInhibit.ctrl = 0; + keyStartStop.shift = keyStartStop.alt = keyStartStop.ctrl = 0; + if (idxCenter > 0 && idxCenter < global_windows_key_sequences.size()) + keyCenter.keycode = global_windows_key_sequences[idxCenter]; + if (idxGameZero > 0 && idxCenter < global_windows_key_sequences.size()) + keyZero.keycode = global_windows_key_sequences[idxGameZero]; + if (idxInhibit > 0 && idxInhibit < global_windows_key_sequences.size()) + keyInhibit.keycode = global_windows_key_sequences[idxInhibit]; + if (idxStartStop > 0 && idxStartStop < global_windows_key_sequences.size()) + keyStartStop.keycode = global_windows_key_sequences[idxStartStop]; + + keyCenter.shift = iniFile.value("Shift_Center", false).toBool(); + keyCenter.alt = iniFile.value("Alt_Center", false).toBool(); + keyCenter.ctrl = iniFile.value("Ctrl_Center", false).toBool(); + + keyInhibit.shift = iniFile.value("Shift_Inhibit", false).toBool(); + keyInhibit.alt = iniFile.value("Alt_Inhibit", false).toBool(); + keyInhibit.ctrl = iniFile.value("Ctrl_Inhibit", false).toBool(); + + keyZero.shift = iniFile.value("Shift_GameZero", false).toBool(); + keyZero.alt = iniFile.value("Alt_GameZero", false).toBool(); + keyZero.ctrl = iniFile.value("Ctrl_GameZero", false).toBool(); + + keyStartStop.shift = iniFile.value("Shift_StartStop", false).toBool(); + keyStartStop.alt = iniFile.value("Alt_StartStop", false).toBool(); + keyStartStop.ctrl = iniFile.value("Ctrl_StartStop", false).toBool(); +#endif + iniFile.endGroup (); +} + // // Load the current Settings from the currently 'active' INI-file. // void KeyboardShortcutDialog::loadSettings() { -int keyindex; - qDebug() << "loadSettings says: Starting "; QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) @@ -1915,62 +1725,29 @@ int keyindex; iniFile.beginGroup ( "KB_Shortcuts" ); - // Center key - ui.cbxCenterMouseKey->setCurrentIndex( iniFile.value ( "MouseKey_Center", 0 ).toInt() ); - keyindex = keyList.indexOf ( iniFile.value ( "Keycode_Center", DIK_HOME ).toInt() ); - if ( keyindex > 0 ) { - ui.cbxCenterKey->setCurrentIndex( keyindex ); - } - else { - ui.cbxCenterKey->setCurrentIndex( 0 ); - } - ui.chkCenterShift->setChecked (iniFile.value ( "Shift_Center", 0 ).toBool()); + ui.chkCenterShift->setChecked (iniFile.value ( "Shift_Center", 0 ).toBool()); ui.chkCenterCtrl->setChecked (iniFile.value ( "Ctrl_Center", 0 ).toBool()); ui.chkCenterAlt->setChecked (iniFile.value ( "Alt_Center", 0 ).toBool()); - ui.chkDisableBeep->setChecked (iniFile.value ( "Disable_Beep", 0 ).toBool()); - // GameZero key - ui.cbxGameZeroMouseKey->setCurrentIndex( iniFile.value ( "MouseKey_GameZero", 0 ).toInt() ); - keyindex = keyList.indexOf ( iniFile.value ( "Keycode_GameZero", 1 ).toInt() ); - if ( keyindex > 0 ) { - ui.cbxGameZeroKey->setCurrentIndex( keyindex ); - } - else { - ui.cbxGameZeroKey->setCurrentIndex( 0 ); - } + ui.cbxCenterKey->setCurrentIndex(iniFile.value("Key_index_Center", 0).toInt()); + ui.chkGameZeroShift->setChecked (iniFile.value ( "Shift_GameZero", 0 ).toBool()); ui.chkGameZeroCtrl->setChecked (iniFile.value ( "Ctrl_GameZero", 0 ).toBool()); ui.chkGameZeroAlt->setChecked (iniFile.value ( "Alt_GameZero", 0 ).toBool()); + ui.cbxGameZeroKey->setCurrentIndex(iniFile.value("Key_index_GameZero", 0).toInt()); - // Start/stop key - ui.cbxStartStopMouseKey->setCurrentIndex( iniFile.value ( "MouseKey_StartStop", 0 ).toInt() ); - keyindex = keyList.indexOf ( iniFile.value ( "Keycode_StartStop", DIK_END ).toInt() ); - if ( keyindex > 0 ) { - ui.cbxStartStopKey->setCurrentIndex( keyindex ); - } - else { - ui.cbxStartStopKey->setCurrentIndex( 0 ); - } ui.chkStartStopShift->setChecked (iniFile.value ( "Shift_StartStop", 0 ).toBool()); ui.chkStartStopCtrl->setChecked (iniFile.value ( "Ctrl_StartStop", 0 ).toBool()); ui.chkStartStopAlt->setChecked (iniFile.value ( "Alt_StartStop", 0 ).toBool()); + ui.cbxStartStopKey->setCurrentIndex(iniFile.value("Key_index_StartStop", 0).toInt()); + ui.radioSetZero->setChecked (iniFile.value ( "SetZero", 1 ).toBool()); ui.radioSetFreeze->setChecked(!ui.radioSetZero->isChecked()); - ui.radioSetEngineStop->setChecked (iniFile.value ( "SetEngineStop", 1 ).toBool()); - ui.radioSetKeepTracking->setChecked(!ui.radioSetEngineStop->isChecked()); - - // Axis-inhibitor key - ui.cbxInhibitMouseKey->setCurrentIndex( iniFile.value ( "MouseKey_Inhibit", 0 ).toInt() ); - keyindex = keyList.indexOf ( iniFile.value ( "Keycode_Inhibit", 1 ).toInt() ); - if ( keyindex > 0 ) { - ui.cbxInhibitKey->setCurrentIndex( keyindex ); - } - else { - ui.cbxInhibitKey->setCurrentIndex( 0 ); - } + ui.chkInhibitShift->setChecked (iniFile.value ( "Shift_Inhibit", 0 ).toBool()); ui.chkInhibitCtrl->setChecked (iniFile.value ( "Ctrl_Inhibit", 0 ).toBool()); ui.chkInhibitAlt->setChecked (iniFile.value ( "Alt_Inhibit", 0 ).toBool()); + ui.cbxInhibitKey->setCurrentIndex(iniFile.value("Key_index_Inhibit", 0).toInt()); ui.chkInhibitPitch->setChecked (iniFile.value ( "Inhibit_Pitch", 0 ).toBool()); ui.chkInhibitYaw->setChecked (iniFile.value ( "Inhibit_Yaw", 0 ).toBool()); @@ -2005,29 +1782,23 @@ void KeyboardShortcutDialog::save() { QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) iniFile.beginGroup ( "KB_Shortcuts" ); - iniFile.setValue ( "MouseKey_Center", ui.cbxCenterMouseKey->currentIndex()); - iniFile.setValue ( "Keycode_Center", keyList.at( ui.cbxCenterKey->currentIndex() ) ); + iniFile.setValue ( "Key_index_Center", ui.cbxCenterKey->currentIndex() ); iniFile.setValue ( "Shift_Center", ui.chkCenterShift->isChecked() ); iniFile.setValue ( "Ctrl_Center", ui.chkCenterCtrl->isChecked() ); iniFile.setValue ( "Alt_Center", ui.chkCenterAlt->isChecked() ); - iniFile.setValue ( "Disable_Beep", ui.chkDisableBeep->isChecked() ); - iniFile.setValue ( "MouseKey_GameZero", ui.cbxGameZeroMouseKey->currentIndex()); - iniFile.setValue ( "Keycode_GameZero", keyList.at( ui.cbxGameZeroKey->currentIndex() ) ); + iniFile.setValue ( "Key_index_GameZero", ui.cbxGameZeroKey->currentIndex() ); iniFile.setValue ( "Shift_GameZero", ui.chkGameZeroShift->isChecked() ); iniFile.setValue ( "Ctrl_GameZero", ui.chkGameZeroCtrl->isChecked() ); iniFile.setValue ( "Alt_GameZero", ui.chkGameZeroAlt->isChecked() ); - iniFile.setValue ( "MouseKey_StartStop", ui.cbxStartStopMouseKey->currentIndex()); - iniFile.setValue ( "Keycode_StartStop", keyList.at( ui.cbxStartStopKey->currentIndex() ) ); + iniFile.setValue ( "Key_index_StartStop", ui.cbxStartStopKey->currentIndex() ); iniFile.setValue ( "Shift_StartStop", ui.chkStartStopShift->isChecked() ); iniFile.setValue ( "Ctrl_StartStop", ui.chkStartStopCtrl->isChecked() ); iniFile.setValue ( "Alt_StartStop", ui.chkStartStopAlt->isChecked() ); iniFile.setValue ( "SetZero", ui.radioSetZero->isChecked() ); - iniFile.setValue ( "SetEngineStop", ui.radioSetEngineStop->isChecked() ); - iniFile.setValue ( "MouseKey_Inhibit", ui.cbxInhibitMouseKey->currentIndex()); - iniFile.setValue ( "Keycode_Inhibit", keyList.at( ui.cbxInhibitKey->currentIndex() ) ); + iniFile.setValue ( "Key_index_Inhibit", ui.cbxInhibitKey->currentIndex() ); iniFile.setValue ( "Shift_Inhibit", ui.chkInhibitShift->isChecked() ); iniFile.setValue ( "Ctrl_Inhibit", ui.chkInhibitCtrl->isChecked() ); iniFile.setValue ( "Alt_Inhibit", ui.chkInhibitAlt->isChecked() ); @@ -2077,25 +1848,51 @@ QWidget( parent , f) QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - ui.qFunctionX->setConfig(Tracker::X.curvePtr, currentFile); - connect(ui.qFunctionX, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - ui.qFunctionY->setConfig(Tracker::Y.curvePtr, currentFile); - connect(ui.qFunctionY, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - ui.qFunctionZ->setConfig(Tracker::Z.curvePtr, currentFile); - connect(ui.qFunctionZ, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + ui.txconfig->setConfig(GlobalPose->X.curvePtr, currentFile); + connect(ui.txconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - ui.qFunctionYaw->setConfig(Tracker::Yaw.curvePtr, currentFile); - connect(ui.qFunctionYaw, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - // - // There are 2 curves for Pitch: Up and Down. Users have indicated that, to be able to use visual Flight controls, it is necessary to have a 'slow' curve for Down... - // - ui.qFunctionPitch->setConfig(Tracker::Pitch.curvePtr, currentFile); - connect(ui.qFunctionPitch, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - ui.qFunctionPitchDown->setConfig(Tracker::Pitch.curvePtrAlt, currentFile); - connect(ui.qFunctionPitchDown, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + ui.txconfig->setConfig(GlobalPose->X.curvePtr, currentFile); + connect(ui.txconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.tyconfig->setConfig(GlobalPose->Y.curvePtr, currentFile); + connect(ui.tyconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.tzconfig->setConfig(GlobalPose->Z.curvePtr, currentFile); + connect(ui.tzconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.rxconfig->setConfig(GlobalPose->Yaw.curvePtr, currentFile); + connect(ui.rxconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.ryconfig->setConfig(GlobalPose->Pitch.curvePtr, currentFile); + connect(ui.ryconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.rzconfig->setConfig(GlobalPose->Roll.curvePtr, currentFile); + connect(ui.rzconfig, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.txconfig_alt->setConfig(GlobalPose->X.curvePtrAlt, currentFile); + connect(ui.txconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - ui.qFunctionRoll->setConfig(Tracker::Roll.curvePtr, currentFile); - connect(ui.qFunctionRoll, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + ui.tyconfig_alt->setConfig(GlobalPose->Y.curvePtrAlt, currentFile); + connect(ui.tyconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.tzconfig_alt->setConfig(GlobalPose->Z.curvePtrAlt, currentFile); + connect(ui.tzconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.rxconfig_alt->setConfig(GlobalPose->Yaw.curvePtrAlt, currentFile); + connect(ui.rxconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.ryconfig_alt->setConfig(GlobalPose->Pitch.curvePtrAlt, currentFile); + connect(ui.ryconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + ui.rzconfig_alt->setConfig(GlobalPose->Roll.curvePtrAlt, currentFile); + connect(ui.rzconfig_alt, SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + + connect(ui.rx_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + connect(ui.ry_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + connect(ui.rz_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + connect(ui.tx_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + connect(ui.ty_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + connect(ui.tz_altp, SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); // Load the settings from the current .INI-file loadSettings(); @@ -2158,10 +1955,6 @@ void CurveConfigurationDialog::doCancel() { // Load the current Settings from the currently 'active' INI-file. // void CurveConfigurationDialog::loadSettings() { -int NeutralZone; -int sensYaw, sensPitch, sensRoll; -int sensX, sensY, sensZ; - qDebug() << "loadSettings says: Starting "; QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) @@ -2171,20 +1964,29 @@ int sensX, sensY, sensZ; qDebug() << "loadSettings says: iniFile = " << currentFile; iniFile.beginGroup ( "Tracking" ); - NeutralZone = iniFile.value ( "NeutralZone", 5 ).toInt(); - sensYaw = iniFile.value ( "sensYaw", 100 ).toInt(); - sensPitch = iniFile.value ( "sensPitch", 100 ).toInt(); - sensRoll = iniFile.value ( "sensRoll", 100 ).toInt(); - sensX = iniFile.value ( "sensX", 100 ).toInt(); - sensY = iniFile.value ( "sensY", 100 ).toInt(); - sensZ = iniFile.value ( "sensZ", 100 ).toInt(); - - iniFile.endGroup (); - - ui.qFunctionYaw->loadSettings(currentFile); - ui.qFunctionPitch->loadSettings(currentFile); - ui.qFunctionPitchDown->loadSettings(currentFile); - ui.qFunctionRoll->loadSettings(currentFile); + iniFile.endGroup (); + + ui.rxconfig->loadSettings(currentFile); + ui.ryconfig->loadSettings(currentFile); + ui.rzconfig->loadSettings(currentFile); + + ui.rxconfig_alt->loadSettings(currentFile); + ui.ryconfig_alt->loadSettings(currentFile); + ui.rzconfig_alt->loadSettings(currentFile); + + GlobalPose->Yaw.altp = iniFile.value("rx_alt", false).toBool(); + GlobalPose->Pitch.altp = iniFile.value("ry_alt", false).toBool(); + GlobalPose->Roll.altp = iniFile.value("rz_alt", false).toBool(); + GlobalPose->X.altp = iniFile.value("tx_alt", false).toBool(); + GlobalPose->Y.altp = iniFile.value("ty_alt", false).toBool(); + GlobalPose->Z.altp = iniFile.value("tz_alt", false).toBool(); + + ui.rx_altp->setChecked(GlobalPose->Yaw.altp); + ui.ry_altp->setChecked(GlobalPose->Pitch.altp); + ui.rz_altp->setChecked(GlobalPose->Roll.altp); + ui.tx_altp->setChecked(GlobalPose->X.altp); + ui.ty_altp->setChecked(GlobalPose->Y.altp); + ui.tz_altp->setChecked(GlobalPose->Z.altp); settingsDirty = false; @@ -2197,19 +1999,32 @@ void CurveConfigurationDialog::save() { qDebug() << "save() says: started"; - QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + + ui.rxconfig->saveSettings(currentFile); + ui.ryconfig->saveSettings(currentFile); + ui.rzconfig->saveSettings(currentFile); + ui.txconfig->saveSettings(currentFile); + ui.tyconfig->saveSettings(currentFile); + ui.tzconfig->saveSettings(currentFile); + + ui.txconfig_alt->saveSettings(currentFile); + ui.tyconfig_alt->saveSettings(currentFile); + ui.tzconfig_alt->saveSettings(currentFile); + ui.rxconfig_alt->saveSettings(currentFile); + ui.ryconfig_alt->saveSettings(currentFile); + ui.rzconfig_alt->saveSettings(currentFile); - ui.qFunctionYaw->saveSettings(currentFile); - ui.qFunctionPitch->saveSettings(currentFile); - ui.qFunctionPitchDown->saveSettings(currentFile); - ui.qFunctionRoll->saveSettings(currentFile); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - ui.qFunctionX->saveSettings(currentFile); - ui.qFunctionY->saveSettings(currentFile); - ui.qFunctionZ->saveSettings(currentFile); + iniFile.setValue("rx_alt", ui.rx_altp->checkState() != Qt::Unchecked); + iniFile.setValue("ry_alt", ui.ry_altp->checkState() != Qt::Unchecked); + iniFile.setValue("rz_alt", ui.rz_altp->checkState() != Qt::Unchecked); + iniFile.setValue("tx_alt", ui.tx_altp->checkState() != Qt::Unchecked); + iniFile.setValue("ty_alt", ui.ty_altp->checkState() != Qt::Unchecked); + iniFile.setValue("tz_alt", ui.tz_altp->checkState() != Qt::Unchecked); settingsDirty = false; @@ -2218,3 +2033,42 @@ void CurveConfigurationDialog::save() { // mainApp->updateSettings(); } + +void FaceTrackNoIR::shortcutRecentered() +{ + if (tracker) + { +#if defined(__WIN32) || defined(_WIN32) + MessageBeep(MB_OK); +#else + QApplication::beep(); +#endif + qDebug() << "Center"; + tracker->do_center = true; + } +} + +void FaceTrackNoIR::shortcutZero() +{ + if (tracker) + { + tracker->do_game_zero = true; + } +} + +void FaceTrackNoIR::shortcutStartStop() +{ + if (tracker) + { + tracker->do_tracking = !tracker->do_tracking; + qDebug() << "do-tracking" << tracker->do_tracking; + } +} + +void FaceTrackNoIR::shortcutInhibit() +{ + if (tracker) + { + tracker->do_inhibit = true; + } +} diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h index 756b5867..7fd91719 100644 --- a/facetracknoir/facetracknoir.h +++ b/facetracknoir/facetracknoir.h @@ -25,7 +25,13 @@ #ifndef FaceTrackNoIR_H #define FaceTrackNoIR_H -#include +#undef FTNOIR_PROTOCOL_BASE_LIB +#undef FTNOIR_TRACKER_BASE_LIB +#undef FTNOIR_FILTER_BASE_LIB +#define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT +#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT +#define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT + #include #include #include @@ -34,30 +40,58 @@ #include #include #include - -#include "../FTNoIR_PoseWidget/glwidget.h" - -#include "ui_FaceTrackNoIR.h" -#include "ui_FTNoIR_KeyboardShortcuts.h" -#include "ui_FTNoIR_Preferences.h" -#include "ui_FTNoIR_Curves.h" - -#include "..\ftnoir_protocol_base\FTNoIR_Protocol_base.h" -#include "..\ftnoir_tracker_base\FTNoIR_Tracker_base.h" -#include "..\ftnoir_filter_base\FTNoIR_Filter_base.h" - -typedef ITrackerDialogPtr (WINAPI *importGetTrackerDialog)(void); -typedef ITrackerDllPtr (WINAPI *importGetTrackerDll)(void); -typedef IProtocolDialogPtr (WINAPI *importGetProtocolDialog)(void); -typedef IProtocolDllPtr (WINAPI *importGetProtocolDll)(void); -typedef IFilterDialogPtr (WINAPI *importGetFilterDialog)(void); -typedef IFilterDllPtr (WINAPI *importGetFilterDll)(void); - -#include +#include +#include +#include +#include +#if !defined(_WIN32) && !defined(__WIN32) +# include +#else +# include +#endif +#include +#include +#include + +#include "ftnoir_posewidget/glwidget.h" + +#include "ui_facetracknoir.h" +#include "ui_ftnoir_keyboardshortcuts.h" +#include "ui_ftnoir_preferences.h" +#include "ui_ftnoir_curves.h" + +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ftnoir_filter_base/ftnoir_filter_base.h" + +#include "global-settings.h" class Tracker; // pre-define class to avoid circular includes +class FaceTrackNoIR; + +class KeybindingWorker; + +#if defined(__WIN32) || defined(_WIN32) +extern QList global_windows_key_sequences; +#include +struct Key { + BYTE keycode; + bool shift; + bool ctrl; + bool alt; + bool ever_pressed; + QElapsedTimer timer; +public: + Key() : keycode(0), shift(false), ctrl(false), alt(false), ever_pressed(false) + { + } +}; +#else +typedef unsigned char BYTE; +struct Key { int foo; }; +#endif -class FaceTrackNoIR : public QMainWindow +class FaceTrackNoIR : public QMainWindow, IDynamicLibraryProvider { Q_OBJECT @@ -65,29 +99,48 @@ public: FaceTrackNoIR(QWidget *parent = 0, Qt::WFlags flags = 0); ~FaceTrackNoIR(); - void getGameProgramName(); // Get the ProgramName from the game and display it. void updateSettings(); // Update the settings (let Tracker read INI-file). - QFrame *getVideoWidget(); // Get a pointer to the video-widget, to use in the DLL - QString getCurrentProtocolName(); // Get the name of the selected protocol - QString getCurrentFilterName(); // Get the name of the selected filter - QString getCurrentTrackerName(); // Get the name of the selected face-tracker - QString getSecondTrackerName(); // Get the name of the second face-tracker ("None" if no selection) + QFrame *get_video_widget(); // Get a pointer to the video-widget, to use in the DLL + Tracker *tracker; + void bindKeyboardShortcuts(); + DynamicLibrary* current_tracker1() { + return dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); + } + DynamicLibrary* current_tracker2() { + return dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); + } + DynamicLibrary* current_protocol() { + return dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); + } + DynamicLibrary* current_filter() { + return dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); + } +#if defined(_WIN32) || defined(__WIN32) + Key keyCenter, keyZero, keyStartStop, keyInhibit; + KeybindingWorker* keybindingWorker; +#else + QxtGlobalShortcut* keyCenter; + QxtGlobalShortcut* keyZero; + QxtGlobalShortcut* keyStartStop; + QxtGlobalShortcut* keyInhibit; +#endif +public slots: + void shortcutRecentered(); + void shortcutZero(); + void shortcutStartStop(); + void shortcutInhibit(); private: Ui::FaceTrackNoIRClass ui; - Tracker *tracker; QTimer *timMinimizeFTN; // Timer to Auto-minimize QTimer *timUpdateHeadPose; // Timer to display headpose QStringList iniFileList; // List of INI-files, that are present in the Settings folder - QStringList protocolFileList; // List of Protocol-DLL-files, that are present in the program-folder - QStringList filterFileList; // List of Filter-DLL-files, that are present in the program-folder - QStringList trackerFileList; // List of Tracker-DLL-files, that are present in the program-folder - ITrackerDialogPtr pTrackerDialog; // Pointer to Tracker dialog instance (in DLL) - ITrackerDialogPtr pSecondTrackerDialog; // Pointer to the second Tracker dialog instance (in DLL) - IProtocolDialogPtr pProtocolDialog; // Pointer to Protocol dialog instance (in DLL) - IFilterDialogPtr pFilterDialog; // Pointer to Filter dialog instance (in DLL) + ITrackerDialog* pTrackerDialog; // Pointer to Tracker dialog instance (in DLL) + ITrackerDialog* pSecondTrackerDialog; // Pointer to the second Tracker dialog instance (in DLL) + IProtocolDialog* pProtocolDialog; // Pointer to Protocol dialog instance (in DLL) + IFilterDialog* pFilterDialog; // Pointer to Filter dialog instance (in DLL) /** Widget variables **/ QVBoxLayout *l; @@ -120,6 +173,12 @@ private: void loadSettings(); void setupFaceTrackNoIR(); + QList dlopen_filters; + QList dlopen_trackers; + QList dlopen_protocols; + + bool looping; + private slots: //file menu void open(); @@ -159,11 +218,9 @@ private: void showHeadPose(); - //smoothing slider - void setSmoothing( int smooth ); - - void startTracker(); + void startTracker(); void stopTracker(); + }; // Widget that has controls for FaceTrackNoIR Preferences. @@ -209,9 +266,6 @@ private: /** helper **/ bool settingsDirty; FaceTrackNoIR *mainApp; - QList stringList; // List of strings, that describe the keyboard-keys - QList keyList; // List of keys, with the values of the keyboard-keys - QList stringListMouse; // List of strings, that describe the mouse-keys private slots: void doOK(); @@ -242,8 +296,41 @@ private: private slots: void doOK(); void doCancel(); - void curveChanged( bool change ) { settingsDirty = true; }; + void curveChanged( bool change ) { settingsDirty = true; } + void curveChanged( int change ) { settingsDirty = true; } }; - #endif // FaceTrackNoIR_H + +extern QList global_key_sequences; +#if defined(__WIN32) || defined(_WIN32) +class KeybindingWorkerDummy { +private: + LPDIRECTINPUT8 din; + LPDIRECTINPUTDEVICE8 dinkeyboard; + Key kCenter, kInhibit, kStartStop, kZero; + FaceTrackNoIR& window; +public: + volatile bool should_quit; + ~KeybindingWorkerDummy(); + KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter, Key keyInhibit, Key keyStartStop, Key keyZero); + void run(); +}; +#else +class KeybindingWorkerDummy { +public: + KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter, Key keyInhibit, Key keyStartStop, Key keyZero); + void run() {} +}; +#endif + +class KeybindingWorker : public QThread, public KeybindingWorkerDummy { + Q_OBJECT +public: + KeybindingWorker(FaceTrackNoIR& w, Key keyCenter, Key keyInhibit, Key keyStartStop, Key keyZero) : KeybindingWorkerDummy(w, keyCenter, keyInhibit, keyStartStop, keyZero) + { + } + void run() { + KeybindingWorkerDummy::run(); + } +}; diff --git a/facetracknoir/facetracknoir.ico b/facetracknoir/facetracknoir.ico new file mode 100644 index 00000000..5115066c Binary files /dev/null and b/facetracknoir/facetracknoir.ico differ diff --git a/facetracknoir/facetracknoir.rc b/facetracknoir/facetracknoir.rc index ed8a68c1..fcae12b3 100644 --- a/facetracknoir/facetracknoir.rc +++ b/facetracknoir/facetracknoir.rc @@ -1,84 +1,2 @@ -// Microsoft Visual C++ generated resource script. -// #include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Dutch (Neutral) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NLD) -#ifdef _WIN32 -LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON "FaceTrackNoIR.ico" -#endif // Dutch (Neutral) resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +IDI_ICON1 ICON "facetracknoir.ico" diff --git a/facetracknoir/ftnoir_curves.ui b/facetracknoir/ftnoir_curves.ui index 19c68cf0..5bbe48be 100644 --- a/facetracknoir/ftnoir_curves.ui +++ b/facetracknoir/ftnoir_curves.ui @@ -6,8 +6,8 @@ 0 0 - 901 - 661 + 718 + 698 @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/facetracknoir.pngimages/facetracknoir.png Qt::LeftToRight @@ -38,7 +38,7 @@ color: black; /* Specials for individual widget(s) */ QWidget#UICCurveConfigurationDialog { -background-color: #484848; +background-color: #dfdfdf; } QWidget#tabWidget { @@ -99,398 +99,538 @@ color: rgb(255, 255, 255); 0 - - - - :/images/rotation_DOFs.png:/images/rotation_DOFs.png + + + rx + + + + 0 + 0 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + + 255 + 0 + 0 + + + + + 200 + 200 + 200 + + + + + + + 0 + 280 + 166 + 21 + + + + Use alternative + + + + + + 0 + 340 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + + 255 + 0 + 0 + + + + + 200 + 200 + 200 + + + + + - Rotations + ry - + + + + 0 + 0 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + 1 + + + + 0 + 255 + 0 + + + + + 200 + 200 + 200 + + + + - 10 - 10 - 794 - 548 + 0 + 280 + 199 + 21 - - - - - - 0 - 0 - - - - - 260 - 240 - - - - - 260 - 500 - - - - 180 - - - 1 - - - - 0 - 255 - 255 - - - - - 192 - 192 - 192 - - - - Input Pitch Up (degr.) - - - Output Pitch Up (degr.) - - - - - - - - 0 - 0 - - - - - 260 - 240 - - - - - 260 - 500 - - - - 1 - - - - 0 - 255 - 0 - - - - - 192 - 192 - 192 - - - - Input Roll (degr.) - - - Output Roll (degr.) - - - - - - - - 0 - 0 - - - - - 260 - 240 - - - - - 400 - 500 - - - - 1 - - - - 255 - 170 - 0 - - - - - 192 - 192 - 192 - - - - Input Yaw (degr.) - - - Output Yaw (degr.) - - - - - - - - 0 - 0 - - - - - 260 - 240 - - - - - 260 - 500 - - - - 90 - - - 2 - - - - 0 - 255 - 255 - - - - - 192 - 192 - 192 - - - - Input Pitch Down (degr.) - - - Output Pitch Down (degr.) - - - - - - - - 16777215 - 25 - - - - Left-click the graph to place a new point, right-click a point to remove. Left-click and drag to move a point. - - - true - - - - - - - - 170 - 140 - - - - image: url(:/images/rotation_DOFs.png); - - - - + + Use alternative + + + + + + 0 + 340 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + 1 + + + + 0 + 255 + 0 + + + + + 200 + 200 + 200 + + - - - - :/images/translation_DOFs.png:/images/translation_DOFs.png + + + rz + + + + 0 + 0 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + 1 + + + + 0 + 0 + 255 + + + + + 200 + 200 + 200 + + + + + + + 0 + 280 + 271 + 21 + + + + Use alternative + + + + + + 0 + 340 + 595 + 240 + + + + 60 + + + 180 + + + 9 + + + 1 + + + + 0 + 0 + 255 + + + + + 200 + 200 + 200 + + + + + - Translations + tx - + - 30 - 10 - 794 - 390 + 0 + 0 + 595 + 260 - - - - - - 260 - 240 - - - - - 260 - 240 - - - - - 255 - 255 - 0 - - - - - 192 - 192 - 192 - - - - Left/Right Input X (cm.) - - - Output X (cm.) - - - - - - - - 260 - 240 - - - - - 260 - 240 - - - - - 85 - 0 - 255 - - - - - 192 - 192 - 192 - - - - Up/Down Input Y (cm.) - - - Output Y (cm.) - - - - - - - - 260 - 240 - - - - - 260 - 240 - - - - - 255 - 0 - 0 - - - - - 192 - 192 - 192 - - - - Forward/Backward Input Z (cm.) - - - Output Z (cm.) - - - - - - - - 16777215 - 25 - - - - Left-click the graph to place a new point, right-click a point to remove. Left-click and drag to move a point. - - - true - - - - - - - - 170 - 140 - - - - image: url(:/images/translation_DOFs.png); - - - - + + 60 + + + 200 + + + 9 + + + 1 + + + + 255 + 0 + 255 + + + + + 200 + 200 + 200 + + + + + + + 0 + 280 + 228 + 21 + + + + Use alternative + + + + + + 0 + 340 + 595 + 260 + + + + 60 + + + 200 + + + 9 + + + 1 + + + + 255 + 0 + 255 + + + + + 200 + 200 + 200 + + + + + + + ty + + + + + 0 + 0 + 595 + 260 + + + + 60 + + + 200 + + + 9 + + + 1 + + + + 255 + 255 + 0 + + + + + 200 + 200 + 200 + + + + + + + 0 + 280 + 229 + 21 + + + + Use alternative + + + + + + 0 + 340 + 595 + 260 + + + + 60 + + + 200 + + + 9 + + + 1 + + + + 255 + 255 + 0 + + + + + 200 + 200 + 200 + + + + + + + tz + + + + + 0 + 0 + 595 + 260 + + + + 60 + + + 200 + + + 9 + + + 1 + + + + 0 + 255 + 255 + + + + + 200 + 200 + 200 + + + + + + + 0 + 280 + 263 + 21 + + + + Use alternative + + + + + + 0 + 340 + 595 + 260 + + + + 60 + + + 200 + + + 9 + + + 1 + + + + 0 + 255 + 255 + + + + + 200 + 200 + 200 + + @@ -499,19 +639,6 @@ color: rgb(255, 255, 255); - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -527,7 +654,7 @@ color: rgb(255, 255, 255); - 52 + 58 0 @@ -552,7 +679,7 @@ color: rgb(255, 255, 255); - 52 + 58 0 @@ -569,17 +696,14 @@ color: rgb(255, 255, 255); - - + + Qt::Horizontal - - QSizePolicy::Fixed - - 10 + 40 20 @@ -596,9 +720,7 @@ color: rgb(255, 255, 255);
qfunctionconfigurator.h
- - - + startEngineClicked() diff --git a/facetracknoir/ftnoir_fsuipccontrols.ui b/facetracknoir/ftnoir_fsuipccontrols.ui index b6120378..e4c4963d 100644 --- a/facetracknoir/ftnoir_fsuipccontrols.ui +++ b/facetracknoir/ftnoir_fsuipccontrols.ui @@ -7,7 +7,7 @@ 0 0 541 - 127 + 131 @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/facetracknoir.pngimages/facetracknoir.png Qt::LeftToRight diff --git a/facetracknoir/ftnoir_ftnservercontrols.ui b/facetracknoir/ftnoir_ftnservercontrols.ui index 44c7e99f..3cb4bdeb 100644 --- a/facetracknoir/ftnoir_ftnservercontrols.ui +++ b/facetracknoir/ftnoir_ftnservercontrols.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/facetracknoir/ftnoir_keyboardshortcuts.ui b/facetracknoir/ftnoir_keyboardshortcuts.ui index 2a5ad691..0faaf4d0 100644 --- a/facetracknoir/ftnoir_keyboardshortcuts.ui +++ b/facetracknoir/ftnoir_keyboardshortcuts.ui @@ -6,7 +6,7 @@ 0 0 - 687 + 591 438 @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight @@ -28,58 +28,8 @@ - - - - Disables: - - - - - - - When OFF: - - - - - - - - 0 - 0 - - - - Center - - - false - - - - - - - Axis Inhibitor - - - - - - - - 50 - 16777215 - - - - Shift - - - - - + + 50 @@ -87,12 +37,12 @@ - Shift + Alt - - + + 50 @@ -100,12 +50,12 @@ - Shift + Alt - - + + 50 @@ -130,8 +80,8 @@ - - + + 50 @@ -143,8 +93,8 @@ - - + + 50 @@ -152,21 +102,18 @@ - Alt + Shift - - - + + + - 50 - 16777215 + 90 + 0 - - Alt - @@ -185,27 +132,7 @@ - - - - - 90 - 0 - - - - - - - - - 90 - 0 - - - - - + @@ -278,7 +205,7 @@ - + @@ -330,7 +257,7 @@ - + color: rgb(0, 0, 0); @@ -397,48 +324,6 @@ - - - - - 100 - 0 - - - - color: rgb(0, 0, 0); - - - Engine tracker - - - - - 10 - 20 - 81 - 17 - - - - Stop Engine - - - - - - 10 - 40 - 91 - 17 - - - - Keep tracking - - - - @@ -542,75 +427,15 @@ - - - - - 0 - 0 - - - - Mouse - - - Qt::AlignCenter - - - false - - - - - - - - 90 - 0 - - - - Select Number - - - QComboBox::InsertAlphabetically - - - - - - - - 90 - 0 - - - - Select Number - - - QComboBox::InsertAlphabetically - - - - - - - - 90 - 0 - - - - Select Number - - - QComboBox::InsertAlphabetically + + + + Qt::Vertical - - + + 90 @@ -619,79 +444,66 @@ - - - - Qt::Vertical - - - - - - - Qt::Vertical + + + + Disables: - - - Qt::Vertical + + + When OFF: - - - - Qt::Vertical + + + + + 0 + 0 + - - - - - - Qt::Vertical + + Center - - - - - - Qt::Vertical + + false - - - - Qt::Vertical + + + + Axis Inhibitor - - - - Qt::Vertical + + + + + 50 + 16777215 + - - - - - - Qt::Vertical + + Shift - - + + - 85 + 50 16777215 - Disable Beep + Shift diff --git a/facetracknoir/ftnoir_preferences.ui b/facetracknoir/ftnoir_preferences.ui index bb440fc6..9e4bcd34 100644 --- a/facetracknoir/ftnoir_preferences.ui +++ b/facetracknoir/ftnoir_preferences.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/facetracknoir/global-settings.cpp b/facetracknoir/global-settings.cpp new file mode 100644 index 00000000..f0f0413e --- /dev/null +++ b/facetracknoir/global-settings.cpp @@ -0,0 +1,142 @@ +#include "global-settings.h" + +#if !(defined(__WIN32) || defined(_WIN32)) +# include +#endif + +SelectedLibraries* Libraries = NULL; + +SelectedLibraries::~SelectedLibraries() +{ + if (pTracker) { + pTracker->WaitForExit(); + } + if (pSecondTracker) { + pSecondTracker->WaitForExit(); + } + + if (pTracker) { + delete pTracker; + pTracker = NULL; + } + + if (pSecondTracker) { + delete pSecondTracker; + pSecondTracker = NULL; + } + + if (pFilter) + delete pFilter; + + if (pProtocol) + delete pProtocol; +} + +SelectedLibraries::SelectedLibraries(IDynamicLibraryProvider* mainApp) : + pTracker(NULL), pSecondTracker(NULL), pFilter(NULL), pProtocol(NULL) +{ + correct = false; + if (!mainApp) + return; + NULLARY_DYNAMIC_FUNCTION ptr; + DynamicLibrary* lib; + + lib = mainApp->current_tracker1(); + + if (lib && lib->Constructor) { + ptr = (NULLARY_DYNAMIC_FUNCTION) lib->Constructor; + pTracker = (ITracker*) ptr(); + } + + lib = mainApp->current_tracker2(); + + if (lib && lib->Constructor) { + ptr = (NULLARY_DYNAMIC_FUNCTION) lib->Constructor; + pSecondTracker = (ITracker*) ptr(); + } + + lib = mainApp->current_protocol(); + + if (lib && lib->Constructor) { + ptr = (NULLARY_DYNAMIC_FUNCTION) lib->Constructor; + pProtocol = (IProtocol*) ptr(); + } + + lib = mainApp->current_filter(); + + if (lib && lib->Constructor) { + ptr = (NULLARY_DYNAMIC_FUNCTION) lib->Constructor; + pFilter = (IFilter*) ptr(); + } + + // Check if the Protocol-server files were installed OK. + // Some servers also create a memory-mapping, for Inter Process Communication. + // The handle of the MainWindow is sent to 'The Game', so it can send a message back. + + if (pProtocol) + if(!pProtocol->checkServerInstallationOK()) + return; + + // retrieve pointers to the User Interface and the main Application + if (pTracker) { + pTracker->StartTracker( mainApp->get_video_widget() ); + } + if (pSecondTracker) { + pSecondTracker->StartTracker( mainApp->get_video_widget() ); + } + + if (pFilter) + pFilter->Initialize(); + + if (pProtocol) + pProtocol->Initialize(); + + correct = true; +} + +DynamicLibrary::DynamicLibrary(const char* filename) +{ + this->filename = filename; + QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename; +#if defined(__WIN32) || defined(_WIN32) + handle = new QLibrary(fullPath); + Dialog = (SETTINGS_FUNCTION) handle->resolve(MAYBE_STDCALL_UNDERSCORE "GetDialog" CALLING_CONVENTION_SUFFIX_VOID_FUNCTION); + Constructor = (NULLARY_DYNAMIC_FUNCTION) handle->resolve(MAYBE_STDCALL_UNDERSCORE "GetConstructor" CALLING_CONVENTION_SUFFIX_VOID_FUNCTION); + Metadata = (METADATA_FUNCTION) handle->resolve(MAYBE_STDCALL_UNDERSCORE "GetMetadata" CALLING_CONVENTION_SUFFIX_VOID_FUNCTION); +#else + handle = dlopen(fullPath.toLatin1().constData(), RTLD_NOW | +# ifdef __linux + RTLD_DEEPBIND +# else + 0 +# endif + ); + if (handle) + { + fprintf(stderr, "Error, if any: %s\n", dlerror()); + fflush(stderr); + Dialog = (SETTINGS_FUNCTION) dlsym(handle, "GetDialog"); + fprintf(stderr, "Error, if any: %s\n", dlerror()); + fflush(stderr); + Constructor = (NULLARY_DYNAMIC_FUNCTION) dlsym(handle, "GetConstructor"); + fprintf(stderr, "Error, if any: %s\n", dlerror()); + fflush(stderr); + Metadata = (METADATA_FUNCTION) dlsym(handle, "GetMetadata"); + fprintf(stderr, "Error, if any: %s\n", dlerror()); + fflush(stderr); + } else { + fprintf(stderr, "Error, if any: %s\n", dlerror()); + fflush(stderr); + } +#endif +} + +DynamicLibrary::~DynamicLibrary() +{ +#if defined(__WIN32) || defined(_WIN32) + handle->unload(); +#else + if (handle) + (void) dlclose(handle); +#endif +} diff --git a/facetracknoir/global-settings.h b/facetracknoir/global-settings.h new file mode 100644 index 00000000..62f00831 --- /dev/null +++ b/facetracknoir/global-settings.h @@ -0,0 +1,85 @@ +#pragma once + +#if defined(_WIN32) || defined(__WIN32) +# define CALLING_CONVENTION_SUFFIX_VOID_FUNCTION "@0" +# ifdef _MSC_VER +# define MAYBE_STDCALL_UNDERSCORE "_" +#else +# define MAYBE_STDCALL_UNDERSCORE "" +# endif +#else +# define CALLING_CONVENTION_SUFFIX_VOID_FUNCTION "" +# define MAYBE_STDCALL_UNDERSCORE "" +#endif + +#include +#include +#include +#include +#include +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ftnoir_filter_base/ftnoir_filter_base.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" + +#if defined(_WIN32) || defined(__WIN32) +# define CALLING_CONVENTION __stdcall +#else +# define CALLING_CONVENTION +#endif + +class IDynamicLibraryProvider; + +struct SelectedLibraries { +public: + ITracker* pTracker; + ITracker* pSecondTracker; + IFilter* pFilter; + IProtocol* pProtocol; + SelectedLibraries(IDynamicLibraryProvider* main = NULL); + ~SelectedLibraries(); + bool correct; +}; + +extern SelectedLibraries* Libraries; + +struct Metadata; + +extern "C" typedef void* (CALLING_CONVENTION * NULLARY_DYNAMIC_FUNCTION)(void); +extern "C" typedef Metadata* (CALLING_CONVENTION* METADATA_FUNCTION)(void); +extern "C" typedef void* (CALLING_CONVENTION* SETTINGS_FUNCTION)(void); + +class DynamicLibrary { +public: + DynamicLibrary(const char* filename); + virtual ~DynamicLibrary(); + SETTINGS_FUNCTION Dialog; + NULLARY_DYNAMIC_FUNCTION Constructor; + METADATA_FUNCTION Metadata; + QString filename; +private: +#if defined(_WIN32) || defined(__WIN32) + QLibrary* handle; +#else + void* handle; +#endif +}; + +struct Metadata +{ + Metadata() {} + virtual ~Metadata() {} + + virtual void getFullName(QString *strToBeFilled) = 0; + virtual void getShortName(QString *strToBeFilled) = 0; + virtual void getDescription(QString *strToBeFilled) = 0; + virtual void getIcon(QIcon *icon) = 0; +}; + +class IDynamicLibraryProvider { +public: + virtual DynamicLibrary* current_tracker1() = 0; + virtual DynamicLibrary* current_tracker2() = 0; + virtual DynamicLibrary* current_protocol() = 0; + virtual DynamicLibrary* current_filter() = 0; + virtual QFrame* get_video_widget() = 0; +}; diff --git a/facetracknoir/global-shortcuts.cpp b/facetracknoir/global-shortcuts.cpp new file mode 100644 index 00000000..286200c0 --- /dev/null +++ b/facetracknoir/global-shortcuts.cpp @@ -0,0 +1,135 @@ +#include "facetracknoir/facetracknoir.h" + +#if defined(__WIN32) || defined(_WIN32) +#include +#include +#include +QList global_windows_key_sequences = + QList() + << 0 + << DIK_A + << DIK_B + << DIK_C + << DIK_D + << DIK_E + << DIK_F + << DIK_G + << DIK_H + << DIK_I + << DIK_J + << DIK_K + << DIK_L + << DIK_M + << DIK_N + << DIK_O + << DIK_P + << DIK_Q + << DIK_R + << DIK_S + << DIK_T + << DIK_U + << DIK_V + << DIK_W + << DIK_X + << DIK_Y + << DIK_Z + << DIK_F1 + << DIK_F2 + << DIK_F3 + << DIK_F4 + << DIK_F5 + << DIK_F6 + << DIK_F7 + << DIK_F8 + << DIK_F9 + << DIK_F10 + << DIK_F11 + << DIK_F12 + << DIK_1 + << DIK_2 + << DIK_3 + << DIK_4 + << DIK_5 + << DIK_6 + << DIK_7 + << DIK_8 + << DIK_9 + << DIK_0 + << DIK_LEFT + << DIK_RIGHT + << DIK_UP + << DIK_DOWN + << DIK_PGUP + << DIK_DOWN + << DIK_HOME + << DIK_END + << DIK_BACK + << DIK_DELETE + << DIK_RETURN; +#endif + +QList global_key_sequences = + QList() + << "" + << "A" + << "B" + << "C" + << "D" + << "E" + << "F" + << "G" + << "H" + << "I" + << "J" + << "K" + << "L" + << "M" + << "N" + << "O" + << "P" + << "Q" + << "R" + << "S" + << "T" + << "U" + << "V" + << "W" + << "X" + << "Y" + << "Z" + << "F1" + << "F2" + << "F3" + << "F4" + << "F5" + << "F6" + << "F7" + << "F8" + << "F9" + << "F10" + << "F11" + << "F12" + << "1" + << "2" + << "3" + << "4" + << "5" + << "6" + << "7" + << "8" + << "9" + << "0" + << "Left" + << "Right" + << "Up" + << "Down" + << "PgUp" + << "PgDown" + << "Home" + << "End" + << "Backspace" + << "Del" + << "Enter" +; + + diff --git a/facetracknoir/images/facetracknoir.ico b/facetracknoir/images/facetracknoir.ico new file mode 100644 index 00000000..5115066c Binary files /dev/null and b/facetracknoir/images/facetracknoir.ico differ diff --git a/facetracknoir/main.cpp b/facetracknoir/main.cpp index 6e0549d7..d2eb84cc 100644 --- a/facetracknoir/main.cpp +++ b/facetracknoir/main.cpp @@ -27,28 +27,28 @@ messages from the Game. */ -#include "FaceApp.h" -#include "FaceTrackNoIR.h" +#include "facetracknoir.h" +#include "tracker.h" #include #include #include #include -int main(int argc, char *argv[]) +#if defined(_WIN32) +#include +#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") +#endif +int main(int argc, char** argv) { -//// QApplication a(argc, argv); - FaceApp a(argc, argv); + QApplication app(argc, argv); QFont font; font.setFamily(font.defaultFamily()); font.setPointSize(9); - a.setFont(font); - + app.setFont(font); + FaceTrackNoIR w; // // Create the Main Window and DeskTop and Exec! // - FaceTrackNoIR w; - a.SetupEventFilter(&w); - QDesktopWidget desktop; w.move(desktop.screenGeometry().width()/2-w.width()/2, 100); w.show(); diff --git a/facetracknoir/posix-version-script.txt b/facetracknoir/posix-version-script.txt new file mode 100644 index 00000000..97edb9aa --- /dev/null +++ b/facetracknoir/posix-version-script.txt @@ -0,0 +1,8 @@ +{ + global: + GetDialog; + GetConstructor; + GetMetadata; + local: + *; +}; \ No newline at end of file diff --git a/facetracknoir/rotation.cpp b/facetracknoir/rotation.cpp index 1c89d775..f6d16d2d 100644 --- a/facetracknoir/rotation.cpp +++ b/facetracknoir/rotation.cpp @@ -32,7 +32,7 @@ void Rotation::fromEuler(double yaw, double pitch, double roll) d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi; } -void Rotation::toEuler(double& yaw, double& pitch, double& roll) +void Rotation::toEuler(volatile double& yaw, volatile double& pitch, volatile double& roll) { roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c)); pitch = asin(2.0*(a*c - b*d)); diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h index 967d6661..9dcea285 100644 --- a/facetracknoir/rotation.h +++ b/facetracknoir/rotation.h @@ -20,7 +20,7 @@ public: // conversions void fromEuler(double yaw, double pitch, double roll); - void toEuler(double& yaw, double& pitch, double& roll); + void toEuler(volatile double& yaw, volatile double& pitch, volatile double& roll); protected: double a,b,c,d; // quaternion coefficients diff --git a/facetracknoir/spot.h b/facetracknoir/spot.h new file mode 100644 index 00000000..e23c4e2c --- /dev/null +++ b/facetracknoir/spot.h @@ -0,0 +1,27 @@ +#ifndef __SPOT_H__ +#define __SPOT_H__ + +class Spot { + +private: + QPoint distance; + QPoint position; + QImage image; + QRect target; + QRect source; + +public: + Spot(); + + void setDistance(QPoint distance); + QPoint getDistance(); + + void setPosition(QPoint position); + QPoint getPosition(); + + QRect getTarget(); + QRect getSource(); + QImage getImage(); +}; + +#endif \ No newline at end of file diff --git a/facetracknoir/tracker.cpp b/facetracknoir/tracker.cpp index 5396c95b..fbc0bd29 100644 --- a/facetracknoir/tracker.cpp +++ b/facetracknoir/tracker.cpp @@ -23,7 +23,6 @@ *********************************************************************************/ /* Modifications (last one on top): - 20130201 - WVR: Remove the Protocol, when stopping the Thread. 20121215 - WVR: Fixed crash after message: protocol not installed correctly... by terminating the thread. 20120921 - WVR: Fixed centering when no filter is selected. 20120917 - WVR: Added Mouse-buttons to ShortKeys. @@ -31,7 +30,7 @@ 20120805 - WVR: The FunctionConfig-widget is used to configure the Curves. It was tweaked some more, because the Accela filter now also uses the Curve(s). ToDo: make the ranges configurable by the user. Development on the Toradex IMU makes us realize, that a fixed input-range may not be so handy after all.. - 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled ´statically´. Now, a Dir() of the + 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled �statically�. Now, a Dir() of the EXE-folder is done, to locate Protocol-DLLs. The Icons were also moved to the DLLs 20120317 - WVR: The Filter and Tracker-code was moved to separate DLLs. The calling-method was changed accordingly. @@ -67,779 +66,249 @@ 1 or (-1). */ #include "tracker.h" -#include "FaceTrackNoIR.h" - -// Flags -bool Tracker::confid = false; -bool Tracker::do_tracking = true; -bool Tracker::do_center = false; -bool Tracker::do_inhibit = false; -bool Tracker::do_game_zero = false; -bool Tracker::do_axis_reverse = false; - -bool Tracker::setZero = true; -bool Tracker::setEngineStop = true; -HANDLE Tracker::hTrackMutex = 0; - -bool Tracker::useAxisReverse = false; // Use Axis Reverse -float Tracker::YawAngle4ReverseAxis = 40.0f; // Axis Reverse settings -float Tracker::Z_Pos4ReverseAxis = -20.0f; -float Tracker::Z_PosWhenReverseAxis = 50.0f; - - -T6DOF Tracker::current_camera(0,0,0,0,0,0); // Used for filtering -T6DOF Tracker::target_camera(0,0,0,0,0,0); -T6DOF Tracker::new_camera(0,0,0,0,0,0); -T6DOF Tracker::output_camera(0,0,0,0,0,0); // Position sent to game protocol - -THeadPoseDOF Tracker::Pitch("PitchUp", "PitchDown", 50, 180, 50, 90); // One structure for each of 6DOF's -THeadPoseDOF Tracker::Yaw("Yaw", "", 50, 180); -THeadPoseDOF Tracker::Roll("Roll", "", 50, 180); -THeadPoseDOF Tracker::X("X","", 50, 180); -THeadPoseDOF Tracker::Y("Y","", 50, 180); -THeadPoseDOF Tracker::Z("Z","", 50, 180); - -TShortKey Tracker::CenterKey; // ShortKey to Center headposition -TShortKey Tracker::StartStopKey; // ShortKey to Start/stop tracking -TShortKey Tracker::InhibitKey; // ShortKey to inhibit axis while tracking -TShortKey Tracker::GameZeroKey; // ShortKey to Set Game Zero -bool Tracker::DisableBeep = false; // Disable beep when center -//TShortKey Tracker::AxisReverseKey; // ShortKey to start/stop axis reverse while tracking - -int Tracker::CenterMouseKey; // ShortKey to Center headposition -int Tracker::StartStopMouseKey; // ShortKey to Start/stop tracking -int Tracker::InhibitMouseKey; // ShortKey to inhibit axis while tracking -int Tracker::GameZeroMouseKey; // ShortKey to Set Game Zero - -//ITrackerPtr Tracker::pTracker; // Pointer to Tracker instance (in DLL) -IProtocolPtr Tracker::pProtocol; // Pointer to Protocol instance (in DLL) -IFilterPtr Tracker::pFilter; // Pointer to Filter instance (in DLL) +#include "facetracknoir.h" +HeadPoseData* GlobalPose = NULL; /** constructor **/ -Tracker::Tracker( FaceTrackNoIR *parent ) { -QString libName; -importGetTracker getIT; -QLibrary *trackerLib; -importGetFilter getFilter; -QLibrary *filterLib; -importGetProtocol getProtocol; -QLibrary *protocolLib; -QFrame *video_frame; - - // Retieve the pointer to the parent +Tracker::Tracker( FaceTrackNoIR *parent ) : + confid(false), + useAxisReverse(false), + YawAngle4ReverseAxis(40), + Z_Pos4ReverseAxis(-20.0f), + Z_PosWhenReverseAxis(50.0), + should_quit(false), + do_tracking(true), + do_center(false), + do_inhibit(false), + do_game_zero(false), + do_axis_reverse(false), + inhibit_rx(false), + inhibit_ry(false), + inhibit_rz(false), + inhibit_tx(false), + inhibit_ty(false), + inhibit_tz(false) +{ + // Retieve the pointer to the parent mainApp = parent; - - // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); - - Tracker::hTrackMutex = CreateMutexA(NULL, false, "HeadPose_mutex"); - - // - // Initialize the headpose-data - // - Tracker::Yaw.initHeadPoseData(); - Tracker::Pitch.initHeadPoseData(); - Tracker::Roll.initHeadPoseData(); - Tracker::X.initHeadPoseData(); - Tracker::Y.initHeadPoseData(); - Tracker::Z.initHeadPoseData(); - - // - // Locate the video-frame, for the DLL - // - video_frame = 0; - video_frame = mainApp->getVideoWidget(); - qDebug() << "Tracker::Tracker VideoFrame = " << video_frame; - - // - // Load the Tracker-engine DLL, get the tracker-class from it and do stuff... - // - pTracker = NULL; - libName = mainApp->getCurrentTrackerName(); - if (!libName.isEmpty()) { - trackerLib = new QLibrary(libName); - getIT = (importGetTracker) trackerLib->resolve("GetTracker"); - qDebug() << "Tracker::Tracker libName = " << libName; - - if (getIT) { - ITracker *ptrXyz(getIT()); // Get the Class - if (ptrXyz) - { - pTracker = ptrXyz; - pTracker->Initialize( video_frame ); - qDebug() << "Tracker::setup Function Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", libName + " DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } - // - // Load the Tracker-engine DLL, get the tracker-class from it and do stuff... - // - pSecondTracker = NULL; - libName = mainApp->getSecondTrackerName(); - if ((!libName.isEmpty()) && (libName != "None")) { - trackerLib = new QLibrary(libName); - getIT = (importGetTracker) trackerLib->resolve("GetTracker"); - - if (getIT) { - ITracker *ptrXyz(getIT()); // Get the Class - if (ptrXyz) - { - pSecondTracker = ptrXyz; - pSecondTracker->Initialize( NULL ); - qDebug() << "Tracker::setup Function Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", libName + " DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - } - } - - // - // Load the DLL with the protocol-logic and retrieve a pointer to the Protocol-class. - // - libName = mainApp->getCurrentProtocolName(); - if (!libName.isEmpty()) { - protocolLib = new QLibrary(libName); - getProtocol = (importGetProtocol) protocolLib->resolve("GetProtocol"); - if (getProtocol) { - IProtocolPtr ptrXyz(getProtocol()); - if (ptrXyz) - { - pProtocol = ptrXyz; - pProtocol->Initialize(); - qDebug() << "Protocol::setup Function Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Protocol-DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - return; - } - } - - // - // Load the DLL with the filter-logic and retrieve a pointer to the Filter-class. - // - pFilter = NULL; - libName = mainApp->getCurrentFilterName(); - - if ((!libName.isEmpty()) && (libName != "None")) { - filterLib = new QLibrary(libName); - - getFilter = (importGetFilter) filterLib->resolve("GetFilter"); - if (getFilter) { - IFilterPtr ptrXyz(getFilter()); - if (ptrXyz) - { - pFilter = ptrXyz; - qDebug() << "Filter::setup Function Resolved!"; - } - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Filter-DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); - return; - } - } - // Load the settings from the INI-file loadSettings(); + GlobalPose->Yaw.headPos = 0; + GlobalPose->Pitch.headPos = 0; + GlobalPose->Roll.headPos = 0; + GlobalPose->X.headPos = 0; + GlobalPose->Y.headPos = 0; + GlobalPose->Z.headPos = 0; } -/** destructor empty **/ -Tracker::~Tracker() { - - // Stop the Tracker(s) - if (pTracker) { - pTracker->StopTracker( true ); - } - if (pSecondTracker) { - pSecondTracker->StopTracker( true ); - } - - // Trigger thread to stop - ::SetEvent(m_StopThread); - - // Wait until thread finished - if (isRunning()) { - ::WaitForSingleObject(m_WaitThread, INFINITE); - } - - // - // Remove the Tracker - // 20120615, WVR: As suggested by Stanislaw - if (pTracker) { - delete pTracker; - pTracker = NULL; - } - if (pSecondTracker) { - delete pSecondTracker; - pSecondTracker = NULL; - } - - // - // Remove the Protocol - // - if (pProtocol) { - delete pProtocol; - pProtocol = NULL; - } - - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); - - if (Tracker::hTrackMutex != 0) { - ::CloseHandle( Tracker::hTrackMutex ); - } - -# ifdef USE_DEBUG_CLIENT - debug_Client->deleteLater(); // Delete Excel protocol-server -# endif - - qDebug() << "Tracker::~Tracker Finished..."; - +Tracker::~Tracker() +{ } -/** setting up the tracker engine **/ -void Tracker::setup() { - bool DLL_Ok; - - // retrieve pointers to the User Interface and the main Application - if (pTracker) { - pTracker->StartTracker( mainApp->winId() ); - } - if (pSecondTracker) { - pSecondTracker->StartTracker( mainApp->winId() ); - } - - // - // Check if the Protocol-server files were installed OK. - // Some servers also create a memory-mapping, for Inter Process Communication. - // The handle of the MainWindow is sent to 'The Game', so it can send a message back. - // - if (pProtocol) { - - DLL_Ok = pProtocol->checkServerInstallationOK( mainApp->winId() ); - if (!DLL_Ok) { - // Trigger thread to stop - ::SetEvent(m_StopThread); - QMessageBox::information(mainApp, "FaceTrackNoIR error", "Protocol is not (correctly) installed!"); - } - } - -# ifdef USE_DEBUG_CLIENT - DLL_Ok = debug_Client->checkServerInstallationOK( mainApp->winId() ); // Check installation - if (!DLL_Ok) { - QMessageBox::information(mainApp, "FaceTrackNoIR error", "Excel Protocol is not (correctly) installed!"); - } -# endif - +static void get_curve(bool inhibitp, bool inhibit_zerop, double pos, double& out, THeadPoseDOF& axis) { + if (inhibitp) { + if (inhibit_zerop) + out = 0; + axis.curvePtr->setTrackingActive( true ); + axis.curvePtrAlt->setTrackingActive( false ); + } + else { + bool altp = (pos < 0) && axis.altp; + if (altp) { + out = axis.invert * axis.curvePtrAlt->getValue(pos); + axis.curvePtr->setTrackingActive( false ); + axis.curvePtrAlt->setTrackingActive( true ); + } + else { + out = axis.invert * axis.curvePtr->getValue(pos); + axis.curvePtr->setTrackingActive( true ); + axis.curvePtrAlt->setTrackingActive( false ); + } + } } /** QThread run method @override **/ void Tracker::run() { -/** Direct Input variables **/ -// -// The DirectX stuff was found here: http://www.directxtutorial.com/tutorial9/e-directinput/dx9e2.aspx -// -LPDIRECTINPUT8 din; // the pointer to our DirectInput interface -LPDIRECTINPUTDEVICE8 dinkeyboard; // the pointer to the keyboard device -LPDIRECTINPUTDEVICE8 dinmouse; // the pointer to the mouse device -BYTE keystate[256]; // the storage for the key-information -DIMOUSESTATE mousestate; // the storage for the mouse-information -HRESULT retAcquire; -bool lastCenterKey = false; // Remember state, to detect rising edge -bool lastStartStopKey = false; -bool lastInhibitKey = false; -bool lastGameZeroKey = false; - -bool lastCenterMouseKey = false; // Remember state, to detect rising edge -bool lastStartStopMouseKey = false; -bool lastInhibitMouseKey = false; -bool lastGameZeroMouseKey = false; - -bool waitAxisReverse = false; -bool waitThroughZero = false; -double actualYaw = 0.0f; -double actualZ = 0.0f; -T6DOF offset_camera(0,0,0,0,0,0); -T6DOF gamezero_camera(0,0,0,0,0,0); -T6DOF gameoutput_camera(0,0,0,0,0,0); - -bool bInitialCenter1 = true; -bool bInitialCenter2 = true; -bool bTracker1Confid = false; -bool bTracker2Confid = false; - - Tracker::do_tracking = true; // Start initially - Tracker::do_center = false; // Center initially - - // - // Test some Filter-stuff - // - if (pFilter) { - QString filterName; - //pFilter->getFullName(&filterName); - //qDebug() << "Tracker::run() FilterName = " << filterName; - } - - // - // Setup the DirectInput for keyboard strokes - // - // create the DirectInput interface - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, - (void**)&din, NULL) != DI_OK) { // COM stuff, so we'll set it to NULL - qDebug() << "Tracker::setup DirectInput8 Creation failed!" << GetLastError(); - } - - // create the keyboard device - if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { - qDebug() << "Tracker::setup CreateDevice function failed!" << GetLastError(); - } - // create the mouse device - din->CreateDevice(GUID_SysMouse, &dinmouse, NULL); - - // set the data format to keyboard format - if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { - qDebug() << "Tracker::setup SetDataFormat function failed!" << GetLastError(); - } - // set the data format to mouse format - dinmouse->SetDataFormat(&c_dfDIMouse); - - // set the control you will have over the keyboard - if (dinkeyboard->SetCooperativeLevel(mainApp->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { - qDebug() << "Tracker::setup SetCooperativeLevel function failed!" << GetLastError(); - } - // set the control you will have over the mouse - dinmouse->SetCooperativeLevel(mainApp->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - - forever - { - - // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) - { - dinkeyboard->Unacquire(); // Unacquire keyboard - dinkeyboard->Release(); - dinmouse->Unacquire(); // Unacquire mouse - dinmouse->Release(); - din->Release(); // Release DirectInput - - // Set event - ::SetEvent(m_WaitThread); - qDebug() << "Tracker::run terminated run()"; - X.curvePtr->setTrackingActive( false ); - Y.curvePtr->setTrackingActive( false ); - Z.curvePtr->setTrackingActive( false ); - Yaw.curvePtr->setTrackingActive( false ); - Pitch.curvePtr->setTrackingActive( false ); - Pitch.curvePtrAlt->setTrackingActive( false ); - Roll.curvePtr->setTrackingActive( false ); - - return; - } + T6DOF current_camera; // Used for filtering + T6DOF target_camera; + T6DOF new_camera; - // - // Check the mouse - // - // get access if we don't have it already - retAcquire = dinmouse->Acquire(); - if ( (retAcquire != DI_OK) && (retAcquire != S_FALSE) ) { - qDebug() << "Tracker::run Acquire function failed!" << GetLastError(); - } - else { - if (dinmouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - } - else { - // - // Check the state of the StartStop MouseKey - // - if ( isMouseKeyPressed( &StartStopMouseKey, &mousestate ) && (!lastStartStopMouseKey) ) { - Tracker::do_tracking = !Tracker::do_tracking; - - // - // To start tracking again and to be at '0', execute Center command too - // - if (Tracker::do_tracking) { - Tracker::confid = false; - if (pTracker) { - pTracker->StartTracker( mainApp->winId() ); - } - if (pSecondTracker) { - pSecondTracker->StartTracker( mainApp->winId() ); - } - } - else { - if (setEngineStop) { // Only stop engine when option is checked - if (pTracker) { - pTracker->StopTracker( false ); - } - if (pSecondTracker) { - pSecondTracker->StopTracker( false ); - } - } - } - qDebug() << "Tracker::run() says StartStop pressed, do_tracking =" << Tracker::do_tracking; - } - lastStartStopMouseKey = isMouseKeyPressed( &StartStopMouseKey, &mousestate ); // Remember - - // - // Check the state of the Center MouseKey - // - if ( isMouseKeyPressed( &CenterMouseKey, &mousestate ) && (!lastCenterMouseKey) ) { - Tracker::do_center = true; - qDebug() << "Tracker::run() says Center MouseKey pressed"; - } - lastCenterMouseKey = isMouseKeyPressed( &CenterMouseKey, &mousestate ); // Remember - - // - // Check the state of the GameZero MouseKey - // - if ( isMouseKeyPressed( &GameZeroMouseKey, &mousestate ) && (!lastGameZeroMouseKey) ) { - Tracker::do_game_zero = true; - qDebug() << "Tracker::run() says GameZero MouseKey pressed"; - } - lastGameZeroMouseKey = isMouseKeyPressed( &GameZeroMouseKey, &mousestate ); // Remember - - // - // Check the state of the Inhibit MouseKey - // - if ( isMouseKeyPressed( &InhibitMouseKey, &mousestate ) && (!lastInhibitMouseKey) ) { - Tracker::do_inhibit = !Tracker::do_inhibit; - qDebug() << "Tracker::run() says Inhibit MouseKey pressed"; - // - // Execute Center command too, when inhibition ends. - // - if (!Tracker::do_inhibit) { - Tracker::do_center = true; - } - } - lastInhibitMouseKey = isMouseKeyPressed( &InhibitMouseKey, &mousestate ); // Remember - } - } - - // - // Check the keyboard - // - // get access if we don't have it already - retAcquire = dinkeyboard->Acquire(); - if ( (retAcquire != DI_OK) && (retAcquire != S_FALSE) ) { - qDebug() << "Tracker::run Acquire function failed!" << GetLastError(); - } - else { - // get the input data - if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - } - else { - // - // Check the state of the Start/Stop key - // - if ( isShortKeyPressed( &StartStopKey, &keystate[0] ) && (!lastStartStopKey) ) { - Tracker::do_tracking = !Tracker::do_tracking; - - // - // To start tracking again and to be at '0', execute Center command too - // - if (Tracker::do_tracking) { - Tracker::confid = false; - if (pTracker) { - pTracker->StartTracker( mainApp->winId() ); - } - if (pSecondTracker) { - pSecondTracker->StartTracker( mainApp->winId() ); - } - } - else { - if (setEngineStop) { // Only stop engine when option is checked - if (pTracker) { - pTracker->StopTracker( false ); - } - if (pSecondTracker) { - pSecondTracker->StopTracker( false ); - } - } - } - qDebug() << "Tracker::run() says StartStop pressed, do_tracking =" << Tracker::do_tracking; - } - lastStartStopKey = isShortKeyPressed( &StartStopKey, &keystate[0] ); // Remember - - // - // Check the state of the Center key - // - if ( isShortKeyPressed( &CenterKey, &keystate[0] ) && (!lastCenterKey) ) { - Tracker::do_center = true; - qDebug() << "Tracker::run() says Center pressed"; - } - lastCenterKey = isShortKeyPressed( &CenterKey, &keystate[0] ); // Remember - - // - // Check the state of the GameZero key - // - if ( isShortKeyPressed( &GameZeroKey, &keystate[0] ) && (!lastGameZeroKey) ) { - Tracker::do_game_zero = true; - qDebug() << "Tracker::run() says GameZero pressed"; - } - lastGameZeroKey = isShortKeyPressed( &GameZeroKey, &keystate[0] ); // Remember - - // - // Check the state of the Inhibit key - // - if ( isShortKeyPressed( &InhibitKey, &keystate[0] ) && (!lastInhibitKey) ) { - Tracker::do_inhibit = !Tracker::do_inhibit; - qDebug() << "Tracker::run() says Inhibit pressed"; - // - // Execute Center command too, when inhibition ends. - // - if (!Tracker::do_inhibit) { - Tracker::do_center = true; - } - } - lastInhibitKey = isShortKeyPressed( &InhibitKey, &keystate[0] ); // Remember - } - } - - // - // Reset the 'wait' flag. Moving above 90 with the key pressed, will (de-)activate Axis Reverse. - // -// qDebug() << "Tracker::run() says actualZ = " << actualZ << ", terwijl Z_Pos4 = " << Z_Pos4ReverseAxis; - if (useAxisReverse) { - Tracker::do_axis_reverse = ((fabs(actualYaw) > YawAngle4ReverseAxis) && (actualZ < Z_Pos4ReverseAxis)); - } - else { - Tracker::do_axis_reverse = false; - } - - - if (WaitForSingleObject(Tracker::hTrackMutex, 100) == WAIT_OBJECT_0) { - - THeadPoseData newpose; - newpose.pitch = 0.0f; - newpose.roll = 0.0f; - newpose.yaw = 0.0f; - newpose.x = 0.0f; - newpose.y = 0.0f; - newpose.z = 0.0f; - - // - // The second tracker serves as 'secondary'. So if an axis is written by the second tracker it CAN be overwritten by the Primary tracker. - // This is enforced by the sequence below. - // - if (pSecondTracker) { - bTracker2Confid = pSecondTracker->GiveHeadPoseData(&newpose); - } - else { - bTracker2Confid = false; - bInitialCenter2 = false; - } - if (pTracker) { - bTracker1Confid = pTracker->GiveHeadPoseData(&newpose); -// qDebug() << "Tracker::run() says Roll = " << newpose.roll; - } - else { - bTracker1Confid = false; - bInitialCenter1 = false; - } - - Tracker::confid = (bTracker1Confid || bTracker2Confid); - if ( Tracker::confid ) { - addHeadPose(newpose); - } - - // - // If Center is pressed, copy the current values to the offsets. - // - if ((Tracker::do_center) || ((bInitialCenter1 && bTracker1Confid ) || (bInitialCenter2 && bTracker2Confid))) { - - if (!DisableBeep) { - MessageBeep (MB_ICONASTERISK); // Acknowledge the key-press with a beep. - } - if (pTracker && bTracker1Confid) { - pTracker->notifyCenter(); // Send 'center' to the tracker - bInitialCenter1 = false; - } - if (pSecondTracker && bTracker2Confid) { - pSecondTracker->notifyCenter(); // Send 'center' to the second tracker - bInitialCenter2 = false; - } - - // - // Only copy valid values - // - if (Tracker::confid) { - - offset_camera.x = getSmoothFromList( &X.rawList ); - offset_camera.y = getSmoothFromList( &Y.rawList ); - offset_camera.z = getSmoothFromList( &Z.rawList ); - offset_camera.pitch = getSmoothFromList( &Pitch.rawList ); - offset_camera.yaw = getSmoothFromList( &Yaw.rawList ); - offset_camera.roll = getSmoothFromList( &Roll.rawList ); - } - - Tracker::do_center = false; - } - - // - // If Set Game Zero is pressed, copy the current values to the offsets. - // Change requested by Stanislaw - // - if (Tracker::confid && Tracker::do_game_zero) { - if (pTracker) { - if (!pTracker->notifyZeroed()) - gamezero_camera = gameoutput_camera; - } -// gamezero_camera = gameoutput_camera; - - Tracker::do_game_zero = false; - } - - if (Tracker::do_tracking && Tracker::confid) { - - // get values - target_camera.x = getSmoothFromList( &X.rawList ); - target_camera.y = getSmoothFromList( &Y.rawList ); - target_camera.z = getSmoothFromList( &Z.rawList ); - target_camera.pitch = getSmoothFromList( &Pitch.rawList ); - target_camera.yaw = getSmoothFromList( &Yaw.rawList ); - target_camera.roll = getSmoothFromList( &Roll.rawList ); -// qDebug() << "Tracker::run() says Roll from Smoothing = " << target_camera.roll; - - // do the centering - target_camera = target_camera - offset_camera; - - // - // Use advanced filtering, when a filter was selected. - // - if (pFilter) { - pFilter->FilterHeadPoseData(¤t_camera, &target_camera, &new_camera, Tracker::Pitch.newSample); -// qDebug() << "Tracker::run() says Roll in Filter = " << current_camera.roll << ", Roll to output = " << new_camera.roll; - } - else { - new_camera = target_camera; -// qDebug() << "Tracker::run() says Roll to output = " << new_camera.roll; - } - output_camera.x = X.invert * X.curvePtr->getValue(new_camera.x); - output_camera.y = Y.invert * Y.curvePtr->getValue(new_camera.y); - output_camera.z = Z.invert * Z.curvePtr->getValue(new_camera.z); - - // - // Determine, which curve (Up or Down) must be used for Pitch - // - bool altp = (new_camera.pitch < 0); - if (altp) { - output_camera.pitch = Pitch.invert * Pitch.curvePtrAlt->getValue(new_camera.pitch); - Pitch.curvePtr->setTrackingActive( false ); - Pitch.curvePtrAlt->setTrackingActive( true ); - } - else { - output_camera.pitch = Pitch.invert * Pitch.curvePtr->getValue(new_camera.pitch); - Pitch.curvePtr->setTrackingActive( true ); - Pitch.curvePtrAlt->setTrackingActive( false ); - } - output_camera.yaw = Yaw.invert * Yaw.curvePtr->getValue(new_camera.yaw); - output_camera.roll = Roll.invert * Roll.curvePtr->getValue(new_camera.roll); - - X.curvePtr->setTrackingActive( true ); - Y.curvePtr->setTrackingActive( true ); - Z.curvePtr->setTrackingActive( true ); - Yaw.curvePtr->setTrackingActive( true ); - Roll.curvePtr->setTrackingActive( true ); - - // - // Reverse Axis. - // - actualYaw = output_camera.yaw; // Save the actual Yaw, otherwise we can't check for +90 - actualZ = output_camera.z; // Also the Z - if (Tracker::do_axis_reverse) { - output_camera.z = Z_PosWhenReverseAxis; // Set the desired Z-position - } - - // - // Reset value for the selected axis, if inhibition is active - // - if (Tracker::do_inhibit) { - if (InhibitKey.doPitch) output_camera.pitch = 0.0f; - if (InhibitKey.doYaw) output_camera.yaw = 0.0f; - if (InhibitKey.doRoll) output_camera.roll = 0.0f; - if (InhibitKey.doX) output_camera.x = 0.0f; - if (InhibitKey.doY) output_camera.y = 0.0f; - if (InhibitKey.doZ) output_camera.z = 0.0f; - } - - // - // Send the headpose to the game - // - if (pProtocol) { - gameoutput_camera = output_camera + gamezero_camera; - pProtocol->sendHeadposeToGame( &gameoutput_camera, &newpose ); // degrees & centimeters - } - } - else { - // - // Go to initial position - // - if (pProtocol && setZero) { - output_camera.pitch = 0.0f; - output_camera.yaw = 0.0f; - output_camera.roll = 0.0f; - output_camera.x = 0.0f; - output_camera.y = 0.0f; - output_camera.z = 0.0f; - gameoutput_camera = output_camera + gamezero_camera; - pProtocol->sendHeadposeToGame( &gameoutput_camera, &newpose ); // degrees & centimeters - } - X.curvePtr->setTrackingActive( false ); - Y.curvePtr->setTrackingActive( false ); - Z.curvePtr->setTrackingActive( false ); - Yaw.curvePtr->setTrackingActive( false ); - Pitch.curvePtr->setTrackingActive( false ); - Pitch.curvePtrAlt->setTrackingActive( false ); - Roll.curvePtr->setTrackingActive( false ); - } - } - - Tracker::Pitch.newSample = false; - ReleaseMutex(Tracker::hTrackMutex); - - //for lower cpu load - usleep(10000); - yieldCurrentThread(); - } -} - -/** Add the headpose-data to the Lists **/ -void Tracker::addHeadPose( THeadPoseData head_pose ) -{ - // Pitch - Tracker::Pitch.headPos = head_pose.pitch; // degrees - addRaw2List ( &Pitch.rawList, Pitch.maxItems, Tracker::Pitch.headPos ); -// Tracker::Pitch.confidence = head_pose.confidence; // Just this one ... - Tracker::Pitch.newSample = true; - - // Yaw - Tracker::Yaw.headPos = head_pose.yaw; // degrees - addRaw2List ( &Yaw.rawList, Yaw.maxItems, Tracker::Yaw.headPos ); - - // Roll - Tracker::Roll.headPos = head_pose.roll; // degrees - addRaw2List ( &Roll.rawList, Roll.maxItems, Tracker::Roll.headPos ); - - // X-position - Tracker::X.headPos = head_pose.x; // centimeters - addRaw2List ( &X.rawList, X.maxItems, Tracker::X.headPos ); - - // Y-position - Tracker::Y.headPos = head_pose.y; // centimeters - addRaw2List ( &Y.rawList, Y.maxItems, Tracker::Y.headPos ); - - // Z-position (distance to camera, absolute!) - Tracker::Z.headPos = head_pose.z; // centimeters - addRaw2List ( &Z.rawList, Z.maxItems, Tracker::Z.headPos ); + /** Direct Input variables **/ + T6DOF offset_camera; + T6DOF gamezero_camera; + T6DOF gameoutput_camera; + + bool bTracker1Confid = false; + bool bTracker2Confid = false; + + THeadPoseData last; + + forever + { + if (should_quit) + break; + + // Check event for stop thread + + THeadPoseData newpose; + newpose.pitch = 0.0f; + newpose.roll = 0.0f; + newpose.yaw = 0.0f; + newpose.x = 0.0f; + newpose.y = 0.0f; + newpose.z = 0.0f; + + // + // The second tracker serves as 'secondary'. So if an axis is written by the second tracker it CAN be overwritten by the Primary tracker. + // This is enforced by the sequence below. + // + if (Libraries->pSecondTracker) { + bTracker2Confid = Libraries->pSecondTracker->GiveHeadPoseData(&newpose); + } + + if (Libraries->pTracker) { + bTracker1Confid = Libraries->pTracker->GiveHeadPoseData(&newpose); + } + + confid = (bTracker1Confid || bTracker2Confid); + + bool newp = last.yaw != newpose.yaw || + last.pitch != newpose.pitch || + last.roll != newpose.roll || + last.x != newpose.x || + last.y != newpose.y || + last.z != newpose.z; + + if (newp) + last = newpose; + + if ( confid ) { + GlobalPose->Yaw.headPos = newpose.yaw; + GlobalPose->Pitch.headPos = newpose.pitch; + GlobalPose->Roll.headPos = newpose.roll; + GlobalPose->X.headPos = newpose.x; + GlobalPose->Y.headPos = newpose.y; + GlobalPose->Z.headPos = newpose.z; + } + + // + // If Center is pressed, copy the current values to the offsets. + // + if (do_center) { + // + // Only copy valid values + // + if (Tracker::confid) { + offset_camera.x = GlobalPose->X.headPos; + offset_camera.y = GlobalPose->Y.headPos; + offset_camera.z = GlobalPose->Z.headPos; + offset_camera.pitch = GlobalPose->Pitch.headPos; + offset_camera.yaw = GlobalPose->Yaw.headPos; + offset_camera.roll = GlobalPose->Roll.headPos; + } + + Tracker::do_center = false; + + // for kalman + if (Libraries->pFilter) + Libraries->pFilter->Initialize(); + + last = newpose; + } + + if (do_game_zero) { + gamezero_camera = gameoutput_camera; + do_game_zero = false; + } + + if (Tracker::do_tracking && Tracker::confid) { + // get values + target_camera.x = GlobalPose->X.headPos; + target_camera.y = GlobalPose->Y.headPos; + target_camera.z = GlobalPose->Z.headPos; + target_camera.pitch = GlobalPose->Pitch.headPos; + target_camera.yaw = GlobalPose->Yaw.headPos; + target_camera.roll = GlobalPose->Roll.headPos; + + // do the centering + target_camera = target_camera - offset_camera; + + // + // Use advanced filtering, when a filter was selected. + // + if (Libraries->pFilter) { + THeadPoseData last_post_filter = gameoutput_camera; + Libraries->pFilter->FilterHeadPoseData(¤t_camera, &target_camera, &new_camera, &last_post_filter, newp); + } + else { + new_camera = target_camera; + } + + get_curve(do_inhibit && inhibit_rx, inhibit_zero, new_camera.yaw, output_camera.yaw, GlobalPose->Yaw); + get_curve(do_inhibit && inhibit_ry, inhibit_zero, new_camera.pitch, output_camera.pitch, GlobalPose->Pitch); + get_curve(do_inhibit && inhibit_rz, inhibit_zero, new_camera.roll, output_camera.roll, GlobalPose->Roll); + get_curve(do_inhibit && inhibit_tx, inhibit_zero, new_camera.x, output_camera.x, GlobalPose->X); + get_curve(do_inhibit && inhibit_ty, inhibit_zero, new_camera.y, output_camera.y, GlobalPose->Y); + get_curve(do_inhibit && inhibit_tz, inhibit_zero, new_camera.z, output_camera.z, GlobalPose->Z); + + if (useAxisReverse) { + do_axis_reverse = ((fabs(output_camera.yaw) > YawAngle4ReverseAxis) && (output_camera.z < Z_Pos4ReverseAxis)); + } else { + do_axis_reverse = false; + } + + // + // Reverse Axis. + // + if (Tracker::do_axis_reverse) { + output_camera.z = Z_PosWhenReverseAxis; // Set the desired Z-position + } + + // + // Send the headpose to the game + // + if (Libraries->pProtocol) { + gameoutput_camera = output_camera + gamezero_camera; + Libraries->pProtocol->sendHeadposeToGame( &gameoutput_camera, &newpose ); // degrees & centimeters + } + } + else { + // + // Go to initial position + // + if (Libraries->pProtocol && inhibit_zero) { + output_camera.pitch = 0.0f; + output_camera.yaw = 0.0f; + output_camera.roll = 0.0f; + output_camera.x = 0.0f; + output_camera.y = 0.0f; + output_camera.z = 0.0f; + gameoutput_camera = output_camera + gamezero_camera; + Libraries->pProtocol->sendHeadposeToGame( &gameoutput_camera, &newpose ); // degrees & centimeters + } + GlobalPose->X.curvePtr->setTrackingActive( false ); + GlobalPose->Y.curvePtr->setTrackingActive( false ); + GlobalPose->Z.curvePtr->setTrackingActive( false ); + GlobalPose->Yaw.curvePtr->setTrackingActive( false ); + GlobalPose->Pitch.curvePtr->setTrackingActive( false ); + GlobalPose->Pitch.curvePtrAlt->setTrackingActive( false ); + GlobalPose->Roll.curvePtr->setTrackingActive( false ); + if (Libraries->pFilter) + Libraries->pFilter->Initialize(); + } + + //for lower cpu load + usleep(10000); + } + + GlobalPose->X.curvePtr->setTrackingActive( false ); + GlobalPose->Y.curvePtr->setTrackingActive( false ); + GlobalPose->Z.curvePtr->setTrackingActive( false ); + GlobalPose->Yaw.curvePtr->setTrackingActive( false ); + GlobalPose->Pitch.curvePtr->setTrackingActive( false ); + GlobalPose->Pitch.curvePtrAlt->setTrackingActive( false ); + GlobalPose->Roll.curvePtr->setTrackingActive( false ); } // @@ -850,8 +319,8 @@ QString str; char dest[100]; str = QString("No protocol active?"); - if (pProtocol) { - pProtocol->getNameFromGame( dest ); + if (Libraries->pProtocol) { + Libraries->pProtocol->getNameFromGame( dest ); str = QString( dest ); } return str; @@ -876,36 +345,17 @@ bool Tracker::handleGameCommand ( int command ) { return false; } -// -// Add the new Raw value to the QList. -// Remove the last item(s), depending on the set maximum list-items. -// -void Tracker::addRaw2List ( QList *rawList, float maxIndex, float raw ) { - // - // Remove old values from the end of the QList. - // If the setting for MaxItems was lowered, the QList is shortened here... - // - while (rawList->size() >= maxIndex) { - rawList->removeLast(); - } - - // - // Insert the newest at the beginning. - // - rawList->prepend ( raw ); -} - // // Get the raw headpose, so it can be displayed. // void Tracker::getHeadPose( THeadPoseData *data ) { - data->x = Tracker::X.headPos; // centimeters - data->y = Tracker::Y.headPos; - data->z = Tracker::Z.headPos; + data->x = GlobalPose->X.headPos; // centimeters + data->y = GlobalPose->Y.headPos; + data->z = GlobalPose->Z.headPos; - data->pitch = Tracker::Pitch.headPos; // degrees - data->yaw = Tracker::Yaw.headPos; - data->roll = Tracker::Roll.headPos; + data->pitch = GlobalPose->Pitch.headPos; // degrees + data->yaw = GlobalPose->Yaw.headPos; + data->roll = GlobalPose->Roll.headPos; } // @@ -921,31 +371,10 @@ void Tracker::getOutputHeadPose( THeadPoseData *data ) { data->roll = output_camera.roll; } -// -// Get the Smoothed value from the QList. -// -float Tracker::getSmoothFromList ( QList *rawList ) { -float sum = 0; - - if (rawList->isEmpty()) return 0.0f; - - // - // Add the Raw values and divide. - // - for ( int i = 0; i < rawList->size(); i++) { - sum += rawList->at(i); - } - return sum / rawList->size(); -} - // // Load the current Settings from the currently 'active' INI-file. // void Tracker::loadSettings() { -//int NeutralZone; -//int sensYaw, sensPitch, sensRoll; -//int sensX, sensY, sensZ; - qDebug() << "Tracker::loadSettings says: Starting "; QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) @@ -954,128 +383,27 @@ void Tracker::loadSettings() { qDebug() << "loadSettings says: iniFile = " << currentFile; - // - // Read the Tracking settings, to fill the curves. - // - //iniFile.beginGroup ( "Tracking" ); - //NeutralZone = iniFile.value ( "NeutralZone", 5 ).toInt(); - //sensYaw = iniFile.value ( "sensYaw", 100 ).toInt(); - //sensPitch = iniFile.value ( "sensPitch", 100 ).toInt(); - //sensRoll = iniFile.value ( "sensRoll", 100 ).toInt(); - //sensX = iniFile.value ( "sensX", 100 ).toInt(); - //sensY = iniFile.value ( "sensY", 100 ).toInt(); - //sensZ = iniFile.value ( "sensZ", 100 ).toInt(); - //iniFile.endGroup (); - - // - // Read the keyboard shortcuts. - // + iniFile.beginGroup ( "Tracking" ); + iniFile.endGroup (); iniFile.beginGroup ( "KB_Shortcuts" ); - - // Center key - CenterMouseKey = iniFile.value ( "MouseKey_Center", 0 ).toInt(); - CenterKey.keycode = iniFile.value ( "Keycode_Center", DIK_HOME ).toInt(); - CenterKey.shift = iniFile.value ( "Shift_Center", 0 ).toBool(); - CenterKey.ctrl = iniFile.value ( "Ctrl_Center", 0 ).toBool(); - CenterKey.alt = iniFile.value ( "Alt_Center", 0 ).toBool(); - DisableBeep = iniFile.value ( "Disable_Beep", 0 ).toBool(); - - // StartStop key - StartStopMouseKey = iniFile.value ( "MouseKey_StartStop", 0 ).toInt(); - StartStopKey.keycode = iniFile.value ( "Keycode_StartStop", DIK_END ).toInt(); - StartStopKey.shift = iniFile.value ( "Shift_StartStop", 0 ).toBool(); - StartStopKey.ctrl = iniFile.value ( "Ctrl_StartStop", 0 ).toBool(); - StartStopKey.alt = iniFile.value ( "Alt_StartStop", 0 ).toBool(); - setZero = iniFile.value ( "SetZero", 1 ).toBool(); - setEngineStop = iniFile.value ( "SetEngineStop", 1 ).toBool(); - - // Inhibit key - InhibitMouseKey = iniFile.value ( "MouseKey_Inhibit", 0 ).toInt(); - InhibitKey.keycode = iniFile.value ( "Keycode_Inhibit", 0 ).toInt(); - InhibitKey.shift = iniFile.value ( "Shift_Inhibit", 0 ).toBool(); - InhibitKey.ctrl = iniFile.value ( "Ctrl_Inhibit", 0 ).toBool(); - InhibitKey.alt = iniFile.value ( "Alt_Inhibit", 0 ).toBool(); - InhibitKey.doPitch = iniFile.value ( "Inhibit_Pitch", 0 ).toBool(); - InhibitKey.doYaw = iniFile.value ( "Inhibit_Yaw", 0 ).toBool(); - InhibitKey.doRoll = iniFile.value ( "Inhibit_Roll", 0 ).toBool(); - InhibitKey.doX = iniFile.value ( "Inhibit_X", 0 ).toBool(); - InhibitKey.doY = iniFile.value ( "Inhibit_Y", 0 ).toBool(); - InhibitKey.doZ = iniFile.value ( "Inhibit_Z", 0 ).toBool(); - - // Game Zero key - GameZeroMouseKey = iniFile.value ( "MouseKey_GameZero", 0 ).toInt(); - GameZeroKey.keycode = iniFile.value ( "Keycode_GameZero", 0 ).toInt(); - GameZeroKey.shift = iniFile.value ( "Shift_GameZero", 0 ).toBool(); - GameZeroKey.ctrl = iniFile.value ( "Ctrl_GameZero", 0 ).toBool(); - GameZeroKey.alt = iniFile.value ( "Alt_GameZero", 0 ).toBool(); - - // Axis Reverse key - //AxisReverseKey.keycode = DIK_R; - //AxisReverseKey.shift = false; - //AxisReverseKey.ctrl = false; - //AxisReverseKey.alt = false; - - // Reverse Axis - useAxisReverse = iniFile.value ( "Enable_ReverseAxis", 0 ).toBool(); - YawAngle4ReverseAxis = iniFile.value ( "RA_Yaw", 40 ).toInt(); - Z_Pos4ReverseAxis = iniFile.value ( "RA_ZPos", 50 ).toInt(); - Z_PosWhenReverseAxis = iniFile.value ( "RA_ToZPos", 80 ).toInt(); - + // Reverse Axis + useAxisReverse = iniFile.value ( "Enable_ReverseAxis", 0 ).toBool(); + YawAngle4ReverseAxis = iniFile.value ( "RA_Yaw", 40 ).toInt(); + Z_Pos4ReverseAxis = iniFile.value ( "RA_ZPos", 50 ).toInt(); + Z_PosWhenReverseAxis = iniFile.value ( "RA_ToZPos", 80 ).toInt(); + inhibit_rx = iniFile.value("Inhibit_Yaw", false).toBool(); + inhibit_ry = iniFile.value("Inhibit_Pitch", false).toBool(); + inhibit_rz = iniFile.value("Inhibit_Roll", false).toBool(); + inhibit_tx = iniFile.value("Inhibit_X", false).toBool(); + inhibit_ty = iniFile.value("Inhibit_Y", false).toBool(); + inhibit_tz = iniFile.value("Inhibit_Z", false).toBool(); + inhibit_zero = iniFile.value("SetZero", false).toBool(); iniFile.endGroup (); } -// -// Determine if the ShortKey (incl. CTRL, SHIFT and/or ALT) is pressed. -// -bool Tracker::isShortKeyPressed( TShortKey *key, BYTE *keystate ){ -bool shift; -bool ctrl; -bool alt; - - // - // First, check if the right key is pressed. If so, check the modifiers - // - if (keystate[key->keycode] & 0x80) { - shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) ); - ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) ); - alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) ); - - // - // If one of the modifiers is needed and not pressed, return false. - // - if (key->shift && !shift) return false; - if (key->ctrl && !ctrl) return false; - if (key->alt && !alt) return false; - - // - // All is well! - // - return true; - } - else { - return false; - } -} - -// -// Determine if the MouseKey is pressed. -// -bool Tracker::isMouseKeyPressed( int *key, DIMOUSESTATE *mousestate ){ - - // - // If key == NONE, or invalid: ready! - // - if ((*key <= 0) || (*key > 5)) { - return false; - } - - // - // Now, check if the right key is pressed. - // - if (mousestate->rgbButtons[*key-1] & 0x80) { - return true; - } - else { - return false; - } -} +void Tracker::setInvertPitch(bool invert) { GlobalPose->Pitch.invert = invert?-1.0f:1.0f; } +void Tracker::setInvertYaw(bool invert) { GlobalPose->Yaw.invert = invert?-1.0f:+1.0f; } +void Tracker::setInvertRoll(bool invert) { GlobalPose->Roll.invert = invert?-1.0f:+1.0f; } +void Tracker::setInvertX(bool invert) { GlobalPose->X.invert = invert?-1.0f:+1.0f; } +void Tracker::setInvertY(bool invert) { GlobalPose->Y.invert = invert?-1.0f:+1.0f; } +void Tracker::setInvertZ(bool invert) { GlobalPose->Z.invert = invert?-1.0f:+1.0f; } diff --git a/facetracknoir/tracker.h b/facetracknoir/tracker.h index 4b161293..5cfcacd7 100644 --- a/facetracknoir/tracker.h +++ b/facetracknoir/tracker.h @@ -30,30 +30,35 @@ #include #include #include -#include #include #include #include #include #include - -#define DIRECTINPUT_VERSION 0x0800 -#include - -#include "FunctionConfig.h" - -#include "..\ftnoir_tracker_base\FTNoIR_Tracker_base.h" -#include "..\ftnoir_protocol_base\FTNoIR_Protocol_base.h" -#include "..\ftnoir_filter_base\FTNoIR_Filter_base.h" +#include +#include "global-settings.h" + +//#define DIRECTINPUT_VERSION 0x0800 +//#include +#undef FTNOIR_PROTOCOL_BASE_LIB +#undef FTNOIR_TRACKER_BASE_LIB +#undef FTNOIR_FILTER_BASE_LIB +#undef FTNOIR_PROTOCOL_BASE_EXPORT +#undef FTNOIR_TRACKER_BASE_EXPORT +#undef FTNOIR_FILTER_BASE_EXPORT +#define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT +#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT +#define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT + +#include +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ftnoir_filter_base/ftnoir_filter_base.h" #include "tracker_types.h" -typedef ITrackerPtr (WINAPI *importGetTracker)(void); -typedef IProtocolPtr (WINAPI *importGetProtocol)(void); -typedef IFilterPtr (WINAPI *importGetFilter)(void); - // include the DirectX Library files -#pragma comment (lib, "dinput8.lib") -#pragma comment (lib, "dxguid.lib") +//#pragma comment (lib, "dinput8.lib") +//#pragma comment (lib, "dxguid.lib") enum AngleName { PITCH = 0, @@ -88,127 +93,48 @@ enum FTNoIR_Tracker_Status { class FaceTrackNoIR; // pre-define parent-class to avoid circular includes +struct HeadPoseData; +extern HeadPoseData* GlobalPose; + // // Structure to hold all variables concerning one of 6 DOF's // class THeadPoseDOF { public: - - THeadPoseDOF(QString primary, QString secondary = "", int maxInput1 = 50, int maxOutput1 = 180, int maxInput2 = 50, int maxOutput2 = 90) { - QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - curvePtr = new FunctionConfig(primary, maxInput1, maxOutput1); // Create the Function-config for input-output translation - curvePtr->loadSettings(iniFile); // Load the settings from the INI-file - if (secondary != "") { - curvePtrAlt = new FunctionConfig(secondary, maxInput2, maxOutput2); - curvePtrAlt->loadSettings(iniFile); - } - - } - - void initHeadPoseData(){ - headPos = 0.0f; - invert = 0.0f; - red = 0.0f; - rawList.clear(); - maxItems = 10.0f; - prevPos = 0.0f; - prevRawPos = 0.0f; - NeutralZone = 0; - MaxInput = 0; - confidence = 0.0f; - newSample = FALSE; - - qDebug() << "initHeadPoseData: " << curvePtr->getTitle(); - - } + THeadPoseDOF(QString primary, QString secondary, int maxInput1 = 50, int maxOutput1 = 180, int maxInput2 = 50, int maxOutput2 = 90) { + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + curvePtr = new FunctionConfig(primary, maxInput1, maxOutput1); // Create the Function-config for input-output translation + curvePtr->loadSettings(iniFile); // Load the settings from the INI-file + if (secondary != "") { + curvePtrAlt = new FunctionConfig(secondary, maxInput2, maxOutput2); + curvePtrAlt->loadSettings(iniFile); + } + headPos = 0.0f; + invert = 1; + altp = false; + } float headPos; // Current position (from faceTracker, radials or meters) - float invert; // Invert measured value (= 1.0f or -1.0f) - float red; // Reduction factor (used for EWMA-filtering, between 0.0f and 1.0f) - QList rawList; // List of 'n' headPos values (used for moving average) - int maxItems; // Maximum number of elements in rawList - float prevPos; // Previous Position - float prevRawPos; // Previous Raw Position - + float invert; // Invert measured value (= 1.0f or -1.0f) FunctionConfig* curvePtr; // Function to translate input -> output FunctionConfig* curvePtrAlt; - - int NeutralZone; // Neutral zone - int MaxInput; // Maximum raw input - float confidence; // Current confidence - bool newSample; // Indicate new sample from tracker -}; - -// -// Structure to hold keycode and CTRL, SHIFT, ALT for shortkeys -// -struct TShortKey { - BYTE keycode; // Required Key - bool shift; // Modifiers to examine - bool ctrl; - bool alt; - bool doPitch; // Modifiers to act on axis - bool doYaw; - bool doRoll; - bool doX; - bool doY; - bool doZ; + bool altp; }; class Tracker : public QThread { Q_OBJECT private: - // Handles to neatly terminate thread... - HANDLE m_StopThread; - HANDLE m_WaitThread; - - static T6DOF current_camera; // Used for filtering - static T6DOF target_camera; - static T6DOF new_camera; - static T6DOF output_camera; + bool useAxisReverse; // Use Axis Reverse + float YawAngle4ReverseAxis; // Axis Reverse settings + float Z_Pos4ReverseAxis; + float Z_PosWhenReverseAxis; + + volatile bool inhibit_rx, inhibit_ry, inhibit_rz, inhibit_tx, inhibit_ty, inhibit_tz, inhibit_zero; - ITrackerPtr pTracker; // Pointer to Tracker instance (in DLL) - ITrackerPtr pSecondTracker; // Pointer to second Tracker instance (in DLL) - static IProtocolPtr pProtocol; // Pointer to Protocol instance (in DLL) - static IFilterPtr pFilter; // Pointer to Filter instance (in DLL) - - static void addHeadPose( THeadPoseData head_pose ); - static void addRaw2List ( QList *rawList, float maxIndex, float raw ); - - static TShortKey CenterKey; // ShortKey to Center headposition - static TShortKey StartStopKey; // ShortKey to Start/stop tracking - static TShortKey InhibitKey; // ShortKey to disable one or more axis during tracking - static TShortKey GameZeroKey; // ShortKey to Set Game Zero -// static TShortKey AxisReverseKey; // ShortKey to reverse axis during tracking - - static int CenterMouseKey; // ShortKey to Center headposition - static int StartStopMouseKey; // ShortKey to Start/stop tracking - static int InhibitMouseKey; // ShortKey to disable one or more axis during tracking - static int GameZeroMouseKey; // ShortKey to Set Game Zero - static bool DisableBeep; // Disable Beep when center is pressed - - // Flags to start/stop/reset tracking - static bool confid; // Tracker data is OK - static bool do_tracking; // Start/stop tracking, using the shortkey - static bool do_center; // Center head-position, using the shortkey - static bool do_inhibit; // Inhibit DOF-axis, using the shortkey - static bool do_game_zero; // Set in-game zero, using the shortkey - static bool do_axis_reverse; // Axis reverse, using the shortkey - - static HANDLE hTrackMutex; // Prevent reading/writing the headpose simultaneously - - static bool setZero; // Set to zero's, when OFF (one-shot) - static bool setEngineStop; // Stop tracker->engine, when OFF - - static bool useAxisReverse; // Use Axis Reverse - static float YawAngle4ReverseAxis; // Axis Reverse settings - static float Z_Pos4ReverseAxis; - static float Z_PosWhenReverseAxis; - - FaceTrackNoIR *mainApp; + FaceTrackNoIR *mainApp; protected: // qthread override run method @@ -216,67 +142,63 @@ protected: public: Tracker( FaceTrackNoIR *parent ); - ~Tracker(); - - /** static member variables for saving the head pose **/ - static THeadPoseDOF Pitch; // Head-rotation X-direction (Up/Down) - static THeadPoseDOF Yaw; // Head-rotation Y-direction () - static THeadPoseDOF Roll; // Head-rotation Z-direction () - static THeadPoseDOF X; // Head-movement X-direction (Left/Right) - static THeadPoseDOF Y; // Head-movement Y-direction (Up/Down) - static THeadPoseDOF Z; // Head-movement Z-direction (To/From camera) - - void setup(); + ~Tracker(); // void registerHeadPoseCallback(); bool handleGameCommand ( int command ); QString getGameProgramName(); // Get the ProgramName from the game and display it. void loadSettings(); // Load settings from the INI-file - bool isShortKeyPressed( TShortKey *key, BYTE *keystate ); - bool isMouseKeyPressed( int *key, DIMOUSESTATE *mousestate ); - - static bool getTrackingActive() { return do_tracking && confid; } - static bool getAxisReverse() { return do_axis_reverse; } - - static bool getConfid() { return confid; } - - static void setInvertPitch(bool invert) { Pitch.invert = invert?-1.0f:+1.0f; } - static void setInvertYaw(bool invert) { Yaw.invert = invert?-1.0f:+1.0f; } - static void setInvertRoll(bool invert) { Roll.invert = invert?-1.0f:+1.0f; } - static void setInvertX(bool invert) { X.invert = invert?-1.0f:+1.0f; } - static void setInvertY(bool invert) { Y.invert = invert?-1.0f:+1.0f; } - static void setInvertZ(bool invert) { Z.invert = invert?-1.0f:+1.0f; } - - static void getHeadPose(THeadPoseData *data); // Return the current headpose data - static void getOutputHeadPose(THeadPoseData *data); // Return the current (processed) headpose data - static IFilterPtr getFilterPtr() { return pFilter; } // Return the pointer for the active Filter - ITracker *getTrackerPtr() { return pTracker; } // Return the pointer for the active Tracker - ITracker *getSecondTrackerPtr() { return pSecondTracker; } // Return the pointer for the secondary Tracker - IProtocol *getProtocolPtr() { return pProtocol; } // Return the pointer for the active Protocol - - void doRefreshVideo() { // Call the face-tracker-function RefreshVideo - if (pTracker) { - pTracker->refreshVideo(); - } - if (pSecondTracker) { - pSecondTracker->refreshVideo(); - } - }; - - static float getSmoothFromList ( QList *rawList ); - static float getDegreesFromRads ( float rads ) { return (rads * 57.295781f); } - static float getRadsFromDegrees ( float degrees ) { return (degrees * 0.017453f); } - - // For now, use one slider for all - void setSmoothing(int x) { - Pitch.maxItems = x; - Yaw.maxItems = x; - Roll.maxItems = x; - X.maxItems = x; - Y.maxItems = x; - Z.maxItems = x; - } + //bool isShortKeyPressed( TShortKey *key, BYTE *keystate ); + //bool isMouseKeyPressed( int *key, DIMOUSESTATE *mousestate ); + + bool getTrackingActive() { return do_tracking && confid; } + bool getAxisReverse() { return do_axis_reverse; } + + bool getConfid() { return confid; } + + void setInvertPitch(bool invert); + void setInvertYaw(bool invert); + void setInvertRoll(bool invert); + void setInvertX(bool invert); + void setInvertY(bool invert); + void setInvertZ(bool invert); + + void getHeadPose(THeadPoseData *data); // Return the current headpose data + void getOutputHeadPose(THeadPoseData *data); // Return the current (processed) headpose data + + float getDegreesFromRads ( float rads ) { return (rads * 57.295781f); } + float getRadsFromDegrees ( float degrees ) { return (degrees * 0.017453f); } + volatile bool should_quit; + // following are now protected by hTrackMutex + volatile bool do_tracking; // Start/stop tracking, using the shortkey + volatile bool do_center; // Center head-position, using the shortkey + volatile bool do_inhibit; // Inhibit DOF-axis, using the shortkey + volatile bool do_game_zero; // Set in-game zero, using the shortkey + volatile bool do_axis_reverse; // Axis reverse, using the shortkey + + // Flags to start/stop/reset tracking + volatile bool confid; // Tracker data is OK; + + T6DOF output_camera; +}; +struct HeadPoseData { +public: + THeadPoseDOF Pitch; + THeadPoseDOF Yaw; + THeadPoseDOF Roll; + THeadPoseDOF X; + THeadPoseDOF Y; + THeadPoseDOF Z; + HeadPoseData() : + Pitch("PitchUp", "PitchDown", 50, 180, 50, 90), + Yaw("Yaw", "YawAlt", 50, 180), + Roll("Roll", "RollAlt", 50, 180), + X("X","XAlt", 50, 180), + Y("Y","YAlt", 50, 180), + Z("Z","ZAlt", 50, 180) + { + } }; -#endif \ No newline at end of file +#endif diff --git a/facetracknoir/tracker_types.h b/facetracknoir/tracker_types.h index 5a13af85..d8e7ecee 100644 --- a/facetracknoir/tracker_types.h +++ b/facetracknoir/tracker_types.h @@ -28,12 +28,12 @@ #ifndef __TRACKER_TYPES_H__ #define __TRACKER_TYPES_H__ -#include "..\ftnoir_tracker_base\ftnoir_tracker_types.h" +#include "ftnoir_tracker_base/ftnoir_tracker_types.h" class T6DOF : public THeadPoseData { public: - T6DOF() : THeadPoseData() {} + T6DOF() : THeadPoseData() {} T6DOF(double x, double y, double z, double yaw, double pitch, double roll) : THeadPoseData(x,y,z, yaw,pitch,roll) {} @@ -42,4 +42,4 @@ public: T6DOF operator-(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B T6DOF operator+(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B^-1 -#endif //__TRACKER_TYPES_H__ \ No newline at end of file +#endif //__TRACKER_TYPES_H__ diff --git a/facetracknoir/uielements/facetracknoir.ico b/facetracknoir/uielements/facetracknoir.ico new file mode 100644 index 00000000..af36ec30 Binary files /dev/null and b/facetracknoir/uielements/facetracknoir.ico differ diff --git a/facetracknoir/uielements/setupfacetracknoir.jpg b/facetracknoir/uielements/setupfacetracknoir.jpg new file mode 100644 index 00000000..8778c6d5 Binary files /dev/null and b/facetracknoir/uielements/setupfacetracknoir.jpg differ diff --git a/ftnoir_filter_accela/default-points.cpp b/ftnoir_filter_accela/default-points.cpp new file mode 100644 index 00000000..2cebff6c --- /dev/null +++ b/ftnoir_filter_accela/default-points.cpp @@ -0,0 +1,38 @@ +#include +#include + +static QList EmptyList() { + return QList(); +} + +extern const QList defScaleRotation, defScaleTranslation; + +const QList defScaleRotation = + EmptyList() + << QPointF(0, 0) + << QPointF(0.308900523560209, 0.0666666666666667) + << QPointF(0.565445026178011, 0.226666666666667) + << QPointF(0.769633507853403, 0.506666666666667) + << QPointF(0.994764397905759, 1) + << QPointF(1.23560209424084, 1.61333333333333) + << QPointF(1.47643979057592, 2.37333333333333) + << QPointF(1.66492146596859, 3.12) + << QPointF(1.80628272251309, 3.92) + << QPointF(1.91623036649215, 4.70666666666667) + << QPointF(2.00523560209424, 5.44) + << QPointF(2.07329842931937, 6) +; + +const QList defScaleTranslation = + EmptyList() + << QPointF(0, 0) + << QPointF(0.282722513089005, 0.08) + << QPointF(0.492146596858639, 0.306666666666667) + << QPointF(0.764397905759162, 0.84) + << QPointF(1.00523560209424, 1.62666666666667) + << QPointF(1.17277486910995, 2.78666666666667) + << QPointF(1.25130890052356, 3.6) + << QPointF(1.31937172774869, 4.29333333333333) + << QPointF(1.38219895287958, 4.90666666666667) + << QPointF(1.43455497382199, 5.65333333333333) +; diff --git a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui new file mode 100644 index 00000000..9be0356b --- /dev/null +++ b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui @@ -0,0 +1,451 @@ + + + AccelaUICFilterControls + + + Qt::ApplicationModal + + + + 0 + 0 + 880 + 673 + + + + Filter settings + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + + + + true + + + + 0 + 0 + + + + + 850 + 574 + + + + + 300 + 574 + + + + 0 + + + + Rotation + + + + + 20 + 20 + 819 + 510 + + + + 4 + + + 6 + + + 191 + + + 75 + + + 1 + + + 1 + + + + 255 + 170 + 0 + + + + + 192 + 192 + 192 + + + + Input + + + Output + + + Translation + + + + + + Translation + + + + + 20 + 20 + 819 + 510 + + + + 4 + + + 6 + + + 191 + + + 75 + + + 1 + + + 1 + + + + 85 + 255 + 0 + + + + + 192 + 192 + 192 + + + + Input + + + Output + + + + + + + + + + + + 25 + 0 + + + + + 150 + 16777215 + + + + color:#0; +background:none; + + + Reduction factor: + + + + + + + + 50 + 15 + + + + 1 + + + 100 + + + 5 + + + 100 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 35 + 22 + + + + background:none; + + + false + + + 1 + + + 100 + + + 100 + + + + + + + + 25 + 0 + + + + + 150 + 16777215 + + + + color:#0; +background:none; + + + Zoom slowness: + + + + + + + + 50 + 15 + + + + 0 + + + 200 + + + 1 + + + 100 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 35 + 22 + + + + background:none; + + + false + + + 0 + + + 200 + + + 100 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + QFunctionConfigurator + QWidget +
qfunctionconfigurator/qfunctionconfigurator.h
+
+
+ + + + slideReduction + valueChanged(int) + spinReduction + setValue(int) + + + 219 + 620 + + + 310 + 622 + + + + + spinReduction + valueChanged(int) + slideReduction + setValue(int) + + + 315 + 613 + + + 170 + 621 + + + + + slideZoom + valueChanged(int) + spinZoom + setValue(int) + + + 547 + 602 + + + 667 + 602 + + + + + spinZoom + valueChanged(int) + slideZoom + setValue(int) + + + 663 + 602 + + + 537 + 602 + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + +
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp index 3e4c3bf6..cb9fb0f5 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela.cpp @@ -10,11 +10,15 @@ Additional changes: I have added two parameters to the constructor of FunctionConfig and renamed 3 member-functions (getFilterFullName is now called getFullName). */ -#include "ftnoir_filter_Accela.h" +#include "ftnoir_filter_accela/ftnoir_filter_accela.h" #include "math.h" #include -#include #include +#include "facetracknoir/global-settings.h" + +#if !defined(_WIN32) && !defined(__WIN32) +# define _isnan isnan +#endif FTNoIR_Filter::FTNoIR_Filter() : functionConfig("Accela-Scaling-Rotation", 4, 6), @@ -32,8 +36,6 @@ FTNoIR_Filter::~FTNoIR_Filter() void FTNoIR_Filter::Initialize() { - loadSettings(); - return; } void FTNoIR_Filter::loadSettings() { @@ -45,24 +47,29 @@ void FTNoIR_Filter::loadSettings() { QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) defPoints.clear(); - for (int i = 0; i < NUM_OF(defScaleRotation); i++) { // Get the default points (hardcoded!) + for (int i = 0; i < defScaleRotation.size(); i++) { // Get the default points (hardcoded!) defPoints.append(defScaleRotation[i]); } functionConfig.loadSettings(iniFile, defPoints); defPoints.clear(); - for (int i = 0; i < NUM_OF(defScaleTranslation); i++) { // Get the default points (hardcoded!) + for (int i = 0; i < defScaleTranslation.size(); i++) { // Get the default points (hardcoded!) defPoints.append(defScaleTranslation[i]); } translationFunctionConfig.loadSettings(iniFile, defPoints); iniFile.beginGroup ( "Accela" ); kMagicNumber = iniFile.value ( "Reduction", 100 ).toFloat(); + kZoomSlowness = iniFile.value("zoom-slowness", 0).toFloat(); iniFile.endGroup (); } -void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, bool newTarget) +void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, + THeadPoseData *target_camera_position, + THeadPoseData *new_camera_position, + THeadPoseData *last_post_filter_values, + bool newTarget) { double target[6]; double prev_output[6]; @@ -130,10 +137,7 @@ void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, T // useful for filtering, as skipping them would result in jerky output. // the magic "100" is the amount of calls to the filter by FTNOIR per sec. // WVR: Added kMagicNumber for Patrick - double velocity = foo / 100.0; - if (kMagicNumber > 0.0f) { - double velocity = foo / kMagicNumber; - } + double velocity = foo / (kMagicNumber > 0 ? kMagicNumber : 100.0) * (1 / std::max(1.0, 1 + kZoomSlowness * -last_post_filter_values->z / 100)); double sum = start + velocity * sign; bool done = (sign > 0 ? sum >= e2 : sum <= e2); if (done) { @@ -168,9 +172,8 @@ void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, T // GetFilter - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilter@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilter=_GetFilter@0") -FTNOIR_FILTER_BASE_EXPORT IFilterPtr __stdcall GetFilter() +extern "C" FTNOIR_FILTER_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Filter; + return (IFilter*) new FTNoIR_Filter; } diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h index 77aa59ea..32cebf99 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.h +++ b/ftnoir_filter_accela/ftnoir_filter_accela.h @@ -26,39 +26,16 @@ #ifndef INCLUDED_FTN_FILTER_H #define INCLUDED_FTN_FILTER_H -#include "..\ftnoir_filter_base\ftnoir_filter_base.h" -#include "ui_FTNoIR_FilterControls.h" -#include +#undef FTNOIR_TRACKER_BASE_LIB +#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT -const QPointF defScaleRotation[] = -{ - QPointF(0, 0), - QPointF(0.308900523560209, 0.0666666666666667), - QPointF(0.565445026178011, 0.226666666666667), - QPointF(0.769633507853403, 0.506666666666667), - QPointF(0.994764397905759, 1), - QPointF(1.23560209424084, 1.61333333333333), - QPointF(1.47643979057592, 2.37333333333333), - QPointF(1.66492146596859, 3.12), - QPointF(1.80628272251309, 3.92), - QPointF(1.91623036649215, 4.70666666666667), - QPointF(2.00523560209424, 5.44), - QPointF(2.07329842931937, 6) -}; +#include "ftnoir_filter_base/ftnoir_filter_base.h" +#include "ui_ftnoir_accela_filtercontrols.h" +#include +#include "facetracknoir/global-settings.h" -const QPointF defScaleTranslation[] = -{ - QPointF(0, 0), - QPointF(0.282722513089005, 0.08), - QPointF(0.492146596858639, 0.306666666666667), - QPointF(0.764397905759162, 0.84), - QPointF(1.00523560209424, 1.62666666666667), - QPointF(1.17277486910995, 2.78666666666667), - QPointF(1.25130890052356, 3.6), - QPointF(1.31937172774869, 4.29333333333333), - QPointF(1.38219895287958, 4.90666666666667), - QPointF(1.43455497382199, 5.65333333333333) -}; +extern const QList defScaleRotation; +extern const QList defScaleTranslation; // // Macro to determine array-size @@ -68,16 +45,14 @@ const QPointF defScaleTranslation[] = //******************************************************************************************************* // FaceTrackNoIR Filter class. //******************************************************************************************************* -class FTNoIR_Filter : public IFilter +class FTNOIR_FILTER_BASE_EXPORT FTNoIR_Filter : public IFilter { public: FTNoIR_Filter(); ~FTNoIR_Filter(); - void Release(); void Initialize(); - void StartFilter(); - void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, bool newTarget); + void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, THeadPoseData *last_post_filter_values, bool newTarget); private: void loadSettings(); // Load the settings from the INI-file @@ -86,7 +61,7 @@ private: bool first_run; double kFactor, kFactorTranslation; double kSensitivity, kSensitivityTranslation; - double kMagicNumber; // Stanislaws' magic number (should be 100 according to him...) + double kMagicNumber, kZoomSlowness; // Stanislaws' magic number (should be 100 according to him...) FunctionConfig functionConfig; FunctionConfig translationFunctionConfig; @@ -97,7 +72,7 @@ private: //******************************************************************************************************* // Widget that has controls for FTNoIR protocol filter-settings. -class FilterControls: public QWidget, Ui::UICFilterControls, public IFilterDialog +class FTNOIR_FILTER_BASE_EXPORT FilterControls: public QWidget, Ui::AccelaUICFilterControls, public IFilterDialog { Q_OBJECT public: @@ -107,17 +82,17 @@ public: void showEvent ( QShowEvent * event ); void Release(); // Member functions which are accessible from outside the DLL - void Initialize(QWidget *parent, IFilterPtr ptr); + void Initialize(QWidget *parent, IFilter *ptr); private: - Ui::UICFilterControls ui; + Ui::AccelaUICFilterControls ui; void loadSettings(); void save(); /** helper **/ bool settingsDirty; - IFilterPtr pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance + IFilter* pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance FunctionConfig functionConfig; FunctionConfig translationFunctionConfig; @@ -131,17 +106,17 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Filter DLL. Functions used to get general info on the Filter //******************************************************************************************************* -class FTNoIR_FilterDll : public IFilterDll +class FTNoIR_FilterDll : public Metadata { public: FTNoIR_FilterDll(); ~FTNoIR_FilterDll(); - void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Filter Mk2"); }; - void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk2"); }; - void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk2"); }; + void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Filter Mk2"); } + void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk2"); } + void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk2"); } - void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); }; + void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); } }; diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp index c230eed8..9970e962 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp @@ -26,9 +26,10 @@ Modifications (last one on top): 20130102 - WVR: Added 'reduction factor' to accommodate Patrick's need for speed. */ -#include "ftnoir_filter_Accela.h" +#include "ftnoir_filter_accela/ftnoir_filter_accela.h" #include "math.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Filter Settings-dialog. @@ -51,7 +52,7 @@ FilterControls::FilterControls() : connect(ui.translationScalingConfig, SIGNAL(CurveChanged(bool)), this, SLOT(settingChanged(bool))); // Connect slider for reduction - connect(ui.slideReduction, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int))); + //connect(ui.slideReduction, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int))); qDebug() << "FilterControls() says: started"; } @@ -71,7 +72,7 @@ void FilterControls::Release() // // Initialize tracker-client-dialog // -void FilterControls::Initialize(QWidget *parent, IFilterPtr ptr) { +void FilterControls::Initialize(QWidget *parent, IFilter* ptr) { // // The dialog can be opened, while the Tracker is running. @@ -79,6 +80,7 @@ void FilterControls::Initialize(QWidget *parent, IFilterPtr ptr) { // This can be used to update settings, while Tracking and may also be handy to display logging-data and such... // pFilter = ptr; + loadSettings(); QPoint offsetpos(100, 100); if (parent) { @@ -100,7 +102,6 @@ void FilterControls::doOK() { // override show event void FilterControls::showEvent ( QShowEvent * event ) { - loadSettings(); } // @@ -150,16 +151,16 @@ QList defPoints; qDebug() << "FTNoIR_Filter::loadSettings2 says: iniFile = " << currentFile; - qDebug() << "FTNoIR_Filter::loadSettings2 says: size = " << NUM_OF(defScaleRotation); + //qDebug() << "FTNoIR_Filter::loadSettings2 says: size = " << NUM_OF(defScaleRotation); defPoints.clear(); - for (int i = 0; i < NUM_OF(defScaleRotation); i++) { // Get the default points (hardcoded!) + for (int i = 0; i < defScaleRotation.size(); i++) { // Get the default points (hardcoded!) defPoints.append(defScaleRotation[i]); } functionConfig.loadSettings(iniFile, defPoints); defPoints.clear(); - for (int i = 0; i < NUM_OF(defScaleTranslation); i++) { // Get the default points (hardcoded!) + for (int i = 0; i < defScaleTranslation.size(); i++) { // Get the default points (hardcoded!) defPoints.append(defScaleTranslation[i]); } translationFunctionConfig.loadSettings(iniFile, defPoints); @@ -169,6 +170,7 @@ QList defPoints; iniFile.beginGroup ( "Accela" ); ui.slideReduction->setValue (iniFile.value ( "Reduction", 100 ).toInt()); + ui.slideZoom->setValue(iniFile.value("zoom-slowness", 0).toInt()); iniFile.endGroup (); settingsDirty = false; @@ -187,6 +189,7 @@ void FilterControls::save() { iniFile.beginGroup ( "Accela" ); iniFile.setValue ( "Reduction", ui.slideReduction->value() ); + iniFile.setValue("zoom-slowness", ui.slideZoom->value()); iniFile.endGroup (); functionConfig.saveSettings(iniFile); @@ -202,9 +205,9 @@ void FilterControls::save() { // GetFilterDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilterDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0") +//#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0") -FTNOIR_FILTER_BASE_EXPORT IFilterDialogPtr __stdcall GetFilterDialog( ) +extern "C" FTNOIR_FILTER_BASE_EXPORT void* CALLING_CONVENTION GetDialog() { - return new FilterControls; + return (IFilterDialog*) new FilterControls; } diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp index e1452bf2..3ae273df 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp @@ -30,8 +30,9 @@ The FilterDll class solves this. The functions to get the name(s) and icon were removed from the two other classes. */ -#include "ftnoir_filter_Accela.h" +#include "ftnoir_filter_accela.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_FilterDll::FTNoIR_FilterDll() { } @@ -48,9 +49,9 @@ FTNoIR_FilterDll::~FTNoIR_FilterDll() // GetFilterDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilterDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0") +//#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0") -FTNOIR_FILTER_BASE_EXPORT IFilterDllPtr __stdcall GetFilterDll() +extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { - return new FTNoIR_FilterDll; + return new FTNoIR_FilterDll; } diff --git a/ftnoir_filter_base/ftnoir_filter_base.h b/ftnoir_filter_base/ftnoir_filter_base.h index 44ce3d72..37309077 100644 --- a/ftnoir_filter_base/ftnoir_filter_base.h +++ b/ftnoir_filter_base/ftnoir_filter_base.h @@ -2,7 +2,7 @@ #define FTNOIR_FILTER_BASE_H #include "ftnoir_filter_base_global.h" -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" #include #include #include @@ -27,40 +27,10 @@ struct IFilter { virtual ~IFilter() {} virtual void Initialize() = 0; - virtual void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, bool newTarget) = 0; + virtual void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, THeadPoseData *last_post_filter, bool newTarget) = 0; }; -typedef IFilter* IFilterPtr; -//typedef IFilter *(__stdcall *importGetFilter)(void); - -// Factory function that creates instances of the Filter object. -EXTERN_C -FTNOIR_FILTER_BASE_EXPORT -IFilterPtr -__stdcall -GetFilter(void); - -//////////////////////////////////////////////////////////////////////////////// -// COM-Like abstract interface. -// This interface doesn't require __declspec(dllexport/dllimport) specifier. -// Method calls are dispatched via virtual table. -// Any C++ compiler can use it. -// Instances are obtained via factory function. -struct IFilterDialog -{ - virtual ~IFilterDialog() {} - virtual void Initialize(QWidget *parent, IFilterPtr ptr) = 0; -}; - -typedef IFilterDialog* IFilterDialogPtr; - - // Factory function that creates instances of the Filter object. -EXTERN_C -FTNOIR_FILTER_BASE_EXPORT -IFilterDialogPtr -__stdcall -GetFilterDialog(void); //////////////////////////////////////////////////////////////////////////////// // COM-Like abstract interface. @@ -78,14 +48,15 @@ struct IFilterDll virtual void getIcon(QIcon *icon) = 0; }; -typedef IFilterDll* IFilterDllPtr; - -// Factory function that creates instances of the Filter object. -EXTERN_C -FTNOIR_FILTER_BASE_EXPORT -IFilterDllPtr -__stdcall -GetFilterDll(void); +struct IFilterDialog +{ + virtual ~IFilterDialog() {} + virtual void Initialize(QWidget *parent, IFilter* ptr) = 0; + virtual void getFullName(QString *strToBeFilled) {}; + virtual void getShortName(QString *strToBeFilled) {}; + virtual void getDescription(QString *strToBeFilled) {}; + virtual void getIcon(QIcon *icon) {}; +}; #endif // FTNOIR_FILTER_BASE_H diff --git a/ftnoir_filter_base/ftnoir_filter_base_global.h b/ftnoir_filter_base/ftnoir_filter_base_global.h index aac4048e..a923f6cf 100644 --- a/ftnoir_filter_base/ftnoir_filter_base_global.h +++ b/ftnoir_filter_base/ftnoir_filter_base_global.h @@ -1,7 +1,7 @@ #ifndef FTNOIR_FILTER_BASE_GLOBAL_H #define FTNOIR_FILTER_BASE_GLOBAL_H -#include +#include #ifdef FTNOIR_FILTER_BASE_LIB # define FTNOIR_FILTER_BASE_EXPORT Q_DECL_EXPORT diff --git a/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui b/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui new file mode 100644 index 00000000..0f31bcd3 --- /dev/null +++ b/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui @@ -0,0 +1,587 @@ + + + UICFilterControls + + + + 0 + 0 + 371 + 380 + + + + + 0 + 380 + + + + EWMA2 Filter settings FaceTrackNoIR + + + + images/facetracknoir.png + + + + Qt::LeftToRight + + + false + + + + + + + + + QLayout::SetMinimumSize + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + + + + pow + + + + + + + + 40 + 22 + + + + background:none; + + + 100 + + + 5 + + + 10 + + + + + + + + 45 + 15 + + + + 1 + + + 100 + + + 10 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 35 + 0 + + + + + 30 + 16777215 + + + + + + + frames + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + + + + Max. + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + + + + Curve + + + + + + + + 40 + 22 + + + + background:none; + + + 1 + + + 100 + + + 5 + + + 2 + + + + + + + + 35 + 0 + + + + + 30 + 16777215 + + + + + + + frames + + + + + + + + 45 + 15 + + + + 1 + + + 100 + + + 10 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 40 + 22 + + + + background:none; + + + 1 + + + 100 + + + 5 + + + 10 + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + + + + Min. + + + + + + + + 45 + 15 + + + + 1 + + + 100 + + + 10 + + + 2 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + 0 + 204 + + + + background-color: rgb(214, 214, 214); +border-color: rgb(0, 0, 0); + + + QFrame::Box + + + <!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:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Min. frames:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Defines the way the filter responds to fast movements;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Higher value: slower response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Max. frames:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Defines the way the filter responds to slow movements;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Higher value: slower response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Pow:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Defines the filters 'readiness' to respond to speed changes;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Higher value = </span><span style=" font-size:10pt; font-weight:600;">higher</span><span style=" font-size:10pt;"> response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"></p></body></html> + + + 5 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 52 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 52 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + btnOK + btnCancel + + + + + minSmooth + valueChanged(int) + spinMinSmooth + setValue(int) + + + 199 + 22 + + + 337 + 23 + + + + + spinMinSmooth + valueChanged(int) + minSmooth + setValue(int) + + + 330 + 12 + + + 185 + 17 + + + + + maxSmooth + valueChanged(int) + spinMaxSmooth + setValue(int) + + + 181 + 48 + + + 335 + 54 + + + + + spinMaxSmooth + valueChanged(int) + maxSmooth + setValue(int) + + + 324 + 42 + + + 259 + 43 + + + + + powCurve + valueChanged(int) + spinPowCurve + setValue(int) + + + 145 + 74 + + + 339 + 78 + + + + + spinPowCurve + valueChanged(int) + powCurve + setValue(int) + + + 330 + 69 + + + 176 + 76 + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp index fac0e13c..5f196533 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp @@ -25,7 +25,9 @@ #include "ftnoir_filter_ewma2.h" #include "math.h" #include - +#include +#include "facetracknoir/global-settings.h" +#include //#define LOG_OUTPUT ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -47,11 +49,6 @@ FTNoIR_Filter::~FTNoIR_Filter() } -void FTNoIR_Filter::Release() -{ - delete this; -} - void FTNoIR_Filter::Initialize() { qDebug() << "FTNoIR_Filter::Initialize says: Starting "; @@ -82,7 +79,7 @@ void FTNoIR_Filter::loadSettings() { } -void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, bool newTarget) +void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, THeadPoseData *last_post_filter, bool newTarget) { //non-optimised version for clarity float prev_output[6]; @@ -149,7 +146,7 @@ void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, T //normalise the deltas for (i=0;i<6;i++) { - norm_output_delta[i]=std::min(std::max(fabs(output_delta[i])/scale[i],0.0f),1.0f); + norm_output_delta[i]=std::min(std::max(fabs(output_delta[i])/scale[i],0.0),1.0); } //calculate the alphas @@ -228,9 +225,9 @@ void FTNoIR_Filter::FilterHeadPoseData(THeadPoseData *current_camera_position, T // GetFilter - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilter@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilter=_GetFilter@0") +//#pragma comment(linker, "/export:GetFilter=_GetFilter@0") -FTNOIR_FILTER_BASE_EXPORT IFilterPtr __stdcall GetFilter() +extern "C" FTNOIR_FILTER_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Filter; + return (IFilter*) new FTNoIR_Filter; } diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h index 18afe3bd..cade740f 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h @@ -26,8 +26,10 @@ #ifndef INCLUDED_FTN_FILTER_H #define INCLUDED_FTN_FILTER_H -#include "..\ftnoir_filter_base\ftnoir_filter_base.h" -#include "ui_FTNoIR_FilterControls.h" +#include "ftnoir_filter_base/ftnoir_filter_base.h" +#include "facetracknoir/global-settings.h" +#include "ui_ftnoir_ewma_filtercontrols.h" +#include ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -38,12 +40,10 @@ class FTNoIR_Filter : public IFilter { public: FTNoIR_Filter(); - ~FTNoIR_Filter(); + ~FTNoIR_Filter(); - void Release(); void Initialize(); - void StartFilter(); - void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, bool newTarget); + void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position, THeadPoseData *last_post_filter, bool newTarget); private: void loadSettings(); // Load the settings from the INI-file @@ -76,7 +76,7 @@ public: void showEvent ( QShowEvent * event ); void Release(); // Member functions which are accessible from outside the DLL - void Initialize(QWidget *parent, IFilterPtr ptr); + void Initialize(QWidget *parent, IFilter* ptr); private: Ui::UICFilterControls ui; @@ -86,7 +86,7 @@ private: /** helper **/ bool settingsDirty; - IFilterPtr pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance + IFilter* pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance private slots: void doOK(); @@ -98,7 +98,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Filter DLL. Functions used to get general info on the Filter //******************************************************************************************************* -class FTNoIR_FilterDll : public IFilterDll +class FTNoIR_FilterDll : public Metadata { public: FTNoIR_FilterDll(); diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp index c7798ac0..3e0fdb25 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp @@ -22,9 +22,11 @@ * with this program; if not, see . * * * ********************************************************************************/ -#include "ftnoir_filter_EWMA2.h" +#include "ftnoir_filter_ewma2.h" #include "math.h" #include +#include "facetracknoir/global-settings.h" +#include "ui_ftnoir_ewma_filtercontrols.h" //******************************************************************************************************* // FaceTrackNoIR Filter Settings-dialog. @@ -72,7 +74,7 @@ void FilterControls::Release() // // Initialize tracker-client-dialog // -void FilterControls::Initialize(QWidget *parent, IFilterPtr ptr) { +void FilterControls::Initialize(QWidget *parent, IFilter* ptr) { // // The dialog can be opened, while the Tracker is running. @@ -189,9 +191,9 @@ void FilterControls::save() { // GetFilterDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilterDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0") +//#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0") -FTNOIR_FILTER_BASE_EXPORT IFilterDialogPtr __stdcall GetFilterDialog( ) +extern "C" FTNOIR_FILTER_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new FilterControls; + return (IFilterDialog*) new FilterControls; } diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp index 4e644446..a01b0661 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_filter_ewma2.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_FilterDll::FTNoIR_FilterDll() { } @@ -48,9 +49,9 @@ FTNoIR_FilterDll::~FTNoIR_FilterDll() // GetFilterDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetFilterDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0") +//#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0") -FTNOIR_FILTER_BASE_EXPORT IFilterDllPtr __stdcall GetFilterDll() +extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_FilterDll; } diff --git a/ftnoir_posewidget/glwidget.cpp b/ftnoir_posewidget/glwidget.cpp index 55b65619..32723dc9 100644 --- a/ftnoir_posewidget/glwidget.cpp +++ b/ftnoir_posewidget/glwidget.cpp @@ -28,10 +28,14 @@ #include #include "glwidget.h" +#include GLWidget::GLWidget(QWidget *parent, QGLWidget *shareWidget) : QGLWidget(parent, shareWidget) { +#if !defined(_WIN32) + setAttribute(Qt::WA_NativeWindow, true); +#endif clearColor = Qt::black; xRot = 0; yRot = 0; @@ -74,7 +78,7 @@ void GLWidget::initializeGL() { makeObject(); - glEnable(GL_DEPTH_TEST); + glDisable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); #ifndef QT_OPENGL_ES_2 glEnable(GL_TEXTURE_2D); @@ -117,16 +121,20 @@ void GLWidget::initializeGL() program->bind(); program->setUniformValue("texture", 0); - +#else + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, vertices.constData()); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData()); #endif } void GLWidget::paintGL() { - qglClearColor(clearColor); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#if !defined(QT_OPENGL_ES_2) +#if 1 glLoadIdentity(); glTranslatef(0.0f, 0.0f, -10.0f); @@ -135,11 +143,6 @@ void GLWidget::paintGL() glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(-1.0f * zRot, 0.0f, 0.0f, 1.0f); - glVertexPointer(3, GL_FLOAT, 0, vertices.constData()); - glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - #else QMatrix4x4 m; @@ -163,6 +166,7 @@ void GLWidget::paintGL() glBindTexture(GL_TEXTURE_2D, textures[i]); glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); } + glFlush(); } void GLWidget::resizeGL(int width, int height) diff --git a/ftnoir_posewidget/glwidget.h b/ftnoir_posewidget/glwidget.h index cff8cb83..3d0e590a 100644 --- a/ftnoir_posewidget/glwidget.h +++ b/ftnoir_posewidget/glwidget.h @@ -29,10 +29,11 @@ #include #include +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" class QGLShaderProgram; -class GLWidget : public QGLWidget +class FTNOIR_TRACKER_BASE_EXPORT GLWidget : public QGLWidget { Q_OBJECT diff --git a/ftnoir_protocol_base/ftnoir_protocol_base.h b/ftnoir_protocol_base/ftnoir_protocol_base.h index 3f598d35..5d88a508 100644 --- a/ftnoir_protocol_base/ftnoir_protocol_base.h +++ b/ftnoir_protocol_base/ftnoir_protocol_base.h @@ -33,12 +33,12 @@ #define FTNOIR_PROTOCOL_BASE_H #include "ftnoir_protocol_base_global.h" -#include "..\ftnoir_tracker_base\ftnoir_tracker_types.h" +#include "ftnoir_tracker_base/ftnoir_tracker_types.h" #include #include //#include "winbase.h" -#include "windows.h" +//#include "windows.h" //#include "winable.h" //////////////////////////////////////////////////////////////////////////////// @@ -58,43 +58,11 @@ struct IProtocol { virtual ~IProtocol() {} virtual void Initialize() = 0; - virtual bool checkServerInstallationOK ( HANDLE handle ) = 0; + virtual bool checkServerInstallationOK() = 0; virtual void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ) = 0; virtual void getNameFromGame( char *dest ) = 0; // Take care dest can handle up to 100 chars... }; -typedef IProtocol* IProtocolPtr; - -// Factory function that creates instances of the Protocol object. -EXTERN_C -FTNOIR_PROTOCOL_BASE_EXPORT -IProtocolPtr -__stdcall -GetProtocol(void); - -//////////////////////////////////////////////////////////////////////////////// -// COM-Like abstract interface. -// This interface doesn't require __declspec(dllexport/dllimport) specifier. -// Method calls are dispatched via virtual table. -// Any C++ compiler can use it. -// Instances are obtained via factory function. -struct IProtocolDialog -{ - virtual ~IProtocolDialog() {} - virtual void Initialize(QWidget *parent) = 0; - virtual void registerProtocol(IProtocol *protocol) = 0; - virtual void unRegisterProtocol() = 0; -}; - -typedef IProtocolDialog* IProtocolDialogPtr; - -// Factory function that creates instances of the Protocol object. -EXTERN_C -FTNOIR_PROTOCOL_BASE_EXPORT -IProtocolDialogPtr -__stdcall -GetProtocolDialog(void); - //////////////////////////////////////////////////////////////////////////////// // COM-Like abstract interface. // This interface doesn't require __declspec(dllexport/dllimport) specifier. @@ -111,14 +79,14 @@ struct IProtocolDll virtual void getIcon(QIcon *icon) = 0; }; -typedef IProtocolDll* IProtocolDllPtr; - -// Factory function that creates instances of the Protocol object. -EXTERN_C -FTNOIR_PROTOCOL_BASE_EXPORT -IProtocolDllPtr -__stdcall -GetProtocolDll(void); +struct IProtocolDialog +{ + virtual ~IProtocolDialog() {} + virtual void Initialize(QWidget *parent) = 0; + virtual void showEvent ( QShowEvent * event ) = 0; + virtual void registerProtocol(IProtocol *protocol) = 0; + virtual void unRegisterProtocol() = 0; +}; #endif // FTNOIR_PROTOCOL_BASE_H diff --git a/ftnoir_protocol_base/ftnoir_protocol_base_global.h b/ftnoir_protocol_base/ftnoir_protocol_base_global.h index 3527bad7..ca51e26d 100644 --- a/ftnoir_protocol_base/ftnoir_protocol_base_global.h +++ b/ftnoir_protocol_base/ftnoir_protocol_base_global.h @@ -1,7 +1,7 @@ #ifndef FTNOIR_PROTOCOL_BASE_GLOBAL_H #define FTNOIR_PROTOCOL_BASE_GLOBAL_H -#include +#include #ifdef FTNOIR_PROTOCOL_BASE_LIB # define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_EXPORT diff --git a/ftnoir_protocol_fg/fgtypes.h b/ftnoir_protocol_fg/fgtypes.h index 949dc213..68f85877 100644 --- a/ftnoir_protocol_fg/fgtypes.h +++ b/ftnoir_protocol_fg/fgtypes.h @@ -14,15 +14,14 @@ #ifndef INCLUDED_FGTYPES_H #define INCLUDED_FGTYPES_H -#include "Windows.h" - // // x,y,z position in metres, heading, pitch and roll in degrees... // -#pragma pack(2) +#pragma pack(push, 2) struct TFlightGearData { double x, y, z, h, p, r; int status; }; +#pragma pack(pop) #endif//INCLUDED_FGTYPES_H diff --git a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui b/ftnoir_protocol_fg/ftnoir_fgcontrols.ui index 3469e7aa..116f830b 100644 --- a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui +++ b/ftnoir_protocol_fg/ftnoir_fgcontrols.ui @@ -15,7 +15,7 @@
- images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp index 5506f534..0c259d61 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp @@ -33,6 +33,7 @@ */ #include "ftnoir_protocol_fg.h" #include +#include "facetracknoir/global-settings.h" // For Todd and Arda Kutlu //#define SEND_ASCII_DATA @@ -42,7 +43,6 @@ FTNoIR_Protocol::FTNoIR_Protocol() { blnConnectionActive = false; - hMainWindow = NULL; loadSettings(); } @@ -103,7 +103,6 @@ void FTNoIR_Protocol::sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData int no_bytes; QHostAddress sender; quint16 senderPort; -PDWORD_PTR MsgResult = 0; #ifdef SEND_ASCII_DATA char data[100]; @@ -152,7 +151,7 @@ char data[100]; //! [1] // no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), QHostAddress::LocalHost, 5550); if (outSocket != 0) { - no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), destIP, destPort); + no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), destIP, destPort); if ( no_bytes > 0) { // qDebug() << "FGServer::writePendingDatagrams says: bytes send =" << no_bytes << sizeof( double ); } @@ -181,9 +180,6 @@ char data[100]; if (!blnConnectionActive) { blnConnectionActive = true; - if (hMainWindow != NULL) { - SendMessageTimeout( (HWND) hMainWindow, RegisterWindowMessageA(FT_PROGRAMID), 0, 0, 0, 2000, MsgResult); - } } } } @@ -193,7 +189,7 @@ char data[100]; // Check if the Client DLL exists and load it (to test it), if so. // Returns 'true' if all seems OK. // -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { // Init. the data FlightData.x = 0.0f; @@ -208,8 +204,6 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) inSocket = 0; outSocket = 0; - hMainWindow = handle; - // // Create UDP-sockets. // @@ -238,7 +232,7 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "FlightGear"); + sprintf(dest, "FlightGear"); return; } @@ -249,9 +243,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Protocol; + return (IProtocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.h b/ftnoir_protocol_fg/ftnoir_protocol_fg.h index 34773540..4ff2846f 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.h +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.h @@ -29,17 +29,17 @@ #ifndef INCLUDED_FGSERVER_H #define INCLUDED_FGSERVER_H -#include "..\ftnoir_protocol_base\ftnoir_protocol_base.h" -#include "ui_FTNoIR_FGcontrols.h" -#include "FGTypes.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ui_ftnoir_fgcontrols.h" +#include "fgtypes.h" #include #include #include #include -#include "Windows.h" -#include "math.h" +#include +#include "facetracknoir/global-settings.h" -static const char* FT_PROGRAMID = "FT_ProgramID"; // For message to FaceTrackNoIR main-window. +#define FT_PROGRAMID "FT_ProgramID" class FTNoIR_Protocol : public IProtocol { @@ -50,14 +50,13 @@ public: void Release(); void Initialize(); - bool checkServerInstallationOK( HANDLE handle ); + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... private: bool blnConnectionActive; - HANDLE hMainWindow; // Save the handle to FaceTrackNoIR main-window // Tracker *headTracker; // For upstream messages... TFlightGearData FlightData; @@ -81,7 +80,6 @@ public: virtual ~FGControls(); void showEvent ( QShowEvent * event ); - void Release(); // Member functions which are accessible from outside the DLL void Initialize(QWidget *parent); void registerProtocol(IProtocol *protocol) { theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol @@ -109,7 +107,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); @@ -119,7 +117,7 @@ public: void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear"); }; void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear UDP protocol"); }; - void getIcon(QIcon *icon) { *icon = QIcon(":/images/FlightGear.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/flightgear.png"); }; }; diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp index 0138a4c1..9867ea2f 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp @@ -33,6 +33,7 @@ */ #include "ftnoir_protocol_fg.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -74,11 +75,6 @@ FGControls::~FGControls() { qDebug() << "~FGControls() says: started"; } -void FGControls::Release() -{ - delete this; -} - // // Initialize tracker-client-dialog // @@ -217,9 +213,9 @@ void FGControls::chkLocalPCOnlyChanged() { // GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") +//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new FGControls; -} \ No newline at end of file + return (IProtocolDialog*) new FGControls; +} diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp index ca71063b..45d6271c 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_fg.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -48,9 +49,9 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") +//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { - return new FTNoIR_ProtocolDll; + return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_fg/images/flightgear.ico b/ftnoir_protocol_fg/images/flightgear.ico new file mode 100644 index 00000000..f96c0f88 Binary files /dev/null and b/ftnoir_protocol_fg/images/flightgear.ico differ diff --git a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui b/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui index b6120378..d02297f3 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui +++ b/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp index 5a4663a1..c750ae26 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp @@ -3,7 +3,7 @@ * gamers from Holland, who don't like to pay much for * * head-tracking. * * * -* Copyright (C) 2010-2013 Wim Vriend (Developing) * +* Copyright (C) 2010-2011 Wim Vriend (Developing) * * Ron Hendriks (Researching and Testing) * * * * Homepage * @@ -31,6 +31,7 @@ is called from run() of Tracker.cpp */ #include "ftnoir_protocol_fsuipc.h" +#include "facetracknoir/global-settings.h" /** constructor **/ FTNoIR_Protocol::FTNoIR_Protocol() @@ -38,9 +39,6 @@ FTNoIR_Protocol::FTNoIR_Protocol() loadSettings(); ProgramName = "Microsoft FS2004"; - blnConnectionActive = false; - hMainWindow = NULL; - prevPosX = 0.0f; prevPosY = 0.0f; prevPosZ = 0.0f; @@ -121,8 +119,6 @@ float virtRotX; float virtRotY; float virtRotZ; -PDWORD_PTR MsgResult = 0; - // qDebug() << "FSUIPCServer::run() says: started!"; virtRotX = -1.0f * headpose->pitch; // degrees @@ -178,14 +174,6 @@ PDWORD_PTR MsgResult = 0; if (result == FSUIPC_ERR_SENDMSG) { FSUIPC_Close(); //timeout (1 second) so assume FS closed } - - if (!blnConnectionActive) { - blnConnectionActive = true; - if (hMainWindow != NULL) { - SendMessageTimeout( (HWND) hMainWindow, RegisterWindowMessageA(FT_PROGRAMID), 0, 0, 0, 2000, MsgResult); - } - } - } } @@ -200,11 +188,21 @@ PDWORD_PTR MsgResult = 0; // // Returns 'true' if all seems OK. // -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { qDebug() << "checkServerInstallationOK says: Starting Function"; - hMainWindow = handle; + // + // Load the DLL. + // + FSUIPCLib.setFileName( LocationOfDLL ); + if (FSUIPCLib.load() != true) { + qDebug() << "checkServerInstallationOK says: Error loading FSUIPC DLL"; + return false; + } + else { + qDebug() << "checkServerInstallationOK says: FSUIPC DLL loaded."; + } return true; } @@ -214,7 +212,7 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "Microsoft FS2002/2004"); + sprintf_s(dest, 99, "FS2002/2004"); return; } @@ -225,9 +223,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor(void) { - return new FTNoIR_Protocol; + return (FTNoIR_Protocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h index 8503f6e7..84d5d180 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h @@ -31,6 +31,7 @@ #include "Windows.h" #include #include "FSUIPC_User.h" +#include "facetracknoir/global-settings.h" #include "..\ftnoir_protocol_base\ftnoir_protocol_base.h" #include "ui_FTNoIR_FSUIPCcontrols.h" @@ -43,7 +44,6 @@ #include static const char* FSUIPC_FILENAME = "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll"; -static const char* FT_PROGRAMID = "FT_ProgramID"; // For message to FaceTrackNoIR main-window. // // Define the structures necessary for the FSUIPC_Write calls @@ -65,7 +65,7 @@ public: void Release(); void Initialize(); - bool checkServerInstallationOK( HANDLE handle ); + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... @@ -76,9 +76,6 @@ private: QString LocationOfDLL; float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ; - bool blnConnectionActive; - HANDLE hMainWindow; // Save the handle to FaceTrackNoIR main-window - static int scale2AnalogLimits( float x, float min_x, float max_x ); void loadSettings(); }; @@ -121,7 +118,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); @@ -131,7 +128,7 @@ public: void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FSUIPC"); }; void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft FS2004 protocol"); }; - void getIcon(QIcon *icon) { *icon = QIcon(":/images/FS9.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/FS9.png"); }; }; diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp index 08c13c08..eca04985 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp @@ -31,6 +31,7 @@ The functions to get the name(s) and icon were removed from the two other classes. */ #include "ftnoir_protocol_fsuipc.h" +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -189,9 +190,9 @@ void FSUIPCControls::getLocationOfDLL() // GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") +//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog(void) { - return new FSUIPCControls; + return (IProtocolDialog*) new FSUIPCControls; } diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp index d61c2d83..72d99fb9 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_fsuipc.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -48,9 +49,9 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") +//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata(void) { return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_fsuipc/images/fs9.ico b/ftnoir_protocol_fsuipc/images/fs9.ico new file mode 100644 index 00000000..9afd1953 Binary files /dev/null and b/ftnoir_protocol_fsuipc/images/fs9.ico differ diff --git a/ftnoir_protocol_ft/FreeTrackClient.c b/ftnoir_protocol_ft/FreeTrackClient.c new file mode 100644 index 00000000..b1b62123 --- /dev/null +++ b/ftnoir_protocol_ft/FreeTrackClient.c @@ -0,0 +1,330 @@ +/******************************************************************************** +* FreeTrackClientDll Implements the FreeTrack 2.0 interface for FT-enabled * +* games. * +* It uses the FreeTrack protocol (memory mapping) to * +* receive data from FaceTrackNoIR (or FreeTrack, or ...). * +* * +* Copyright (C) 2013 Wim Vriend (Developing) * +* Ron Hendriks (Testing and Research) * +* * +* Homepage * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +* * +********************************************************************************/ +/* + Modifications (last one on top): + + 20130208 - WVR: The old DLL from FreeTrack seems to crash ArmA2. And we need 64-bit support. + +*/ + +/* + * COMPILE WITH: + * % i686-w64-mingw32-gcc -shared -o FreeTrackClient.dll -O2 FreeTrackClient.c + * DO NOT USE MSVC! IT INTRODUCES FAULTY MANIFEST!!! + * -- sthalik + */ + +#ifdef WIN64 +#pragma comment(linker, "/export:FTGetData") +#pragma comment(linker, "/export:FTReportName") +#pragma comment(linker, "/export:FTGetDllVersion") +#pragma comment(linker, "/export:FTProvider") +#endif + +#define FT_DECLSPEC __declspec(dllexport) + +#define FT_EXPORT(t) FT_DECLSPEC t __stdcall +#define NP_AXIS_MAX 16383 + +#include +#include +#include +#include +#include +#include + +typedef struct TFreeTrackData { + int DataID; + int CamWidth; + int CamHeight; + // virtual pose + float Yaw; // positive yaw to the left + float Pitch; // positive pitch up + float Roll; // positive roll to the left + float X; + float Y; + float Z; + // raw pose with no smoothing, sensitivity, response curve etc. + float RawYaw; + float RawPitch; + float RawRoll; + float RawX; + float RawY; + float RawZ; + // raw points, sorted by Y, origin top left corner + float X1; + float Y1; + float X2; + float Y2; + float X3; + float Y3; + float X4; + float Y4; +} TFreeTrackData; +typedef TFreeTrackData * PFreetrackData; + +// +// Functions to create/open the file-mapping +// and to destroy it again. +// +float scale2AnalogLimits( float x, float min_x, float max_x ); +float getDegreesFromRads ( float rads ); +FT_EXPORT(BOOL) FTCreateMapping(void); + +#if 0 +static FILE *debug_stream; +#define dbg_report(...) if (debug_stream) { fprintf(debug_stream, __VA_ARGS__); fflush(debug_stream); } +#else +#define dbg_report(...) +#endif + +// +// Handles to 'handle' the memory mapping +// +#define FT_MM_DATA "FT_SharedMem" +#define FREETRACK_MUTEX "FT_Mutext" + +static HANDLE hFTMemMap = 0; +static TFreeTrackData *pMemData = 0; +static HANDLE hFTMutex = 0; +static const char* dllVersion = "1.0.0.0"; +static const char* dllProvider = "FreeTrack"; + +static unsigned short gameid = 0; + +// +// DllMain gets called, when the DLL is (un)loaded or a process attaches. +// +FT_EXPORT(BOOL) WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: +#ifdef WIN64 + dbg_report("\n= WIN64 =========================================================================================\n"); +#else + dbg_report("\n= WIN32 =========================================================================================\n"); +#endif + dbg_report("DllMain: (0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + dbg_report("DllMain: Attach request\n"); +// debug_stream = fopen("c:\\FreeTrackClient.log", "a"); + DisableThreadLibraryCalls(hinstDLL); + break; + + case DLL_PROCESS_DETACH: + dbg_report("DllMain: Detach\n"); + dbg_report("DllMain: (0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + dbg_report("==========================================================================================\n"); + break; + } + return TRUE; +} + +/****************************************************************** + * FTGetData (FreeTrackClient.1) + */ +#pragma comment(linker, "/export:FTGetData@4=FTGetData") +FT_EXPORT(BOOL) FTGetData(TFreeTrackData* data) +{ + static int frame = 0; + static int prevDataID = 0; + static int dlyTrackingOff = 0; + static int tracking = 0; + +// dbg_report("NP_GetData called."); + if (FTCreateMapping() == FALSE) return FALSE; + + if (hFTMutex && WaitForSingleObject(hFTMutex, 5) == WAIT_OBJECT_0) { + if (pMemData) { + + // + // When FaceTrackNoIR does not update frames (any more), don't update the data. + // + if (prevDataID != pMemData->DataID) { + *data = *pMemData; + dlyTrackingOff = 0; + } + else { + dlyTrackingOff++; + if (dlyTrackingOff > 20) { + dlyTrackingOff = 100; + tracking = FALSE; + } + } + prevDataID = pMemData->DataID; + + // + // Limit the range of DataID + // + if (pMemData->DataID > 1000) { + pMemData->DataID = 0; + } + data->DataID = pMemData->DataID; + + // + // Send the ID to FaceTrackNoIR, so it can display the game-name. + // This could be a FreeTrack-specific ID + // + //sprintf(pMemData->GameID, "%d", gameid ); + + } + ReleaseMutex(hFTMutex); + } + return TRUE; +} + +/****************************************************************** + * FTReportName (FreeTrackClient.2) + */ +#pragma comment(linker, "/export:FTReportName@4=FTReportName") +// +// For some mysterious reason, the previously existing function FTReportID has been changed to FTReportName, but with an integer as argument. +// The Delphi-code from the FreeTrack repo suggest a char * as argument, so it cost me an afternoon to figure it out (and keep ArmA2 from crashing). +// Thanks guys! +// +FT_EXPORT(void) FTReportName( int name ) +{ + dbg_report("FTReportName request (ID = %d).\n", name); + gameid = name; // They might have really passed the name here... but they didn't! + return; +} + +/****************************************************************** + * FTGetDllVersion (FreeTrackClient.3) + */ +#pragma comment(linker, "/export:FTGetDllVersion@0=FTGetDllVersion") +FT_EXPORT(const char*) FTGetDllVersion(void) +{ + dbg_report("FTGetDllVersion request.\n"); + + return dllVersion; +} + +/****************************************************************** + * FTProvider (FreeTrackClient.4) + */ +#pragma comment(linker, "/export:FTProvider@0=FTProvider") +FT_EXPORT(const char*) FTProvider(void) +{ + dbg_report("FTProvider request.\n"); + + return dllProvider; +} + +// +// Create a memory-mapping to the Freetrack data. +// It contains the tracking data, a handle to the main-window and the program-name of the Game! +// +// +#pragma comment(linker, "/export:FTCreateMapping@0=FTCreateMapping") +FT_EXPORT(BOOL) FTCreateMapping(void) +{ + BOOL bMappingExists = FALSE; + PDWORD_PTR MsgResult = 0; + + // + // Memory-mapping already exists! + // + if ( pMemData != NULL ) { + return TRUE; + } + + dbg_report("FTCreateMapping request (pMemData == NULL).\n"); + + // + // A FileMapping is used to create 'shared memory' between the FTClient and the FTServer. + // + // Try to create a FileMapping to the Shared Memory. This is done to check if it's already there (what + // may mean the face-tracker program is already running). + // + // If one already exists: close it and open the file-mapping to the existing one. + // + hFTMemMap = CreateFileMappingA( INVALID_HANDLE_VALUE , 00 , PAGE_READWRITE , 0 , + sizeof( TFreeTrackData ), + (LPCSTR) FT_MM_DATA ); + + if ( ( hFTMemMap != 0 ) && ( GetLastError() == ERROR_ALREADY_EXISTS ) ) { + dbg_report("FTCreateMapping: Mapping already exists.\n"); + bMappingExists = TRUE; // So the server was (probably) already started! + CloseHandle( hFTMemMap ); + hFTMemMap = 0; + } + + // + // Create a new FileMapping, Read/Write access + // + hFTMemMap = OpenFileMappingA( FILE_MAP_ALL_ACCESS , FALSE , (LPCSTR) FT_MM_DATA ); + if ( ( hFTMemMap != 0 ) ) { + dbg_report("FTCreateMapping: Mapping opened.\n"); + pMemData = (TFreeTrackData *) MapViewOfFile(hFTMemMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof( TFreeTrackData ) ); + hFTMutex = CreateMutexA(NULL, FALSE, FREETRACK_MUTEX); + } + else { + return FALSE; + } + return TRUE; +} + +// +// Destory the FileMapping to the shared memory +// +#pragma comment(linker, "/export:FTDestroyMapping@0=FTDestroyMapping") +FT_EXPORT(void) FTDestroyMapping(void) +{ + if ( pMemData != NULL ) { + UnmapViewOfFile ( pMemData ); + } + + CloseHandle( hFTMutex ); + CloseHandle( hFTMemMap ); + pMemData = 0; + hFTMemMap = 0; +} + +// +// 4 convenience +// +float getDegreesFromRads ( float rads ) { + return (rads * 57.295781f); +} + +// +// Scale the measured value to the TIR values +// +float scale2AnalogLimits( float x, float min_x, float max_x ) { +double y; +double local_x; + + local_x = x; + if (local_x > max_x) { + local_x = max_x; + } + if (local_x < min_x) { + local_x = min_x; + } + y = ( NP_AXIS_MAX * local_x ) / max_x; + + return (float) y; +} diff --git a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui b/ftnoir_protocol_ft/ftnoir_ftcontrols.ui index fc5abbcf..34873c76 100644 --- a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui +++ b/ftnoir_protocol_ft/ftnoir_ftcontrols.ui @@ -6,22 +6,16 @@ 0 0 - 645 - 416 + 411 + 112 - - - 645 - 0 - - - FreeTrack 2.0 settings FaceTrackNoIR + FreeTrack settings FaceTrackNoIR - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/freetrack.pngimages/freetrack.png Qt::LeftToRight @@ -31,282 +25,7 @@ - - - - - - 0 - 70 - - - - TIRViews - - - - - 80 - 30 - 88 - 17 - - - - Qt::RightToLeft - - - Use TIRViews - - - - - - 189 - 10 - 421 - 16 - - - - TIRViews is only required for some older games (like CFS3). For it to work, TIRViews.dll - - - - - - 189 - 30 - 421 - 16 - - - - must be placed in the FaceTrackNoIR program folder. If the checkbox is disabled, the - - - true - - - - - - 189 - 50 - 411 - 16 - - - - the DLL was not found. You can get it from NaturalPoint. - - - - - - - - - 0 - 70 - - - - TrackIR.exe - - - - - 20 - 30 - 145 - 17 - - - - Qt::RightToLeft - - - Start dummy TrackIR.exe - - - - - - 189 - 10 - 351 - 16 - - - - Some programs check, to see if a process called TrackIR.exe is running, - - - - - - 189 - 30 - 261 - 16 - - - - before enabling head-tracking (EZCA is one of them). - - - true - - - - - - 189 - 50 - 231 - 16 - - - - Check the checkbox, to overcome this problem. - - - - - - - - - 0 - 70 - - - - Select interface - - - - - 189 - 10 - 351 - 16 - - - - Some games support both FreeTrack and TrackIR and may get confused, - - - - - - 189 - 30 - 261 - 16 - - - - when both interfaces are visible. - - - true - - - - - - 189 - 50 - 381 - 16 - - - - Try to disable one interface, if you experience problems. - - - - - - 6 - 30 - 168 - 22 - - - - - - - - - - 0 - 70 - - - - Repair NPClient location - - - - - 188 - 10 - 381 - 20 - - - - Users who use other software with an NPClient DLL (like TrackIR, FreeTrack or - - - - - - 184 - 30 - 411 - 20 - - - - GlovePIE) may need to repair the location of the DLL, after running FaceTrackNoIR. - - - true - - - - - - 187 - 50 - 391 - 20 - - - - Use this button to locate the desired NPClient DLL. - - - - - - 4 - 30 - 171 - 23 - - - - Locate DLL - - - - + @@ -335,6 +54,17 @@ + + + + + + There are no settings necessary for the FreeTrack protocol. + + + + + diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp index b8461993..1482d76c 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp @@ -3,7 +3,7 @@ * gamers from Holland, who don't like to pay much for * * head-tracking. * * * -* Copyright (C) 2013 Wim Vriend (Developing) * +* Copyright (C) 2010 Wim Vriend (Developing) * * Ron Hendriks (Researching and Testing) * * * * Homepage * @@ -26,10 +26,6 @@ ********************************************************************************/ /* Modifications (last one on top): - 20130209 - WVR: Some games support both interfaces and cause trouble. Added ComboBox to fix this (hide one interface - by clearing the appropriate Registry-setting). - 20130203 - WVR: Added Tirviews and dummy checkboxes to the Settings dialog. This is necessary for CFS3 etc. - 20130125 - WVR: Upgraded to FT2.0: now the FreeTrack protocol supports all TIR-enabled games. 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc. 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame is called from run() of Tracker.cpp @@ -39,154 +35,48 @@ Now it works direcly in shared memory! */ #include "ftnoir_protocol_ft.h" -#include "csv.h" +#include "facetracknoir/global-settings.h" /** constructor **/ FTNoIR_Protocol::FTNoIR_Protocol() { comhandle = 0; - useTIRViews = false; - useDummyExe = false; - intUsedInterface = 0; - - // - // Load the INI-settings. - // loadSettings(); - ProgramName = ""; - intGameID = 0; - - dummyTrackIR = 0; - viewsStart = 0; - viewsStop = 0; - } /** destructor **/ FTNoIR_Protocol::~FTNoIR_Protocol() { - - qDebug()<< "~FTNoIR_Protocol: Destructor started."; - // - // Stop if started - // - if (viewsStop != NULL) { - qDebug()<< "~FTNoIR_Protocol: Stopping TIRViews."; - viewsStop(); - FTIRViewsLib.unload(); - } - - // - // Kill the dummy TrackIR process. + // Destroy the File-mapping // - qDebug() << "~FTNoIR_Protocol() about to kill TrackIR.exe process"; - try { - if (dummyTrackIR) { - qDebug() << "FTServer::~FTServer() about to kill TrackIR.exe process"; -// dummyTrackIR->close(); - dummyTrackIR->kill(); - } - } - catch (...) - { - qDebug() << "~FTServer says: some error occurred"; - } + FTDestroyMapping(); // - // Destroy the File-mapping + // Free the DLL's // - FTDestroyMapping(); + //////FTClientLib.unload(); } -void FTNoIR_Protocol::Initialize() +/** helper to Auto-destruct **/ +void FTNoIR_Protocol::Release() { - return; + delete this; } -// -// Read the game-data from CSV -// -bool FTNoIR_Protocol::getGameData( QString gameID ){ -QStringList gameLine; - - qDebug() << "getGameData, ID = " << gameID; - - // - // Open the supported games list, to get the Name. - // - QFile file(QCoreApplication::applicationDirPath() + "/Settings/FaceTrackNoIR Supported Games.csv"); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){ - QString strError( "Cannot load file: FaceTrackNoIR Supported Games.csv" ); - sprintf_s(pMemData->ProgramName, 99, strError.toAscii()); - sprintf_s(pMemData->FTNVERSION, 9, "V160"); - - // - // Return true anyway, because maybe it's V160 compatible. - // - return true; - } - CSV csv(&file); - gameLine = csv.parseLine(); - - while (gameLine.count() > 2) { - //qDebug() << "Column 0: " << gameLine.at(0); // No. - //qDebug() << "Column 1: " << gameLine.at(1); // Game Name - //qDebug() << "Column 2: " << gameLine.at(2); // Game Protocol - //qDebug() << "Column 3: " << gameLine.at(3); // Supported since version - //qDebug() << "Column 4: " << gameLine.at(4); // Verified - //qDebug() << "Column 5: " << gameLine.at(5); // By - //qDebug() << "Column 6: " << gameLine.at(6); // International ID - //qDebug() << "Column 7: " << gameLine.at(7); // FaceTrackNoIR ID - - // - // If the gameID was found, fill the shared memory - // - if (gameLine.count() > 6) { - if (gameLine.at(6).compare( gameID, Qt::CaseInsensitive ) == 0) { - if (pMemData != NULL) { - sprintf_s(pMemData->ProgramName, 99, gameLine.at(1).toAscii()); - sprintf_s(pMemData->FTNVERSION, 9, gameLine.at(3).toAscii()); - sprintf_s(pMemData->FTNID, 24, gameLine.at(7).toAscii()); - } - file.close(); - return true; - } - } - - gameLine = csv.parseLine(); - } - - // - // If the gameID was NOT found, fill only the name "Unknown game connected" - // - QString strUnknown("Unknown game connected (ID = " + gameID + ")"); - sprintf_s(pMemData->ProgramName, 99, strUnknown.toAscii()); - file.close(); - return true; +void FTNoIR_Protocol::Initialize() +{ + QSettings settings("NaturalPoint", "NATURALPOINT\\NPClient Location"); + QString aLocation = QCoreApplication::applicationDirPath() + "/"; + if (QFile::exists( aLocation + "/npclient.dll" )) + settings.setValue( "Path" , aLocation ); } // // Load the current Settings from the currently 'active' INI-file. // void FTNoIR_Protocol::loadSettings() { - QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "FT" ); - intUsedInterface = iniFile.value ( "UsedInterface", 0 ).toInt(); - iniFile.endGroup (); - - // - // Use the settings-section from the deprecated fake-TIR protocol, as they are most likely to be found there. - // - iniFile.beginGroup ( "FTIR" ); - useTIRViews = iniFile.value ( "useTIRViews", 0 ).toBool(); - useDummyExe = iniFile.value ( "useDummyExe", 1 ).toBool(); - iniFile.endGroup (); } // @@ -209,10 +99,7 @@ float headRotX; float headRotY; float headRotZ; -PDWORD_PTR MsgResult = 0; - - - // + // // Scale the Raw measurements to the client measurements. // headRotX = getRadsFromDegrees(headpose->pitch); @@ -265,145 +152,82 @@ PDWORD_PTR MsgResult = 0; pMemData->data.Y3 = 0; pMemData->data.Y4 = 0; - // - // Check if the handle that was sent to the Game, was changed (on x64, this will be done by the ED-API) - // If the "Report Program Name" command arrives (which is a '1', for now), raise the event from here! - // - if (hMainWindow != pMemData->handle) { // Handle in memory-mapping was changed! - comhandle = (__int32) pMemData->handle; // Get the command from the Game. - if (comhandle == 1) { // "Report Program Name" - SendMessageTimeout( (HWND) hMainWindow, RegisterWindowMessageA(FT_PROGRAMID), 0, 0, 0, 2000, MsgResult); - pMemData->handle = 0; // Reset the command, to enable future commands... - } - } + //qDebug() << "FTServer says: pMemData.DataID =" << pMemData->data.DataID; + //qDebug() << "FTServer says: ProgramName =" << pMemData->ProgramName; // - // The game-ID was changed? - // - QString gameID = QString(pMemData->GameID); - //QString gameID = QString("9999"); - -// qDebug() << "sendHeadposeToGame: gameID = " << gameID; - if (gameID.length() > 0) { - if ( gameID.toInt() != intGameID ) { - if (getGameData( gameID ) ) { - SendMessageTimeout( (HWND) hMainWindow, RegisterWindowMessageA(FT_PROGRAMID), 0, 0, 0, 2000, MsgResult); - } - intGameID = gameID.toInt(); - } - } - else { - intGameID = 0; - pMemData->ProgramName[0] = NULL; - pMemData->FTNID[0] = NULL; - pMemData->FTNVERSION[0] = NULL; - } - ReleaseMutex(hFTMutex); } - pMemData->data.DataID += 1; + if (pMemData) + pMemData->data.DataID += 1; } // -// Set the Path variables and load the memory-mapping. -// Simplified function: No need to check if the DLL's actually exist. The are installed by the installer. -// If they are absent, something went terribly wrong anyway... -// +// Check if the Client DLL exists and load it (to test it), if so. // Returns 'true' if all seems OK. // -// -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { - QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER) - QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER) - QString aLocation; // Location of Client DLL + QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER) + QString aLocation; // Location of Client DLL + QString aFileName; // File Path and Name - qDebug() << "checkServerInstallationOK says: Starting Function"; + qDebug() << "FTCheckClientDLL says: Starting Function"; try { // - // Write the path in the registry (for FreeTrack and FreeTrack20), for the game(s). + // Load the FreeTrackClient.dll from the current path of FaceTrackNoIR, because there is no + // guarantee FreeTrack is also installed. + // + // Write this path in the registry (under FreeTrack/FreeTrackClient, for the game(s). // aLocation = QCoreApplication::applicationDirPath() + "/"; - - qDebug() << "checkServerInstallationOK says: used interface = " << intUsedInterface; - switch (intUsedInterface) { - case 0: // Use both interfaces - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , aLocation ); - break; - case 1: // Use FreeTrack, disable TrackIR - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , "" ); - break; - case 2: // Use TrackIR, disable FreeTrack - settings.setValue( "Path" , "" ); - settingsTIR.setValue( "Path" , aLocation ); - break; - default: - // should never be reached - break; - } + qDebug() << "FTCheckClientDLL says: Location of DLL =" << aLocation; // - // TIRViews must be started first, or the NPClient DLL will never be loaded. + // Append a '/' to the Path and then the name of the dll. // - if (useTIRViews) { - - QString aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll"; - if ( QFile::exists( aFileName ) ) { - - FTIRViewsLib.setFileName(aFileName); - FTIRViewsLib.load(); - - viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart"); - if (viewsStart == NULL) { - qDebug() << "FTServer::run() says: TIRViewsStart function not found in DLL!"; - } - else { - qDebug() << "FTServer::run() says: TIRViewsStart executed!"; - viewsStart(); - } - - // - // Load the Stop function from TIRViews.dll. Call it when terminating the thread. - // - viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop"); - if (viewsStop == NULL) { - qDebug() << "FTServer::run() says: TIRViewsStop function not found in DLL!"; - } - } + aFileName = aLocation; + aFileName.append(FT_CLIENT_FILENAME); + qDebug() << "FTCheckClientDLL says: Full path of DLL =" << aFileName; + + if ( QFile::exists( aFileName ) ) { + qDebug() << "FTCheckClientDLL says: DLL exists!"; + // + // Write the path to the key in the Registry, so the game(s) can find it too... + // + settings.setValue( "Path" , aLocation ); + + // + // Load the DLL and map to the functions in it. + // + ////////FTClientLib.setFileName(aFileName); + ////////FTClientLib.load(); + ////////provider = (importProvider) FTClientLib.resolve("FTProvider"); + ////////if (provider) { + //////// pProvider = provider(); + //////// qDebug() << "FTCheckClientDLL says: Provider =" << pProvider; + ////////} } - - // - // Check if TIRViews or dummy TrackIR.exe is required for this game - // - if (useDummyExe) { - QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe"; - dummyTrackIR = new QProcess(); - dummyTrackIR->start(program); - - qDebug() << "FTServer::run() says: TrackIR.exe executed!"; + else { + QMessageBox::information(0, "FaceTrackNoIR error", QString("Necessary file (FreeTrackClient.dll) was NOT found!\n")); + return false; } - - } catch(...) { settings.~QSettings(); } - return FTCreateMapping( handle ); + return FTCreateMapping(); } // -// Create a memory-mapping to the FreeTrack data. +// Create a memory-mapping to the TrackIR data. // It contains the tracking data, a handle to the main-window and the program-name of the Game! // // -bool FTNoIR_Protocol::FTCreateMapping( HANDLE handle ) +bool FTNoIR_Protocol::FTCreateMapping() { -bool bFirst = false; - qDebug() << "FTCreateMapping says: Starting Function"; // @@ -413,18 +237,14 @@ bool bFirst = false; // If one already exists: close it. // hFTMemMap = CreateFileMappingA( INVALID_HANDLE_VALUE , 00 , PAGE_READWRITE , 0 , -// sizeof( TFreeTrackData ) + sizeof( HANDLE ) + 100, - sizeof( FTMemMap ), + sizeof( TFreeTrackData ) + sizeof( HANDLE ) + 100, (LPCSTR) FT_MM_DATA ); if ( hFTMemMap != 0 ) { - bFirst = true; qDebug() << "FTCreateMapping says: FileMapping Created!" << hFTMemMap; } if ( ( hFTMemMap != 0 ) && ( (long) GetLastError == ERROR_ALREADY_EXISTS ) ) { - bFirst = false; - qDebug() << "FTCreateMapping says: FileMapping already exists!" << hFTMemMap; CloseHandle( hFTMemMap ); hFTMemMap = 0; } @@ -435,16 +255,7 @@ bool bFirst = false; hFTMemMap = OpenFileMappingA( FILE_MAP_ALL_ACCESS , false , (LPCSTR) FT_MM_DATA ); if ( ( hFTMemMap != 0 ) ) { qDebug() << "FTCreateMapping says: FileMapping Opened:" << hFTMemMap; - pMemData = (FTMemMap *) MapViewOfFile(hFTMemMap, FILE_MAP_ALL_ACCESS, 0, 0, -// sizeof(TFreeTrackData) + sizeof(hFTMemMap) + 100); - sizeof(FTMemMap)); - if (pMemData != NULL) { - if (bFirst) { - memset(pMemData, 0, sizeof(FTMemMap)); // Write zero's, if first... - } - pMemData->handle = handle; // The game uses the handle, to send a message that the Program-Name was set! - hMainWindow = handle; - } + pMemData = (FTMemMap *) MapViewOfFile(hFTMemMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TFreeTrackData) + sizeof(hFTMemMap) + 100); hFTMutex = CreateMutexA(NULL, false, FREETRACK_MUTEX); } else { @@ -481,7 +292,7 @@ void FTNoIR_Protocol::FTDestroyMapping() // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "FreeTrack interface"); + sprintf(dest, "FreeTrack interface"); qDebug() << "FTNoIR_Protocol::getNameFromGame says: Started, pMemData = " << pMemData << ", mutex = " << hFTMutex; @@ -491,7 +302,7 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) { if (pMemData != NULL) { qDebug() << "FTNoIR_Protocol::getNameFromGame says: Inside MemData"; - sprintf_s(dest, 99, "%s", pMemData->ProgramName); + sprintf(dest, "%s", pMemData->ProgramName); } return; @@ -505,9 +316,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Protocol; + return (IProtocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.h b/ftnoir_protocol_ft/ftnoir_protocol_ft.h index c82c3e79..690984a4 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.h +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.h @@ -28,21 +28,21 @@ #ifndef INCLUDED_FTSERVER_H #define INCLUDED_FTSERVER_H -#include "..\ftnoir_protocol_base\ftnoir_protocol_base.h" -#include "ui_FTNoIR_FTcontrols.h" -#include "FTTypes.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ui_ftnoir_ftcontrols.h" +#include "fttypes.h" #include #include #include #include #include #include -#include "Windows.h" +#include +// todo wine glue //#include "math.h" +#include "facetracknoir/global-settings.h" -//typedef char *(WINAPI *importProvider)(void); -typedef void (WINAPI *importTIRViewsStart)(void); -typedef void (WINAPI *importTIRViewsStop)(void); +typedef char *(WINAPI *importProvider)(void); class FTNoIR_Protocol : public IProtocol { @@ -53,35 +53,25 @@ public: void Release(); void Initialize(); - bool checkServerInstallationOK( HANDLE handle ); + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... private: - bool FTCreateMapping(HANDLE handle); + bool FTCreateMapping(); void FTDestroyMapping(); - importTIRViewsStart viewsStart; // Functions inside TIRViews.dll - importTIRViewsStop viewsStop; - HANDLE hFTMemMap; FTMemMap *pMemData; HANDLE hFTMutex; - HANDLE hMainWindow; // Save the handle to FaceTrackNoIR main-window __int32 comhandle; // Handle on x32, command on x64 // Private properties QString ProgramName; - QLibrary FTIRViewsLib; - QProcess *dummyTrackIR; - int intGameID; - int intUsedInterface; // Determine which interface to use (or to hide from the game) - bool useTIRViews; // Needs to be in the Settings dialog - bool useDummyExe; + QLibrary FTClientLib; float getRadsFromDegrees ( float degrees ) { return (degrees * 0.017453f); } - bool getGameData( QString gameID ); void loadSettings(); }; @@ -115,27 +105,25 @@ private: FTNoIR_Protocol *theProtocol; private slots: - void selectDLL(); void doOK(); void doCancel(); void settingChanged() { settingsDirty = true; }; - void settingChanged(int) { settingsDirty = true; }; }; //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); ~FTNoIR_ProtocolDll(); - void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }; - void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }; - void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Enhanced FreeTrack protocol"); }; + void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack"); }; + void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack"); }; + void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack protocol"); }; - void getIcon(QIcon *icon) { *icon = QIcon(":/images/Freetrack.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/freetrack.png"); }; }; diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp index 2e6c91f7..46dd263f 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp @@ -32,7 +32,7 @@ */ #include "ftnoir_protocol_ft.h" #include -#include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -51,36 +51,12 @@ QWidget() // Connect Qt signals to member-functions connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); - connect(ui.bntLocateNPClient, SIGNAL(clicked()), this, SLOT(selectDLL())); - connect(ui.chkTIRViews, SIGNAL(stateChanged(int)), this, SLOT(settingChanged())); - connect(ui.chkStartDummy, SIGNAL(stateChanged(int)), this, SLOT(settingChanged())); - connect(ui.cbxSelectInterface, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged( int ))); - - ui.cbxSelectInterface->addItem("Enable both"); - ui.cbxSelectInterface->addItem("Use FreeTrack, hide TrackIR"); - ui.cbxSelectInterface->addItem("Use TrackIR, hide FreeTrack"); +// connect(ui.chkTIRViews, SIGNAL(stateChanged(int)), this, SLOT(chkTIRViewsChanged())); theProtocol = NULL; // Load the settings from the current .INI-file loadSettings(); - - - aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll"; - if ( !QFile::exists( aFileName ) ) { - ui.chkTIRViews->setChecked( false ); - ui.chkTIRViews->setEnabled ( false ); - - // - // Best do this save() last, or it will continually reset the settings... :-( - // - save(); - } - else { - ui.chkTIRViews->setEnabled ( true ); - } - - } // @@ -90,6 +66,11 @@ FTControls::~FTControls() { qDebug() << "~FTControls() says: started"; } +void FTControls::Release() +{ + delete this; +} + // // Initialize tracker-client-dialog // @@ -161,12 +142,7 @@ void FTControls::loadSettings() { qDebug() << "loadSettings says: iniFile = " << currentFile; iniFile.beginGroup ( "FT" ); - ui.cbxSelectInterface->setCurrentIndex( iniFile.value ( "UsedInterface", 0 ).toInt() ); - iniFile.endGroup (); - - iniFile.beginGroup ( "FTIR" ); - ui.chkTIRViews->setChecked (iniFile.value ( "useTIRViews", 0 ).toBool()); - ui.chkStartDummy->setChecked (iniFile.value ( "useDummyExe", 1 ).toBool()); +// ui.chkTIRViews->setChecked (iniFile.value ( "useTIRViews", 0 ).toBool()); iniFile.endGroup (); settingsDirty = false; @@ -182,44 +158,12 @@ void FTControls::save() { QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) iniFile.beginGroup ( "FT" ); - iniFile.setValue ( "UsedInterface", ui.cbxSelectInterface->currentIndex()); - iniFile.endGroup (); - - iniFile.beginGroup ( "FTIR" ); - iniFile.setValue ( "useTIRViews", ui.chkTIRViews->isChecked() ); - iniFile.setValue ( "useDummyExe", ui.chkStartDummy->isChecked() ); +// iniFile.setValue ( "useTIRViews", ui.chkTIRViews->isChecked() ); iniFile.endGroup (); settingsDirty = false; } -// -// Select a NPClient.dll file, to repair the Location in the Registry. -// Several program distribute their own version of this file. -// -void FTControls::selectDLL() { - QFileDialog::Options options; - QFileDialog::FileMode mode; - - options |= QFileDialog::DontUseNativeDialog; - mode = QFileDialog::ExistingFile; - QString selectedFilter; - QString fileName = QFileDialog::getOpenFileName( this, tr("Select the desired NPClient DLL"), QCoreApplication::applicationDirPath() + "/NPClient.dll", tr("Dll file (*.dll);;All Files (*)")); - - // - // Write the location of the file in the required Registry-key. - // - if (! fileName.isEmpty() ) { - if (fileName.endsWith("NPClient.dll", Qt::CaseInsensitive) ) { - QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER) - QString aLocation = fileName.left(fileName.length() - 12); // Location of Client DLL - - settingsTIR.setValue( "Path" , aLocation ); - } - } -} - - //////////////////////////////////////////////////////////////////////////////// // Factory function that creates instances if the Protocol-settings dialog object. @@ -227,9 +171,9 @@ void FTControls::selectDLL() { // GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") +//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new FTControls; + return (IProtocolDialog*) new FTControls; } diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp index 4513c6ba..1209e38b 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_ft.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -48,9 +49,9 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") +//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { - return new FTNoIR_ProtocolDll; + return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_ft/fttypes.h b/ftnoir_protocol_ft/fttypes.h index 1f389711..3f411cfe 100644 --- a/ftnoir_protocol_ft/fttypes.h +++ b/ftnoir_protocol_ft/fttypes.h @@ -4,7 +4,7 @@ * It was loosely translated from FTTypes.pas * * which was created by the FreeTrack-team. * * * -* Copyright (C) 2013 Wim Vriend (Developing) * +* Copyright (C) 2010 Wim Vriend (Developing) * * Ron Hendriks (Testing and Research) * * * * Homepage * @@ -25,26 +25,23 @@ * We would like to extend our grattitude to the creators of SweetSpotter, * * which has become the basis of this program: "Great work guys!" * ********************************************************************************/ -/* - Modifications (last one on top): - 20130125 - WVR: Upgraded to FT2.0: now the FreeTrack protocol supports all TIR-enabled games. The memory-mapping was expanded for this purpose. -*/ #pragma once #ifndef INCLUDED_FTTYPES_H #define INCLUDED_FTTYPES_H -#include "Windows.h" +#include #include #include //#include "Registry.h" // static const char* FT_CLIENT_LOCATION = "Software\\Freetrack\\FreetrackClient"; - static const char* FT_CLIENT_FILENAME = "FreeTrackClient.Dll"; - static const char* FT_MM_DATA = "FT_SharedMem"; - static const char* FREETRACK = "Freetrack"; - static const char* FREETRACK_MUTEX = "FT_Mutext"; - static const char* FT_PROGRAMID = "FT_ProgramID"; + +#define FT_CLIENT_FILENAME "FreeTrackClient.Dll" +#define FT_MM_DATA "FT_SharedMem" +#define FREETRACK "Freetrack" +#define FREETRACK_MUTEX "FT_Mutext" +#define FT_PROGRAMID "FT_ProgramID" struct TFreeTrackData { @@ -85,20 +82,10 @@ struct FTMemMap { #else HANDLE handle; #endif - char ProgramName[100]; // The name of the game - char GameID[10]; // The international game-ID - char FTNID[30]; // The FaceTrackNoIR game-ID - char FTNVERSION[10]; // The version of FaceTrackNoIR, in which the game was first supported + char ProgramName[100]; }; typedef FTMemMap * PFTMemMap; -//extern bool (*FTGetData) (PFreetrackData data); -// DLL function signatures -// These match those given in FTTypes.pas -// WINAPI is macro for __stdcall defined somewhere in the depths of windows.h -typedef bool (WINAPI *importGetData)(TFreeTrackData * data); -typedef char *(WINAPI *importGetDllVersion)(void); -typedef void (WINAPI *importReportID)(int name); -typedef char *(WINAPI *importProvider)(void); +extern bool (*FTGetData) (PFreetrackData data); #endif//INCLUDED_FTTYPES_H diff --git a/ftnoir_protocol_ft/images/freetrack.ico b/ftnoir_protocol_ft/images/freetrack.ico new file mode 100644 index 00000000..02554c3d Binary files /dev/null and b/ftnoir_protocol_ft/images/freetrack.ico differ diff --git a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui b/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui index 56983fbe..d8efec61 100644 --- a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui +++ b/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui @@ -15,7 +15,7 @@
- images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/facetracknoir.png Qt::LeftToRight diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp index cfb6c618..26f331b3 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp @@ -33,36 +33,27 @@ */ #include "ftnoir_protocol_ftn.h" #include +#include "facetracknoir/global-settings.h" /** constructor **/ FTNoIR_Protocol::FTNoIR_Protocol() { loadSettings(); + outSocket = 0; } /** destructor **/ FTNoIR_Protocol::~FTNoIR_Protocol() { - if (inSocket != 0) { - inSocket->close(); - delete inSocket; - } - if (outSocket != 0) { outSocket->close(); delete outSocket; } } -/** helper to Auto-destruct **/ -void FTNoIR_Protocol::Release() -{ - delete this; -} - void FTNoIR_Protocol::Initialize() { - return; + loadSettings(); } // @@ -88,15 +79,13 @@ void FTNoIR_Protocol::loadSettings() { // void FTNoIR_Protocol::sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ) { int no_bytes; -QHostAddress sender; -quint16 senderPort; +THeadPoseData TestData; // // Copy the Raw measurements directly to the client. // - frame_counter += 1; TestData = *headpose; - TestData.frame_number = frame_counter; + TestData.frame_number = 0; // // Try to send an UDP-message to the receiver @@ -112,63 +101,14 @@ quint16 senderPort; qDebug() << "FTNServer::writePendingDatagrams says: nothing sent!"; } } - - // - // Receiver may send data, so we must read that here. - // - if (inSocket != 0) { - while (inSocket->hasPendingDatagrams()) { - - QByteArray datagram; - datagram.resize(inSocket->pendingDatagramSize()); - - inSocket->readDatagram( (char * ) &cmd, sizeof(cmd), &sender, &senderPort); - - fg_cmd = cmd; // Let's just accept that command for now... - if ( cmd > 0 ) { - qDebug() << "FTNServer::sendHeadposeToGame hasPendingDatagrams, cmd = " << cmd; -// headTracker->handleGameCommand ( cmd ); // Send it upstream, for the Tracker to handle - } - } - } } // // Check if the Client DLL exists and load it (to test it), if so. // Returns 'true' if all seems OK. // -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { - // Init. the data - TestData.x = 0.0f; - TestData.y = 0.0f; - TestData.z = 0.0f; - TestData.yaw = 0.0f; - TestData.pitch = 0.0f; - TestData.roll = 0.0f; - fg_cmd = 1; - - inSocket = 0; - outSocket = 0; - - frame_counter = 0; - - // - // Create UDP-sockets. - // - if (inSocket == 0) { - qDebug() << "FGServer::sendHeadposeToGame creating insocket"; - inSocket = new QUdpSocket(); - - // Connect the inSocket to the port, to receive messages - if (!inSocket->bind(QHostAddress::Any, destPort+1, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton); - delete inSocket; - inSocket = 0; - return false; - } - } - if (outSocket == 0) { outSocket = new QUdpSocket(); } @@ -181,7 +121,7 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "FaceTrackNoIR"); + sprintf(dest, "FaceTrackNoIR UDP"); return; } @@ -192,9 +132,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Protocol; + return (IProtocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h index 24f760c5..7dca6842 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h @@ -29,15 +29,15 @@ #ifndef INCLUDED_FTNSERVER_H #define INCLUDED_FTNSERVER_H -#include "..\ftnoir_protocol_base\ftnoir_protocol_base.h" -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" -#include "ui_FTNoIR_FTNcontrols.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ui_ftnoir_ftncontrols.h" #include #include #include #include -#include "Windows.h" -#include "math.h" +#include +#include "facetracknoir/global-settings.h" class FTNoIR_Protocol : public IProtocol { @@ -45,24 +45,17 @@ public: FTNoIR_Protocol(); ~FTNoIR_Protocol(); - void Release(); void Initialize(); - bool checkServerInstallationOK( HANDLE handle ); + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... private: - THeadPoseData TestData; - long frame_counter; - QUdpSocket *inSocket; // Receive from FaceTrackNoIR QUdpSocket *outSocket; // Send to FaceTrackNoIR - qint32 cmd; - qint32 fg_cmd; // Command from FlightGear QHostAddress destIP; // Destination IP-address int destPort; // Destination port-number void loadSettings(); - }; // Widget that has controls for FTNoIR protocol client-settings. @@ -77,12 +70,8 @@ public: void Release(); // Member functions which are accessible from outside the DLL void Initialize(QWidget *parent); - void registerProtocol(IProtocol *protocol) { - theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol - }; - void unRegisterProtocol() { - theProtocol = NULL; // Reset the pointer - }; + void registerProtocol(IProtocol *protocol) {} + void unRegisterProtocol() {} private: Ui::UICFTNControls ui; @@ -91,28 +80,27 @@ private: /** helper **/ bool settingsDirty; - FTNoIR_Protocol *theProtocol; private slots: void doOK(); void doCancel(); - void settingChanged() { settingsDirty = true; }; + void settingChanged() { settingsDirty = true; } }; //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); ~FTNoIR_ProtocolDll(); - void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR"); }; - void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FTN Client"); }; - void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR Client protocol"); }; + void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR"); } + void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FTN Client"); } + void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR Client protocol"); } - void getIcon(QIcon *icon) { *icon = QIcon(":/images/FaceTrackNoIR.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/facetracknoir.png"); } }; #endif//INCLUDED_FTNSERVER_H diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp index 58dbfbad..24ccc8b9 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_ftn.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -59,8 +60,6 @@ QWidget() connect(ui.spinIPFourthNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); connect(ui.spinPortNumber, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); - theProtocol = NULL; - // Load the settings from the current .INI-file loadSettings(); } @@ -186,9 +185,9 @@ void FTNControls::save() { // GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") +//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new FTNControls; + return (IProtocolDialog*) new FTNControls; } diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp index 00badedf..61f06914 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_ftn.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -48,9 +49,9 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") +//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_ftn/images/facetracknoir.ico b/ftnoir_protocol_ftn/images/facetracknoir.ico new file mode 100644 index 00000000..5115066c Binary files /dev/null and b/ftnoir_protocol_ftn/images/facetracknoir.ico differ diff --git a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui b/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui index 4a6cc3b9..1a7712f2 100644 --- a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui +++ b/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui @@ -15,7 +15,7 @@ - :/images/Mouse.ico:/images/Mouse.ico + :/images/Mouse.png:/images/Mouse.png Qt::LeftToRight diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp index f81a38f7..953482a5 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp @@ -33,6 +33,7 @@ is called from run() of Tracker.cpp */ #include "ftnoir_protocol_mouse.h" +#include "facetracknoir/global-settings.h" /** constructor **/ FTNoIR_Protocol::FTNoIR_Protocol() @@ -106,9 +107,9 @@ void FTNoIR_Protocol::loadSettings() { // Update Headpose in Game. // void FTNoIR_Protocol::sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ) { -float fMouse_X; // The actual value -float fMouse_Y; -float fMouse_Wheel; +float fMouse_X = 0; // The actual value +float fMouse_Y = 0; +float fMouse_Wheel = 0; // @@ -213,39 +214,6 @@ float fMouse_Wheel; break; } - // - // Determine which style is used. - // - SecureZeroMemory(&MouseStruct, sizeof(MouseStruct)); - MouseStruct.type = INPUT_MOUSE; - switch (Mouse_Style) { - case FTN_ABSOLUTE: - MouseStruct.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_WHEEL | MOUSEEVENTF_ABSOLUTE; - if (useVirtualDesk) { - MouseStruct.mi.dwFlags |= MOUSEEVENTF_VIRTUALDESK; - } - MouseStruct.mi.dx = scale2AnalogLimits(-1.0f * fMouse_X * mouse_X_factor, -150, 150); - MouseStruct.mi.dy = scale2AnalogLimits(fMouse_Y * mouse_Y_factor, -150, 150); - MouseStruct.mi.mouseData = mouse_Wheel_factor * (fMouse_Wheel - prev_fMouse_Wheel); - - frame_delay = 9999; // Seems no problem with Absolute positioning - break; - - case FTN_RELATIVE: - MouseStruct.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_WHEEL; - MouseStruct.mi.dx = -1.0f * mouse_X_factor * (fMouse_X - prev_fMouse_X); - MouseStruct.mi.dy = mouse_Y_factor * (fMouse_Y - prev_fMouse_Y); - MouseStruct.mi.mouseData = - 1.0f * mouse_Wheel_factor * (fMouse_Wheel - prev_fMouse_Wheel); - - frame_delay += 1; // Add 1 to the counter - qDebug() << "sendHeadposeToGame(): FTN_RELATIVE x = " << MouseStruct.mi.dx << ", y = " << MouseStruct.mi.dy; - break; - - default: - Mouse_Style = FTN_ABSOLUTE; // Force to a valid value... - break; - } - // // Only send Input, when it has changed. // This releases the Mouse, when tracking is stopped (for a while). @@ -264,7 +232,7 @@ float fMouse_Wheel; // // Returns 'true' if all seems OK. // -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { return true; @@ -275,7 +243,7 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "Mouse"); + sprintf(dest, "Mouse"); return; } @@ -286,9 +254,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Protocol; + return (IProtocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h index b7765b96..e4bc6256 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h @@ -30,17 +30,17 @@ #ifndef INCLUDED_MOUSESERVER_H #define INCLUDED_MOUSESERVER_H -//#include -#include "..\ftnoir_protocol_base\ftnoir_protocol_base.h" -#include "ui_FTNoIR_MOUSEcontrols.h" +#include "ftnoir_protocol_base/ftnoir_protocol_base.h" +#include "ui_ftnoir_mousecontrols.h" #include #include #include #include #include #include - -#include "winable.h" +#include +#include +#include "facetracknoir/global-settings.h" #define MOUSE_AXIS_MIN 0 #define MOUSE_AXIS_MAX 65535 @@ -69,7 +69,7 @@ public: void Release(); void Initialize(); - bool checkServerInstallationOK( HANDLE handle ); + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... @@ -133,7 +133,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); @@ -143,7 +143,7 @@ public: void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look"); }; void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look protocol"); }; - void getIcon(QIcon *icon) { *icon = QIcon(":/images/Mouse.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/mouse.png"); }; }; diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp index b8d7d7ee..263be205 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp @@ -30,8 +30,9 @@ The ProtocolDll class solves this. The functions to get the name(s) and icon were removed from the two other classes. */ -#include "ftnoir_protocol_MOUSE.h" +#include "ftnoir_protocol_mouse.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -227,9 +228,9 @@ void MOUSEControls::save() { // GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") +//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new MOUSEControls; + return (IProtocolDialog*) new MOUSEControls; } diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp index cc6ddc17..219f62af 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp @@ -30,8 +30,9 @@ The ProtocolDll class solves this. The functions to get the name(s) and icon were removed from the two other classes. */ -#include "ftnoir_protocol_MOUSE.h" +#include "ftnoir_protocol_mouse.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -48,9 +49,9 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") +//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_mouse/images/mouse.ico b/ftnoir_protocol_mouse/images/mouse.ico new file mode 100644 index 00000000..1151ab2b Binary files /dev/null and b/ftnoir_protocol_mouse/images/mouse.ico differ diff --git a/ftnoir_protocol_sc/ftnoir-protocol-sc.rc b/ftnoir_protocol_sc/ftnoir-protocol-sc.rc new file mode 100644 index 00000000..3838d941 --- /dev/null +++ b/ftnoir_protocol_sc/ftnoir-protocol-sc.rc @@ -0,0 +1,2 @@ +#include "winuser.h" +2 RT_MANIFEST scserver.manifest \ No newline at end of file diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp index 7ca38e64..c01096bf 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp @@ -33,6 +33,7 @@ is called from run() of Tracker.cpp */ #include "ftnoir_protocol_sc.h" +#include "facetracknoir/global-settings.h" importSimConnect_CameraSetRelative6DOF FTNoIR_Protocol::simconnect_set6DOF; HANDLE FTNoIR_Protocol::hSimConnect = 0; // Handle to SimConnect @@ -59,7 +60,6 @@ FTNoIR_Protocol::FTNoIR_Protocol() ProgramName = "Microsoft FSX"; blnSimConnectActive = false; hSimConnect = 0; - hMainWindow = 0; } /** destructor **/ @@ -76,17 +76,6 @@ FTNoIR_Protocol::~FTNoIR_Protocol() // SCClientLib.unload(); Generates crash when tracker is ended... } -/** helper to Auto-destruct **/ -void FTNoIR_Protocol::Release() -{ - delete this; -} - -void FTNoIR_Protocol::Initialize() -{ - return; -} - // // Load the current Settings from the currently 'active' INI-file. // @@ -101,7 +90,7 @@ void FTNoIR_Protocol::sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData PDWORD_PTR MsgResult = 0; - virtSCRotX = -1.0f * headpose->pitch; // degrees + virtSCRotX = -1.0f * headpose->pitch; // degrees virtSCRotY = -1.0f * headpose->yaw; virtSCRotZ = headpose->roll; @@ -113,25 +102,22 @@ PDWORD_PTR MsgResult = 0; // It's only useful to send data, if the connection was made. // if (!blnSimConnectActive) { - if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) { - qDebug() << "FTNoIR_Protocol::sendHeadposeToGame() says: SimConnect active!"; + if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) { + qDebug() << "FTNoIR_Protocol::sendHeadposeToGame() says: SimConnect active!"; - //set up the events we want to listen for - HRESULT hr; + //set up the events we want to listen for + HRESULT hr; - simconnect_subscribetosystemevent(hSimConnect, EVENT_PING, "Frame"); + simconnect_subscribetosystemevent(hSimConnect, EVENT_PING, "Frame"); - hr = simconnect_mapclienteventtosimevent(hSimConnect, EVENT_INIT, ""); - hr = simconnect_addclienteventtonotificationgroup(hSimConnect, GROUP0, EVENT_INIT, false); - hr = simconnect_setnotificationgrouppriority(hSimConnect, GROUP0, SIMCONNECT_GROUP_PRIORITY_HIGHEST); - ////hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT0, "VK_COMMA", EVENT_INIT); - ////hr = SimConnect_SetInputGroupState(hSimConnect, INPUT0, SIMCONNECT_STATE_ON); + hr = simconnect_mapclienteventtosimevent(hSimConnect, EVENT_INIT, ""); + hr = simconnect_addclienteventtonotificationgroup(hSimConnect, GROUP0, EVENT_INIT, false); + hr = simconnect_setnotificationgrouppriority(hSimConnect, GROUP0, SIMCONNECT_GROUP_PRIORITY_HIGHEST); + ////hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT0, "VK_COMMA", EVENT_INIT); + ////hr = SimConnect_SetInputGroupState(hSimConnect, INPUT0, SIMCONNECT_STATE_ON); - blnSimConnectActive = true; - if (hMainWindow != NULL) { - SendMessageTimeout( (HWND) hMainWindow, RegisterWindowMessageA(FT_PROGRAMID), 0, 0, 0, 2000, MsgResult); - } - } + blnSimConnectActive = true; + } } else { // @@ -165,33 +151,29 @@ PDWORD_PTR MsgResult = 0; // // Returns 'true' if all seems OK. // -bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) +bool FTNoIR_Protocol::checkServerInstallationOK() { QString aFileName; // File Path and Name // Code to activate the context for the SimConnect DLL - ACTCTX act = { 0 }; + ACTCTX act = { 0 }; HANDLE hctx; ULONG_PTR ulCookie; - hMainWindow = handle; - qDebug() << "SCCheckClientDLL says: Starting Function"; try { - +#if 0 act.cbSize = sizeof(act); act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + char full_path[2048]; + strcpy(full_path, QCoreApplication::applicationDirPath().toLatin1().constData()); + strcat(full_path, "\\libftnoir-proto-simconnect.dll"); - QString manifest(QCoreApplication::applicationDirPath()); -// manifest += "\\FaceTrackNoIR.exe"; - manifest += "\\FTNoIR_Protocol_SC.dll"; - const wchar_t * encodedName = reinterpret_cast(manifest.utf16()); - - act.lpSource = encodedName; - act.lpResourceName = MAKEINTRESOURCE(101); + act.lpSource = full_path; + act.lpResourceName = MAKEINTRESOURCEA(101); - hctx = CreateActCtx (&act); + hctx = CreateActCtxA (&act); if (hctx != INVALID_HANDLE_VALUE) { if (!ActivateActCtx(hctx, &ulCookie)) { @@ -203,32 +185,26 @@ bool FTNoIR_Protocol::checkServerInstallationOK( HANDLE handle ) qDebug() << "SCCheckClientDLL says: Error INVALID_HANDLE: " << GetLastError(); return false; } - // // Just try to load the DLL. Let Windows handle the PATH's and such trivialities... // - aFileName = SC_CLIENT_FILENAME; - - // - // Load the DLL. - // - SCClientLib.setFileName(aFileName); - if (SCClientLib.load() != true) { - qDebug() << "SCCheckClientDLL says: Error loading SimConnect DLL"; - return false; - } - // // Deactivate the context again: the function-references should stay in-tact... // DeactivateActCtx(0, ulCookie); ReleaseActCtx(hctx); - +#endif } catch(...) { qDebug() << "SCCheckClientDLL says: Error loading SimConnect DLL"; return false; } + SCClientLib.setFileName(SC_CLIENT_FILENAME); + if (SCClientLib.load() != true) { + qDebug() << "SCCheckClientDLL says: Error loading SimConnect DLL"; + return false; + } + // // Get the functions from the DLL. // @@ -374,7 +350,7 @@ void CALLBACK FTNoIR_Protocol::processNextSimconnectEvent(SIMCONNECT_RECV* pData // void FTNoIR_Protocol::getNameFromGame( char *dest ) { - sprintf_s(dest, 99, "Microsoft FSX"); + sprintf(dest, "Microsoft FSX"); return; } @@ -385,9 +361,9 @@ void FTNoIR_Protocol::getNameFromGame( char *dest ) // GetProtocol - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetProtocol@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") +//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolPtr __stdcall GetProtocol() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Protocol; + return (IProtocol*) new FTNoIR_Protocol; } diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.h b/ftnoir_protocol_sc/ftnoir_protocol_sc.h index 42eca457..57919193 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.h +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.h @@ -29,6 +29,7 @@ #pragma once #ifndef INCLUDED_SCSERVER_H #define INCLUDED_SCSERVER_H +#include "facetracknoir/global-settings.h" // // Prevent the SimConnect manifest from being merged in the application-manifest @@ -59,8 +60,7 @@ typedef HRESULT (WINAPI *importSimConnect_MapClientEventToSimEvent)(HANDLE hSimC typedef HRESULT (WINAPI *importSimConnect_AddClientEventToNotificationGroup)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable); typedef HRESULT (WINAPI *importSimConnect_SetNotificationGroupPriority)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); -static const char* SC_CLIENT_FILENAME = "SimConnect.dll"; -static const char* FT_PROGRAMID = "FT_ProgramID"; // For message to FaceTrackNoIR main-window. +#define SC_CLIENT_FILENAME "SimConnect.dll" enum GROUP_ID { @@ -83,11 +83,8 @@ class FTNoIR_Protocol : public IProtocol public: FTNoIR_Protocol(); ~FTNoIR_Protocol(); - - void Release(); - void Initialize(); - - bool checkServerInstallationOK( HANDLE handle ); + void Initialize() {} + bool checkServerInstallationOK(); void sendHeadposeToGame( THeadPoseData *headpose, THeadPoseData *rawheadpose ); void getNameFromGame( char *dest ); // Take care dest can handle up to 100 chars... @@ -112,10 +109,9 @@ private: static float prevSCRotY; static float prevSCRotZ; - bool blnSimConnectActive; - HANDLE hMainWindow; // Save the handle to FaceTrackNoIR main-window + bool blnSimConnectActive; - importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL + importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL importSimConnect_Close simconnect_close; static importSimConnect_CameraSetRelative6DOF simconnect_set6DOF; importSimConnect_CallDispatch simconnect_calldispatch; @@ -166,7 +162,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol //******************************************************************************************************* -class FTNoIR_ProtocolDll : public IProtocolDll +class FTNoIR_ProtocolDll : public Metadata { public: FTNoIR_ProtocolDll(); @@ -176,7 +172,7 @@ public: void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("SimConnect"); }; void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft SimConnect protocol"); }; - void getIcon(QIcon *icon) { *icon = QIcon(":/images/FSX.ico"); }; + void getIcon(QIcon *icon) { *icon = QIcon(":/images/fsx.png"); }; }; #endif//INCLUDED_SCSERVER_H diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp index 9047fa61..32abf64a 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp @@ -30,8 +30,9 @@ The ProtocolDll class solves this. The functions to get the name(s) and icon were removed from the two other classes. */ -#include "ftnoir_protocol_SC.h" +#include "ftnoir_protocol_sc.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -151,7 +152,7 @@ void SCControls::save() { // _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language. #pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialogPtr __stdcall GetProtocolDialog( ) +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new SCControls; + return (IProtocolDialog*) new SCControls; } diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp index f67f95db..3d59ef48 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_protocol_SC.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() { } @@ -50,7 +51,7 @@ FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll() // _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language. #pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0") -FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDllPtr __stdcall GetProtocolDll() +extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_ProtocolDll; } diff --git a/ftnoir_protocol_sc/ftnoir_sccontrols.ui b/ftnoir_protocol_sc/ftnoir_sccontrols.ui index 3e7a5062..a0cbf393 100644 --- a/ftnoir_protocol_sc/ftnoir_sccontrols.ui +++ b/ftnoir_protocol_sc/ftnoir_sccontrols.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/ftnoir_protocol_sc/images/fsx.ico b/ftnoir_protocol_sc/images/fsx.ico new file mode 100644 index 00000000..1c71d409 Binary files /dev/null and b/ftnoir_protocol_sc/images/fsx.ico differ diff --git a/ftnoir_protocol_wine/images/wine.ico b/ftnoir_protocol_wine/images/wine.ico new file mode 100644 index 00000000..58edbb62 Binary files /dev/null and b/ftnoir_protocol_wine/images/wine.ico differ diff --git a/ftnoir_tracker_base/ftnoir_tracker_base.h b/ftnoir_tracker_base/ftnoir_tracker_base.h index 396df4d1..416d3944 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_base.h +++ b/ftnoir_tracker_base/ftnoir_tracker_base.h @@ -35,6 +35,9 @@ #include "ftnoir_tracker_types.h" #include #include +#include +#include +#include //////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus @@ -52,29 +55,14 @@ struct ITracker { virtual ~ITracker() {} - virtual void Initialize( QFrame *videoframe ) = 0; - virtual void StartTracker( HWND parent_window ) = 0; - virtual void StopTracker(bool exit) = 0; - virtual bool GiveHeadPoseData(THeadPoseData *data) = 0; + virtual void StartTracker( QFrame* frame ) = 0; + virtual bool GiveHeadPoseData(THeadPoseData *data) = 0; - virtual bool notifyZeroed() { - return false; - } - virtual void refreshVideo() {} - virtual void notifyCenter() { - return; - } + virtual void WaitForExit() = 0; }; typedef ITracker* ITrackerPtr; -// Factory function that creates instances of the Tracker object. -EXTERN_C -FTNOIR_TRACKER_BASE_EXPORT -ITrackerPtr -__stdcall -GetTracker(void); - //////////////////////////////////////////////////////////////////////////////// // COM-Like abstract interface. // This interface doesn't require __declspec(dllexport/dllimport) specifier. @@ -83,20 +71,12 @@ GetTracker(void); // Instances are obtained via factory function. struct ITrackerDialog { - virtual ~ITrackerDialog() {} + virtual ~ITrackerDialog() {} virtual void Initialize(QWidget *parent) = 0; virtual void registerTracker(ITracker *tracker) = 0; virtual void unRegisterTracker() = 0; }; -typedef ITrackerDialog* ITrackerDialogPtr; - -// Factory function that creates instances of the Tracker object. -EXTERN_C -FTNOIR_TRACKER_BASE_EXPORT -ITrackerDialogPtr -__stdcall -GetTrackerDialog(void); //////////////////////////////////////////////////////////////////////////////// // COM-Like abstract interface. @@ -115,14 +95,5 @@ struct ITrackerDll virtual void getIcon(QIcon *icon) = 0; }; -typedef ITrackerDll* ITrackerDllPtr; - -// Factory function that creates instances of the Tracker object. -EXTERN_C -FTNOIR_TRACKER_BASE_EXPORT -ITrackerDllPtr -__stdcall -GetTrackerDll(void); - #endif // FTNOIR_TRACKER_BASE_H diff --git a/ftnoir_tracker_base/ftnoir_tracker_base_global.h b/ftnoir_tracker_base/ftnoir_tracker_base_global.h index 9f4a6118..a449c282 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_base_global.h +++ b/ftnoir_tracker_base/ftnoir_tracker_base_global.h @@ -1,7 +1,7 @@ #ifndef FTNOIR_TRACKER_BASE_GLOBAL_H #define FTNOIR_TRACKER_BASE_GLOBAL_H -#include +#include #ifdef FTNOIR_TRACKER_BASE_LIB # define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_EXPORT diff --git a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h b/ftnoir_tracker_base/ftnoir_tracker_sm_types.h index a8802e4a..1faf893f 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h +++ b/ftnoir_tracker_base/ftnoir_tracker_sm_types.h @@ -1,10 +1,11 @@ // // Definitions for the Shared Memory to send the data to FaceTrackNoIR // -static const char* SM_MM_DATA = "SM_SharedMem"; -static const char* SM_FACEAPI = "SM_FaceAPI"; -static const char* SM_MUTEX = "SM_Mutex"; +#define SM_MM_DATA "SM_SharedMem" +#define SM_FACEAPI "SM_FaceAPI" +#define SM_MUTEX "SM_Mutex" +#include "faceapi/stdafx.h" #include struct TFaceData { diff --git a/ftnoir_tracker_base/ftnoir_tracker_types.h b/ftnoir_tracker_base/ftnoir_tracker_types.h index ace7a6e3..ee443b95 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_types.h +++ b/ftnoir_tracker_base/ftnoir_tracker_types.h @@ -44,7 +44,7 @@ struct THeadPoseData { : x(x), y(y), z(z), yaw(yaw), pitch(pitch), roll(roll), frame_number(0) {} double x, y, z, yaw, pitch, roll; - long frame_number; + unsigned char frame_number; }; #pragma pack(pop) diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp index 336ede2d..5785b21a 100644 --- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp @@ -1,13 +1,11 @@ #include "stdafx.h" -#include "../ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" #include "headtracker-ftnoir.h" #include "ftnoir_tracker_ht.h" #include "ftnoir_tracker_ht_dll.h" #include "ui_trackercontrols.h" -#include "../facetracknoir/global-settings.h" - -#define WIDGET_WIDTH 250 -#define WIDGET_HEIGHT 188 +#include "facetracknoir/global-settings.h" +#include #if defined(_WIN32) || defined(__WIN32) #include @@ -98,31 +96,48 @@ static void load_settings(ht_config_t* config, Tracker* tracker) QSettings iniFile( currentFile, QSettings::IniFormat ); iniFile.beginGroup( "HT-Tracker" ); - config->classification_delay = 4000; - config->field_of_view = iniFile.value("fov", 69).toFloat(); + config->classification_delay = 500; + config->field_of_view = iniFile.value("fov", 52).toFloat(); config->pyrlk_pyramids = 3; - config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21; - config->max_keypoints = 250; - config->keypoint_quality = 12; - config->keypoint_distance = 2.3f; - config->keypoint_3distance = 6; - //config->force_width = 640; - //config->force_height = 480; - config->force_fps = iniFile.value("fps", 0).toInt(); - config->camera_index = iniFile.value("camera-index", -1).toInt(); - config->ransac_num_iters = 100; - config->ransac_max_reprojection_error = 6.5f; - config->ransac_max_inlier_error = 6.5f; - config->ransac_max_mean_error = 4.0f; - config->ransac_abs_max_mean_error = 7.0f; - config->debug = 0; - config->ransac_min_features = 0.75f; + config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21; + config->max_keypoints = 300; + config->keypoint_quality = 2; + config->keypoint_distance = 2.5; + config->keypoint_3distance = 6; + //config->force_width = 640; + //config->force_height = 480; + config->force_fps = iniFile.value("fps", 0).toInt(); + config->camera_index = iniFile.value("camera-index", -1).toInt(); + config->ransac_num_iters = 100; + config->ransac_max_reprojection_error = 3.63637; + config->ransac_max_inlier_error = 3; + config->ransac_max_mean_error = 3.5; + config->ransac_abs_max_mean_error = 7; + config->debug = 1; + config->ransac_min_features = 0.80; int res = iniFile.value("resolution", 0).toInt(); if (res < 0 || res >= (int)(sizeof(*resolution_choices) / sizeof(resolution_tuple))) res = 0; resolution_tuple r = resolution_choices[res]; config->force_width = r.width; - config->force_height = r.height; + config->force_height = r.height; + config->user_landmarks = iniFile.value("use-bashed-coords").toBool(); + if (config->user_landmarks) + { + config->user_landmark_locations[0][0] = iniFile.value("b1").toDouble(); + config->user_landmark_locations[1][0] = iniFile.value("b2").toDouble(); + config->user_landmark_locations[2][0] = iniFile.value("b3").toDouble(); + config->user_landmark_locations[0][1] = iniFile.value("b4").toDouble(); + config->user_landmark_locations[1][1] = iniFile.value("b5").toDouble(); + config->user_landmark_locations[2][1] = iniFile.value("b6").toDouble(); + config->user_landmark_locations[0][2] = iniFile.value("b7").toDouble(); + config->user_landmark_locations[1][2] = iniFile.value("b8").toDouble(); + config->user_landmark_locations[2][2] = iniFile.value("b9").toDouble(); + config->user_landmark_locations[0][3] = iniFile.value("b10").toDouble(); + config->user_landmark_locations[1][3] = iniFile.value("b11").toDouble(); + config->user_landmark_locations[2][3] = iniFile.value("b12").toDouble(); + } + qDebug() << "width" << r.width << "height" << r.height; if (tracker) { tracker->enableRX = iniFile.value("enable-rx", true).toBool(); @@ -159,7 +174,6 @@ Tracker::~Tracker() void Tracker::StartTracker(QFrame* videoframe) { - videoframe->setAttribute(Qt::WA_NativeWindow); videoframe->show(); videoWidget = new VideoWidget(videoframe); QHBoxLayout* layout = new QHBoxLayout(); @@ -168,7 +182,6 @@ void Tracker::StartTracker(QFrame* videoframe) if (videoframe->layout()) delete videoframe->layout(); videoframe->setLayout(layout); - videoWidget->resize(WIDGET_WIDTH, WIDGET_HEIGHT); videoWidget->show(); this->layout = layout; load_settings(&shm->config, this); @@ -181,8 +194,8 @@ void Tracker::StartTracker(QFrame* videoframe) #else subprocess.start(QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir"); #endif - connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget())); - timer.start(15); + connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()), Qt::QueuedConnection); + timer.start(40); } void Tracker::paint_widget() { @@ -209,8 +222,12 @@ bool Tracker::GiveHeadPoseData(THeadPoseData* data) data->yaw = shm->result.rotx; if (enableRY) data->pitch = shm->result.roty; - if (enableRZ) + if (enableRZ) { data->roll = shm->result.rotz; + double sign = data->roll >= 0 ? 1 : -1; + if (fabs(fabs(data->roll) - 180) < fabs(data->roll)) + data->roll = fabs(fabs(data->roll) - 180) * sign; + } if (enableTX) data->x = shm->result.tx; if (enableTY) @@ -227,7 +244,7 @@ bool Tracker::GiveHeadPoseData(THeadPoseData* data) //----------------------------------------------------------------------------- void TrackerDll::getFullName(QString *strToBeFilled) { - *strToBeFilled = "HT 0.7"; + *strToBeFilled = "HT 0.8"; } void TrackerDll::getShortName(QString *strToBeFilled) @@ -278,7 +295,6 @@ extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) TrackerControls::TrackerControls() { ui.setupUi(this); - loadSettings(); connect(ui.cameraName, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int))); connect(ui.cameraFPS, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int))); connect(ui.cameraFOV, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(double))); @@ -290,6 +306,7 @@ TrackerControls::TrackerControls() connect(ui.tz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(doCancel())); connect(ui.buttonOK, SIGNAL(clicked()), this, SLOT(doOK())); + loadSettings(); settingsDirty = false; } @@ -303,6 +320,7 @@ void TrackerControls::showEvent(QShowEvent *event) void TrackerControls::Initialize(QWidget* parent) { + loadSettings(); show(); } @@ -343,6 +361,19 @@ void TrackerControls::loadSettings() ui.ty->setCheckState(iniFile.value("enable-ty", true).toBool() ? Qt::Checked : Qt::Unchecked); ui.tz->setCheckState(iniFile.value("enable-tz", true).toBool() ? Qt::Checked : Qt::Unchecked); ui.resolution->setCurrentIndex(iniFile.value("resolution", 0).toInt()); + ui.groupBox_2->setChecked(iniFile.value("use-bashed-coords").toBool()); + ui.doubleSpinBox_1->setValue(iniFile.value("b1", 0).toDouble()); + ui.doubleSpinBox_2->setValue(iniFile.value("b2", 0).toDouble()); + ui.doubleSpinBox_3->setValue(iniFile.value("b3", 0).toDouble()); + ui.doubleSpinBox_4->setValue(iniFile.value("b4", 0).toDouble()); + ui.doubleSpinBox_5->setValue(iniFile.value("b5", 0).toDouble()); + ui.doubleSpinBox_6->setValue(iniFile.value("b6", 0).toDouble()); + ui.doubleSpinBox_7->setValue(iniFile.value("b7", 0).toDouble()); + ui.doubleSpinBox_8->setValue(iniFile.value("b8", 0).toDouble()); + ui.doubleSpinBox_9->setValue(iniFile.value("b9", 0).toDouble()); + ui.doubleSpinBox_10->setValue(iniFile.value("b10", 0).toDouble()); + ui.doubleSpinBox_11->setValue(iniFile.value("b11", 0).toDouble()); + ui.doubleSpinBox_12->setValue(iniFile.value("b12", 0).toDouble()); iniFile.endGroup(); settingsDirty = false; } @@ -381,6 +412,19 @@ void TrackerControls::save() iniFile.setValue("enable-ty", ui.ty->checkState() != Qt::Unchecked ? true : false); iniFile.setValue("enable-tz", ui.tz->checkState() != Qt::Unchecked ? true : false); iniFile.setValue("resolution", ui.resolution->currentIndex()); + iniFile.setValue("b1", ui.doubleSpinBox_1->value()); + iniFile.setValue("b2", ui.doubleSpinBox_2->value()); + iniFile.setValue("b3", ui.doubleSpinBox_3->value()); + iniFile.setValue("b4", ui.doubleSpinBox_4->value()); + iniFile.setValue("b5", ui.doubleSpinBox_5->value()); + iniFile.setValue("b6", ui.doubleSpinBox_6->value()); + iniFile.setValue("b7", ui.doubleSpinBox_7->value()); + iniFile.setValue("b8", ui.doubleSpinBox_8->value()); + iniFile.setValue("b9", ui.doubleSpinBox_9->value()); + iniFile.setValue("b10", ui.doubleSpinBox_10->value()); + iniFile.setValue("b11", ui.doubleSpinBox_11->value()); + iniFile.setValue("b12", ui.doubleSpinBox_12->value()); + iniFile.setValue("use-bashed-coords", ui.groupBox_2->isChecked()); iniFile.endGroup(); settingsDirty = false; } diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h index 1a449dca..f5d0c271 100644 --- a/ftnoir_tracker_ht/ftnoir_tracker_ht.h +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013 Stanislaw Halik +/* Copyright (c) 2013 Stanis³aw Halik * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -9,11 +9,11 @@ #define FTNOIR_TRACKER_HT_H #include "stdafx.h" -#include "../ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" #include "headtracker-ftnoir.h" #include "ui_trackercontrols.h" #include "video_widget.h" -#include "../compat/compat.h" +#include "compat/compat.h" #include #include diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h index f3bfd381..1e53f802 100644 --- a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h +++ b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h @@ -5,8 +5,8 @@ * copyright notice and this permission notice appear in all copies. */ -#include "../ftnoir_tracker_base/ftnoir_tracker_base.h" -#include "../facetracknoir/global-settings.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "facetracknoir/global-settings.h" //----------------------------------------------------------------------------- class TrackerDll : public Metadata diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h index ac8d45cf..81caf16f 100644 --- a/ftnoir_tracker_ht/ht-api.h +++ b/ftnoir_tracker_ht/ht-api.h @@ -1,9 +1,9 @@ #pragma once #ifndef HT_API #ifndef __cplusplus -# define HT_EXTERN +# define HT_EXTERN #else -# define HT_EXTERN extern "C" +# define HT_EXTERN extern "C" #endif # if defined(_WIN32) && !defined(MINGW) # define HT_API(t) HT_EXTERN __declspec(dllexport) t __stdcall @@ -19,56 +19,58 @@ struct ht_context; typedef struct ht_context headtracker_t; typedef struct ht_config { - float field_of_view; - float classification_delay; - int pyrlk_pyramids; - int pyrlk_win_size_w; - int pyrlk_win_size_h; + float field_of_view; + float classification_delay; + int pyrlk_pyramids; + int pyrlk_win_size_w; + int pyrlk_win_size_h; float ransac_max_inlier_error; float ransac_max_reprojection_error; - int max_keypoints; + int max_keypoints; int keypoint_quality; - float keypoint_distance; + float keypoint_distance; float keypoint_3distance; int force_width; - int force_height; - int force_fps; - int camera_index; - bool debug; + int force_height; + int force_fps; + int camera_index; + bool debug; int ransac_num_iters; float ransac_min_features; float ransac_max_mean_error; float ransac_abs_max_mean_error; + bool user_landmarks; + float user_landmark_locations[3][4]; } ht_config_t; typedef struct { double rotx, roty, rotz; double tx, ty, tz; - bool filled; + bool filled; } ht_result_t; typedef enum { - cfg_type_float = 0, - cfg_type_int = 1, - cfg_type_bool = 2, + cfg_type_float = 0, + cfg_type_int = 1, + cfg_type_bool = 2, cfg_type_double = 3 } ht_cfg_type_t; typedef union { - double d; - float f; - int i; + double d; + float f; + int i; } ht_cfg_value_t; typedef struct { - const char* name; - int offset; - ht_cfg_type_t type; - ht_cfg_value_t default_value; - ht_cfg_value_t min; - ht_cfg_value_t max; - const char* docstring; + const char* name; + int offset; + ht_cfg_type_t type; + ht_cfg_value_t default_value; + ht_cfg_value_t min; + ht_cfg_value_t max; + const char* docstring; } ht_reflection_t; typedef struct { diff --git a/ftnoir_tracker_ht/images/ht.ico b/ftnoir_tracker_ht/images/ht.ico new file mode 100644 index 00000000..7555ce25 Binary files /dev/null and b/ftnoir_tracker_ht/images/ht.ico differ diff --git a/ftnoir_tracker_ht/trackercontrols.ui b/ftnoir_tracker_ht/trackercontrols.ui index 0a1bc3ae..2f4b1915 100644 --- a/ftnoir_tracker_ht/trackercontrols.ui +++ b/ftnoir_tracker_ht/trackercontrols.ui @@ -9,19 +9,19 @@ 0 0 - 500 + 724 160 - + 0 0 - 500 + 750 160 @@ -38,7 +38,7 @@
- Horizontal field of view + Horizontal FOV
@@ -68,7 +68,7 @@ 10 40 - 101 + 137 16
@@ -111,7 +111,7 @@ 10 70 - 71 + 133 16
@@ -122,7 +122,7 @@ - 340 + 220 130 75 23 @@ -135,7 +135,7 @@ - 420 + 300 130 75 23 @@ -251,7 +251,7 @@ 10 100 - 61 + 128 16 @@ -289,6 +289,289 @@
+ + + + 500 + 10 + 221 + 141 + + + + Bashed coordinates + + + true + + + false + + + + + 10 + 20 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 80 + 20 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 150 + 20 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 150 + 50 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 10 + 50 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 80 + 50 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 150 + 80 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 10 + 80 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 80 + 80 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 150 + 110 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 80 + 110 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + + + + + 10 + 110 + 61 + 22 + + + + true + + + QAbstractSpinBox::NoButtons + + + 5 + + + -99.000000000000000 + + +
diff --git a/ftnoir_tracker_ht/video_widget.cpp b/ftnoir_tracker_ht/video_widget.cpp new file mode 100644 index 00000000..51d92967 --- /dev/null +++ b/ftnoir_tracker_ht/video_widget.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "video_widget.h" + +#include + +using namespace std; + +// ---------------------------------------------------------------------------- +void VideoWidget::initializeGL() +{ + glClearColor(0.0, 0.0, 0.0, 0.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void VideoWidget::resizeGL(int w, int h) +{ + // setup 1 to 1 projection + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, w, 0, h, -1, 1); + resize_frame(resized_qframe); + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + glVertex2f(0,0); + glVertex2f(1,0); + glVertex2f(1,1); + glVertex2f(0,1); + glEnd(); +} + +void VideoWidget::paintGL() +{ + QMutexLocker lck(&mtx); + if (resized_qframe.size() == size() || (resized_qframe.width() <= width() && resized_qframe.height() <= height())) + { + glDrawPixels(resized_qframe.width(), resized_qframe.height(), GL_RGB, GL_UNSIGNED_BYTE, resized_qframe.bits()); + } + else + glClear(GL_DEPTH_BUFFER_BIT); + glFlush(); +} + +void VideoWidget::resize_frame(QImage& qframe) +{ + QMutexLocker lck(&mtx); + if (qframe.size() == size() || (qframe.width() <= width() && qframe.height() <= height())) + resized_qframe = qframe.copy(); + else + resized_qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation).copy(); +} + + +void VideoWidget::updateImage(unsigned char *frame, int width, int height) +{ + QImage foo = QImage(frame, width, height, 3 * width, QImage::Format_RGB888).rgbSwapped().mirrored(); + resize_frame(foo); +} + +void VideoWidget::update() { + updateGL(); +} diff --git a/ftnoir_tracker_ht/video_widget.h b/ftnoir_tracker_ht/video_widget.h new file mode 100644 index 00000000..adc57335 --- /dev/null +++ b/ftnoir_tracker_ht/video_widget.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#ifndef VIDEOWIDGET_H +#define VIDEOWIDGET_H + +#include +#include +#include +#include +#include +#include +#include +// ---------------------------------------------------------------------------- +class VideoWidget : public QGLWidget +{ + Q_OBJECT + +public: + VideoWidget(QWidget *parent) : QGLWidget(parent) { +#if !defined(_WIN32) + setAttribute(Qt::WA_NativeWindow, true); +#endif + } + + void initializeGL(); + void resizeGL(int w, int h); + void paintGL(); + + void updateImage(unsigned char* frame, int width, int height); + void update(); +private: + void resize_frame(QImage& qframe); + QImage resized_qframe; + QMutex mtx; +}; + +#endif // VIDEOWIDGET_H diff --git a/ftnoir_tracker_pt/Resources/icon.ico b/ftnoir_tracker_pt/Resources/icon.ico new file mode 100644 index 00000000..c4b2aedc Binary files /dev/null and b/ftnoir_tracker_pt/Resources/icon.ico differ diff --git a/ftnoir_tracker_pt/camera.cpp b/ftnoir_tracker_pt/camera.cpp index fc11c738..96ba3b89 100644 --- a/ftnoir_tracker_pt/camera.cpp +++ b/ftnoir_tracker_pt/camera.cpp @@ -68,45 +68,33 @@ bool Camera::get_frame(float dt, cv::Mat* frame) } // ---------------------------------------------------------------------------- -/* void CVCamera::start() { - cap = cvCreateCameraCapture(desired_index); - // extract camera info - if (cap) - { - active = true; - active_index = desired_index; - cam_info.res_x = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH); - cam_info.res_y = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT); - } + cap = new VideoCapture(desired_index); +// extract camera info + active = true; + active_index = desired_index; + cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH); + cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT); } void CVCamera::stop() { - if (cap) cvReleaseCapture(&cap); + if (cap) { + cap->release(); + delete cap; + cap = NULL; + } active = false; } bool CVCamera::_get_frame(Mat* frame) { - if (cap && cvGrabFrame(cap) != 0) - { - // retrieve frame - IplImage* _img = cvRetrieveFrame(cap, 0); - if(_img) - { - if(_img->origin == IPL_ORIGIN_TL) - *frame = Mat(_img); - else - { - Mat temp(_img); - flip(temp, *frame, 0); - } - return true; - } - } - return false; + Mat tmp; + bool ret = cap->read(tmp); + if (ret) + flip(tmp, *frame, 0); + return ret; } void CVCamera::_set_index() @@ -121,21 +109,21 @@ void CVCamera::_set_f() void CVCamera::_set_fps() { - if (cap) cvSetCaptureProperty(cap, CV_CAP_PROP_FPS, cam_desired.fps); + if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps); } void CVCamera::_set_res() { if (cap) { - cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x); - cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); - cam_info.res_x = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH); - cam_info.res_y = cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT); + cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x); + cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); + cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH); + cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT); } } -*/ +#if 0 // ---------------------------------------------------------------------------- VICamera::VICamera() : frame_buffer(NULL) { @@ -223,4 +211,4 @@ void VICamera::_set_res() { if (active) restart(); } - +#endif diff --git a/ftnoir_tracker_pt/camera.h b/ftnoir_tracker_pt/camera.h index cd1f0842..9977431b 100644 --- a/ftnoir_tracker_pt/camera.h +++ b/ftnoir_tracker_pt/camera.h @@ -9,7 +9,7 @@ #define CAMERA_H #include -#include "videoInput/videoInput.h" +//#include "videoInput/videoInput.h" // ---------------------------------------------------------------------------- struct CamInfo @@ -27,7 +27,7 @@ struct CamInfo class Camera { public: - Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1), active(false) {} + Camera() : desired_index(0), active_index(-1), active(false), dt_valid(0), dt_mean(0) {} virtual ~Camera() {} // start/stop capturing @@ -57,19 +57,19 @@ protected: virtual void _set_fps() = 0; virtual void _set_res() = 0; + int desired_index; + int active_index; bool active; - int desired_index; - int active_index; + float dt_valid; + float dt_mean; CamInfo cam_info; CamInfo cam_desired; - float dt_valid; - float dt_mean; }; // ---------------------------------------------------------------------------- // OpenCV camera -/* + class CVCamera : public Camera { public: @@ -86,12 +86,13 @@ protected: void _set_fps(); void _set_res(); - CvCapture* cap; + cv::VideoCapture* cap; }; -*/ + // ---------------------------------------------------------------------------- // videoInput camera +#if 0 class VICamera : public Camera { public: @@ -112,5 +113,6 @@ protected: cv::Mat new_frame; unsigned char* frame_buffer; }; +#endif #endif //CAMERA_H diff --git a/ftnoir_tracker_pt/ftnoir_pt_controls.ui b/ftnoir_tracker_pt/ftnoir_pt_controls.ui index 0174df23..0934a4fb 100644 --- a/ftnoir_tracker_pt/ftnoir_pt_controls.ui +++ b/ftnoir_tracker_pt/ftnoir_pt_controls.ui @@ -9,7 +9,7 @@ 0 0 - 405 + 451 489
@@ -23,8 +23,8 @@ PointTracker Settings - - :/Resources/icon.ico:/Resources/icon.ico + + :/Resources/icon.png:/Resources/icon.png Qt::LeftToRight @@ -54,7 +54,7 @@ - 0 + 1 @@ -561,6 +561,9 @@ Desired capture framerate + + 300 +
@@ -959,7 +962,7 @@ - :/Resources/clip_side.png + :/resources/clip_side.png @@ -1082,7 +1085,7 @@ - :/Resources/clip_front.png + :/resources/clip_front.png @@ -1137,7 +1140,7 @@ - :/Resources/cap_side.png + :/resources/cap_side.png @@ -1247,7 +1250,7 @@ - :/Resources/cap_front.png + :/resources/cap_front.png @@ -1656,7 +1659,7 @@ - :/Resources/Logo_IR.png + :/resources/logo_ir.png diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp index 5b77da69..db863e3a 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp @@ -11,23 +11,22 @@ #include #include #include +#include "facetracknoir/global-settings.h" using namespace std; using namespace cv; -using namespace boost; //#define PT_PERF_LOG //log performance //----------------------------------------------------------------------------- Tracker::Tracker() - : frame_count(0), commands(0), video_widget(NULL), tracking_valid(false) + : tracking_valid(false), frame_count(0), commands(0), video_widget(NULL), fresh(false) { + should_quit = false; qDebug()<<"Tracker::Tracker"; TrackerSettings settings; - settings.load_ini(); + settings.load_ini(); apply(settings); - camera.start(); - start(); } Tracker::~Tracker() @@ -66,8 +65,12 @@ void Tracker::run() forever { { + + refreshVideo(); QMutexLocker lock(&mutex); - + if (should_quit) + break; + if (commands & ABORT) break; if (commands & PAUSE) continue; commands = 0; @@ -105,7 +108,7 @@ void Tracker::apply(const TrackerSettings& settings) point_extractor.threshold_val = settings.threshold; point_extractor.min_size = settings.min_point_size; point_extractor.max_size = settings.max_point_size; - point_tracker.point_model = boost::shared_ptr(new PointModel(settings.M01, settings.M02)); + point_tracker.point_model = std::auto_ptr(new PointModel(settings.M01, settings.M02)); point_tracker.dynamic_pose_resolution = settings.dyn_pose_res; sleep_time = settings.sleep_time; point_tracker.dt_reset = settings.reset_time / 1000.0; @@ -138,57 +141,60 @@ void Tracker::center() X_CH_0 = X_CM_0 * X_MH; } -//----------------------------------------------------------------------------- -// ITracker interface -void Tracker::Initialize(QFrame *videoframe) -{ - const int VIDEO_FRAME_WIDTH = 252; - const int VIDEO_FRAME_HEIGHT = 189; - - qDebug("Tracker::Initialize"); - // setup video frame - videoframe->setAttribute(Qt::WA_NativeWindow); - videoframe->show(); - video_widget = new VideoWidget(videoframe); - QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(video_widget); - if (videoframe->layout()) delete videoframe->layout(); - videoframe->setLayout(layout); - video_widget->resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT); -} - void Tracker::refreshVideo() { if (video_widget) { Mat frame_copy; - shared_ptr< vector > points; + std::auto_ptr< vector > points; { QMutexLocker lock(&mutex); if (!draw_frame || frame.empty()) return; // copy the frame and points from the tracker thread frame_copy = frame.clone(); - points = shared_ptr< vector >(new vector(point_extractor.get_points())); + points = std::auto_ptr< vector >(new vector(point_extractor.get_points())); } - video_widget->update(frame_copy, points); + video_widget->update_image(frame_copy, points); + fresh = true; } } -void Tracker::StartTracker(HWND parent_window) +void Tracker::StartTracker(QFrame* videoframe) { + const int VIDEO_FRAME_WIDTH = 252; + const int VIDEO_FRAME_HEIGHT = 189; + TrackerSettings settings; + settings.load_ini(); + apply(settings); + camera.start(); + start(); + qDebug("Tracker::Initialize"); + // setup video frame + video_widget = new VideoWidget(videoframe); + QHBoxLayout* layout = new QHBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(video_widget); + if (videoframe->layout()) delete videoframe->layout(); + videoframe->setLayout(layout); + video_widget->resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT); + videoframe->show(); reset_command(PAUSE); + connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()), Qt::QueuedConnection); + timer.start(40); } -void Tracker::StopTracker(bool exit) -{ - set_command(PAUSE); +void Tracker::paint_widget() { + if (fresh) { + fresh = false; + video_widget->update(); + } } bool Tracker::GiveHeadPoseData(THeadPoseData *data) { + refreshVideo(); const float rad2deg = 180.0/3.14159265; const float deg2rad = 1.0/rad2deg; { @@ -249,9 +255,9 @@ bool Tracker::GiveHeadPoseData(THeadPoseData *data) } //----------------------------------------------------------------------------- -#pragma comment(linker, "/export:GetTracker=_GetTracker@0") +//#pragma comment(linker, "/export:GetTracker=_GetTracker@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker() +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new Tracker; -} \ No newline at end of file + return (ITracker*) new Tracker; +} diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.h b/ftnoir_tracker_pt/ftnoir_tracker_pt.h index 2533a39b..49881b69 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.h @@ -8,7 +8,7 @@ #ifndef FTNOIR_TRACKER_PT_H #define FTNOIR_TRACKER_PT_H -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" #include "ftnoir_tracker_pt_settings.h" #include "camera.h" #include "point_extractor.h" @@ -20,18 +20,19 @@ #include #include #include +#include +#include //----------------------------------------------------------------------------- -class Tracker : public ITracker, QThread +class Tracker : public QThread, public ITracker { + Q_OBJECT public: Tracker(); ~Tracker(); // ITracker interface - void Initialize(QFrame *videoframe); - void StartTracker(HWND parent_window); - void StopTracker(bool exit); + void StartTracker(QFrame* videoFrame); bool GiveHeadPoseData(THeadPoseData *data); void refreshVideo(); @@ -40,6 +41,10 @@ public: void center(); void reset(); // reset the trackers internal state variables void run(); + void WaitForExit() { + should_quit = true; + wait(); + } void get_pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.get_pose(); } int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } @@ -47,8 +52,6 @@ public: protected: FrameTrafo X_CH_0; // for centering - - QMutex mutex; cv::Mat frame; // the output frame for display enum Command { @@ -57,9 +60,8 @@ protected: }; void set_command(Command command); void reset_command(Command command); - int commands; - VICamera camera; + CVCamera camera; PointExtractor point_extractor; PointTracker point_tracker; bool tracking_valid; @@ -78,9 +80,17 @@ protected: bool bEnableZ; long frame_count; + int commands; VideoWidget* video_widget; Timer time; + QMutex mutex; + volatile bool should_quit; + volatile bool fresh; + QTimer timer; + +protected slots: + void paint_widget(); }; #endif // FTNOIR_TRACKER_PT_H diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp index a1531dd7..c1067ba7 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp @@ -9,10 +9,11 @@ #include #include +#include "facetracknoir/global-settings.h" //----------------------------------------------------------------------------- TrackerDialog::TrackerDialog() - : settings_dirty(false), tracker(NULL), timer(this), trans_calib_running(false) + : settings_dirty(false), tracker(NULL), trans_calib_running(false), timer(this) { qDebug()<<"TrackerDialog::TrackerDialog"; setAttribute(Qt::WA_DeleteOnClose, false); @@ -328,9 +329,9 @@ void TrackerDialog::unRegisterTracker() } //----------------------------------------------------------------------------- -#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") +//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( ) +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new TrackerDialog; -} \ No newline at end of file + return (ITrackerDialog*) new TrackerDialog; +} diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h index 0f836dfe..28120692 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h @@ -8,10 +8,10 @@ #ifndef FTNOIR_TRACKER_PT_DIALOG_H #define FTNOIR_TRACKER_PT_DIALOG_H -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" #include "ftnoir_tracker_pt_settings.h" #include "ftnoir_tracker_pt.h" -#include "ui_FTNoIR_PT_Controls.h" +#include "ui_ftnoir_pt_controls.h" #include "trans_calib.h" #include @@ -99,4 +99,4 @@ protected: Ui::UICPTClientControls ui; }; -#endif //FTNOIR_TRACKER_PT_DIALOG_H \ No newline at end of file +#endif //FTNOIR_TRACKER_PT_DIALOG_H diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp index 7f58d77d..22c4a33d 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp @@ -6,8 +6,8 @@ */ #include "ftnoir_tracker_pt_dll.h" - #include +#include "facetracknoir/global-settings.h" //----------------------------------------------------------------------------- void TrackerDll::getFullName(QString *strToBeFilled) @@ -27,14 +27,14 @@ void TrackerDll::getDescription(QString *strToBeFilled) void TrackerDll::getIcon(QIcon *icon) { - *icon = QIcon(":/Resources/icon.ico"); + *icon = QIcon(":/resources/icon.png"); } //----------------------------------------------------------------------------- -#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") +//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDllPtr __stdcall GetTrackerDll() +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new TrackerDll; } diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h index 15ad63aa..f684c55b 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h @@ -5,10 +5,11 @@ * copyright notice and this permission notice appear in all copies. */ -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "facetracknoir/global-settings.h" //----------------------------------------------------------------------------- -class TrackerDll : public ITrackerDll +class TrackerDll : public Metadata { // ITrackerDll interface void Initialize() {} @@ -16,4 +17,4 @@ class TrackerDll : public ITrackerDll void getShortName(QString *strToBeFilled); void getDescription(QString *strToBeFilled); void getIcon(QIcon *icon); -}; \ No newline at end of file +}; diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp index 4aa1a658..b6e9ad3a 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -11,6 +11,14 @@ using namespace cv; using namespace std; +struct BlobInfo +{ + BlobInfo() : m00(0), m10(0), m01(0) {} + long m00; + long m10; + long m01; +}; + // ---------------------------------------------------------------------------- const vector& PointExtractor::extract_points(Mat frame, float dt, bool draw_output) { @@ -39,13 +47,6 @@ const vector& PointExtractor::extract_points(Mat frame, float dt, bool dr // find connected components... // extract blobs with floodfill - struct BlobInfo - { - BlobInfo() : m00(0), m10(0), m01(0) {} - long m00; - long m10; - long m01; - }; vector blobs; int blob_count = 1; diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/ftnoir_tracker_pt/point_tracker.cpp index d617de19..c08d6d83 100644 --- a/ftnoir_tracker_pt/point_tracker.cpp +++ b/ftnoir_tracker_pt/point_tracker.cpp @@ -14,7 +14,6 @@ #include using namespace cv; -using namespace boost; using namespace std; const float PI = 3.14159265358979323846f; @@ -68,26 +67,27 @@ PointModel::PointModel(Vec3f M01, Vec3f M02) get_d_order(points, d_order); } +static bool d_vals_sort(const pair a, const pair b) +{ + return a.first < b.first; +} + void PointModel::get_d_order(const std::vector& points, int d_order[]) const { // get sort indices with respect to d scalar product vector< pair > d_vals; - for (int i = 0; i(d.dot(points[i]), i)); - struct - { - bool operator()(const pair& a, const pair& b) { return a.first < b.first; } - } comp; - sort(d_vals.begin(), d_vals.end(), comp); + sort(d_vals.begin(), d_vals.end(), d_vals_sort); - for (int i = 0; i& points, float f, float dt) } // if there is a pointtracking problem, reset the velocities - if (!point_model || points.size() != PointModel::N_POINTS) + if (!point_model.get() || (int) points.size() != PointModel::N_POINTS) { //qDebug()<<"Wrong number of points!"; reset_velocities(); @@ -141,7 +141,7 @@ bool PointTracker::track(const vector& points, float f, float dt) return false; } - int n_iter = POSIT(f); + (void) POSIT(f); //qDebug()<<"Number of POSIT iterations: "< #include -#include #include // ---------------------------------------------------------------------------- @@ -76,7 +76,7 @@ public: // f : (focal length)/(sensor width) // dt : time since last call bool track(const std::vector& points, float f, float dt); - boost::shared_ptr point_model; + std::auto_ptr point_model; bool dynamic_pose_resolution; float dt_reset; diff --git a/ftnoir_tracker_pt/timer.cpp b/ftnoir_tracker_pt/timer.cpp index 363b5b09..9e6ca8b8 100644 --- a/ftnoir_tracker_pt/timer.cpp +++ b/ftnoir_tracker_pt/timer.cpp @@ -55,8 +55,7 @@ double Timer::elapsed() startTime = startCount.QuadPart * (1e3 / frequency.QuadPart); endTime = endCount.QuadPart * (1e3 / frequency.QuadPart); #else - if(!stopped) - gettimeofday(&endCount, NULL); + (void) gettimeofday(&endCount, NULL); startTime = (startCount.tv_sec * 1e3) + startCount.tv_usec; endTime = (endCount.tv_sec * 1e3) + endCount.tv_usec; diff --git a/ftnoir_tracker_pt/video_widget.cpp b/ftnoir_tracker_pt/video_widget.cpp index c2b41da1..c297c455 100644 --- a/ftnoir_tracker_pt/video_widget.cpp +++ b/ftnoir_tracker_pt/video_widget.cpp @@ -3,8 +3,6 @@ * 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. - * - * 20130312, WVR: Add 7 lines to resizeGL after resize_frame. This should lower CPU-load. */ #include "video_widget.h" @@ -13,7 +11,6 @@ using namespace cv; using namespace std; -using namespace boost; // ---------------------------------------------------------------------------- void VideoWidget::initializeGL() @@ -31,21 +28,20 @@ void VideoWidget::resizeGL(int w, int h) glLoadIdentity(); glOrtho(0, w, 0, h, -1, 1); resize_frame(); - glDisable(GL_DEPTH_TEST); - glBegin(GL_QUADS); - glVertex2f(0,0); - glVertex2f(1,0); - glVertex2f(1,1); - glVertex2f(0,1); - glEnd(); + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + glVertex2f(0,0); + glVertex2f(1,0); + glVertex2f(1,1); + glVertex2f(0,1); + glEnd(); } void VideoWidget::paintGL() { - glClear(GL_COLOR_BUFFER_BIT); - if (!resized_qframe.isNull()) - { - glDrawPixels(resized_qframe.width(), resized_qframe.height(), GL_RGBA, GL_UNSIGNED_BYTE, resized_qframe.bits()); + QMutexLocker lck(&mtx); + if (resized_qframe.size() == size() || (resized_qframe.width() <= width() && resized_qframe.height() <= height())) { + glDrawPixels(resized_qframe.width(), resized_qframe.height(), GL_RGB, GL_UNSIGNED_BYTE, resized_qframe.bits()); const int crosshair_radius = 10; const int crosshair_thickness = 1; @@ -69,30 +65,44 @@ void VideoWidget::paintGL() glVertex2i(x, y+crosshair_radius); glEnd(); } - } - glFlush(); + + } else { + glClear(GL_DEPTH_BUFFER_BIT); + } + glFlush(); } void VideoWidget::resize_frame() { - if (!qframe.isNull()) - resized_qframe = qframe.scaled(this->size(), Qt::KeepAspectRatio); + QMutexLocker lck(&mtx); +#ifdef _WIN32 + if (qframe.size() == size() || (qframe.width() <= width() && qframe.height() <= height())) + resized_qframe = qframe.mirrored(); + else + resized_qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation).mirrored(); +#else + if (qframe.size() == size() || (qframe.width() <= width() && qframe.height() <= height())) + resized_qframe = qframe.copy(); + else + resized_qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); +#endif } +void VideoWidget::update() +{ + updateGL(); +} -void VideoWidget::update(Mat frame, shared_ptr< vector > points) +void VideoWidget::update_image(Mat frame, std::auto_ptr< vector > points) { this->frame = frame; this->points = points; - // convert to QImage + // convert to QImage if (frame.channels() == 3) - qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888).rgbSwapped(); + qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.cols * 3, QImage::Format_RGB888).rgbSwapped(); else if (frame.channels() == 1) - qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_Indexed8); - qframe = QGLWidget::convertToGLFormat(qframe); - + qframe = QImage((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.cols, QImage::Format_Indexed8); resize_frame(); - updateGL(); } diff --git a/ftnoir_tracker_pt/video_widget.h b/ftnoir_tracker_pt/video_widget.h index f49fef18..2425603b 100644 --- a/ftnoir_tracker_pt/video_widget.h +++ b/ftnoir_tracker_pt/video_widget.h @@ -11,7 +11,10 @@ #include #include #include -#include +#include +#include +#include +#include // ---------------------------------------------------------------------------- class VideoWidget : public QGLWidget @@ -19,13 +22,18 @@ class VideoWidget : public QGLWidget Q_OBJECT public: - VideoWidget(QWidget *parent) : QGLWidget(parent) {} + VideoWidget(QWidget *parent) : QGLWidget(parent) { +#if !defined(_WIN32) + setAttribute(Qt::WA_NativeWindow, true); +#endif + } void initializeGL(); void resizeGL(int w, int h); void paintGL(); - void update(cv::Mat frame, boost::shared_ptr< std::vector > points); + void update_image(cv::Mat frame, std::auto_ptr< std::vector > points); + void update(); private: void resize_frame(); @@ -34,7 +42,8 @@ private: QImage qframe; QImage resized_qframe; - boost::shared_ptr< std::vector > points; + std::auto_ptr< std::vector > points; + QMutex mtx; }; #endif // VIDEOWIDGET_H diff --git a/ftnoir_tracker_sm/ftnoir_sm_controls.ui b/ftnoir_tracker_sm/ftnoir_sm_controls.ui index 93befd19..06ebc9ca 100644 --- a/ftnoir_tracker_sm/ftnoir_sm_controls.ui +++ b/ftnoir_tracker_sm/ftnoir_sm_controls.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/sm.pngimages/sm.png Qt::LeftToRight @@ -103,7 +103,7 @@ Enable Axis - + 10 diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp index 624e35a0..35d3a3db 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp @@ -24,6 +24,7 @@ ********************************************************************************/ #include "ftnoir_tracker_sm.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_Tracker::FTNoIR_Tracker() { @@ -49,67 +50,60 @@ FTNoIR_Tracker::~FTNoIR_Tracker() hSMMemMap = 0; } -void FTNoIR_Tracker::Initialize( QFrame *videoframe ) -{ - qDebug() << "FTNoIR_Tracker::Initialize says: Starting "; - - if (SMCreateMapping()) { - qDebug() << "FTNoIR_Tracker::Initialize Mapping created."; - } - else { - QMessageBox::warning(0,"FaceTrackNoIR Error","Memory mapping not created!",QMessageBox::Ok,QMessageBox::NoButton); - } - - loadSettings(); - - if ( pMemData != NULL ) { - pMemData->command = 0; // Reset any and all commands - if (videoframe != NULL) { - pMemData->handle = videoframe->winId(); // Handle of Videoframe widget - } - else { - pMemData->handle = NULL; // reset Handle of Videoframe widget - } - } - - // - // Start FTNoIR_FaceAPI_EXE.exe. The exe contains all faceAPI-stuff and is non-Qt... - // - QString program = "FTNoIR_FaceAPI_EXE.exe"; - faceAPI = new QProcess(0); - faceAPI->start(program); - - // Show the video widget - qDebug() << "FTNoIR_Tracker::Initialize says: videoframe = " << videoframe; - - if (videoframe != NULL) { - videoframe->show(); - } - return; -} - -void FTNoIR_Tracker::StartTracker( HWND parent_window ) +void FTNoIR_Tracker::StartTracker(QFrame *videoframe ) { + qDebug() << "FTNoIR_Tracker::Initialize says: Starting "; + + if (SMCreateMapping()) { + qDebug() << "FTNoIR_Tracker::Initialize Mapping created."; + } + else { + QMessageBox::warning(0,"FaceTrackNoIR Error","Memory mapping not created!",QMessageBox::Ok,QMessageBox::NoButton); + } + + loadSettings(); + + if ( pMemData != NULL ) { + pMemData->command = 0; // Reset any and all commands + if (videoframe != NULL) { + pMemData->handle = videoframe->winId(); // Handle of Videoframe widget + } + else { + pMemData->handle = NULL; // reset Handle of Videoframe widget + } + } + + // + // Start FTNoIR_FaceAPI_EXE.exe. The exe contains all faceAPI-stuff and is non-Qt... + // + // XXX TODO isolate it into separate directory + faceAPI = new QProcess(); + faceAPI->setWorkingDirectory(QCoreApplication::applicationDirPath() + "/faceapi"); + faceAPI->start("\"" + QCoreApplication::applicationDirPath() + "/faceapi/ftnoir-faceapi-wrapper" + "\""); + // Show the video widget + qDebug() << "FTNoIR_Tracker::Initialize says: videoframe = " << videoframe; + + if (videoframe != NULL) { + videoframe->show(); + } if ( pMemData != NULL ) { pMemData->command = FT_SM_START; // Start command } - return; } -void FTNoIR_Tracker::StopTracker( bool exit ) +void FTNoIR_Tracker::WaitForExit() { qDebug() << "FTNoIR_Tracker::StopTracker says: Starting "; // stops the faceapi engine if ( pMemData != NULL ) { // if (exit == true) { - pMemData->command = (exit) ? FT_SM_EXIT : FT_SM_STOP; // Issue 'stop' command + pMemData->command = FT_SM_EXIT; //} //else { // pMemData->command = FT_SM_STOP; // Issue 'stop' command //} } - return; } bool FTNoIR_Tracker::GiveHeadPoseData(THeadPoseData *data) @@ -246,9 +240,9 @@ bool FTNoIR_Tracker::SMCreateMapping() // GetTracker - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTracker@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTracker=_GetTracker@0") +//#pragma comment(linker, "/export:GetTracker=_GetTracker@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker() +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Tracker; + return (ITracker*) new FTNoIR_Tracker; } diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp index 5c422402..b62f652c 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp @@ -24,6 +24,7 @@ ********************************************************************************/ #include "ftnoir_tracker_sm.h" #include +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // faceAPI Client Settings-dialog. @@ -338,9 +339,9 @@ void TrackerControls::doCommand(int command, int value) // GetTrackerDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTrackerDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") +//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( ) +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetDialog() { - return new TrackerControls; + return (ITrackerDialog*) new TrackerControls; } diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp index 5f01568f..70326499 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_tracker_sm.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_TrackerDll::FTNoIR_TrackerDll() { //populate the description strings @@ -67,7 +68,7 @@ void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled) void FTNoIR_TrackerDll::getIcon(QIcon *icon) { - *icon = QIcon(":/images/SeeingMachines.ico"); + *icon = QIcon(":/images/sm.png"); }; //////////////////////////////////////////////////////////////////////////////// @@ -77,9 +78,9 @@ void FTNoIR_TrackerDll::getIcon(QIcon *icon) // GetTrackerDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTrackerDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") +//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDllPtr __stdcall GetTrackerDll() +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_TrackerDll; } diff --git a/ftnoir_tracker_sm/ftnoir_tracker_sm.h b/ftnoir_tracker_sm/ftnoir_tracker_sm.h index b7aed1d0..39997970 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_sm.h +++ b/ftnoir_tracker_sm/ftnoir_tracker_sm.h @@ -31,6 +31,8 @@ #include #include "Windows.h" #include "math.h" +#include "facetracknoir/global-settings.h" +#include using namespace std; @@ -40,10 +42,10 @@ public: FTNoIR_Tracker(); ~FTNoIR_Tracker(); - void Initialize( QFrame *videoframe ); - void StartTracker( HWND parent_window ); + void StartTracker( QFrame* parent_window ); void StopTracker( bool exit ); bool GiveHeadPoseData(THeadPoseData *data); // Returns true if confidence is good + void WaitForExit(); void loadSettings(); bool SMCreateMapping(); @@ -137,7 +139,7 @@ signals: //******************************************************************************************************* // FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker //******************************************************************************************************* -class FTNoIR_TrackerDll : public ITrackerDll +class FTNoIR_TrackerDll : public Metadata { public: FTNoIR_TrackerDll(); diff --git a/ftnoir_tracker_sm/images/sm.ico b/ftnoir_tracker_sm/images/sm.ico new file mode 100644 index 00000000..19b24c84 Binary files /dev/null and b/ftnoir_tracker_sm/images/sm.ico differ diff --git a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui b/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui index 7ac6c0f4..5883e317 100644 --- a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui +++ b/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui @@ -15,7 +15,7 @@ - images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png Qt::LeftToRight diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp index 102c85bd..4978fa8d 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp @@ -23,16 +23,13 @@ * * ********************************************************************************/ #include "ftnoir_tracker_udp.h" +#include "facetracknoir/global-settings.h" FTNoIR_Tracker::FTNoIR_Tracker() { inSocket = 0; outSocket = 0; - // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); - bEnableRoll = true; bEnablePitch = true; bEnableYaw = true; @@ -51,18 +48,6 @@ FTNoIR_Tracker::FTNoIR_Tracker() FTNoIR_Tracker::~FTNoIR_Tracker() { - // Trigger thread to stop - ::SetEvent(m_StopThread); - - // Wait until thread finished - if (isRunning()) { - ::WaitForSingleObject(m_WaitThread, INFINITE); - } - - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); - if (inSocket) { inSocket->close(); delete inSocket; @@ -77,7 +62,6 @@ FTNoIR_Tracker::~FTNoIR_Tracker() /** QThread run @override **/ void FTNoIR_Tracker::run() { -int no_bytes; QHostAddress sender; quint16 senderPort; @@ -85,77 +69,51 @@ quint16 senderPort; // Read the data that was received. // forever { - - // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) - { - // Set event - ::SetEvent(m_WaitThread); - qDebug() << "FTNoIR_Tracker::run() terminated run()"; - return; - } - + if (should_quit) + break; if (inSocket != 0) { while (inSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(inSocket->pendingDatagramSize()); - + mutex.lock(); inSocket->readDatagram( (char * ) &newHeadPose, sizeof(newHeadPose), &sender, &senderPort); + mutex.unlock(); } } else { - qDebug() << "FTNoIR_Tracker::run() insocket not ready: exit run()"; - return; + break; } - //for lower cpu load usleep(10000); -// yieldCurrentThread(); - } -} - -void FTNoIR_Tracker::Initialize( QFrame *videoframe ) -{ - qDebug() << "FTNoIR_Tracker::Initialize says: Starting "; - loadSettings(); - - // - // Create UDP-sockets if they don't exist already. - // They must be created here, because they must be in the new thread (FTNoIR_Tracker::run()) - // - if (inSocket == 0) { - qDebug() << "FTNoIR_Tracker::Initialize() creating insocket"; - inSocket = new QUdpSocket(); - // Connect the inSocket to the port, to receive messages - - if (!inSocket->bind(QHostAddress::Any, (int) portAddress, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { - QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton); - delete inSocket; - inSocket = 0; - } } - - return; -} - -void FTNoIR_Tracker::StartTracker( HWND parent_window ) -{ - start( QThread::TimeCriticalPriority ); - return; } -void FTNoIR_Tracker::StopTracker( bool exit ) +void FTNoIR_Tracker::StartTracker(QFrame* videoFrame) { - // - // OK, the thread is not stopped, doing this. That might be dangerous anyway... - // - if (exit || !exit) return; + loadSettings(); + // + // Create UDP-sockets if they don't exist already. + // They must be created here, because they must be in the new thread (FTNoIR_Tracker::run()) + // + if (inSocket == 0) { + qDebug() << "FTNoIR_Tracker::Initialize() creating insocket"; + inSocket = new QUdpSocket(); + // Connect the inSocket to the port, to receive messages + + if (!inSocket->bind(QHostAddress::Any, (int) portAddress, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { + QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton); + delete inSocket; + inSocket = 0; + } + } + start(); return; } bool FTNoIR_Tracker::GiveHeadPoseData(THeadPoseData *data) { + mutex.lock(); if (bEnableX) { data->x = newHeadPose.x; } @@ -165,15 +123,16 @@ bool FTNoIR_Tracker::GiveHeadPoseData(THeadPoseData *data) if (bEnableX) { data->z = newHeadPose.z; } - if (bEnableX) { + if (bEnableYaw) { data->yaw = newHeadPose.yaw; } - if (bEnableX) { + if (bEnablePitch) { data->pitch = newHeadPose.pitch; } - if (bEnableX) { + if (bEnableRoll) { data->roll = newHeadPose.roll; } + mutex.unlock(); return true; } @@ -209,9 +168,9 @@ void FTNoIR_Tracker::loadSettings() { // GetTracker - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTracker@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTracker=_GetTracker@0") +//#pragma comment(linker, "/export:GetTracker=_GetTracker@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker() +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetConstructor() { - return new FTNoIR_Tracker; + return (ITracker*) new FTNoIR_Tracker; } diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.h b/ftnoir_tracker_udp/ftnoir_tracker_udp.h index 94645c84..d60b27a4 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.h +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.h @@ -1,39 +1,38 @@ -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" -#include "ui_FTNoIR_FTNClientcontrols.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ui_ftnoir_ftnclientcontrols.h" #include #include #include #include -#include "Windows.h" -#include "math.h" +#include +#include +#include +#include "facetracknoir/global-settings.h" -class FTNoIR_Tracker : public ITracker, QThread +class FTNoIR_Tracker : public ITracker, public QThread { public: FTNoIR_Tracker(); ~FTNoIR_Tracker(); - void Initialize( QFrame *videoframe ); - void StartTracker( HWND parent_window ); - void StopTracker( bool exit ); + void StartTracker( QFrame *videoframe ); bool GiveHeadPoseData(THeadPoseData *data); void loadSettings(); + volatile bool should_quit; + void WaitForExit() { + should_quit = true; + wait(); + } protected: void run(); // qthread override run method private: - // Handles to neatly terminate thread... - HANDLE m_StopThread; - HANDLE m_WaitThread; - // UDP socket-variables QUdpSocket *inSocket; // Receive from ... QUdpSocket *outSocket; // Send to ... QHostAddress destIP; // Destination IP-address - int destPort; // Destination port-number QHostAddress srcIP; // Source IP-address - int srcPort; // Source port-number THeadPoseData newHeadPose; // Structure with new headpose @@ -44,6 +43,7 @@ private: bool bEnableX; bool bEnableY; bool bEnableZ; + QMutex mutex; }; // Widget that has controls for FTNoIR protocol client-settings. @@ -53,7 +53,7 @@ class TrackerControls: public QWidget, Ui::UICFTNClientControls, public ITracker public: explicit TrackerControls(); - virtual ~TrackerControls(); + ~TrackerControls(); void showEvent ( QShowEvent * event ); void Initialize(QWidget *parent); @@ -78,7 +78,7 @@ private slots: //******************************************************************************************************* // FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker //******************************************************************************************************* -class FTNoIR_TrackerDll : public ITrackerDll +class FTNoIR_TrackerDll : public Metadata { public: FTNoIR_TrackerDll(); diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp index b489822a..b67afc66 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp @@ -23,6 +23,7 @@ * * ********************************************************************************/ #include "ftnoir_tracker_udp.h" +#include "facetracknoir/global-settings.h" //******************************************************************************************************* // FaceTrackNoIR Client Settings-dialog. @@ -173,9 +174,9 @@ void TrackerControls::save() { // GetTrackerDialog - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTrackerDialog@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") +//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( ) +extern "C" FTNOIR_TRACKER_BASE_EXPORT void* CALLING_CONVENTION GetDialog( ) { - return new TrackerControls; + return (ITrackerDialog*) new TrackerControls; } diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp index a086a888..cbb0c644 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp @@ -32,6 +32,7 @@ */ #include "ftnoir_tracker_udp.h" #include +#include "facetracknoir/global-settings.h" FTNoIR_TrackerDll::FTNoIR_TrackerDll() { //populate the description strings @@ -67,7 +68,7 @@ void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled) void FTNoIR_TrackerDll::getIcon(QIcon *icon) { - *icon = QIcon(":/images/FaceTrackNoIR.ico"); + *icon = QIcon(":/images/facetracknoir.png"); }; //////////////////////////////////////////////////////////////////////////////// @@ -77,9 +78,9 @@ void FTNoIR_TrackerDll::getIcon(QIcon *icon) // GetTrackerDll - Undecorated name, which can be easily used with GetProcAddress // Win32 API function. // _GetTrackerDll@0 - Common name decoration for __stdcall functions in C language. -#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") +//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDllPtr __stdcall GetTrackerDll() +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() { return new FTNoIR_TrackerDll; } diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp index 243564d1..25d5599a 100644 Binary files a/qfunctionconfigurator/functionconfig.cpp and b/qfunctionconfigurator/functionconfig.cpp differ diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h index 8dc9cf98..281007d6 100644 Binary files a/qfunctionconfigurator/functionconfig.h and b/qfunctionconfigurator/functionconfig.h differ diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp index fe2ad49d..e143a536 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ b/qfunctionconfigurator/qfunctionconfigurator.cpp @@ -1,721 +1,700 @@ -/******************************************************************************** -* FaceTrackNoIR This program is a private project of some enthusiastic * -* gamers from Holland, who don't like to pay much for * -* head-tracking. * -* * -* Copyright (C) 2012 Wim Vriend (Developing) * -* Ron Hendriks (Researching and Testing) * -* * -* Homepage http://facetracknoir.sourceforge.net/home/default.htm * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU General Public License as published by the * -* Free Software Foundation; either version 3 of the License, or (at your * -* option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * -* more details. * -* * -* You should have received a copy of the GNU General Public License along * -* with this program; if not, see . * -* * -* The FunctionConfigurator was made by Stanislaw Halik, and adapted to * -* FaceTrackNoIR. * -* * -* All credits for this nice piece of code should go to Stanislaw. * -* * -* Copyright (c) 2011-2012, Stanislaw Halik * -* Permission to use, copy, modify, and/or distribute this * -* software for any purpose with or without fee is hereby granted, * -* provided that the above copyright notice and this permission * -* notice appear in all copies. * -********************************************************************************/ -/* - Modifications (last one on top): - 20120830 - WVR: Changed functionality a bit. Now only draw the handles, when the function is drawn. - Only check mouseMoves, when they occur 'in range'. Redraw the curve, when a resize occurs. - Somehow, the curve was not drawn correctly, when this was not done (all points were too high). - After a 'Reset' this would disappear... - 20120828 - WVR: Removed bSkipText, which was used to not show a number below each vertical gridline. -*/ -#include "qfunctionconfigurator.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -QFunctionConfigurator::~QFunctionConfigurator() -{ - WaitForSingleObject(_mutex, INFINITE); - CloseHandle(_mutex); - delete btnReset; -} - -static const int pointSize = 5; - -QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) - : QWidget(parent) -{ - - // - // Defaults, for when the widget has no values different from the domXML() - // - MaxInput = 50; // Maximum input limit - MaxOutput = 180; // Maximum output limit - pPerEGU_Output = 1; // Number of pixels, per EGU - pPerEGU_Input = 4; // Number of pixels, per EGU - gDistEGU_Input = 5; // Distance of gridlines - gDistEGU_Output = 10; // Distance of gridlines - - - // Change compared to BezierConfigurator: X = horizontal (input), Y = vertical (output) - // This will require the Curve-Dialog to be higher (which was the reason it was reversed in the first place..) - range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output); - - setMouseTracking(true); - moving = NULL; // Pointer to the curve-point, that's being moved - movingPoint = 1; // Index of that same point - - // - // Add a Reset-button - // - btnReset = new QPushButton(QString("Reset"), this); - connect(btnReset, SIGNAL(clicked()), this, SLOT(resetCurve())); - - // - // Variables for FunctionConfig - // - _config = 0; - _points = QList(); - _draw_points = QList(); - _mutex = CreateMutex(NULL, false, NULL); - _draw_background = true; - _draw_function = true; - -// qDebug() << "QFunctionConfigurator::QFunctionConfigurator object created."; - -} - -// -// Attach an existing FunctionConfig to the Widget. -// -void QFunctionConfigurator::setConfig(FunctionConfig* config, QString settingsFile) { -QPointF currentPoint; -QPointF drawPoint; -qreal x; - - WaitForSingleObject(_mutex, INFINITE); - _config = config; - _points = config->getPoints(); - strSettingsFile = settingsFile; // Remember for Reset() - - qDebug() << "QFunctionConfigurator::setConfig" << config->getTitle(); - setCaption(config->getTitle()); - - // - // Get the Function Points, one for each pixel in the horizontal range. - // If the curve does not change, there is no need to run this code every time (it slows down drawing). - // - _draw_points.clear(); - for (int j = 0; j < MaxInput * pPerEGU_Input; j++) { - // - // Weird: not casting to float causes C++ to round the number... - // - x = (float) j / (float) pPerEGU_Input; - currentPoint.setX ( x ); - currentPoint.setY (_config->getValue( x )); - drawPoint = graphicalizePoint(currentPoint, "setConfig"); - if (withinRect(drawPoint, range)) { - _draw_points.append(drawPoint); -// qDebug() << "QFunctionConfigurator::setConfig _draw_Point to add = " << drawPoint; - } - } - - ReleaseMutex(_mutex); - _draw_function = true; - this->update(); -} - -// -// Load the FunctionConfig (points) from the INI-file. -// -void QFunctionConfigurator::loadSettings(QString settingsFile) { - - QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file) - strSettingsFile = settingsFile; // Remember for Reset() - qDebug() << "QFunctionConfigurator::loadSettings = " << settingsFile; - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - _config->loadSettings(iniFile); - setConfig(_config, settingsFile); - } - ReleaseMutex(_mutex); -} - -// -// Save the FunctionConfig (points) to the INI-file. -// -void QFunctionConfigurator::saveSettings(QString settingsFile) { - QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file) - strSettingsFile = settingsFile; // Remember for Reset() - qDebug() << "QFunctionConfigurator::saveSettings = " << settingsFile; - - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - _config->saveSettings(iniFile); - } - ReleaseMutex(_mutex); -} - -// -// Draw the Background for the graph, the gridlines and the gridpoints. -// The static objects are drawn on a Pixmap, so it does not have to be repeated every paintEvent. Hope this speeds things up... -// -void QFunctionConfigurator::drawBackground(const QRectF &fullRect) -{ -int i; -QRect scale; - - qDebug() << "QFunctionConfigurator::drawBackground."; - - _background = QPixmap(fullRect.width(), fullRect.height()); - QPainter painter(&_background); - - painter.save(); - painter.setRenderHint(QPainter::Antialiasing); - painter.fillRect(fullRect, colBackground); - QColor bg_color(112, 154, 209); - painter.fillRect(range, bg_color); - - QFont font("ComicSans", 4); - font.setPointSize(8); - painter.setFont(font); - - QPen pen(QColor(55, 104, 170, 127), 1, Qt::SolidLine); - - // - // Draw the Caption - // - if (_config) { - strCaption = _config->getTitle(); - } - - scale.setCoords(range.left(), 0, range.right(), 20); - painter.drawText(scale, Qt::AlignCenter, strCaption); - - // - // Draw the horizontal grid - // - for (i = range.bottom() - gDistEGU_Output * pPerEGU_Output; i >= range.top(); i -= gDistEGU_Output * pPerEGU_Output) { - drawLine(&painter, QPointF(40, i), QPointF(range.right(), i), pen); - scale.setCoords(0, i - 5, range.left() - 5, i + 5); - painter.drawText(scale, Qt::AlignRight, tr("%1").arg(((range.bottom() - i))/pPerEGU_Output)); - } - - // - // Draw the vertical guidelines - // - for (i = range.left(); i <= range.right(); i += gDistEGU_Input * pPerEGU_Input) { - drawLine(&painter, QPointF(i, range.top()), QPointF(i, range.bottom()), pen); - scale.setCoords(i - 10, range.bottom() + 2, i + 10, range.bottom() + 15); - painter.drawText(scale, Qt::AlignCenter, tr("%1").arg(abs(((range.left() - i))/pPerEGU_Input))); - } - - scale.setCoords(range.left(), range.bottom() + 20, range.right(), range.bottom() + 35); - painter.drawText(scale, Qt::AlignRight, strInputEGU); - - // - // Draw the EGU of the vertical axis (vertically!) - // - font.setPointSize(10); - painter.translate(range.topLeft().x() - 35, range.topLeft().y()); - painter.rotate(90); - painter.drawText(0,0,strOutputEGU ); - - // - // Draw the two axis - // - pen.setWidth(2); - pen.setColor( Qt::black ); - drawLine(&painter, range.topLeft() - QPointF(2,0), range.bottomLeft() - QPointF(2,0), pen); - drawLine(&painter, range.bottomLeft(), range.bottomRight(), pen); - - painter.restore(); -} - - -// -// Draw the Function for the graph, on a Pixmap. -// -void QFunctionConfigurator::drawFunction(const QRectF &fullRect) -{ - if (!_config) - return; -int i; -QPointF prevPoint; -QPointF currentPoint; - - // - // Use the background picture to draw on. - // ToDo: find out how to add Pixmaps, without getting it all green... - // - _function = QPixmap(_background); - QPainter painter(&_function); - - painter.save(); - painter.setRenderHint(QPainter::Antialiasing, false); - - // - // Draw the handles for the Points - // - for (i = 0; i < _points.size(); i++) { - currentPoint = graphicalizePoint( _points[i], "drawFunction handles" ); // Get the next point and convert it to Widget measures - drawPoint(&painter, currentPoint, QColor(200, 200, 210, 120)); - lastPoint = currentPoint; // Remember which point is the rightmost in the graph -//qDebug() << "QFunctionConfigurator::paintEvent, drawing handle for " << currentPoint; - } - - - QPen pen(colBezier, 2, Qt::SolidLine); - - prevPoint = graphicalizePoint( QPointF(0,0), "drawFunction lines" ); // Start at the Axis - double max = maxInputEGU(); - QPointF prev = graphicalizePoint(QPointF(0, 0)); - double step = 1 / (double) pixPerEGU_Input(); - for (double i = 0; i < max; i += step) { - double val = _config->getValue(i); - QPointF cur = graphicalizePoint(QPointF(i, val)); - drawLine(&painter, prev, cur, pen); - prev = cur; - } - painter.restore(); -} - -// -// The Widget paints the surface every x msecs. -// -void QFunctionConfigurator::paintEvent(QPaintEvent *e) -{ -QPointF prevPoint; -QPointF currentPoint; -QPointF actualPos; -int i; - -// qDebug() << "QFunctionConfigurator::paintEvent."; - - QPainter p(this); - p.setRenderHint(QPainter::Antialiasing); - p.setClipRect(e->rect()); - - if (_draw_background) { - drawBackground(e->rect()); // Draw the static parts on a Pixmap - p.drawPixmap(0, 0, _background); // Paint the background - _draw_background = false; - - btnReset->move(e->rect().left(), e->rect().bottom() - btnReset->height() - 2); - } - - if (_draw_function) { - drawFunction(e->rect()); // Draw the Function on a Pixmap - _draw_function = false; - } - p.drawPixmap(0, 0, _function); // Always draw the background and the function - - QPen pen(Qt::white, 1, Qt::SolidLine); - - // - // Draw the Points, that make up the Curve - // - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - - // - // When moving, also draw a sketched version of the Function. - // - if (moving) { - prevPoint = graphicalizePoint( QPointF(0,0), "paintEvent moving" ); // Start at the Axis - for (i = 0; i < _points.size(); i++) { - currentPoint = graphicalizePoint( _points[i], "paintEvent moving" ); // Get the next point and convert it to Widget measures - drawLine(&p, prevPoint, currentPoint, pen); - prevPoint = currentPoint; -// qDebug() << "QFunctionConfigurator::paintEvent, drawing while moving " << currentPoint; - } - - // - // When moving, also draw a few help-lines, so positioning the point gets easier. - // - pen.setWidth(1); - pen.setColor( Qt::white ); - pen.setStyle( Qt::DashLine ); - actualPos = graphicalizePoint(*moving, "paintEvent moving help line(s)"); - drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen); - drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen); - } - - // - // If the Tracker is active, the 'Last Point' it requested is recorded. - // Show that point on the graph, with some lines to assist. - // This new feature is very handy for tweaking the curves! - // - if (_config->getLastPoint( currentPoint )) { - -// qDebug() << "QFunctionConfigurator::paintEvent, drawing tracked Point " << currentPoint; - - actualPos = graphicalizePoint( currentPoint, "paintEvent tracking" ); - drawPoint(&p, actualPos, QColor(255, 0, 0, 120)); - - pen.setWidth(1); - pen.setColor( Qt::black ); - pen.setStyle( Qt::SolidLine ); - drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen); - drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen); - } - - } - ReleaseMutex(_mutex); - - // - // Draw the delimiters - // - pen.setWidth(1); - pen.setColor( Qt::white ); - pen.setStyle( Qt::SolidLine ); - drawLine(&p, QPoint(lastPoint.x(), range.top()), QPoint(lastPoint.x(), range.bottom()), pen); - drawLine(&p, QPoint(range.left(), lastPoint.y()), QPoint(range.right(), lastPoint.y()), pen); - - QTimer::singleShot(250, this, SLOT(update())); -} - -// -// Draw the handle, to move the Bezier-curve. -// -void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QColor colBG ) -{ - painter->save(); - painter->setPen(QColor(50, 100, 120, 200)); - painter->setBrush( colBG ); - painter->drawEllipse(QRectF(pos.x() - pointSize, - pos.y() - pointSize, - pointSize*2, pointSize*2)); - painter->restore(); -} - -void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen) -{ - painter->save(); - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawLine(start, end); - painter->restore(); -} - -// -// If the mousebutton is pressed, check if it is inside one of the Points. -// If so: start moving that Point, until mouse release. -// -void QFunctionConfigurator::mousePressEvent(QMouseEvent *e) -{ - // - // First: check the left mouse-button - // - if (e->button() == Qt::LeftButton) { - - // - // Check to see if the cursor is touching one of the points. - // - bool bTouchingPoint = false; - movingPoint = -1; - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - - for (int i = 0; i < _points.size(); i++) { - if ( markContains( graphicalizePoint( _points[i], "mousePressEvent markContains" ), e->pos() ) ) { - bTouchingPoint = true; - moving = &_points[i]; - movingPoint = i; - } - } - - // - // If the Left Mouse-button was clicked without touching a Point, add a new Point - // - if (!bTouchingPoint) { - if (withinRect(e->pos(), range)) { - _config->addPoint(normalizePoint(e->pos())); - setConfig(_config, strSettingsFile); - moving = NULL; - emit CurveChanged( true ); - } - } - } - ReleaseMutex(_mutex); - } - - // - // Then: check the right mouse-button - // - if (e->button() == Qt::RightButton) { - - // - // Check to see if the cursor is touching one of the points. - // - moving = NULL; - movingPoint = -1; - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - - for (int i = 0; i < _points.size(); i++) { - if ( markContains( graphicalizePoint( _points[i], "mousePressEvent RightButton" ), e->pos() ) ) { - movingPoint = i; - } - } - - // - // If the Right Mouse-button was clicked while touching a Point, remove the Point - // - if (movingPoint >= 0) { - _config->removePoint(movingPoint); - setConfig(_config, strSettingsFile); - movingPoint = -1; - emit CurveChanged( true ); - } - } - ReleaseMutex(_mutex); - } - -} - -// -// If the mouse if moving, make sure the Bezier moves along. -// Of course, only when a Point is selected... -// -void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) -{ - - if (moving) { - - setCursor(Qt::ClosedHandCursor); - - // - // Change the currently moving Point. - // - *moving = normalizePoint(e->pos()); - update(); - } - else { - - // - // Check to see if the cursor is touching one of the points. - // - bool bTouchingPoint = false; - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - - for (int i = 0; i < _points.size(); i++) { - if ( markContains( graphicalizePoint( _points[i], "mouseMoveEvent" ), e->pos() ) ) { - bTouchingPoint = true; - } - } - } - ReleaseMutex(_mutex); - - if ( bTouchingPoint ) { - setCursor(Qt::OpenHandCursor); - } - else { - setCursor(Qt::ArrowCursor); - } - - } -} - -void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e) -{ - //qDebug()<<"releasing"; - if (moving > 0) { - emit CurveChanged( true ); - - // - // Update the Point in the _config - // - WaitForSingleObject(_mutex, INFINITE); - if (_config) { - _config->movePoint(movingPoint, normalizePoint(e->pos())); - setConfig(_config, strSettingsFile); - } - ReleaseMutex(_mutex); - - } - setCursor(Qt::ArrowCursor); - moving = NULL; - movingPoint = 0; -} - -// -// Determine if the mousebutton was pressed within the range of the Point. -// -bool QFunctionConfigurator::markContains(const QPointF &pos, const QPointF &coord) const -{ - QRectF rect(pos.x() - pointSize, - pos.y() - pointSize, - pointSize*2, pointSize*2); - QPainterPath path; - path.addEllipse(rect); - return path.contains(coord); -} - -bool QFunctionConfigurator::withinRect( const QPointF &coord, const QRectF &rect ) const -{ - QPainterPath path; - path.addRect(rect); - return path.contains(coord); -} - -// -// Convert the Point in the graph, to the real-life Point. -// -QPointF QFunctionConfigurator::normalizePoint(QPointF point) const -{ - QPointF norm; - - norm.setX( (point.x() - range.left()) / pPerEGU_Input ); - norm.setY( (range.bottom() - point.y()) / pPerEGU_Output ); - - if (norm.x() > maxInputEGU()) - norm.setX(maxInputEGU()); - else if (norm.x() < 0) - norm.setX(0); - if (norm.y() > maxOutputEGU()) - norm.setY(maxOutputEGU()); - else if (norm.y() < 0) - norm.setY(0); - - return norm; -} - -// -// Convert the real-life Point into the graphical Point. -// -QPointF QFunctionConfigurator::graphicalizePoint(QPointF point, QString source) const -{ -QPointF graph; - - graph.setX( range.left() + (fabs(point.x()) * pPerEGU_Input) ); - graph.setY( range.bottom() - (fabs(point.y()) * pPerEGU_Output) ); - -// qDebug() << "QFunctionConfigurator::graphicalizePoint source = " << source << ", point = " << point << ", graph = " << graph; - - return graph; -} - -void QFunctionConfigurator::setmaxInputEGU(int value) -{ - MaxInput = value; - setMinimumWidth(MaxInput * pPerEGU_Input + 55); -// resetCurve(); - resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); -} -void QFunctionConfigurator::setmaxOutputEGU(int value) -{ - MaxOutput = value; - setMinimumHeight(MaxOutput * pPerEGU_Output + 60); -// resetCurve(); - resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); -} - -// -// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined. -// -void QFunctionConfigurator::setpixPerEGU_Input(int value) -{ - pPerEGU_Input = value; - setMinimumWidth(MaxInput * pPerEGU_Input + 55); - resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); -} - -// -// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined. -// -void QFunctionConfigurator::setpixPerEGU_Output(int value) -{ - pPerEGU_Output = value; - setMinimumHeight(MaxOutput * pPerEGU_Output + 60); - resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); -} - -// -// Define the distance of the grid 'in EGU' points. -// -void QFunctionConfigurator::setgridDistEGU_Input(int value) -{ - gDistEGU_Input = value; - _draw_background = true; - _draw_function = true; - repaint(); -} - -// -// Define the distance of the grid 'in EGU' points. -// -void QFunctionConfigurator::setgridDistEGU_Output(int value) -{ - gDistEGU_Output = value; - _draw_background = true; - _draw_function = true; - repaint(); -} - -void QFunctionConfigurator::setColorBezier(QColor color) -{ - colBezier = color; - update(); -} -void QFunctionConfigurator::setColorBackground(QColor color) -{ - colBackground = color; - update(); -} - -void QFunctionConfigurator::setInputEGU(QString egu) -{ - strInputEGU = egu; - update(); -} -void QFunctionConfigurator::setOutputEGU(QString egu) -{ - strOutputEGU = egu; - update(); -} -void QFunctionConfigurator::setCaption(QString cap) -{ - strCaption = cap; - update(); -} - -void QFunctionConfigurator::resizeEvent(QResizeEvent *e) -{ - QSize s = e->size(); - range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output); - - qDebug() << "QFunctionConfigurator::resizeEvent, name = " << strCaption << ",range = " << range; - - if (_config) { - setConfig(_config, strSettingsFile); - } - _draw_background = true; - _draw_function = true; - repaint(); -} +/******************************************************************************** +* FaceTrackNoIR This program is a private project of some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2012 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage http://facetracknoir.sourceforge.net/home/default.htm * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +* * +* The FunctionConfigurator was made by Stanislaw Halik, and adapted to * +* FaceTrackNoIR. * +* * +* All credits for this nice piece of code should go to Stanislaw. * +* * +* Copyright (c) 2011-2012, Stanislaw Halik * +* Permission to use, copy, modify, and/or distribute this * +* software for any purpose with or without fee is hereby granted, * +* provided that the above copyright notice and this permission * +* notice appear in all copies. * +********************************************************************************/ +/* + Modifications (last one on top): + 20120830 - WVR: Changed functionality a bit. Now only draw the handles, when the function is drawn. + Only check mouseMoves, when they occur 'in range'. Redraw the curve, when a resize occurs. + Somehow, the curve was not drawn correctly, when this was not done (all points were too high). + After a 'Reset' this would disappear... + 20120828 - WVR: Removed bSkipText, which was used to not show a number below each vertical gridline. +*/ +#include "qfunctionconfigurator/qfunctionconfigurator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +QFunctionConfigurator::~QFunctionConfigurator() +{ + delete btnReset; +} + +static const int pointSize = 5; + +QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) + : QWidget(parent) +{ + + // + // Defaults, for when the widget has no values different from the domXML() + // + MaxInput = 50; // Maximum input limit + MaxOutput = 180; // Maximum output limit + pPerEGU_Output = 1; // Number of pixels, per EGU + pPerEGU_Input = 4; // Number of pixels, per EGU + gDistEGU_Input = 5; // Distance of gridlines + gDistEGU_Output = 10; // Distance of gridlines + + + // Change compared to BezierConfigurator: X = horizontal (input), Y = vertical (output) + // This will require the Curve-Dialog to be higher (which was the reason it was reversed in the first place..) + range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output); + + setMouseTracking(true); + moving = NULL; // Pointer to the curve-point, that's being moved + movingPoint = 1; // Index of that same point + + // + // Add a Reset-button + // + btnReset = new QPushButton(QString("Reset"), this); + connect(btnReset, SIGNAL(clicked()), this, SLOT(resetCurve())); + + // + // Variables for FunctionConfig + // + _config = 0; + _points = QList(); + _draw_points = QList(); + _draw_background = true; + _draw_function = true; + +// qDebug() << "QFunctionConfigurator::QFunctionConfigurator object created."; + +} + +// +// Attach an existing FunctionConfig to the Widget. +// +void QFunctionConfigurator::setConfig(FunctionConfig* config, QString settingsFile) { +QPointF currentPoint; +QPointF drawPoint; +qreal x; + + _config = config; + _points = config->getPoints(); + strSettingsFile = settingsFile; // Remember for Reset() + + qDebug() << "QFunctionConfigurator::setConfig" << config->getTitle(); + setCaption(config->getTitle()); + + // + // Get the Function Points, one for each pixel in the horizontal range. + // If the curve does not change, there is no need to run this code every time (it slows down drawing). + // + _draw_points.clear(); + for (int j = 0; j < MaxInput * pPerEGU_Input; j++) { + // + // Weird: not casting to float causes C++ to round the number... + // + x = (float) j / (float) pPerEGU_Input; + currentPoint.setX ( x ); + currentPoint.setY (_config->getValue( x )); + drawPoint = graphicalizePoint(currentPoint, "setConfig"); + if (withinRect(drawPoint, range)) { + _draw_points.append(drawPoint); +// qDebug() << "QFunctionConfigurator::setConfig _draw_Point to add = " << drawPoint; + } + } + + _draw_function = true; + this->update(); +} + +// +// Load the FunctionConfig (points) from the INI-file. +// +void QFunctionConfigurator::loadSettings(QString settingsFile) { + + QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file) + strSettingsFile = settingsFile; // Remember for Reset() + qDebug() << "QFunctionConfigurator::loadSettings = " << settingsFile; + if (_config) { + _config->loadSettings(iniFile); + setConfig(_config, settingsFile); + } +} + +// +// Save the FunctionConfig (points) to the INI-file. +// +void QFunctionConfigurator::saveSettings(QString settingsFile) { + QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file) + strSettingsFile = settingsFile; // Remember for Reset() + qDebug() << "QFunctionConfigurator::saveSettings = " << settingsFile; + + if (_config) { + _config->saveSettings(iniFile); + } +} + +// +// Draw the Background for the graph, the gridlines and the gridpoints. +// The static objects are drawn on a Pixmap, so it does not have to be repeated every paintEvent. Hope this speeds things up... +// +void QFunctionConfigurator::drawBackground(const QRectF &fullRect) +{ +int i; +QRect scale; + + qDebug() << "QFunctionConfigurator::drawBackground."; + + _background = QPixmap(fullRect.width(), fullRect.height()); + QPainter painter(&_background); + + painter.save(); + painter.setRenderHint(QPainter::Antialiasing); + painter.fillRect(fullRect, colBackground); + QColor bg_color(112, 154, 209); + painter.fillRect(range, bg_color); + + QFont font("ComicSans", 4); + font.setPointSize(8); + painter.setFont(font); + + QPen pen(QColor(55, 104, 170, 127), 1, Qt::SolidLine); + + // + // Draw the Caption + // + if (_config) { + strCaption = _config->getTitle(); + } + + scale.setCoords(range.left(), 0, range.right(), 20); + painter.drawText(scale, Qt::AlignCenter, strCaption); + + // + // Draw the horizontal grid + // + for (i = range.bottom() - gDistEGU_Output * pPerEGU_Output; i >= range.top(); i -= gDistEGU_Output * pPerEGU_Output) { + drawLine(&painter, QPointF(40, i), QPointF(range.right(), i), pen); + scale.setCoords(0, i - 5, range.left() - 5, i + 5); + painter.drawText(scale, Qt::AlignRight, tr("%1").arg(((range.bottom() - i))/pPerEGU_Output)); + } + + // + // Draw the vertical guidelines + // + for (i = range.left(); i <= range.right(); i += gDistEGU_Input * pPerEGU_Input) { + drawLine(&painter, QPointF(i, range.top()), QPointF(i, range.bottom()), pen); + scale.setCoords(i - 10, range.bottom() + 2, i + 10, range.bottom() + 15); + painter.drawText(scale, Qt::AlignCenter, tr("%1").arg(abs(((range.left() - i))/pPerEGU_Input))); + } + + scale.setCoords(range.left(), range.bottom() + 20, range.right(), range.bottom() + 35); + painter.drawText(scale, Qt::AlignRight, strInputEGU); + + // + // Draw the EGU of the vertical axis (vertically!) + // + font.setPointSize(10); + painter.translate(range.topLeft().x() - 35, range.topLeft().y()); + painter.rotate(90); + painter.drawText(0,0,strOutputEGU ); + + // + // Draw the two axis + // + pen.setWidth(2); + pen.setColor( Qt::black ); + drawLine(&painter, range.topLeft() - QPointF(2,0), range.bottomLeft() - QPointF(2,0), pen); + drawLine(&painter, range.bottomLeft(), range.bottomRight(), pen); + + painter.restore(); +} + + +// +// Draw the Function for the graph, on a Pixmap. +// +void QFunctionConfigurator::drawFunction(const QRectF &fullRect) +{ + if (!_config) + return; +int i; +QPointF prevPoint; +QPointF currentPoint; + + // + // Use the background picture to draw on. + // ToDo: find out how to add Pixmaps, without getting it all green... + // + _function = QPixmap(_background); + QPainter painter(&_function); + + painter.save(); + painter.setRenderHint(QPainter::Antialiasing, true); + + // + // Draw the handles for the Points + // + for (i = 0; i < _points.size(); i++) { + currentPoint = graphicalizePoint( _points[i], "drawFunction handles" ); // Get the next point and convert it to Widget measures + drawPoint(&painter, currentPoint, QColor(200, 200, 210, 120)); + lastPoint = currentPoint; // Remember which point is the rightmost in the graph +//qDebug() << "QFunctionConfigurator::paintEvent, drawing handle for " << currentPoint; + } + + + QPen pen(colBezier, 1.5, Qt::SolidLine); + + prevPoint = graphicalizePoint( QPointF(0,0), "drawFunction lines" ); // Start at the Axis + double max = maxInputEGU(); + QPointF prev = graphicalizePoint(QPointF(0, 0)); + double step = 1 / (double) pixPerEGU_Input(); + for (double i = 0; i < max; i += step) { + double val = _config->getValue(i); + QPointF cur = graphicalizePoint(QPointF(i, val)); + drawLine(&painter, prev, cur, pen); + prev = cur; + } + painter.restore(); +} + +// +// The Widget paints the surface every x msecs. +// +void QFunctionConfigurator::paintEvent(QPaintEvent *e) +{ +QPointF prevPoint; +QPointF currentPoint; +QPointF actualPos; +int i; + +// qDebug() << "QFunctionConfigurator::paintEvent."; + + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + p.setClipRect(e->rect()); + + if (_draw_background) { + drawBackground(e->rect()); // Draw the static parts on a Pixmap + p.drawPixmap(0, 0, _background); // Paint the background + _draw_background = false; + + btnReset->move(e->rect().left(), e->rect().bottom() - btnReset->height() - 2); + } + + if (_draw_function) { + drawFunction(e->rect()); // Draw the Function on a Pixmap + _draw_function = false; + } + p.drawPixmap(0, 0, _function); // Always draw the background and the function + + QPen pen(Qt::white, 1, Qt::SolidLine); + + // + // Draw the Points, that make up the Curve + // + if (_config) { + + // + // When moving, also draw a sketched version of the Function. + // + if (moving) { + prevPoint = graphicalizePoint( QPointF(0,0), "paintEvent moving" ); // Start at the Axis + for (i = 0; i < _points.size(); i++) { + currentPoint = graphicalizePoint( _points[i], "paintEvent moving" ); // Get the next point and convert it to Widget measures + drawLine(&p, prevPoint, currentPoint, pen); + prevPoint = currentPoint; +// qDebug() << "QFunctionConfigurator::paintEvent, drawing while moving " << currentPoint; + } + + // + // When moving, also draw a few help-lines, so positioning the point gets easier. + // + pen.setWidth(1); + pen.setColor( Qt::white ); + pen.setStyle( Qt::DashLine ); + actualPos = graphicalizePoint(*moving, "paintEvent moving help line(s)"); + drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen); + drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen); + } + + // + // If the Tracker is active, the 'Last Point' it requested is recorded. + // Show that point on the graph, with some lines to assist. + // This new feature is very handy for tweaking the curves! + // + if (_config->getLastPoint( currentPoint )) { + +// qDebug() << "QFunctionConfigurator::paintEvent, drawing tracked Point " << currentPoint; + + actualPos = graphicalizePoint( currentPoint, "paintEvent tracking" ); + drawPoint(&p, actualPos, QColor(255, 0, 0, 120)); + + pen.setWidth(1); + pen.setColor( Qt::black ); + pen.setStyle( Qt::SolidLine ); + drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen); + drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen); + } + + } + + // + // Draw the delimiters + // + pen.setWidth(1); + pen.setColor( Qt::white ); + pen.setStyle( Qt::SolidLine ); + drawLine(&p, QPoint(lastPoint.x(), range.top()), QPoint(lastPoint.x(), range.bottom()), pen); + drawLine(&p, QPoint(range.left(), lastPoint.y()), QPoint(range.right(), lastPoint.y()), pen); + + QTimer::singleShot(50, this, SLOT(update())); +} + +// +// Draw the handle, to move the Bezier-curve. +// +void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QColor colBG ) +{ + painter->save(); + painter->setPen(QColor(50, 100, 120, 200)); + painter->setBrush( colBG ); + painter->drawEllipse(QRectF(pos.x() - pointSize, + pos.y() - pointSize, + pointSize*2, pointSize*2)); + painter->restore(); +} + +void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen) +{ + painter->save(); + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawLine(start, end); + painter->restore(); +} + +// +// If the mousebutton is pressed, check if it is inside one of the Points. +// If so: start moving that Point, until mouse release. +// +void QFunctionConfigurator::mousePressEvent(QMouseEvent *e) +{ + // + // First: check the left mouse-button + // + if (e->button() == Qt::LeftButton) { + + // + // Check to see if the cursor is touching one of the points. + // + bool bTouchingPoint = false; + movingPoint = -1; + if (_config) { + + for (int i = 0; i < _points.size(); i++) { + if ( markContains( graphicalizePoint( _points[i], "mousePressEvent markContains" ), e->pos() ) ) { + bTouchingPoint = true; + moving = &_points[i]; + movingPoint = i; + } + } + + // + // If the Left Mouse-button was clicked without touching a Point, add a new Point + // + if (!bTouchingPoint) { + if (withinRect(e->pos(), range)) { + _config->addPoint(normalizePoint(e->pos())); + setConfig(_config, strSettingsFile); + moving = NULL; + emit CurveChanged( true ); + } + } + } + } + + // + // Then: check the right mouse-button + // + if (e->button() == Qt::RightButton) { + + // + // Check to see if the cursor is touching one of the points. + // + moving = NULL; + movingPoint = -1; + if (_config) { + + for (int i = 0; i < _points.size(); i++) { + if ( markContains( graphicalizePoint( _points[i], "mousePressEvent RightButton" ), e->pos() ) ) { + movingPoint = i; + } + } + + // + // If the Right Mouse-button was clicked while touching a Point, remove the Point + // + if (movingPoint >= 0) { + _config->removePoint(movingPoint); + setConfig(_config, strSettingsFile); + movingPoint = -1; + emit CurveChanged( true ); + } + } + } + +} + +// +// If the mouse if moving, make sure the Bezier moves along. +// Of course, only when a Point is selected... +// +void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) +{ + + if (moving) { + + setCursor(Qt::ClosedHandCursor); + + // + // Change the currently moving Point. + // + *moving = normalizePoint(e->pos()); + update(); + } + else { + + // + // Check to see if the cursor is touching one of the points. + // + bool bTouchingPoint = false; + if (_config) { + + for (int i = 0; i < _points.size(); i++) { + if ( markContains( graphicalizePoint( _points[i], "mouseMoveEvent" ), e->pos() ) ) { + bTouchingPoint = true; + } + } + } + + if ( bTouchingPoint ) { + setCursor(Qt::OpenHandCursor); + } + else { + setCursor(Qt::ArrowCursor); + } + + } +} + +void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e) +{ + //qDebug()<<"releasing"; + if (moving > 0) { + emit CurveChanged( true ); + + // + // Update the Point in the _config + // + if (_config) { + _config->movePoint(movingPoint, normalizePoint(e->pos())); + setConfig(_config, strSettingsFile); + } + } + setCursor(Qt::ArrowCursor); + moving = NULL; + movingPoint = 0; +} + +// +// Determine if the mousebutton was pressed within the range of the Point. +// +bool QFunctionConfigurator::markContains(const QPointF &pos, const QPointF &coord) const +{ + QRectF rect(pos.x() - pointSize, + pos.y() - pointSize, + pointSize*2, pointSize*2); + QPainterPath path; + path.addEllipse(rect); + return path.contains(coord); +} + +bool QFunctionConfigurator::withinRect( const QPointF &coord, const QRectF &rect ) const +{ + QPainterPath path; + path.addRect(rect); + return path.contains(coord); +} + +// +// Convert the Point in the graph, to the real-life Point. +// +QPointF QFunctionConfigurator::normalizePoint(QPointF point) const +{ + QPointF norm; + + norm.setX( (point.x() - range.left()) / pPerEGU_Input ); + norm.setY( (range.bottom() - point.y()) / pPerEGU_Output ); + + if (norm.x() > maxInputEGU()) + norm.setX(maxInputEGU()); + else if (norm.x() < 0) + norm.setX(0); + if (norm.y() > maxOutputEGU()) + norm.setY(maxOutputEGU()); + else if (norm.y() < 0) + norm.setY(0); + + return norm; +} + +// +// Convert the real-life Point into the graphical Point. +// +QPointF QFunctionConfigurator::graphicalizePoint(QPointF point, QString source) const +{ +QPointF graph; + + graph.setX( range.left() + (fabs(point.x()) * pPerEGU_Input) ); + graph.setY( range.bottom() - (fabs(point.y()) * pPerEGU_Output) ); + +// qDebug() << "QFunctionConfigurator::graphicalizePoint source = " << source << ", point = " << point << ", graph = " << graph; + + return graph; +} + +void QFunctionConfigurator::setmaxInputEGU(int value) +{ + MaxInput = value; + setMinimumWidth(MaxInput * pPerEGU_Input + 55); +// resetCurve(); + resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); +} +void QFunctionConfigurator::setmaxOutputEGU(int value) +{ + MaxOutput = value; + setMinimumHeight(MaxOutput * pPerEGU_Output + 60); +// resetCurve(); + resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); +} + +// +// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined. +// +void QFunctionConfigurator::setpixPerEGU_Input(int value) +{ + pPerEGU_Input = value; + setMinimumWidth(MaxInput * pPerEGU_Input + 55); + resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); +} + +// +// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined. +// +void QFunctionConfigurator::setpixPerEGU_Output(int value) +{ + pPerEGU_Output = value; + setMinimumHeight(MaxOutput * pPerEGU_Output + 60); + resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 ); +} + +// +// Define the distance of the grid 'in EGU' points. +// +void QFunctionConfigurator::setgridDistEGU_Input(int value) +{ + gDistEGU_Input = value; + _draw_background = true; + _draw_function = true; + repaint(); +} + +// +// Define the distance of the grid 'in EGU' points. +// +void QFunctionConfigurator::setgridDistEGU_Output(int value) +{ + gDistEGU_Output = value; + _draw_background = true; + _draw_function = true; + repaint(); +} + +void QFunctionConfigurator::setColorBezier(QColor color) +{ + colBezier = color; + update(); +} +void QFunctionConfigurator::setColorBackground(QColor color) +{ + colBackground = color; + update(); +} + +void QFunctionConfigurator::setInputEGU(QString egu) +{ + strInputEGU = egu; + update(); +} +void QFunctionConfigurator::setOutputEGU(QString egu) +{ + strOutputEGU = egu; + update(); +} +void QFunctionConfigurator::setCaption(QString cap) +{ + strCaption = cap; + update(); +} + +void QFunctionConfigurator::resizeEvent(QResizeEvent *e) +{ + range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output); + + qDebug() << "QFunctionConfigurator::resizeEvent, name = " << strCaption << ",range = " << range; + + if (_config) { + setConfig(_config, strSettingsFile); + } + _draw_background = true; + _draw_function = true; + repaint(); +} diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h index c467bc92..6ad810c1 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.h +++ b/qfunctionconfigurator/qfunctionconfigurator.h @@ -1,206 +1,207 @@ -/******************************************************************************** -* FaceTrackNoIR This program is a private project of some enthusiastic * -* gamers from Holland, who don't like to pay much for * -* head-tracking. * -* * -* Copyright (C) 2012 Wim Vriend (Developing) * -* Ron Hendriks (Researching and Testing) * -* * -* Homepage http://facetracknoir.sourceforge.net/home/default.htm * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU General Public License as published by the * -* Free Software Foundation; either version 3 of the License, or (at your * -* option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * -* more details. * -* * -* You should have received a copy of the GNU General Public License along * -* with this program; if not, see . * -* * -* The FunctionConfigurator was made by Stanislaw Halik, and adapted to * -* FaceTrackNoIR. * -* * -* All credits for this nice piece of code should go to Stanislaw. * -* * -* Copyright (c) 2011-2012, Stanislaw Halik * -* Permission to use, copy, modify, and/or distribute this * -* software for any purpose with or without fee is hereby granted, * -* provided that the above copyright notice and this permission * -* notice appear in all copies. * -********************************************************************************/ -#ifndef QFUNCTIONCONFIGURATOR_H -#define QFUNCTIONCONFIGURATOR_H - -#include -#include -#include -#include "FunctionConfig.h" - -// -// The FunctionConfigurator Widget is used to display and configure a function (curve). -// The Function is used by FaceTrackNoIR to 'translate' the actual head-pose to the virtual headpose. Every axis is configured by a separate Function. -// -// The Function is coded in a separate Class and can exists, without the Widget. When the widget is displayed (therefore 'created'), the Function can be attached to the -// Widget and the Widget used to change the Function. -// -class QDESIGNER_WIDGET_EXPORT QFunctionConfigurator : public QWidget -{ - Q_OBJECT - Q_PROPERTY(int maxInputEGU READ maxInputEGU WRITE setmaxInputEGU); - Q_PROPERTY(int maxOutputEGU READ maxOutputEGU WRITE setmaxOutputEGU); - Q_PROPERTY(int pixPerEGU_Input READ pixPerEGU_Input WRITE setpixPerEGU_Input); - Q_PROPERTY(int pixPerEGU_Output READ pixPerEGU_Output WRITE setpixPerEGU_Output); - Q_PROPERTY(int gridDistEGU_Input READ gridDistEGU_Input WRITE setgridDistEGU_Input); - Q_PROPERTY(int gridDistEGU_Output READ gridDistEGU_Output WRITE setgridDistEGU_Output); - - Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier); - Q_PROPERTY(QColor colorBackground READ colorBackground WRITE setColorBackground); - Q_PROPERTY(QString stringInputEGU READ stringInputEGU WRITE setInputEGU); - Q_PROPERTY(QString stringOutputEGU READ stringOutputEGU WRITE setOutputEGU); - Q_PROPERTY(QString stringCaption READ stringCaption WRITE setCaption); - - // Return the current value to Designer - int maxInputEGU() const - { - return MaxInput; - } - int maxOutputEGU() const - { - return MaxOutput; - } - int pixPerEGU_Input() const - { - return pPerEGU_Input; - } - int pixPerEGU_Output() const - { - return pPerEGU_Output; - } - int gridDistEGU_Input() const - { - return gDistEGU_Input; - } - int gridDistEGU_Output() const - { - return gDistEGU_Output; - } - - // Return the current color to Designer - QColor colorBezier() const - { - return colBezier; - } - // Return the current color to Designer - QColor colorBackground() const - { - return colBackground; - } - // Return the current string to Designer - QString stringInputEGU() const - { - return strInputEGU; - } - // Return the current string to Designer - QString stringOutputEGU() const - { - return strOutputEGU; - } - // Return the current string to Designer - QString stringCaption() const - { - return strCaption; - } - -public: - QFunctionConfigurator(QWidget *parent = 0); - ~QFunctionConfigurator(); - FunctionConfig* config(); - - void setConfig(FunctionConfig* config, QString settingsFile); // Connect the FunctionConfig to the Widget. - void loadSettings(QString settingsFile); // Load the FunctionConfig (points) from the INI-file - void saveSettings(QString settingsFile); // Save the FunctionConfig (points) to the INI-file - -signals: - void CurveChanged(bool); - -public slots: - void setmaxInputEGU(int); - void setmaxOutputEGU(int); - void setpixPerEGU_Input(int); - void setpixPerEGU_Output(int); - void setgridDistEGU_Input(int); - void setgridDistEGU_Output(int); - - void setColorBezier(QColor); - void setColorBackground(QColor); - void setInputEGU(QString); - void setOutputEGU(QString); - void setCaption(QString); - - void resetCurve() { - qDebug() << "QFunctionConfigurator::resetCurve = " << strSettingsFile; - loadSettings( strSettingsFile ); - } - -protected slots: - void paintEvent(QPaintEvent *e); - void mousePressEvent(QMouseEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - -protected: - void drawBackground(const QRectF &rect); - void drawFunction(const QRectF &rect); - void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG ); - void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen); - bool markContains(const QPointF &pt, const QPointF &coord) const; -// bool withinRange( const QPointF &coord ) const; - bool withinRect( const QPointF &coord, const QRectF &rect ) const; - -protected: - virtual void resizeEvent(QResizeEvent *); - -private: - QRectF range; // The actual rectangle for the Bezier-curve - QPointF lastPoint; // The right-most point of the Function - QPointF normalizePoint (QPointF point) const; // Convert the graphical Point to a real-life Point - QPointF graphicalizePoint (QPointF point, QString source = "") const; // Convert the Point to a graphical Point - - QPointF *moving; - int movingPoint; - - int MaxInput; // Maximum input limit - int MaxOutput; // Maximum output limit - int pPerEGU_Input; // Number of pixels, per EGU of Input - int pPerEGU_Output; // Number of pixels, per EGU of Output - int gDistEGU_Input; // Distance of the grid, in EGU of Input - int gDistEGU_Output; // Distance of the grid, in EGU of Output - - QColor colBezier; // Color of Bezier curve - QColor colBackground; // Color of widget background - QString strInputEGU; // Engineering Units input (vertical axis) - QString strOutputEGU; // Engineering Units output (horizontal axis) - QString strCaption; // Caption of the graph - QString strSettingsFile; // Name of last read INI-file - QPushButton *btnReset; // Reset Curve - - bool _draw_background; // Flag to determine if the background should be (re-)drawn on the QPixmap - QPixmap _background; // Image of the static parts (axis, lines, etc.) - bool _draw_function; // Flag to determine if the function should be (re-)drawn on the QPixmap - QPixmap _function; // Image of the function (static unless edited by the user) - - // - // Properties of the CurveConfigurator Widget - // - QString _title; // Title do display in Widget and to load Settings - FunctionConfig* _config; - QList _points; // Function-points - QList _draw_points; // Curve-points needed for drawing - HANDLE _mutex; -}; - -#endif // QFUNCTIONCONFIGURATOR_H +/******************************************************************************** +* FaceTrackNoIR This program is a private project of some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2012 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage http://facetracknoir.sourceforge.net/home/default.htm * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +* * +* The FunctionConfigurator was made by Stanislaw Halik, and adapted to * +* FaceTrackNoIR. * +* * +* All credits for this nice piece of code should go to Stanislaw. * +* * +* Copyright (c) 2011-2012, Stanislaw Halik * +* Permission to use, copy, modify, and/or distribute this * +* software for any purpose with or without fee is hereby granted, * +* provided that the above copyright notice and this permission * +* notice appear in all copies. * +********************************************************************************/ +#ifndef QFUNCTIONCONFIGURATOR_H +#define QFUNCTIONCONFIGURATOR_H + +#include +#include +#include +#include +#include "qfunctionconfigurator/functionconfig.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" + +// +// The FunctionConfigurator Widget is used to display and configure a function (curve). +// The Function is used by FaceTrackNoIR to 'translate' the actual head-pose to the virtual headpose. Every axis is configured by a separate Function. +// +// The Function is coded in a separate Class and can exists, without the Widget. When the widget is displayed (therefore 'created'), the Function can be attached to the +// Widget and the Widget used to change the Function. +// +class FTNOIR_TRACKER_BASE_EXPORT QFunctionConfigurator : public QWidget +{ + Q_OBJECT + Q_PROPERTY(int maxInputEGU READ maxInputEGU WRITE setmaxInputEGU); + Q_PROPERTY(int maxOutputEGU READ maxOutputEGU WRITE setmaxOutputEGU); + Q_PROPERTY(int pixPerEGU_Input READ pixPerEGU_Input WRITE setpixPerEGU_Input); + Q_PROPERTY(int pixPerEGU_Output READ pixPerEGU_Output WRITE setpixPerEGU_Output); + Q_PROPERTY(int gridDistEGU_Input READ gridDistEGU_Input WRITE setgridDistEGU_Input); + Q_PROPERTY(int gridDistEGU_Output READ gridDistEGU_Output WRITE setgridDistEGU_Output); + + Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier); + Q_PROPERTY(QColor colorBackground READ colorBackground WRITE setColorBackground); + Q_PROPERTY(QString stringInputEGU READ stringInputEGU WRITE setInputEGU); + Q_PROPERTY(QString stringOutputEGU READ stringOutputEGU WRITE setOutputEGU); + Q_PROPERTY(QString stringCaption READ stringCaption WRITE setCaption); + + // Return the current value to Designer + int maxInputEGU() const + { + return MaxInput; + } + int maxOutputEGU() const + { + return MaxOutput; + } + int pixPerEGU_Input() const + { + return pPerEGU_Input; + } + int pixPerEGU_Output() const + { + return pPerEGU_Output; + } + int gridDistEGU_Input() const + { + return gDistEGU_Input; + } + int gridDistEGU_Output() const + { + return gDistEGU_Output; + } + + // Return the current color to Designer + QColor colorBezier() const + { + return colBezier; + } + // Return the current color to Designer + QColor colorBackground() const + { + return colBackground; + } + // Return the current string to Designer + QString stringInputEGU() const + { + return strInputEGU; + } + // Return the current string to Designer + QString stringOutputEGU() const + { + return strOutputEGU; + } + // Return the current string to Designer + QString stringCaption() const + { + return strCaption; + } + +public: + QFunctionConfigurator(QWidget *parent = 0); + ~QFunctionConfigurator(); + FunctionConfig* config(); + + void setConfig(FunctionConfig* config, QString settingsFile); // Connect the FunctionConfig to the Widget. + void loadSettings(QString settingsFile); // Load the FunctionConfig (points) from the INI-file + void saveSettings(QString settingsFile); // Save the FunctionConfig (points) to the INI-file + +signals: + void CurveChanged(bool); + +public slots: + void setmaxInputEGU(int); + void setmaxOutputEGU(int); + void setpixPerEGU_Input(int); + void setpixPerEGU_Output(int); + void setgridDistEGU_Input(int); + void setgridDistEGU_Output(int); + + void setColorBezier(QColor); + void setColorBackground(QColor); + void setInputEGU(QString); + void setOutputEGU(QString); + void setCaption(QString); + + void resetCurve() { + qDebug() << "QFunctionConfigurator::resetCurve = " << strSettingsFile; + loadSettings( strSettingsFile ); + } + +protected slots: + void paintEvent(QPaintEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + +protected: + void drawBackground(const QRectF &rect); + void drawFunction(const QRectF &rect); + void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG ); + void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen); + bool markContains(const QPointF &pt, const QPointF &coord) const; +// bool withinRange( const QPointF &coord ) const; + bool withinRect( const QPointF &coord, const QRectF &rect ) const; + +protected: + virtual void resizeEvent(QResizeEvent *); + +private: + QRectF range; // The actual rectangle for the Bezier-curve + QPointF lastPoint; // The right-most point of the Function + QPointF normalizePoint (QPointF point) const; // Convert the graphical Point to a real-life Point + QPointF graphicalizePoint (QPointF point, QString source = "") const; // Convert the Point to a graphical Point + + QPointF *moving; + int movingPoint; + + int MaxInput; // Maximum input limit + int MaxOutput; // Maximum output limit + int pPerEGU_Input; // Number of pixels, per EGU of Input + int pPerEGU_Output; // Number of pixels, per EGU of Output + int gDistEGU_Input; // Distance of the grid, in EGU of Input + int gDistEGU_Output; // Distance of the grid, in EGU of Output + + QColor colBezier; // Color of Bezier curve + QColor colBackground; // Color of widget background + QString strInputEGU; // Engineering Units input (vertical axis) + QString strOutputEGU; // Engineering Units output (horizontal axis) + QString strCaption; // Caption of the graph + QString strSettingsFile; // Name of last read INI-file + QPushButton *btnReset; // Reset Curve + + bool _draw_background; // Flag to determine if the background should be (re-)drawn on the QPixmap + QPixmap _background; // Image of the static parts (axis, lines, etc.) + bool _draw_function; // Flag to determine if the function should be (re-)drawn on the QPixmap + QPixmap _function; // Image of the function (static unless edited by the user) + + // + // Properties of the CurveConfigurator Widget + // + QString _title; // Title do display in Widget and to load Settings + FunctionConfig* _config; + QList _points; // Function-points + QList _draw_points; // Curve-points needed for drawing +}; + +#endif // QFUNCTIONCONFIGURATOR_H diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c new file mode 100644 index 00000000..fc1a5186 --- /dev/null +++ b/x-plane-plugin/plugin.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// using Wine name to ease things +#define WINE_SHM_NAME "facetracknoir-wine-shm" +#define WINE_MTX_NAME "facetracknoir-wine-mtx" + +typedef struct PortableLockedShm { + void* mem; + int fd, size; +} PortableLockedShm; + +typedef struct WineSHM { + float rx, ry, rz, tx, ty, tz; + char stop; +} WineSHM; + +static PortableLockedShm* lck_posix = NULL; +static WineSHM* shm_posix = NULL; +static void *view_x, *view_y, *view_z, *view_heading, *view_pitch; +static float offset_x, offset_y, offset_z; + +PortableLockedShm* PortableLockedShm_init(const char *shmName, const char *mutexName, int mapSize) +{ + PortableLockedShm* self = malloc(sizeof(PortableLockedShm)); + char shm_filename[NAME_MAX]; + shm_filename[0] = '/'; + strncpy(shm_filename+1, shmName, NAME_MAX-2); + shm_filename[NAME_MAX-1] = '\0'; + sprintf(shm_filename + strlen(shm_filename), "%ld\n", (long) getuid()); + //(void) shm_unlink(shm_filename); + + self->fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600); + if (ftruncate(self->fd, mapSize) == 0) + self->mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, self->fd, (off_t)0); + else + self->mem = (void*) -1; + return self; +} + +void PortableLockedShm_free(PortableLockedShm* self) +{ + //(void) shm_unlink(shm_filename); + (void) munmap(self->mem, self->size); + (void) close(self->fd); + free(self); +} + +void PortableLockedShm_lock(PortableLockedShm* self) +{ + flock(self->fd, LOCK_SH); +} + +void PortableLockedShm_unlock(PortableLockedShm* self) +{ + flock(self->fd, LOCK_UN); +} + +static void reinit_offset() { + offset_x = XPLMGetDataf(view_x); + offset_y = XPLMGetDataf(view_y); + offset_z = XPLMGetDataf(view_z); +} + +int write_head_position( + XPLMDrawingPhase inPhase, + int inIsBefore, + void * inRefcon) +{ + if (lck_posix != NULL && shm_posix != NULL) { + PortableLockedShm_lock(lck_posix); + XPLMSetDataf(view_x, shm_posix->tx * 1e-2 + offset_x); + XPLMSetDataf(view_y, shm_posix->ty * 1e-2 + offset_y); + XPLMSetDataf(view_z, shm_posix->tz * 1e-2 + offset_z); + XPLMSetDataf(view_heading, shm_posix->rx * 57.295781); + XPLMSetDataf(view_pitch, shm_posix->ry * 57.295781); + PortableLockedShm_unlock(lck_posix); + } + return 1; +} + +PLUGIN_API int XPluginStart ( char * outName, char * outSignature, char * outDescription ) { + view_x = XPLMFindDataRef("sim/aircraft/view/acf_peX"); + view_y = XPLMFindDataRef("sim/aircraft/view/acf_peY"); + view_z = XPLMFindDataRef("sim/aircraft/view/acf_peZ"); + view_heading = XPLMFindDataRef("sim/graphics/view/pilots_head_psi"); + view_pitch = XPLMFindDataRef("sim/graphics/view/pilots_head_the"); + if (view_x && view_y && view_z && view_heading && view_pitch) { + lck_posix = PortableLockedShm_init(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); + if (lck_posix->mem == (void*)-1) { + fprintf(stderr, "FTNOIR failed to init SHM #1!\n"); + return 0; + } + if (lck_posix->mem == NULL) { + fprintf(stderr, "FTNOIR failed to init SHM #2!\n"); + return 0; + } + shm_posix = (WineSHM*) lck_posix->mem; + memset(shm_posix, 0, sizeof(WineSHM)); + strcpy(outName, "FaceTrackNoIR"); + strcpy(outSignature, "FaceTrackNoIR - FreeTrack lives!"); + strcpy(outDescription, "Face tracking view control"); + fprintf(stderr, "FTNOIR init complete\n"); + return 1; + } + return 0; +} + +#if 0 +static int camera_callback(XPLMCameraPosition_t* outCameraPosition, int inIsLosingControl, void* inRefCon) { + if (!inIsLosingControl && XPLMGetCycleNumber() > 0) { + //XPLMReadCameraPosition(outCameraPosition); + PortableLockedShm_lock(lck_posix); + outCameraPosition->heading = shm_posix->rx * 57.295781; + outCameraPosition->pitch = shm_posix->ry * 57.295781; + outCameraPosition->roll = shm_posix->rz * 57.295781; + outCameraPosition->x = XPLMGetDataf(view_x); + outCameraPosition->y = XPLMGetDataf(view_y); + outCameraPosition->z = XPLMGetDataf(view_z); + PortableLockedShm_unlock(lck_posix); + return 1; + } + return 0; +} +static float flight_loop ( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void * inRefcon) +{ + XPLMControlCamera(xplm_ControlCameraForever, camera_callback, NULL); + // don't want it called anymore + return 0; +} +#endif + +PLUGIN_API void XPluginStop ( void ) { +#if 0 + // crashes due to race + if (lck_posix) + PortableLockedShm_free(lck_posix); + lck_posix = NULL; + shm_posix = NULL; +#endif +} + +PLUGIN_API void XPluginEnable ( void ) { + reinit_offset(); + XPLMRegisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL); +#if 0 + XPLMRegisterFlightLoopCallback(flight_loop, -1, NULL); +#endif +} + +PLUGIN_API void XPluginDisable ( void ) { + XPLMUnregisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL); + XPLMSetDataf(view_x, offset_x); + XPLMSetDataf(view_y, offset_y); + XPLMSetDataf(view_z, offset_z); +#if 0 + XPLMUnregisterFlightLoopCallback(flight_loop, NULL); + if (XPLMIsCameraBeingControlled(NULL)) + XPLMDontControlCamera(); +#endif +} + +PLUGIN_API void XPluginReceiveMessage( + XPLMPluginID inFromWho, + int inMessage, + void * inParam) +{ + if (inMessage == XPLM_MSG_AIRPORT_LOADED) + reinit_offset(); +} diff --git a/x-plane-plugin/version-script.txt b/x-plane-plugin/version-script.txt new file mode 100644 index 00000000..cfb84ec8 --- /dev/null +++ b/x-plane-plugin/version-script.txt @@ -0,0 +1,10 @@ +{ + global: + XPluginStart; + XPluginStop; + XPluginEnable; + XPluginDisable; + XPluginReceiveMessage; + local: + *; +}; -- cgit v1.2.3