From d4dd9675276093817756187c04d89f10da2df02e Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sat, 13 Sep 2014 14:09:08 +0200
Subject: nix comment cancer

---
 qfunctionconfigurator/functionconfig.cpp | 48 +++-----------------------------
 1 file changed, 4 insertions(+), 44 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 97a6db24..85d058fb 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -17,9 +17,6 @@
 #include <math.h>
 #include <QPixmap>
 
-//
-// Constructor with List of Points in argument.
-//
 FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput) :
     _mutex(QMutex::Recursive)
 {
@@ -29,9 +26,9 @@ FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput)
 	_size = 0;
 	lastValueTracked = QPointF(0,0);
 	_tracking_active = false;
-	_max_Input = intMaxInput;					// Added WVR 20120805
+	_max_Input = intMaxInput;
 	_max_Output = intMaxOutput;
-    QSettings settings("opentrack");	// Registry settings (in HK_USER)
+    QSettings settings("opentrack");
     QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
     QSettings iniFile( currentFile, QSettings::IniFormat );
     loadSettings(iniFile);
@@ -53,11 +50,6 @@ FunctionConfig::FunctionConfig() :
 {
 }
 
-//
-// Calculate the value of the function, given the input 'x'.
-// Used to draw the curve and, most importantly, to translate input to output.
-// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
-//
 float FunctionConfig::getValue(float x) {
     QMutexLocker foo(&_mutex);
     int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
@@ -67,9 +59,6 @@ float FunctionConfig::getValue(float x) {
 	return ret;
 }
 
-//
-// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
-//
 bool FunctionConfig::getLastPoint(QPointF& point ) {
     QMutexLocker foo(&_mutex);
 	point = lastValueTracked;
@@ -172,10 +161,6 @@ FunctionConfig::~FunctionConfig() {
         delete[] _data;
 }
 
-//
-// Remove a Point from the Function.
-// Used by the Widget.
-//
 void FunctionConfig::removePoint(int i) {
     QMutexLocker foo(&_mutex);
     if (i >= 0 && i < _points.size())
@@ -185,20 +170,12 @@ void FunctionConfig::removePoint(int i) {
     }
 }
 
-//
-// Add a Point to the Function.
-// Used by the Widget and by loadSettings.
-//
 void FunctionConfig::addPoint(QPointF pt) {
     QMutexLocker foo(&_mutex);
 	_points.append(pt);
 	reload();
 }
 
-//
-// Move a Function Point.
-// Used by the Widget.
-//
 void FunctionConfig::movePoint(int idx, QPointF pt) {
     QMutexLocker foo(&_mutex);
     if (idx >= 0 && idx < _points.size())
@@ -208,10 +185,6 @@ void FunctionConfig::movePoint(int idx, QPointF pt) {
     }
 }
 
-//
-// Return the List of Points.
-// Used by the Widget.
-//
 QList<QPointF> FunctionConfig::getPoints() {
 	QList<QPointF> ret;
     QMutexLocker foo(&_mutex);
@@ -221,10 +194,6 @@ QList<QPointF> FunctionConfig::getPoints() {
 	return ret;
 }
 
-//
-// Load the Points for the Function from the INI-file designated by settings.
-// Settings for a specific Curve are loaded from their own Group in the INI-file.
-//
 void FunctionConfig::loadSettings(QSettings& settings) {
     QMutexLocker foo(&_mutex);
     QPointF newPoint;
@@ -235,12 +204,8 @@ void FunctionConfig::loadSettings(QSettings& settings) {
     int max = settings.value("point-count", 0).toInt();
 
 	for (int i = 0; i < max; i++) {
-        newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
-                           settings.value(QString("point-%1-y").arg(i), 0).toFloat());
-        //
-		// Make sure the new Point fits in the Function Range.
-		// Maybe this can be improved?
-		//
+		newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
+				   settings.value(QString("point-%1-y").arg(i), 0).toFloat());
 		if (newPoint.x() > _max_Input) {
 			newPoint.setX(_max_Input);
 		}
@@ -254,11 +219,6 @@ void FunctionConfig::loadSettings(QSettings& settings) {
 	reload();
 }
 
-//
-// Save the Points for the Function to the INI-file designated by settings.
-// Settings for a specific Curve are saved in their own Group in the INI-file.
-// The number of Points is also saved, to make loading more convenient.
-//
 void FunctionConfig::saveSettings(QSettings& settings) {
     QMutexLocker foo(&_mutex);
 	settings.beginGroup(QString("Curves-%1").arg(_title));
-- 
cgit v1.2.3


From 679f424c250a38473c82bf1f997b75fbea4d3758 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Wed, 17 Sep 2014 12:40:39 +0200
Subject: nix explicit malloc

simplifies, allows for copy operator
---
 facetracknoir/facetracknoir.cpp                 |   4 +-
 facetracknoir/facetracknoir.h                   |   2 +-
 facetracknoir/tracker.h                         |  46 ++++----
 qfunctionconfigurator/functionconfig.cpp        | 143 ++++++++++--------------
 qfunctionconfigurator/functionconfig.h          |  79 +++++++++----
 qfunctionconfigurator/qfunctionconfigurator.cpp |  13 +--
 qfunctionconfigurator/qfunctionconfigurator.h   |  23 ++--
 7 files changed, 154 insertions(+), 156 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp
index 8df368cd..da8fae61 100644
--- a/facetracknoir/facetracknoir.cpp
+++ b/facetracknoir/facetracknoir.cpp
@@ -366,8 +366,8 @@ void FaceTrackNoIR::startTracker( ) {
 
         for (int i = 0; i < 6; i++)
         {
-            axis(i).curve.loadSettings(iniFile);
-            axis(i).curveAlt.loadSettings(iniFile);
+            axis(i).curve.loadSettings(iniFile, axis(i).name1);
+            axis(i).curveAlt.loadSettings(iniFile, axis(i).name2);
         }
     }
 
diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h
index 1da2d6b8..dc37ad37 100644
--- a/facetracknoir/facetracknoir.h
+++ b/facetracknoir/facetracknoir.h
@@ -86,7 +86,7 @@ public:
         return dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
     }
     THeadPoseDOF& axis(int idx) {
-        return *pose.axes[idx];
+        return pose.axes[idx];
     }
 
 #if defined(_WIN32)
diff --git a/facetracknoir/tracker.h b/facetracknoir/tracker.h
index 152551d4..d06ac9d2 100644
--- a/facetracknoir/tracker.h
+++ b/facetracknoir/tracker.h
@@ -21,12 +21,7 @@
 #include "facetracknoir/timer.hpp"
 using namespace options;
 
-class FaceTrackNoIR;				// pre-define parent-class to avoid circular includes
-
 class THeadPoseDOF {
-private:
-    THeadPoseDOF(const THeadPoseDOF &) = delete;
-    THeadPoseDOF& operator=(const THeadPoseDOF&) = delete;
 public:
     THeadPoseDOF(QString primary,
                  QString secondary,
@@ -36,22 +31,27 @@ public:
                  int maxOutput2,
                  axis_opts* opts) :
         headPos(0),
-        curve(primary, maxInput1, maxOutput1),
-        curveAlt(secondary, maxInput2, maxOutput2),
-        opts(*opts)
+        curve(maxInput1, maxOutput1),
+        curveAlt(maxInput2, maxOutput2),
+        opts(*opts),
+        name1(primary),
+        name2(secondary)
     {
         QSettings settings("opentrack");
         QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
         QSettings iniFile( currentFile, QSettings::IniFormat );
-        curve.loadSettings(iniFile);
-        curveAlt.loadSettings(iniFile);
+        curve.loadSettings(iniFile, primary);
+        curveAlt.loadSettings(iniFile, secondary);
     }
     volatile double headPos;
     FunctionConfig curve;
 	FunctionConfig curveAlt;
     axis_opts& opts;
+    QString name1, name2;
 };
 
+class FaceTrackNoIR;
+
 class Tracker : protected QThread {
 	Q_OBJECT
 
@@ -80,23 +80,17 @@ public:
 
 class HeadPoseData {
 public:
-    THeadPoseDOF* axes[6];
-    HeadPoseData(std::vector<axis_opts*> opts)
-    {
-        axes[TX] = new THeadPoseDOF("tx","tx_alt", 100, 100, 100, 100, opts[TX]);
-        axes[TY] = new THeadPoseDOF("ty","ty_alt", 100, 100, 100, 100, opts[TY]);
-        axes[TZ] = new THeadPoseDOF("tz","tz_alt", 100, 100, 100, 100, opts[TZ]);
-        axes[Yaw] = new THeadPoseDOF("rx", "rx_alt", 180, 180, 180, 180, opts[Yaw]);
-        axes[Pitch] = new THeadPoseDOF("ry", "ry_alt", 90, 90, 90, 90, opts[Pitch]);
-        axes[Roll] = new THeadPoseDOF("rz", "rz_alt", 180, 180, 180, 180, opts[Roll]);
-    }
-    ~HeadPoseData()
-    {
-        for (int i = 0; i < 6; i++)
-        {
-            delete axes[i];
+    THeadPoseDOF axes[6];
+    HeadPoseData(std::vector<axis_opts*> opts) :
+        axes {
+            THeadPoseDOF("tx","tx_alt", 100, 100, 100, 100, opts[TX]),
+            THeadPoseDOF("ty","ty_alt", 100, 100, 100, 100, opts[TY]),
+            THeadPoseDOF("tz","tz_alt", 100, 100, 100, 100, opts[TZ]),
+            THeadPoseDOF("rx", "rx_alt", 180, 180, 180, 180, opts[Yaw]),
+            THeadPoseDOF("ry", "ry_alt", 90, 90, 90, 90, opts[Pitch]),
+            THeadPoseDOF("rz", "rz_alt", 180, 180, 180, 180, opts[Roll])
         }
-    }
+    {}
 };
 
 #endif
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 85d058fb..640db1ef 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -17,36 +17,17 @@
 #include <math.h>
 #include <QPixmap>
 
-FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput) :
-    _mutex(QMutex::Recursive)
-{
-	_title = title;
-    _points = QList<QPointF>();
-	_data = 0;
-	_size = 0;
-	lastValueTracked = QPointF(0,0);
-	_tracking_active = false;
-	_max_Input = intMaxInput;
-	_max_Output = intMaxOutput;
-    QSettings settings("opentrack");
-    QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
-    QSettings iniFile( currentFile, QSettings::IniFormat );
-    loadSettings(iniFile);
-	reload();
-}
-
 void FunctionConfig::setTrackingActive(bool blnActive)
 {
-    _tracking_active = blnActive;
+    activep = blnActive;
 }
 
 FunctionConfig::FunctionConfig() :
     _mutex(QMutex::Recursive),
-    _data(0),
-    _size(0),
-    _tracking_active(false),
-    _max_Input(0),
-    _max_Output(0)
+    data(0),
+    activep(false),
+    max_x(0),
+    max_y(0)
 {
 }
 
@@ -54,31 +35,30 @@ float FunctionConfig::getValue(float x) {
     QMutexLocker foo(&_mutex);
     int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
     float ret = getValueInternal(x2);
-	lastValueTracked.setX(x);
-	lastValueTracked.setY(ret);
+	last_input_value.setX(x);
+	last_input_value.setY(ret);
 	return ret;
 }
 
 bool FunctionConfig::getLastPoint(QPointF& point ) {
     QMutexLocker foo(&_mutex);
-	point = lastValueTracked;
-	return _tracking_active;
+	point = last_input_value;
+	return activep;
 }
 
 float FunctionConfig::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
 	x = x < 0 ? -x : x;
     float ret;
-	if (!_data)
-		ret = 0;
-	else if (_size == 0)
+    int sz = data.size();
+	if (sz == 0)
 		ret = 0;
 	else if (x < 0)
 		ret = 0;
-	else if (x < _size && x >= 0)
-		ret = _data[x];
+	else if (x < sz && x >= 0)
+		ret = data[x];
 	else
-		ret = _data[_size - 1];
+		ret = data[sz - 1];
 	return ret * sign;
 }
 
@@ -96,35 +76,32 @@ static bool sortFn(const QPointF& one, const QPointF& two) {
 }
 
 void FunctionConfig::reload() {
-	_size = 0;
+	if (input.size())
+		qStableSort(input.begin(), input.end(), sortFn);
 
-	if (_points.size())
-		qStableSort(_points.begin(), _points.end(), sortFn);
+	if (input.size()) {
+        data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x());
+        
+        const int sz = data.size();
 
-	if (_data)
-        delete[] _data;
-	_data = NULL;
-	if (_points.size()) {
-        _data = new float[_size = MEMOIZE_PRECISION * _points[_points.size() - 1].x()];
+        for (int i = 0; i < sz; i++)
+                data[i] = -1;
 
-        for (int i = 0; i < _size; i++)
-                _data[i] = -1e6;
-
-		for (int k = 0; k < _points[0].x() * MEMOIZE_PRECISION; k++) {
-            if (k < _size)
-                _data[k] = _points[0].y() * k / (_points[0].x() * MEMOIZE_PRECISION);
+		for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {
+            if (k < sz)
+                data[k] = input[0].y() * k / (input[0].x() * MEMOIZE_PRECISION);
         }
 
-       for (int i = 0; i < _points.size(); i++) {
-            QPointF p0 = ensureInBounds(_points, i - 1);
-            QPointF p1 = ensureInBounds(_points, i);
-            QPointF p2 = ensureInBounds(_points, i + 1);
-            QPointF p3 = ensureInBounds(_points, i + 2);
+       for (int i = 0; i < sz; i++) {
+            QPointF p0 = ensureInBounds(input, i - 1);
+            QPointF p1 = ensureInBounds(input, i);
+            QPointF p2 = ensureInBounds(input, i + 1);
+            QPointF p3 = ensureInBounds(input, i + 2);
 
-            int end = p2.x() * MEMOIZE_PRECISION;
+            int end = std::min<int>(sz, p2.x() * MEMOIZE_PRECISION);
             int start = p1.x() * MEMOIZE_PRECISION;
 
-            for (int j = start; j < end && j < _size; j++) {
+            for (int j = start; j < end; j++) {
                 double t = (j - start) / (double) (end - start);
                 double t2 = t*t;
                 double t3 = t*t*t;
@@ -140,47 +117,41 @@ void FunctionConfig::reload() {
                                  (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 +
                                  (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3);
 
-                if (x >= 0 && x < _size)
-                    _data[x] = y;
+                if (x >= 0 && x < sz)
+                    data[x] = y;
             }
 		}
 
        float last = 0;
-
-       for (int i = 0; i < _size; i++)
+       for (int i = 0; i < sz; i++)
        {
-           if (_data[i] == -1e6)
-               _data[i] = last;
-           last = _data[i];
+           if (data[i] <= 0)
+               data[i] = last;
+           last = data[i];
        }
 	}
 }
 
-FunctionConfig::~FunctionConfig() {
-	if (_data)
-        delete[] _data;
-}
-
 void FunctionConfig::removePoint(int i) {
     QMutexLocker foo(&_mutex);
-    if (i >= 0 && i < _points.size())
+    if (i >= 0 && i < input.size())
     {
-        _points.removeAt(i);
+        input.removeAt(i);
         reload();
     }
 }
 
 void FunctionConfig::addPoint(QPointF pt) {
     QMutexLocker foo(&_mutex);
-	_points.append(pt);
+	input.append(pt);
 	reload();
 }
 
 void FunctionConfig::movePoint(int idx, QPointF pt) {
     QMutexLocker foo(&_mutex);
-    if (idx >= 0 && idx < _points.size())
+    if (idx >= 0 && idx < input.size())
     {
-        _points[idx] = pt;
+        input[idx] = pt;
         reload();
     }
 }
@@ -188,45 +159,45 @@ void FunctionConfig::movePoint(int idx, QPointF pt) {
 QList<QPointF> FunctionConfig::getPoints() {
 	QList<QPointF> ret;
     QMutexLocker foo(&_mutex);
-    for (int i = 0; i < _points.size(); i++) {
-		ret.append(_points[i]);
+    for (int i = 0; i < input.size(); i++) {
+		ret.append(input[i]);
 	}
 	return ret;
 }
 
-void FunctionConfig::loadSettings(QSettings& settings) {
+void FunctionConfig::loadSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
     QPointF newPoint;
 
 	QList<QPointF> points;
-	settings.beginGroup(QString("Curves-%1").arg(_title));
+	settings.beginGroup(QString("Curves-%1").arg(title));
 	
     int max = settings.value("point-count", 0).toInt();
 
 	for (int i = 0; i < max; i++) {
 		newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
 				   settings.value(QString("point-%1-y").arg(i), 0).toFloat());
-		if (newPoint.x() > _max_Input) {
-			newPoint.setX(_max_Input);
+		if (newPoint.x() > max_x) {
+			newPoint.setX(max_x);
 		}
-		if (newPoint.y() > _max_Output) {
-			newPoint.setY(_max_Output);
+		if (newPoint.y() > max_y) {
+			newPoint.setY(max_y);
 		}
 		points.append(newPoint);
 	}
     settings.endGroup();
-	_points = points;
+	input = points;
 	reload();
 }
 
-void FunctionConfig::saveSettings(QSettings& settings) {
+void FunctionConfig::saveSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
-	settings.beginGroup(QString("Curves-%1").arg(_title));
-	int max = _points.size();
+	settings.beginGroup(QString("Curves-%1").arg(title));
+	int max = input.size();
 	settings.setValue("point-count", max);
 	for (int i = 0; i < max; i++) {
-		settings.setValue(QString("point-%1-x").arg(i), _points[i].x());
-		settings.setValue(QString("point-%1-y").arg(i), _points[i].y());
+		settings.setValue(QString("point-%1-x").arg(i), input[i].x());
+		settings.setValue(QString("point-%1-y").arg(i), input[i].y());
     }
 
     for (int i = max; true; i++)
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 9b43f0bd..22bfc406 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2011-2014, Stanislaw Halik <sthalik@misaki.pl>
 
  * Permission to use, copy, modify, and/or distribute this
  * software for any purpose with or without fee is hereby granted,
@@ -14,36 +14,72 @@
 #include <QSettings>
 #include <QMutex>
 #include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include <vector>
 
 #define MEMOIZE_PRECISION 100
 
+class MyMutex {
+private:
+    QMutex inner;
+    
+public:
+    QMutex* operator->() { return &inner; }
+    QMutex* operator->() const { return &const_cast<MyMutex*>(this)->inner; }
+    
+    MyMutex operator=(const MyMutex& datum)
+    {
+        auto mode =
+                datum->isRecursive()
+                ? QMutex::Recursive
+                : QMutex::NonRecursive;
+        
+        return MyMutex(mode);
+    }
+    
+    MyMutex(const MyMutex& datum)
+    {
+        *this = datum;
+    }
+    
+    MyMutex(QMutex::RecursionMode mode = QMutex::NonRecursive) :
+        inner(mode)
+    {
+    }
+    
+    QMutex* operator&()
+    {
+        return &inner;
+    }
+};
+
 class FTNOIR_TRACKER_BASE_EXPORT FunctionConfig {
 private:
-    QMutex _mutex;
-	QList<QPointF> _points;
-	void reload();
-    float* _data;
-	int _size;
-	QString _title;
+    void reload();
     float getValueInternal(int x);
-	QPointF lastValueTracked;
-    volatile bool _tracking_active;
-	int _max_Input;
-	int _max_Output;
-    FunctionConfig(const FunctionConfig&) = delete;
+    
+    MyMutex _mutex;
+	QList<QPointF> input;
+    std::vector<float> data;
+	QPointF last_input_value;
+    volatile bool activep;
+	int max_x;
+	int max_y;
 public:
-    int maxInput() const { return _max_Input; }
-    int maxOutput() const { return _max_Output; }
+    int maxInput() const { return max_x; }
+    int maxOutput() const { return max_y; }
     FunctionConfig();
-    FunctionConfig(QString title, int intMaxInput, int intMaxOutput);
-    ~FunctionConfig();
+    FunctionConfig(int maxx, int maxy)
+    {
+        setMaxInput(maxx);
+        setMaxOutput(maxy);
+    }
 
     float getValue(float x);
 	bool getLastPoint(QPointF& point);
 	void removePoint(int i);
     void removeAllPoints() {
         QMutexLocker foo(&_mutex);
-        _points.clear();
+        input.clear();
         reload();
     }
 
@@ -51,15 +87,14 @@ public:
 	void movePoint(int idx, QPointF pt);
 	QList<QPointF> getPoints();
 	void setMaxInput(int MaxInput) {
-		_max_Input = MaxInput;
+		max_x = MaxInput;
 	}
 	void setMaxOutput(int MaxOutput) {
-		_max_Output = MaxOutput;
+		max_y = MaxOutput;
 	}
 
-	void saveSettings(QSettings& settings);
-	void loadSettings(QSettings& settings);
+	void saveSettings(QSettings& settings, const QString& title);
+	void loadSettings(QSettings& settings, const QString& title);
 
 	void setTrackingActive(bool blnActive);
-    QString getTitle() { return _title; }
 };
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index e94eded4..a197dadb 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -41,7 +41,7 @@ void QFunctionConfigurator::setConfig(FunctionConfig* config) {
     QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
     QSettings iniFile( currentFile, QSettings::IniFormat );
 
-    config->loadSettings(iniFile);
+    config->loadSettings(iniFile, name);
     _config = config;
     _draw_function = _draw_background = true;
     update_range();
@@ -52,7 +52,7 @@ void QFunctionConfigurator::saveSettings(QString settingsFile) {
     QSettings iniFile( settingsFile, QSettings::IniFormat );						// Application settings (in INI-file)
 
     if (_config) {
-        _config->saveSettings(iniFile);
+        _config->saveSettings(iniFile, name);
     }
 }
 
@@ -279,7 +279,6 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
             }
             if (!bTouchingPoint) {
                 _config->addPoint(pixel_coord_to_point(e->pos()));
-                emit CurveChanged( true );
             }
         }
     }
@@ -296,7 +295,6 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
 
             if (found_pt != -1) {
                 _config->removePoint(found_pt);
-                emit CurveChanged( true );
             }
             movingPoint = -1;
         }
@@ -353,7 +351,6 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
     if (e->button() == Qt::LeftButton) {
         timer.invalidate();
         if (movingPoint >= 0 && movingPoint < points.size()) {
-            emit CurveChanged( true );
             if (_config) {
                 _config->movePoint(movingPoint, pixel_coord_to_point(e->pos()));
             }
@@ -400,12 +397,6 @@ QPointF QFunctionConfigurator::point_to_pixel(QPointF point) const
                    range.y() + range.height() - point.y() * c.y());
 }
 
-void QFunctionConfigurator::setColorBezier(QColor color)
-{
-    colBezier = color;
-    update();
-}
-
 void QFunctionConfigurator::resizeEvent(QResizeEvent *)
 {
     update_range();
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index d3a8741f..e4af0062 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -16,40 +16,47 @@
 class FTNOIR_TRACKER_BASE_EXPORT QFunctionConfigurator : public QWidget
 {
 	Q_OBJECT
-    Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
+    Q_PROPERTY(QString Name READ get_name WRITE set_name)
+    
     QColor colorBezier() const
     {
         return colBezier;
     }
+    void setColorBezier(QColor color)
+    {
+        colBezier = color;
+        update();
+    }
+    QString get_name() const {
+        return name;
+    }
+    void set_name(QString name)
+    {
+        this->name = name;
+    }
 public:
 	QFunctionConfigurator(QWidget *parent = 0);
 	FunctionConfig* config();
 
     void setConfig(FunctionConfig* config);
     void saveSettings(QString settingsFile);
-
-signals:
-    void CurveChanged(bool);
-
 public slots:
-    void setColorBezier(QColor);
 protected slots:
 	void paintEvent(QPaintEvent *e);
 	void mousePressEvent(QMouseEvent *e);
 	void mouseMoveEvent(QMouseEvent *e);
 	void mouseReleaseEvent(QMouseEvent *e);
-      
 protected:
     void drawBackground();
 	void drawFunction();
 	void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG );
 	void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen);
     bool point_within_pixel(QPointF pt, QPointF pixel) const;
-
 protected:
 	virtual void resizeEvent(QResizeEvent *);
 
 private:
+    QString name;
     void update_range() {
         if (!_config)
             return;
-- 
cgit v1.2.3


From cf5ab7886e8228d1622566cc59277bcf089199a9 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Thu, 18 Sep 2014 07:24:52 +0200
Subject: cleanup qfc

Issue: #44

Remove confusing logic and retarded comments by the usual offender. Change
prototypes a bit for clarity's sake again.
---
 facetracknoir/curve-config.cpp                  |  56 +++----
 qfunctionconfigurator/functionconfig.cpp        |  11 +-
 qfunctionconfigurator/functionconfig.h          |   2 +-
 qfunctionconfigurator/qfunctionconfigurator.cpp | 188 +++++++++++-------------
 qfunctionconfigurator/qfunctionconfigurator.h   |  72 +++++----
 5 files changed, 158 insertions(+), 171 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp
index e1f39d03..535655c2 100644
--- a/facetracknoir/curve-config.cpp
+++ b/facetracknoir/curve-config.cpp
@@ -1,7 +1,5 @@
 #include "facetracknoir/facetracknoir.h"
 #include "facetracknoir/curve-config.h"
-#include <QDebug>
-#include <QCheckBox>
 CurveConfigurationDialog::CurveConfigurationDialog(FaceTrackNoIR *ftnoir, QWidget *parent) :
     QWidget( parent, Qt::Dialog ), mainApp(ftnoir)
 {
@@ -78,39 +76,45 @@ void CurveConfigurationDialog::loadSettings() {
         ui.rzconfig_alt
     };
 
-    QSettings settings("opentrack");
-    QString currentFile = settings.value("SettingsFile",
-                                         QCoreApplication::applicationDirPath() + "/settings/default.ini" )
-            .toString();
-
     for (int i = 0; i < 6; i++)
     {
-        configs[i]->setConfig(&mainApp->axis(i).curve);
-        alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt);
+        configs[i]->setConfig(&mainApp->axis(i).curve, mainApp->axis(i).name1);
+        alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt, mainApp->axis(i).name2);
     }
 }
 
 void CurveConfigurationDialog::save() {
-
-	qDebug() << "save() says: started";
-
     QSettings settings("opentrack");
     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);
+    
+    struct {
+        QFunctionConfigurator* qfc;
+        Axis axis;
+        bool altp;
+    } qfcs[] =
+    {
+        { ui.rxconfig, Yaw, false },
+        { ui.ryconfig, Pitch, false},
+        { ui.rzconfig, Roll, false },
+        { ui.txconfig, TX, false },
+        { ui.tyconfig, TY, false },
+        { ui.tzconfig, TZ, false },
+        
+        { ui.rxconfig_alt, Yaw, true },
+        { ui.ryconfig_alt, Pitch, true},
+        { ui.rzconfig_alt, Roll, true },
+        { ui.txconfig_alt, TX, true },
+        { ui.tyconfig_alt, TY, true },
+        { ui.tzconfig_alt, TZ, true },
+        { nullptr, Yaw, false }
+    };
+    
+    for (int i = 0; qfcs[i].qfc; i++)
+    {
+        THeadPoseDOF& axis = mainApp->axis(qfcs[i].axis);
+        qfcs[i].qfc->saveSettings(currentFile, qfcs[i].altp ? axis.name2 : axis.name1);
+    }
 }
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 640db1ef..159f350e 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -14,7 +14,7 @@
 #include <QtAlgorithms>
 #include <QtAlgorithms>
 #include <QSettings>
-#include <math.h>
+#include <cmath>
 #include <QPixmap>
 
 void FunctionConfig::setTrackingActive(bool blnActive)
@@ -156,13 +156,10 @@ void FunctionConfig::movePoint(int idx, QPointF pt) {
     }
 }
 
-QList<QPointF> FunctionConfig::getPoints() {
-	QList<QPointF> ret;
+const QList<QPointF> FunctionConfig::getPoints() {
     QMutexLocker foo(&_mutex);
-    for (int i = 0; i < input.size(); i++) {
-		ret.append(input[i]);
-	}
-	return ret;
+    // NB can't pass by reference
+	return input;
 }
 
 void FunctionConfig::loadSettings(QSettings& settings, const QString& title) {
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 22bfc406..ee2087a0 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -85,7 +85,7 @@ public:
 
 	void addPoint(QPointF pt);
 	void movePoint(int idx, QPointF pt);
-	QList<QPointF> getPoints();
+	const QList<QPointF> getPoints();
 	void setMaxInput(int MaxInput) {
 		max_x = MaxInput;
 	}
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index a197dadb..17431986 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -1,10 +1,12 @@
-/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
- *                         Adapted to FaceTrackNoIR by Wim Vriend.
+/* Copyright (c) 2011-2014 Stanislaw Halik <sthalik@misaki.pl>
+ * 
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  */
 
+// Adapted to FaceTrackNoIR by Wim Vriend.
+
 #include "qfunctionconfigurator/qfunctionconfigurator.h"
 #include <QPainter>
 #include <QPaintEvent>
@@ -25,35 +27,33 @@
 
 static const int pointSize = 5;
 
-QFunctionConfigurator::QFunctionConfigurator(QWidget *parent)
-    : QWidget(parent)
+QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) :
+    QWidget(parent),
+    _config(nullptr),
+    moving_control_point_idx(-1),
+    _draw_function(true)
 {
-    movingPoint = -1;
-    _config = 0;
-    _draw_background = true;
-    _draw_function = true;
     update_range();
     setMouseTracking(true);
 }
 
-void QFunctionConfigurator::setConfig(FunctionConfig* config) {
+void QFunctionConfigurator::setConfig(FunctionConfig* config, const QString& name) {
     QSettings settings("opentrack");
     QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
     QSettings iniFile( currentFile, QSettings::IniFormat );
 
     config->loadSettings(iniFile, name);
     _config = config;
-    _draw_function = _draw_background = true;
+    _draw_function = true;
     update_range();
     update();
 }
 
-void QFunctionConfigurator::saveSettings(QString settingsFile) {
-    QSettings iniFile( settingsFile, QSettings::IniFormat );						// Application settings (in INI-file)
+void QFunctionConfigurator::saveSettings(QString settingsFile, const QString& name) {
+    QSettings iniFile(settingsFile, QSettings::IniFormat);
 
-    if (_config) {
+    if (_config)
         _config->saveSettings(iniFile, name);
-    }
 }
 
 void QFunctionConfigurator::drawBackground()
@@ -61,11 +61,13 @@ void QFunctionConfigurator::drawBackground()
     if (!_config)
         return;
     _background = QPixmap(width(), height());
+    
     QPainter painter(&_background);
     painter.fillRect(rect(), QColor::fromRgb(204, 204, 204));
     painter.setRenderHint(QPainter::Antialiasing);
+    
     QColor bg_color(112, 154, 209);
-    painter.fillRect(range, bg_color);
+    painter.fillRect(pixel_bounds, bg_color);
 
     QFont font;
     font.setPointSize(8);
@@ -79,61 +81,59 @@ void QFunctionConfigurator::drawBackground()
     const int maxy = _config->maxOutput();
 
     // horizontal grid
-
     for (int i = 0; i < maxy; i += xstep)
     {
-        double y = range.height() - i * c.y() + range.y();
+        double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y();
         drawLine(&painter,
-                 QPointF(range.x(), y),
-                 QPointF(range.x() + range.width(), y),
+                 QPointF(pixel_bounds.x(), y),
+                 QPointF(pixel_bounds.x() + pixel_bounds.width(), y),
                  pen);
         painter.drawText(QRectF(10,
                                 y - metrics.height()/2,
-                                range.left(),
+                                pixel_bounds.left(),
                                 metrics.height()),
                          QString::number(i));
     }
 
     {
         const int i = maxy;
-        double y = range.height() - i * c.y() + range.y();
+        double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y();
         drawLine(&painter,
-                 QPointF(range.x(), y),
-                 QPointF(range.x() + range.width(), y),
+                 QPointF(pixel_bounds.x(), y),
+                 QPointF(pixel_bounds.x() + pixel_bounds.width(), y),
                  pen);
         painter.drawText(QRectF(10,
                                 y - metrics.height()/2,
-                                range.x() - 10,
+                                pixel_bounds.x() - 10,
                                 metrics.height()),
                          QString::number(i));
     }
 
     // vertical grid
-
     for (int i = 0; i < maxx; i += ystep)
     {
-        double x = range.x() + i * c.x();
+        double x = pixel_bounds.x() + i * c.x();
         drawLine(&painter,
-                 QPointF(x, range.y()),
-                 QPointF(x, range.y() + range.height()),
+                 QPointF(x, pixel_bounds.y()),
+                 QPointF(x, pixel_bounds.y() + pixel_bounds.height()),
                  pen);
         const QString text = QString::number(i);
         painter.drawText(QRectF(x - metrics.width(text)/2,
-                                range.height() + 10 + metrics.height(),
+                                pixel_bounds.height() + 10 + metrics.height(),
                                 metrics.width(text),
                                 metrics.height()),
                          text);
     }
     {
         const int i = maxx;
-        double x = range.x() + i * c.x();
+        double x = pixel_bounds.x() + i * c.x();
         drawLine(&painter,
-                 QPointF(x, range.y()),
-                 QPointF(x, range.y() + range.height()),
+                 QPointF(x, pixel_bounds.y()),
+                 QPointF(x, pixel_bounds.y() + pixel_bounds.height()),
                  pen);
         const QString text = QString::number(i);
         painter.drawText(QRectF(x - metrics.width(text)/2,
-                                range.height() + 10 + metrics.height(),
+                                pixel_bounds.height() + 10 + metrics.height(),
                                 metrics.width(text),
                                 metrics.height()),
                          text);
@@ -144,9 +144,6 @@ void QFunctionConfigurator::drawFunction()
 {
     if (!_config)
         return;
-    int i;
-    QPointF prevPoint;
-    QPointF currentPoint;
 
     _function = QPixmap(_background);
     QPainter painter(&_function);
@@ -156,19 +153,18 @@ void QFunctionConfigurator::drawFunction()
 
     QList<QPointF> points = _config->getPoints();
 
-    for (i = 0; i < points.size(); i++) {
-        currentPoint = point_to_pixel( points[i] );		// 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
+    for (int i = 0; i < points.size(); i++) {
+        drawPoint(&painter,
+                  point_to_pixel(points[i]),
+                  QColor(200, 200, 210, 120));
     }
 
+    QPen pen(spline_color, 1.2, Qt::SolidLine);
 
-    QPen pen(colBezier, 1.2, Qt::SolidLine);
-
-    prevPoint = point_to_pixel( QPointF(0,0) );		// Start at the Axis
-    double max = _config->maxInput();
+    static const constexpr double step = 1.02;
+    const double max = _config->maxInput();
+    
     QPointF prev = point_to_pixel(QPointF(0, 0));
-    const double step = 1.01;
     for (double i = 0; i < max; i += step) {
         double val = _config->getValue(i);
         QPointF cur = point_to_pixel(QPointF(i, val));
@@ -180,66 +176,54 @@ void QFunctionConfigurator::drawFunction()
 
 void QFunctionConfigurator::paintEvent(QPaintEvent *e)
 {
-    QPointF prevPoint;
-    QPointF currentPoint;
-    QPointF actualPos;
-    int i;
-
     QPainter p(this);
     p.setRenderHint(QPainter::Antialiasing);
 
-    if (_draw_background) {
+    if (_background.isNull())
         drawBackground();
-        _draw_background = false;
-    }
     p.drawPixmap(e->rect(), _background);
 
     if (_draw_function) {
-        drawFunction();						// Draw the Function on a Pixmap
         _draw_function = false;
+        drawFunction();
     }
-    p.drawPixmap(e->rect(), _function);						// Always draw the background and the function
+    p.drawPixmap(e->rect(), _function);
 
     if (_config) {
         QPen pen(Qt::white, 1, Qt::SolidLine);
         QList<QPointF> points = _config->getPoints();
-        if (movingPoint >= 0 && movingPoint < points.size()) {
-            prevPoint = point_to_pixel( QPointF(0,0) );				// Start at the Axis
-            for (i = 0; i < points.size(); i++) {
-                currentPoint = point_to_pixel( points[i] );		// Get the next point and convert it to Widget measures
-                drawLine(&p, prevPoint, currentPoint, pen);
-                prevPoint = currentPoint;
+        if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
+            QPointF prev;
+            for (int i = 0; i < points.size(); i++) {
+                auto tmp = point_to_pixel(points[i]);
+                drawLine(&p, prev, tmp, pen);
+                prev = tmp;
             }
             pen.setWidth(1);
             pen.setColor( Qt::white );
             pen.setStyle( Qt::DashLine );
-            actualPos = point_to_pixel(points[movingPoint]);
-            drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
-            drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.height() + range.top()), pen);
+            QPointF pixel_pos = point_to_pixel(points[moving_control_point_idx]);
+            drawLine(&p, QPoint(pixel_bounds.left(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_pos.y()), pen);
+            drawLine(&p, QPoint(pixel_pos.x(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_bounds.height() + pixel_bounds.top()), 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 )) {
-            actualPos = point_to_pixel( QPointF(fabs(currentPoint.x()), fabs(currentPoint.y())) );
-            drawPoint(&p, actualPos, QColor(255, 0, 0, 120));
+        QPointF last;
+        if (_config->getLastPoint(last)) {
+            QPointF pixel_pos = point_to_pixel( QPointF(fabs(last.x()), fabs(last.y())) );
+            drawPoint(&p, pixel_pos, 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.width()), pen);
+            drawLine(&p, QPoint(pixel_bounds.left(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_pos.y()), pen);
+            drawLine(&p, QPoint(pixel_pos.x(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_bounds.width()), pen);
         }
-
     }
 }
 
-//
-// Draw the handle, to move the Bezier-curve.
-//
 void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QColor colBG )
 {
     painter->save();
@@ -251,7 +235,7 @@ void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QCo
     painter->restore();
 }
 
-void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen)
+void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen &pen)
 {
     painter->save();
     painter->setPen(pen);
@@ -267,12 +251,12 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
     QList<QPointF> points = _config->getPoints();
     if (e->button() == Qt::LeftButton) {
         bool bTouchingPoint = false;
-        movingPoint = -1;
+        moving_control_point_idx = -1;
         if (_config) {
             for (int i = 0; i < points.size(); i++) {
                 if ( point_within_pixel(points[i], e->pos() ) ) {
                     bTouchingPoint = true;
-                    movingPoint = i;
+                    moving_control_point_idx = i;
                     timer.restart();
                     break;
                 }
@@ -296,7 +280,7 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
             if (found_pt != -1) {
                 _config->removePoint(found_pt);
             }
-            movingPoint = -1;
+            moving_control_point_idx = -1;
         }
     }
     _draw_function = true;
@@ -307,29 +291,33 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)
 {
     if (!_config)
         return;
+    
+    static const constexpr int min_refresh_delay = 25;
+    
+    if (timer.isValid() && timer.elapsed() < min_refresh_delay)
+        return;
+    
+    static const constexpr int refresh_delay = 50;
     QList<QPointF> points = _config->getPoints();
-    const int refresh_delay = 50;
 
-    if (movingPoint >= 0 && movingPoint < points.size()) {
+    if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
         setCursor(Qt::ClosedHandCursor);
 
         if (timer.isValid() && timer.elapsed() > refresh_delay)
         {
             timer.restart();
             QPointF new_pt = pixel_coord_to_point(e->pos());
-            points[movingPoint] = new_pt;
-            _config->movePoint(movingPoint, new_pt);
+            points[moving_control_point_idx] = new_pt;
+            _config->movePoint(moving_control_point_idx, new_pt);
             _draw_function = true;
             update();
         }
     }
     else {
         bool bTouchingPoint = false;
-        if (_config) {
-            for (int i = 0; i < points.size(); i++) {
-                if ( point_within_pixel(points[i], e->pos() ) ) {
-                    bTouchingPoint = true;
-                }
+        for (int i = 0; i < points.size(); i++) {
+            if ( point_within_pixel(points[i], e->pos() ) ) {
+                bTouchingPoint = true;
             }
         }
 
@@ -346,37 +334,39 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
 {
     if (!_config)
         return;
+    
     QList<QPointF> points = _config->getPoints();
 
     if (e->button() == Qt::LeftButton) {
         timer.invalidate();
-        if (movingPoint >= 0 && movingPoint < points.size()) {
+        if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
             if (_config) {
-                _config->movePoint(movingPoint, pixel_coord_to_point(e->pos()));
+                _config->movePoint(moving_control_point_idx, pixel_coord_to_point(e->pos()));
             }
         }
         setCursor(Qt::ArrowCursor);
-        movingPoint = -1;
+        moving_control_point_idx = -1;
     }
 
     _draw_function = true;
     update();
 }
 
-bool QFunctionConfigurator::point_within_pixel(QPointF pt, QPointF pixel) const
+bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel)
 {
-    QPointF pixel2(range.x() + pt.x() * c.x(), (range.y() + range.height() - pt.y() * c.y()));
+    QPointF pixel2(pixel_bounds.x() + pt.x() * c.x(),
+                   (pixel_bounds.y() + pixel_bounds.height() - pt.y() * c.y()));
     return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize &&
            pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize;
 }
 
-QPointF QFunctionConfigurator::pixel_coord_to_point(QPointF point) const
+QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point)
 {
     if (!_config)
         return QPointF(-1, -1);
 
-    double x = (point.x() - range.x()) / c.x();
-    double y = (range.height() - point.y() + range.y()) / c.y();
+    double x = (point.x() - pixel_bounds.x()) / c.x();
+    double y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y();
 
     if (x < 0)
         x = 0;
@@ -391,10 +381,10 @@ QPointF QFunctionConfigurator::pixel_coord_to_point(QPointF point) const
     return QPointF(x, y);
 }
 
-QPointF QFunctionConfigurator::point_to_pixel(QPointF point) const
+QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point)
 {
-    return QPointF(range.x() + point.x() * c.x(),
-                   range.y() + range.height() - point.y() * c.y());
+    return QPointF(pixel_bounds.x() + point.x() * c.x(),
+                   pixel_bounds.y() + pixel_bounds.height() - point.y() * c.y());
 }
 
 void QFunctionConfigurator::resizeEvent(QResizeEvent *)
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index e4af0062..4643f0d5 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2011-2014 Stanislaw Halik <sthalik@misaki.pl>
  *                         Adapted to FaceTrackNoIR by Wim Vriend.
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,73 +16,69 @@
 class FTNOIR_TRACKER_BASE_EXPORT QFunctionConfigurator : public QWidget
 {
 	Q_OBJECT
-    Q_PROPERTY(QString Name READ get_name WRITE set_name)
+    Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
+public:
+	QFunctionConfigurator(QWidget *parent = 0);
+    
+	FunctionConfig* config();
+    void setConfig(FunctionConfig* config, const QString &name);
+    
+    void saveSettings(QString settingsFile, const QString &name);
     
     QColor colorBezier() const
     {
-        return colBezier;
+        return spline_color;
     }
     void setColorBezier(QColor color)
     {
-        colBezier = color;
+        spline_color = color;
         update();
     }
-    QString get_name() const {
-        return name;
-    }
-    void set_name(QString name)
-    {
-        this->name = name;
-    }
-public:
-	QFunctionConfigurator(QWidget *parent = 0);
-	FunctionConfig* config();
-
-    void setConfig(FunctionConfig* config);
-    void saveSettings(QString settingsFile);
-public slots:
 protected slots:
 	void paintEvent(QPaintEvent *e);
 	void mousePressEvent(QMouseEvent *e);
 	void mouseMoveEvent(QMouseEvent *e);
 	void mouseReleaseEvent(QMouseEvent *e);
-protected:
+private:
     void drawBackground();
 	void drawFunction();
 	void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG );
-	void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen);
-    bool point_within_pixel(QPointF pt, QPointF pixel) const;
+	void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen& pen);
+    bool point_within_pixel(const QPointF& pt, const QPointF& pixel);
 protected:
 	virtual void resizeEvent(QResizeEvent *);
-
 private:
-    QString name;
     void update_range() {
         if (!_config)
             return;
-        double w = width(), h = height();
+        
+        const double w = width(), h = height();
         const double mwl = 40, mhl = 20;
         const double mwr = 15, mhr = 35;
-        range = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr));
-        c = QPointF(range.width() / _config->maxInput(), range.height() / _config->maxOutput());
-        _draw_function = _draw_background = true;
+        
+        pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr));
+        c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput());
+        _draw_function = true;
+        
+        _background = QPixmap();
+        _function = QPixmap();
     }
 
-	QRectF  range;
-	QPointF lastPoint;
-    QPointF pixel_coord_to_point (QPointF point) const;
-    QPointF point_to_pixel (QPointF point) const;
+    QPointF pixel_coord_to_point (const QPointF& point);
+    QPointF point_to_pixel (const QPointF& point);
 
-    int     movingPoint;
+    FunctionConfig* _config;
+    
+    // bounds of the rectangle user can interact with
+	QRectF  pixel_bounds;
+    
+    int moving_control_point_idx;
     QElapsedTimer timer;
     QPointF c;
 
-	QColor colBezier;
-
-	bool _draw_background;
+	QColor spline_color;
+    
 	QPixmap _background;
-	bool _draw_function;
 	QPixmap _function;
-
-	FunctionConfig* _config;
+    bool _draw_function;
 };
-- 
cgit v1.2.3


From 97bd173ee4b6f30c12ca590e213b21bbc83f8617 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sat, 4 Oct 2014 17:28:49 +0200
Subject: flush before windows breaks and data lossage

---
 CMakeLists.txt                                     |  14 +-
 .../README-CREDIT.txt                              |   6 +
 .../ft_tester/Makefile.am                          |  54 +++
 .../ft_tester/Makefile.in                          | 491 ++++++++++++++++++++
 .../ft_tester/fttester.rc.in                       |  67 +++
 .../ft_tester/main.cpp                             | 211 +++++++++
 .../ft_tester/resource.h                           |  27 ++
 .../important-stuff/NPClient.h                     |  17 +
 .../important-stuff/NPClient.spec                  |  23 +
 .../important-stuff/NPClient_dll.h                 |  58 +++
 .../important-stuff/NPClient_main.c                | 444 ++++++++++++++++++
 .../important-stuff/game_data.c                    | 149 ++++++
 .../important-stuff/game_data.h                    |  17 +
 .../tester/Makefile.am                             |  78 ++++
 .../tester/Makefile.in                             | 512 +++++++++++++++++++++
 .../tester/main.cpp                                | 100 ++++
 .../tester/npifc.c                                 | 302 ++++++++++++
 .../tester/npifc.h                                 |  66 +++
 .../tester/npview.rc.in                            |  49 ++
 .../tester/resource.h                              |  23 +
 .../tester/rest.c                                  |   1 +
 .../tester/rest.h                                  |   1 +
 facetracknoir/curve-config.cpp                     |  71 +--
 facetracknoir/curve-config.h                       |   8 +-
 facetracknoir/facetracknoir.cpp                    | 213 ++++-----
 facetracknoir/facetracknoir.h                      |  59 ++-
 facetracknoir/mappings.hpp                         |  79 ++++
 facetracknoir/plugin-qt-api.hpp                    |   8 +-
 facetracknoir/plugin-support.h                     |   2 +-
 facetracknoir/qcopyable-mutex.hpp                  |  37 ++
 facetracknoir/rotation.h                           |  19 +-
 facetracknoir/tracker.cpp                          |  82 ++--
 facetracknoir/tracker.h                            |  77 +---
 facetracknoir/tracker_types.cpp                    |  43 --
 facetracknoir/tracker_types.h                      |  65 ++-
 freetrackclient/freetrackclient.c                  |  38 +-
 ftnoir_filter_kalman/ftnoir_filter_kalman.h        |  11 +-
 ftnoir_protocol_ft/fttypes.h                       |  10 +-
 qfunctionconfigurator/functionconfig.cpp           |  24 +-
 qfunctionconfigurator/functionconfig.h             |  81 +---
 qfunctionconfigurator/qfunctionconfigurator.cpp    |   2 +-
 qfunctionconfigurator/qfunctionconfigurator.h      |   6 +-
 42 files changed, 3173 insertions(+), 472 deletions(-)
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/README-CREDIT.txt
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.am
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.in
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/fttester.rc.in
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/main.cpp
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/resource.h
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.h
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.spec
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_dll.h
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_main.c
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.c
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.h
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.am
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.in
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/main.cpp
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.c
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.h
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npview.rc.in
 create mode 100644 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/resource.h
 create mode 120000 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.c
 create mode 120000 facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.h
 create mode 100644 facetracknoir/mappings.hpp
 create mode 100644 facetracknoir/qcopyable-mutex.hpp
 delete mode 100644 facetracknoir/tracker_types.cpp

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ceffd54..655d70c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.11)
 cmake_policy(SET CMP0020 NEW)
 
 if(MSVC)
-	message(FATAL_ERROR "Support for MSVC removed due to incomplete C++11 support")
+        message(FATAL_ERROR "Support for MSVC removed due to incomplete C++11 support")
 endif()
 
 include(CMakeParseArguments)
@@ -131,9 +131,9 @@ endif()
 set(EXTRA-MOCS "${CMAKE_SOURCE_DIR}/facetracknoir/options.h")
 
 function(link_with_dinput8 n)
-	if(WIN32)
-		target_link_libraries(${n} dinput8 dxguid strmiids)
-	endif()
+        if(WIN32)
+                target_link_libraries(${n} dinput8 dxguid strmiids)
+        endif()
 endfunction()
 
 macro(opentrack_module n dir)
@@ -376,9 +376,9 @@ if(SDK_RIFT)
         target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a" winmm setupapi ws2_32 imagehlp wbemuuid)
     else()
         if(NOT APPLE)
-		target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a" udev Xinerama)
+                target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a" udev Xinerama)
         else()
-		target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a")
+                target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a")
         endif()
     endif()
 endif()
@@ -426,7 +426,7 @@ if(UNIX OR APPLE)
     SET_TARGET_PROPERTIES(opentrack-qxt-mini PROPERTIES COMPILE_FLAGS "-DBUILD_QXT_CORE=42 -DBUILD_QXT_WIDGETS=42 -DBUILD_QXT_GUI=42")
     target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS})
     if(NOT APPLE)
-	    target_link_libraries(opentrack-qxt-mini X11)
+            target_link_libraries(opentrack-qxt-mini X11)
     endif()
 endif()
 
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/README-CREDIT.txt b/facetracknoir/clientfiles/important-source-code-really-important-really-really/README-CREDIT.txt
new file mode 100644
index 00000000..82214139
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/README-CREDIT.txt
@@ -0,0 +1,6 @@
+The contents of the directory written by one and only, uglyDwarf.
+
+Obtained at epoch time 1412397452 from the mithril-mine's shaft, where
+the elite dwarves reside.
+
+For the latest happenings, visit <https://code.google.com/p/linux-track/>
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.am b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.am
new file mode 100644
index 00000000..02747edb
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.am
@@ -0,0 +1,54 @@
+noinst_SCRIPTS = 
+if WINE_PLUGIN
+  noinst_SCRIPTS += ftc.exe.so
+endif #WINE_PLUGIN
+
+if DARWIN
+  LDFLAGS += -Wl,-no_arch_warnings
+else
+  LDFLAGS += -Wl,--no-warn-search-mismatch
+endif
+
+CC = winegcc
+
+CXX = wineg++
+
+SUFFIXES = .o .cpp .c .rc
+
+.cpp.o :
+	$(CXX) -c $(CXXFLAGS_PRE) $(CXXFLAGS) $(CPPFLAGS) -m32 -o $@ $<
+
+.c.o :
+	$(CC) -c $(CFLAGS_PRE) $(CFLAGS) $(CPPFLAGS) -m32 -o $@ $<
+
+.rc.o :
+	wrc -o $@ $(RCFLAGS) $<
+
+CXXFLAGS_PRE = -g -DHAVE_CONFIG_H -I../../.. -I. -I@srcdir@/../.. -I@top_builddir@
+CFLAGS_PRE = -g -I../.. -I../../.. -DHAVE_CONFIG_H -I@srcdir@/../.. -I@top_builddir@
+RCFLAGS = -I @srcdir@
+#VPATH = ../..:@srcdir@/../..:@top_builddir@:@srcdir@
+vpath %.h @srcdir@/../..
+vpath %.h @top_builddir@
+vpath %.c @srcdir@
+vpath %.c @srcdir@/../..
+
+ftc.exe.so : main.o fttester.o
+	wineg++ -g -o $@ -L. $(WINE_LIBS) $(LDFLAGS) -m32 -Wall -Wextra $^
+
+fttester.o : fttester.rc resource.h config.h
+
+main.o : main.cpp
+
+clean-local: clean-local-check
+.PHONY: clean-local-check
+clean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+distclean-local: distclean-local-check
+.PHONY: distclean-local-check
+distclean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+EXTRA_DIST = resource.h fttester.rc main.cpp
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.in b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.in
new file mode 100644
index 00000000..d1fff34d
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/Makefile.in
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@WINE_PLUGIN_TRUE@am__append_1 = ftc.exe.so
+@DARWIN_TRUE@am__append_2 = -Wl,-no_arch_warnings
+@DARWIN_FALSE@am__append_3 = -Wl,--no-warn-search-mismatch
+subdir = src/wine_bridge/ft_tester
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/fttester.rc.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = fttester.rc
+CONFIG_CLEAN_VPATH_FILES =
+SCRIPTS = $(noinst_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+depcomp =
+am__depfiles_maybe =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BISON = @BISON@
+CC = winegcc
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = wineg++
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@ $(am__append_2) $(am__append_3)
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIB32DIR = @LIB32DIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCFLAGS = @OBJCFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENCV_CFLAGS = @OPENCV_CFLAGS@
+OPENCV_LIBS = @OPENCV_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+QMAKE_PATH = @QMAKE_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINE64_LIBS = @WINE64_LIBS@
+WINE_LIBS = @WINE_LIBS@
+XPL_CPPFLAGS = @XPL_CPPFLAGS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+with_makensis = @with_makensis@
+with_wine64 = @with_wine64@
+noinst_SCRIPTS = $(am__append_1)
+SUFFIXES = .o .cpp .c .rc
+CXXFLAGS_PRE = -g -DHAVE_CONFIG_H -I../../.. -I. -I@srcdir@/../.. -I@top_builddir@
+CFLAGS_PRE = -g -I../.. -I../../.. -DHAVE_CONFIG_H -I@srcdir@/../.. -I@top_builddir@
+RCFLAGS = -I @srcdir@
+EXTRA_DIST = resource.h fttester.rc main.cpp
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .o .cpp .c .rc
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps src/wine_bridge/ft_tester/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu --ignore-deps src/wine_bridge/ft_tester/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+fttester.rc: $(top_builddir)/config.status $(srcdir)/fttester.rc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	clean-local cscopelist-am ctags-am distclean distclean-generic \
+	distclean-libtool distclean-local distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+	uninstall-am
+
+
+.cpp.o :
+	$(CXX) -c $(CXXFLAGS_PRE) $(CXXFLAGS) $(CPPFLAGS) -m32 -o $@ $<
+
+.c.o :
+	$(CC) -c $(CFLAGS_PRE) $(CFLAGS) $(CPPFLAGS) -m32 -o $@ $<
+
+.rc.o :
+	wrc -o $@ $(RCFLAGS) $<
+#VPATH = ../..:@srcdir@/../..:@top_builddir@:@srcdir@
+vpath %.h @srcdir@/../..
+vpath %.h @top_builddir@
+vpath %.c @srcdir@
+vpath %.c @srcdir@/../..
+
+ftc.exe.so : main.o fttester.o
+	wineg++ -g -o $@ -L. $(WINE_LIBS) $(LDFLAGS) -m32 -Wall -Wextra $^
+
+fttester.o : fttester.rc resource.h config.h
+
+main.o : main.cpp
+
+clean-local: clean-local-check
+.PHONY: clean-local-check
+clean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+distclean-local: distclean-local-check
+.PHONY: distclean-local-check
+distclean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/fttester.rc.in b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/fttester.rc.in
new file mode 100644
index 00000000..332f3c73
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/fttester.rc.in
@@ -0,0 +1,67 @@
+// Generated by ResEdit 1.5.9
+// Copyright (C) 2006-2011
+// http://www.resedit.net
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include "resource.h"
+
+#ifdef HAVE_CONFIG_H
+  #include "../../../config.h"
+#endif
+
+
+
+
+//
+// Dialog resources
+//
+//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_DIALOG1 DIALOGEX 0, 0, 333, 183
+STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
+CAPTION "FreeTrack client test utility v@PACKAGE_VERSION@"
+FONT 8, "Ms Shell Dlg", 400, 0, 1
+{
+    DEFPUSHBUTTON   "Quit", IDQUIT, 262, 153, 50, 14
+    PUSHBUTTON      "Start", IDC_START, 199, 153, 50, 14
+    EDITTEXT        IDC_YAW, 38, 15, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Yaw", IDC_STATIC, 12, 17, 21, 14, SS_RIGHT
+    EDITTEXT        IDC_PITCH, 38, 38, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Pitch", IDC_STATIC, 16, 40, 17, 14, SS_RIGHT
+    EDITTEXT        IDC_ROLL, 38, 61, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Roll", IDC_STATIC, 20, 63, 13, 14, SS_RIGHT
+    EDITTEXT        IDC_X, 38, 84, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "X", IDC_STATIC, 27, 86, 6, 14, SS_RIGHT
+    EDITTEXT        IDC_Y, 38, 107, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Y", IDC_STATIC, 27, 109, 6, 14, SS_RIGHT
+    EDITTEXT        IDC_Z, 38, 130, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Z", IDC_STATIC, 27, 132, 6, 14, SS_RIGHT
+    EDITTEXT        IDC_RYAW, 137, 15, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw Yaw", IDC_STATIC, 101, 17, 32, 8, SS_RIGHT
+    EDITTEXT        IDC_RPITCH, 137, 38, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw Pitch", IDC_STATIC, 99, 40, 34, 8, SS_RIGHT
+    EDITTEXT        IDC_RROLL, 137, 61, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw Roll", IDC_STATIC, 103, 63, 30, 8, SS_RIGHT
+    EDITTEXT        IDC_RX, 137, 84, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw X", IDC_STATIC, 111, 86, 22, 8, SS_RIGHT
+    EDITTEXT        IDC_RY, 137, 107, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw Y", IDC_STATIC, 111, 109, 22, 8, SS_RIGHT
+    EDITTEXT        IDC_RZ, 137, 130, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Raw Z", IDC_STATIC, 111, 132, 22, 8, SS_RIGHT
+    EDITTEXT        IDC_NUM, 264, 15, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Frame Number", IDC_STATIC, 212, 17, 47, 8, SS_RIGHT
+    EDITTEXT        IDC_RES, 264, 38, 48, 14, ES_AUTOHSCROLL
+    RTEXT           "Camera Resolution", IDC_STATIC, 199, 40, 60, 8, SS_RIGHT
+    EDITTEXT        IDC_PT0, 227, 61, 85, 14, ES_AUTOHSCROLL
+    RTEXT           "Point 1", IDC_STATIC, 199, 63, 23, 8, SS_RIGHT
+    EDITTEXT        IDC_PT1, 227, 84, 85, 14, ES_AUTOHSCROLL
+    RTEXT           "Point 2", IDC_STATIC, 199, 86, 23, 8, SS_RIGHT
+    EDITTEXT        IDC_PT2, 227, 107, 85, 14, ES_AUTOHSCROLL
+    RTEXT           "Point 3", IDC_STATIC, 199, 109, 23, 8, SS_RIGHT
+    EDITTEXT        IDC_PT3, 227, 130, 85, 14, ES_AUTOHSCROLL
+    RTEXT           "Point 4", IDC_STATIC, 199, 132, 23, 8, SS_RIGHT
+    EDITTEXT        IDC_TITLE, 38, 153, 147, 14, ES_AUTOHSCROLL
+    RTEXT           "Title", IDC_STATIC, 19, 155, 14, 8, SS_RIGHT
+}
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/main.cpp b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/main.cpp
new file mode 100644
index 00000000..a737f88f
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/main.cpp
@@ -0,0 +1,211 @@
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <cstdio>
+#include <stdint.h>
+#include <sstream>
+#include <cstdlib>
+#include <iomanip>
+
+#include "resource.h"
+
+HINSTANCE hInst;
+UINT_PTR timer = 0;
+
+HMODULE ftclient;
+
+typedef struct
+{
+	unsigned int dataID;
+	int res_x; int res_y;
+	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 ryaw;
+	float rpitch;
+	float rroll;
+	float rx;
+	float ry;
+	float rz;
+    // raw points, sorted by Y, origin top left corner
+	float x0, y0;
+	float x1, y1;
+	float x2, y2;
+	float x3, y3;
+}FreeTrackData;
+
+
+typedef bool (WINAPI *importGetData)(FreeTrackData * data);
+typedef char *(WINAPI *importGetDllVersion)(void);
+typedef void (WINAPI *importReportName)(char *name);
+typedef char *(WINAPI *importProvider)(void);
+
+importGetData getData;
+importGetDllVersion getDllVersion;
+importReportName	reportName;
+importProvider provider;
+
+
+char *client_path()
+{
+  HKEY  hkey   = 0;
+  RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Freetrack\\FreetrackClient", 0,
+    KEY_QUERY_VALUE, &hkey);
+  if(!hkey){
+    printf("Can't open registry key\n");
+    return NULL;
+  }
+
+  BYTE path[1024];
+  DWORD buf_len = 1024;
+  LONG result = RegQueryValueEx(hkey, "Path", NULL, NULL, path, &buf_len);
+  char *full_path = (char *)malloc(2048);
+  if(result == ERROR_SUCCESS && buf_len > 0){
+    sprintf(full_path, "%s\\FreeTrackClient.dll", path);
+  }
+  RegCloseKey(hkey);
+  return full_path;
+}
+
+
+bool start(HWND hwnd)
+{
+  char *libname = client_path();
+  if(libname == NULL){
+    printf("Freetrack client not found!\n");
+    return false;
+  }
+  ftclient = LoadLibrary(libname);
+  if(ftclient == NULL){
+    printf("Couldn't load Freetrack client library '%s'!\n", libname);
+    return false;
+  }
+  printf("Freetrack client library %s loaded.\n", client_path());
+
+
+  getData = (importGetData)GetProcAddress(ftclient, "FTGetData");
+  getDllVersion = (importGetDllVersion)GetProcAddress(ftclient, "FTGetDllVersion");
+  reportName = (importReportName)GetProcAddress(ftclient, "FTReportName");
+  provider = (importProvider)GetProcAddress(ftclient, "FTProvider");
+
+  if((getData == NULL) || (getDllVersion == NULL) || (reportName == NULL) || (provider == NULL)){
+    printf("Couldn't load Freetrack client functions!\n");
+    FreeLibrary(ftclient);
+    return false;
+  }
+
+  printf("Dll version: %s\n", getDllVersion());
+  printf("Provider: %s\n", provider());
+  char title[1024];
+  GetDlgItemText(hwnd, IDC_TITLE, title, 1020);
+  reportName(title);
+  return true;
+}
+
+void reportError(std::string msg)
+{
+  MessageBoxA(0, "FreeTrack client test", msg.c_str(), 0);
+}
+VOID CALLBACK TimerProcedure(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+  (void) uMsg;
+  (void) idEvent;
+  (void) dwTime;
+  FreeTrackData d;
+  getData(&d);
+  SetDlgItemInt(hwnd, IDC_PITCH, d.pitch, true);
+  SetDlgItemInt(hwnd, IDC_ROLL, d.roll, true);
+  SetDlgItemInt(hwnd, IDC_YAW, d.yaw, true);
+
+  SetDlgItemInt(hwnd, IDC_X, d.x, true);
+  SetDlgItemInt(hwnd, IDC_Y, d.y, true);
+  SetDlgItemInt(hwnd, IDC_Z, d.z, true);
+
+  SetDlgItemInt(hwnd, IDC_RPITCH, d.rpitch, true);
+  SetDlgItemInt(hwnd, IDC_RROLL, d.rroll, true);
+  SetDlgItemInt(hwnd, IDC_RYAW, d.ryaw, true);
+
+  SetDlgItemInt(hwnd, IDC_RX, d.rx, true);
+  SetDlgItemInt(hwnd, IDC_RY, d.ry, true);
+  SetDlgItemInt(hwnd, IDC_RZ, d.rz, true);
+  
+  std::ostringstream s; 
+  s.str(std::string());
+  s<<"("<<std::fixed<<std::setprecision(1)<<d.x0<<"; "<<d.y0<<")";
+  SetDlgItemText(hwnd, IDC_PT0, s.str().c_str());
+
+  s.str(std::string());
+  s<<"("<<std::fixed<<std::setprecision(1)<<d.x1<<"; "<<d.y1<<")";
+  SetDlgItemText(hwnd, IDC_PT1, s.str().c_str());
+
+  s.str(std::string());
+  s<<"("<<std::fixed<<std::setprecision(1)<<d.x2<<"; "<<d.y2<<")";
+  SetDlgItemText(hwnd, IDC_PT2, s.str().c_str());
+
+  s.str(std::string());
+  s<<"("<<std::fixed<<std::setprecision(1)<<d.x3<<"; "<<d.y3<<")";
+  SetDlgItemText(hwnd, IDC_PT3, s.str().c_str());
+
+  s.str(std::string());
+  s<<d.res_x<<"x"<<d.res_y;
+  SetDlgItemText(hwnd, IDC_RES, s.str().c_str());
+  SetDlgItemInt(hwnd, IDC_NUM, d.dataID, true);
+}
+
+BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    (void) lParam;
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            SetDlgItemText(hwndDlg, IDC_TITLE, "Default");
+            return TRUE;
+
+        case WM_CLOSE:
+            EndDialog(hwndDlg, 0);
+            return TRUE;
+
+        case WM_COMMAND:
+            switch(LOWORD(wParam))
+            {
+                /*
+                 * TODO: Add more control ID's, when needed.
+                 */
+                case IDQUIT:
+                    FreeLibrary(ftclient);
+                    EndDialog(hwndDlg, 0);
+                    return TRUE;
+                case IDC_START:
+                  start(hwndDlg);
+//l                  int ok;
+//                  int num = GetDlgItemInt(hwndDlg, IDC_APPID, (BOOL*)&ok, false);
+                  if(timer != 0){
+                    KillTimer(hwndDlg, timer);
+                    timer = 0;
+                  }
+                  timer = SetTimer(hwndDlg, 0, 50, TimerProcedure);
+                  break;
+
+            }
+    }
+
+    return FALSE;
+}
+
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+{
+  (void) hPrevInstance;
+  (void) lpCmdLine;
+  (void) nShowCmd;
+  hInst = hInstance;
+  
+  // The user interface is a modal dialog box
+  return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DialogProc);
+}
+
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/resource.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/resource.h
new file mode 100644
index 00000000..8bba17b4
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/ft_tester/resource.h
@@ -0,0 +1,27 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDD_DIALOG1                             100
+#define IDQUIT                                  1002
+#define IDC_YAW                                 1005
+#define IDC_PITCH                               1023
+#define IDC_ROLL                                1024
+#define IDC_X                                   1025
+#define IDC_Y                                   1026
+#define IDC_Z                                   1027
+#define IDC_RYAW                                1028
+#define IDC_RPITCH                              1029
+#define IDC_RROLL                               1030
+#define IDC_RX                                  1031
+#define IDC_RY                                  1032
+#define IDC_RZ                                  1033
+#define IDC_NUM                                 1034
+#define IDC_RES                                 1035
+#define IDC_PT0                                 1036
+#define IDC_PT1                                 1037
+#define IDC_PT2                                 1038
+#define IDC_PT3                                 1039
+#define IDC_START                               1040
+#define IDC_TITLE                               1041
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.h
new file mode 100644
index 00000000..770e1c71
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.h
@@ -0,0 +1,17 @@
+
+extern int NP_RegisterWindowHandle (HWND hwnd);
+extern int NP_UnregisterWindowHandle (void);
+extern int NP_RegisterProgramProfileID (unsigned short id);
+extern int NP_QueryVersion (unsigned short *version);
+extern int NP_RequestData (unsigned short req);
+extern int NP_GetSignature (tir_signature_t *sig);
+extern int NP_GetData (tir_data_t *data);
+extern int NP_GetParameter (void);
+extern int NP_SetParameter (void);
+extern int NP_StartCursor (void);
+extern int NP_StopCursor (void);
+extern int NP_ReCenter (void);
+extern int NP_StartDataTransmission (void);
+extern int NP_StopDataTransmission (void);
+
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.spec b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.spec
new file mode 100644
index 00000000..7fe5f1b4
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient.spec
@@ -0,0 +1,23 @@
+# Generated from NPClient.dll by winedump
+
+1 stub NPPriv_ClientNotify
+2 stub NPPriv_GetLastError
+3 stub NPPriv_SetData
+4 stub NPPriv_SetLastError
+5 stub NPPriv_SetParameter
+6 stub NPPriv_SetSignature
+7 stub NPPriv_SetVersion
+8 stdcall NP_GetData( ptr ) NPCLIENT_NP_GetData
+9 stdcall NP_GetParameter( long long) NPCLIENT_NP_GetParameter
+10 stdcall NP_GetSignature( ptr ) NPCLIENT_NP_GetSignature
+11 stdcall NP_QueryVersion( ptr ) NPCLIENT_NP_QueryVersion
+12 stdcall NP_ReCenter() NPCLIENT_NP_ReCenter
+13 stdcall NP_RegisterProgramProfileID( long ) NPCLIENT_NP_RegisterProgramProfileID
+14 stdcall NP_RegisterWindowHandle( ptr ) NPCLIENT_NP_RegisterWindowHandle
+15 stdcall NP_RequestData( long ) NPCLIENT_NP_RequestData
+16 stdcall NP_SetParameter( long long ) NPCLIENT_NP_SetParameter
+17 stdcall NP_StartCursor() NPCLIENT_NP_StartCursor
+18 stdcall NP_StartDataTransmission() NPCLIENT_NP_StartDataTransmission
+19 stdcall NP_StopCursor() NPCLIENT_NP_StopCursor
+20 stdcall NP_StopDataTransmission() NPCLIENT_NP_StopDataTransmission
+21 stdcall NP_UnregisterWindowHandle() NPCLIENT_NP_UnregisterWindowHandle
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_dll.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_dll.h
new file mode 100644
index 00000000..b0bab5db
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_dll.h
@@ -0,0 +1,58 @@
+/*
+ * NPClient.dll
+ *
+ * Generated from NPClient.dll by winedump.
+ *
+ * DO NOT SEND GENERATED DLLS FOR INCLUSION INTO WINE !
+ *
+ */
+#ifndef __WINE_NPCLIENT_DLL_H
+#define __WINE_NPCLIENT_DLL_H
+
+#include "windef.h"
+#include "wine/debug.h"
+#include "winbase.h"
+#include "winnt.h"
+
+#pragma pack(1)
+typedef struct tir_data{
+  short status;
+  short frame;
+  unsigned int cksum;
+  float roll, pitch, yaw;
+  float tx, ty, tz;
+  float padding[9];
+} tir_data_t;
+
+typedef struct tir_signature{
+    char DllSignature[200];
+    char AppSignature[200];
+} tir_signature_t;
+#pragma pack(0)
+
+
+/* __stdcall NPCLIENT_NPPriv_ClientNotify(); */
+/* __stdcall NPCLIENT_NPPriv_GetLastError(); */
+/* __stdcall NPCLIENT_NPPriv_SetData(); */
+/* __stdcall NPCLIENT_NPPriv_SetLastError(); */
+/* __stdcall NPCLIENT_NPPriv_SetParameter(); */
+/* __stdcall NPCLIENT_NPPriv_SetSignature(); */
+/* __stdcall NPCLIENT_NPPriv_SetVersion(); */
+int __stdcall NPCLIENT_NP_GetData(tir_data_t * data);
+int __stdcall NPCLIENT_NP_GetParameter(int arg0, int arg1);
+int __stdcall NPCLIENT_NP_GetSignature(tir_signature_t * sig);
+int __stdcall NPCLIENT_NP_QueryVersion(unsigned short * version);
+int __stdcall NPCLIENT_NP_ReCenter(void);
+int __stdcall NPCLIENT_NP_RegisterProgramProfileID(unsigned short id);
+int __stdcall NPCLIENT_NP_RegisterWindowHandle(HWND hwnd);
+int __stdcall NPCLIENT_NP_RequestData(unsigned short req);
+int __stdcall NPCLIENT_NP_SetParameter(int arg0, int arg1);
+int __stdcall NPCLIENT_NP_StartCursor(void);
+int __stdcall NPCLIENT_NP_StartDataTransmission(void);
+int __stdcall NPCLIENT_NP_StopCursor(void);
+int __stdcall NPCLIENT_NP_StopDataTransmission(void);
+int __stdcall NPCLIENT_NP_UnregisterWindowHandle(void);
+
+
+
+#endif	/* __WINE_NPCLIENT_DLL_H */
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_main.c b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_main.c
new file mode 100644
index 00000000..f892f89e
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/NPClient_main.c
@@ -0,0 +1,444 @@
+/*
+ * NPClient.dll
+ *
+ * Generated from NPClient.dll by winedump.
+ *
+ * DO NOT SUBMIT GENERATED DLLS FOR INCLUSION INTO WINE!
+ *
+ */
+
+#include <linuxtrack.h>
+#include "rest.h"
+//#include "config.h"
+#define __WINESRC__
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "windef.h"
+#include "winbase.h"
+#include "NPClient_dll.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(NPClient);
+
+bool crypted = false;
+static unsigned char table[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static int dbg_flag;
+
+static void dbg_report(const char *msg,...)
+{
+  static FILE *f = NULL;
+  if(dbg_flag){
+    if(f == NULL){
+      f = fopen("NPClient.log", "w");
+    }
+    va_list ap;
+    va_start(ap,msg);
+    vfprintf(f, msg, ap);
+    fflush(f);
+    va_end(ap);
+  }
+}
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+
+    switch (fdwReason)
+    {
+        case DLL_WINE_PREATTACH:
+            return TRUE;
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hinstDLL);
+            dbg_flag = getDebugFlag('w');
+            dbg_report("Attach request\n");
+            break;
+        case DLL_PROCESS_DETACH:
+            linuxtrack_shutdown();
+            break;
+    }
+
+    return TRUE;
+}
+/******************************************************************
+ *		NPPriv_ClientNotify (NPCLIENT.1)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_ClientNotify()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_GetLastError (NPCLIENT.2)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_GetLastError()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_SetData (NPCLIENT.3)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_SetData()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_SetLastError (NPCLIENT.4)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_SetLastError()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_SetParameter (NPCLIENT.5)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_SetParameter()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_SetSignature (NPCLIENT.6)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_SetSignature()
+{
+	/* @stub in .spec */
+}
+#endif
+/******************************************************************
+ *		NPPriv_SetVersion (NPCLIENT.7)
+ *
+ *
+ */
+#if 0
+__stdcall NPCLIENT_NPPriv_SetVersion()
+{
+	/* @stub in .spec */
+}
+#endif
+
+static float limit_num(float min, float val, float max)
+{
+  if(val < min) return min;
+  if(val > max) return max;
+  return val;
+}
+
+static unsigned int cksum(unsigned char buf[], unsigned int size)
+{
+  if((size == 0) || (buf == NULL)){
+    return 0;
+  }
+  
+  int rounds = size >> 2;
+  int rem = size % 4;
+
+  int c = size;
+  int a0, a2;
+//  printf("Orig: ");
+//for(a0 = 0; a0 < (int)size; ++a0)
+//{
+//  printf("%02X", buf[a0]);
+//}
+//printf("\n");
+  while(rounds != 0){
+    a0 = *(short int*)buf;
+    a2 = *(short int*)(buf+2);
+    buf += 4;
+    c += a0;
+    a2 ^= (c << 5);
+    a2 <<= 11;
+    c ^= a2;
+    c += (c >> 11);
+    --rounds;
+  }
+  switch(rem){
+    case 3:
+        a0 = *(short int*)buf;
+        a2 = *(signed char*)(buf+2);
+        c += a0;
+        a2 = (a2 << 2) ^ c;
+        c ^= (a2 << 16);
+        a2 = (c >> 11);
+      break;
+    case 2:
+        a2 = *(short int*)buf;
+        c += a2;
+        c ^= (c << 11);
+        a2 = (c >> 17);
+      break;
+    case 1:
+        a2 = *(signed char*)(buf);
+        c += a2;
+        c ^= (c << 10);
+        a2 = (c >> 1);
+      break;
+    default:
+      break;
+  }
+  if(rem != 0){
+    c+=a2;
+  }
+
+  c ^= (c << 3);
+  c += (c >> 5);
+  c ^= (c << 4);
+  c += (c >> 17);
+  c ^= (c << 25);
+  c += (c >> 6);
+
+  return (unsigned int)c;
+}
+
+static void enhance(unsigned char buf[], unsigned int size,
+             unsigned char codetable[], unsigned int table_size)
+{
+  unsigned int table_ptr = 0;
+  unsigned char var = 0x88;
+  unsigned char tmp;
+  if((size <= 0) || (table_size <= 0) ||
+     (buf == NULL) || (codetable == NULL)){
+    return;
+  }
+  do{
+    tmp = buf[--size];
+    buf[size] = tmp ^ codetable[table_ptr] ^ var;
+    var += size + tmp;
+    ++table_ptr;
+    if(table_ptr >= table_size){
+      table_ptr -= table_size;
+    }
+  }while(size != 0);
+}
+
+
+/******************************************************************
+ *		NP_GetData (NPCLIENT.8)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_GetData(tir_data_t * data)
+{
+  float r, p, y, tx, ty, tz;
+  unsigned int frame;
+  int res = linuxtrack_get_pose(&y, &p, &r, &tx, &ty, &tz, &frame);
+  memset((char *)data, 0, sizeof(tir_data_t));
+  data->status = (linuxtrack_get_tracking_state() == RUNNING) ? 0 : 1;
+  data->frame = frame & 0xFFFF;
+  data->cksum = 0;
+  data->roll = r / 180.0 * 16383;
+  data->pitch = -p / 180.0 * 16383;
+  data->yaw = y / 180.0 * 16383;
+  data->tx = -limit_num(-16383.0, 15 * tx, 16383); 
+  data->ty = limit_num(-16383.0, 15 * ty, 16383); 
+  data->tz = limit_num(-16383.0, 15 * tz, 16383);
+  data->cksum = cksum((unsigned char*)data, sizeof(tir_data_t));
+  //printf("Cksum: %04X\n", data->cksum);
+  if(crypted){
+    enhance((unsigned char*)data, sizeof(tir_data_t), table, sizeof(table));
+  }
+  return (res >= 0) ? 0: 1;
+}
+/******************************************************************
+ *		NP_GetParameter (NPCLIENT.9)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_GetParameter(int arg0, int arg1)
+{
+        dbg_report("GetParameter request: %d %d\n", arg0, arg1);
+	TRACE("(void): stub\n");
+	return (int) 0;
+}
+
+/******************************************************************
+ *		NP_GetSignature (NPCLIENT.10)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_GetSignature(tir_signature_t * sig)
+{
+  dbg_report("GetSignature request\n");
+  if(getSomeSeriousPoetry(sig->DllSignature, sig->AppSignature)){
+    printf("Signature result: OK\n");
+    return 0;
+  }else{
+    printf("Signature result: NOT OK!\n");
+    return 1;
+  }
+}
+/******************************************************************
+ *		NP_QueryVersion (NPCLIENT.11)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_QueryVersion(unsigned short * version)
+{
+        dbg_report("QueryVersion request\n");
+	*version=0x0500;
+	return 0;
+}
+/******************************************************************
+ *		NP_ReCenter (NPCLIENT.12)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_ReCenter(void)
+{
+  dbg_report("ReCenter request\n");
+  linuxtrack_recenter();
+  return 0;
+}
+
+/******************************************************************
+ *		NP_RegisterProgramProfileID (NPCLIENT.13)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_RegisterProgramProfileID(unsigned short id)
+{
+  dbg_report("RegisterProgramProfileID request: %d\n", id);
+  game_desc_t gd;
+  if(game_data_get_desc(id, &gd)){
+    printf("Application ID: %d - %s!!!\n", id, gd.name);
+    if(game_data_get_desc(id, &gd)){
+      crypted = gd.encrypted;
+      if(gd.encrypted){
+        printf("Table: %02X %02X %02X %02X %02X %02X %02X %02X\n", table[0],table[1],table[2],table[3],table[4],
+             table[5], table[6], table[7]);
+        table[0] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+        table[1] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+        table[2] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+        table[3] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+        table[4] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+        table[5] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+        table[6] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+        table[7] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+      }
+    }
+    if(linuxtrack_init(gd.name) != 0){
+      return 1;
+    }
+  }else{
+    if(!linuxtrack_init("Default")){
+      return 1;
+    }
+  }
+  linuxtrack_suspend();
+  return 0;
+}
+/******************************************************************
+ *		NP_RegisterWindowHandle (NPCLIENT.14)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_RegisterWindowHandle(HWND hwnd)
+{
+        dbg_report("RegisterWindowHandle request: 0x%X\n", hwnd);
+	TRACE("((HWND)%p): stub\n",hwnd);
+	return (int) 0;
+}
+/******************************************************************
+ *		NP_RequestData (NPCLIENT.15)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_RequestData(unsigned short req)
+{
+        dbg_report("RequestData request: %d\n", req);
+	TRACE("((unsigned short)%d): stub\n",req);
+	return (int) 0;
+}
+/******************************************************************
+ *		NP_SetParameter (NPCLIENT.16)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_SetParameter(int arg0, int arg1)
+{
+        dbg_report("SetParameter request: %d %d\n", arg0, arg1);
+	TRACE("(void): stub\n");
+	return (int) 0;
+}
+/******************************************************************
+ *		NP_StartCursor (NPCLIENT.17)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_StartCursor(void)
+{
+        dbg_report("StartCursor request\n");
+	TRACE("(void): stub\n");
+	return (int) 0;
+}
+/******************************************************************
+ *		NP_StartDataTransmission (NPCLIENT.18)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_StartDataTransmission(void)
+{
+  dbg_report("StartDataTransmission request\n");
+  linuxtrack_wakeup();
+  return 0;
+}
+/******************************************************************
+ *		NP_StopCursor (NPCLIENT.19)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_StopCursor(void)
+{
+        dbg_report("StopCursor request\n");
+	TRACE("(void): stub\n");
+	return (int) 0;
+}
+/******************************************************************
+ *		NP_StopDataTransmission (NPCLIENT.20)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_StopDataTransmission(void)
+{
+  dbg_report("StopDataTransmission request\n");
+  linuxtrack_suspend();
+  return 0;
+}
+/******************************************************************
+ *		NP_UnregisterWindowHandle (NPCLIENT.21)
+ *
+ *
+ */
+int __stdcall NPCLIENT_NP_UnregisterWindowHandle(void)
+{
+        dbg_report("UnregisterWindowHandle request\n");
+	TRACE("(void): stub\n");
+	return (int) 0;
+}
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.c b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.c
new file mode 100644
index 00000000..3197ba37
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.c
@@ -0,0 +1,149 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <mxml.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <utils.h>
+
+
+//First 5 bytes is MD5 hash of "NaturalPoint"
+static uint8_t secret_key[] = {0x0e, 0x9a, 0x63, 0x71, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint8_t S[256] = {0};
+
+static char *decoded = NULL;
+
+static mxml_node_t *xml = NULL;
+static mxml_node_t *tree = NULL;
+
+static void ksa(uint8_t key[], size_t len)
+{
+  unsigned int i, j;
+  for(i = 0; i < 256; ++i){
+    S[i] = i;
+  }
+  j = 0;
+  for(i = 0; i < 256; ++i){
+    j = (j + S[i] + key[i % len]) % 256;
+    uint8_t tmp = S[i];
+    S[i] = S[j];
+    S[j] = tmp;
+  }
+}
+
+static uint8_t rc4()
+{
+  static uint8_t i = 0;
+  static uint8_t j = 0;
+
+  i += 1;
+  j += S[i];
+  uint8_t tmp = S[i];
+  S[i] = S[j];
+  S[j] = tmp;
+  return S[(S[i] + S[j]) % 256];
+}
+
+static bool decrypt_file(const char *fname, bool from_update)
+{
+  uint32_t header[5];
+  size_t datlen;
+  ksa(secret_key, 16);
+  FILE *inp;
+  struct stat fst;
+
+  if((inp = fopen(fname, "rb")) == NULL){
+    printf("Can't open input file '%s'", fname);
+    return false;
+  }
+
+  if(fstat(fileno(inp), &fst) != 0){
+    fclose(inp);
+    printf("Cannot stat file '%s'\n", fname);
+    return false;
+  }
+  
+  if(from_update){
+    if(fread(&header, sizeof(uint32_t), 5, inp) != 5){
+      fclose(inp);
+      printf("Can't read the header - file '%s' is less than 20 bytes long?\n", fname);
+      return false;
+    }
+    datlen = header[4];
+  }else{
+    datlen = fst.st_size;
+  }
+  if((decoded = (char *)malloc(datlen+1)) == NULL){
+    printf("malloc failed!\n");
+    return false;
+  }
+  memset(decoded, 0, datlen+1);
+  size_t i;
+  size_t len = fread(decoded, 1, datlen, inp);
+  (void) len;
+  for(i = 0; i < datlen; ++i) decoded[i] ^= rc4();
+  fclose(inp);
+  
+  //inp = fopen("tmp.dump", "w");
+  //fwrite(decoded, 1, datlen, inp);
+  //fclose(inp);
+  
+  return true;
+}
+
+static bool game_data_init(const char *fname, bool from_update)
+{
+  static bool initialized = false;
+  if(initialized){
+    return true;
+  }
+  if(!decrypt_file(fname, from_update)){
+    printf("Error decrypting file!\n");
+    return false;
+  }
+  xml = mxmlNewXML("1.0");
+  tree = mxmlLoadString(xml, decoded, MXML_TEXT_CALLBACK);
+  return (tree != NULL);
+}
+
+static void game_data_close()
+{
+  mxmlDelete(tree);
+  free(decoded);
+}
+
+bool get_game_data(const char *input_fname, const char *output_fname, bool from_update)
+{
+  FILE *outfile = NULL;
+  if((outfile = fopen(output_fname, "w")) == NULL){
+    ltr_int_log_message("Can't open the output file '%s'!\n", output_fname);
+    return false;
+  }
+  if(!game_data_init(input_fname, from_update)){
+    ltr_int_log_message("Can't process the data file '%s'!\n", input_fname);
+    return false;
+  }
+  
+  mxml_node_t *game;
+  const char *name;
+  const char *id;
+  for(game = mxmlFindElement(tree, tree, "Game", NULL, NULL, MXML_DESCEND); 
+      game != NULL;
+      game =  mxmlFindElement(game, tree, "Game", NULL, NULL, MXML_DESCEND)){
+    name = mxmlElementGetAttr(game, "Name");
+    id = mxmlElementGetAttr(game, "Id");
+      
+    mxml_node_t *appid = mxmlFindElement(game, game, "ApplicationID", NULL, NULL, MXML_DESCEND);
+    if(appid == NULL){
+      fprintf(outfile, "%s \"%s\"\n", id, name);
+    }else{
+      fprintf(outfile, "%s \"%s\" (%s)\n", id, name, appid->child->value.text.string);
+    }
+  }  
+  fclose(outfile);
+  game_data_close();
+  return true;
+}
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.h
new file mode 100644
index 00000000..b71f7a15
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/important-stuff/game_data.h
@@ -0,0 +1,17 @@
+#ifndef GAME_DATA__H
+#define GAME_DATA__H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool get_game_data(const char *input_fname, const char *output_fname, bool from_update);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.am b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.am
new file mode 100644
index 00000000..e025209a
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.am
@@ -0,0 +1,78 @@
+noinst_SCRIPTS = 
+if WINE_PLUGIN
+  noinst_SCRIPTS += Tester.exe
+if WINE64
+  noinst_SCRIPTS += Tester64.exe
+endif #WINE64
+endif #WINE_PLUGIN
+
+if DARWIN
+  LDFLAGS += -Wl,-no_arch_warnings
+else
+  LDFLAGS += -Wl,--no-warn-search-mismatch
+endif
+
+CC = winegcc
+
+CXX = wineg++
+
+SUFFIXES = .o .cpp .c .rc 64.o
+
+.cpp.o :
+	$(CXX) -c $(CXXFLAGS) -m32 -o $@ $<
+
+.c.o :
+	$(CC) -c $(CFLAGS) -m32 -o $@ $<
+
+.cpp64.o :
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+.c64.o :
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+.rc.o :
+	wrc -o $@ $(RCFLAGS) $<
+
+CXXFLAGS += -g -DHAVE_CONFIG_H -I../../.. -I. -I@srcdir@/../.. -I@top_builddir@
+CFLAGS += -g -I../.. -I../../.. -DHAVE_CONFIG_H -I@srcdir@/../.. -I@top_builddir@
+RCFLAGS = -I @srcdir@
+#VPATH = ../..:@srcdir@/../..:@top_builddir@:@srcdir@
+vpath %.h @srcdir@/../..
+vpath %.h @top_builddir@
+vpath %.c @srcdir@
+vpath %.c @srcdir@/../..
+
+
+Tester64.exe : main64.o rest64.o npifc64.o npview.o
+	wineg++ -g -o Tester64 -L. $(WINE64_LIBS) $(LDFLAGS) -Wall -Wextra $^
+
+Tester.exe : main.o npview.o rest.o npifc.o
+	wineg++ -g -o Tester -L. $(WINE_LIBS) $(LDFLAGS) -m32 -Wall -Wextra $^
+
+main.o : main.cpp Makefile
+
+main64.o : main.cpp Makefile
+
+npview.o : npview.rc
+
+rest.o : rest.c rest.h Makefile
+
+rest64.o : rest.c rest.h Makefile
+
+npifc.o : npifc.c npifc.h Makefile
+
+npifc64.o : CFLAGS+="-DFOR_WIN64=1"
+npifc64.o : npifc.c npifc.h Makefile
+
+clean-local: clean-local-check
+.PHONY: clean-local-check
+clean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+distclean-local: distclean-local-check
+.PHONY: distclean-local-check
+distclean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+EXTRA_DIST = main.cpp npifc.c npifc.h resource.h rest.c rest.h
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.in b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.in
new file mode 100644
index 00000000..cc49d754
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/Makefile.in
@@ -0,0 +1,512 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@WINE_PLUGIN_TRUE@am__append_1 = Tester.exe
+@WINE64_TRUE@@WINE_PLUGIN_TRUE@am__append_2 = Tester64.exe
+@DARWIN_TRUE@am__append_3 = -Wl,-no_arch_warnings
+@DARWIN_FALSE@am__append_4 = -Wl,--no-warn-search-mismatch
+subdir = src/wine_bridge/tester
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/npview.rc.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = npview.rc
+CONFIG_CLEAN_VPATH_FILES =
+SCRIPTS = $(noinst_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+depcomp =
+am__depfiles_maybe =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BISON = @BISON@
+CC = winegcc
+CFLAGS = @CFLAGS@ -g -I../.. -I../../.. -DHAVE_CONFIG_H \
+	-I@srcdir@/../.. -I@top_builddir@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = wineg++
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@ -g -DHAVE_CONFIG_H -I../../.. -I. \
+	-I@srcdir@/../.. -I@top_builddir@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@ $(am__append_3) $(am__append_4)
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIB32DIR = @LIB32DIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCFLAGS = @OBJCFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENCV_CFLAGS = @OPENCV_CFLAGS@
+OPENCV_LIBS = @OPENCV_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+QMAKE_PATH = @QMAKE_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINE64_LIBS = @WINE64_LIBS@
+WINE_LIBS = @WINE_LIBS@
+XPL_CPPFLAGS = @XPL_CPPFLAGS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+with_makensis = @with_makensis@
+with_wine64 = @with_wine64@
+noinst_SCRIPTS = $(am__append_1) $(am__append_2)
+SUFFIXES = .o .cpp .c .rc 64.o
+RCFLAGS = -I @srcdir@
+EXTRA_DIST = main.cpp npifc.c npifc.h resource.h rest.c rest.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .o .cpp .c .rc 64.o
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps src/wine_bridge/tester/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu --ignore-deps src/wine_bridge/tester/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+npview.rc: $(top_builddir)/config.status $(srcdir)/npview.rc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	clean-local cscopelist-am ctags-am distclean distclean-generic \
+	distclean-libtool distclean-local distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+	uninstall-am
+
+
+.cpp.o :
+	$(CXX) -c $(CXXFLAGS) -m32 -o $@ $<
+
+.c.o :
+	$(CC) -c $(CFLAGS) -m32 -o $@ $<
+
+.cpp64.o :
+	$(CXX) -c $(CXXFLAGS) -o $@ $<
+
+.c64.o :
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+.rc.o :
+	wrc -o $@ $(RCFLAGS) $<
+#VPATH = ../..:@srcdir@/../..:@top_builddir@:@srcdir@
+vpath %.h @srcdir@/../..
+vpath %.h @top_builddir@
+vpath %.c @srcdir@
+vpath %.c @srcdir@/../..
+
+Tester64.exe : main64.o rest64.o npifc64.o npview.o
+	wineg++ -g -o Tester64 -L. $(WINE64_LIBS) $(LDFLAGS) -Wall -Wextra $^
+
+Tester.exe : main.o npview.o rest.o npifc.o
+	wineg++ -g -o Tester -L. $(WINE_LIBS) $(LDFLAGS) -m32 -Wall -Wextra $^
+
+main.o : main.cpp Makefile
+
+main64.o : main.cpp Makefile
+
+npview.o : npview.rc
+
+rest.o : rest.c rest.h Makefile
+
+rest64.o : rest.c rest.h Makefile
+
+npifc.o : npifc.c npifc.h Makefile
+
+npifc64.o : CFLAGS+="-DFOR_WIN64=1"
+npifc64.o : npifc.c npifc.h Makefile
+
+clean-local: clean-local-check
+.PHONY: clean-local-check
+clean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+distclean-local: distclean-local-check
+.PHONY: distclean-local-check
+distclean-local-check:
+	rm -f *.exe* *.dll* *.sh *.o
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/main.cpp b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/main.cpp
new file mode 100644
index 00000000..95ca0d9b
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/main.cpp
@@ -0,0 +1,100 @@
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "resource.h"
+#include "rest.h"
+#include "npifc.h"
+
+HINSTANCE hInst;
+UINT_PTR timer = 0;
+
+VOID CALLBACK TimerProcedure(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+  (void) uMsg;
+  (void) idEvent;
+  (void) dwTime;
+  tir_data_t td;
+  npifc_getdata(&td);
+  SetDlgItemInt(hwnd, IDC_PITCH, td.pitch, true);
+  SetDlgItemInt(hwnd, IDC_ROLL, td.roll, true);
+  SetDlgItemInt(hwnd, IDC_YAW, td.yaw, true);
+
+  SetDlgItemInt(hwnd, IDC_X1, td.tx, true);
+  SetDlgItemInt(hwnd, IDC_Y1, td.ty, true);
+  SetDlgItemInt(hwnd, IDC_Z1, td.tz, true);
+
+  SetDlgItemInt(hwnd, IDC_X2, td.padding[0], true);
+  SetDlgItemInt(hwnd, IDC_Y2, td.padding[1], true);
+  SetDlgItemInt(hwnd, IDC_Z2, td.padding[2], true);
+  SetDlgItemInt(hwnd, IDC_X3, td.padding[3], true);
+  SetDlgItemInt(hwnd, IDC_Y3, td.padding[4], true);
+  SetDlgItemInt(hwnd, IDC_Z3, td.padding[5], true);
+  SetDlgItemInt(hwnd, IDC_S, td.status, true);
+  SetDlgItemInt(hwnd, IDC_F, td.frame, true);
+}
+
+BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    (void) lParam;
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            SetDlgItemInt(hwndDlg, IDC_APPID, 2307, true);
+            return TRUE;
+
+        case WM_CLOSE:
+            EndDialog(hwndDlg, 0);
+            return TRUE;
+
+        case WM_COMMAND:
+            switch(LOWORD(wParam))
+            {
+                /*
+                 * TODO: Add more control ID's, when needed.
+                 */
+                case IDQUIT:
+                    npifc_close();
+                    EndDialog(hwndDlg, 0);
+                    return TRUE;
+                case IDSTART:
+                  int ok;
+                  int num = GetDlgItemInt(hwndDlg, IDC_APPID, (BOOL*)&ok, false);
+                  if(!ok){
+                    num = 2307;
+                  }
+                  game_desc_t gd;
+                  if(timer != 0){
+                    KillTimer(hwndDlg, timer);
+                    timer = 0;
+                  }
+                  if(game_data_get_desc(num, &gd)){
+                    printf("Application ID: %d - %s\n", num, gd.name);
+                    if(npifc_init(hwndDlg, num)){
+                      timer = SetTimer(hwndDlg, 0, 50, TimerProcedure);
+                    }
+                  }else{
+                    printf("Unknown Application ID: %d\n", num);
+                  }
+                  break;
+
+            }
+    }
+
+    return FALSE;
+}
+
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+{
+  (void) hPrevInstance;
+  (void) lpCmdLine;
+  (void) nShowCmd;
+  hInst = hInstance;
+  
+  // The user interface is a modal dialog box
+  return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DialogProc);
+}
+
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.c b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.c
new file mode 100644
index 00000000..b036464e
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.c
@@ -0,0 +1,302 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "npifc.h"
+#include "rest.h"
+
+
+tir_signature_t ts;
+HMODULE npclient;
+/*
+typedef int (*NP_RegisterWindowHandle_t)(HWND hwnd);
+typedef int (*NP_UnregisterWindowHandle_t)(void);
+typedef int (*NP_RegisterProgramProfileID_t)(unsigned short id);
+typedef int (*NP_QueryVersion_t)(unsigned short *version);
+typedef int (*NP_RequestData_t)(unsigned short req);
+typedef int (*NP_GetSignature_t)(tir_signature_t *sig);
+typedef int (*NP_GetData_t)(tir_data_t *data);
+typedef int (*NP_GetParameter_t)(void);
+typedef int (*NP_SetParameter_t)(void);
+typedef int (*NP_StartCursor_t)(void);
+typedef int (*NP_StopCursor_t)(void);
+typedef int (*NP_ReCenter_t)(void);
+typedef int (*NP_StartDataTransmission_t)(void);
+typedef int (*NP_StopDataTransmission_t)(void);
+*/
+NP_RegisterWindowHandle_t NP_RegisterWindowHandle = NULL;
+NP_UnregisterWindowHandle_t NP_UnregisterWindowHandle = NULL;
+NP_RegisterProgramProfileID_t NP_RegisterProgramProfileID = NULL;
+NP_QueryVersion_t NP_QueryVersion = NULL;
+NP_RequestData_t NP_RequestData = NULL;
+NP_GetSignature_t NP_GetSignature = NULL;
+NP_GetData_t NP_GetData = NULL;
+NP_GetParameter_t NP_GetParameter = NULL;
+NP_SetParameter_t NP_SetParameter = NULL;
+NP_StartCursor_t NP_StartCursor = NULL;
+NP_StopCursor_t NP_StopCursor = NULL;
+NP_ReCenter_t NP_ReCenter = NULL;
+NP_StartDataTransmission_t NP_StartDataTransmission = NULL;
+NP_StopDataTransmission_t NP_StopDataTransmission = NULL;
+
+bool crypted = false;
+
+
+
+unsigned char table[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+char *client_path()
+{
+  HKEY  hkey   = 0;
+  RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", 0,
+    KEY_QUERY_VALUE, &hkey);
+  if(!hkey){
+    printf("Can't open registry key\n");
+    return NULL;
+  }
+
+  BYTE path[1024];
+  DWORD buf_len = 1024;
+  LONG result = RegQueryValueEx(hkey, "Path", NULL, NULL, path, &buf_len);
+  char *full_path = NULL;
+  int res = -1;
+  if(result == ERROR_SUCCESS && buf_len > 0){
+#ifdef FOR_WIN64
+    res = asprintf(&full_path, "%s/NPClient64.dll", path);
+#else
+    res = asprintf(&full_path, "%s/NPClient.dll", path);
+#endif
+  }
+  RegCloseKey(hkey);
+  if(res > 0){
+    return full_path;
+  }else{
+    return NULL;
+  }
+}
+
+bool initialized = false;
+
+bool npifc_init(HWND wnd, int id)
+{
+  //table[] = {0xb3, 0x16, 0x36, 0xeb, 0xb9, 0x05, 0x4f, 0xa4};
+  game_desc_t gd;
+  if(game_data_get_desc(id, &gd)){
+    crypted = gd.encrypted;
+    if(gd.encrypted){
+      table[0] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+      table[1] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+      table[2] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+      table[3] = (unsigned char)(gd.key1&0xff); gd.key1 >>= 8;
+      table[4] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+      table[5] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+      table[6] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+      table[7] = (unsigned char)(gd.key2&0xff); gd.key2 >>= 8;
+    }
+  }
+  printf("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+          table[0], table[1], table[2], table[3],
+          table[4], table[5], table[6], table[7]);
+
+  char *client = client_path();
+  if(client == NULL){
+    printf("Couldn't obtain client path!\n");
+    return false;
+  }
+  npclient = LoadLibrary(client);
+  if(!npclient){
+    printf("Can't load client %s\n", client);
+    return false;
+  }
+
+  NP_RegisterWindowHandle = (NP_RegisterWindowHandle_t)GetProcAddress(npclient, "NP_RegisterWindowHandle");
+  NP_UnregisterWindowHandle = (NP_UnregisterWindowHandle_t)GetProcAddress(npclient, "NP_UnregisterWindowHandle");
+  NP_RegisterProgramProfileID = (NP_RegisterProgramProfileID_t)GetProcAddress(npclient, "NP_RegisterProgramProfileID");
+  NP_QueryVersion = (NP_QueryVersion_t)GetProcAddress(npclient, "NP_QueryVersion");
+  NP_RequestData = (NP_RequestData_t)GetProcAddress(npclient, "NP_RequestData");
+  NP_GetSignature = (NP_GetSignature_t)GetProcAddress(npclient, "NP_GetSignature");
+  NP_GetData = (NP_GetData_t)GetProcAddress(npclient, "NP_GetData");
+  NP_GetParameter = (NP_GetParameter_t)GetProcAddress(npclient, "NP_GetParameter");
+  NP_SetParameter = (NP_SetParameter_t)GetProcAddress(npclient, "NP_SetParameter");
+  NP_StartCursor = (NP_StartCursor_t)GetProcAddress(npclient, "NP_StartCursor");
+  NP_StopCursor = (NP_StopCursor_t)GetProcAddress(npclient, "NP_StopCursor");
+  NP_ReCenter = (NP_ReCenter_t)GetProcAddress(npclient, "NP_ReCenter");
+  NP_StartDataTransmission = (NP_StartDataTransmission_t)GetProcAddress(npclient, "NP_StartDataTransmission");
+  NP_StopDataTransmission = (NP_StopDataTransmission_t)GetProcAddress(npclient, "NP_StopDataTransmission");
+  if((NP_RegisterWindowHandle == NULL) || (NP_UnregisterWindowHandle == NULL)
+     || (NP_RegisterProgramProfileID == NULL) || (NP_QueryVersion == NULL) || (NP_RequestData == NULL)
+     || (NP_GetSignature == NULL) || (NP_GetData == NULL) || (NP_GetParameter == NULL)
+     || (NP_SetParameter == NULL) || (NP_StartCursor == NULL) || (NP_StopCursor == NULL)
+     || (NP_ReCenter == NULL) || (NP_StartDataTransmission == NULL) || (NP_StopDataTransmission == NULL)){
+    printf("Couldn't bind all necessary functions!\n");
+    return false;
+  }
+  tir_signature_t sig;
+  int res;
+  if((res = NP_GetSignature(&sig)) != 0){
+    printf("Error retrieving signature! %d\n", res);
+    return false;
+  }
+  printf("Dll Sig:%s\nApp Sig2:%s\n", sig.DllSignature, sig.AppSignature);
+  NP_RegisterWindowHandle(wnd);
+  if(NP_RegisterProgramProfileID(id) != 0){
+    printf("Couldn't register profile id!\n");
+    return false;
+  }
+  printf("Program profile registered!\n");
+  NP_RequestData(65535);
+  NP_StopCursor();
+  NP_StartDataTransmission();
+  initialized = true;
+  return true;
+}
+
+void npifc_close()
+{
+  if(initialized){
+    NP_StopDataTransmission();
+    NP_StartCursor();
+    NP_UnregisterWindowHandle();
+  }
+  initialized = false;
+}
+
+void c_encrypt(unsigned char buf[], unsigned int size,
+             unsigned char code_table[], unsigned int table_size)
+{
+  unsigned int table_ptr = 0;
+  unsigned char var = 0x88;
+  unsigned char tmp;
+  if((size <= 0) || (table_size <= 0) ||
+     (buf == NULL) || (code_table == NULL))
+     return;
+  do{
+    tmp = buf[--size];
+    buf[size] = tmp ^ code_table[table_ptr] ^ var;
+    var += size + tmp;
+    ++table_ptr;
+    if(table_ptr >= table_size){
+      table_ptr -= table_size;
+    }
+  }while(size != 0);
+}
+
+
+
+void decrypt(unsigned char buf[], unsigned int size,
+             unsigned char code_table[], unsigned int table_size)
+{
+  unsigned int table_ptr = 0;
+  unsigned char var = 0x88;
+  unsigned char tmp;
+  if((size <= 0) || (table_size <= 0) ||
+     (buf == NULL) || (code_table == NULL)){
+      return;
+  }
+ do{
+    tmp = buf[--size];
+    buf[size] = tmp ^ code_table[table_ptr] ^ var;
+    var += size + buf[size];
+    ++table_ptr;
+    if(table_ptr >= table_size){
+      table_ptr -= table_size;
+    }
+  }while(size != 0);
+}
+
+unsigned int cksum(unsigned char buf[], unsigned int size)
+{
+  if((size == 0) || (buf == NULL)){
+    return 0;
+  }
+  int rounds = size >> 2;
+  int rem = size % 4;
+
+  int c = size;
+  int a0 = 0;
+  int a2 = 0;
+
+  while(rounds != 0){
+    a0 = *(short int*)buf;
+    a2 = *(short int*)(buf+2);
+    buf += 4;
+    c += a0;
+    a2 ^= (c << 5);
+    a2 <<= 11;
+    c ^= a2;
+    c += (c >> 11);
+    --rounds;
+  }
+  switch(rem){
+    case 3:
+        a0 = *(short int*)buf;
+        a2 = *(signed char*)(buf+2);
+        c += a0;
+        a2 = (a2 << 2) ^ c;
+        c ^= (a2 << 16);
+        a2 = (c >> 11);
+      break;
+    case 2:
+        a2 = *(short int*)buf;
+        c += a2;
+        c ^= (c << 11);
+        a2 = (c >> 17);
+      break;
+    case 1:
+        a2 = *(signed char*)(buf);
+        c += a2;
+        c ^= (c << 10);
+        a2 = (c >> 1);
+      break;
+    default:
+      break;
+  }
+  if(rem != 0){
+    c+=a2;
+  }
+
+  c ^= (c << 3);
+  c += (c >> 5);
+  c ^= (c << 4);
+  c += (c >> 17);
+  c ^= (c << 25);
+  c += (c >> 6);
+
+  return (unsigned int)c;
+}
+
+int decode_frame(tir_data_t *td)
+{
+    //printf("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+    //      table[0], table[1], table[2], table[3],
+    //      table[4], table[5], table[6], table[7]);
+    unsigned int csum;
+    decrypt((unsigned char*)td, sizeof(*td), table, sizeof(table));
+    csum = td->cksum;
+    td->cksum = 0;
+    if(csum != cksum((unsigned char*)td, sizeof(*td))){
+        printf("Problem with frame!\n");
+        //int a0;
+        //printf("Dec:  ");
+        //for(a0 = 0; a0 < (int)sizeof(tir_data_t); ++a0)
+        //{
+        //  printf("%02X", ((unsigned char *)td)[a0]);
+        //}
+        //printf("\n");
+        //printf("Cksum: %04X vs computed: %04X\n", csum, cksum((unsigned char*)td, sizeof(*td)));
+        return -1;
+    }
+    //printf("Frame OK!\n");
+    return 0;
+}
+
+int npifc_getdata(tir_data_t *data)
+{
+  int res = NP_GetData(data);
+  if(crypted){
+    decode_frame(data);
+  }
+  return res;
+}
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.h
new file mode 100644
index 00000000..d580e16d
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npifc.h
@@ -0,0 +1,66 @@
+#ifndef NPIFC__H
+#define NPIFC__H
+
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  bool npifc_init(HWND wnd, int id);
+  void npifc_close();
+
+#pragma pack(1)
+typedef struct tir_data{
+  short status;
+  short frame;
+  unsigned int cksum;
+  float roll, pitch, yaw;
+  float tx, ty, tz;
+  float padding[9];
+} tir_data_t;
+
+typedef struct tir_signature{
+    char DllSignature[200];
+    char AppSignature[200];
+} tir_signature_t;
+#pragma pack(0)
+
+int npifc_getdata(tir_data_t *data);
+
+typedef int __stdcall (*NP_RegisterWindowHandle_t)(HWND hwnd);
+typedef int __stdcall (*NP_UnregisterWindowHandle_t)(void);
+typedef int __stdcall (*NP_RegisterProgramProfileID_t)(unsigned short id);
+typedef int __stdcall (*NP_QueryVersion_t)(unsigned short *version);
+typedef int __stdcall (*NP_RequestData_t)(unsigned short req);
+typedef int __stdcall (*NP_GetSignature_t)(tir_signature_t *sig);
+typedef int __stdcall (*NP_GetData_t)(tir_data_t *data);
+typedef int __stdcall (*NP_GetParameter_t)(void);
+typedef int __stdcall (*NP_SetParameter_t)(void);
+typedef int __stdcall (*NP_StartCursor_t)(void);
+typedef int __stdcall (*NP_StopCursor_t)(void);
+typedef int __stdcall (*NP_ReCenter_t)(void);
+typedef int __stdcall (*NP_StartDataTransmission_t)(void);
+typedef int __stdcall (*NP_StopDataTransmission_t)(void);
+
+extern NP_RegisterWindowHandle_t NP_RegisterWindowHandle;
+extern NP_UnregisterWindowHandle_t NP_UnregisterWindowHandle;
+extern NP_RegisterProgramProfileID_t NP_RegisterProgramProfileID;
+extern NP_QueryVersion_t NP_QueryVersion;
+extern NP_RequestData_t NP_RequestData;
+extern NP_GetSignature_t NP_GetSignature;
+extern NP_GetData_t NP_GetData;
+extern NP_GetParameter_t NP_GetParameter;
+extern NP_SetParameter_t NP_SetParameter;
+extern NP_StartCursor_t NP_StartCursor;
+extern NP_StopCursor_t NP_StopCursor;
+extern NP_ReCenter_t NP_ReCenter;
+extern NP_StartDataTransmission_t NP_StartDataTransmission;
+extern NP_StopDataTransmission_t NP_StopDataTransmission;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npview.rc.in b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npview.rc.in
new file mode 100644
index 00000000..231002f1
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/npview.rc.in
@@ -0,0 +1,49 @@
+// Generated by ResEdit 1.5.9
+// Copyright (C) 2006-2011
+// http://www.resedit.net
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include "resource.h"
+
+#ifdef HAVE_CONFIG_H
+  #include "../../../config.h"
+#endif
+
+
+
+//
+// Dialog resources
+//
+//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_DIALOG1 DIALOGEX 0, 0, 379, 124
+STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
+CAPTION "NPTest v@PACKAGE_VERSION@"
+FONT 8, "Ms Shell Dlg", 400, 0, 1
+{
+    DEFPUSHBUTTON   "Quit", IDQUIT, 262, 102, 50, 14
+    DEFPUSHBUTTON   "Start", IDSTART, 7, 102, 50, 14
+    EDITTEXT        IDC_PITCH, 32, 32, 51, 14, ES_AUTOHSCROLL
+    LTEXT           "Pitch", IDC_STATIC, 11, 34, 20, 8, SS_LEFT
+    LTEXT           "Yaw", IDC_STATIC, 11, 59, 20, 8, SS_LEFT
+    EDITTEXT        IDC_YAW, 32, 57, 51, 14, ES_AUTOHSCROLL
+    LTEXT           "Roll", IDC_STATIC, 11, 84, 20, 8, SS_LEFT
+    EDITTEXT        IDC_ROLL, 32, 82, 51, 14, ES_AUTOHSCROLL
+    LTEXT           "X", IDC_STATIC, 101, 35, 6, 8, SS_LEFT
+    EDITTEXT        IDC_X1, 112, 32, 51, 14, ES_AUTOHSCROLL
+    LTEXT           "Y", IDC_STATIC, 101, 60, 6, 8, SS_LEFT
+    EDITTEXT        IDC_Y1, 112, 57, 51, 14, ES_AUTOHSCROLL
+    LTEXT           "Z", IDC_STATIC, 101, 85, 6, 8, SS_LEFT
+    EDITTEXT        IDC_Z1, 112, 82, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_X2, 172, 32, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_Y2, 172, 57, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_Z2, 172, 82, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_X3, 232, 32, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_Y3, 232, 57, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_Z3, 232, 82, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_S, 292, 32, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_F, 292, 57, 51, 14, ES_AUTOHSCROLL
+    EDITTEXT        IDC_APPID, 32, 12, 51, 12, ES_AUTOHSCROLL
+    LTEXT           "ID", IDC_STATIC, 17, 14, 8, 8, SS_LEFT
+}
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/resource.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/resource.h
new file mode 100644
index 00000000..328d9cb7
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/resource.h
@@ -0,0 +1,23 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDD_DIALOG1                             100
+#define IDQUIT                                  1002
+#define IDSTART                                 1003
+#define IDC_APPID                               1016
+#define IDC_PITCH                               1017
+#define IDC_YAW                                 1018
+#define IDC_ROLL                                1019
+#define IDC_X1                                  1020
+#define IDC_X2                                  1021
+#define IDC_X3                                  1022
+#define IDC_Y1                                  1023
+#define IDC_Y2                                  1024
+#define IDC_Y3                                  1025
+#define IDC_Z1                                  1026
+#define IDC_Z2                                  1027
+#define IDC_Z3                                  1028
+#define IDC_S                                   1029
+#define IDC_F                                   1030
+
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.c b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.c
new file mode 120000
index 00000000..663c21a9
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.c
@@ -0,0 +1 @@
+../client/rest.c
\ No newline at end of file
diff --git a/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.h b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.h
new file mode 120000
index 00000000..6dca182a
--- /dev/null
+++ b/facetracknoir/clientfiles/important-source-code-really-important-really-really/tester/rest.h
@@ -0,0 +1 @@
+../client/rest.h
\ No newline at end of file
diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp
index abf03a5e..886e40fa 100644
--- a/facetracknoir/curve-config.cpp
+++ b/facetracknoir/curve-config.cpp
@@ -1,12 +1,13 @@
-#include "facetracknoir/facetracknoir.h"
-#include "facetracknoir/curve-config.h"
-CurveConfigurationDialog::CurveConfigurationDialog(FaceTrackNoIR *ftnoir, QWidget *parent) :
-    QWidget( parent, Qt::Dialog ), mainApp(ftnoir)
+#include "./facetracknoir.h"
+#include "./curve-config.h"
+#include "./main-settings.hpp"
+CurveConfigurationDialog::CurveConfigurationDialog(Mappings& m, main_settings& s, QWidget *parent) : QWidget(parent, Qt::Dialog),
+    m(m)
 {
     ui.setupUi( this );
 
     // rest of mapping settings taken care of by options::value<t>
-    mainApp->load_mappings();
+    m.load_mappings();
 
     {
         struct {
@@ -34,8 +35,8 @@ CurveConfigurationDialog::CurveConfigurationDialog(FaceTrackNoIR *ftnoir, QWidge
         for (int i = 0; qfcs[i].qfc; i++)
         {
             const bool altp = qfcs[i].altp;
-            THeadPoseDOF& axis = mainApp->axis(qfcs[i].axis);
-            FunctionConfig* conf = altp ? &axis.curveAlt : &axis.curve;
+            Mapping& axis = m(qfcs[i].axis);
+            Map* conf = altp ? &axis.curveAlt : &axis.curve;
             const auto& name = qfcs[i].altp ? axis.name2 : axis.name1;
 
             qfcs[i].qfc->setConfig(conf, name);
@@ -49,36 +50,36 @@ CurveConfigurationDialog::CurveConfigurationDialog(FaceTrackNoIR *ftnoir, QWidge
     connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
     connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
 
-    tie_setting(mainApp->s.a_x.altp, ui.tx_altp);
-    tie_setting(mainApp->s.a_y.altp, ui.ty_altp);
-    tie_setting(mainApp->s.a_z.altp, ui.tz_altp);
-    tie_setting(mainApp->s.a_yaw.altp, ui.rx_altp);
-    tie_setting(mainApp->s.a_pitch.altp, ui.ry_altp);
-    tie_setting(mainApp->s.a_roll.altp, ui.rz_altp);
+    tie_setting(s.a_x.altp, ui.tx_altp);
+    tie_setting(s.a_y.altp, ui.ty_altp);
+    tie_setting(s.a_z.altp, ui.tz_altp);
+    tie_setting(s.a_yaw.altp, ui.rx_altp);
+    tie_setting(s.a_pitch.altp, ui.ry_altp);
+    tie_setting(s.a_roll.altp, ui.rz_altp);
 
-    tie_setting(mainApp->s.tcomp_p, ui.tcomp_enable);
-    tie_setting(mainApp->s.tcomp_tz, ui.tcomp_rz);
+    tie_setting(s.tcomp_p, ui.tcomp_enable);
+    tie_setting(s.tcomp_tz, ui.tcomp_rz);
 
-    tie_setting(mainApp->s.a_x.zero, ui.pos_tx);
-    tie_setting(mainApp->s.a_y.zero, ui.pos_ty);
-    tie_setting(mainApp->s.a_z.zero, ui.pos_tz);
-    tie_setting(mainApp->s.a_yaw.zero, ui.pos_rx);
-    tie_setting(mainApp->s.a_pitch.zero, ui.pos_ry);
-    tie_setting(mainApp->s.a_roll.zero, ui.pos_rz);
+    tie_setting(s.a_x.zero, ui.pos_tx);
+    tie_setting(s.a_y.zero, ui.pos_ty);
+    tie_setting(s.a_z.zero, ui.pos_tz);
+    tie_setting(s.a_yaw.zero, ui.pos_rx);
+    tie_setting(s.a_pitch.zero, ui.pos_ry);
+    tie_setting(s.a_roll.zero, ui.pos_rz);
 
-    tie_setting(mainApp->s.a_yaw.invert, ui.invert_yaw);
-    tie_setting(mainApp->s.a_pitch.invert, ui.invert_pitch);
-    tie_setting(mainApp->s.a_roll.invert, ui.invert_roll);
-    tie_setting(mainApp->s.a_x.invert, ui.invert_x);
-    tie_setting(mainApp->s.a_y.invert, ui.invert_y);
-    tie_setting(mainApp->s.a_z.invert, ui.invert_z);
+    tie_setting(s.a_yaw.invert, ui.invert_yaw);
+    tie_setting(s.a_pitch.invert, ui.invert_pitch);
+    tie_setting(s.a_roll.invert, ui.invert_roll);
+    tie_setting(s.a_x.invert, ui.invert_x);
+    tie_setting(s.a_y.invert, ui.invert_y);
+    tie_setting(s.a_z.invert, ui.invert_z);
 
-    tie_setting(mainApp->s.a_yaw.src, ui.src_yaw);
-    tie_setting(mainApp->s.a_pitch.src, ui.src_pitch);
-    tie_setting(mainApp->s.a_roll.src, ui.src_roll);
-    tie_setting(mainApp->s.a_x.src, ui.src_x);
-    tie_setting(mainApp->s.a_y.src, ui.src_y);
-    tie_setting(mainApp->s.a_z.src, ui.src_z);
+    tie_setting(s.a_yaw.src, ui.src_yaw);
+    tie_setting(s.a_pitch.src, ui.src_pitch);
+    tie_setting(s.a_roll.src, ui.src_roll);
+    tie_setting(s.a_x.src, ui.src_x);
+    tie_setting(s.a_y.src, ui.src_y);
+    tie_setting(s.a_z.src, ui.src_z);
 }
 
 void CurveConfigurationDialog::doOK() {
@@ -87,10 +88,10 @@ void CurveConfigurationDialog::doOK() {
 }
 
 void CurveConfigurationDialog::doCancel() {
-    mainApp->load_mappings();
+    m.load_mappings();
     this->close();
 }
 
 void CurveConfigurationDialog::save() {
-    mainApp->save_mappings();
+    m.save_mappings();
 }
diff --git a/facetracknoir/curve-config.h b/facetracknoir/curve-config.h
index 49aba7bd..67a588e2 100644
--- a/facetracknoir/curve-config.h
+++ b/facetracknoir/curve-config.h
@@ -1,19 +1,17 @@
 #pragma once
 #include <QWidget>
-#include <QPalette>
+#include "./mappings.hpp"
 #include "ui_ftnoir_curves.h"
 
-class FaceTrackNoIR;
-
 class CurveConfigurationDialog: public QWidget
 {
     Q_OBJECT
 public:
-    CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent );
+    CurveConfigurationDialog(Mappings &m, main_settings &s, QWidget *parent );
 private:
     Ui::UICCurveConfigurationDialog ui;
+    Mappings& m;
     void save();
-    FaceTrackNoIR *mainApp;
 private slots:
     void doOK();
     void doCancel();
diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp
index 868b6dbf..af76f09b 100644
--- a/facetracknoir/facetracknoir.cpp
+++ b/facetracknoir/facetracknoir.cpp
@@ -75,8 +75,8 @@ static void fill_combobox(const QString& filter, QList<DynamicLibrary*>& list, Q
     }
 }
 
-FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) :
-    QMainWindow(parent),
+FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) : QMainWindow(parent),
+    tracker(nullptr),
 #if defined(_WIN32)
     keybindingWorker(NULL),
 #else
@@ -87,34 +87,21 @@ FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) :
     s(b),
     pose(std::vector<axis_opts*>{&s.a_x, &s.a_y, &s.a_z, &s.a_yaw, &s.a_pitch, &s.a_roll}),
     timUpdateHeadPose(this),
-    pTrackerDialog(NULL),
-    pProtocolDialog(NULL),
-    pFilterDialog(NULL),
+    pTrackerDialog(nullptr),
+    pProtocolDialog(nullptr),
+    pFilterDialog(nullptr),
+    shortcuts_widget(nullptr),
+    mapping_widget(new CurveConfigurationDialog(pose, s, this)),
     kbd_quit(QKeySequence("Ctrl+Q"), this),
     looping(0),
     video_frame_layout(new QVBoxLayout()),
     no_feed_pixmap(":/uielements/no-feed.png")
-{	
+{
     ui.setupUi(this);
     setFixedSize(size());
     ui.video_frame_label->setPixmap(no_feed_pixmap);
     updateButtonState(false, false);
 
-	_keyboard_shortcuts = 0;
-	_curve_config = 0;
-
-	tracker = 0;
-
-    CurveConfigurationDialog* ccd;
-
-    if (!_curve_config)
-    {
-        ccd = new CurveConfigurationDialog( this, this );
-        _curve_config = ccd;
-    } else {
-        ccd = dynamic_cast<CurveConfigurationDialog*>(_curve_config);
-    }
-
     QDir::setCurrent(QCoreApplication::applicationDirPath());
 
     fill_profile_cbx();
@@ -157,7 +144,7 @@ FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) :
 
 FaceTrackNoIR::~FaceTrackNoIR() {
 
-	stopTracker();
+    stopTracker();
     save();
     if (Libraries)
         delete Libraries;
@@ -171,38 +158,26 @@ QFrame* FaceTrackNoIR::get_video_widget() {
 void FaceTrackNoIR::open() {
      QFileDialog dialog(this);
      dialog.setFileMode(QFileDialog::ExistingFile);
-     
-	 QString fileName = dialog.getOpenFileName(
-								this,
+
+     QString fileName = dialog.getOpenFileName(
+                                this,
                                  tr("Open the settings file"),
-								 QCoreApplication::applicationDirPath() + "/settings/",
+                                 QCoreApplication::applicationDirPath() + "/settings/",
                                  tr("Settings file (*.ini);;All Files (*)"),
                                                NULL);
 
-	if (! fileName.isEmpty() ) {
+    if (! fileName.isEmpty() ) {
         {
             QSettings settings("opentrack");
             settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath());
         }
         fill_profile_cbx();
-		loadSettings();
+        loadSettings();
     }
 }
 
 void FaceTrackNoIR::save_mappings() {
-    QSettings settings("opentrack");
-
-    QString currentFile =
-            settings.value("SettingsFile",
-                           QCoreApplication::applicationDirPath() + "/settings/default.ini")
-            .toString();
-    QSettings iniFile( currentFile, QSettings::IniFormat );
-    
-    for (int i = 0; i < 6; i++)
-    {
-        axis(i).curve.saveSettings(iniFile, axis(i).name1);
-        axis(i).curveAlt.saveSettings(iniFile, axis(i).name2);
-    }
+    pose.save_mappings();
 }
 
 #if defined(__unix) || defined(__linux) || defined(__APPLE__)
@@ -212,7 +187,7 @@ void FaceTrackNoIR::save_mappings() {
 void FaceTrackNoIR::save() {
     b->save();
     save_mappings();
-    
+
 #if defined(__unix) || defined(__linux)
     QSettings settings("opentrack");
     const QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
@@ -229,27 +204,27 @@ void FaceTrackNoIR::save() {
 void FaceTrackNoIR::saveAs()
 {
     looping++;
-	QSettings settings("opentrack");
-	QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+    QSettings settings("opentrack");
+    QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
 
-	QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"),
-													oldFile,
+    QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"),
+                                                    oldFile,
                                                     tr("Settings file (*.ini);;All Files (*)"));
-	if (!fileName.isEmpty()) {
+    if (!fileName.isEmpty()) {
 
-		QFileInfo newFileInfo ( fileName );
-		if ((newFileInfo.exists()) && (oldFile != fileName)) {
-			QFile newFileFile ( fileName );
-			newFileFile.remove();
-		}
+        QFileInfo newFileInfo ( fileName );
+        if ((newFileInfo.exists()) && (oldFile != fileName)) {
+            QFile newFileFile ( fileName );
+            newFileFile.remove();
+        }
 
-		QFileInfo oldFileInfo ( oldFile );
-		if (oldFileInfo.exists()) {
-			QFile oldFileFile ( oldFile );
-			oldFileFile.copy( fileName );
-		}
+        QFileInfo oldFileInfo ( oldFile );
+        if (oldFileInfo.exists()) {
+            QFile oldFileFile ( oldFile );
+            oldFileFile.copy( fileName );
+        }
 
-		settings.setValue ("SettingsFile", fileName);
+        settings.setValue ("SettingsFile", fileName);
         save();
     }
 
@@ -258,15 +233,7 @@ void FaceTrackNoIR::saveAs()
 }
 
 void FaceTrackNoIR::load_mappings() {
-    QSettings settings("opentrack");
-    QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
-    QSettings iniFile( currentFile, QSettings::IniFormat );
-
-    for (int i = 0; i < 6; i++)
-    {
-        axis(i).curve.loadSettings(iniFile, axis(i).name1);
-        axis(i).curveAlt.loadSettings(iniFile, axis(i).name2);
-    }
+    pose.load_mappings();
 }
 
 void FaceTrackNoIR::loadSettings() {
@@ -303,7 +270,7 @@ void FaceTrackNoIR::startTracker( ) {
         stopTracker();
         return;
     }
-    
+
 #if defined(_WIN32)
     keybindingWorker = new KeybindingWorker(*this, keyCenter, keyToggle);
     keybindingWorker->start();
@@ -313,15 +280,15 @@ void FaceTrackNoIR::startTracker( ) {
         delete tracker;
     }
 
-    tracker = new Tracker ( this, s );
+    tracker = new Tracker(s, pose);
 
     if (pTrackerDialog && Libraries->pTracker) {
         pTrackerDialog->registerTracker( Libraries->pTracker );
-	}
-    
+    }
+
     if (pFilterDialog && Libraries->pFilter)
         pFilterDialog->registerFilter(Libraries->pFilter);
-    
+
     tracker->start();
 
     ui.video_frame->show();
@@ -345,7 +312,7 @@ void FaceTrackNoIR::stopTracker( ) {
         keybindingWorker = NULL;
     }
 #endif
-	timUpdateHeadPose.stop();
+    timUpdateHeadPose.stop();
     ui.pose_display->rotateBy(0, 0, 0);
 
     if (pTrackerDialog) {
@@ -366,44 +333,41 @@ void FaceTrackNoIR::stopTracker( ) {
     }
 
     if ( tracker ) {
-		delete tracker;
-		tracker = 0;
+        delete tracker;
+        tracker = 0;
         if (Libraries) {
             delete Libraries;
             Libraries = NULL;
         }
-	}
+    }
     updateButtonState(false, false);
 }
 
-void FaceTrackNoIR::showHeadPose() {
-    double newdata[6];
-
-    tracker->getHeadPose(newdata);
-    ui.lcdNumX->display(newdata[TX]);
-    ui.lcdNumY->display(newdata[TY]);
-    ui.lcdNumZ->display(newdata[TZ]);
-
+void FaceTrackNoIR::showHeadPose()
+{
+    double mapped[6], raw[6];
 
-    ui.lcdNumRotX->display(newdata[Yaw]);
-    ui.lcdNumRotY->display(newdata[Pitch]);
-    ui.lcdNumRotZ->display(newdata[Roll]);
+    tracker->get_raw_and_mapped_poses(mapped, raw);
 
-    tracker->getOutputHeadPose(newdata);
+    ui.pose_display->rotateBy(mapped[Yaw], mapped[Roll], mapped[Pitch]);
 
-    ui.pose_display->rotateBy(newdata[Yaw], newdata[Roll], newdata[Pitch]);
+    if (mapping_widget)
+        mapping_widget->update();
 
-    ui.lcdNumOutputPosX->display(newdata[TX]);
-    ui.lcdNumOutputPosY->display(newdata[TY]);
-    ui.lcdNumOutputPosZ->display(newdata[TZ]);
+    ui.lcdNumX->display(raw[TX]);
+    ui.lcdNumY->display(raw[TY]);
+    ui.lcdNumZ->display(raw[TZ]);
+    ui.lcdNumRotX->display(raw[Yaw]);
+    ui.lcdNumRotY->display(raw[Pitch]);
+    ui.lcdNumRotZ->display(raw[Roll]);
 
-    ui.lcdNumOutputRotX->display(newdata[Yaw]);
-    ui.lcdNumOutputRotY->display(newdata[Pitch]);
-    ui.lcdNumOutputRotZ->display(newdata[Roll]);
+    ui.lcdNumOutputPosX->display(mapped[TX]);
+    ui.lcdNumOutputPosY->display(mapped[TY]);
+    ui.lcdNumOutputPosZ->display(mapped[TZ]);
+    ui.lcdNumOutputRotX->display(mapped[Yaw]);
+    ui.lcdNumOutputRotY->display(mapped[Pitch]);
+    ui.lcdNumOutputRotZ->display(mapped[Roll]);
 
-    if (_curve_config) {
-        _curve_config->update();
-    }
     if (Libraries->pProtocol)
     {
         const QString name = Libraries->pProtocol->getGameName();
@@ -411,11 +375,12 @@ void FaceTrackNoIR::showHeadPose() {
     }
 }
 
-void FaceTrackNoIR::showTrackerSettings() {
-	if (pTrackerDialog) {
-		delete pTrackerDialog;
-		pTrackerDialog = NULL;
-	}
+void FaceTrackNoIR::showTrackerSettings()
+{
+    if (pTrackerDialog) {
+        delete pTrackerDialog;
+        pTrackerDialog = NULL;
+    }
 
     DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
 
@@ -470,24 +435,24 @@ void FaceTrackNoIR::showFilterControls() {
 }
 void FaceTrackNoIR::showKeyboardShortcuts() {
 
-	if (!_keyboard_shortcuts)
+    if (!shortcuts_widget)
     {
-        _keyboard_shortcuts = new KeyboardShortcutDialog( this, this );
+        shortcuts_widget = new KeyboardShortcutDialog( this, this );
     }
 
-    _keyboard_shortcuts->show();
-    _keyboard_shortcuts->raise();
+    shortcuts_widget->show();
+    shortcuts_widget->raise();
 }
-void FaceTrackNoIR::showCurveConfiguration() {    
-    if (!_curve_config)
-        _curve_config = new CurveConfigurationDialog( this, this );
-    
-    _curve_config->show();
-    _curve_config->raise();
+void FaceTrackNoIR::showCurveConfiguration() {
+    if (!mapping_widget)
+        mapping_widget = new CurveConfigurationDialog(pose, s, this);
+
+    mapping_widget->show();
+    mapping_widget->raise();
 }
 
 void FaceTrackNoIR::exit() {
-	QCoreApplication::exit(0);
+    QCoreApplication::exit(0);
 }
 
 extern "C" volatile const char* opentrack_version;
@@ -515,11 +480,11 @@ void FaceTrackNoIR::fill_profile_cbx()
 
 void FaceTrackNoIR::profileSelected(int index)
 {
-	QSettings settings("opentrack");
-	QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+    QSettings settings("opentrack");
+    QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
     QFileInfo pathInfo ( currentFile );
     settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + ui.iconcomboProfile->itemText(index));
-	loadSettings();
+    loadSettings();
 }
 
 #if !defined(_WIN32)
@@ -542,8 +507,8 @@ void FaceTrackNoIR::bind_keyboard_shortcut(QxtGlobalShortcut& key, key_opts& k)
             key.setShortcut(QKeySequence::fromString(seq, QKeySequence::PortableText));
             key.setEnabled();
         } else {
-	    key.setDisabled();
-	}
+        key.setDisabled();
+    }
     }
 }
 #else
@@ -590,20 +555,18 @@ void FaceTrackNoIR::bindKeyboardShortcuts()
 
 void FaceTrackNoIR::shortcutRecentered()
 {
+    qDebug() << "Center";
     if (s.dingp)
         QApplication::beep();
-
-    qDebug() << "Center";
     if (tracker)
-        tracker->do_center = true;
+        tracker->center();
 }
 
 void FaceTrackNoIR::shortcutToggled()
 {
+    qDebug() << "Toggle";
     if (s.dingp)
         QApplication::beep();
-
-    qDebug() << "Toggle";
     if (tracker)
-        tracker->enabled = !tracker->enabled;
+        tracker->toggle_enabled();
 }
diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h
index c722ad5c..09f96147 100644
--- a/facetracknoir/facetracknoir.h
+++ b/facetracknoir/facetracknoir.h
@@ -44,31 +44,29 @@
 
 #include "ui_facetracknoir.h"
 
-#include "facetracknoir/options.h"
-using namespace options;
-
-#include "facetracknoir/main-settings.hpp"
-
-#include "facetracknoir/plugin-support.h"
-#include "tracker.h"
-#include "facetracknoir/shortcuts.h"
+#include "./options.h"
+#include "./main-settings.hpp"
+#include "./plugin-support.h"
+#include "./tracker.h"
+#include "./shortcuts.h"
+#include "./curve-config.h"
 
-class Tracker;				// pre-define class to avoid circular includes
-class FaceTrackNoIR;
-
-class KeybindingWorker;
+using namespace options;
 
 class FaceTrackNoIR : public QMainWindow, IDynamicLibraryProvider
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
     FaceTrackNoIR(QWidget *parent = 0);
-	~FaceTrackNoIR();
+    ~FaceTrackNoIR();
 
     QFrame *get_video_widget();
     Tracker *tracker;
     void bindKeyboardShortcuts();
+
+    // XXX this shit stinks -sh 20141004
+    // TODO move to separate class representing running tracker state
     DynamicLibrary* current_tracker1() override {
         return dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
     }
@@ -78,15 +76,12 @@ public:
     DynamicLibrary* current_filter() override {
         return dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
     }
-    THeadPoseDOF& axis(int idx) {
-        return pose.axes[idx];
-    }
 
 #if defined(_WIN32)
     Key keyCenter;
     Key keyToggle;
     KeybindingWorker* keybindingWorker;
-#else 
+#else
     QxtGlobalShortcut keyCenter;
     QxtGlobalShortcut keyToggle;
 #endif
@@ -95,22 +90,20 @@ public:
 public slots:
     void shortcutRecentered();
     void shortcutToggled();
-
 private:
-    HeadPoseData pose;
+    Mappings pose;
     Ui::OpentrackUI ui;
-	QTimer timUpdateHeadPose;
+    QTimer timUpdateHeadPose;
 
     ITrackerDialog* pTrackerDialog;
     IProtocolDialog* pProtocolDialog;
     IFilterDialog* pFilterDialog;
 
-	QWidget *_keyboard_shortcuts;
-	QWidget *_curve_config;
+    QWidget *shortcuts_widget;
+    CurveConfigurationDialog* mapping_widget;
 
-	void createIconGroupBox();
-
-	void loadSettings();
+    void createIconGroupBox();
+    void loadSettings();
     void updateButtonState(bool running, bool inertialp);
 
     QList<DynamicLibrary*> dlopen_filters;
@@ -118,33 +111,33 @@ private:
     QList<DynamicLibrary*> dlopen_protocols;
     QShortcut kbd_quit;
     int looping;
-    
+
     QLayout* video_frame_layout;
     QPixmap no_feed_pixmap;
 #ifndef _WIN32
     void bind_keyboard_shortcut(QxtGlobalShortcut&, key_opts& k);
 #endif
     void fill_profile_cbx();
-    
+
 private slots:
     void open();
     void save();
     void saveAs();
     void exit();
     void profileSelected(int index);
-    
+
     void showTrackerSettings();
-    
+
     void showServerControls();
     void showFilterControls();
     void showKeyboardShortcuts();
     void showCurveConfiguration();
-    
+
     void showHeadPose();
-    
+
     void startTracker();
     void stopTracker();
-    
+
 public:
     void save_mappings();
     void load_mappings();
diff --git a/facetracknoir/mappings.hpp b/facetracknoir/mappings.hpp
new file mode 100644
index 00000000..4dae7a90
--- /dev/null
+++ b/facetracknoir/mappings.hpp
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <QSettings>
+#include "options.h"
+using namespace options;
+#include "../qfunctionconfigurator/functionconfig.h"
+#include "main-settings.hpp"
+
+class Mapping {
+public:
+    Mapping(QString primary,
+            QString secondary,
+            int maxInput1,
+            int maxOutput1,
+            int maxInput2,
+            int maxOutput2,
+            axis_opts& opts) :
+        curve(maxInput1, maxOutput1),
+        curveAlt(maxInput2, maxOutput2),
+        opts(opts),
+        name1(primary),
+        name2(secondary)
+    {
+        // XXX TODO move all this qsettings boilerplate into a single header -sh 20141004
+        QSettings settings("opentrack");
+        QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+        QSettings iniFile(currentFile, QSettings::IniFormat);
+        curve.loadSettings(iniFile, primary);
+        curveAlt.loadSettings(iniFile, secondary);
+    }
+    Map curve;
+    Map curveAlt;
+    axis_opts& opts;
+    QString name1, name2;
+};
+
+class Mappings {
+private:
+    Mapping axes[6];
+public:
+    Mappings(std::vector<axis_opts*> opts) :
+        axes {
+            Mapping("tx","tx_alt", 100, 100, 100, 100, *opts[TX]),
+            Mapping("ty","ty_alt", 100, 100, 100, 100, *opts[TY]),
+            Mapping("tz","tz_alt", 100, 100, 100, 100, *opts[TZ]),
+            Mapping("rx", "rx_alt", 180, 180, 180, 180, *opts[Yaw]),
+            Mapping("ry", "ry_alt", 90, 90, 90, 90, *opts[Pitch]),
+            Mapping("rz", "rz_alt", 180, 180, 180, 180, *opts[Roll])
+        }
+    {}
+
+    inline Mapping& operator()(int i) { return axes[i]; }
+    inline const Mapping& operator()(int i) const { return axes[i]; }
+
+    void load_mappings()
+    {
+        QSettings settings("opentrack");
+        QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+        QSettings iniFile( currentFile, QSettings::IniFormat );
+
+        for (int i = 0; i < 6; i++)
+        {
+            axes[i].curve.loadSettings(iniFile, axes[i].name1);
+            axes[i].curveAlt.loadSettings(iniFile, axes[i].name2);
+        }
+    }
+    void save_mappings()
+    {
+        QSettings settings("opentrack");
+        QString currentFile = settings.value("SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini").toString();
+        QSettings iniFile(currentFile, QSettings::IniFormat);
+
+        for (int i = 0; i < 6; i++)
+        {
+            axes[i].curve.saveSettings(iniFile, axes[i].name1);
+            axes[i].curveAlt.saveSettings(iniFile, axes[i].name2);
+        }
+    }
+};
diff --git a/facetracknoir/plugin-qt-api.hpp b/facetracknoir/plugin-qt-api.hpp
index a8dd153b..0e2e3c32 100644
--- a/facetracknoir/plugin-qt-api.hpp
+++ b/facetracknoir/plugin-qt-api.hpp
@@ -14,11 +14,15 @@ struct Metadata
     virtual void getIcon(QIcon *icon) = 0;
 };
 
+// XXX TODO get rid of QString/QFrame to fix ABI woes
+// will lead plugins from different C++ runtimes working -sh 20141004
+
+// XXX TODO make virtual public the mess -sh 20141004
+
 struct IFilter
 {
     virtual ~IFilter() = 0;
     virtual void FilterHeadPoseData(const double *target_camera_position, double *new_camera_position) = 0;
-    virtual void reset() = 0;
 };
 inline IFilter::~IFilter() {}
 
@@ -62,4 +66,4 @@ struct ITrackerDialog
     virtual void registerTracker(ITracker *tracker) = 0;
     virtual void unRegisterTracker() = 0;
 };
-inline ITrackerDialog::~ITrackerDialog() {}
\ No newline at end of file
+inline ITrackerDialog::~ITrackerDialog() {}
diff --git a/facetracknoir/plugin-support.h b/facetracknoir/plugin-support.h
index 3924fc09..c3914cfb 100644
--- a/facetracknoir/plugin-support.h
+++ b/facetracknoir/plugin-support.h
@@ -45,7 +45,7 @@ private:
 };
 
 
-// merely to break a circular header dependency -sh
+// TODO it can die if running tracker state separated into class -sh 20141004
 class IDynamicLibraryProvider {
 public:
     virtual DynamicLibrary* current_tracker1() = 0;
diff --git a/facetracknoir/qcopyable-mutex.hpp b/facetracknoir/qcopyable-mutex.hpp
new file mode 100644
index 00000000..f7f36f93
--- /dev/null
+++ b/facetracknoir/qcopyable-mutex.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <QMutex>
+
+class MyMutex {
+private:
+    QMutex inner;
+
+public:
+    QMutex* operator->() { return &inner; }
+    QMutex* operator->() const { return &const_cast<MyMutex*>(this)->inner; }
+
+    MyMutex operator=(const MyMutex& datum)
+    {
+        auto mode =
+                datum->isRecursive()
+                ? QMutex::Recursive
+                : QMutex::NonRecursive;
+
+        return MyMutex(mode);
+    }
+
+    MyMutex(const MyMutex& datum)
+    {
+        *this = datum;
+    }
+
+    MyMutex(QMutex::RecursionMode mode = QMutex::NonRecursive) :
+        inner(mode)
+    {
+    }
+
+    QMutex* operator&()
+    {
+        return &inner;
+    }
+};
diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h
index 5ff5ce61..b3bb891e 100644
--- a/facetracknoir/rotation.h
+++ b/facetracknoir/rotation.h
@@ -8,18 +8,17 @@
 #pragma once
 #include <cmath>
 
-class RotationType {
+class Quat {
 
 public:
-    RotationType() : a(1.0),b(0.0),c(0.0),d(0.0) {}
-    RotationType(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); }
-    RotationType(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
+    Quat() : a(1.0),b(0.0),c(0.0),d(0.0) {}
+    Quat(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); }
+    Quat(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
 
-    RotationType inv(){
-        return RotationType(a,-b,-c, -d);
+    Quat inv(){
+        return Quat(a,-b,-c, -d);
     }
 
-
     // conversions
     // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
     void fromEuler(double yaw, double pitch, double roll)
@@ -45,10 +44,10 @@ public:
         yaw =  atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d));
     }
 
-    const RotationType operator*(const RotationType& B) const
+    const Quat operator*(const Quat& B) const
     {
-        const RotationType& A = *this;
-        return RotationType(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d,	// quaternion multiplication
+        const Quat& A = *this;
+        return Quat(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d,	// quaternion multiplication
                         A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c,
                         A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b,
                         A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a);
diff --git a/facetracknoir/tracker.cpp b/facetracknoir/tracker.cpp
index 17f1af5f..0c2d289f 100644
--- a/facetracknoir/tracker.cpp
+++ b/facetracknoir/tracker.cpp
@@ -22,12 +22,12 @@
 #   include <windows.h>
 #endif
 
-Tracker::Tracker(FaceTrackNoIR *parent , main_settings& s) :
-    mainApp(parent),
+Tracker::Tracker(main_settings& s, Mappings &m) :
     s(s),
-    should_quit(false),
-    do_center(false),
-    enabled(true)
+    m(m),
+    centerp(false),
+    enabledp(true),
+    should_quit(false)
 {
 }
 
@@ -37,7 +37,7 @@ Tracker::~Tracker()
     wait();
 }
 
-static void get_curve(double pos, double& out, THeadPoseDOF& axis) {
+void Tracker::get_curve(double pos, double& out, Mapping& axis) {
     bool altp = (pos < 0) && axis.opts.altp;
     axis.curve.setTrackingActive( !altp );
     axis.curveAlt.setTrackingActive( altp );
@@ -83,7 +83,7 @@ static void t_compensate(double* input, double* output, bool rz)
 }
 
 void Tracker::run() {
-    T6DOF offset_camera;
+    T6DOF pose_offset, unstopped_pose;
 
     double newpose[6] = {0};
     int sleep_ms = 15;
@@ -113,52 +113,42 @@ void Tracker::run() {
 
             for (int i = 0; i < 6; i++)
             {
-                raw_6dof.axes[i] = newpose[i];
-
-                auto& axis = mainApp->axis(i);
-
+                auto& axis = m(i);
                 int k = axis.opts.src;
                 if (k < 0 || k >= 6)
                     continue;
-
-                axis.headPos = newpose[k];
+                // not really raw, after axis remap -sh
+                raw_6dof(i) = newpose[k];
             }
 
-            if (do_center)  {
-                for (int i = 0; i < 6; i++)
-                    offset_camera.axes[i] = mainApp->axis(i).headPos;
-
-                do_center = false;
-
-                if (Libraries->pFilter)
-                    Libraries->pFilter->reset();
+            if (centerp)  {
+                centerp = false;
+                pose_offset = raw_6dof;
             }
 
-            T6DOF target_camera, target_camera2, new_camera;
+            {
+                if (enabledp)
+                    unstopped_pose = raw_6dof;
 
-            if (!enabled)
-                target_camera = raw_6dof;
-            else
-                for (int i = 0; i < 6; i++)
-                    target_camera.axes[i] = mainApp->axis(i).headPos;
+                {
 
-            target_camera2 = target_camera - offset_camera;
+                    if (Libraries->pFilter)
+                        Libraries->pFilter->FilterHeadPoseData(unstopped_pose, output_pose);
+                    else
+                        output_pose = unstopped_pose;
 
-            if (Libraries->pFilter) {
-                Libraries->pFilter->FilterHeadPoseData(target_camera2.axes, new_camera.axes);
-            } else {
-                new_camera = target_camera2;
-            }
+                    output_pose = output_pose - pose_offset;
+                }
 
-            for (int i = 0; i < 6; i++) {
-                get_curve(new_camera.axes[i], output_camera.axes[i], mainApp->axis(i));
+                for (int i = 0; i < 6; i++)
+                    get_curve(output_pose(i), output_pose(i), m(i));
             }
 
-            if (mainApp->s.tcomp_p)
-                t_compensate(output_camera.axes, output_camera.axes, mainApp->s.tcomp_tz);
+            if (s.tcomp_p)
+                t_compensate(output_pose, output_pose, s.tcomp_tz);
 
             if (Libraries->pProtocol) {
-                Libraries->pProtocol->sendHeadposeToGame(output_camera.axes);
+                Libraries->pProtocol->sendHeadposeToGame(output_pose);
             }
         }
 
@@ -172,21 +162,17 @@ void Tracker::run() {
 
     for (int i = 0; i < 6; i++)
     {
-        mainApp->axis(i).curve.setTrackingActive(false);
-        mainApp->axis(i).curveAlt.setTrackingActive(false);
+        m(i).curve.setTrackingActive(false);
+        m(i).curveAlt.setTrackingActive(false);
     }
 }
 
-void Tracker::getHeadPose( double *data ) {
-    QMutexLocker foo(&mtx);
+void Tracker::get_raw_and_mapped_poses(double* mapped, double* raw) const {
+    QMutexLocker foo(&const_cast<Tracker&>(*this).mtx);
     for (int i = 0; i < 6; i++)
     {
-        data[i] = raw_6dof.axes[i];
+        raw[i] = raw_6dof(i);
+        mapped[i] = output_pose(i);
     }
 }
 
-void Tracker::getOutputHeadPose( double *data ) {
-    QMutexLocker foo(&mtx);
-    for (int i = 0; i < 6; i++)
-        data[i] = output_camera.axes[i];
-}
diff --git a/facetracknoir/tracker.h b/facetracknoir/tracker.h
index 54350164..05ae4180 100644
--- a/facetracknoir/tracker.h
+++ b/facetracknoir/tracker.h
@@ -11,85 +11,42 @@
 #include <QDebug>
 #include <QMutex>
 #include "plugin-support.h"
+#include "mappings.hpp"
+
 #include <vector>
+#include <atomic>
 
 #include <qfunctionconfigurator/functionconfig.h>
 #include "tracker_types.h"
 #include "facetracknoir/main-settings.hpp"
 #include "facetracknoir/options.h"
 #include "facetracknoir/timer.hpp"
-using namespace options;
 
-class THeadPoseDOF {
-public:
-    THeadPoseDOF(QString primary,
-                 QString secondary,
-                 int maxInput1,
-                 int maxOutput1,
-                 int maxInput2,
-                 int maxOutput2,
-                 axis_opts* opts) :
-        headPos(0),
-        curve(maxInput1, maxOutput1),
-        curveAlt(maxInput2, maxOutput2),
-        opts(*opts),
-        name1(primary),
-        name2(secondary)
-    {
-        QSettings settings("opentrack");
-        QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
-        QSettings iniFile( currentFile, QSettings::IniFormat );
-        curve.loadSettings(iniFile, primary);
-        curveAlt.loadSettings(iniFile, secondary);
-    }
-    volatile double headPos;
-    FunctionConfig curve;
-	FunctionConfig curveAlt;
-    axis_opts& opts;
-    QString name1, name2;
-};
 
-class FaceTrackNoIR;
 
 class Tracker : protected QThread {
-	Q_OBJECT
-
+    Q_OBJECT
 private:
-    FaceTrackNoIR *mainApp;
     QMutex mtx;
     main_settings& s;
-    volatile bool should_quit;
+    // XXX can be const-cast when functionconfig const-correct -sh 20141004
+    Mappings& m;
     Timer t;
-protected:
-	void run();
+    T6DOF output_pose, raw_6dof;
+    std::atomic<bool> centerp;
+    std::atomic<bool> enabledp;
+    std::atomic<bool> should_quit;
 
+    static void get_curve(double pos, double& out, Mapping& axis);
+protected:
+    void run() override;
 public:
-    Tracker( FaceTrackNoIR *parent, main_settings& s);
+    Tracker(main_settings& s, Mappings& m);
     ~Tracker();
 
-    void getHeadPose(double *data);
-    void getOutputHeadPose(double *data);
-    volatile bool do_center;
-    volatile bool enabled;
-    
-    T6DOF output_camera, raw_6dof;
-
+    void get_raw_and_mapped_poses(double* mapped, double* raw) const;
     void start() { QThread::start(); }
+    void center() { centerp.store(true); }
+    void toggle_enabled() { enabledp.store(!enabledp.load()); }
 };
-
-class HeadPoseData {
-public:
-    THeadPoseDOF axes[6];
-    HeadPoseData(std::vector<axis_opts*> opts) :
-        axes {
-            THeadPoseDOF("tx","tx_alt", 100, 100, 100, 100, opts[TX]),
-            THeadPoseDOF("ty","ty_alt", 100, 100, 100, 100, opts[TY]),
-            THeadPoseDOF("tz","tz_alt", 100, 100, 100, 100, opts[TZ]),
-            THeadPoseDOF("rx", "rx_alt", 180, 180, 180, 180, opts[Yaw]),
-            THeadPoseDOF("ry", "ry_alt", 90, 90, 90, 90, opts[Pitch]),
-            THeadPoseDOF("rz", "rz_alt", 180, 180, 180, 180, opts[Roll])
-        }
-    {}
-};
-
 #endif
diff --git a/facetracknoir/tracker_types.cpp b/facetracknoir/tracker_types.cpp
deleted file mode 100644
index 2d7ec45a..00000000
--- a/facetracknoir/tracker_types.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "tracker_types.h"
-#include "rotation.h"
-#include "facetracknoir/plugin-api.hpp"
-
-#define PI 3.14159265358979323846264
-#define D2R PI/180.0
-#define R2D 180.0/PI
-
-T6DOF operator-(const T6DOF& A, const T6DOF& B)
-{
-    RotationType R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
-    RotationType R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
-	RotationType R_C = R_A * R_B.inv();
-
-	T6DOF C;
-    R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
-    C.axes[Yaw] *= R2D;
-    C.axes[Pitch] *= R2D;
-    C.axes[Roll] *= R2D;
-
-    C.axes[TX] = A.axes[TX] - B.axes[TX];
-    C.axes[TY] = A.axes[TY] - B.axes[TY];
-    C.axes[TZ] = A.axes[TZ] - B.axes[TZ];
-    return C;
-}
-
-T6DOF operator+(const T6DOF& A, const T6DOF& B)
-{
-    RotationType R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
-    RotationType R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
-	RotationType R_C = R_A * R_B;
-
-	T6DOF C;
-    R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
-    C.axes[Yaw] *= R2D;
-    C.axes[Pitch] *= R2D;
-    C.axes[Roll] *= R2D;
-
-    C.axes[TX] = A.axes[TX] + B.axes[TX];
-    C.axes[TY] = A.axes[TY] + B.axes[TY];
-    C.axes[TZ] = A.axes[TZ] + B.axes[TZ];
-	return C;
-}
diff --git a/facetracknoir/tracker_types.h b/facetracknoir/tracker_types.h
index 80b74759..c667498e 100644
--- a/facetracknoir/tracker_types.h
+++ b/facetracknoir/tracker_types.h
@@ -1,11 +1,66 @@
 #pragma once
 
+#include <utility>
+#include <algorithm>
+#include "rotation.h"
+#include "plugin-api.hpp"
+
 struct T6DOF {
-public:
-    double axes[6];
+private:
+    static constexpr double PI = 3.14159265358979323846264;
+    static constexpr double D2R = PI/180.0;
+    static constexpr double R2D = 180.0/PI;
 
+    double axes[6];
+public:
     T6DOF() : axes {0,0,0, 0,0,0 } {}
-};
 
-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
+    inline operator double*() { return axes; }
+    inline operator const double*() const { return axes; }
+
+    inline double& operator()(int i) { return axes[i]; }
+    inline double operator()(int i) const { return axes[i]; }
+
+    Quat quat() const
+    {
+        return Quat(axes[Yaw]*D2R, axes[Pitch]*D2R, axes[Roll]*D2R);
+    }
+
+    static T6DOF fromQuat(const Quat& q)
+    {
+        T6DOF ret;
+        q.toEuler(ret(Yaw), ret(Pitch), ret(Roll));
+        return ret;
+    }
+
+    T6DOF operator-(const T6DOF& B) const
+    {
+        const Quat q = (quat() * B.quat().inv());
+        T6DOF ret = fromQuat(q);
+        for (int i = TX; i < Yaw; i++)
+            ret(i) = B(i);
+        return ret;
+    }
+
+    T6DOF operator+(const T6DOF& B) const
+    {
+        const Quat q = (quat() * B.quat().inv());
+        T6DOF ret = fromQuat(q);
+        for (int i = TX; i < Yaw; i++)
+            ret(i) = B(i);
+        return ret;
+    }
+
+    T6DOF operator|(const T6DOF& replacement) const
+    {
+        T6DOF ret = *this;
+        for (int i = 0; i < 6; i++)
+        {
+            static constexpr double eps = 1e-5;
+            // NB replace zero-valued elements with argument's
+            if (std::abs(ret(i)) < eps)
+                ret(i) = replacement(i);
+        }
+        return ret;
+    }
+};
diff --git a/freetrackclient/freetrackclient.c b/freetrackclient/freetrackclient.c
index 5323bcae..200242b9 100644
--- a/freetrackclient/freetrackclient.c
+++ b/freetrackclient/freetrackclient.c
@@ -27,27 +27,27 @@
 #include <string.h>
 #include <windows.h>
 
-#include "ftnoir_protocol_ft/fttypes.h"
+#include "../ftnoir_protocol_ft/fttypes.h"
 
 #define FT_EXPORT(t) __declspec(dllexport) t __stdcall
 
 #if 0
-#include <stdio.h>
+#   include <stdio.h>
 static FILE *debug_stream = fopen("c:\\FreeTrackClient.log", "a");
-#define dbg_report(...) if (debug_stream) { fprintf(debug_stream, __VA_ARGS__); fflush(debug_stream); }
+#   define dbg_report(...) if (debug_stream) { fprintf(debug_stream, __VA_ARGS__); fflush(debug_stream); }
 #else
 #define dbg_report(...) ((void)0)
 #endif
 
 static HANDLE hFTMemMap = 0;
-static FTHeap *pMemData = 0;
-static HANDLE hFTMutex = 0;
+static FTHeap* ipc_heap = 0;
+static HANDLE ipc_mutex = 0;
 static const char* dllVersion = "1.0.0.0";
 static const char* dllProvider = "FreeTrack";
 
-static bool FTCreateMapping(void)
+static bool impl_create_mapping(void)
 {
-    if (pMemData != NULL)
+    if (ipc_heap != NULL)
         return true;
 
     hFTMemMap = CreateFileMappingA(INVALID_HANDLE_VALUE,
@@ -58,26 +58,27 @@ static bool FTCreateMapping(void)
                                    (LPCSTR) FREETRACK_HEAP);
 
     if (hFTMemMap == NULL)
-        return (pMemData = NULL), false;
+        return (ipc_heap = NULL), false;
 
-    pMemData = (FTHeap*) MapViewOfFile(hFTMemMap, FILE_MAP_WRITE, 0, 0, sizeof(FTHeap));
-    hFTMutex = CreateMutexA(NULL, false, FREETRACK_MUTEX);
+    ipc_heap = (FTHeap*) MapViewOfFile(hFTMemMap, FILE_MAP_WRITE, 0, 0, sizeof(FTHeap));
+    ipc_mutex = CreateMutexA(NULL, false, FREETRACK_MUTEX);
 
     return true;
 }
 
+#pragma comment (linker, "/export:FTGetData")
 FT_EXPORT(bool) FTGetData(FTData* data)
 {
-    if (FTCreateMapping() == false)
+    if (impl_create_mapping() == false)
         return false;
 
-    if (hFTMutex && WaitForSingleObject(hFTMutex, 16) == WAIT_OBJECT_0) {
-        if (pMemData) {
-            if (pMemData->data.DataID > (1 << 29))
-                pMemData->data.DataID = 0;
-            data->DataID = pMemData->data.DataID;
+    if (ipc_mutex && WaitForSingleObject(ipc_mutex, 16) == WAIT_OBJECT_0) {
+        if (ipc_heap) {
+            if (ipc_heap->data.DataID > (1 << 29))
+                ipc_heap->data.DataID = 0;
+            data->DataID = ipc_heap->data.DataID;
         }
-        ReleaseMutex(hFTMutex);
+        ReleaseMutex(ipc_mutex);
     }
     return true;
 }
@@ -87,17 +88,20 @@ FT_EXPORT(bool) FTGetData(FTData* data)
 // 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!
 */
+#pragma comment (linker, "/export:FTReportName")
 FT_EXPORT(void) FTReportName( int name )
 {
     dbg_report("FTReportName request (ID = %d).\n", name);
 }
 
+#pragma comment (linker, "/export:FTGetDllVersion")
 FT_EXPORT(const char*) FTGetDllVersion(void)
 {
     dbg_report("FTGetDllVersion request.\n");
     return dllVersion;
 }
 
+#pragma comment (linker, "/export:FTProvider")
 FT_EXPORT(const char*) FTProvider(void)
 {
     dbg_report("FTProvider request.\n");
diff --git a/ftnoir_filter_kalman/ftnoir_filter_kalman.h b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
index a47ebf4f..cbe728ab 100755
--- a/ftnoir_filter_kalman/ftnoir_filter_kalman.h
+++ b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
@@ -1,6 +1,6 @@
 #pragma once
 /* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
- * 
+ *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
@@ -10,13 +10,12 @@
 
 #include "ui_ftnoir_kalman_filtercontrols.h"
 #include "facetracknoir/plugin-api.hpp"
-#include <opencv2/opencv.hpp>
+#include <opencv2/core/core.hpp>
+#include <opencv2/video/video.hpp>
 #include <vector>
 #include <QString>
-#include <QIcon>
-#include <QWidget>
 #include <QElapsedTimer>
-#include <QObject>
+#include <QWidget>
 #include "facetracknoir/options.h"
 using namespace options;
 
@@ -24,7 +23,7 @@ class OPENTRACK_EXPORT FTNoIR_Filter : public IFilter
 {
 public:
     FTNoIR_Filter();
-    void reset() override;
+    void reset();
     void FilterHeadPoseData(const double *target_camera_position,
                             double *new_camera_position) override;
     cv::KalmanFilter kalman;
diff --git a/ftnoir_protocol_ft/fttypes.h b/ftnoir_protocol_ft/fttypes.h
index 0558f881..f41350c8 100644
--- a/ftnoir_protocol_ft/fttypes.h
+++ b/ftnoir_protocol_ft/fttypes.h
@@ -19,7 +19,11 @@
 
 #pragma once
 
-#include <inttypes.h>
+#ifndef _MSC_VER
+#   include <inttypes.h>
+#else
+typedef unsigned __int32 uint32_t;
+#endif
 
 #define FREETRACK_HEAP "FT_SharedMem"
 #define FREETRACK_MUTEX "FT_Mutext"
@@ -54,7 +58,9 @@ typedef struct __FTData {
     float Y4;
 } FTData;
 
-typedef struct __FTAlloc {
+/* we add some shit at the end for other legacy proto, sadly */
+
+typedef struct __FTHeap {
     FTData data;
     int32_t GameID;
     unsigned char table[8];
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 159f350e..f39562c1 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -17,12 +17,12 @@
 #include <cmath>
 #include <QPixmap>
 
-void FunctionConfig::setTrackingActive(bool blnActive)
+void Map::setTrackingActive(bool blnActive)
 {
     activep = blnActive;
 }
 
-FunctionConfig::FunctionConfig() :
+Map::Map() :
     _mutex(QMutex::Recursive),
     data(0),
     activep(false),
@@ -31,7 +31,7 @@ FunctionConfig::FunctionConfig() :
 {
 }
 
-float FunctionConfig::getValue(float x) {
+float Map::getValue(float x) {
     QMutexLocker foo(&_mutex);
     int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
     float ret = getValueInternal(x2);
@@ -40,13 +40,13 @@ float FunctionConfig::getValue(float x) {
 	return ret;
 }
 
-bool FunctionConfig::getLastPoint(QPointF& point ) {
+bool Map::getLastPoint(QPointF& point ) {
     QMutexLocker foo(&_mutex);
 	point = last_input_value;
 	return activep;
 }
 
-float FunctionConfig::getValueInternal(int x) {
+float Map::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
 	x = x < 0 ? -x : x;
     float ret;
@@ -75,7 +75,7 @@ static bool sortFn(const QPointF& one, const QPointF& two) {
 	return one.x() < two.x();
 }
 
-void FunctionConfig::reload() {
+void Map::reload() {
 	if (input.size())
 		qStableSort(input.begin(), input.end(), sortFn);
 
@@ -132,7 +132,7 @@ void FunctionConfig::reload() {
 	}
 }
 
-void FunctionConfig::removePoint(int i) {
+void Map::removePoint(int i) {
     QMutexLocker foo(&_mutex);
     if (i >= 0 && i < input.size())
     {
@@ -141,13 +141,13 @@ void FunctionConfig::removePoint(int i) {
     }
 }
 
-void FunctionConfig::addPoint(QPointF pt) {
+void Map::addPoint(QPointF pt) {
     QMutexLocker foo(&_mutex);
 	input.append(pt);
 	reload();
 }
 
-void FunctionConfig::movePoint(int idx, QPointF pt) {
+void Map::movePoint(int idx, QPointF pt) {
     QMutexLocker foo(&_mutex);
     if (idx >= 0 && idx < input.size())
     {
@@ -156,13 +156,13 @@ void FunctionConfig::movePoint(int idx, QPointF pt) {
     }
 }
 
-const QList<QPointF> FunctionConfig::getPoints() {
+const QList<QPointF> Map::getPoints() {
     QMutexLocker foo(&_mutex);
     // NB can't pass by reference
 	return input;
 }
 
-void FunctionConfig::loadSettings(QSettings& settings, const QString& title) {
+void Map::loadSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
     QPointF newPoint;
 
@@ -187,7 +187,7 @@ void FunctionConfig::loadSettings(QSettings& settings, const QString& title) {
 	reload();
 }
 
-void FunctionConfig::saveSettings(QSettings& settings, const QString& title) {
+void Map::saveSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
 	settings.beginGroup(QString("Curves-%1").arg(title));
 	int max = input.size();
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 66e7f3e8..ccfd1ba3 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -13,88 +13,55 @@
 #include <QString>
 #include <QSettings>
 #include <QMutex>
-#include "facetracknoir/plugin-api.hpp"
 #include <vector>
+#include "../facetracknoir/plugin-api.hpp"
+#include "../facetracknoir/qcopyable-mutex.hpp"
 
 #define MEMOIZE_PRECISION 100
 
-class MyMutex {
-private:
-    QMutex inner;
-    
-public:
-    QMutex* operator->() { return &inner; }
-    QMutex* operator->() const { return &const_cast<MyMutex*>(this)->inner; }
-    
-    MyMutex operator=(const MyMutex& datum)
-    {
-        auto mode =
-                datum->isRecursive()
-                ? QMutex::Recursive
-                : QMutex::NonRecursive;
-        
-        return MyMutex(mode);
-    }
-    
-    MyMutex(const MyMutex& datum)
-    {
-        *this = datum;
-    }
-    
-    MyMutex(QMutex::RecursionMode mode = QMutex::NonRecursive) :
-        inner(mode)
-    {
-    }
-    
-    QMutex* operator&()
-    {
-        return &inner;
-    }
-};
-
-class OPENTRACK_EXPORT FunctionConfig {
+class OPENTRACK_EXPORT Map {
 private:
     void reload();
     float getValueInternal(int x);
-    
+
     MyMutex _mutex;
-	QList<QPointF> input;
+    QList<QPointF> input;
     std::vector<float> data;
-	QPointF last_input_value;
+    QPointF last_input_value;
     volatile bool activep;
-	int max_x;
-	int max_y;
+    int max_x;
+    int max_y;
 public:
     int maxInput() const { return max_x; }
     int maxOutput() const { return max_y; }
-    FunctionConfig();
-    FunctionConfig(int maxx, int maxy)
+    Map();
+    Map(int maxx, int maxy)
     {
         setMaxInput(maxx);
         setMaxOutput(maxy);
     }
 
     float getValue(float x);
-	bool getLastPoint(QPointF& point);
-	void removePoint(int i);
+    bool getLastPoint(QPointF& point);
+    void removePoint(int i);
     void removeAllPoints() {
         QMutexLocker foo(&_mutex);
         input.clear();
         reload();
     }
 
-	void addPoint(QPointF pt);
-	void movePoint(int idx, QPointF pt);
-	const QList<QPointF> getPoints();
-	void setMaxInput(int MaxInput) {
-		max_x = MaxInput;
-	}
-	void setMaxOutput(int MaxOutput) {
-		max_y = MaxOutput;
-	}
+    void addPoint(QPointF pt);
+    void movePoint(int idx, QPointF pt);
+    const QList<QPointF> getPoints();
+    void setMaxInput(int MaxInput) {
+        max_x = MaxInput;
+    }
+    void setMaxOutput(int MaxOutput) {
+        max_y = MaxOutput;
+    }
 
-	void saveSettings(QSettings& settings, const QString& title);
-	void loadSettings(QSettings& settings, const QString& title);
+    void saveSettings(QSettings& settings, const QString& title);
+    void loadSettings(QSettings& settings, const QString& title);
 
-	void setTrackingActive(bool blnActive);
+    void setTrackingActive(bool blnActive);
 };
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index 1e5b957c..57d1500a 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -37,7 +37,7 @@ QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) :
     setMouseTracking(true);
 }
 
-void QFunctionConfigurator::setConfig(FunctionConfig* config, const QString& name) {
+void QFunctionConfigurator::setConfig(Map* config, const QString& name) {
     QSettings settings("opentrack");
     QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
     QSettings iniFile( currentFile, QSettings::IniFormat );
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index facc5bbe..e35d0bc3 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -20,8 +20,8 @@ class OPENTRACK_EXPORT QFunctionConfigurator : public QWidget
 public:
 	QFunctionConfigurator(QWidget *parent = 0);
     
-	FunctionConfig* config();
-    void setConfig(FunctionConfig* config, const QString &name);
+	Map* config();
+    void setConfig(Map* config, const QString &name);
     
     QColor colorBezier() const
     {
@@ -65,7 +65,7 @@ private:
     QPointF pixel_coord_to_point (const QPointF& point);
     QPointF point_to_pixel (const QPointF& point);
 
-    FunctionConfig* _config;
+    Map* _config;
     
     // bounds of the rectangle user can interact with
 	QRectF  pixel_bounds;
-- 
cgit v1.2.3


From f78f4b73325a9df11c80bc191f735650006bd635 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 5 Oct 2014 20:25:40 +0200
Subject: retab only

---
 qfunctionconfigurator/functionconfig.cpp | 108 +++++++++++++++----------------
 1 file changed, 54 insertions(+), 54 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index f39562c1..7c4aaaab 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -35,51 +35,51 @@ float Map::getValue(float x) {
     QMutexLocker foo(&_mutex);
     int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
     float ret = getValueInternal(x2);
-	last_input_value.setX(x);
-	last_input_value.setY(ret);
-	return ret;
+        last_input_value.setX(x);
+        last_input_value.setY(ret);
+        return ret;
 }
 
 bool Map::getLastPoint(QPointF& point ) {
     QMutexLocker foo(&_mutex);
-	point = last_input_value;
-	return activep;
+        point = last_input_value;
+        return activep;
 }
 
 float Map::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
-	x = x < 0 ? -x : x;
+    x = x < 0 ? -x : x;
     float ret;
     int sz = data.size();
-	if (sz == 0)
-		ret = 0;
-	else if (x < 0)
-		ret = 0;
-	else if (x < sz && x >= 0)
-		ret = data[x];
-	else
-		ret = data[sz - 1];
-	return ret * sign;
+        if (sz == 0)
+                ret = 0;
+        else if (x < 0)
+                ret = 0;
+        else if (x < sz && x >= 0)
+                ret = data[x];
+        else
+                ret = data[sz - 1];
+        return ret * sign;
 }
 
 static __inline QPointF ensureInBounds(QList<QPointF> points, int i) {
-	int siz = points.size();
-	if (siz == 0 || i < 0)
-		return QPointF(0, 0);
-	if (siz > i)
-		return points[i];
-	return points[siz - 1];
+        int siz = points.size();
+        if (siz == 0 || i < 0)
+                return QPointF(0, 0);
+        if (siz > i)
+                return points[i];
+        return points[siz - 1];
 }
 
 static bool sortFn(const QPointF& one, const QPointF& two) {
-	return one.x() < two.x();
+        return one.x() < two.x();
 }
 
 void Map::reload() {
-	if (input.size())
-		qStableSort(input.begin(), input.end(), sortFn);
+        if (input.size())
+                qStableSort(input.begin(), input.end(), sortFn);
 
-	if (input.size()) {
+        if (input.size()) {
         data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x());
         
         const int sz = data.size();
@@ -87,7 +87,7 @@ void Map::reload() {
         for (int i = 0; i < sz; i++)
                 data[i] = -1;
 
-		for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {
+                for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {
             if (k < sz)
                 data[k] = input[0].y() * k / (input[0].x() * MEMOIZE_PRECISION);
         }
@@ -120,7 +120,7 @@ void Map::reload() {
                 if (x >= 0 && x < sz)
                     data[x] = y;
             }
-		}
+                }
 
        float last = 0;
        for (int i = 0; i < sz; i++)
@@ -129,7 +129,7 @@ void Map::reload() {
                data[i] = last;
            last = data[i];
        }
-	}
+        }
 }
 
 void Map::removePoint(int i) {
@@ -143,8 +143,8 @@ void Map::removePoint(int i) {
 
 void Map::addPoint(QPointF pt) {
     QMutexLocker foo(&_mutex);
-	input.append(pt);
-	reload();
+        input.append(pt);
+        reload();
 }
 
 void Map::movePoint(int idx, QPointF pt) {
@@ -159,42 +159,42 @@ void Map::movePoint(int idx, QPointF pt) {
 const QList<QPointF> Map::getPoints() {
     QMutexLocker foo(&_mutex);
     // NB can't pass by reference
-	return input;
+        return input;
 }
 
 void Map::loadSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
     QPointF newPoint;
 
-	QList<QPointF> points;
-	settings.beginGroup(QString("Curves-%1").arg(title));
-	
+        QList<QPointF> points;
+        settings.beginGroup(QString("Curves-%1").arg(title));
+        
     int max = settings.value("point-count", 0).toInt();
 
-	for (int i = 0; i < max; i++) {
-		newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
-				   settings.value(QString("point-%1-y").arg(i), 0).toFloat());
-		if (newPoint.x() > max_x) {
-			newPoint.setX(max_x);
-		}
-		if (newPoint.y() > max_y) {
-			newPoint.setY(max_y);
-		}
-		points.append(newPoint);
-	}
+        for (int i = 0; i < max; i++) {
+                newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
+                                   settings.value(QString("point-%1-y").arg(i), 0).toFloat());
+                if (newPoint.x() > max_x) {
+                        newPoint.setX(max_x);
+                }
+                if (newPoint.y() > max_y) {
+                        newPoint.setY(max_y);
+                }
+                points.append(newPoint);
+        }
     settings.endGroup();
-	input = points;
-	reload();
+        input = points;
+        reload();
 }
 
 void Map::saveSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
-	settings.beginGroup(QString("Curves-%1").arg(title));
-	int max = input.size();
-	settings.setValue("point-count", max);
-	for (int i = 0; i < max; i++) {
-		settings.setValue(QString("point-%1-x").arg(i), input[i].x());
-		settings.setValue(QString("point-%1-y").arg(i), input[i].y());
+        settings.beginGroup(QString("Curves-%1").arg(title));
+        int max = input.size();
+        settings.setValue("point-count", max);
+        for (int i = 0; i < max; i++) {
+                settings.setValue(QString("point-%1-x").arg(i), input[i].x());
+                settings.setValue(QString("point-%1-y").arg(i), input[i].y());
     }
 
     for (int i = max; true; i++)
@@ -205,5 +205,5 @@ void Map::saveSettings(QSettings& settings, const QString& title) {
         settings.remove(x);
         settings.remove(QString("point-%1-y").arg(i));
     }
-	settings.endGroup();
+        settings.endGroup();
 }
-- 
cgit v1.2.3


From 921853c7443060d21e18909ba806a859f8af86a5 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 5 Oct 2014 20:37:09 +0200
Subject: mapping was set to nonsense when exceeded spline bounds

---
 qfunctionconfigurator/functionconfig.cpp | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 7c4aaaab..99b6d871 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -14,8 +14,9 @@
 #include <QtAlgorithms>
 #include <QtAlgorithms>
 #include <QSettings>
-#include <cmath>
 #include <QPixmap>
+#include <cmath>
+#include <algorithm>
 
 void Map::setTrackingActive(bool blnActive)
 {
@@ -48,18 +49,14 @@ bool Map::getLastPoint(QPointF& point ) {
 
 float Map::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
-    x = x < 0 ? -x : x;
+    x = fabs(x);
     float ret;
     int sz = data.size();
-        if (sz == 0)
-                ret = 0;
-        else if (x < 0)
-                ret = 0;
-        else if (x < sz && x >= 0)
-                ret = data[x];
-        else
-                ret = data[sz - 1];
-        return ret * sign;
+    if (sz == 0)
+        ret = 0;
+    else
+        ret = std::max(std::min(x, sz-1), 0);
+    return ret * sign;
 }
 
 static __inline QPointF ensureInBounds(QList<QPointF> points, int i) {
-- 
cgit v1.2.3


From 1e10164eb7b66988e0404890239af7b7c1543395 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 5 Oct 2014 20:37:32 +0200
Subject: whitespace only

---
 qfunctionconfigurator/functionconfig.cpp | 72 ++++++++++++++++----------------
 1 file changed, 37 insertions(+), 35 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 99b6d871..69522da9 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -36,15 +36,15 @@ float Map::getValue(float x) {
     QMutexLocker foo(&_mutex);
     int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
     float ret = getValueInternal(x2);
-        last_input_value.setX(x);
-        last_input_value.setY(ret);
-        return ret;
+    last_input_value.setX(x);
+    last_input_value.setY(ret);
+    return ret;
 }
 
 bool Map::getLastPoint(QPointF& point ) {
     QMutexLocker foo(&_mutex);
-        point = last_input_value;
-        return activep;
+    point = last_input_value;
+    return activep;
 }
 
 float Map::getValueInternal(int x) {
@@ -73,12 +73,13 @@ static bool sortFn(const QPointF& one, const QPointF& two) {
 }
 
 void Map::reload() {
-        if (input.size())
-                qStableSort(input.begin(), input.end(), sortFn);
+    if (input.size())
+            qStableSort(input.begin(), input.end(), sortFn);
 
-        if (input.size()) {
+    if (input.size())
+    {
         data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x());
-        
+
         const int sz = data.size();
 
         for (int i = 0; i < sz; i++)
@@ -117,7 +118,7 @@ void Map::reload() {
                 if (x >= 0 && x < sz)
                     data[x] = y;
             }
-                }
+       }
 
        float last = 0;
        for (int i = 0; i < sz; i++)
@@ -126,7 +127,7 @@ void Map::reload() {
                data[i] = last;
            last = data[i];
        }
-        }
+    }
 }
 
 void Map::removePoint(int i) {
@@ -156,42 +157,43 @@ void Map::movePoint(int idx, QPointF pt) {
 const QList<QPointF> Map::getPoints() {
     QMutexLocker foo(&_mutex);
     // NB can't pass by reference
-        return input;
+    return input;
 }
 
 void Map::loadSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
     QPointF newPoint;
+    QList<QPointF> points;
+    settings.beginGroup(QString("Curves-%1").arg(title));
 
-        QList<QPointF> points;
-        settings.beginGroup(QString("Curves-%1").arg(title));
-        
     int max = settings.value("point-count", 0).toInt();
 
-        for (int i = 0; i < max; i++) {
-                newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
-                                   settings.value(QString("point-%1-y").arg(i), 0).toFloat());
-                if (newPoint.x() > max_x) {
-                        newPoint.setX(max_x);
-                }
-                if (newPoint.y() > max_y) {
-                        newPoint.setY(max_y);
-                }
-                points.append(newPoint);
-        }
+    for (int i = 0; i < max; i++) {
+            newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
+                               settings.value(QString("point-%1-y").arg(i), 0).toFloat());
+            if (newPoint.x() > max_x) {
+                    newPoint.setX(max_x);
+            }
+            if (newPoint.y() > max_y) {
+                    newPoint.setY(max_y);
+            }
+            points.append(newPoint);
+    }
+
     settings.endGroup();
-        input = points;
-        reload();
+    input = points;
+    reload();
 }
 
 void Map::saveSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
-        settings.beginGroup(QString("Curves-%1").arg(title));
-        int max = input.size();
-        settings.setValue("point-count", max);
-        for (int i = 0; i < max; i++) {
-                settings.setValue(QString("point-%1-x").arg(i), input[i].x());
-                settings.setValue(QString("point-%1-y").arg(i), input[i].y());
+    settings.beginGroup(QString("Curves-%1").arg(title));
+    int max = input.size();
+    settings.setValue("point-count", max);
+
+    for (int i = 0; i < max; i++) {
+        settings.setValue(QString("point-%1-x").arg(i), input[i].x());
+        settings.setValue(QString("point-%1-y").arg(i), input[i].y());
     }
 
     for (int i = max; true; i++)
@@ -202,5 +204,5 @@ void Map::saveSettings(QSettings& settings, const QString& title) {
         settings.remove(x);
         settings.remove(QString("point-%1-y").arg(i));
     }
-        settings.endGroup();
+    settings.endGroup();
 }
-- 
cgit v1.2.3


From 7581608afa596e3ab64fa312361fccf5cc409450 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 5 Oct 2014 20:47:32 +0200
Subject: cleanup some useless logic

---
 qfunctionconfigurator/functionconfig.cpp | 4 ++--
 qfunctionconfigurator/functionconfig.h   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 69522da9..6db3b55f 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -34,7 +34,7 @@ Map::Map() :
 
 float Map::getValue(float x) {
     QMutexLocker foo(&_mutex);
-    int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
+    int x2 = x * (double) MEMOIZE_PRECISION;
     float ret = getValueInternal(x2);
     last_input_value.setX(x);
     last_input_value.setY(ret);
@@ -55,7 +55,7 @@ float Map::getValueInternal(int x) {
     if (sz == 0)
         ret = 0;
     else
-        ret = std::max(std::min(x, sz-1), 0);
+        ret = data[std::max(std::min(x, sz-1), 0)];
     return ret * sign;
 }
 
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index ccfd1ba3..7d21fd63 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -17,10 +17,10 @@
 #include "../facetracknoir/plugin-api.hpp"
 #include "../facetracknoir/qcopyable-mutex.hpp"
 
-#define MEMOIZE_PRECISION 100
 
 class OPENTRACK_EXPORT Map {
 private:
+    static constexpr long MEMOIZE_PRECISION = 25;
     void reload();
     float getValueInternal(int x);
 
-- 
cgit v1.2.3


From 2cdc070555e717c99a287b90d8b9ffbf9e69b6cd Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 5 Oct 2014 21:38:08 +0200
Subject: nix cmath

---
 qfunctionconfigurator/functionconfig.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 6db3b55f..4c52b6eb 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -15,7 +15,6 @@
 #include <QtAlgorithms>
 #include <QSettings>
 #include <QPixmap>
-#include <cmath>
 #include <algorithm>
 
 void Map::setTrackingActive(bool blnActive)
@@ -49,7 +48,7 @@ bool Map::getLastPoint(QPointF& point ) {
 
 float Map::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
-    x = fabs(x);
+    x = std::abs((double) x);
     float ret;
     int sz = data.size();
     if (sz == 0)
-- 
cgit v1.2.3


From 88f985ca34275fc1cc014c5b8fa618ca95233db7 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 12 Oct 2014 00:30:13 +0200
Subject: spline editor needs discard changes on cancel

---
 facetracknoir/curve-config.cpp                  | 15 ++--
 facetracknoir/curve-config.h                    |  5 +-
 facetracknoir/facetracknoir.cpp                 |  8 +-
 facetracknoir/facetracknoir.h                   |  2 +-
 facetracknoir/facetracknoir.ui                  | 12 ---
 facetracknoir/mappings.hpp                      |  9 +++
 qfunctionconfigurator/functionconfig.cpp        | 97 ++++++++++++++-----------
 qfunctionconfigurator/functionconfig.h          | 12 ++-
 qfunctionconfigurator/qfunctionconfigurator.cpp | 71 ++++++++++--------
 qfunctionconfigurator/qfunctionconfigurator.h   | 16 +---
 10 files changed, 128 insertions(+), 119 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp
index 886e40fa..57cea7a4 100644
--- a/facetracknoir/curve-config.cpp
+++ b/facetracknoir/curve-config.cpp
@@ -1,7 +1,8 @@
 #include "./facetracknoir.h"
 #include "./curve-config.h"
 #include "./main-settings.hpp"
-CurveConfigurationDialog::CurveConfigurationDialog(Mappings& m, main_settings& s, QWidget *parent) : QWidget(parent, Qt::Dialog),
+MapWidget::MapWidget(Mappings& m, main_settings& s, QWidget *parent) :
+    QWidget(parent, Qt::Dialog),
     m(m)
 {
     ui.setupUi( this );
@@ -82,16 +83,12 @@ CurveConfigurationDialog::CurveConfigurationDialog(Mappings& m, main_settings& s
     tie_setting(s.a_z.src, ui.src_z);
 }
 
-void CurveConfigurationDialog::doOK() {
-    save();
+void MapWidget::doOK() {
+    m.save_mappings();
     this->close();
 }
 
-void CurveConfigurationDialog::doCancel() {
-    m.load_mappings();
+void MapWidget::doCancel() {
+    m.invalidate_unsaved();
     this->close();
 }
-
-void CurveConfigurationDialog::save() {
-    m.save_mappings();
-}
diff --git a/facetracknoir/curve-config.h b/facetracknoir/curve-config.h
index 67a588e2..d485c4ff 100644
--- a/facetracknoir/curve-config.h
+++ b/facetracknoir/curve-config.h
@@ -3,15 +3,14 @@
 #include "./mappings.hpp"
 #include "ui_ftnoir_curves.h"
 
-class CurveConfigurationDialog: public QWidget
+class MapWidget: public QWidget
 {
     Q_OBJECT
 public:
-    CurveConfigurationDialog(Mappings &m, main_settings &s, QWidget *parent );
+    MapWidget(Mappings &m, main_settings &s, QWidget *parent );
 private:
     Ui::UICCurveConfigurationDialog ui;
     Mappings& m;
-    void save();
 private slots:
     void doOK();
     void doCancel();
diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp
index af76f09b..f689cb5f 100644
--- a/facetracknoir/facetracknoir.cpp
+++ b/facetracknoir/facetracknoir.cpp
@@ -91,7 +91,7 @@ FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) : QMainWindow(parent),
     pProtocolDialog(nullptr),
     pFilterDialog(nullptr),
     shortcuts_widget(nullptr),
-    mapping_widget(new CurveConfigurationDialog(pose, s, this)),
+    mapping_widget(nullptr),
     kbd_quit(QKeySequence("Ctrl+Q"), this),
     looping(0),
     video_frame_layout(new QVBoxLayout()),
@@ -444,8 +444,10 @@ void FaceTrackNoIR::showKeyboardShortcuts() {
     shortcuts_widget->raise();
 }
 void FaceTrackNoIR::showCurveConfiguration() {
-    if (!mapping_widget)
-        mapping_widget = new CurveConfigurationDialog(pose, s, this);
+    if (mapping_widget)
+        delete mapping_widget;
+    
+    mapping_widget = new MapWidget(pose, s, this);
 
     mapping_widget->show();
     mapping_widget->raise();
diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h
index 09f96147..d4c3a369 100644
--- a/facetracknoir/facetracknoir.h
+++ b/facetracknoir/facetracknoir.h
@@ -100,7 +100,7 @@ private:
     IFilterDialog* pFilterDialog;
 
     QWidget *shortcuts_widget;
-    CurveConfigurationDialog* mapping_widget;
+    MapWidget* mapping_widget;
 
     void createIconGroupBox();
     void loadSettings();
diff --git a/facetracknoir/facetracknoir.ui b/facetracknoir/facetracknoir.ui
index 1d769f0d..41c6abc9 100644
--- a/facetracknoir/facetracknoir.ui
+++ b/facetracknoir/facetracknoir.ui
@@ -435,12 +435,6 @@
         </property>
         <item row="0" column="0">
          <widget class="QPushButton" name="btnEditCurves">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
           <property name="text">
            <string>Mapping</string>
           </property>
@@ -458,12 +452,6 @@
         </item>
         <item row="1" column="0">
          <widget class="QPushButton" name="btnShortcuts">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
           <property name="text">
            <string>Keys</string>
           </property>
diff --git a/facetracknoir/mappings.hpp b/facetracknoir/mappings.hpp
index a3e53450..5953ed1e 100644
--- a/facetracknoir/mappings.hpp
+++ b/facetracknoir/mappings.hpp
@@ -76,4 +76,13 @@ public:
             axes[i].curveAlt.saveSettings(iniFile, axes[i].name2);
         }
     }
+    
+    void invalidate_unsaved()
+    {
+        for (int i = 0; i < 6; i++)
+        {
+            axes[i].curve.invalidate_unsaved_settings();
+            axes[i].curveAlt.invalidate_unsaved_settings();
+        }
+    }
 };
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 4c52b6eb..0d37156e 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -24,7 +24,6 @@ void Map::setTrackingActive(bool blnActive)
 
 Map::Map() :
     _mutex(QMutex::Recursive),
-    data(0),
     activep(false),
     max_x(0),
     max_y(0)
@@ -48,13 +47,13 @@ bool Map::getLastPoint(QPointF& point ) {
 
 float Map::getValueInternal(int x) {
     float sign = x < 0 ? -1 : 1;
-    x = std::abs((double) x);
+    x = std::abs(x);
     float ret;
-    int sz = data.size();
+    int sz = cur.data.size();
     if (sz == 0)
         ret = 0;
     else
-        ret = data[std::max(std::min(x, sz-1), 0)];
+        ret = cur.data[std::max(std::min(x, sz-1), 0)];
     return ret * sign;
 }
 
@@ -72,91 +71,99 @@ static bool sortFn(const QPointF& one, const QPointF& two) {
 }
 
 void Map::reload() {
-    if (input.size())
-            qStableSort(input.begin(), input.end(), sortFn);
-
-    if (input.size())
+    if (cur.input.size())
     {
+        auto& input = cur.input;
+        auto& data = cur.data;
+        
+        qStableSort(input.begin(), input.end(), sortFn);
         data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x());
-
+        
         const int sz = data.size();
-
+        
         for (int i = 0; i < sz; i++)
-                data[i] = -1;
-
-                for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {
+            data[i] = -1;
+        
+        for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {
             if (k < sz)
                 data[k] = input[0].y() * k / (input[0].x() * MEMOIZE_PRECISION);
         }
-
-       for (int i = 0; i < sz; i++) {
+        
+        for (int i = 0; i < sz; i++) {
             QPointF p0 = ensureInBounds(input, i - 1);
             QPointF p1 = ensureInBounds(input, i);
             QPointF p2 = ensureInBounds(input, i + 1);
             QPointF p3 = ensureInBounds(input, i + 2);
-
+            
             int end = std::min<int>(sz, p2.x() * MEMOIZE_PRECISION);
             int start = p1.x() * MEMOIZE_PRECISION;
-
+            
             for (int j = start; j < end; j++) {
                 double t = (j - start) / (double) (end - start);
                 double t2 = t*t;
                 double t3 = t*t*t;
-
+                
                 int x = .5 * ((2. * p1.x()) +
                               (-p0.x() + p2.x()) * t +
                               (2. * p0.x() - 5. * p1.x() + 4. * p2.x() - p3.x()) * t2 +
                               (-p0.x() + 3. * p1.x() - 3. * p2.x() + p3.x()) * t3)
                         * MEMOIZE_PRECISION;
-
+                
                 float y = .5 * ((2. * p1.y()) +
-                                 (-p0.y() + p2.y()) * t +
-                                 (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 +
-                                 (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3);
-
+                                (-p0.y() + p2.y()) * t +
+                                (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 +
+                                (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3);
+                
                 if (x >= 0 && x < sz)
                     data[x] = y;
             }
-       }
-
-       float last = 0;
-       for (int i = 0; i < sz; i++)
-       {
-           if (data[i] <= 0)
-               data[i] = last;
-           last = data[i];
-       }
+        }
+        
+        float last = 0;
+        for (int i = 0; i < sz; i++)
+        {
+            if (data[i] <= 0)
+                data[i] = last;
+            last = data[i];
+        }
     }
+    else
+        cur.data.clear();
 }
 
 void Map::removePoint(int i) {
     QMutexLocker foo(&_mutex);
-    if (i >= 0 && i < input.size())
+    if (i >= 0 && i < cur.input.size())
     {
-        input.removeAt(i);
+        cur.input.removeAt(i);
         reload();
     }
 }
 
 void Map::addPoint(QPointF pt) {
     QMutexLocker foo(&_mutex);
-        input.append(pt);
+        cur.input.append(pt);
         reload();
 }
 
 void Map::movePoint(int idx, QPointF pt) {
     QMutexLocker foo(&_mutex);
-    if (idx >= 0 && idx < input.size())
+    if (idx >= 0 && idx < cur.input.size())
     {
-        input[idx] = pt;
+        cur.input[idx] = pt;
         reload();
     }
 }
 
 const QList<QPointF> Map::getPoints() {
     QMutexLocker foo(&_mutex);
-    // NB can't pass by reference
-    return input;
+    return cur.input;
+}
+
+void Map::invalidate_unsaved_settings()
+{
+    cur = saved;
+    reload();
 }
 
 void Map::loadSettings(QSettings& settings, const QString& title) {
@@ -180,19 +187,20 @@ void Map::loadSettings(QSettings& settings, const QString& title) {
     }
 
     settings.endGroup();
-    input = points;
+    cur.input = points;
     reload();
+    saved = cur;
 }
 
 void Map::saveSettings(QSettings& settings, const QString& title) {
     QMutexLocker foo(&_mutex);
     settings.beginGroup(QString("Curves-%1").arg(title));
-    int max = input.size();
+    int max = cur.input.size();
     settings.setValue("point-count", max);
 
     for (int i = 0; i < max; i++) {
-        settings.setValue(QString("point-%1-x").arg(i), input[i].x());
-        settings.setValue(QString("point-%1-y").arg(i), input[i].y());
+        settings.setValue(QString("point-%1-x").arg(i), cur.input[i].x());
+        settings.setValue(QString("point-%1-y").arg(i), cur.input[i].y());
     }
 
     for (int i = max; true; i++)
@@ -203,5 +211,8 @@ void Map::saveSettings(QSettings& settings, const QString& title) {
         settings.remove(x);
         settings.remove(QString("point-%1-y").arg(i));
     }
+    
+    saved = cur;
+        
     settings.endGroup();
 }
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 7d21fd63..e24f54cf 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -20,17 +20,22 @@
 
 class OPENTRACK_EXPORT Map {
 private:
+    struct State {
+        QList<QPointF> input;
+        std::vector<float> data;        
+    };
+    
     static constexpr long MEMOIZE_PRECISION = 25;
     void reload();
     float getValueInternal(int x);
 
     MyMutex _mutex;
-    QList<QPointF> input;
-    std::vector<float> data;
     QPointF last_input_value;
     volatile bool activep;
     int max_x;
     int max_y;
+    
+    State cur, saved;
 public:
     int maxInput() const { return max_x; }
     int maxOutput() const { return max_y; }
@@ -46,7 +51,7 @@ public:
     void removePoint(int i);
     void removeAllPoints() {
         QMutexLocker foo(&_mutex);
-        input.clear();
+        cur.input.clear();
         reload();
     }
 
@@ -62,6 +67,7 @@ public:
 
     void saveSettings(QSettings& settings, const QString& title);
     void loadSettings(QSettings& settings, const QString& title);
+    void invalidate_unsaved_settings();
 
     void setTrackingActive(bool blnActive);
 };
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index 57d1500a..b15f308e 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -10,20 +10,11 @@
 #include "qfunctionconfigurator/qfunctionconfigurator.h"
 #include <QPainter>
 #include <QPaintEvent>
-#include <QPainterPathStroker>
-#include <QPainterPath>
-#include <QBrush>
-#include <QFileDialog>
 #include <QPen>
-#include <QMessageBox>
-#include <QImage>
 #include <QPixmap>
 #include <QTimer>
-#include <QtDebug>
 #include <cmath>
-#include <QTabWidget>
-#include <QTabBar>
-#include <QFontMetrics>
+#include <algorithm>
 
 static const int pointSize = 5;
 
@@ -57,8 +48,7 @@ void QFunctionConfigurator::drawBackground()
     
     QPainter painter(&_background);
     painter.fillRect(rect(), QColor::fromRgb(204, 204, 204));
-    painter.setRenderHint(QPainter::Antialiasing);
-    
+
     QColor bg_color(112, 154, 209);
     painter.fillRect(pixel_bounds, bg_color);
 
@@ -140,8 +130,6 @@ void QFunctionConfigurator::drawFunction()
 
     _function = QPixmap(_background);
     QPainter painter(&_function);
-
-    painter.save();
     painter.setRenderHint(QPainter::Antialiasing, true);
 
     QList<QPointF> points = _config->getPoints();
@@ -164,13 +152,11 @@ void QFunctionConfigurator::drawFunction()
         drawLine(&painter, prev, cur, pen);
         prev = cur;
     }
-    painter.restore();
 }
 
 void QFunctionConfigurator::paintEvent(QPaintEvent *e)
 {
     QPainter p(this);
-    p.setRenderHint(QPainter::Antialiasing);
 
     if (_background.isNull())
         drawBackground();
@@ -179,6 +165,7 @@ void QFunctionConfigurator::paintEvent(QPaintEvent *e)
         _draw_function = false;
         drawFunction();
     }
+    
     p.drawPixmap(e->rect(), _function);
 
     if (_config) {
@@ -246,10 +233,9 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
         moving_control_point_idx = -1;
         if (_config) {
             for (int i = 0; i < points.size(); i++) {
-                if ( point_within_pixel(points[i], e->pos() ) ) {
+                if (point_within_pixel(points[i], e->pos())) {
                     bTouchingPoint = true;
                     moving_control_point_idx = i;
-                    timer.restart();
                     break;
                 }
             }
@@ -263,7 +249,7 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
         if (_config) {
             int found_pt = -1;
             for (int i = 0; i < points.size(); i++) {
-                if ( point_within_pixel(points[i], e->pos() ) ) {
+                if (point_within_pixel(points[i], e->pos())) {
                     found_pt = i;
                     break;
                 }
@@ -284,21 +270,31 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)
     if (!_config)
         return;
     
-    static constexpr int min_refresh_delay = 25;
+    static constexpr int min_refresh_delay = 12;
     
     if (timer.isValid() && timer.elapsed() < min_refresh_delay)
         return;
     
-    static constexpr int refresh_delay = 50;
+    static constexpr int refresh_delay = 17;
     QList<QPointF> points = _config->getPoints();
 
-    if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
+    if (moving_control_point_idx != -1 && moving_control_point_idx < points.size()) {
         setCursor(Qt::ClosedHandCursor);
-
-        if (timer.isValid() && timer.elapsed() > refresh_delay)
+        
+        bool overlap = false;
+        
+        QPointF new_pt = pixel_coord_to_point(e->pos());
+        
+        if (moving_control_point_idx + 1 < points.size())
+            overlap |= new_pt.x() > points[moving_control_point_idx+1].x();
+        if (moving_control_point_idx != 0)
+            overlap |= new_pt.x() < points[moving_control_point_idx-1].x();
+        
+        if (overlap)
+            moving_control_point_idx = -1;
+        else if (timer.isValid() && timer.elapsed() > refresh_delay)
         {
             timer.restart();
-            QPointF new_pt = pixel_coord_to_point(e->pos());
             points[moving_control_point_idx] = new_pt;
             _config->movePoint(moving_control_point_idx, new_pt);
             _draw_function = true;
@@ -326,11 +322,9 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
 {
     if (!_config)
         return;
-    
-    QList<QPointF> points = _config->getPoints();
 
     if (e->button() == Qt::LeftButton) {
-        timer.invalidate();
+        QList<QPointF> points = _config->getPoints();
         if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
             if (_config) {
                 _config->movePoint(moving_control_point_idx, pixel_coord_to_point(e->pos()));
@@ -338,10 +332,27 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
         }
         setCursor(Qt::ArrowCursor);
         moving_control_point_idx = -1;
+        
+        _draw_function = true;
+        update();
     }
+}
 
+void QFunctionConfigurator::update_range()
+{
+    if (!_config)
+        return;
+    
+    const double w = width(), h = height();
+    const double mwl = 40, mhl = 20;
+    const double mwr = 15, mhr = 35;
+    
+    pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr));
+    c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput());
     _draw_function = true;
-    update();
+    
+    _background = QPixmap();
+    _function = QPixmap();
 }
 
 bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel)
@@ -382,5 +393,5 @@ QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point)
 void QFunctionConfigurator::resizeEvent(QResizeEvent *)
 {
     update_range();
-    repaint();
+    update();
 }
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index e35d0bc3..25d8f8bc 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -46,21 +46,7 @@ private:
 protected:
 	virtual void resizeEvent(QResizeEvent *);
 private:
-    void update_range() {
-        if (!_config)
-            return;
-        
-        const double w = width(), h = height();
-        const double mwl = 40, mhl = 20;
-        const double mwr = 15, mhr = 35;
-        
-        pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr));
-        c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput());
-        _draw_function = true;
-        
-        _background = QPixmap();
-        _function = QPixmap();
-    }
+    void update_range();
 
     QPointF pixel_coord_to_point (const QPointF& point);
     QPointF point_to_pixel (const QPointF& point);
-- 
cgit v1.2.3


From e63b05db86c6b3a9c9967578a0b811ded5daecc3 Mon Sep 17 00:00:00 2001
From: Stanislaw Halik <sthalik@misaki.pl>
Date: Sun, 12 Oct 2014 16:07:54 +0200
Subject: copyright in header only

---
 qfunctionconfigurator/functionconfig.cpp        | 8 --------
 qfunctionconfigurator/qfunctionconfigurator.cpp | 9 ---------
 qfunctionconfigurator/qfunctionconfigurator.h   | 7 +++++--
 3 files changed, 5 insertions(+), 19 deletions(-)

(limited to 'qfunctionconfigurator/functionconfig.cpp')

diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 0d37156e..a4d03ed8 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -1,11 +1,3 @@
-/* Copyright (c) 2012, 2013 Stanisław Halik <sthalik@misaki.pl>
-
- * Permission to use, copy, modify, and/or distribute this
- * software for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice and this permission
- * notice appear in all copies.
- */
-
 #include <QMutexLocker>
 #include <QCoreApplication>
 #include <QPointF>
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index b15f308e..94a31be5 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -1,12 +1,3 @@
-/* Copyright (c) 2011-2014 Stanislaw Halik <sthalik@misaki.pl>
- * 
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-// Adapted to FaceTrackNoIR by Wim Vriend.
-
 #include "qfunctionconfigurator/qfunctionconfigurator.h"
 #include <QPainter>
 #include <QPaintEvent>
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index 25d8f8bc..229d9977 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -1,9 +1,12 @@
 /* Copyright (c) 2011-2014 Stanislaw Halik <sthalik@misaki.pl>
- *                         Adapted to FaceTrackNoIR by Wim Vriend.
+ * 
  * 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.
  */
+
+// Adapted to FaceTrackNoIR by Wim Vriend.
+
 #pragma once
 
 #include <QWidget>
@@ -44,7 +47,7 @@ private:
 	void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen& pen);
     bool point_within_pixel(const QPointF& pt, const QPointF& pixel);
 protected:
-	virtual void resizeEvent(QResizeEvent *);
+	void resizeEvent(QResizeEvent *) override;
 private:
     void update_range();
 
-- 
cgit v1.2.3