summaryrefslogtreecommitdiffhomepage
path: root/qfunctionconfigurator
diff options
context:
space:
mode:
Diffstat (limited to 'qfunctionconfigurator')
-rw-r--r--qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp (renamed from qfunctionconfigurator/qfunctionconfiguratorplugin.cpp)47
-rw-r--r--qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h (renamed from qfunctionconfigurator/qfunctionconfiguratorplugin.h)9
-rw-r--r--qfunctionconfigurator/functionconfig.cpp563
-rw-r--r--qfunctionconfigurator/functionconfig.h153
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.cpp853
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.h171
6 files changed, 691 insertions, 1105 deletions
diff --git a/qfunctionconfigurator/qfunctionconfiguratorplugin.cpp b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp
index 5e98eb39..1a9da10a 100644
--- a/qfunctionconfigurator/qfunctionconfiguratorplugin.cpp
+++ b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp
@@ -1,37 +1,9 @@
-/********************************************************************************
-* FaceTrackNoIR This program is a private project of some enthusiastic *
-* gamers from Holland, who don't like to pay much for *
-* head-tracking. *
-* *
-* Copyright (C) 2012 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage http://facetracknoir.sourceforge.net/home/default.htm *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <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. *
-********************************************************************************/
+/* Copyright (c) 2011-2012 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.
+ */
#include "qfunctionconfigurator.h"
#include <QtCore/QtPlugin>
@@ -110,13 +82,6 @@ QString QFunctionConfiguratorPlugin::domXml() const
" <blue>0</blue>\n"
" </color>\n"
" </property>\n"
- " <property name=\"colorBackground\">\n"
- " <color>\n"
- " <red>192</red>\n"
- " <green>192</green>\n"
- " <blue>192</blue>\n"
- " </color>\n"
- " </property>\n"
" <property name=\"stringInputEGU\" stdset=\"0\">\n"
" <string>Input Yaw (degr.)</string>\n"
" </property>\n"
diff --git a/qfunctionconfigurator/qfunctionconfiguratorplugin.h b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h
index c6b65fcc..bc637338 100644
--- a/qfunctionconfigurator/qfunctionconfiguratorplugin.h
+++ b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h
@@ -1,3 +1,9 @@
+/* Copyright (c) 2011-2012 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.
+ */
#ifndef QFUNCTIONCONFIGURATORPLUGIN_H
#define QFUNCTIONCONFIGURATORPLUGIN_H
@@ -6,7 +12,8 @@
class QFunctionConfiguratorPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
- Q_INTERFACES(QDesignerCustomWidgetInterface)
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "analogclock.json")
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
QFunctionConfiguratorPlugin(QObject *parent = 0);
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 1b06bdc2..97a6db24 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -1,282 +1,281 @@
-/* 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>
-#include <QList>
-#include "functionconfig.h"
-#include <QtAlgorithms>
-#include <QtAlgorithms>
-#include <QSettings>
-#include <math.h>
-#include <QPixmap>
-#include <QDebug>
-
-//
-// Constructor with List of Points in argument.
-//
-FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput)
-{
- _mutex = new QMutex(QMutex::Recursive);
- _title = title;
- _points = QList<QPointF>();
- _data = 0;
- _size = 0;
- lastValueTracked = QPointF(0,0);
- _tracking_active = false;
- _max_Input = intMaxInput; // Added WVR 20120805
- _max_Output = intMaxOutput;
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- loadSettings(iniFile);
- reload();
-}
-
-FunctionConfig::FunctionConfig() :
- _tracking_active(false),
- _max_Input(0),
- _max_Output(0),
- _data(0),
- _mutex(0),
- _size(0)
-{
- _mutex = new QMutex();
-}
-
-//
-// 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);
- float ret = getValueInternal(x2);
- lastValueTracked.setX(x);
- lastValueTracked.setY(ret);
- 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;
- return _tracking_active;
-}
-
-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)
- ret = 0;
- else if (x < 0)
- ret = 0;
- else if (x < _size && x >= 0)
- ret = _data[x];
- else
- ret = _data[_size - 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];
-}
-
-static bool sortFn(const QPointF& one, const QPointF& two) {
- return one.x() < two.x();
-}
-
-void FunctionConfig::reload() {
- _size = 0;
-
- if (_points.size())
- qStableSort(_points.begin(), _points.end(), sortFn);
-
- 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 < _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 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);
-
- int end = p2.x() * MEMOIZE_PRECISION;
- int start = p1.x() * MEMOIZE_PRECISION;
-
- for (int j = start; j < end && j < _size; j++) {
- float t = (j - start) / (float) (end - start);
- float t2 = t*t;
- float 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);
-
- if (x >= 0 && x < _size)
- _data[x] = y;
- }
- }
-
- float last = 0;
-
- for (int i = 0; i < _size; i++)
- {
- if (_data[i] == -1e6)
- _data[i] = last;
- last = _data[i];
- }
- }
-}
-
-FunctionConfig::~FunctionConfig() {
- if (_data)
- delete[] _data;
- if (_mutex)
- delete _mutex;
-}
-
-//
-// Remove a Point from the Function.
-// Used by the Widget.
-//
-void FunctionConfig::removePoint(int i) {
- QMutexLocker foo(_mutex);
- if (i >= 0 && i < _points.size())
- {
- _points.removeAt(i);
- reload();
- }
-}
-
-//
-// 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())
- {
- _points[idx] = pt;
- reload();
- }
-}
-
-//
-// Return the List of Points.
-// Used by the Widget.
-//
-QList<QPointF> FunctionConfig::getPoints() {
- QList<QPointF> ret;
- QMutexLocker foo(_mutex);
- for (int i = 0; i < _points.size(); i++) {
- ret.append(_points[i]);
- }
- 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;
-
- QList<QPointF> points;
- settings.beginGroup(QString("Curves-%1").arg(_title));
-
- int max = settings.value("point-count", 0).toInt();
-
- qDebug() << _title << "count" << max;
-
- for (int i = 0; i < max; i++) {
- newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), (i + 1) * _max_Input/2).toFloat(),
- settings.value(QString("point-%1-y").arg(i), (i + 1) * _max_Output/2).toFloat());
- //
- // Make sure the new Point fits in the Function Range.
- // Maybe this can be improved?
- //
- if (newPoint.x() > _max_Input) {
- newPoint.setX(_max_Input);
- }
- if (newPoint.y() > _max_Output) {
- newPoint.setY(_max_Output);
- }
- points.append(newPoint);
- }
- settings.endGroup();
- _points = points;
- 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));
- int max = _points.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());
- }
-
- for (int i = max; true; i++)
- {
- QString x = QString("point-%1-x").arg(i);
- if (!settings.contains(x))
- break;
- settings.remove(x);
- settings.remove(QString("point-%1-y").arg(i));
- }
- settings.endGroup();
-}
+/* 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>
+#include <QList>
+#include "functionconfig.h"
+#include <QtAlgorithms>
+#include <QtAlgorithms>
+#include <QSettings>
+#include <math.h>
+#include <QPixmap>
+
+//
+// Constructor with List of Points in argument.
+//
+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; // Added WVR 20120805
+ _max_Output = intMaxOutput;
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+ 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;
+}
+
+FunctionConfig::FunctionConfig() :
+ _mutex(QMutex::Recursive),
+ _data(0),
+ _size(0),
+ _tracking_active(false),
+ _max_Input(0),
+ _max_Output(0)
+{
+}
+
+//
+// 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);
+ float ret = getValueInternal(x2);
+ lastValueTracked.setX(x);
+ lastValueTracked.setY(ret);
+ 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;
+ return _tracking_active;
+}
+
+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)
+ ret = 0;
+ else if (x < 0)
+ ret = 0;
+ else if (x < _size && x >= 0)
+ ret = _data[x];
+ else
+ ret = _data[_size - 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];
+}
+
+static bool sortFn(const QPointF& one, const QPointF& two) {
+ return one.x() < two.x();
+}
+
+void FunctionConfig::reload() {
+ _size = 0;
+
+ if (_points.size())
+ qStableSort(_points.begin(), _points.end(), sortFn);
+
+ 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 < _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 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);
+
+ int end = p2.x() * MEMOIZE_PRECISION;
+ int start = p1.x() * MEMOIZE_PRECISION;
+
+ for (int j = start; j < end && j < _size; 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);
+
+ if (x >= 0 && x < _size)
+ _data[x] = y;
+ }
+ }
+
+ float last = 0;
+
+ for (int i = 0; i < _size; i++)
+ {
+ if (_data[i] == -1e6)
+ _data[i] = last;
+ last = _data[i];
+ }
+ }
+}
+
+FunctionConfig::~FunctionConfig() {
+ if (_data)
+ 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())
+ {
+ _points.removeAt(i);
+ reload();
+ }
+}
+
+//
+// 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())
+ {
+ _points[idx] = pt;
+ reload();
+ }
+}
+
+//
+// Return the List of Points.
+// Used by the Widget.
+//
+QList<QPointF> FunctionConfig::getPoints() {
+ QList<QPointF> ret;
+ QMutexLocker foo(&_mutex);
+ for (int i = 0; i < _points.size(); i++) {
+ ret.append(_points[i]);
+ }
+ 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;
+
+ 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());
+ //
+ // Make sure the new Point fits in the Function Range.
+ // Maybe this can be improved?
+ //
+ if (newPoint.x() > _max_Input) {
+ newPoint.setX(_max_Input);
+ }
+ if (newPoint.y() > _max_Output) {
+ newPoint.setY(_max_Output);
+ }
+ points.append(newPoint);
+ }
+ settings.endGroup();
+ _points = points;
+ 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));
+ int max = _points.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());
+ }
+
+ for (int i = max; true; i++)
+ {
+ QString x = QString("point-%1-x").arg(i);
+ if (!settings.contains(x))
+ break;
+ settings.remove(x);
+ settings.remove(QString("point-%1-y").arg(i));
+ }
+ settings.endGroup();
+}
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 0f60c979..4d771dfd 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -1,78 +1,75 @@
-/* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl>
-
- * Permission to use, copy, modify, and/or distribute this
- * software for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice and this permission
- * notice appear in all copies.
- */
-
-#include <QList>
-#include <QPointF>
-#include <QString>
-#include <QSettings>
-#include <QMutex>
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-
-#ifndef FUNCTION_CONFIG_H
-#define FUNCTION_CONFIG_H
-
-#define MEMOIZE_PRECISION 500
-
-class FTNOIR_TRACKER_BASE_EXPORT FunctionConfig {
-private:
- QMutex* _mutex;
- QList<QPointF> _points;
- void reload();
- float* _data;
- int _size;
- QString _title;
- float getValueInternal(int x);
- QPointF lastValueTracked; // The last input value requested by the Tracker, with it's output-value.
- volatile bool _tracking_active;
- int _max_Input;
- int _max_Output;
- FunctionConfig(const FunctionConfig&) {}
-public:
- //
- // Contructor(s) and destructor
- //
- FunctionConfig();
- FunctionConfig(QString title, int intMaxInput, int intMaxOutput);
- virtual ~FunctionConfig();
-
- float getValue(float x);
- bool getLastPoint(QPointF& point); // Get the last Point that was requested.
-
- //
- // Functions to manipulate the Function
- //
- void removePoint(int i);
- void removeAllPoints() {
- QMutexLocker foo(_mutex);
- _points.clear();
- reload();
- }
-
- void addPoint(QPointF pt);
- void movePoint(int idx, QPointF pt);
- QList<QPointF> getPoints();
- void setMaxInput(int MaxInput) {
- _max_Input = MaxInput;
- }
- void setMaxOutput(int MaxOutput) {
- _max_Output = MaxOutput;
- }
-
- //
- // Functions to load/save the Function-Points to an INI-file
- //
- void saveSettings(QSettings& settings);
- void loadSettings(QSettings& settings);
-
- void setTrackingActive(bool blnActive) {
- _tracking_active = blnActive;
- }
- QString getTitle() { return _title; }
-};
-
-#endif
+/* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl>
+
+ * Permission to use, copy, modify, and/or distribute this
+ * software for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice and this permission
+ * notice appear in all copies.
+ */
+
+#pragma once
+
+#include <QList>
+#include <QPointF>
+#include <QString>
+#include <QSettings>
+#include <QMutex>
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+
+#define MEMOIZE_PRECISION 100
+
+class FTNOIR_TRACKER_BASE_EXPORT FunctionConfig {
+private:
+ QMutex _mutex;
+ QList<QPointF> _points;
+ void reload();
+ float* _data;
+ int _size;
+ QString _title;
+ float getValueInternal(int x);
+ QPointF lastValueTracked; // The last input value requested by the Tracker, with it's output-value.
+ volatile bool _tracking_active;
+ int _max_Input;
+ int _max_Output;
+ FunctionConfig(const FunctionConfig&) = delete;
+public:
+ int maxInput() const { return _max_Input; }
+ int maxOutput() const { return _max_Output; }
+ //
+ // Contructor(s) and destructor
+ //
+ FunctionConfig();
+ FunctionConfig(QString title, int intMaxInput, int intMaxOutput);
+ ~FunctionConfig();
+
+ float getValue(float x);
+ bool getLastPoint(QPointF& point); // Get the last Point that was requested.
+
+ //
+ // Functions to manipulate the Function
+ //
+ void removePoint(int i);
+ void removeAllPoints() {
+ QMutexLocker foo(&_mutex);
+ _points.clear();
+ reload();
+ }
+
+ void addPoint(QPointF pt);
+ void movePoint(int idx, QPointF pt);
+ QList<QPointF> getPoints();
+ void setMaxInput(int MaxInput) {
+ _max_Input = MaxInput;
+ }
+ void setMaxOutput(int MaxOutput) {
+ _max_Output = MaxOutput;
+ }
+
+ //
+ // Functions to load/save the Function-Points to an INI-file
+ //
+ void saveSettings(QSettings& settings);
+ void loadSettings(QSettings& settings);
+
+ void setTrackingActive(bool blnActive);
+ QString getTitle() { return _title; }
+};
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index 304d252e..55d1e1bc 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -1,45 +1,10 @@
-/********************************************************************************
-* FaceTrackNoIR This program is a private project of some enthusiastic *
-* gamers from Holland, who don't like to pay much for *
-* head-tracking. *
-* *
-* Copyright (C) 2012 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage http://facetracknoir.sourceforge.net/home/default.htm *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <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. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: Changed functionality a bit. Now only draw the handles, when the function is drawn.
- Only check mouseMoves, when they occur 'in range'. Redraw the curve, when a resize occurs.
- Somehow, the curve was not drawn correctly, when this was not done (all points were too high).
- After a 'Reset' this would disappear...
- 20120828 - WVR: Removed bSkipText, which was used to not show a number below each vertical gridline.
-*/
+/* Copyright (c) 2011-2012 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.
+ */
+
#include "qfunctionconfigurator/qfunctionconfigurator.h"
#include <QPainter>
#include <QPaintEvent>
@@ -52,323 +17,224 @@
#include <QImage>
#include <QPixmap>
#include <QTimer>
-
#include <QtDebug>
-
-#include <math.h>
+#include <cmath>
+#include <QTabWidget>
+#include <QTabBar>
+#include <QFontMetrics>
static const int pointSize = 5;
QFunctionConfigurator::QFunctionConfigurator(QWidget *parent)
: QWidget(parent)
{
-
- //
- // Defaults, for when the widget has no values different from the domXML()
- //
- MaxInput = 50; // Maximum input limit
- MaxOutput = 180; // Maximum output limit
- pPerEGU_Output = 1; // Number of pixels, per EGU
- pPerEGU_Input = 4; // Number of pixels, per EGU
- gDistEGU_Input = 5; // Distance of gridlines
- gDistEGU_Output = 10; // Distance of gridlines
-
-
- // Change compared to BezierConfigurator: X = horizontal (input), Y = vertical (output)
- // This will require the Curve-Dialog to be higher (which was the reason it was reversed in the first place..)
- range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output);
-
- setMouseTracking(true);
movingPoint = -1; // Index of that same point
-
- //
- // Variables for FunctionConfig
- //
- _config = 0;
- _points = QList<QPointF>();
- _draw_background = true;
- _draw_function = true;
-
-// qDebug() << "QFunctionConfigurator::QFunctionConfigurator object created.";
-
+ _config = 0;
+ _draw_background = true;
+ _draw_function = true;
+ update_range();
+ setMouseTracking(true);
}
-//
-// Attach an existing FunctionConfig to the Widget.
-//
-void QFunctionConfigurator::setConfig(FunctionConfig* config, QString settingsFile) {
-QPointF currentPoint;
-QPointF drawPoint;
-qreal x;
-
- _config = config;
- _points = config->getPoints();
- strSettingsFile = settingsFile; // Remember for Reset()
-
- qDebug() << "QFunctionConfigurator::setConfig" << config->getTitle();
- setCaption(config->getTitle());
-
- //
- // Get the Function Points, one for each pixel in the horizontal range.
- // If the curve does not change, there is no need to run this code every time (it slows down drawing).
- //
- for (int j = 0; j < MaxInput * pPerEGU_Input; j++) {
- //
- // Weird: not casting to float causes C++ to round the number...
- //
- x = (float) j / (float) pPerEGU_Input;
- currentPoint.setX ( x );
- currentPoint.setY (_config->getValue( x ));
- drawPoint = graphicalizePoint(currentPoint, "setConfig");
- //if (withinRect(drawPoint, range)) {
- //_draw_points.append(drawPoint);
-// qDebug() << "QFunctionConfigurator::setConfig _draw_Point to add = " << drawPoint;
- //}
- }
-
- _draw_function = true;
- this->update();
-}
+void QFunctionConfigurator::setConfig(FunctionConfig* config) {
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-//
-// Load the FunctionConfig (points) from the INI-file.
-//
-void QFunctionConfigurator::loadSettings(QString settingsFile) {
-
- QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- strSettingsFile = settingsFile; // Remember for Reset()
- qDebug() << "QFunctionConfigurator::loadSettings = " << settingsFile;
- if (_config) {
- _config->loadSettings(iniFile);
- setConfig(_config, settingsFile);
- }
+ config->loadSettings(iniFile);
+ _config = config;
+ _draw_function = _draw_background = true;
+ update_range();
+ update();
}
-//
-// Save the FunctionConfig (points) to the INI-file.
-//
void QFunctionConfigurator::saveSettings(QString settingsFile) {
- QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- strSettingsFile = settingsFile; // Remember for Reset()
- qDebug() << "QFunctionConfigurator::saveSettings = " << settingsFile;
+ QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- if (_config) {
- _config->saveSettings(iniFile);
- }
+ if (_config) {
+ _config->saveSettings(iniFile);
+ }
}
-//
-// Draw the Background for the graph, the gridlines and the gridpoints.
-// The static objects are drawn on a Pixmap, so it does not have to be repeated every paintEvent. Hope this speeds things up...
-//
-void QFunctionConfigurator::drawBackground(const QRectF &fullRect)
+void QFunctionConfigurator::drawBackground()
{
-int i;
-QRect scale;
-
- qDebug() << "QFunctionConfigurator::drawBackground.";
-
- _background = QPixmap(fullRect.width(), fullRect.height());
- QPainter painter(&_background);
-
- painter.save();
- painter.setRenderHint(QPainter::Antialiasing);
- painter.fillRect(fullRect, colBackground);
- QColor bg_color(112, 154, 209);
- painter.fillRect(range, bg_color);
-
- QFont font("ComicSans", 4);
+ 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);
+
+ QFont font;
font.setPointSize(8);
painter.setFont(font);
+ QFontMetrics metrics(font);
QPen pen(QColor(55, 104, 170, 127), 1, Qt::SolidLine);
- //
- // Draw the Caption
- //
- if (_config) {
- strCaption = _config->getTitle();
- }
-
- scale.setCoords(range.left(), 0, range.right(), 20);
- painter.drawText(scale, Qt::AlignCenter, strCaption);
-
- //
- // Draw the horizontal grid
- //
- for (i = range.bottom() - gDistEGU_Output * pPerEGU_Output; i >= range.top(); i -= gDistEGU_Output * pPerEGU_Output) {
- drawLine(&painter, QPointF(40, i), QPointF(range.right(), i), pen);
- scale.setCoords(0, i - 5, range.left() - 5, i + 5);
- painter.drawText(scale, Qt::AlignRight, tr("%1").arg(((range.bottom() - i))/pPerEGU_Output));
- }
-
- //
- // Draw the vertical guidelines
- //
- for (i = range.left(); i <= range.right(); i += gDistEGU_Input * pPerEGU_Input) {
- drawLine(&painter, QPointF(i, range.top()), QPointF(i, range.bottom()), pen);
- scale.setCoords(i - 10, range.bottom() + 2, i + 10, range.bottom() + 15);
- painter.drawText(scale, Qt::AlignCenter, tr("%1").arg(abs(((range.left() - i))/pPerEGU_Input)));
- }
-
- scale.setCoords(range.left(), range.bottom() + 20, range.right(), range.bottom() + 35);
- painter.drawText(scale, Qt::AlignRight, strInputEGU);
-
- //
- // Draw the EGU of the vertical axis (vertically!)
- //
- font.setPointSize(10);
- painter.translate(range.topLeft().x() - 35, range.topLeft().y());
- painter.rotate(90);
- painter.drawText(0,0,strOutputEGU );
-
- //
- // Draw the two axis
- //
- pen.setWidth(2);
- pen.setColor( Qt::black );
- drawLine(&painter, range.topLeft() - QPointF(2,0), range.bottomLeft() - QPointF(2,0), pen);
- drawLine(&painter, range.bottomLeft(), range.bottomRight(), pen);
-
- painter.restore();
-}
+ const int xstep = 10, ystep = 10;
+ const int maxx = _config->maxInput();
+ const int maxy = _config->maxOutput();
+
+ // horizontal grid
+
+ for (int i = 0; i < maxy; i += xstep)
+ {
+ double y = range.height() - i * c.y() + range.y();
+ drawLine(&painter,
+ QPointF(range.x(), y),
+ QPointF(range.x() + range.width(), y),
+ pen);
+ painter.drawText(QRectF(10,
+ y - metrics.height()/2,
+ range.left(),
+ metrics.height()),
+ QString::number(i));
+ }
+ {
+ const int i = maxy;
+ double y = range.height() - i * c.y() + range.y();
+ drawLine(&painter,
+ QPointF(range.x(), y),
+ QPointF(range.x() + range.width(), y),
+ pen);
+ painter.drawText(QRectF(10,
+ y - metrics.height()/2,
+ range.x() - 10,
+ metrics.height()),
+ QString::number(i));
+ }
-//
-// Draw the Function for the graph, on a Pixmap.
-//
-void QFunctionConfigurator::drawFunction(const QRectF &fullRect)
+ // vertical grid
+
+ for (int i = 0; i < maxx; i += ystep)
+ {
+ double x = range.x() + i * c.x();
+ drawLine(&painter,
+ QPointF(x, range.y()),
+ QPointF(x, range.y() + range.height()),
+ pen);
+ const QString text = QString::number(i);
+ painter.drawText(QRectF(x - metrics.width(text)/2,
+ range.height() + 10 + metrics.height(),
+ metrics.width(text),
+ metrics.height()),
+ text);
+ }
+ {
+ const int i = maxx;
+ double x = range.x() + i * c.x();
+ drawLine(&painter,
+ QPointF(x, range.y()),
+ QPointF(x, range.y() + range.height()),
+ pen);
+ const QString text = QString::number(i);
+ painter.drawText(QRectF(x - metrics.width(text)/2,
+ range.height() + 10 + metrics.height(),
+ metrics.width(text),
+ metrics.height()),
+ text);
+ }
+}
+
+void QFunctionConfigurator::drawFunction()
{
- if (!_config)
- return;
-int i;
-QPointF prevPoint;
-QPointF currentPoint;
-
- //
- // Use the background picture to draw on.
- // ToDo: find out how to add Pixmaps, without getting it all green...
- //
- _function = QPixmap(_background);
- QPainter painter(&_function);
-
- painter.save();
+ if (!_config)
+ return;
+ int i;
+ QPointF prevPoint;
+ QPointF currentPoint;
+
+ _function = QPixmap(_background);
+ QPainter painter(&_function);
+
+ painter.save();
painter.setRenderHint(QPainter::Antialiasing, true);
- //
- // Draw the handles for the Points
- //
- for (i = 0; i < _points.size(); i++) {
- currentPoint = graphicalizePoint( _points[i], "drawFunction handles" ); // Get the next point and convert it to Widget measures
- drawPoint(&painter, currentPoint, QColor(200, 200, 210, 120));
- lastPoint = currentPoint; // Remember which point is the rightmost in the graph
-//qDebug() << "QFunctionConfigurator::paintEvent, drawing handle for " << currentPoint;
- }
+ 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
+ }
QPen pen(colBezier, 1.2, Qt::SolidLine);
- prevPoint = graphicalizePoint( QPointF(0,0), "drawFunction lines" ); // Start at the Axis
- double max = maxInputEGU();
- QPointF prev = graphicalizePoint(QPointF(0, 0));
- double step = 1e-1 / (double) pixPerEGU_Input();
- for (double i = 0; i < max; i += step) {
- double val = _config->getValue(i);
- QPointF cur = graphicalizePoint(QPointF(i, val));
- drawLine(&painter, prev, cur, pen);
- prev = cur;
- }
- painter.restore();
+ prevPoint = point_to_pixel( QPointF(0,0) ); // Start at the Axis
+ 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));
+ drawLine(&painter, prev, cur, pen);
+ prev = cur;
+ }
+ painter.restore();
}
-//
-// The Widget paints the surface every x msecs.
-//
void QFunctionConfigurator::paintEvent(QPaintEvent *e)
{
-QPointF prevPoint;
-QPointF currentPoint;
-QPointF actualPos;
-int i;
+ QPointF prevPoint;
+ QPointF currentPoint;
+ QPointF actualPos;
+ int i;
-// qDebug() << "QFunctionConfigurator::paintEvent.";
-
- QPainter p(this);
+ QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
- p.setClipRect(e->rect());
-
- if (_draw_background) {
- drawBackground(e->rect()); // Draw the static parts on a Pixmap
- p.drawPixmap(0, 0, _background); // Paint the background
- _draw_background = false;
- }
-
- if (_draw_function) {
- drawFunction(e->rect()); // Draw the Function on a Pixmap
- _draw_function = false;
- }
- p.drawPixmap(0, 0, _function); // Always draw the background and the function
-
- QPen pen(Qt::white, 1, Qt::SolidLine);
-
- //
- // Draw the Points, that make up the Curve
- //
- if (_config) {
- //
- // When moving, also draw a sketched version of the Function.
- //
- if (movingPoint >= 0 && movingPoint < _points.size()) {
- prevPoint = graphicalizePoint( QPointF(0,0), "paintEvent moving" ); // Start at the Axis
- for (i = 0; i < _points.size(); i++) {
- currentPoint = graphicalizePoint( _points[i], "paintEvent moving" ); // Get the next point and convert it to Widget measures
- drawLine(&p, prevPoint, currentPoint, pen);
- prevPoint = currentPoint;
-// qDebug() << "QFunctionConfigurator::paintEvent, drawing while moving " << currentPoint;
- }
-
- //
- // When moving, also draw a few help-lines, so positioning the point gets easier.
- //
- pen.setWidth(1);
- pen.setColor( Qt::white );
- pen.setStyle( Qt::DashLine );
- actualPos = graphicalizePoint(_points[movingPoint], "paintEvent moving help line(s)");
- drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
- drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen);
- }
-
- //
- // If the Tracker is active, the 'Last Point' it requested is recorded.
- // Show that point on the graph, with some lines to assist.
- // This new feature is very handy for tweaking the curves!
- //
- if (_config->getLastPoint( currentPoint )) {
-
-// qDebug() << "QFunctionConfigurator::paintEvent, drawing tracked Point " << currentPoint;
-
- actualPos = graphicalizePoint( currentPoint, "paintEvent tracking" );
- drawPoint(&p, actualPos, QColor(255, 0, 0, 120));
-
- pen.setWidth(1);
- pen.setColor( Qt::black );
- pen.setStyle( Qt::SolidLine );
- drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
- drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen);
- }
-
- }
-
- //
- // Draw the delimiters
- //
- pen.setWidth(1);
- pen.setColor( Qt::white );
- pen.setStyle( Qt::SolidLine );
- drawLine(&p, QPoint(lastPoint.x(), range.top()), QPoint(lastPoint.x(), range.bottom()), pen);
- drawLine(&p, QPoint(range.left(), lastPoint.y()), QPoint(range.right(), lastPoint.y()), pen);
-
- //QTimer::singleShot(50, this, SLOT(update()));
+
+ if (_draw_background) {
+ drawBackground();
+ _draw_background = false;
+ }
+ p.drawPixmap(e->rect(), _background);
+
+ if (_draw_function) {
+ drawFunction(); // Draw the Function on a Pixmap
+ _draw_function = false;
+ }
+ p.drawPixmap(e->rect(), _function); // Always draw the background and the 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;
+ }
+ 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);
+ }
+
+ //
+ // 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));
+
+ 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);
+ }
+
+ }
}
//
@@ -394,252 +260,144 @@ void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, co
painter->restore();
}
-//
-// If the mousebutton is pressed, check if it is inside one of the Points.
-// If so: start moving that Point, until mouse release.
-//
void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
{
- //
- // First: check the left mouse-button
- //
- if (e->button() == Qt::LeftButton) {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- bool bTouchingPoint = false;
- movingPoint = -1;
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mousePressEvent markContains" ), e->pos() ) ) {
- bTouchingPoint = true;
- movingPoint = i;
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+ if (e->button() == Qt::LeftButton) {
+ bool bTouchingPoint = false;
+ movingPoint = -1;
+ if (_config) {
+ for (int i = 0; i < points.size(); i++) {
+ if ( point_within_pixel(points[i], e->pos() ) ) {
+ bTouchingPoint = true;
+ movingPoint = i;
+ timer.restart();
break;
- }
- }
-
- //
- // If the Left Mouse-button was clicked without touching a Point, add a new Point
- //
- if (!bTouchingPoint) {
- if (withinRect(e->pos(), range)) {
- _config->addPoint(normalizePoint(e->pos()));
- setConfig(_config, strSettingsFile);
- movingPoint = -1;
- emit CurveChanged( true );
- }
- }
- }
- }
-
- //
- // Then: check the right mouse-button
- //
- if (e->button() == Qt::RightButton) {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mousePressEvent RightButton" ), e->pos() ) ) {
- movingPoint = i;
+ }
+ }
+ if (!bTouchingPoint) {
+ _config->addPoint(pixel_coord_to_point(e->pos()));
+ emit CurveChanged( true );
+ }
+ }
+ }
+
+ if (e->button() == Qt::RightButton) {
+ if (_config) {
+ int found_pt = -1;
+ for (int i = 0; i < points.size(); i++) {
+ if ( point_within_pixel(points[i], e->pos() ) ) {
+ found_pt = i;
break;
- }
- }
-
- //
- // If the Right Mouse-button was clicked while touching a Point, remove the Point
- //
- if (movingPoint >= 0 && movingPoint < _points.size()) {
- _config->removePoint(movingPoint);
- movingPoint = -1;
- setConfig(_config, strSettingsFile);
- emit CurveChanged( true );
- }
- else
- movingPoint = -1;
+ }
+ }
+
+ if (found_pt != -1) {
+ _config->removePoint(found_pt);
+ emit CurveChanged( true );
+ }
+ movingPoint = -1;
}
- }
+ }
+ _draw_function = true;
+ update();
}
-//
-// If the mouse if moving, make sure the Bezier moves along.
-// Of course, only when a Point is selected...
-//
void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)
{
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+ const int refresh_delay = 50;
+
+ if (movingPoint >= 0 && movingPoint < 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);
+ _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;
+ }
+ }
+ }
- if (movingPoint >= 0 && movingPoint < _points.size()) {
-
- setCursor(Qt::ClosedHandCursor);
-
- //
- // Change the currently moving Point.
- //
- _points[movingPoint] = normalizePoint(e->pos());
- update();
+ if ( bTouchingPoint ) {
+ setCursor(Qt::OpenHandCursor);
+ }
+ else {
+ setCursor(Qt::ArrowCursor);
+ }
}
- else {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- bool bTouchingPoint = false;
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mouseMoveEvent" ), e->pos() ) ) {
- bTouchingPoint = true;
- }
- }
- }
-
- if ( bTouchingPoint ) {
- setCursor(Qt::OpenHandCursor);
- }
- else {
- setCursor(Qt::ArrowCursor);
- }
-
- }
}
void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
{
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+
if (e->button() == Qt::LeftButton) {
- //qDebug()<<"releasing";
- if (movingPoint >= 0 && movingPoint < _points.size()) {
+ timer.invalidate();
+ if (movingPoint >= 0 && movingPoint < points.size()) {
emit CurveChanged( true );
-
- //
- // Update the Point in the _config
- //
if (_config) {
- _config->movePoint(movingPoint, normalizePoint(e->pos()));
- setConfig(_config, strSettingsFile);
+ _config->movePoint(movingPoint, pixel_coord_to_point(e->pos()));
}
}
setCursor(Qt::ArrowCursor);
movingPoint = -1;
}
-}
-
-//
-// Determine if the mousebutton was pressed within the range of the Point.
-//
-bool QFunctionConfigurator::markContains(const QPointF &pos, const QPointF &coord) const
-{
- QRectF rect(pos.x() - pointSize,
- pos.y() - pointSize,
- pointSize*2, pointSize*2);
- QPainterPath path;
- path.addEllipse(rect);
- return path.contains(coord);
-}
-bool QFunctionConfigurator::withinRect( const QPointF &coord, const QRectF &rect ) const
-{
- QPainterPath path;
- path.addRect(rect);
- return path.contains(coord);
+ _draw_function = true;
+ update();
}
-//
-// Convert the Point in the graph, to the real-life Point.
-//
-QPointF QFunctionConfigurator::normalizePoint(QPointF point) const
+bool QFunctionConfigurator::point_within_pixel(QPointF pt, QPointF pixel) const
{
- QPointF norm;
-
- norm.setX( (point.x() - range.left()) / pPerEGU_Input );
- norm.setY( (range.bottom() - point.y()) / pPerEGU_Output );
-
- if (norm.x() > maxInputEGU())
- norm.setX(maxInputEGU());
- else if (norm.x() < 0)
- norm.setX(0);
- if (norm.y() > maxOutputEGU())
- norm.setY(maxOutputEGU());
- else if (norm.y() < 0)
- norm.setY(0);
-
- return norm;
+ QPointF pixel2(range.x() + pt.x() * c.x(), (range.y() + range.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;
}
-//
-// Convert the real-life Point into the graphical Point.
-//
-QPointF QFunctionConfigurator::graphicalizePoint(QPointF point, QString source) const
+QPointF QFunctionConfigurator::pixel_coord_to_point(QPointF point) const
{
-QPointF graph;
-
- graph.setX( range.left() + (fabs(point.x()) * pPerEGU_Input) );
- graph.setY( range.bottom() - (fabs(point.y()) * pPerEGU_Output) );
-
-// qDebug() << "QFunctionConfigurator::graphicalizePoint source = " << source << ", point = " << point << ", graph = " << graph;
-
- return graph;
-}
+ if (!_config)
+ return QPointF(-1, -1);
-void QFunctionConfigurator::setmaxInputEGU(int value)
-{
- MaxInput = value;
- setMinimumWidth(MaxInput * pPerEGU_Input + 55);
-// resetCurve();
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
-void QFunctionConfigurator::setmaxOutputEGU(int value)
-{
- MaxOutput = value;
- setMinimumHeight(MaxOutput * pPerEGU_Output + 60);
-// resetCurve();
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ double x = (point.x() - range.x()) / c.x();
+ double y = (range.height() - point.y() + range.y()) / c.y();
-//
-// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined.
-//
-void QFunctionConfigurator::setpixPerEGU_Input(int value)
-{
- pPerEGU_Input = value;
- setMinimumWidth(MaxInput * pPerEGU_Input + 55);
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ if (x < 0)
+ x = 0;
+ if (x > _config->maxInput())
+ x = _config->maxInput();
-//
-// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined.
-//
-void QFunctionConfigurator::setpixPerEGU_Output(int value)
-{
- pPerEGU_Output = value;
- setMinimumHeight(MaxOutput * pPerEGU_Output + 60);
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ if (y < 0)
+ y = 0;
+ if (y > _config->maxOutput())
+ y = _config->maxOutput();
-//
-// Define the distance of the grid 'in EGU' points.
-//
-void QFunctionConfigurator::setgridDistEGU_Input(int value)
-{
- gDistEGU_Input = value;
- _draw_background = true;
- _draw_function = true;
- repaint();
+ return QPointF(x, y);
}
-//
-// Define the distance of the grid 'in EGU' points.
-//
-void QFunctionConfigurator::setgridDistEGU_Output(int value)
+QPointF QFunctionConfigurator::point_to_pixel(QPointF point) const
{
- gDistEGU_Output = value;
- _draw_background = true;
- _draw_function = true;
- repaint();
+ return QPointF(range.x() + point.x() * c.x(),
+ range.y() + range.height() - point.y() * c.y());
}
void QFunctionConfigurator::setColorBezier(QColor color)
@@ -647,38 +405,9 @@ void QFunctionConfigurator::setColorBezier(QColor color)
colBezier = color;
update();
}
-void QFunctionConfigurator::setColorBackground(QColor color)
-{
- colBackground = color;
- update();
-}
-
-void QFunctionConfigurator::setInputEGU(QString egu)
-{
- strInputEGU = egu;
- update();
-}
-void QFunctionConfigurator::setOutputEGU(QString egu)
-{
- strOutputEGU = egu;
- update();
-}
-void QFunctionConfigurator::setCaption(QString cap)
-{
- strCaption = cap;
- update();
-}
-void QFunctionConfigurator::resizeEvent(QResizeEvent *e)
+void QFunctionConfigurator::resizeEvent(QResizeEvent *)
{
- range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output);
-
- qDebug() << "QFunctionConfigurator::resizeEvent, name = " << strCaption << ",range = " << range;
-
- if (_config) {
- setConfig(_config, strSettingsFile);
- }
- _draw_background = true;
- _draw_function = true;
- repaint();
+ update_range();
+ repaint();
}
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index 963f6b13..1f6b4f78 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -1,44 +1,16 @@
-/********************************************************************************
-* FaceTrackNoIR This program is a private project of some enthusiastic *
-* gamers from Holland, who don't like to pay much for *
-* head-tracking. *
-* *
-* Copyright (C) 2012 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage http://facetracknoir.sourceforge.net/home/default.htm *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <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. *
-********************************************************************************/
+/* Copyright (c) 2011-2012 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.
+ */
#ifndef QFUNCTIONCONFIGURATOR_H
#define QFUNCTIONCONFIGURATOR_H
#include <QWidget>
#include <QtGui>
-#include <QtDesigner/QDesignerExportWidget>
#include <QPointF>
+#include <QElapsedTimer>
#include "qfunctionconfigurator/functionconfig.h"
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
@@ -49,104 +21,27 @@
// The Function is coded in a separate Class and can exists, without the Widget. When the widget is displayed (therefore 'created'), the Function can be attached to the
// Widget and the Widget used to change the Function.
//
+
class FTNOIR_TRACKER_BASE_EXPORT QFunctionConfigurator : public QWidget
{
Q_OBJECT
- Q_PROPERTY(int maxInputEGU READ maxInputEGU WRITE setmaxInputEGU);
- Q_PROPERTY(int maxOutputEGU READ maxOutputEGU WRITE setmaxOutputEGU);
- Q_PROPERTY(int pixPerEGU_Input READ pixPerEGU_Input WRITE setpixPerEGU_Input);
- Q_PROPERTY(int pixPerEGU_Output READ pixPerEGU_Output WRITE setpixPerEGU_Output);
- Q_PROPERTY(int gridDistEGU_Input READ gridDistEGU_Input WRITE setgridDistEGU_Input);
- Q_PROPERTY(int gridDistEGU_Output READ gridDistEGU_Output WRITE setgridDistEGU_Output);
-
- Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier);
- Q_PROPERTY(QColor colorBackground READ colorBackground WRITE setColorBackground);
- Q_PROPERTY(QString stringInputEGU READ stringInputEGU WRITE setInputEGU);
- Q_PROPERTY(QString stringOutputEGU READ stringOutputEGU WRITE setOutputEGU);
- Q_PROPERTY(QString stringCaption READ stringCaption WRITE setCaption);
-
- // Return the current value to Designer
- int maxInputEGU() const
- {
- return MaxInput;
- }
- int maxOutputEGU() const
- {
- return MaxOutput;
- }
- int pixPerEGU_Input() const
- {
- return pPerEGU_Input;
- }
- int pixPerEGU_Output() const
- {
- return pPerEGU_Output;
- }
- int gridDistEGU_Input() const
- {
- return gDistEGU_Input;
- }
- int gridDistEGU_Output() const
- {
- return gDistEGU_Output;
- }
-
- // Return the current color to Designer
- QColor colorBezier() const
+ Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
+ QColor colorBezier() const
{
return colBezier;
}
- // Return the current color to Designer
- QColor colorBackground() const
- {
- return colBackground;
- }
- // Return the current string to Designer
- QString stringInputEGU() const
- {
- return strInputEGU;
- }
- // Return the current string to Designer
- QString stringOutputEGU() const
- {
- return strOutputEGU;
- }
- // Return the current string to Designer
- QString stringCaption() const
- {
- return strCaption;
- }
-
public:
QFunctionConfigurator(QWidget *parent = 0);
FunctionConfig* config();
- void setConfig(FunctionConfig* config, QString settingsFile); // Connect the FunctionConfig to the Widget.
- void loadSettings(QString settingsFile); // Load the FunctionConfig (points) from the INI-file
- void saveSettings(QString settingsFile); // Save the FunctionConfig (points) to the INI-file
+ void setConfig(FunctionConfig* config);
+ void saveSettings(QString settingsFile);
signals:
void CurveChanged(bool);
public slots:
- void setmaxInputEGU(int);
- void setmaxOutputEGU(int);
- void setpixPerEGU_Input(int);
- void setpixPerEGU_Output(int);
- void setgridDistEGU_Input(int);
- void setgridDistEGU_Output(int);
-
void setColorBezier(QColor);
- void setColorBackground(QColor);
- void setInputEGU(QString);
- void setOutputEGU(QString);
- void setCaption(QString);
-
- void resetCurve() {
- qDebug() << "QFunctionConfigurator::resetCurve = " << strSettingsFile;
- loadSettings( strSettingsFile );
- }
-
protected slots:
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
@@ -154,50 +49,44 @@ protected slots:
void mouseReleaseEvent(QMouseEvent *e);
protected:
- void drawBackground(const QRectF &rect);
- void drawFunction(const QRectF &rect);
+ 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 markContains(const QPointF &pt, const QPointF &coord) const;
-// bool withinRange( const QPointF &coord ) const;
- bool withinRect( const QPointF &coord, const QRectF &rect ) const;
+ bool point_within_pixel(QPointF pt, QPointF pixel) const;
protected:
virtual void resizeEvent(QResizeEvent *);
private:
+ void update_range() {
+ if (!_config)
+ return;
+ 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;
+ }
+
QRectF range; // The actual rectangle for the Bezier-curve
QPointF lastPoint; // The right-most point of the Function
- QPointF normalizePoint (QPointF point) const; // Convert the graphical Point to a real-life Point
- QPointF graphicalizePoint (QPointF point, QString source = "") const; // Convert the Point to a graphical Point
+ QPointF pixel_coord_to_point (QPointF point) const; // Convert the graphical Point to a real-life Point
+ QPointF point_to_pixel (QPointF point) const; // Convert the Point to a graphical Point
int movingPoint;
-
- int MaxInput; // Maximum input limit
- int MaxOutput; // Maximum output limit
- int pPerEGU_Input; // Number of pixels, per EGU of Input
- int pPerEGU_Output; // Number of pixels, per EGU of Output
- int gDistEGU_Input; // Distance of the grid, in EGU of Input
- int gDistEGU_Output; // Distance of the grid, in EGU of Output
+ QElapsedTimer timer;
+ QPointF c;
QColor colBezier; // Color of Bezier curve
- QColor colBackground; // Color of widget background
- QString strInputEGU; // Engineering Units input (vertical axis)
- QString strOutputEGU; // Engineering Units output (horizontal axis)
- QString strCaption; // Caption of the graph
- QString strSettingsFile; // Name of last read INI-file
bool _draw_background; // Flag to determine if the background should be (re-)drawn on the QPixmap
QPixmap _background; // Image of the static parts (axis, lines, etc.)
bool _draw_function; // Flag to determine if the function should be (re-)drawn on the QPixmap
QPixmap _function; // Image of the function (static unless edited by the user)
- //
- // Properties of the CurveConfigurator Widget
- //
- QString _title; // Title do display in Widget and to load Settings
FunctionConfig* _config;
- QList<QPointF> _points; // Function-points
};
#endif // QFUNCTIONCONFIGURATOR_H