0
0
Fork 0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2025-04-23 16:01:42 +00:00

🧑‍💻 Encapsulate ProUI G-code preview

This commit is contained in:
Scott Lahteine 2023-08-24 15:09:03 -05:00
parent e1121a4cd0
commit 4613f85bb7
3 changed files with 121 additions and 131 deletions

View file

@ -288,7 +288,7 @@ MenuItem *editZValueItem = nullptr;
bool isPrinting() { return printingIsActive() || printingIsPaused(); } bool isPrinting() { return printingIsActive() || printingIsPaused(); }
bool sdPrinting() { return isPrinting() && IS_SD_FILE_OPEN(); } bool sdPrinting() { return isPrinting() && IS_SD_FILE_OPEN(); }
bool Host_Printing() { return isPrinting() && !IS_SD_FILE_OPEN(); } bool hostPrinting() { return isPrinting() && !IS_SD_FILE_OPEN(); }
#define DWIN_LANGUAGE_EEPROM_ADDRESS 0x01 // Between 0x01 and 0x63 (EEPROM_OFFSET-1) #define DWIN_LANGUAGE_EEPROM_ADDRESS 0x01 // Between 0x01 and 0x63 (EEPROM_OFFSET-1)
// BL24CXX::check() uses 0x00 // BL24CXX::check() uses 0x00
@ -634,9 +634,9 @@ void drawPrintDone() {
DWINUI::clearMainArea(); DWINUI::clearMainArea();
dwinPrintHeader(nullptr); dwinPrintHeader(nullptr);
#if HAS_GCODE_PREVIEW #if HAS_GCODE_PREVIEW
const bool haspreview = Preview_Valid(); const bool haspreview = preview.valid();
if (haspreview) { if (haspreview) {
Preview_Show(); preview.show();
DWINUI::drawButton(BTN_Continue, 86, 295); DWINUI::drawButton(BTN_Continue, 86, 295);
} }
#else #else
@ -1675,7 +1675,7 @@ void dwinLevelingDone() {
// Started a Print Job // Started a Print Job
void dwinPrintStarted() { void dwinPrintStarted() {
TERN_(HAS_GCODE_PREVIEW, if (Host_Printing()) Preview_Invalidate()); TERN_(HAS_GCODE_PREVIEW, if (hostPrinting()) preview.invalidate());
TERN_(SET_PROGRESS_PERCENT, ui.progress_reset()); TERN_(SET_PROGRESS_PERCENT, ui.progress_reset());
TERN_(SET_REMAINING_TIME, ui.reset_remaining_time()); TERN_(SET_REMAINING_TIME, ui.reset_remaining_time());
hmiFlag.pause_flag = false; hmiFlag.pause_flag = false;
@ -1960,7 +1960,7 @@ void dwinRedrawScreen() {
void gotoConfirmToPrint() { void gotoConfirmToPrint() {
#if HAS_GCODE_PREVIEW #if HAS_GCODE_PREVIEW
if (hmiData.enablePreview) return gotoPopup(Preview_DrawFromSD, onClickConfirmToPrint); if (hmiData.enablePreview) return gotoPopup(preview.drawFromSD, onClickConfirmToPrint);
#endif #endif
card.openAndPrintFile(card.filename); // Direct print SD file card.openAndPrintFile(card.filename); // Direct print SD file
} }

View file

@ -31,6 +31,8 @@
#if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW) #if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW)
#include "gcode_preview.h"
#include "../../../core/types.h" #include "../../../core/types.h"
#include "../../marlinui.h" #include "../../marlinui.h"
#include "../../../sd/cardreader.h" #include "../../../sd/cardreader.h"
@ -38,78 +40,66 @@
#include "dwin.h" #include "dwin.h"
#include "dwin_popup.h" #include "dwin_popup.h"
#include "base64.hpp" #include "base64.hpp"
#include "gcode_preview.h"
#define THUMBWIDTH 230 #define THUMBWIDTH 230
#define THUMBHEIGHT 180 #define THUMBHEIGHT 180
Preview preview;
typedef struct { typedef struct {
char name[13] = ""; // 8.3 + null char name[13] = ""; // 8.3 + null
uint32_t thumbstart = 0; uint32_t thumbstart = 0;
int thumbsize = 0; int thumbsize = 0;
int thumbheight = 0; int thumbheight = 0, thumbwidth = 0;
int thumbwidth = 0;
uint8_t *thumbdata = nullptr;
float time = 0; float time = 0;
float filament = 0; float filament = 0;
float layer = 0; float layer = 0;
float width = 0; float width = 0, height = 0, length = 0;
float height = 0;
float length = 0;
void setname(const char * const fn);
void clear();
} fileprop_t;
fileprop_t fileprop;
void fileprop_t::setname(const char * const fn) { void setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(&name[0], fn, len); memcpy(name, fn, len);
name[len] = '\0'; name[len] = '\0';
} }
void fileprop_t::clear() { void clear() {
fileprop.name[0] = '\0'; fileprop.name[0] = '\0';
fileprop.thumbstart = 0; fileprop.thumbstart = 0;
fileprop.thumbsize = 0; fileprop.thumbsize = 0;
fileprop.thumbheight = 0; fileprop.thumbheight = fileprop.thumbwidth = 0;
fileprop.thumbwidth = 0;
fileprop.thumbdata = nullptr;
fileprop.time = 0; fileprop.time = 0;
fileprop.filament = 0; fileprop.filament = 0;
fileprop.layer = 0; fileprop.layer = 0;
fileprop.height = 0; fileprop.height = fileprop.width = fileprop.length = 0;
fileprop.width = 0;
fileprop.length = 0;
} }
void Get_Value(char *buf, const char * const key, float &value) { } fileprop_t;
fileprop_t fileprop;
void getValue(const char * const buf, PGM_P const key, float &value) {
if (value != 0.0f) return;
char *posptr = strstr_P(buf, key);
if (posptr == nullptr) return;
char num[10] = ""; char num[10] = "";
char * posptr = 0; for (uint8_t i = 0; i < sizeof(num);) {
uint8_t i = 0; const char c = *posptr;
if (!!value) return; if (ISEOL(c) || c == '\0') {
posptr = strstr(buf, key);
if (posptr != nullptr) {
while (i < sizeof(num)) {
char c = posptr[0];
if (!ISEOL(c) && (c != 0)) {
if ((c > 47 && c < 58) || (c == '.')) num[i++] = c;
posptr++;
}
else {
num[i] = '\0'; num[i] = '\0';
value = atof(num); value = atof(num);
return; break;
}
} }
if (WITHIN(c, '0', '9') || c == '.') num[i++] = c;
posptr++;
} }
} }
bool Has_Preview() { bool Preview::hasPreview() {
const char * tbstart = "; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT); const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT));
char * posptr = 0; char *posptr = nullptr;
uint8_t nbyte = 1;
uint32_t indx = 0; uint32_t indx = 0;
char buf[256];
float tmp = 0; float tmp = 0;
fileprop.clear(); fileprop.clear();
@ -117,30 +107,32 @@ bool Has_Preview() {
card.openFileRead(fileprop.name); card.openFileRead(fileprop.name);
while ((nbyte > 0) && (indx < 4 * sizeof(buf)) && !fileprop.thumbstart) { char buf[256];
uint8_t nbyte = 1;
while (!fileprop.thumbstart && nbyte > 0 && indx < 4 * sizeof(buf)) {
nbyte = card.read(buf, sizeof(buf) - 1); nbyte = card.read(buf, sizeof(buf) - 1);
if (nbyte > 0) { if (nbyte > 0) {
buf[nbyte] = '\0'; buf[nbyte] = '\0';
Get_Value(buf, ";TIME:", fileprop.time); getValue(buf, PSTR(";TIME:"), fileprop.time);
Get_Value(buf, ";Filament used:", fileprop.filament); getValue(buf, PSTR(";Filament used:"), fileprop.filament);
Get_Value(buf, ";Layer height:", fileprop.layer); getValue(buf, PSTR(";Layer height:"), fileprop.layer);
Get_Value(buf, ";MINX:", tmp); getValue(buf, PSTR(";MINX:"), tmp);
Get_Value(buf, ";MAXX:", fileprop.width); getValue(buf, PSTR(";MAXX:"), fileprop.width);
fileprop.width -= tmp; fileprop.width -= tmp;
tmp = 0; tmp = 0;
Get_Value(buf, ";MINY:", tmp); getValue(buf, PSTR(";MINY:"), tmp);
Get_Value(buf, ";MAXY:", fileprop.length); getValue(buf, PSTR(";MAXY:"), fileprop.length);
fileprop.length -= tmp; fileprop.length -= tmp;
tmp = 0; tmp = 0;
Get_Value(buf, ";MINZ:", tmp); getValue(buf, PSTR(";MINZ:"), tmp);
Get_Value(buf, ";MAXZ:", fileprop.height); getValue(buf, PSTR(";MAXZ:"), fileprop.height);
fileprop.height -= tmp; fileprop.height -= tmp;
posptr = strstr(buf, tbstart); posptr = strstr_P(buf, tbstart);
if (posptr != nullptr) { if (posptr != nullptr) {
fileprop.thumbstart = indx + (posptr - &buf[0]); fileprop.thumbstart = indx + (posptr - &buf[0]);
} }
else { else {
indx += _MAX(10, nbyte - (signed)strlen(tbstart)); indx += _MAX(10, nbyte - (signed)strlen_P(tbstart));
card.setIndex(indx); card.setIndex(indx);
} }
} }
@ -149,98 +141,89 @@ bool Has_Preview() {
if (!fileprop.thumbstart) { if (!fileprop.thumbstart) {
card.closefile(); card.closefile();
LCD_MESSAGE_F("Thumbnail not found"); LCD_MESSAGE_F("Thumbnail not found");
return 0; return false;
} }
// Get the size of the thumbnail // Get the size of the thumbnail
card.setIndex(fileprop.thumbstart + strlen(tbstart)); card.setIndex(fileprop.thumbstart + strlen_P(tbstart));
for (uint8_t i = 0; i < 16; i++) { for (uint8_t i = 0; i < 16; i++) {
char c = card.get(); const char c = card.get();
if (!ISEOL(c)) { if (ISEOL(c)) { buf[i] = '\0'; break; }
buf[i] = c; buf[i] = c;
} }
else {
buf[i] = 0;
break;
}
}
fileprop.thumbsize = atoi(buf); fileprop.thumbsize = atoi(buf);
// Exit if there isn't a thumbnail // Exit if there isn't a thumbnail
if (!fileprop.thumbsize) { if (!fileprop.thumbsize) {
card.closefile(); card.closefile();
LCD_MESSAGE_F("Invalid Thumbnail Size"); LCD_MESSAGE_F("Invalid Thumbnail Size");
return 0; return false;
} }
uint16_t readed = 0;
uint8_t buf64[fileprop.thumbsize]; uint8_t buf64[fileprop.thumbsize];
uint16_t nread = 0;
fileprop.thumbdata = new uint8_t[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail while (nread < fileprop.thumbsize) {
const uint8_t c = card.get();
while (readed < fileprop.thumbsize) { if (!ISEOL(c) && c != ';' && c != ' ')
uint8_t c = card.get(); buf64[nread++] = c;
if (!ISEOL(c) && (c != ';') && (c != ' ')) {
buf64[readed] = c;
readed++;
}
} }
card.closefile(); card.closefile();
buf64[readed] = 0; buf64[nread] = '\0';
uint8_t thumbdata[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail
fileprop.thumbsize = decode_base64(buf64, thumbdata);
DWINUI::writeToSRAM(0x00, fileprop.thumbsize, thumbdata);
fileprop.thumbwidth = THUMBWIDTH; fileprop.thumbwidth = THUMBWIDTH;
fileprop.thumbheight = THUMBHEIGHT; fileprop.thumbheight = THUMBHEIGHT;
fileprop.thumbsize = decode_base64(buf64, fileprop.thumbdata); card.closefile();
DWINUI::WriteToSRAM(0x00, fileprop.thumbsize, fileprop.thumbdata);
delete[] fileprop.thumbdata;
return true; return true;
} }
void Preview_DrawFromSD() { void Preview::drawFromSD() {
if (Has_Preview()) { if (!hasPreview()) {
hmiFlag.select_flag = 1;
wait_for_user = false;
return;
}
MString<45> buf; MString<45> buf;
char str_1[6] = "", str_2[6] = "", str_3[6] = "";
dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) { if (fileprop.time) {
buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60); buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::drawString(20, 10, &buf); DWINUI::drawString(20, 10, &buf);
} }
if (fileprop.filament) { if (fileprop.filament) {
buf.setf(F("Filament used: %s m"), dtostrf(fileprop.filament, 1, 2, str_1)); buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m"));
DWINUI::drawString(20, 30, &buf); DWINUI::drawString(20, 30, &buf);
} }
if (fileprop.layer) { if (fileprop.layer) {
buf.setf(F("Layer height: %s mm"), dtostrf(fileprop.layer, 1, 2, str_1)); buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm"));
DWINUI::drawString(20, 50, &buf); DWINUI::drawString(20, 50, &buf);
} }
if (fileprop.width) { if (fileprop.width) {
buf.setf(F("Volume: %sx%sx%s mm"), dtostrf(fileprop.width, 1, 1, str_1), dtostrf(fileprop.length, 1, 1, str_2), dtostrf(fileprop.height, 1, 1, str_3)); buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm"));
DWINUI::drawString(20, 70, &buf); DWINUI::drawString(20, 70, &buf);
} }
DWINUI::drawButton(BTN_Print, 26, 290); DWINUI::drawButton(BTN_Print, 26, 290);
DWINUI::drawButton(BTN_Cancel, 146, 290); DWINUI::drawButton(BTN_Cancel, 146, 290);
Preview_Show(); show();
drawSelectHighlight(true, 290); drawSelectHighlight(true, 290);
dwinUpdateLCD(); dwinUpdateLCD();
} }
else {
hmiFlag.select_flag = 1;
wait_for_user = false;
}
}
void Preview_Invalidate() { void Preview::invalidate() {
fileprop.thumbsize = 0; fileprop.thumbsize = 0;
} }
bool Preview_Valid() { bool Preview::valid() {
return !!fileprop.thumbsize; return !!fileprop.thumbsize;
} }
void Preview_Show() { void Preview::show() {
const uint8_t xpos = (DWIN_WIDTH - fileprop.thumbwidth) / 2; const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2,
const uint8_t ypos = (205 - fileprop.thumbheight) / 2 + 87; ypos = (205 - fileprop.thumbheight) / 2 + 87;
dwinIconShow(xpos, ypos, 0x00); dwinIconShow(xpos, ypos, 0x00);
} }
#endif // HAS_GCODE_PREVIEW && DWIN_LCD_PROUI #endif // DWIN_LCD_PROUI && HAS_GCODE_PREVIEW

View file

@ -28,7 +28,14 @@
* Date: 2022/09/03 * Date: 2022/09/03
*/ */
void Preview_DrawFromSD(); class Preview {
void Preview_Invalidate(); public:
bool Preview_Valid(); static void drawFromSD();
void Preview_Show(); static void invalidate();
static bool valid();
static void show();
private:
static bool hasPreview();
};
extern Preview preview;