Skip to content

Commit

Permalink
πŸ§‘β€πŸ’» Encapsulate ProUI G-code preview
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead authored and EvilGremlin committed Oct 26, 2023
1 parent 95d3ecd commit 6b6df94
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 131 deletions.
10 changes: 5 additions & 5 deletions Marlin/src/lcd/e3v2/proui/dwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ MenuItem *editZValueItem = nullptr;

bool isPrinting() { return printingIsActive() || printingIsPaused(); }
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)
// BL24CXX::check() uses 0x00
Expand Down Expand Up @@ -634,9 +634,9 @@ void drawPrintDone() {
DWINUI::clearMainArea();
dwinPrintHeader(nullptr);
#if HAS_GCODE_PREVIEW
const bool haspreview = Preview_Valid();
const bool haspreview = preview.valid();
if (haspreview) {
Preview_Show();
preview.show();
DWINUI::drawButton(BTN_Continue, 86, 295);
}
#else
Expand Down Expand Up @@ -1675,7 +1675,7 @@ void dwinLevelingDone() {

// Started a Print Job
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_REMAINING_TIME, ui.reset_remaining_time());
hmiFlag.pause_flag = false;
Expand Down Expand Up @@ -1960,7 +1960,7 @@ void dwinRedrawScreen() {

void gotoConfirmToPrint() {
#if HAS_GCODE_PREVIEW
if (hmiData.enablePreview) return gotoPopup(Preview_DrawFromSD, onClickConfirmToPrint);
if (hmiData.enablePreview) return gotoPopup(preview.drawFromSD, onClickConfirmToPrint);
#endif
card.openAndPrintFile(card.filename); // Direct print SD file
}
Expand Down
227 changes: 105 additions & 122 deletions Marlin/src/lcd/e3v2/proui/gcode_preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,116 +31,108 @@

#if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW)

#include "gcode_preview.h"

#include "../../../core/types.h"
#include "../../marlinui.h"
#include "../../../sd/cardreader.h"
#include "../../../MarlinCore.h" // for wait_for_user
#include "dwin.h"
#include "dwin_popup.h"
#include "base64.hpp"
#include "gcode_preview.h"

#define THUMBWIDTH 230
#define THUMBHEIGHT 180

Preview preview;

typedef struct {
char name[13] = ""; //8.3 + null
char name[13] = ""; // 8.3 + null
uint32_t thumbstart = 0;
int thumbsize = 0;
int thumbheight = 0;
int thumbwidth = 0;
uint8_t *thumbdata = nullptr;
int thumbheight = 0, thumbwidth = 0;
float time = 0;
float filament = 0;
float layer = 0;
float width = 0;
float height = 0;
float length = 0;
void setname(const char * const fn);
void clear();
float width = 0, height = 0, length = 0;

void setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(name, fn, len);
name[len] = '\0';
}

void clear() {
fileprop.name[0] = '\0';
fileprop.thumbstart = 0;
fileprop.thumbsize = 0;
fileprop.thumbheight = fileprop.thumbwidth = 0;
fileprop.time = 0;
fileprop.filament = 0;
fileprop.layer = 0;
fileprop.height = fileprop.width = fileprop.length = 0;
}

} fileprop_t;

fileprop_t fileprop;

void fileprop_t::setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(&name[0], fn, len);
name[len] = '\0';
}
void getValue(const char * const buf, PGM_P const key, float &value) {
if (value != 0.0f) return;

void fileprop_t::clear() {
fileprop.name[0] = '\0';
fileprop.thumbstart = 0;
fileprop.thumbsize = 0;
fileprop.thumbheight = 0;
fileprop.thumbwidth = 0;
fileprop.thumbdata = nullptr;
fileprop.time = 0;
fileprop.filament = 0;
fileprop.layer = 0;
fileprop.height = 0;
fileprop.width = 0;
fileprop.length = 0;
}
char *posptr = strstr_P(buf, key);
if (posptr == nullptr) return;

void Get_Value(char *buf, const char * const key, float &value) {
char num[10] = "";
char * posptr = 0;
uint8_t i = 0;
if (!!value) return;
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';
value = atof(num);
return;
}
for (uint8_t i = 0; i < sizeof(num);) {
const char c = *posptr;
if (ISEOL(c) || c == '\0') {
num[i] = '\0';
value = atof(num);
break;
}
if (WITHIN(c, '0', '9') || c == '.') num[i++] = c;
posptr++;
}
}

bool Has_Preview() {
const char * tbstart = "; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT);
char * posptr = 0;
uint8_t nbyte = 1;
bool Preview::hasPreview() {
const char * const tbstart = PSTR("; thumbnail begin " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT));
char *posptr = nullptr;
uint32_t indx = 0;
char buf[256];
float tmp = 0;

fileprop.clear();
fileprop.setname(card.filename);

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);
if (nbyte > 0) {
buf[nbyte] = '\0';
Get_Value(buf, ";TIME:", fileprop.time);
Get_Value(buf, ";Filament used:", fileprop.filament);
Get_Value(buf, ";Layer height:", fileprop.layer);
Get_Value(buf, ";MINX:", tmp);
Get_Value(buf, ";MAXX:", fileprop.width);
getValue(buf, PSTR(";TIME:"), fileprop.time);
getValue(buf, PSTR(";Filament used:"), fileprop.filament);
getValue(buf, PSTR(";Layer height:"), fileprop.layer);
getValue(buf, PSTR(";MINX:"), tmp);
getValue(buf, PSTR(";MAXX:"), fileprop.width);
fileprop.width -= tmp;
tmp = 0;
Get_Value(buf, ";MINY:", tmp);
Get_Value(buf, ";MAXY:", fileprop.length);
getValue(buf, PSTR(";MINY:"), tmp);
getValue(buf, PSTR(";MAXY:"), fileprop.length);
fileprop.length -= tmp;
tmp = 0;
Get_Value(buf, ";MINZ:", tmp);
Get_Value(buf, ";MAXZ:", fileprop.height);
getValue(buf, PSTR(";MINZ:"), tmp);
getValue(buf, PSTR(";MAXZ:"), fileprop.height);
fileprop.height -= tmp;
posptr = strstr(buf, tbstart);
posptr = strstr_P(buf, tbstart);
if (posptr != nullptr) {
fileprop.thumbstart = indx + (posptr - &buf[0]);
}
else {
indx += _MAX(10, nbyte - (signed)strlen(tbstart));
indx += _MAX(10, nbyte - (signed)strlen_P(tbstart));
card.setIndex(indx);
}
}
Expand All @@ -149,98 +141,89 @@ bool Has_Preview() {
if (!fileprop.thumbstart) {
card.closefile();
LCD_MESSAGE_F("Thumbnail not found");
return 0;
return false;
}

// 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++) {
char c = card.get();
if (!ISEOL(c)) {
buf[i] = c;
}
else {
buf[i] = 0;
break;
}
const char c = card.get();
if (ISEOL(c)) { buf[i] = '\0'; break; }
buf[i] = c;
}
fileprop.thumbsize = atoi(buf);

// Exit if there isn't a thumbnail
if (!fileprop.thumbsize) {
card.closefile();
LCD_MESSAGE_F("Invalid Thumbnail Size");
return 0;
return false;
}

uint16_t readed = 0;
uint8_t buf64[fileprop.thumbsize];

fileprop.thumbdata = new uint8_t[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail

while (readed < fileprop.thumbsize) {
uint8_t c = card.get();
if (!ISEOL(c) && (c != ';') && (c != ' ')) {
buf64[readed] = c;
readed++;
}
uint16_t nread = 0;
while (nread < fileprop.thumbsize) {
const uint8_t c = card.get();
if (!ISEOL(c) && c != ';' && c != ' ')
buf64[nread++] = c;
}
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.thumbheight = THUMBHEIGHT;
fileprop.thumbsize = decode_base64(buf64, fileprop.thumbdata); card.closefile();
DWINUI::WriteToSRAM(0x00, fileprop.thumbsize, fileprop.thumbdata);
delete[] fileprop.thumbdata;

return true;
}

void Preview_DrawFromSD() {
if (Has_Preview()) {
MString<45> buf;
char str_1[6] = "", str_2[6] = "", str_3[6] = "";
dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) {
buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::drawString(20, 10, &buf);
}
if (fileprop.filament) {
buf.setf(F("Filament used: %s m"), dtostrf(fileprop.filament, 1, 2, str_1));
DWINUI::drawString(20, 30, &buf);
}
if (fileprop.layer) {
buf.setf(F("Layer height: %s mm"), dtostrf(fileprop.layer, 1, 2, str_1));
DWINUI::drawString(20, 50, &buf);
}
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));
DWINUI::drawString(20, 70, &buf);
}
DWINUI::drawButton(BTN_Print, 26, 290);
DWINUI::drawButton(BTN_Cancel, 146, 290);
Preview_Show();
drawSelectHighlight(true, 290);
dwinUpdateLCD();
}
else {
void Preview::drawFromSD() {
if (!hasPreview()) {
hmiFlag.select_flag = 1;
wait_for_user = false;
return;
}

MString<45> buf;
dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) {
buf.setf(F("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::drawString(20, 10, &buf);
}
if (fileprop.filament) {
buf.set(F("Filament used: "), p_float_t(fileprop.filament, 2), F(" m"));
DWINUI::drawString(20, 30, &buf);
}
if (fileprop.layer) {
buf.set(F("Layer height: "), p_float_t(fileprop.layer, 2), F(" mm"));
DWINUI::drawString(20, 50, &buf);
}
if (fileprop.width) {
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::drawButton(BTN_Print, 26, 290);
DWINUI::drawButton(BTN_Cancel, 146, 290);
show();
drawSelectHighlight(true, 290);
dwinUpdateLCD();
}

void Preview_Invalidate() {
void Preview::invalidate() {
fileprop.thumbsize = 0;
}

bool Preview_Valid() {
bool Preview::valid() {
return !!fileprop.thumbsize;
}

void Preview_Show() {
const uint8_t xpos = (DWIN_WIDTH - fileprop.thumbwidth) / 2;
const uint8_t ypos = (205 - fileprop.thumbheight) / 2 + 87;
void Preview::show() {
const uint8_t xpos = ((DWIN_WIDTH) - fileprop.thumbwidth) / 2,
ypos = (205 - fileprop.thumbheight) / 2 + 87;
dwinIconShow(xpos, ypos, 0x00);
}

#endif // HAS_GCODE_PREVIEW && DWIN_LCD_PROUI
#endif // DWIN_LCD_PROUI && HAS_GCODE_PREVIEW
15 changes: 11 additions & 4 deletions Marlin/src/lcd/e3v2/proui/gcode_preview.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@
* Date: 2022/09/03
*/

void Preview_DrawFromSD();
void Preview_Invalidate();
bool Preview_Valid();
void Preview_Show();
class Preview {
public:
static void drawFromSD();
static void invalidate();
static bool valid();
static void show();
private:
static bool hasPreview();
};

extern Preview preview;

0 comments on commit 6b6df94

Please sign in to comment.