diff options
Diffstat (limited to 'qfunctionconfigurator/qfunctionconfigurator.cpp')
-rw-r--r-- | qfunctionconfigurator/qfunctionconfigurator.cpp | 267 |
1 files changed, 121 insertions, 146 deletions
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp index 55d1e1bc..94a31be5 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ b/qfunctionconfigurator/qfunctionconfigurator.cpp @@ -1,71 +1,47 @@ -/* 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> -#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; -QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) - : QWidget(parent) +QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) : + QWidget(parent), + _config(nullptr), + moving_control_point_idx(-1), + _draw_function(true) { - movingPoint = -1; // Index of that same point - _config = 0; - _draw_background = true; - _draw_function = true; update_range(); setMouseTracking(true); } -void QFunctionConfigurator::setConfig(FunctionConfig* config) { - QSettings settings("opentrack"); // Registry settings (in HK_USER) +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 ); // Application settings (in INI-file) + QSettings iniFile( currentFile, QSettings::IniFormat ); - config->loadSettings(iniFile); + 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) - - if (_config) { - _config->saveSettings(iniFile); - } -} - 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 +55,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,102 +118,82 @@ void QFunctionConfigurator::drawFunction() { if (!_config) return; - int i; - QPointF prevPoint; - QPointF currentPoint; _function = QPixmap(_background); QPainter painter(&_function); - - painter.save(); painter.setRenderHint(QPainter::Antialiasing, true); 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 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)); drawLine(&painter, prev, cur, pen); prev = cur; } - painter.restore(); } 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 (points.size() && moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) { + QPointF prev = points[0]; + for (int i = 1; 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 +205,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,19 +221,17 @@ 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() ) ) { + if (point_within_pixel(points[i], e->pos())) { bTouchingPoint = true; - movingPoint = i; - timer.restart(); + moving_control_point_idx = i; break; } } if (!bTouchingPoint) { _config->addPoint(pixel_coord_to_point(e->pos())); - emit CurveChanged( true ); } } } @@ -288,7 +240,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; } @@ -296,9 +248,8 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e) if (found_pt != -1) { _config->removePoint(found_pt); - emit CurveChanged( true ); } - movingPoint = -1; + moving_control_point_idx = -1; } } _draw_function = true; @@ -309,29 +260,43 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) { if (!_config) return; + + static constexpr int min_refresh_delay = 12; + + if (timer.isValid() && timer.elapsed() < min_refresh_delay) + return; + + static constexpr int refresh_delay = 17; QList<QPointF> points = _config->getPoints(); - const int refresh_delay = 50; - if (movingPoint >= 0 && movingPoint < 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[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; } } @@ -348,38 +313,54 @@ 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()) { - emit CurveChanged( true ); + QList<QPointF> points = _config->getPoints(); + 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(); } +} +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(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; @@ -394,20 +375,14 @@ QPointF QFunctionConfigurator::pixel_coord_to_point(QPointF point) const return QPointF(x, y); } -QPointF QFunctionConfigurator::point_to_pixel(QPointF point) const -{ - return QPointF(range.x() + point.x() * c.x(), - range.y() + range.height() - point.y() * c.y()); -} - -void QFunctionConfigurator::setColorBezier(QColor color) +QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point) { - colBezier = color; - update(); + return QPointF(pixel_bounds.x() + point.x() * c.x(), + pixel_bounds.y() + pixel_bounds.height() - point.y() * c.y()); } void QFunctionConfigurator::resizeEvent(QResizeEvent *) { update_range(); - repaint(); + update(); } |