From 88f985ca34275fc1cc014c5b8fa618ca95233db7 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik 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(-) 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 @@ - - - 0 - 0 - - Mapping @@ -458,12 +452,6 @@ - - - 0 - 0 - - Keys 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(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(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 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 input; + std::vector data; + }; + static constexpr long MEMOIZE_PRECISION = 25; void reload(); float getValueInternal(int x); MyMutex _mutex; - QList input; - std::vector 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 #include -#include -#include -#include -#include #include -#include -#include #include #include -#include #include -#include -#include -#include +#include 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 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 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 points = _config->getPoints(); if (e->button() == Qt::LeftButton) { - timer.invalidate(); + QList 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