summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gui/main-window.cpp20
-rw-r--r--gui/main-window.hpp2
-rw-r--r--spline-widget/spline-widget.cpp74
-rw-r--r--spline-widget/spline-widget.hpp22
-rw-r--r--spline-widget/spline.cpp315
-rw-r--r--spline-widget/spline.hpp68
6 files changed, 238 insertions, 263 deletions
diff --git a/gui/main-window.cpp b/gui/main-window.cpp
index be7ddbe3..b09b70d0 100644
--- a/gui/main-window.cpp
+++ b/gui/main-window.cpp
@@ -122,10 +122,6 @@ MainWindow::MainWindow() :
this, [&]() -> void { qDebug() << "restart tracker"; stopTracker(); startTracker(); },
Qt::QueuedConnection);
- // this sort of makes sense since the cancel button on the mapping window
- // emits this signal.
- connect(s.b_map.get(), &bundle_type::reloading, this, &MainWindow::reload_splines);
-
// tray
{
init_tray_menu();
@@ -262,20 +258,6 @@ void MainWindow::save_modules()
m.b->save();
}
-void MainWindow::load_mappings()
-{
- pose.load_mappings();
- if (mapping_widget)
- mapping_widget->reload();
-}
-
-void MainWindow::load_settings()
-{
- m.b->reload();
- s.b->reload();
- load_mappings();
-}
-
void MainWindow::make_empty_config()
{
QString name;
@@ -644,7 +626,7 @@ void MainWindow::profile_selected(const QString& name)
save_modules();
set_profile(new_name);
set_title();
- load_settings();
+ options::detail::bundler::refresh_all_bundles();
}
}
diff --git a/gui/main-window.hpp b/gui/main-window.hpp
index a74575c9..6923c119 100644
--- a/gui/main-window.hpp
+++ b/gui/main-window.hpp
@@ -78,8 +78,6 @@ class MainWindow : public QMainWindow, private State
return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr);
}
- void load_settings();
- void load_mappings();
void updateButtonState(bool running, bool inertialp);
void display_pose(const double* mapped, const double* raw);
void ensure_tray();
diff --git a/spline-widget/spline-widget.cpp b/spline-widget/spline-widget.cpp
index 1f049339..85477ba7 100644
--- a/spline-widget/spline-widget.cpp
+++ b/spline-widget/spline-widget.cpp
@@ -5,8 +5,6 @@
* copyright notice and this permission notice appear in all copies.
*/
-#include "compat/options.hpp"
-using namespace options;
#include "spline-widget.hpp"
#include <QPainter>
#include <QPaintEvent>
@@ -28,13 +26,21 @@ spline_widget::spline_widget(QWidget *parent) :
setMouseTracking(true);
}
-void spline_widget::setConfig(spline* config, const QString& name)
+void spline_widget::setConfig(spline* config, bundle b)
{
- mem<QSettings> iniFile = group::ini_file();
- if (name != "")
- config->loadSettings(*iniFile, name);
+ if (config && config->get_bundle() && config->get_bundle() != b)
+ {
+ QObject::disconnect(connection);
+ connection = QMetaObject::Connection();
+ }
+
+ if (config && config->get_bundle() != b)
+ config->set_bundle(b);
_config = config;
- _draw_function = true;
+ if (b)
+ connection = connect(b.get(), &bundle_type::reloading,
+ this, &spline_widget::reload_spline,
+ Qt::QueuedConnection);
update_range();
update();
}
@@ -76,11 +82,11 @@ void spline_widget::drawBackground()
QPen pen(color__, 1, Qt::SolidLine);
const int xstep = 10, ystep = 10;
- const qreal maxx = _config->maxInput() + ystep;
- const qreal maxy = _config->maxOutput() + xstep;
+ const qreal maxx = _config->maxInput();
+ const qreal maxy = _config->maxOutput();
// horizontal grid
- for (int i = 0; i < maxy; i += xstep)
+ for (int i = 0; i <= maxy; i += xstep)
{
const qreal y = pixel_bounds.height() - i * c.y() + pixel_bounds.y();
drawLine(&painter,
@@ -95,7 +101,7 @@ void spline_widget::drawBackground()
}
// vertical grid
- for (int i = 0; i < maxx; i += ystep)
+ for (int i = 0; i <= maxx; i += ystep)
{
const qreal x = pixel_bounds.x() + i * c.x();
drawLine(&painter,
@@ -120,7 +126,7 @@ void spline_widget::drawFunction()
QPainter painter(&_function);
painter.setRenderHint(QPainter::Antialiasing, true);
- QList<QPointF> points = _config->getPoints();
+ points_t points = _config->getPoints();
const int alpha = !isEnabled() ? 64 : 120;
if (!_preview_only)
@@ -158,14 +164,14 @@ void spline_widget::drawFunction()
QPointF prev = point_to_pixel(QPointF(0, 0));
for (qreal i = 0; i < max; i += step)
{
- const qreal val = qreal(_config->getValue(float(i)));
+ const qreal val = qreal(_config->getValue(i));
QPointF cur = point_to_pixel(QPointF(i, val));
painter.drawLine(prev, cur);
prev = cur;
}
{
- const qreal val = _config->getValue(float(max));
+ const qreal val = qreal(_config->getValue(max));
QPointF last = point_to_pixel(QPointF(max, val));
painter.drawLine(prev, last);
}
@@ -183,7 +189,8 @@ void spline_widget::paintEvent(QPaintEvent *e)
drawBackground();
}
- if (_draw_function) {
+ if (_draw_function)
+ {
_draw_function = false;
drawFunction();
}
@@ -193,13 +200,13 @@ void spline_widget::paintEvent(QPaintEvent *e)
if (_config)
{
QPen pen(Qt::white, 1, Qt::SolidLine);
- QList<QPointF> points = _config->getPoints();
+ points_t points = _config->getPoints();
if (points.size() &&
moving_control_point_idx >= 0 &&
moving_control_point_idx < points.size())
{
if (points[0].x() > 1e-2)
- points.prepend(QPointF(0, 0));
+ points.push_front(QPointF(0, 0));
QPointF prev = point_to_pixel(points[0]);
for (int i = 1; i < points.size(); i++)
{
@@ -245,7 +252,7 @@ void spline_widget::mousePressEvent(QMouseEvent *e)
{
if (!_config || !isEnabled())
return;
- QList<QPointF> points = _config->getPoints();
+ points_t points = _config->getPoints();
if (e->button() == Qt::LeftButton)
{
bool bTouchingPoint = false;
@@ -257,7 +264,7 @@ void spline_widget::mousePressEvent(QMouseEvent *e)
if (point_within_pixel(points[i], e->pos()))
{
bTouchingPoint = true;
- moving_control_point_idx = i;
+ moving_control_point_idx = int(i);
break;
}
}
@@ -269,7 +276,7 @@ void spline_widget::mousePressEvent(QMouseEvent *e)
for (int i = 0; i < points.size(); i++)
{
const QPointF pt = point_to_pixel(points[i]);
- const auto x = pt.x() - pos.x();
+ const qreal x = pt.x() - pos.x();
if (point_closeness_limit * point_closeness_limit >= x * x)
{
too_close = true;
@@ -313,11 +320,13 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e)
if (!_config || !isEnabled())
return;
- QList<QPointF> points = _config->getPoints();
+ points_t points = _config->getPoints();
- if (moving_control_point_idx != -1 &&
+ if (moving_control_point_idx >= 0 &&
moving_control_point_idx < points.size())
{
+ const int idx = moving_control_point_idx;
+
setCursor(Qt::ClosedHandCursor);
bool overlap = false;
@@ -328,9 +337,9 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e)
for (int i = 0; i < 2; i++)
{
bool bad = false;
- if (moving_control_point_idx + 1 < points.size())
+ if (idx + 1 < points.size())
{
- auto other = points[moving_control_point_idx+1];
+ auto other = points[idx+1];
auto other_pix = point_to_pixel(other);
bad = pix.x() + point_closeness_limit > other_pix.x();
if (i == 0 && bad)
@@ -341,9 +350,9 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e)
else
overlap |= bad;
}
- if (moving_control_point_idx != 0)
+ if (idx != 0)
{
- auto other = points[moving_control_point_idx-1];
+ auto other = points[idx-1];
auto other_pix = point_to_pixel(other);
bad = pix.x() - point_closeness_limit < other_pix.x();
if (i == 0 && bad)
@@ -360,8 +369,8 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e)
if (!overlap)
{
- points[moving_control_point_idx] = new_pt;
- _config->movePoint(moving_control_point_idx, new_pt);
+ points[idx] = new_pt;
+ _config->movePoint(int(idx), new_pt);
_draw_function = true;
update();
}
@@ -406,6 +415,15 @@ void spline_widget::mouseReleaseEvent(QMouseEvent *e)
}
}
+void spline_widget::reload_spline()
+{
+ if (_config && _config->get_bundle() != nullptr)
+ {
+ _config->set_bundle(_config->get_bundle());
+ update_range();
+ }
+}
+
void spline_widget::update_range()
{
if (!_config)
diff --git a/spline-widget/spline-widget.hpp b/spline-widget/spline-widget.hpp
index 1dbdb8e1..9ad4f598 100644
--- a/spline-widget/spline-widget.hpp
+++ b/spline-widget/spline-widget.hpp
@@ -9,22 +9,29 @@
#pragma once
+#include "spline.hpp"
+#include "api/plugin-api.hpp"
+#include "options/options.hpp"
#include <QWidget>
#include <QtGui>
+#include <QMetaObject>
#include <QPointF>
-#include "spline.hpp"
-#include "api/plugin-api.hpp"
+#include <QDebug>
+using namespace options;
-class SPLINE_WIDGET_EXPORT spline_widget : public QWidget
+class SPLINE_WIDGET_EXPORT spline_widget final : public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
Q_PROPERTY(bool is_preview_only READ is_preview_only WRITE set_preview_only)
+
+ using points_t = spline::points_t;
public:
spline_widget(QWidget *parent = 0);
spline* config();
- void setConfig(spline* config, const QString &name);
+
+ void setConfig(spline* config, bundle b);
QColor colorBezier() const
{
@@ -49,6 +56,7 @@ protected slots:
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
+ void reload_spline();
private:
void drawBackground();
void drawFunction();
@@ -68,13 +76,17 @@ private:
// bounds of the rectangle user can interact with
QRectF pixel_bounds;
- int moving_control_point_idx;
QPointF c;
QColor spline_color;
QPixmap _background;
QPixmap _function;
+
+ QMetaObject::Connection connection;
+
+ int moving_control_point_idx;
+
int snap_x, snap_y;
bool _draw_function, _preview_only;
diff --git a/spline-widget/spline.cpp b/spline-widget/spline.cpp
index 48b508ef..da67f0d4 100644
--- a/spline-widget/spline.cpp
+++ b/spline-widget/spline.cpp
@@ -10,31 +10,29 @@
#include <QMutexLocker>
#include <QCoreApplication>
#include <QPointF>
-#include <QList>
-#include <QtAlgorithms>
-#include <QtAlgorithms>
#include <QSettings>
-#include <QPixmap>
#include <QString>
#include <algorithm>
#include <cmath>
#include <QDebug>
+constexpr int spline::value_count;
+
void spline::setTrackingActive(bool blnActive)
{
activep = blnActive;
}
-spline::spline() : spline(0, 0)
+spline::spline() : spline(0, 0, "")
{
}
void spline::removeAllPoints()
{
- QMutexLocker foo(&_mutex);
- cur.input.clear();
- reload();
+ QMutexLocker l(&_mutex);
+ s->points = points_t();
+ update_interp_data();
}
void spline::setMaxInput(qreal max_input)
@@ -61,30 +59,28 @@ qreal spline::maxOutput() const
return max_y;
}
-spline::spline(qreal maxx, qreal maxy) :
+// todo try non-recursive mtx
+spline::spline(qreal maxx, qreal maxy, const QString& name) :
+ data(value_count, -1.f),
_mutex(QMutex::Recursive),
- max_x(0),
- max_y(0),
+ max_x(maxx),
+ max_y(maxy),
activep(false)
{
- setMaxInput(maxx);
- setMaxOutput(maxy);
- if (cur.input.size() == 0)
- cur.input.push_back(QPointF(maxx, maxy));
- reload();
+ set_bundle(options::make_bundle(name));
}
-float spline::getValue(float x)
+float spline::getValue(double x)
{
QMutexLocker foo(&_mutex);
- float q = x * precision();
+ float q = float(x * precision(s->points));
int xi = (int)q;
float yi = getValueInternal(xi);
float yiplus1 = getValueInternal(xi+1);
float f = (q-xi);
float ret = yiplus1 * f + yi * (1.0f - f); // at least do a linear interpolation.
last_input_value.setX(std::fabs(x));
- last_input_value.setY(std::fabs(ret));
+ last_input_value.setY(double(std::fabs(ret)));
return ret;
}
@@ -100,244 +96,187 @@ float spline::getValueInternal(int x)
float sign = x < 0 ? -1 : 1;
x = abs(x);
float ret;
- unsigned sz = cur.data.size();
- if (sz == 0)
- ret = 0;
- else
- ret = cur.data[std::min(unsigned(x), sz-1u)];
+ ret = data[std::min(unsigned(x), unsigned(value_count)-1u)];
return ret * sign;
}
-static QPointF ensureInBounds(const QList<QPointF>& points, int i)
+void spline::add_lone_point()
+{
+ points_t points;
+ points.push_back(QPointF(max_x, max_y));
+
+ s->points = points;
+}
+
+QPointF spline::ensure_in_bounds(const QList<QPointF>& points, int i)
{
- int siz = points.size();
- if (siz == 0 || i < 0)
+ const int sz = points.size();
+
+ if (i < 0 || sz == 0)
return QPointF(0, 0);
- if (siz > i)
+ if (i < sz)
return points[i];
- return points[siz - 1];
+ return points[sz - 1];
}
-static bool sortFn(const QPointF& one, const QPointF& two)
+bool spline::sort_fn(const QPointF& one, const QPointF& two)
{
return one.x() < two.x();
}
-void spline::reload()
+void spline::update_interp_data()
{
- if (cur.input.size())
- {
- std::stable_sort(cur.input.begin(), cur.input.end(), sortFn);
+ points_t points = s->points;
- QList<QPointF> input = cur.input;
- auto& data = cur.data;
+ if (points.size() == 0)
+ points.append(QPointF(max_x, max_y));
- data = std::vector<float>(value_count);
- const float mult = precision();
- const unsigned mult_ = unsigned(mult * 30);
+ std::stable_sort(points.begin(), points.end(), sort_fn);
- const unsigned sz = data.size();
+ const double mult = precision(points);
+ const double mult_ = mult * 30;
- for (unsigned i = 0; i < sz; i++)
- data[i] = -1;
+ for (unsigned i = 0; i < value_count; i++)
+ data[i] = -1;
- if (input.size() == 1 && input[0].x() > 1e-2)
+ if (points.size() == 1)
+ {
+ const double x = points[0].x();
+ const double y = points[0].y();
+ const int max = clamp(int(x * precision(points)), 0, value_count-1);
+ for (int k = 0; k <= max; k++)
{
- const float x = float(input[0].x());
- const float y = float(input[0].y());
- const unsigned max = unsigned(x * mult);
- for (unsigned k = 0; k < max; k++) {
- if (k < sz)
- data[k] = y * k / max;
- }
+ if (k < value_count)
+ data[unsigned(k)] = float(y * k / max);
}
- else if (input[0].x() > 1e-2)
- input.prepend(QPointF(0, 0));
+ }
+ else
+ {
+ if (points[0].x() > 1e-2)
+ points.push_front(QPointF(0, 0));
- for (int i = 0; i < int(sz); i++)
+ for (int i = 0; i < points.size(); i++)
{
- const QPointF p0 = ensureInBounds(input, i - 1);
- const QPointF p1 = ensureInBounds(input, i);
- const QPointF p2 = ensureInBounds(input, i + 1);
- const QPointF p3 = ensureInBounds(input, i + 2);
+ const QPointF p0 = ensure_in_bounds(points, i - 1);
+ const QPointF p1 = ensure_in_bounds(points, i);
+ const QPointF p2 = ensure_in_bounds(points, i + 1);
+ const QPointF p3 = ensure_in_bounds(points, i + 2);
- const float p0_x = p0.x(), p1_x = p1.x(), p2_x = p2.x(), p3_x = p3.x();
- const float p0_y = p0.y(), p1_y = p1.y(), p2_y = p2.y(), p3_y = p3.y();
+ const double p0_x = p0.x(), p1_x = p1.x(), p2_x = p2.x(), p3_x = p3.x();
+ const double p0_y = p0.y(), p1_y = p1.y(), p2_y = p2.y(), p3_y = p3.y();
// multiplier helps fill in all the x's needed
- const unsigned end = std::min(sz, unsigned(p2_x * mult_));
- const unsigned start = unsigned(p1_x * mult);
+ const unsigned end = std::min(unsigned(value_count), unsigned(p2_x * mult_));
+ const unsigned start = std::max(0u, unsigned(p1_x * mult));
for (unsigned j = start; j < end; j++)
{
- const float t = (j - start) / (float) (end - start);
- const float t2 = t*t;
- const float t3 = t*t*t;
-
- const int x = .5f * ((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)
- * mult;
-
- const float y = .5f * ((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 < (int)sz)
- data[x] = y;
+ const double t = (j - start) / (double) (end - start);
+ const double t2 = t*t;
+ const double t3 = t*t*t;
+
+ const int x = int(.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)
+ * mult);
+
+ const float y = float(.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 < value_count)
+ data[unsigned(x)] = y;
}
}
+ }
- float last = 0;
- for (unsigned i = 0; i < sz; i++)
- {
- if (data[i] < 0)
- data[i] = last;
- last = data[i];
- }
+ float last = 0;
+ for (unsigned i = 0; i < unsigned(value_count); i++)
+ {
+ if (data[i] < 0)
+ data[i] = last;
+ last = data[i];
}
- else
- cur.data.clear();
}
void spline::removePoint(int i)
{
QMutexLocker foo(&_mutex);
- if (i >= 0 && i < cur.input.size())
+
+ points_t points = s->points;
+
+ if (i >= 0 && i < points.size())
{
- cur.input.removeAt(i);
- reload();
+ points.erase(points.begin() + i);
+ s->points = points;
+ update_interp_data();
}
}
void spline::addPoint(QPointF pt)
{
QMutexLocker foo(&_mutex);
- cur.input.append(pt);
- reload();
- std::stable_sort(cur.input.begin(), cur.input.end(), sortFn);
+
+ points_t points = s->points;
+ points.push_back(pt);
+ std::stable_sort(points.begin(), points.end(), sort_fn);
+ s->points = points;
+ update_interp_data();
}
void spline::movePoint(int idx, QPointF pt)
{
QMutexLocker foo(&_mutex);
- if (idx >= 0 && idx < cur.input.size())
+
+ points_t points = s->points;
+
+ if (idx >= 0 && idx < points.size())
{
- cur.input[idx] = pt;
+ points[idx] = pt;
// we don't allow points to be reordered, but sort due to possible caller logic error
- std::stable_sort(cur.input.begin(), cur.input.end(), sortFn);
- reload();
+ std::stable_sort(points.begin(), points.end(), sort_fn);
+ s->points = points;
+ update_interp_data();
}
}
-const QList<QPointF> spline::getPoints()
+QList<QPointF> spline::getPoints() const
{
QMutexLocker foo(&_mutex);
- return cur.input;
+ return s->points;
}
-void spline::invalidate_unsaved_settings()
+void spline::reload()
{
- QMutexLocker foo(&_mutex);
- cur = saved;
- reload();
+ if (s && s->b)
+ s->b->reload();
}
-void spline::loadSettings(QSettings& settings, const QString& title)
+void spline::save()
{
- 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).toDouble(),
- settings.value(QString("point-%1-y").arg(i), 0).toDouble());
- if (newPoint.x() > max_x)
- newPoint.setX(max_x);
- if (newPoint.y() > max_y)
- newPoint.setY(max_y);
- points.append(newPoint);
- }
-
- settings.endGroup();
-
- if (max == 0)
- points.append(QPointF(maxInput(), maxOutput()));
-
- cur.input = points;
- reload();
- saved = cur;
+ if (s && s->b)
+ s->b->save();
}
-bool spline::State::operator==(const State& other) const
+void spline::set_bundle(bundle b)
{
- if (input.size() != other.input.size())
- return false;
-
- const int sz = input.size();
-
- using std::fabs;
+ if (b)
+ s = std::unique_ptr<settings>(new settings(b));
+ else
+ s = std::unique_ptr<settings>(new settings(options::make_bundle("")));
- for (int i = 0; i < sz; i++)
- {
- const qreal eps = 1e-3;
+ last_input_value = QPointF(0, 0);
+ activep = false;
- if (fabs(input[i].x() - other.input[i].x()) > eps ||
- fabs(input[i].y() - other.input[i].y()) > eps)
- {
- return false;
- }
- }
- return true;
+ update_interp_data();
}
-void spline::saveSettings(QSettings& settings, const QString& title)
+int spline::precision(const QList<QPointF>& points) const
{
- QMutexLocker foo(&_mutex);
-
- if (cur == saved)
- return;
+ if (points.size())
+ return int(value_count / clamp(points[points.size() - 1].x(), 1, max_x));
- qDebug() << "spline-widget: saving" << title;
-
- settings.beginGroup(QStringLiteral("Curves-%1").arg(title));
-
- if (cur.input.size() == 0)
- cur.input.push_back(QPointF(max_x, max_y));
-
- const 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), cur.input[i].x());
- settings.setValue(QString("point-%1-y").arg(i), cur.input[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));
- }
-
- saved = cur;
-
- settings.endGroup();
-}
-
-
-int spline::precision() const
-{
- if (cur.input.size())
- return (value_count-1) / std::max<float>(1.f, (cur.input[cur.input.size() - 1].x()));
- return 1;
+ return value_count / clamp(int(max_x), 1, value_count);
}
diff --git a/spline-widget/spline.hpp b/spline-widget/spline.hpp
index 26775402..4f6531b9 100644
--- a/spline-widget/spline.hpp
+++ b/spline-widget/spline.hpp
@@ -8,15 +8,16 @@
#pragma once
-#include <QtGlobal>
-#include <QList>
+#include <QObject>
#include <QPointF>
#include <QString>
-#include <QSettings>
#include <QMutex>
#include <vector>
#include <limits>
+#include <memory>
#include "compat/qcopyable-mutex.hpp"
+#include "options/options.hpp"
+using namespace options;
#ifdef BUILD_spline_widget
# define SPLINE_WIDGET_EXPORT Q_DECL_EXPORT
@@ -24,47 +25,72 @@
# define SPLINE_WIDGET_EXPORT Q_DECL_IMPORT
#endif
-class SPLINE_WIDGET_EXPORT spline
+class SPLINE_WIDGET_EXPORT spline final
{
private:
- int precision() const;
- void reload();
- float getValueInternal(int x);
-
- struct State
+ struct settings
{
- QList<QPointF> input;
- std::vector<float> data;
- bool operator==(const State& s) const;
+ bundle b;
+ value<QList<QPointF>> points;
+ settings(bundle b) :
+ b(b),
+ points(b, "points", QList<QPointF>())
+ {}
};
+ ptr<settings> s;
+
+ std::vector<float> data;
+ using interp_data_t = decltype(data);
+
+ static constexpr int value_count = 10000;
+
+ int precision(const QList<QPointF>& points) const;
+ void update_interp_data();
+ float getValueInternal(int x);
+ void add_lone_point();
+ static bool sort_fn(const QPointF& one, const QPointF& two);
+
+ static QPointF ensure_in_bounds(const QList<QPointF>& points, int i);
+
MyMutex _mutex;
QPointF last_input_value;
- State cur, saved;
qreal max_x, max_y;
volatile bool activep;
- static constexpr int value_count = 10000;
+ template<typename t, typename u, typename w>
+ static inline auto clamp(t val, u min, w max) -> decltype (val * min * max)
+ {
+ if (val > max)
+ return max;
+ if (val < min)
+ return min;
+ return val;
+ }
+
public:
+ void reload();
+ void save();
+ void set_bundle(bundle b);
+
qreal maxInput() const;
qreal maxOutput() const;
spline();
- spline(qreal maxx, qreal maxy);
+ spline(qreal maxx, qreal maxy, const QString& name);
- float getValue(float x);
+ float getValue(double x);
bool getLastPoint(QPointF& point);
void removePoint(int i);
void removeAllPoints();
void addPoint(QPointF pt);
void movePoint(int idx, QPointF pt);
- const QList<QPointF> getPoints();
+ QList<QPointF> getPoints() const;
void setMaxInput(qreal MaxInput);
void setMaxOutput(qreal MaxOutput);
- void saveSettings(QSettings& settings, const QString& title);
- void loadSettings(QSettings& settings, const QString& title);
- void invalidate_unsaved_settings();
-
void setTrackingActive(bool blnActive);
+ bundle get_bundle() { return s->b; }
+
+ using points_t = decltype(s->points.get());
};