fix(color): Invalid custom curves + layout updates (#2973)
* Layout updates and bug fixes for curve editor. - Fix issue 2972 where an invalid curve could be created - Use vertical layout or list of points - Add border to preview to better show end points - Fix issue where preview was redrawn very frequently - Better organisation of curve edit classes * Fix to refresh curve preview on input edit page when parameters changed.
This commit is contained in:
@@ -42,53 +42,60 @@ IMPL_LZ4_BITMAP(LBM_CURVE_POINT);
|
||||
IMPL_LZ4_BITMAP(LBM_CURVE_POINT_CENTER);
|
||||
IMPL_LZ4_BITMAP(LBM_CURVE_COORD_SHADOW);
|
||||
|
||||
Curve::Curve(Window * parent, const rect_t & rect, std::function<int(int)> function, std::function<int()> position):
|
||||
Window(parent, rect, OPAQUE),
|
||||
function(std::move(function)),
|
||||
position(std::move(position))
|
||||
{
|
||||
}
|
||||
|
||||
void Curve::drawBackground(BitmapBuffer * dc)
|
||||
{
|
||||
dc->clear(COLOR_THEME_PRIMARY2);
|
||||
|
||||
// Axis
|
||||
dc->drawSolidHorizontalLine(0, height()/2, width(), COLOR_THEME_SECONDARY2);
|
||||
dc->drawSolidVerticalLine(width()/2, 0, height(), COLOR_THEME_SECONDARY2);
|
||||
dc->drawSolidHorizontalLine(dx, dy+dh/2, dw, COLOR_THEME_SECONDARY2);
|
||||
dc->drawSolidVerticalLine(dx+dw/2, dy, dh, COLOR_THEME_SECONDARY2);
|
||||
|
||||
// Extra lines
|
||||
dc->drawVerticalLine(width()/4, 0, height(), STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawVerticalLine(width()*3/4, 0, height(), STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawHorizontalLine(0, height()/4, width(), STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawHorizontalLine(0, height()*3/4, width(), STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawVerticalLine(dx+dw/4, dy, dh, STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawVerticalLine(dx+dw*3/4, dy, dh, STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawHorizontalLine(dx, dy+dh/4, dw, STASHED, COLOR_THEME_SECONDARY2);
|
||||
dc->drawHorizontalLine(dx, dy+dh*3/4, dw, STASHED, COLOR_THEME_SECONDARY2);
|
||||
|
||||
// Outside border
|
||||
dc->drawSolidRect(0, 0, width(), height(), 1, COLOR_THEME_SECONDARY2);
|
||||
dc->drawSolidRect(dx, dy, dw, dh, 1, COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
|
||||
coord_t Curve::getPointX(int x) const
|
||||
{
|
||||
return limit<coord_t>(0,
|
||||
width() / 2 + divRoundClosest(x * width() / 2, RESX),
|
||||
width() - 1);
|
||||
return dx + limit<coord_t>(0,
|
||||
dw / 2 + divRoundClosest(x * dw / 2, RESX),
|
||||
dw - 1);
|
||||
}
|
||||
|
||||
coord_t Curve::getPointY(int y) const
|
||||
{
|
||||
return limit<coord_t>(0,
|
||||
height() / 2 - divRoundClosest(y * height() / 2, RESX),
|
||||
height() - 1);
|
||||
return dy + limit<coord_t>(0,
|
||||
dh / 2 - divRoundClosest(y * dh / 2, RESX),
|
||||
dh - 1);
|
||||
}
|
||||
|
||||
void Curve::drawCurve(BitmapBuffer * dc)
|
||||
{
|
||||
auto prev = (coord_t) -1;
|
||||
|
||||
for (int x = 0; x < width(); x++) {
|
||||
coord_t y = getPointY(function(divRoundClosest((x - width() / 2) * RESX, width() / 2)));
|
||||
for (int x = 0; x < dw; x++) {
|
||||
coord_t y = getPointY(function(divRoundClosest((x - dw / 2) * RESX, dw / 2)));
|
||||
if (prev >= 0) {
|
||||
if (prev < y) {
|
||||
for (int tmp = prev; tmp <= y; tmp++) {
|
||||
dc->drawBitmapPattern(x - 2, tmp - 2, LBM_POINT, COLOR_THEME_SECONDARY1);
|
||||
dc->drawBitmapPattern(dx + x - 2, tmp - 2, LBM_POINT, COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int tmp = y; tmp <= prev; tmp++) {
|
||||
dc->drawBitmapPattern(x - 2, tmp - 2, LBM_POINT, COLOR_THEME_SECONDARY1);
|
||||
dc->drawBitmapPattern(dx + x - 2, tmp - 2, LBM_POINT, COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,8 +112,8 @@ void Curve::drawPosition(BitmapBuffer * dc)
|
||||
coord_t y = getPointY(valueY);
|
||||
|
||||
// the 2 lines
|
||||
dc->drawSolidHorizontalLine(0, y, width(), COLOR_THEME_ACTIVE);
|
||||
dc->drawSolidVerticalLine(x, 0, height(), COLOR_THEME_ACTIVE);
|
||||
dc->drawSolidHorizontalLine(dx, y, dw, COLOR_THEME_ACTIVE);
|
||||
dc->drawSolidVerticalLine(x, dy, dh, COLOR_THEME_ACTIVE);
|
||||
|
||||
// the point (white inside)
|
||||
dc->drawBitmapPattern(x-4, y-4, LBM_CURVE_POINT, COLOR_THEME_ACTIVE);
|
||||
@@ -114,8 +121,8 @@ void Curve::drawPosition(BitmapBuffer * dc)
|
||||
|
||||
char coords[16];
|
||||
strAppendSigned(strAppend(strAppendSigned(coords, calcRESXto100(valueX)), ","), calcRESXto100(valueY));
|
||||
dc->drawSolidFilledRect(10, 11, 1 + getTextWidth(coords, 0, FONT(XS)), 17, COLOR_THEME_ACTIVE);
|
||||
dc->drawText(11, 10, coords, FONT(XS) | COLOR_THEME_PRIMARY2);
|
||||
dc->drawSolidFilledRect(10, 11, 2 + getTextWidth(coords, 0, FONT(XS)), 17, COLOR_THEME_ACTIVE);
|
||||
dc->drawText(11, 10, coords, FONT(XS) | COLOR_THEME_PRIMARY1);
|
||||
}
|
||||
|
||||
void Curve::drawPoint(BitmapBuffer * dc, const CurvePoint & point)
|
||||
@@ -129,6 +136,16 @@ void Curve::drawPoint(BitmapBuffer * dc, const CurvePoint & point)
|
||||
|
||||
void Curve::paint(BitmapBuffer * dc)
|
||||
{
|
||||
if (points.size() > 0) {
|
||||
dx = 4;
|
||||
dy = 4;
|
||||
} else {
|
||||
dx = 2;
|
||||
dy = 2;
|
||||
}
|
||||
dw = width() - dx * 2;
|
||||
dh = height() - dy * 2;
|
||||
|
||||
drawBackground(dc);
|
||||
drawCurve(dc);
|
||||
for (auto point: points) {
|
||||
@@ -150,3 +167,16 @@ void Curve::clearPoints()
|
||||
points.clear();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Curve::checkEvents()
|
||||
{
|
||||
if (position) {
|
||||
int pos = position();
|
||||
if (pos != lastPos) {
|
||||
lastPos = pos;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
Window::checkEvents();
|
||||
}
|
||||
|
||||
@@ -33,12 +33,7 @@ class Curve: public Window
|
||||
friend class CurveEdit;
|
||||
|
||||
public:
|
||||
Curve(Window * parent, const rect_t & rect, std::function<int(int)> function, std::function<int()> position=nullptr):
|
||||
Window(parent, rect, OPAQUE),
|
||||
function(std::move(function)),
|
||||
position(std::move(position))
|
||||
{
|
||||
}
|
||||
Curve(Window * parent, const rect_t & rect, std::function<int(int)> function, std::function<int()> position=nullptr);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
@@ -47,19 +42,7 @@ class Curve: public Window
|
||||
}
|
||||
#endif
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
// will always force a full window refresh
|
||||
if (position) {
|
||||
// int pos = position();
|
||||
// if (pos != lastPos) {
|
||||
// lastPos = pos;
|
||||
invalidate();
|
||||
// }
|
||||
}
|
||||
|
||||
Window::checkEvents();
|
||||
}
|
||||
void checkEvents() override;
|
||||
|
||||
void addPoint(const point_t & point, LcdFlags flags);
|
||||
|
||||
@@ -68,7 +51,9 @@ class Curve: public Window
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
protected:
|
||||
// int lastPos = 0;
|
||||
// Drawing rectangle position & size
|
||||
uint8_t dx, dy, dw, dh;
|
||||
int lastPos = 0;
|
||||
std::function<int(int)> function;
|
||||
std::function<int()> position;
|
||||
std::list<CurvePoint> points;
|
||||
|
||||
@@ -46,8 +46,9 @@ void CurveParam::value_changed(lv_event_t* e)
|
||||
param->update();
|
||||
}
|
||||
|
||||
CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref) :
|
||||
Window(parent, rect), ref(ref)
|
||||
CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref,
|
||||
std::function<void(int32_t)> setRefValue) :
|
||||
Window(parent, rect), ref(ref), setRefValue(setRefValue)
|
||||
{
|
||||
lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW_WRAP);
|
||||
lv_obj_set_style_pad_column(lvobj, lv_dpx(4), 0);
|
||||
@@ -66,17 +67,16 @@ CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref) :
|
||||
|
||||
// CURVE_REF_DIFF
|
||||
// CURVE_REF_EXPO
|
||||
value_edit = new GVarNumberEdit(this, rect_t{}, -100, 100,
|
||||
GET_SET_DEFAULT(ref->value));
|
||||
value_edit = new GVarNumberEdit(this, rect_t{}, -100, 100, GET_DEFAULT(ref->value), setRefValue);
|
||||
value_edit->setSuffix("%");
|
||||
|
||||
// CURVE_REF_FUNC
|
||||
func_choice = new Choice(this, rect_t{}, STR_VCURVEFUNC, 0, CURVE_BASE - 1,
|
||||
GET_SET_DEFAULT(ref->value));
|
||||
GET_DEFAULT(ref->value), setRefValue);
|
||||
|
||||
// CURVE_REF_CUSTOM
|
||||
cust_choice = new ChoiceEx(this, rect_t{}, -MAX_CURVES, MAX_CURVES,
|
||||
GET_SET_DEFAULT(ref->value));
|
||||
GET_DEFAULT(ref->value), setRefValue);
|
||||
cust_choice->setTextHandler([](int value) { return getCurveString(value); });
|
||||
cust_choice->set_lv_LongPressHandler(LongPressHandler, &(ref->value));
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ class CurveParam : public Window
|
||||
{
|
||||
// Curve
|
||||
CurveRef* ref;
|
||||
std::function<void(int32_t)> setRefValue;
|
||||
|
||||
// Controls
|
||||
GVarNumberEdit* value_edit;
|
||||
@@ -46,5 +47,6 @@ class CurveParam : public Window
|
||||
static void LongPressHandler(void* data);
|
||||
|
||||
public:
|
||||
CurveParam(Window* parent, const rect_t& rect, CurveRef* ref);
|
||||
CurveParam(Window* parent, const rect_t& rect, CurveRef* ref,
|
||||
std::function<void(int32_t)> setRefValue);
|
||||
};
|
||||
|
||||
@@ -26,100 +26,150 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
CurveDataEdit::CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index, CurveEdit * curveEdit) :
|
||||
FormGroup(parent, rect, FORM_FORWARD_FOCUS),
|
||||
index(index),
|
||||
curveEdit(curveEdit)
|
||||
static const lv_coord_t default_col_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t default_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
CurveDataEdit::CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index) :
|
||||
Window(parent, rect, FORM_FORWARD_FOCUS),
|
||||
index(index)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
#if LCD_W > LCD_H
|
||||
#define NUM_BTN_WIDTH 44
|
||||
#else
|
||||
#define NUM_BTN_WIDTH 48
|
||||
#endif
|
||||
|
||||
void CurveDataEdit::curvePointsRow(FormGroup::Line* parent, int start, int count, int curvePointsCount, bool isCustom)
|
||||
{
|
||||
static const lv_coord_t points_col_dsc[] = {11, LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
auto form = new FormWindow(parent, rect_t{});
|
||||
form->padAll(0);
|
||||
form->setFlexLayout();
|
||||
|
||||
FlexGridLayout grid(points_col_dsc, default_row_dsc, 4);
|
||||
|
||||
auto line = form->newLine(&grid);
|
||||
line->padAll(0);
|
||||
line->padLeft(4);
|
||||
line->padRight(4);
|
||||
lv_obj_set_grid_align(line->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
new StaticText(line, rect_t{}, "", CENTERED|COLOR_THEME_PRIMARY1);
|
||||
|
||||
// Point number
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto txt = new StaticText(line, rect_t{}, std::to_string(i + start + 1), 0, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY1);
|
||||
}
|
||||
|
||||
line = form->newLine(&grid);
|
||||
line->padAll(2);
|
||||
line->padLeft(4);
|
||||
line->padRight(4);
|
||||
lv_obj_set_grid_align(line->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
new StaticText(line, rect_t{}, "X", 0, CENTERED|COLOR_THEME_PRIMARY1);
|
||||
|
||||
int8_t* points = curveAddress(index);
|
||||
|
||||
// x value
|
||||
if (isCustom) {
|
||||
uint8_t i = 0;
|
||||
uint8_t c = count;
|
||||
if (start == 0) {
|
||||
new StaticText(line, rect_t{}, "-100", 0, CENTERED | COLOR_THEME_SECONDARY1);
|
||||
i += 1;
|
||||
}
|
||||
if ((start + count) == curvePointsCount) {
|
||||
c -= 1;
|
||||
}
|
||||
// Adjustable points for custom curves
|
||||
for (; i < c; i++) {
|
||||
uint8_t px = i + start - 1;
|
||||
numEditX[px] = new NumberEdit(
|
||||
line, rect_t{ 0, 0, NUM_BTN_WIDTH, 0 },
|
||||
(px == 0) ? -100 : points[curvePointsCount + px - 1],
|
||||
(px == curvePointsCount - 3) ? 100 : points[curvePointsCount + px + 1],
|
||||
GET_VALUE(points[curvePointsCount + px]),
|
||||
[=](int32_t newValue) {
|
||||
points[curvePointsCount + px] = newValue;
|
||||
if (px > 0) {
|
||||
numEditX[px-1]->setMax(newValue);
|
||||
}
|
||||
if (px < curvePointsCount - 3) {
|
||||
numEditX[px+1]->setMin(newValue);
|
||||
}
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
},
|
||||
0, RIGHT);
|
||||
lv_obj_set_grid_cell(numEditX[px]->getLvObj(), LV_GRID_ALIGN_CENTER, i+1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
}
|
||||
if ((start + count) == curvePointsCount) {
|
||||
new StaticText(line, rect_t{}, "100", 0, CENTERED | COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
new StaticText(line, rect_t{},
|
||||
std::to_string(-100 + (200 * (i + start)) / (curvePointsCount - 1)),
|
||||
0, CENTERED | COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
}
|
||||
|
||||
line = form->newLine(&grid);
|
||||
line->padAll(2);
|
||||
line->padLeft(4);
|
||||
line->padRight(4);
|
||||
lv_obj_set_grid_align(line->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
new StaticText(line, rect_t{}, "Y", 0, CENTERED|COLOR_THEME_PRIMARY1);
|
||||
|
||||
// y value
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
auto numedit = new NumberEdit(
|
||||
line, rect_t{ 0, 0, NUM_BTN_WIDTH, 0 },
|
||||
-100, 100, GET_VALUE(points[i+start]),
|
||||
[=](int32_t newValue) {
|
||||
points[i+start] = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
},
|
||||
0, RIGHT);
|
||||
lv_obj_set_grid_cell(numedit->getLvObj(), LV_GRID_ALIGN_CENTER, i+1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDataEdit::update()
|
||||
{
|
||||
clear();
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setLabelWidth(0);
|
||||
grid.setMarginRight(parent->width() - rect.w + 5);
|
||||
memset(numEditX, 0, sizeof(numEditX));
|
||||
|
||||
coord_t boxWidth = rect.w / 5;
|
||||
coord_t boxHeight = PAGE_LINE_HEIGHT;
|
||||
auto form = new FormWindow(this, rect_t{});
|
||||
form->padAll(0);
|
||||
form->padBottom(4);
|
||||
form->setFlexLayout();
|
||||
|
||||
FlexGridLayout grid(default_col_dsc, default_row_dsc, 4);
|
||||
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
uint8_t curvePointsCount = 5 + curve.points;
|
||||
|
||||
// Point number
|
||||
for (int i = 0; i < curvePointsCount; i++) {
|
||||
auto txt = new StaticText(
|
||||
this,
|
||||
{i * boxWidth + PAGE_PADDING, 10, boxWidth - PAGE_PADDING, boxHeight},
|
||||
std::to_string(i + 1) + " ", 0, RIGHT | COLOR_THEME_SECONDARY1);
|
||||
txt->setBackgroundColor(COLOR_THEME_SECONDARY2);
|
||||
for (int i = 0; i < curvePointsCount; i += 5) {
|
||||
int count = 5;
|
||||
if (i + count > curvePointsCount) count = curvePointsCount - i;
|
||||
auto line = form->newLine(&grid);
|
||||
line->padAll(0);
|
||||
lv_obj_set_grid_align(line->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
curvePointsRow(line, i, count, curvePointsCount, curve.type == CURVE_TYPE_CUSTOM);
|
||||
}
|
||||
grid.spacer(boxHeight + 10 + PAGE_PADDING);
|
||||
|
||||
// x value
|
||||
if (curve.type == CURVE_TYPE_CUSTOM) {
|
||||
// Adjustable points for custom curves
|
||||
for (int i = 0; i < curvePointsCount; i++) {
|
||||
int8_t* points = curveAddress(index);
|
||||
auto pointEdit = new NumberEdit(
|
||||
this,
|
||||
{coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth),
|
||||
grid.getWindowHeight(), coord_t(boxWidth - PAGE_LINE_SPACING),
|
||||
boxHeight},
|
||||
i <= 1 ? -100 : points[curvePointsCount + i - 2],
|
||||
i >= curvePointsCount - 2 ? 100 : points[curvePointsCount + i],
|
||||
GET_VALUE(i == 0 ? -100
|
||||
: i == curvePointsCount - 1
|
||||
? 100
|
||||
: points[curvePointsCount + i - 1]),
|
||||
[=](int32_t newValue) {
|
||||
if (i == 0 || i == curvePointsCount - 1) return;
|
||||
points[curvePointsCount + i - 1] = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
},
|
||||
0, RIGHT);
|
||||
|
||||
if (i == 0 || i == curvePointsCount - 1) {
|
||||
pointEdit->disable();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < curvePointsCount; i++) {
|
||||
new StaticText(this, {i * boxWidth, grid.getWindowHeight(), boxWidth, boxHeight},
|
||||
std::to_string(-100 + 200 * i / (5 + curve.points - 1)), 0,
|
||||
RIGHT | COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
}
|
||||
grid.spacer(boxHeight + PAGE_PADDING);
|
||||
|
||||
// y value
|
||||
for (uint8_t i = 0; i < curvePointsCount; i++) {
|
||||
int8_t* points = curveAddress(index);
|
||||
new NumberEdit(
|
||||
this,
|
||||
{coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth),
|
||||
grid.getWindowHeight(),
|
||||
coord_t(boxWidth - PAGE_LINE_SPACING),
|
||||
boxHeight},
|
||||
-100, 100, GET_VALUE(points[i]),
|
||||
[=](int32_t newValue) {
|
||||
points[i] = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
},
|
||||
0, RIGHT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CurveDataEdit::paint(BitmapBuffer* dc)
|
||||
{
|
||||
dc->clear(COLOR_THEME_SECONDARY3);
|
||||
// dc->drawSolidHorizontalLine(0, rect.h / 3, getInnerWidth(), 0);
|
||||
// dc->drawSolidHorizontalLine(0, 2 * rect.h / 3, getInnerWidth(), 0);
|
||||
}
|
||||
|
||||
void CurveEdit::SetCurrentSource(uint32_t source)
|
||||
@@ -297,7 +347,6 @@ void CurveEdit::onEvent(event_t event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CurveEdit::checkEvents()
|
||||
{
|
||||
if (!lockSource) {
|
||||
@@ -314,3 +363,151 @@ void CurveEdit::checkEvents()
|
||||
}
|
||||
FormField::checkEvents();
|
||||
}
|
||||
|
||||
CurveEditWindow::CurveEditWindow(uint8_t index):
|
||||
Page(ICON_MODEL_CURVES),
|
||||
index(index)
|
||||
{
|
||||
buildBody(&body);
|
||||
buildHeader(&header);
|
||||
}
|
||||
|
||||
void CurveEditWindow::buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_MENUCURVE, 0, COLOR_THEME_PRIMARY2);
|
||||
char s[16];
|
||||
strAppendStringWithIndex(s, STR_CV, index + 1);
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
|
||||
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
|
||||
s, 0, COLOR_THEME_PRIMARY2);
|
||||
}
|
||||
|
||||
void CurveEditWindow::buildBody(FormWindow * window)
|
||||
{
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
auto form = new FormWindow(window, rect_t{});
|
||||
form->padAll(0);
|
||||
form->setFlexLayout();
|
||||
|
||||
FlexGridLayout grid(default_col_dsc, default_row_dsc, 0);
|
||||
|
||||
auto line = form->newLine(&grid);
|
||||
line->padAll(0);
|
||||
lv_obj_set_grid_align(line->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
#if LCD_H > LCD_W // portrait
|
||||
lv_obj_set_flex_flow(line->getLvObj(), LV_FLEX_FLOW_COLUMN);
|
||||
coord_t curveWidth = window->width() - 88;
|
||||
coord_t boxWidth = window->width();
|
||||
coord_t boxHeight = window->height() - curveWidth;
|
||||
#else
|
||||
lv_obj_set_flex_flow(line->getLvObj(), LV_FLEX_FLOW_ROW);
|
||||
coord_t curveWidth = window->height() - 2 * PAGE_PADDING;
|
||||
coord_t boxWidth = window->width() - curveWidth;
|
||||
coord_t boxHeight = window->height();
|
||||
#endif
|
||||
|
||||
auto box = new Window(line, rect_t{});
|
||||
box->setWidth(boxWidth);
|
||||
box->setHeight(boxHeight);
|
||||
box->padAll(0);
|
||||
|
||||
static const lv_coord_t controls_col_dsc[] = {LV_GRID_FR(5), LV_GRID_FR(8), LV_GRID_FR(5), LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
form = new FormWindow(box, rect_t{});
|
||||
form->padAll(0);
|
||||
form->setFlexLayout();
|
||||
|
||||
FlexGridLayout iGrid(controls_col_dsc, default_row_dsc, 0);
|
||||
|
||||
auto iLine = form->newLine(&iGrid);
|
||||
iLine->padAll(4);
|
||||
iLine->padBottom(0);
|
||||
lv_obj_set_grid_align(iLine->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
// Name
|
||||
new StaticText(iLine, rect_t{}, STR_NAME, 0, COLOR_THEME_PRIMARY1);
|
||||
new ModelTextEdit(iLine, rect_t{0, 0, 100, 0}, curve.name, sizeof(curve.name));
|
||||
|
||||
// Smooth
|
||||
auto smooth = new TextButton(iLine, rect_t{}, STR_SMOOTH, [=]() {
|
||||
g_model.curves[index].smooth = !g_model.curves[index].smooth;
|
||||
curveEdit->updatePreview();
|
||||
return g_model.curves[index].smooth;
|
||||
});
|
||||
smooth->check(g_model.curves[index].smooth);
|
||||
smooth->padAll(2);
|
||||
smooth->setHeight(26);
|
||||
|
||||
iLine = form->newLine(&iGrid);
|
||||
iLine->padAll(4);
|
||||
iLine->padBottom(0);
|
||||
lv_obj_set_grid_align(iLine->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
// Type
|
||||
new StaticText(iLine, rect_t{}, STR_TYPE, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(iLine, rect_t{0, 0, 100, 0}, STR_CURVE_TYPES, 0, 1, GET_DEFAULT(g_model.curves[index].type),
|
||||
[=](int32_t newValue) {
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
if (newValue != curve.type) {
|
||||
for (int i = 1; i < 4 + curve.points; i++) {
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + curve.points)), index));
|
||||
}
|
||||
if (moveCurve(index, newValue == CURVE_TYPE_CUSTOM ? 3 + curve.points : -3 - curve.points)) {
|
||||
if (newValue == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
curve.type = newValue;
|
||||
}
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if (curveDataEdit) {
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Points count
|
||||
auto edit = new NumberEdit(iLine, rect_t{}, 2, 17, GET_DEFAULT(g_model.curves[index].points + 5),
|
||||
[=](int32_t newValue) {
|
||||
newValue -= 5;
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int newPoints[MAX_POINTS_PER_CURVE];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4 + newValue] = points[4 + curve.points];
|
||||
for (int i = 1; i < 4 + newValue; i++)
|
||||
newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + newValue), index));
|
||||
if (moveCurve(index, (newValue - curve.points) * (curve.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
|
||||
for (int i = 0; i < 5 + newValue; i++) {
|
||||
points[i] = newPoints[i];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + newValue)
|
||||
points[5 + newValue + i - 1] = -100 + (i * 200) / (4 + newValue);
|
||||
}
|
||||
curve.points = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if (curveDataEdit) {
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
edit->setSuffix(STR_PTS);
|
||||
|
||||
iLine = form->newLine(&iGrid);
|
||||
iLine->padAll(0);
|
||||
lv_obj_set_grid_align(iLine->getLvObj(), LV_GRID_ALIGN_SPACE_BETWEEN, LV_GRID_ALIGN_SPACE_BETWEEN);
|
||||
|
||||
curveDataEdit = new CurveDataEdit(iLine, rect_t{ 0, 0, box->width(), box->height() - 67 }, index);
|
||||
|
||||
// Curve editor
|
||||
lv_obj_set_flex_align(line->getLvObj(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND);
|
||||
curveEdit = new CurveEdit(line, { 0, 0, curveWidth, curveWidth }, index);
|
||||
|
||||
curveDataEdit->setCurveEdit(curveEdit);
|
||||
}
|
||||
|
||||
@@ -21,31 +21,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
#include "form.h"
|
||||
#include "curve.h"
|
||||
|
||||
class CurveEdit;
|
||||
|
||||
class CurveDataEdit : public FormGroup
|
||||
{
|
||||
friend class CurveEdit;
|
||||
|
||||
public:
|
||||
CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index, CurveEdit * curveEdit);
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
void update();
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
CurveEdit * curveEdit;
|
||||
};
|
||||
class NumberEdit;
|
||||
|
||||
class CurveEdit: public FormField
|
||||
{
|
||||
friend class CurveDataEdit;
|
||||
|
||||
public:
|
||||
CurveEdit(Window * parent, const rect_t & rect, uint8_t index);
|
||||
static void SetCurrentSource(uint32_t source);
|
||||
@@ -84,3 +67,40 @@ class CurveEdit: public FormField
|
||||
void left();
|
||||
bool isCustomCurve() const;
|
||||
};
|
||||
|
||||
class CurveDataEdit : public Window
|
||||
{
|
||||
public:
|
||||
CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index);
|
||||
|
||||
void setCurveEdit(CurveEdit* _curveEdit)
|
||||
{
|
||||
curveEdit = _curveEdit;
|
||||
update();
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
void update();
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
CurveEdit * curveEdit;
|
||||
NumberEdit* numEditX[16];
|
||||
|
||||
void curvePointsRow(FormGroup::Line* parent, int start, int count, int curvePointsCount, bool isCustom);
|
||||
};
|
||||
|
||||
class CurveEditWindow : public Page
|
||||
{
|
||||
public:
|
||||
CurveEditWindow(uint8_t index);
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
CurveEdit * curveEdit = nullptr;
|
||||
CurveDataEdit * curveDataEdit = nullptr;
|
||||
|
||||
void buildHeader(Window * window);
|
||||
void buildBody(FormWindow * window);
|
||||
};
|
||||
|
||||
@@ -116,13 +116,25 @@ void InputEditWindow::buildBody(FormWindow* form)
|
||||
// Weight
|
||||
line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_WEIGHT, 0, COLOR_THEME_PRIMARY1);
|
||||
auto gvar = new GVarNumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(input->weight));
|
||||
auto gvar = new GVarNumberEdit(line, rect_t{}, -100, 100,
|
||||
GET_DEFAULT(input->weight),
|
||||
[=](int32_t newValue) {
|
||||
input->weight = newValue;
|
||||
preview->invalidate();
|
||||
SET_DIRTY();
|
||||
});
|
||||
gvar->setSuffix("%");
|
||||
|
||||
// Offset
|
||||
line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_OFFSET, 0, COLOR_THEME_PRIMARY1);
|
||||
gvar = new GVarNumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(input->offset));
|
||||
gvar = new GVarNumberEdit(line, rect_t{}, -100, 100,
|
||||
GET_DEFAULT(input->offset),
|
||||
[=](int32_t newValue) {
|
||||
input->offset = newValue;
|
||||
preview->invalidate();
|
||||
SET_DIRTY();
|
||||
});
|
||||
gvar->setSuffix("%");
|
||||
|
||||
// Switch
|
||||
@@ -134,7 +146,12 @@ void InputEditWindow::buildBody(FormWindow* form)
|
||||
// Curve
|
||||
line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_CURVE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto param = new CurveParam(line, rect_t{}, &input->curve);
|
||||
auto param = new CurveParam(line, rect_t{}, &input->curve,
|
||||
[=](int32_t newValue) {
|
||||
input->curve.value = newValue;
|
||||
preview->invalidate();
|
||||
SET_DIRTY();
|
||||
});
|
||||
lv_obj_set_style_grid_cell_x_align(param->getLvObj(), LV_GRID_ALIGN_STRETCH, 0);
|
||||
|
||||
line = form->newLine();
|
||||
|
||||
@@ -136,7 +136,7 @@ void MixEditWindow::buildBody(FormWindow* form)
|
||||
|
||||
// Curve
|
||||
new StaticText(line, rect_t{}, STR_CURVE, 0, COLOR_THEME_PRIMARY1);
|
||||
new CurveParam(line, rect_t{}, &mix->curve);
|
||||
new CurveParam(line, rect_t{}, &mix->curve, SET_DEFAULT(mix->curve.value));
|
||||
|
||||
line = form->newLine();
|
||||
lv_obj_set_style_pad_all(line->getLvObj(), lv_dpx(8), 0);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
|
||||
// initialize a new curves points to the default for a 5 point
|
||||
// curve.
|
||||
void initPoints(const CurveHeader &curve, int8_t *points)
|
||||
@@ -37,212 +36,6 @@ void initPoints(const CurveHeader &curve, int8_t *points)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CurveEditWindow : public Page
|
||||
{
|
||||
public:
|
||||
explicit CurveEditWindow(uint8_t index):
|
||||
Page(ICON_MODEL_CURVES),
|
||||
index(index)
|
||||
{
|
||||
buildBody(&body);
|
||||
buildHeader(&header);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
CurveEdit * curveEdit = nullptr;
|
||||
CurveDataEdit * curveDataEdit = nullptr;
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_MENUCURVE, 0, COLOR_THEME_PRIMARY2);
|
||||
char s[16];
|
||||
strAppendStringWithIndex(s, STR_CV, index + 1);
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
|
||||
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
|
||||
s, 0, COLOR_THEME_PRIMARY2);
|
||||
}
|
||||
|
||||
#if LCD_W > LCD_H
|
||||
void buildBody(FormWindow * window)
|
||||
{
|
||||
coord_t curveWidth = window->height() - 2 * PAGE_PADDING;
|
||||
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
// Curve editor
|
||||
curveEdit = new CurveEdit(window, { coord_t(LCD_W - curveWidth - PAGE_PADDING), PAGE_PADDING, curveWidth, curveWidth}, index);
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setLabelWidth(PAGE_PADDING);
|
||||
grid.setMarginRight(curveWidth + 2 * PAGE_PADDING);
|
||||
grid.spacer(PAGE_PADDING);
|
||||
|
||||
// Name
|
||||
new StaticText(window, grid.getFieldSlot(), STR_NAME, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name));
|
||||
grid.nextLine();
|
||||
|
||||
// Type
|
||||
new StaticText(window, grid.getFieldSlot(), STR_TYPE, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
new Choice(window, grid.getFieldSlot(2, 0), STR_CURVE_TYPES, 0, 1, GET_DEFAULT(g_model.curves[index].type),
|
||||
[=](int32_t newValue) {
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
if (newValue != curve.type) {
|
||||
for (int i = 1; i < 4 + curve.points; i++) {
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + curve.points)), index));
|
||||
}
|
||||
if (moveCurve(index, newValue == CURVE_TYPE_CUSTOM ? 3 + curve.points : -3 - curve.points)) {
|
||||
if (newValue == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
curve.type = newValue;
|
||||
}
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if (curveDataEdit) {
|
||||
curveDataEdit->clear();
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Points count
|
||||
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 1), 2, 17, GET_DEFAULT(g_model.curves[index].points + 5),
|
||||
[=](int32_t newValue) {
|
||||
newValue -= 5;
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int newPoints[MAX_POINTS_PER_CURVE];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4 + newValue] = points[4 + curve.points];
|
||||
for (int i = 1; i < 4 + newValue; i++)
|
||||
newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + newValue), index));
|
||||
if (moveCurve(index, (newValue - curve.points) * (curve.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
|
||||
for (int i = 0; i < 5 + newValue; i++) {
|
||||
points[i] = newPoints[i];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + newValue)
|
||||
points[5 + newValue + i - 1] = -100 + (i * 200) / (4 + newValue);
|
||||
}
|
||||
curve.points = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if (curveDataEdit) {
|
||||
curveDataEdit->clear();
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
edit->setSuffix(STR_PTS);
|
||||
grid.nextLine();
|
||||
|
||||
// Smooth
|
||||
new StaticText(window, grid.getFieldSlot(2, 0), STR_SMOOTH, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(2, 1), GET_DEFAULT(g_model.curves[index].smooth),
|
||||
[=](int32_t newValue) {
|
||||
g_model.curves[index].smooth = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
curveDataEdit = new CurveDataEdit(window, {0, grid.getWindowHeight(), coord_t(LCD_W - curveWidth - PAGE_PADDING - 1), window->height() - grid.getWindowHeight() - PAGE_PADDING}, index, curveEdit);
|
||||
}
|
||||
#else
|
||||
void buildBody(FormWindow * window)
|
||||
{
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setMarginLeft(PAGE_PADDING);
|
||||
grid.setMarginRight(PAGE_PADDING);
|
||||
grid.setLabelWidth(100);
|
||||
grid.spacer(PAGE_PADDING);
|
||||
|
||||
// Curve editor
|
||||
curveEdit = new CurveEdit(window, { 42, grid.getWindowHeight(), LCD_W - 80, LCD_W - 80}, index);
|
||||
grid.spacer(curveEdit->height() + 15);
|
||||
|
||||
// Name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_NAME, 0, COLOR_THEME_PRIMARY1);
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name));
|
||||
grid.nextLine();
|
||||
|
||||
// Type
|
||||
new StaticText(window, grid.getLabelSlot(), STR_TYPE, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(window, grid.getFieldSlot(2, 0), STR_CURVE_TYPES, 0, 1, GET_DEFAULT(g_model.curves[index].type),
|
||||
[=](int32_t newValue) {
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
if (newValue != curve.type) {
|
||||
for (int i = 1; i < 4 + curve.points; i++) {
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + curve.points)), index));
|
||||
}
|
||||
if (moveCurve(index, newValue == CURVE_TYPE_CUSTOM ? 3 + curve.points : -3 - curve.points)) {
|
||||
if (newValue == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
curve.type = newValue;
|
||||
}
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if(curveDataEdit) {
|
||||
curveDataEdit->clear();
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Points count
|
||||
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 1), 2, 17, GET_DEFAULT(g_model.curves[index].points + 5),
|
||||
[=](int32_t newValue) {
|
||||
newValue -= 5;
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int newPoints[MAX_POINTS_PER_CURVE];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4 + newValue] = points[4 + curve.points];
|
||||
for (int i = 1; i < 4 + newValue; i++)
|
||||
newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + newValue), index));
|
||||
if (moveCurve(index, (newValue - curve.points) * (curve.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
|
||||
for (int i = 0; i < 5 + newValue; i++) {
|
||||
points[i] = newPoints[i];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + newValue)
|
||||
points[5 + newValue + i - 1] = -100 + (i * 200) / (4 + newValue);
|
||||
}
|
||||
curve.points = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
if(curveDataEdit) {
|
||||
curveDataEdit->clear();
|
||||
curveDataEdit->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
edit->setSuffix(STR_PTS);
|
||||
grid.nextLine();
|
||||
|
||||
// Smooth
|
||||
new StaticText(window, grid.getLabelSlot(), STR_SMOOTH, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_DEFAULT(g_model.curves[index].smooth),
|
||||
[=](int32_t newValue) {
|
||||
g_model.curves[index].smooth = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->updatePreview();
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
curveDataEdit = new CurveDataEdit(window, {PAGE_PADDING, grid.getWindowHeight(), coord_t(LCD_W - PAGE_PADDING - 1), window->height() - grid.getWindowHeight() - PAGE_PADDING}, index, curveEdit);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CurveButton : public Button {
|
||||
public:
|
||||
CurveButton(FormGroup * parent, const rect_t &rect, uint8_t index) :
|
||||
@@ -288,7 +81,6 @@ ModelCurvesPage::ModelCurvesPage() :
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// can be called from any other screen to edit a curve.
|
||||
// currently called from model_mixes.cpp on longpress.
|
||||
void ModelCurvesPage::pushEditCurve(int index)
|
||||
|
||||
Reference in New Issue
Block a user