Touch UI Bed Mesh Screen refactor, enhancements (#21521)
- Split mesh view and edit screen into two screens - The editor now live-updates the graphics - Added Touch UI mesh progress feedback to `G26` - Show positive / negative mesh values in different colors
This commit is contained in:
parent
8da8bf7e87
commit
75b790376d
|
@ -730,7 +730,7 @@ void unified_bed_leveling::shift_mesh_height() {
|
||||||
uint8_t count = GRID_MAX_POINTS;
|
uint8_t count = GRID_MAX_POINTS;
|
||||||
|
|
||||||
mesh_index_pair best;
|
mesh_index_pair best;
|
||||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::MESH_START));
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_START));
|
||||||
do {
|
do {
|
||||||
if (do_ubl_mesh_map) display_map(param.T_map_type);
|
if (do_ubl_mesh_map) display_map(param.T_map_type);
|
||||||
|
|
||||||
|
@ -755,14 +755,14 @@ void unified_bed_leveling::shift_mesh_height() {
|
||||||
: find_closest_mesh_point_of_type(INVALID, nearby, true);
|
: find_closest_mesh_point_of_type(INVALID, nearby, true);
|
||||||
|
|
||||||
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
|
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
|
||||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_START));
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_START));
|
||||||
const float measured_z = probe.probe_at_point(
|
const float measured_z = probe.probe_at_point(
|
||||||
best.meshpos(),
|
best.meshpos(),
|
||||||
stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity
|
stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity
|
||||||
);
|
);
|
||||||
z_values[best.pos.x][best.pos.y] = measured_z;
|
z_values[best.pos.x][best.pos.y] = measured_z;
|
||||||
#if ENABLED(EXTENSIBLE_UI)
|
#if ENABLED(EXTENSIBLE_UI)
|
||||||
ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_FINISH);
|
ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_FINISH);
|
||||||
ExtUI::onMeshUpdate(best.pos, measured_z);
|
ExtUI::onMeshUpdate(best.pos, measured_z);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -770,7 +770,7 @@ void unified_bed_leveling::shift_mesh_height() {
|
||||||
|
|
||||||
} while (best.pos.x >= 0 && --count);
|
} while (best.pos.x >= 0 && --count);
|
||||||
|
|
||||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::MESH_FINISH));
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH));
|
||||||
|
|
||||||
// Release UI during stow to allow for PAUSE_BEFORE_DEPLOY_STOW
|
// Release UI during stow to allow for PAUSE_BEFORE_DEPLOY_STOW
|
||||||
TERN_(HAS_LCD_MENU, ui.release());
|
TERN_(HAS_LCD_MENU, ui.release());
|
||||||
|
|
|
@ -113,6 +113,10 @@
|
||||||
#include "../../module/temperature.h"
|
#include "../../module/temperature.h"
|
||||||
#include "../../lcd/marlinui.h"
|
#include "../../lcd/marlinui.h"
|
||||||
|
|
||||||
|
#if ENABLED(EXTENSIBLE_UI)
|
||||||
|
#include "../../lcd/extui/ui_api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(UBL_HILBERT_CURVE)
|
#if ENABLED(UBL_HILBERT_CURVE)
|
||||||
#include "../../feature/bedlevel/hilbert_curve.h"
|
#include "../../feature/bedlevel/hilbert_curve.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -725,11 +729,13 @@ void GcodeSuite::G26() {
|
||||||
#endif // !ARC_SUPPORT
|
#endif // !ARC_SUPPORT
|
||||||
|
|
||||||
mesh_index_pair location;
|
mesh_index_pair location;
|
||||||
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location.pos, ExtUI::G26_START));
|
||||||
do {
|
do {
|
||||||
// Find the nearest confluence
|
// Find the nearest confluence
|
||||||
location = g26.find_closest_circle_to_print(g26.continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos);
|
location = g26.find_closest_circle_to_print(g26.continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos);
|
||||||
|
|
||||||
if (location.valid()) {
|
if (location.valid()) {
|
||||||
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location.pos, ExtUI::G26_POINT_START));
|
||||||
const xy_pos_t circle = _GET_MESH_POS(location.pos);
|
const xy_pos_t circle = _GET_MESH_POS(location.pos);
|
||||||
|
|
||||||
// If this mesh location is outside the printable radius, skip it.
|
// If this mesh location is outside the printable radius, skip it.
|
||||||
|
@ -845,6 +851,8 @@ void GcodeSuite::G26() {
|
||||||
g26.connect_neighbor_with_line(location.pos, 1, 0);
|
g26.connect_neighbor_with_line(location.pos, 1, 0);
|
||||||
g26.connect_neighbor_with_line(location.pos, 0, -1);
|
g26.connect_neighbor_with_line(location.pos, 0, -1);
|
||||||
g26.connect_neighbor_with_line(location.pos, 0, 1);
|
g26.connect_neighbor_with_line(location.pos, 0, 1);
|
||||||
|
planner.synchronize();
|
||||||
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location.pos, ExtUI::G26_POINT_FINISH));
|
||||||
if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE;
|
if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,6 +862,7 @@ void GcodeSuite::G26() {
|
||||||
|
|
||||||
LEAVE:
|
LEAVE:
|
||||||
ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1);
|
ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1);
|
||||||
|
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location, ExtUI::G26_FINISH));
|
||||||
|
|
||||||
g26.retract_filament(destination);
|
g26.retract_filament(destination);
|
||||||
destination.z = Z_CLEARANCE_BETWEEN_PROBES;
|
destination.z = Z_CLEARANCE_BETWEEN_PROBES;
|
||||||
|
|
|
@ -141,11 +141,11 @@ namespace ExtUI {
|
||||||
void onMeshLevelingStart() {}
|
void onMeshLevelingStart() {}
|
||||||
|
|
||||||
void onMeshUpdate(const int8_t x, const int8_t y, const_float_t val) {
|
void onMeshUpdate(const int8_t x, const int8_t y, const_float_t val) {
|
||||||
BedMeshScreen::onMeshUpdate(x, y, val);
|
BedMeshViewScreen::onMeshUpdate(x, y, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
|
void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
|
||||||
BedMeshScreen::onMeshUpdate(x, y, state);
|
BedMeshViewScreen::onMeshUpdate(x, y, state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***********************
|
/*********************
|
||||||
* bed_mesh_screen.cpp *
|
* bed_mesh_base.cpp *
|
||||||
***********************/
|
*********************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Written By Marcio Teixeira 2020 *
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
@ -21,43 +21,17 @@
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "screens.h"
|
#include "screens.h"
|
||||||
#include "screen_data.h"
|
|
||||||
|
|
||||||
#ifdef FTDI_BED_MESH_SCREEN
|
#ifdef FTDI_BED_MESH_BASE
|
||||||
|
|
||||||
using namespace FTDI;
|
using namespace FTDI;
|
||||||
using namespace Theme;
|
|
||||||
using namespace ExtUI;
|
|
||||||
|
|
||||||
constexpr static BedMeshScreenData &mydata = screen_data.BedMeshScreen;
|
void BedMeshBase::_drawMesh(CommandProcessor &cmd, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t opts, float autoscale_max, uint8_t highlightedTag, mesh_getter_ptr func, void *data) {
|
||||||
constexpr static float gaugeThickness = 0.25;
|
|
||||||
|
|
||||||
#if ENABLED(TOUCH_UI_PORTRAIT)
|
|
||||||
#define GRID_COLS 3
|
|
||||||
#define GRID_ROWS 10
|
|
||||||
|
|
||||||
#define MESH_POS BTN_POS(1, 2), BTN_SIZE(3,5)
|
|
||||||
#define MESSAGE_POS BTN_POS(1, 7), BTN_SIZE(3,1)
|
|
||||||
#define Z_LABEL_POS BTN_POS(1, 8), BTN_SIZE(1,1)
|
|
||||||
#define Z_VALUE_POS BTN_POS(2, 8), BTN_SIZE(2,1)
|
|
||||||
#define OKAY_POS BTN_POS(1,10), BTN_SIZE(3,1)
|
|
||||||
#else
|
|
||||||
#define GRID_COLS 5
|
|
||||||
#define GRID_ROWS 5
|
|
||||||
|
|
||||||
#define MESH_POS BTN_POS(1,1), BTN_SIZE(3,5)
|
|
||||||
#define MESSAGE_POS BTN_POS(4,1), BTN_SIZE(2,1)
|
|
||||||
#define Z_LABEL_POS BTN_POS(4,2), BTN_SIZE(2,1)
|
|
||||||
#define Z_VALUE_POS BTN_POS(4,3), BTN_SIZE(2,1)
|
|
||||||
#define OKAY_POS BTN_POS(4,5), BTN_SIZE(2,1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max) {
|
|
||||||
constexpr uint8_t rows = GRID_MAX_POINTS_Y;
|
constexpr uint8_t rows = GRID_MAX_POINTS_Y;
|
||||||
constexpr uint8_t cols = GRID_MAX_POINTS_X;
|
constexpr uint8_t cols = GRID_MAX_POINTS_X;
|
||||||
|
|
||||||
#define VALUE(X,Y) (data ? data[X][Y] : 0)
|
#define VALUE(X,Y) (func ? func(X,Y,data) : 0)
|
||||||
#define ISVAL(X,Y) (data ? !isnan(VALUE(X,Y)) : true)
|
#define ISVAL(X,Y) (func ? !isnan(VALUE(X,Y)) : true)
|
||||||
#define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0)
|
#define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0)
|
||||||
|
|
||||||
// Compute the mean, min and max for the points
|
// Compute the mean, min and max for the points
|
||||||
|
@ -67,7 +41,7 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
|
||||||
float val_min = INFINITY;
|
float val_min = INFINITY;
|
||||||
uint8_t val_cnt = 0;
|
uint8_t val_cnt = 0;
|
||||||
|
|
||||||
if (data && (opts & USE_AUTOSCALE)) {
|
if (opts & USE_AUTOSCALE) {
|
||||||
for (uint8_t y = 0; y < rows; y++) {
|
for (uint8_t y = 0; y < rows; y++) {
|
||||||
for (uint8_t x = 0; x < cols; x++) {
|
for (uint8_t x = 0; x < cols; x++) {
|
||||||
if (ISVAL(x,y)) {
|
if (ISVAL(x,y)) {
|
||||||
|
@ -140,7 +114,6 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
|
||||||
|
|
||||||
const uint16_t basePointSize = min(w,h) / max(cols,rows);
|
const uint16_t basePointSize = min(w,h) / max(cols,rows);
|
||||||
|
|
||||||
CommandProcessor cmd;
|
|
||||||
cmd.cmd(SAVE_CONTEXT())
|
cmd.cmd(SAVE_CONTEXT())
|
||||||
.cmd(TAG_MASK(false))
|
.cmd(TAG_MASK(false))
|
||||||
.cmd(SAVE_CONTEXT());
|
.cmd(SAVE_CONTEXT());
|
||||||
|
@ -167,10 +140,14 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
|
||||||
for (uint8_t x = 0; x < cols; x++) {
|
for (uint8_t x = 0; x < cols; x++) {
|
||||||
if (ISVAL(x,y)) {
|
if (ISVAL(x,y)) {
|
||||||
if (opts & USE_COLORS) {
|
if (opts & USE_COLORS) {
|
||||||
const float val_dev = VALUE(x, y) - val_mean;
|
const float val_dev = sq(VALUE(x, y) - val_mean);
|
||||||
const uint8_t neg_byte = sq(val_dev) / (val_dev < 0 ? sq_min : sq_max) * 0xFF;
|
uint8_t r = 0, b = 0;
|
||||||
const uint8_t pos_byte = 255 - neg_byte;
|
//*(VALUE(x, y) < 0 ? &r : &b) = val_dev / sq_min * 0xFF;
|
||||||
cmd.cmd(COLOR_RGB(pos_byte, pos_byte, 0xFF));
|
if (VALUE(x, y) < 0)
|
||||||
|
r = val_dev / sq_min * 0xFF;
|
||||||
|
else
|
||||||
|
b = val_dev / sq_max * 0xFF;
|
||||||
|
cmd.cmd(COLOR_RGB(0xFF - b, 0xFF - b - r, 0xFF - r));
|
||||||
}
|
}
|
||||||
cmd.cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
|
cmd.cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
|
||||||
}
|
}
|
||||||
|
@ -198,7 +175,7 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts & USE_HIGHLIGHT) {
|
if (opts & USE_HIGHLIGHT) {
|
||||||
const uint8_t tag = mydata.highlightedTag;
|
const uint8_t tag = highlightedTag;
|
||||||
xy_uint8_t pt;
|
xy_uint8_t pt;
|
||||||
if (tagToPoint(tag, pt)) {
|
if (tagToPoint(tag, pt)) {
|
||||||
cmd.cmd(COLOR_A(128))
|
cmd.cmd(COLOR_A(128))
|
||||||
|
@ -211,184 +188,32 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
|
||||||
cmd.cmd(RESTORE_CONTEXT());
|
cmd.cmd(RESTORE_CONTEXT());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BedMeshScreen::pointToTag(uint8_t x, uint8_t y) {
|
uint8_t BedMeshBase::pointToTag(uint8_t x, uint8_t y) {
|
||||||
return y * (GRID_MAX_POINTS_X) + x + 10;
|
return x >= 0 && x < GRID_MAX_POINTS_X && y >= 0 && y < GRID_MAX_POINTS_Y ? y * (GRID_MAX_POINTS_X) + x + 10 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BedMeshScreen::tagToPoint(uint8_t tag, xy_uint8_t &pt) {
|
bool BedMeshBase::tagToPoint(uint8_t tag, xy_uint8_t &pt) {
|
||||||
if (tag < 10) return false;
|
if (tag < 10) return false;
|
||||||
pt.x = (tag - 10) % (GRID_MAX_POINTS_X);
|
pt.x = (tag - 10) % (GRID_MAX_POINTS_X);
|
||||||
pt.y = (tag - 10) / (GRID_MAX_POINTS_X);
|
pt.y = (tag - 10) / (GRID_MAX_POINTS_X);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BedMeshScreen::onEntry() {
|
void BedMeshBase::drawMeshBackground(CommandProcessor &cmd, int16_t x, int16_t y, int16_t w, int16_t h) {
|
||||||
mydata.allowEditing = true;
|
cmd.cmd(COLOR_RGB(Theme::bed_mesh_shadow_rgb));
|
||||||
mydata.highlightedTag = 0;
|
_drawMesh(cmd, x, y, w, h, USE_POINTS | USE_TAGS, 0.1, 0, nullptr, nullptr);
|
||||||
mydata.zAdjustment = 0;
|
|
||||||
mydata.count = GRID_MAX_POINTS;
|
|
||||||
mydata.message = mydata.MSG_NONE;
|
|
||||||
BaseScreen::onEntry();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float BedMeshScreen::getHighlightedValue(bool nanAsZero) {
|
void BedMeshBase::drawMeshForeground(CommandProcessor &cmd, int16_t x, int16_t y, int16_t w, int16_t h, mesh_getter_ptr func, void *data, uint8_t highlightedTag, float progress) {
|
||||||
xy_uint8_t pt;
|
constexpr float autoscale_max_amplitude = 0.03;
|
||||||
if (tagToPoint(mydata.highlightedTag, pt)) {
|
|
||||||
const float val = ExtUI::getMeshPoint(pt);
|
cmd.cmd(COLOR_RGB(Theme::bed_mesh_lines_rgb));
|
||||||
return (isnan(val) && nanAsZero) ? 0 : val;
|
_drawMesh(cmd, x, y, w, h,
|
||||||
}
|
USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (progress > 0.95 ? USE_COLORS : 0),
|
||||||
return NAN;
|
autoscale_max_amplitude * progress,
|
||||||
|
highlightedTag,
|
||||||
|
func, data
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BedMeshScreen::setHighlightedValue(float value) {
|
#endif // FTDI_BED_MESH_BASE
|
||||||
xy_uint8_t pt;
|
|
||||||
if (tagToPoint(mydata.highlightedTag, pt))
|
|
||||||
ExtUI::setMeshPoint(pt, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::moveToHighlightedValue() {
|
|
||||||
xy_uint8_t pt;
|
|
||||||
if (tagToPoint(mydata.highlightedTag, pt))
|
|
||||||
ExtUI::moveToMeshPoint(pt, gaugeThickness + mydata.zAdjustment);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::adjustHighlightedValue(float increment) {
|
|
||||||
mydata.zAdjustment += increment;
|
|
||||||
moveToHighlightedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::saveAdjustedHighlightedValue() {
|
|
||||||
if (mydata.zAdjustment) {
|
|
||||||
BedMeshScreen::setHighlightedValue(BedMeshScreen::getHighlightedValue(true) + mydata.zAdjustment);
|
|
||||||
mydata.zAdjustment = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::changeHighlightedValue(uint8_t tag) {
|
|
||||||
if (mydata.allowEditing) saveAdjustedHighlightedValue();
|
|
||||||
mydata.highlightedTag = tag;
|
|
||||||
if (mydata.allowEditing) moveToHighlightedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::drawHighlightedPointValue() {
|
|
||||||
CommandProcessor cmd;
|
|
||||||
cmd.font(Theme::font_medium)
|
|
||||||
.colors(normal_btn)
|
|
||||||
.text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
|
|
||||||
.font(font_small);
|
|
||||||
|
|
||||||
if (mydata.allowEditing)
|
|
||||||
draw_adjuster(cmd, Z_VALUE_POS, 2, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
|
||||||
else
|
|
||||||
draw_adjuster_value(cmd, Z_VALUE_POS, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
|
||||||
|
|
||||||
cmd.colors(action_btn)
|
|
||||||
.tag(1).button(OKAY_POS, GET_TEXT_F(MSG_BUTTON_OKAY))
|
|
||||||
.tag(0);
|
|
||||||
|
|
||||||
switch (mydata.message) {
|
|
||||||
case mydata.MSG_MESH_COMPLETE: cmd.text(MESSAGE_POS, GET_TEXT_F(MSG_BED_MAPPING_DONE)); break;
|
|
||||||
case mydata.MSG_MESH_INCOMPLETE: cmd.text(MESSAGE_POS, GET_TEXT_F(MSG_BED_MAPPING_INCOMPLETE)); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::onRedraw(draw_mode_t what) {
|
|
||||||
#define _INSET_POS(x,y,w,h) x + min(w,h)/10, y + min(w,h)/10, w - min(w,h)/5, h - min(w,h)/5
|
|
||||||
#define INSET_POS(pos) _INSET_POS(pos)
|
|
||||||
|
|
||||||
if (what & BACKGROUND) {
|
|
||||||
CommandProcessor cmd;
|
|
||||||
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
|
|
||||||
.cmd(CLEAR(true,true,true));
|
|
||||||
|
|
||||||
// Draw the shadow and tags
|
|
||||||
cmd.cmd(COLOR_RGB(Theme::bed_mesh_shadow_rgb));
|
|
||||||
BedMeshScreen::drawMesh(INSET_POS(MESH_POS), nullptr, USE_POINTS | USE_TAGS);
|
|
||||||
cmd.cmd(COLOR_RGB(bg_text_enabled));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what & FOREGROUND) {
|
|
||||||
constexpr float autoscale_max_amplitude = 0.03;
|
|
||||||
const bool gotAllPoints = mydata.count >= GRID_MAX_POINTS;
|
|
||||||
if (gotAllPoints) {
|
|
||||||
drawHighlightedPointValue();
|
|
||||||
}
|
|
||||||
CommandProcessor cmd;
|
|
||||||
cmd.cmd(COLOR_RGB(Theme::bed_mesh_lines_rgb));
|
|
||||||
const float levelingProgress = sq(float(mydata.count) / GRID_MAX_POINTS);
|
|
||||||
BedMeshScreen::drawMesh(INSET_POS(MESH_POS), ExtUI::getMeshArray(),
|
|
||||||
USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (gotAllPoints ? USE_COLORS : 0),
|
|
||||||
autoscale_max_amplitude * levelingProgress
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BedMeshScreen::onTouchEnd(uint8_t tag) {
|
|
||||||
constexpr float increment = 0.01;
|
|
||||||
switch (tag) {
|
|
||||||
case 1:
|
|
||||||
saveAdjustedHighlightedValue();
|
|
||||||
injectCommands_P(PSTR("G29 S1"));
|
|
||||||
GOTO_PREVIOUS();
|
|
||||||
return true;
|
|
||||||
case 2: adjustHighlightedValue(-increment); break;
|
|
||||||
case 3: adjustHighlightedValue( increment); break;
|
|
||||||
default:
|
|
||||||
if (tag >= 10)
|
|
||||||
changeHighlightedValue(tag);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::onMeshUpdate(const int8_t, const int8_t, const float) {
|
|
||||||
if (AT_SCREEN(BedMeshScreen))
|
|
||||||
onRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
|
|
||||||
switch (state) {
|
|
||||||
case ExtUI::MESH_START:
|
|
||||||
mydata.allowEditing = false;
|
|
||||||
mydata.count = 0;
|
|
||||||
mydata.message = mydata.MSG_NONE;
|
|
||||||
break;
|
|
||||||
case ExtUI::MESH_FINISH:
|
|
||||||
if (mydata.count == GRID_MAX_POINTS && ExtUI::getMeshValid())
|
|
||||||
mydata.message = mydata.MSG_MESH_COMPLETE;
|
|
||||||
else
|
|
||||||
mydata.message = mydata.MSG_MESH_INCOMPLETE;
|
|
||||||
mydata.count = GRID_MAX_POINTS;
|
|
||||||
break;
|
|
||||||
case ExtUI::PROBE_START:
|
|
||||||
mydata.highlightedTag = pointToTag(x, y);
|
|
||||||
break;
|
|
||||||
case ExtUI::PROBE_FINISH:
|
|
||||||
mydata.count++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BedMeshScreen::onMeshUpdate(x, y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::startMeshProbe() {
|
|
||||||
GOTO_SCREEN(BedMeshScreen);
|
|
||||||
mydata.allowEditing = false;
|
|
||||||
mydata.count = 0;
|
|
||||||
injectCommands_P(PSTR(BED_LEVELING_COMMANDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::showMesh() {
|
|
||||||
GOTO_SCREEN(BedMeshScreen);
|
|
||||||
mydata.allowEditing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BedMeshScreen::showMeshEditor() {
|
|
||||||
SpinnerDialogBox::enqueueAndWait_P(ExtUI::isMachineHomed() ? F("M420 S1") : F("G28\nM420 S1"));
|
|
||||||
// After the spinner, go to this screen.
|
|
||||||
current_screen.forget();
|
|
||||||
PUSH_SCREEN(BedMeshScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FTDI_BED_MESH_SCREEN
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*******************
|
||||||
|
* bed_mesh_base.h *
|
||||||
|
*******************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* To view a copy of the GNU General Public License, go to the following *
|
||||||
|
* location: <https://www.gnu.org/licenses/>. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define FTDI_BED_MESH_BASE
|
||||||
|
|
||||||
|
class BedMeshBase : public BaseScreen {
|
||||||
|
protected:
|
||||||
|
typedef float (*mesh_getter_ptr)(uint8_t x, uint8_t y, void *data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum MeshOpts {
|
||||||
|
USE_POINTS = 0x01,
|
||||||
|
USE_COLORS = 0x02,
|
||||||
|
USE_TAGS = 0x04,
|
||||||
|
USE_HIGHLIGHT = 0x08,
|
||||||
|
USE_AUTOSCALE = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _drawMesh(CommandProcessor &, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t opts, float autoscale_max, uint8_t highlightedTag, mesh_getter_ptr func, void *data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void drawMeshForeground(CommandProcessor &cmd, int16_t x, int16_t y, int16_t w, int16_t h, mesh_getter_ptr func, void *data, uint8_t highlightedTag = 0, float progress = 1.0);
|
||||||
|
static void drawMeshBackground(CommandProcessor &cmd, int16_t x, int16_t y, int16_t w, int16_t h);
|
||||||
|
static uint8_t pointToTag(uint8_t x, uint8_t y);
|
||||||
|
static bool tagToPoint(uint8_t tag, xy_uint8_t &pt);
|
||||||
|
};
|
|
@ -0,0 +1,186 @@
|
||||||
|
/****************************
|
||||||
|
* bed_mesh_edit_screen.cpp *
|
||||||
|
****************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* To view a copy of the GNU General Public License, go to the following *
|
||||||
|
* location: <https://www.gnu.org/licenses/>. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "screens.h"
|
||||||
|
#include "screen_data.h"
|
||||||
|
|
||||||
|
#ifdef FTDI_BED_MESH_EDIT_SCREEN
|
||||||
|
|
||||||
|
using namespace FTDI;
|
||||||
|
using namespace Theme;
|
||||||
|
using namespace ExtUI;
|
||||||
|
|
||||||
|
constexpr static BedMeshEditScreenData &mydata = screen_data.BedMeshEditScreen;
|
||||||
|
constexpr static float gaugeThickness = 0.25;
|
||||||
|
|
||||||
|
#if ENABLED(TOUCH_UI_PORTRAIT)
|
||||||
|
#define GRID_COLS 3
|
||||||
|
#define GRID_ROWS 10
|
||||||
|
|
||||||
|
#define MESH_POS BTN_POS(1, 2), BTN_SIZE(3,5)
|
||||||
|
#define MESSAGE_POS BTN_POS(1, 7), BTN_SIZE(3,1)
|
||||||
|
#define Z_LABEL_POS BTN_POS(1, 8), BTN_SIZE(1,1)
|
||||||
|
#define Z_VALUE_POS BTN_POS(2, 8), BTN_SIZE(2,1)
|
||||||
|
#define BACK_POS BTN_POS(1,10), BTN_SIZE(2,1)
|
||||||
|
#define SAVE_POS BTN_POS(3,10), BTN_SIZE(1,1)
|
||||||
|
#else
|
||||||
|
#define GRID_COLS 5
|
||||||
|
#define GRID_ROWS 5
|
||||||
|
|
||||||
|
#define MESH_POS BTN_POS(1,1), BTN_SIZE(3,5)
|
||||||
|
#define MESSAGE_POS BTN_POS(4,1), BTN_SIZE(2,1)
|
||||||
|
#define Z_LABEL_POS BTN_POS(4,2), BTN_SIZE(2,1)
|
||||||
|
#define Z_VALUE_POS BTN_POS(4,3), BTN_SIZE(2,1)
|
||||||
|
#define BACK_POS BTN_POS(4,5), BTN_SIZE(1,1)
|
||||||
|
#define SAVE_POS BTN_POS(5,5), BTN_SIZE(1,1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static float meshGetter(uint8_t x, uint8_t y, void*) {
|
||||||
|
xy_uint8_t pos;
|
||||||
|
pos.x = x;
|
||||||
|
pos.y = y;
|
||||||
|
return ExtUI::getMeshPoint(pos) + (mydata.highlight.x != -1 && mydata.highlight == pos ? mydata.zAdjustment : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::onEntry() {
|
||||||
|
mydata.needSave = false;
|
||||||
|
mydata.highlight.x = -1;
|
||||||
|
mydata.zAdjustment = 0;
|
||||||
|
BaseScreen::onEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
float BedMeshEditScreen::getHighlightedValue() {
|
||||||
|
const float val = ExtUI::getMeshPoint(mydata.highlight);
|
||||||
|
return (isnan(val) ? 0 : val) + mydata.zAdjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::setHighlightedValue(float value) {
|
||||||
|
ExtUI::setMeshPoint(mydata.highlight, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::moveToHighlightedValue() {
|
||||||
|
if (ExtUI::getMeshValid()) {
|
||||||
|
ExtUI::setLevelingActive(true);
|
||||||
|
ExtUI::moveToMeshPoint(mydata.highlight, gaugeThickness + mydata.zAdjustment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::adjustHighlightedValue(float increment) {
|
||||||
|
if(mydata.highlight.x != -1) {
|
||||||
|
mydata.zAdjustment += increment;
|
||||||
|
moveToHighlightedValue();
|
||||||
|
mydata.needSave = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::saveAdjustedHighlightedValue() {
|
||||||
|
if (mydata.zAdjustment && mydata.highlight.x != -1) {
|
||||||
|
setHighlightedValue(getHighlightedValue());
|
||||||
|
mydata.zAdjustment = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BedMeshEditScreen::changeHighlightedValue(uint8_t tag) {
|
||||||
|
saveAdjustedHighlightedValue();
|
||||||
|
if (tagToPoint(tag, mydata.highlight)) {
|
||||||
|
moveToHighlightedValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::drawHighlightedPointValue() {
|
||||||
|
CommandProcessor cmd;
|
||||||
|
cmd.font(Theme::font_medium)
|
||||||
|
.colors(normal_btn)
|
||||||
|
.text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
|
||||||
|
.font(font_small);
|
||||||
|
if(mydata.highlight.x != -1)
|
||||||
|
draw_adjuster(cmd, Z_VALUE_POS, 3, getHighlightedValue(), GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
||||||
|
cmd.colors(mydata.needSave ? normal_btn : action_btn)
|
||||||
|
.tag(1).button(BACK_POS, GET_TEXT_F(MSG_BUTTON_BACK))
|
||||||
|
.colors(mydata.needSave ? action_btn : normal_btn)
|
||||||
|
.enabled(mydata.needSave)
|
||||||
|
.tag(2).button(SAVE_POS, GET_TEXT_F(MSG_TOUCHMI_SAVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::onRedraw(draw_mode_t what) {
|
||||||
|
#define _INSET_POS(x,y,w,h) x + min(w,h)/10, y + min(w,h)/10, w - min(w,h)/5, h - min(w,h)/5
|
||||||
|
#define INSET_POS(pos) _INSET_POS(pos)
|
||||||
|
|
||||||
|
CommandProcessor cmd;
|
||||||
|
|
||||||
|
if (what & BACKGROUND) {
|
||||||
|
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
|
||||||
|
.cmd(CLEAR(true,true,true));
|
||||||
|
drawMeshBackground(cmd, INSET_POS(MESH_POS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (what & FOREGROUND) {
|
||||||
|
drawHighlightedPointValue();
|
||||||
|
drawMeshForeground(cmd, INSET_POS(MESH_POS), meshGetter, nullptr, pointToTag(mydata.highlight.x,mydata.highlight.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BedMeshEditScreen::onTouchHeld(uint8_t tag) {
|
||||||
|
constexpr float increment = 0.01;
|
||||||
|
switch (tag) {
|
||||||
|
case 3: adjustHighlightedValue(-increment); return true;
|
||||||
|
case 4: adjustHighlightedValue( increment); return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BedMeshEditScreen::onTouchEnd(uint8_t tag) {
|
||||||
|
switch (tag) {
|
||||||
|
case 1:
|
||||||
|
// On Cancel, reload saved mesh, discarding changes
|
||||||
|
GOTO_PREVIOUS();
|
||||||
|
injectCommands_P(PSTR("G29 L1"));
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
saveAdjustedHighlightedValue();
|
||||||
|
injectCommands_P(PSTR("G29 S1"));
|
||||||
|
mydata.needSave = false;
|
||||||
|
return true;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
return onTouchHeld(tag);
|
||||||
|
default: return changeHighlightedValue(tag);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshEditScreen::show() {
|
||||||
|
// On entry, home if needed and save current mesh
|
||||||
|
if (!ExtUI::isMachineHomed()) {
|
||||||
|
SpinnerDialogBox::enqueueAndWait_P(F("G28\nG29 S1"));
|
||||||
|
// After the spinner, go to this screen.
|
||||||
|
current_screen.forget();
|
||||||
|
PUSH_SCREEN(BedMeshEditScreen);
|
||||||
|
} else {
|
||||||
|
injectCommands_P(PSTR("G29 S1"));
|
||||||
|
GOTO_SCREEN(BedMeshEditScreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FTDI_BED_MESH_EDIT_SCREEN
|
|
@ -1,6 +1,6 @@
|
||||||
/*********************
|
/**************************
|
||||||
* bed_mesh_screen.h *
|
* bed_mesh_edit_screen.h *
|
||||||
*********************/
|
*************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Written By Marcio Teixeira 2020 *
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
@ -21,49 +21,28 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define FTDI_BED_MESH_SCREEN
|
#define FTDI_BED_MESH_EDIT_SCREEN
|
||||||
#define FTDI_BED_MESH_SCREEN_CLASS BedMeshScreen
|
#define FTDI_BED_MESH_EDIT_SCREEN_CLASS BedMeshEditScreen
|
||||||
|
|
||||||
struct BedMeshScreenData {
|
struct BedMeshEditScreenData {
|
||||||
enum : uint8_t {
|
bool needSave;
|
||||||
MSG_NONE,
|
xy_uint8_t highlight;
|
||||||
MSG_MESH_COMPLETE,
|
|
||||||
MSG_MESH_INCOMPLETE
|
|
||||||
} message;
|
|
||||||
uint8_t count;
|
|
||||||
uint8_t highlightedTag;
|
|
||||||
float zAdjustment;
|
float zAdjustment;
|
||||||
bool allowEditing;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CACHE> {
|
class BedMeshEditScreen : public BedMeshBase, public CachedScreen<BED_MESH_EDIT_SCREEN_CACHE> {
|
||||||
private:
|
private:
|
||||||
enum MeshOpts {
|
static float getHighlightedValue();
|
||||||
USE_POINTS = 0x01,
|
|
||||||
USE_COLORS = 0x02,
|
|
||||||
USE_TAGS = 0x04,
|
|
||||||
USE_HIGHLIGHT = 0x08,
|
|
||||||
USE_AUTOSCALE = 0x10
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t pointToTag(uint8_t x, uint8_t y);
|
|
||||||
static bool tagToPoint(uint8_t tag, xy_uint8_t &pt);
|
|
||||||
static float getHighlightedValue(bool nanAsZero);
|
|
||||||
static void setHighlightedValue(float value);
|
static void setHighlightedValue(float value);
|
||||||
static void moveToHighlightedValue();
|
static void moveToHighlightedValue();
|
||||||
static void adjustHighlightedValue(float increment);
|
static void adjustHighlightedValue(float increment);
|
||||||
static void saveAdjustedHighlightedValue();
|
static void saveAdjustedHighlightedValue();
|
||||||
static void changeHighlightedValue(uint8_t tag);
|
static bool changeHighlightedValue(uint8_t tag);
|
||||||
static void drawHighlightedPointValue();
|
static void drawHighlightedPointValue();
|
||||||
static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max = 0.1);
|
|
||||||
public:
|
public:
|
||||||
static void onMeshUpdate(const int8_t x, const int8_t y, const float val);
|
|
||||||
static void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t);
|
|
||||||
static void onEntry();
|
static void onEntry();
|
||||||
static void onRedraw(draw_mode_t);
|
static void onRedraw(draw_mode_t);
|
||||||
|
static bool onTouchHeld(uint8_t tag);
|
||||||
static bool onTouchEnd(uint8_t tag);
|
static bool onTouchEnd(uint8_t tag);
|
||||||
|
static void show();
|
||||||
static void startMeshProbe();
|
|
||||||
static void showMesh();
|
|
||||||
static void showMeshEditor();
|
|
||||||
};
|
};
|
|
@ -0,0 +1,172 @@
|
||||||
|
/****************************
|
||||||
|
* bed_mesh_view_screen.cpp *
|
||||||
|
****************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* To view a copy of the GNU General Public License, go to the following *
|
||||||
|
* location: <https://www.gnu.org/licenses/>. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "screens.h"
|
||||||
|
#include "screen_data.h"
|
||||||
|
|
||||||
|
#ifdef FTDI_BED_MESH_VIEW_SCREEN
|
||||||
|
|
||||||
|
using namespace FTDI;
|
||||||
|
using namespace Theme;
|
||||||
|
using namespace ExtUI;
|
||||||
|
|
||||||
|
constexpr static BedMeshViewScreenData &mydata = screen_data.BedMeshViewScreen;
|
||||||
|
constexpr static float gaugeThickness = 0.25;
|
||||||
|
|
||||||
|
#if ENABLED(TOUCH_UI_PORTRAIT)
|
||||||
|
#define GRID_COLS 3
|
||||||
|
#define GRID_ROWS 10
|
||||||
|
|
||||||
|
#define MESH_POS BTN_POS(1, 2), BTN_SIZE(3,5)
|
||||||
|
#define MESSAGE_POS BTN_POS(1, 7), BTN_SIZE(3,1)
|
||||||
|
#define Z_LABEL_POS BTN_POS(1, 8), BTN_SIZE(1,1)
|
||||||
|
#define Z_VALUE_POS BTN_POS(2, 8), BTN_SIZE(2,1)
|
||||||
|
#define OKAY_POS BTN_POS(1,10), BTN_SIZE(3,1)
|
||||||
|
#else
|
||||||
|
#define GRID_COLS 5
|
||||||
|
#define GRID_ROWS 5
|
||||||
|
|
||||||
|
#define MESH_POS BTN_POS(1,1), BTN_SIZE(3,5)
|
||||||
|
#define MESSAGE_POS BTN_POS(4,1), BTN_SIZE(2,1)
|
||||||
|
#define Z_LABEL_POS BTN_POS(4,2), BTN_SIZE(2,1)
|
||||||
|
#define Z_VALUE_POS BTN_POS(4,3), BTN_SIZE(2,1)
|
||||||
|
#define OKAY_POS BTN_POS(4,5), BTN_SIZE(2,1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static float meshGetter(uint8_t x, uint8_t y, void*) {
|
||||||
|
xy_uint8_t pos;
|
||||||
|
pos.x = x;
|
||||||
|
pos.y = y;
|
||||||
|
return ExtUI::getMeshPoint(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::onEntry() {
|
||||||
|
mydata.highlight.x = -1;
|
||||||
|
mydata.count = GRID_MAX_POINTS;
|
||||||
|
mydata.message = nullptr;
|
||||||
|
BaseScreen::onEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::drawHighlightedPointValue() {
|
||||||
|
CommandProcessor cmd;
|
||||||
|
cmd.font(Theme::font_medium)
|
||||||
|
.colors(normal_btn)
|
||||||
|
.text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
|
||||||
|
.font(font_small);
|
||||||
|
|
||||||
|
if(mydata.highlight.x != -1)
|
||||||
|
draw_adjuster_value(cmd, Z_VALUE_POS, ExtUI::getMeshPoint(mydata.highlight), GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
||||||
|
|
||||||
|
cmd.colors(action_btn)
|
||||||
|
.tag(1).button(OKAY_POS, GET_TEXT_F(MSG_BUTTON_OKAY))
|
||||||
|
.tag(0);
|
||||||
|
|
||||||
|
if(mydata.message) cmd.text(MESSAGE_POS, mydata.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::onRedraw(draw_mode_t what) {
|
||||||
|
#define _INSET_POS(x,y,w,h) x + min(w,h)/10, y + min(w,h)/10, w - min(w,h)/5, h - min(w,h)/5
|
||||||
|
#define INSET_POS(pos) _INSET_POS(pos)
|
||||||
|
|
||||||
|
CommandProcessor cmd;
|
||||||
|
|
||||||
|
if (what & BACKGROUND) {
|
||||||
|
cmd.cmd(CLEAR_COLOR_RGB(bg_color))
|
||||||
|
.cmd(CLEAR(true,true,true));
|
||||||
|
drawMeshBackground(cmd, INSET_POS(MESH_POS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (what & FOREGROUND) {
|
||||||
|
const float progress = sq(float(mydata.count) / GRID_MAX_POINTS);
|
||||||
|
if (progress >= 1.0)
|
||||||
|
drawHighlightedPointValue();
|
||||||
|
drawMeshForeground(cmd, INSET_POS(MESH_POS), meshGetter, nullptr, pointToTag(mydata.highlight.x, mydata.highlight.y), progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BedMeshViewScreen::onTouchEnd(uint8_t tag) {
|
||||||
|
switch (tag) {
|
||||||
|
case 1: GOTO_PREVIOUS(); return true;
|
||||||
|
default: return tagToPoint(tag, mydata.highlight);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::onMeshUpdate(const int8_t, const int8_t, const float) {
|
||||||
|
if (AT_SCREEN(BedMeshViewScreen)) {
|
||||||
|
onRefresh();
|
||||||
|
ExtUI::yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
|
||||||
|
switch (state) {
|
||||||
|
case ExtUI::G29_START:
|
||||||
|
mydata.message = nullptr;
|
||||||
|
mydata.count = 0;
|
||||||
|
break;
|
||||||
|
case ExtUI::G29_FINISH:
|
||||||
|
if (mydata.count == GRID_MAX_POINTS && ExtUI::getMeshValid())
|
||||||
|
mydata.message = GET_TEXT_F(MSG_BED_MAPPING_DONE);
|
||||||
|
else
|
||||||
|
mydata.message = GET_TEXT_F(MSG_BED_MAPPING_INCOMPLETE);
|
||||||
|
mydata.count = GRID_MAX_POINTS;
|
||||||
|
break;
|
||||||
|
case ExtUI::G26_START:
|
||||||
|
GOTO_SCREEN(BedMeshViewScreen);
|
||||||
|
mydata.message = nullptr;
|
||||||
|
mydata.count = 0;
|
||||||
|
break;
|
||||||
|
case ExtUI::G26_FINISH:
|
||||||
|
GOTO_SCREEN(StatusScreen);
|
||||||
|
break;
|
||||||
|
case ExtUI::G29_POINT_START:
|
||||||
|
case ExtUI::G26_POINT_START:
|
||||||
|
mydata.highlight.x = x;
|
||||||
|
mydata.highlight.y = y;
|
||||||
|
break;
|
||||||
|
case ExtUI::G29_POINT_FINISH:
|
||||||
|
case ExtUI::G26_POINT_FINISH:
|
||||||
|
mydata.count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BedMeshViewScreen::onMeshUpdate(x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::doProbe() {
|
||||||
|
GOTO_SCREEN(BedMeshViewScreen);
|
||||||
|
mydata.count = 0;
|
||||||
|
injectCommands_P(PSTR(BED_LEVELING_COMMANDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::doMeshValidation() {
|
||||||
|
mydata.count = 0;
|
||||||
|
GOTO_SCREEN(StatusScreen);
|
||||||
|
injectCommands_P(PSTR("G28 O\nM117 Heating...\nG26 R X0 Y0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BedMeshViewScreen::show() {
|
||||||
|
injectCommands_P(PSTR("G29 L1"));
|
||||||
|
GOTO_SCREEN(BedMeshViewScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FTDI_BED_MESH_VIEW_SCREEN
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**************************
|
||||||
|
* bed_mesh_view_screen.h *
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Written By Marcio Teixeira 2020 *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* To view a copy of the GNU General Public License, go to the following *
|
||||||
|
* location: <https://www.gnu.org/licenses/>. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define FTDI_BED_MESH_VIEW_SCREEN
|
||||||
|
#define FTDI_BED_MESH_VIEW_SCREEN_CLASS BedMeshViewScreen
|
||||||
|
|
||||||
|
struct BedMeshViewScreenData {
|
||||||
|
progmem_str message;
|
||||||
|
uint8_t count;
|
||||||
|
xy_uint8_t highlight;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BedMeshViewScreen : public BedMeshBase, public CachedScreen<BED_MESH_VIEW_SCREEN_CACHE> {
|
||||||
|
private:
|
||||||
|
static float getHighlightedValue();
|
||||||
|
static bool changeHighlightedValue(uint8_t tag);
|
||||||
|
static void drawHighlightedPointValue();
|
||||||
|
public:
|
||||||
|
static void onMeshUpdate(const int8_t x, const int8_t y, const float val);
|
||||||
|
static void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t);
|
||||||
|
static void onEntry();
|
||||||
|
static void onRedraw(draw_mode_t);
|
||||||
|
static bool onTouchEnd(uint8_t tag);
|
||||||
|
|
||||||
|
static void doProbe();
|
||||||
|
static void doMeshValidation();
|
||||||
|
static void show();
|
||||||
|
};
|
|
@ -111,20 +111,17 @@ bool LevelingMenu::onTouchEnd(uint8_t tag) {
|
||||||
#define BED_LEVELING_COMMANDS "G29"
|
#define BED_LEVELING_COMMANDS "G29"
|
||||||
#endif
|
#endif
|
||||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||||
BedMeshScreen::startMeshProbe();
|
BedMeshViewScreen::doProbe();
|
||||||
#else
|
#else
|
||||||
SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
|
SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||||
case 4: BedMeshScreen::showMesh(); break;
|
case 4: BedMeshViewScreen::show(); break;
|
||||||
case 5: BedMeshScreen::showMeshEditor(); break;
|
case 5: BedMeshEditScreen::show(); break;
|
||||||
#endif
|
#endif
|
||||||
#if ENABLED(G26_MESH_VALIDATION)
|
#if ENABLED(G26_MESH_VALIDATION)
|
||||||
case 6:
|
case 6: BedMeshViewScreen::doMeshValidation(); break;
|
||||||
GOTO_SCREEN(StatusScreen);
|
|
||||||
injectCommands_P(PSTR("M117 Printing Test Pattern\nG28 O\nG26 R"));
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
#if ENABLED(BLTOUCH)
|
#if ENABLED(BLTOUCH)
|
||||||
case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
|
case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
|
||||||
|
|
|
@ -55,7 +55,8 @@ union screen_data_t {
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_CHANGE_FILAMENT_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_CHANGE_FILAMENT_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_FILES_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_FILES_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_MOVE_AXIS_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_MOVE_AXIS_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_BED_MESH_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_BED_MESH_VIEW_SCREEN)
|
||||||
|
DECL_DATA_IF_INCLUDED(FTDI_BED_MESH_EDIT_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_STRESS_TEST_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_STRESS_TEST_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_COCOA_PREHEAT_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_COCOA_PREHEAT_SCREEN)
|
||||||
DECL_DATA_IF_INCLUDED(FTDI_COCOA_LOAD_CHOCOLATE_SCREEN)
|
DECL_DATA_IF_INCLUDED(FTDI_COCOA_LOAD_CHOCOLATE_SCREEN)
|
||||||
|
|
|
@ -75,7 +75,8 @@ SCREEN_TABLE {
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_STEPPER_BUMP_SENSITIVITY_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_STEPPER_BUMP_SENSITIVITY_SCREEN)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_LEVELING_MENU)
|
DECL_SCREEN_IF_INCLUDED(FTDI_LEVELING_MENU)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_Z_OFFSET_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_Z_OFFSET_SCREEN)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_BED_MESH_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_BED_MESH_VIEW_SCREEN)
|
||||||
|
DECL_SCREEN_IF_INCLUDED(FTDI_BED_MESH_EDIT_SCREEN)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_NOZZLE_OFFSETS_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_NOZZLE_OFFSETS_SCREEN)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_BACKLASH_COMP_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_BACKLASH_COMP_SCREEN)
|
||||||
DECL_SCREEN_IF_INCLUDED(FTDI_FEEDRATE_PERCENT_SCREEN)
|
DECL_SCREEN_IF_INCLUDED(FTDI_FEEDRATE_PERCENT_SCREEN)
|
||||||
|
|
|
@ -61,7 +61,8 @@ enum {
|
||||||
ZOFFSET_SCREEN_CACHE,
|
ZOFFSET_SCREEN_CACHE,
|
||||||
#endif
|
#endif
|
||||||
#if HAS_MESH
|
#if HAS_MESH
|
||||||
BED_MESH_SCREEN_CACHE,
|
BED_MESH_VIEW_SCREEN_CACHE,
|
||||||
|
BED_MESH_EDIT_SCREEN_CACHE,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if ENABLED(BABYSTEPPING)
|
#if ENABLED(BABYSTEPPING)
|
||||||
|
@ -206,7 +207,9 @@ enum {
|
||||||
#include "z_offset_screen.h"
|
#include "z_offset_screen.h"
|
||||||
#endif
|
#endif
|
||||||
#if HAS_MESH
|
#if HAS_MESH
|
||||||
#include "bed_mesh_screen.h"
|
#include "bed_mesh_base.h"
|
||||||
|
#include "bed_mesh_view_screen.h"
|
||||||
|
#include "bed_mesh_edit_screen.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -168,10 +168,14 @@ namespace ExtUI {
|
||||||
inline void onMeshUpdate(const xy_int8_t &pos, const_float_t zval) { onMeshUpdate(pos.x, pos.y, zval); }
|
inline void onMeshUpdate(const xy_int8_t &pos, const_float_t zval) { onMeshUpdate(pos.x, pos.y, zval); }
|
||||||
|
|
||||||
typedef enum : uint8_t {
|
typedef enum : uint8_t {
|
||||||
MESH_START, // Prior to start of probe
|
G29_START, // Prior to start of probe
|
||||||
MESH_FINISH, // Following probe of all points
|
G29_FINISH, // Following probe of all points
|
||||||
PROBE_START, // Beginning probe of grid location
|
G29_POINT_START, // Beginning probe of grid location
|
||||||
PROBE_FINISH // Finished probe of grid location
|
G29_POINT_FINISH, // Finished probe of grid location
|
||||||
|
G26_START,
|
||||||
|
G26_FINISH,
|
||||||
|
G26_POINT_START,
|
||||||
|
G26_POINT_FINISH
|
||||||
} probe_state_t;
|
} probe_state_t;
|
||||||
void onMeshUpdate(const int8_t xpos, const int8_t ypos, probe_state_t state);
|
void onMeshUpdate(const int8_t xpos, const int8_t ypos, probe_state_t state);
|
||||||
inline void onMeshUpdate(const xy_int8_t &pos, probe_state_t state) { onMeshUpdate(pos.x, pos.y, state); }
|
inline void onMeshUpdate(const xy_int8_t &pos, probe_state_t state) { onMeshUpdate(pos.x, pos.y, state); }
|
||||||
|
|
Loading…
Reference in a new issue