summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tracker-tobii-eyex/CMakeLists.txt6
-rw-r--r--tracker-tobii-eyex/tobii-eyex-dialog.cpp25
-rw-r--r--tracker-tobii-eyex/tobii-eyex-dialog.ui210
-rw-r--r--tracker-tobii-eyex/tobii-eyex.cpp173
-rw-r--r--tracker-tobii-eyex/tobii-eyex.hpp22
5 files changed, 228 insertions, 208 deletions
diff --git a/tracker-tobii-eyex/CMakeLists.txt b/tracker-tobii-eyex/CMakeLists.txt
index cfbe0160..20f4badd 100644
--- a/tracker-tobii-eyex/CMakeLists.txt
+++ b/tracker-tobii-eyex/CMakeLists.txt
@@ -1,7 +1,7 @@
if(WIN32)
set(SDK_TOBII_EYEX "" CACHE PATH "")
if(SDK_TOBII_EYEX)
- opentrack_boilerplate(opentrack-tracker-tobii-eyex NO-INSTALL)
+ opentrack_boilerplate(opentrack-tracker-tobii-eyex)
target_link_libraries(opentrack-tracker-tobii-eyex opentrack-spline-widget)
set(tobii-libdir ${SDK_TOBII_EYEX}/lib/x86/)
set(tobii-dll ${tobii-libdir}/Tobii.EyeX.Client.dll)
@@ -13,9 +13,7 @@ if(WIN32)
set(tobii-incdir ${SDK_TOBII_EYEX}/include/eyex)
target_include_directories(opentrack-tracker-tobii-eyex SYSTEM PUBLIC ${tobii-incdir})
- if(FALSE)
- install(FILES ${tobii-dll} DESTINATION ${opentrack-hier-pfx} ${opentrack-perms})
- endif()
+ install(FILES ${tobii-dll} DESTINATION ${opentrack-hier-pfx} ${opentrack-perms})
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
file(TO_CMAKE_PATH "$ENV{SystemRoot}" sysroot)
if (IS_DIRECTORY "${sysroot}/SysWOW64")
diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.cpp b/tracker-tobii-eyex/tobii-eyex-dialog.cpp
index bb9ffcea..7f69fa16 100644
--- a/tracker-tobii-eyex/tobii-eyex-dialog.cpp
+++ b/tracker-tobii-eyex/tobii-eyex-dialog.cpp
@@ -11,6 +11,31 @@ tobii_eyex_dialog::tobii_eyex_dialog()
ui.tracking_mode->addItem("Absolute", tobii_absolute);
tie_setting(s.mode, ui.tracking_mode);
+
+ ui.relative_mode_gain->setConfig(&rs.acc_mode_spline);
+ ui.relative_mode_gain->set_preview_only(true);
+
+ tie_setting(rs.dz_len, ui.deadzone);
+ tie_setting(rs.expt_slope, ui.exponent);
+ tie_setting(rs.expt_len, ui.exponent_len);
+ tie_setting(rs.expt_norm, ui.exponent_norm);
+
+ tie_setting(rs.log_slope, ui.log_base);
+ tie_setting(rs.log_len, ui.log_len);
+ tie_setting(rs.log_norm, ui.log_norm);
+
+ connect(rs.b.get(), &bundle_::changed, this, [this]() { rs.make_spline(); }, Qt::QueuedConnection);
+
+ // todo add specialization for label with traits
+#if 0
+ tie_setting(rs.dz_len, ui.deadzone_label);
+ tie_setting(rs.expt_slope, ui.exponent_label);
+ tie_setting(rs.expt_len, ui.exponent_len_label);
+ tie_setting(rs.expt_norm, ui.exponent_norm_label);
+ tie_setting(rs.log_slope, ui.log_base_label);
+ tie_setting(rs.log_len, ui.log_len_label);
+ tie_setting(rs.log_norm, ui.log_norm_label);
+#endif
}
void tobii_eyex_dialog::do_ok()
diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.ui b/tracker-tobii-eyex/tobii-eyex-dialog.ui
index 1a85f417..7a8c92aa 100644
--- a/tracker-tobii-eyex/tobii-eyex-dialog.ui
+++ b/tracker-tobii-eyex/tobii-eyex-dialog.ui
@@ -179,8 +179,8 @@
<property name="verticalSpacing">
<number>3</number>
</property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_11">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -188,7 +188,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Speed</string>
+ <string>Deadzone</string>
</property>
</widget>
</item>
@@ -208,21 +208,8 @@
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Deadzone</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="deadzone_label">
+ <item row="2" column="1">
+ <widget class="QLabel" name="exponent_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -256,21 +243,27 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_10">
+ <item row="2" column="2">
+ <widget class="QSlider" name="exponent">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Exponent</string>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QLabel" name="exponent_label">
+ <item row="1" column="1">
+ <widget class="QLabel" name="deadzone_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -285,27 +278,34 @@
</property>
</widget>
</item>
- <item row="2" column="2">
- <widget class="QSlider" name="exponent">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_11">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <property name="text">
+ <string>Speed</string>
</property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Log segment length</string>
</property>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_5">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -313,7 +313,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Exponential length</string>
+ <string>Exponent</string>
</property>
</widget>
</item>
@@ -333,8 +333,21 @@
</property>
</widget>
</item>
- <item row="3" column="2">
- <widget class="QSlider" name="exponent_len">
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Exponent segment length</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QSlider" name="log_len">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -352,8 +365,8 @@
</property>
</widget>
</item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_7">
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -361,12 +374,12 @@
</sizepolicy>
</property>
<property name="text">
- <string>Linear coefficient</string>
+ <string>Log slope</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QLabel" name="linear_c_label">
+ <item row="6" column="1">
+ <widget class="QLabel" name="log_base_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -381,8 +394,8 @@
</property>
</widget>
</item>
- <item row="4" column="2">
- <widget class="QSlider" name="linear_c">
+ <item row="6" column="2">
+ <widget class="QSlider" name="log_base">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -400,21 +413,27 @@
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_6">
+ <item row="0" column="2">
+ <widget class="QSlider" name="speed">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Linear length</string>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
<item row="5" column="1">
- <widget class="QLabel" name="linear_len_label">
+ <widget class="QLabel" name="log_len_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -429,56 +448,40 @@
</property>
</widget>
</item>
- <item row="5" column="2">
- <widget class="QSlider" name="linear_len">
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_6">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Exponent norm</string>
</property>
</widget>
</item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_8">
+ <item row="4" column="2">
+ <widget class="QSlider" name="exponent_norm">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Logarithm base</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QLabel" name="log_base_label">
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>0</height>
- </size>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- <property name="text">
- <string>0</string>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="tickInterval">
+ <number>25</number>
</property>
</widget>
</item>
- <item row="6" column="2">
- <widget class="QSlider" name="log_base">
+ <item row="3" column="2">
+ <widget class="QSlider" name="exponent_len">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -496,21 +499,24 @@
</property>
</widget>
</item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_9">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="4" column="1">
+ <widget class="QLabel" name="exponent_norm_label">
+ <property name="minimumSize">
+ <size>
+ <width>24</width>
+ <height>0</height>
+ </size>
</property>
<property name="text">
- <string>Logarithm coefficient</string>
+ <string>0</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
- <widget class="QLabel" name="log_c_label">
+ <widget class="QLabel" name="log_norm_label">
<property name="minimumSize">
<size>
<width>24</width>
@@ -526,7 +532,7 @@
</widget>
</item>
<item row="7" column="2">
- <widget class="QSlider" name="log_c">
+ <widget class="QSlider" name="log_norm">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
@@ -544,22 +550,16 @@
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="QSlider" name="speed">
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_12">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
- </property>
- <property name="tickInterval">
- <number>25</number>
+ <property name="text">
+ <string>Log norm</string>
</property>
</widget>
</item>
diff --git a/tracker-tobii-eyex/tobii-eyex.cpp b/tracker-tobii-eyex/tobii-eyex.cpp
index 74c31240..1a2f922b 100644
--- a/tracker-tobii-eyex/tobii-eyex.cpp
+++ b/tracker-tobii-eyex/tobii-eyex.cpp
@@ -6,6 +6,8 @@
#include <vector>
#include <algorithm>
#include <iterator>
+#include <utility>
+#include <numeric>
#include <QDebug>
#include <QMutexLocker>
#include <QMessageBox>
@@ -36,51 +38,80 @@ static inline tobii_eyex_tracker& to_self(TX_USERPARAM param)
return *reinterpret_cast<tobii_eyex_tracker*>(param);
}
-template<typename t>
-static constexpr t clamp(t datum, t min, t max)
+// there's an underflow in spline code, can't use 1e0
+static constexpr const double spline_max = 1e2;
+
+void rel_settings::make_spline_(part* functors, unsigned len)
{
- return ((datum > max) ? max : ((datum < min) ? min : datum));
+ acc_mode_spline.removeAllPoints();
+
+ double lastx = 0, lasty = 0;
+
+ using std::accumulate;
+
+ const double inv_norm_y = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.norm; });
+ const double inv_norm_x = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.len; });
+
+ for (unsigned k = 0; k < len; k++)
+ {
+ part& fun = functors[k];
+
+ const double xscale = fun.len * spline_max * inv_norm_x;
+ const double maxx = fun.f(1);
+ const double yscale = fun.norm * spline_max * inv_norm_y * (maxx < 1e-3 ? 0 : 1./maxx);
+
+ for (unsigned i = 0; i <= fun.nparts; i++)
+ {
+ const double x = lastx + (fun.nparts == 0 ? 1 : i) / (1.+fun.nparts) * xscale;
+ const double y = lasty + clamp(fun.f(x) * yscale, 0, spline_max);
+ qDebug() << k << i << x << y;
+ acc_mode_spline.addPoint(x, y);
+ }
+
+ lastx += xscale;
+ lasty += yscale;
+ }
}
-void rel_settings::draw_spline()
+/*
+ def plot(f):
+ rng = arange(-1 + .01, 1, 1e-4)
+ plt.plot(rng, map(f, rng))
+*/
+
+double rel_settings::gain(double value)
{
- spline& spline = acc_mode_spline;
+ return acc_mode_spline.get_value_no_save(value * spline_max) / spline_max;
+}
- spline.removeAllPoints();
+void rel_settings::make_spline()
+{
+ const double log_c = 1./std::log(log_slope());
- static constexpr float std_norm_expt = 1.f/3;
- const float norm_expt = std_norm_expt * float(expt_norm->cur());
- static constexpr float std_norm_lin = 2.f/3;
- const float norm_lin = clamp((1-norm_expt) * lin_norm->cur() * std_norm_lin, 0., 1.);
+ part functors[]
+ {
+ { 1, dz_len(), 0, [](double) { return 0; } },
+ { 5, expt_len(), expt_norm(), [=](double x) { return std::pow(x, expt_slope()); } },
+ { 7, 1 - dz_len() - expt_len() - log_len(), std::max(0., 1 - expt_norm() - log_norm()), [](double x) { return x; } },
+ { 7, log_len(), log_norm(), [=](double x) { return std::log(1+x)*log_c; } },
+ };
+ make_spline_(functors, std::distance(std::begin(functors), std::end(functors)));
}
rel_settings::rel_settings() :
opts("tobii-eyex-relative-mode"),
- speed(b, "speed", s(5, .1, 10)),
- dz_end_pt(b, "deadzone-length", s(4, 0, 15)),
- expt_slope(b, "exponent-slope", s(1.5, 1.25, 3)),
- expt_norm(b, "exponent-norm", s(1, .25, 4)),
- lin_norm(b, "linear-norm", s(1, .25, 4)),
+ speed(b, "speed", s(3, .1, 10)),
+ dz_len(b, "deadzone-length", s(.04, 0, .2)),
+ expt_slope(b, "exponent-slope", s(1.75, 1.25, 3)),
+ expt_len(b, "exponent-length", s(.25, 0, .5)),
+ expt_norm(b, "exponent-norm", s(.3, .1, .5)),
+ log_slope(b, "log-slope", s(2.75, 1.25, 10)),
+ log_len(b, "log-len", s(.1, 0, .2)),
+ log_norm(b, "log-norm", s(.1, .05, .3)),
acc_mode_spline(100, 100, "")
{
- QObject::connect(&dz_end_pt,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&expt_slope,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&expt_norm,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- QObject::connect(&lin_norm,
- static_cast<void(base_value::*)(const slider_value&) const>(&base_value::valueChanged),
- this,
- &rel_settings::draw_spline);
- draw_spline();
+ make_spline();
}
tobii_eyex_tracker::tobii_eyex_tracker() :
@@ -287,67 +318,16 @@ void tobii_eyex_tracker::start_tracker(QFrame*)
dbg_verbose("api initialized");
}
-// the gain function was prototyped in python with jupyter qtconsole.
-// you can use qtconsole's inline matplotlib support to see the gain function.
-// the `piecewise' function assumes monotonic growth or constant value for all functions.
-/*
-
-from math import *
-from itertools import izip
-import matplotlib
-import matplotlib.pyplot as plt
-
-try:
- import IPython
- IPython.get_ipython().magic(u'matplotlib inline')
-except:
- pass
-
-def frange(from_, to_, step_=1e-4):
- i = from_
- while True:
- yield i
- i += step_
- if i >= to_:
- break
-
-def plot_fn(fn, from_=0., to_=1., step=None):
- if step is None:
- step = max(1e-4, (to_-from_)*1e-4)
- xs = [i for i in frange(from_, to_, step)]
- plt.plot(xs, map(fn, xs))
-
-def piecewise(x, funs, bounds):
- y = 0.
- last_bound = 0.
- norm = 0.
- for fun in funs:
- norm += fun(1.)
- for fun, bound in izip(funs, bounds):
- if x > bound:
- y += fun(1.)
- else:
- b = bound - last_bound
- x_ = (x - last_bound) / b
- y += fun(x_)
- break
- last_bound = bound
- return y / norm
-
-def f(x): return x**1.75
-def g(x): return 1.75*1.75*x
-def h(x): return log(1+x)/log(2.5)
-def zero(x): return 0.
-
-plot_fn(lambda x: piecewise(x, [zero, f, g, h], [.05, .25, .7, 1.]))
-
-*/
-
tobii_eyex_tracker::num tobii_eyex_tracker::gain(num x_)
{
return 1;
}
+static inline double signum(double x)
+{
+ return !(x < 0) - (x < 0);
+}
+
void tobii_eyex_tracker::data(double* data)
{
TX_REAL px, py, dw, dh, x_, y_;
@@ -378,20 +358,21 @@ void tobii_eyex_tracker::data(double* data)
{
const double dt = t.elapsed_seconds();
t.start();
- // XXX TODO make slider
- static constexpr double v = 300;
- const double x = gain(x_);
- const double y = gain(y_);
+ using std::fabs;
+
+ static constexpr double max_yaw = 45, max_pitch = 30;
+ static constexpr double c_yaw = 3;
+ static constexpr double c_pitch = c_yaw * max_pitch / max_yaw;
- const double yaw_delta = (x * v) * dt;
- const double pitch_delta = (y * -v) * dt;
+ const double yaw_delta = gain(fabs(x_)) * signum(x_) * c_yaw * dt;
+ const double pitch_delta = gain(fabs(y_)) * signum(y_) * c_pitch * dt;
yaw += yaw_delta;
pitch += pitch_delta;
- yaw = clamp(yaw, -180., 180.);
- pitch = clamp(pitch, -60., 60.);
+ yaw = clamp(yaw, -max_yaw, max_yaw);
+ pitch = clamp(pitch, -max_pitch, max_pitch);
}
if (do_center)
diff --git a/tracker-tobii-eyex/tobii-eyex.hpp b/tracker-tobii-eyex/tobii-eyex.hpp
index aeac4d89..68acb25c 100644
--- a/tracker-tobii-eyex/tobii-eyex.hpp
+++ b/tracker-tobii-eyex/tobii-eyex.hpp
@@ -18,9 +18,11 @@ using namespace options;
#include "spline-widget/spline.hpp"
#include "spline-widget/spline-widget.hpp"
+#include <functional>
#include <atomic>
#include <QObject>
#include <QMutex>
+#include <QTimer>
enum tobii_mode
{
@@ -31,13 +33,27 @@ enum tobii_mode
class rel_settings final : public QObject, public opts
{
Q_OBJECT
+
+ using functor = std::function<double(double)>;
+
+ struct part
+ {
+ int nparts;
+ double len, norm;
+ functor f;
+ };
+
+ void make_spline_(part* functors, unsigned len);
+
public:
using s = slider_value;
- value<slider_value> speed, dz_end_pt, expt_slope, expt_norm, lin_norm;
+ value<slider_value> speed, dz_len, expt_slope, expt_len, expt_norm, log_slope, log_len, log_norm;
spline acc_mode_spline;
rel_settings();
-private slots:
- void draw_spline();
+ double gain(double value);
+
+public slots:
+ void make_spline();
};
struct settings final : public opts