mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 06:35:58 +08:00
Preview and GCodeViewer: removed file mapping for gcode window visualization + Fixed build on non Windows OSs
This commit is contained in:
parent
6b1dc90075
commit
0bea17c128
@ -1075,8 +1075,6 @@ ConfigSubstitutions ConfigBase::load_from_binary_gcode_file(const std::string& f
|
||||
throw Slic3r::RuntimeError(format("The selected file is not a valid binary gcode.\nError: %1%",
|
||||
std::string(bgcode::core::translate_result(res))));
|
||||
|
||||
fseek(file.f, 0, SEEK_END);
|
||||
const long file_size = ftell(file.f);
|
||||
rewind(file.f);
|
||||
|
||||
bgcode::core::FileHeader file_header;
|
||||
|
@ -25,10 +25,10 @@
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#if ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
#include <windows.h>
|
||||
#include <debugapi.h>
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#endif // ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
|
||||
static const float DEFAULT_TOOLPATH_WIDTH = 0.4f;
|
||||
static const float DEFAULT_TOOLPATH_HEIGHT = 0.2f;
|
||||
@ -1173,7 +1173,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
res = printer_metadata_block.read_data(*file.f, file_header, block_header);
|
||||
if (res != bgcode::core::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file '" + filename + "': " + std::string(bgcode::core::translate_result(res)) + "\n");
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#if ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
OutputDebugStringA("Printer metadata:\n");
|
||||
for (const auto& [key, value] : printer_metadata_block.raw_data) {
|
||||
OutputDebugStringA(key.c_str());
|
||||
@ -1181,7 +1181,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
OutputDebugStringA(value.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#endif // ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
|
||||
// read thumbnail blocks
|
||||
res = bgcode::core::read_next_block_header(*file.f, file_header, block_header, verify_checksum);
|
||||
@ -1229,7 +1229,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
res = print_metadata_block.read_data(*file.f, file_header, block_header);
|
||||
if (res != bgcode::core::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file '" + filename + "': " + std::string(bgcode::core::translate_result(res)) + "\n");
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#if ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
OutputDebugStringA("Print metadata:\n");
|
||||
for (const auto& [key, value] : print_metadata_block.raw_data) {
|
||||
OutputDebugStringA(key.c_str());
|
||||
@ -1237,7 +1237,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
OutputDebugStringA(value.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#endif // ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
|
||||
// read slicer metadata block
|
||||
res = bgcode::core::read_next_block_header(*file.f, file_header, block_header, verify_checksum);
|
||||
@ -1249,7 +1249,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
res = slicer_metadata_block.read_data(*file.f, file_header, block_header);
|
||||
if (res != bgcode::core::EResult::Success)
|
||||
throw Slic3r::RuntimeError("Error while reading file '" + filename + "': " + std::string(bgcode::core::translate_result(res)) + "\n");
|
||||
#if ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#if ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
OutputDebugStringA("Slicer metadata:\n");
|
||||
for (const auto& [key, value] : slicer_metadata_block.raw_data) {
|
||||
OutputDebugStringA(key.c_str());
|
||||
@ -1257,7 +1257,7 @@ void GCodeProcessor::process_binary_file(const std::string& filename, std::funct
|
||||
OutputDebugStringA(value.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE_DEBUG
|
||||
#endif // ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
DynamicPrintConfig config;
|
||||
config.apply(FullPrintConfig::defaults());
|
||||
std::string str;
|
||||
|
@ -63,13 +63,16 @@
|
||||
|
||||
|
||||
//====================
|
||||
// 2.6.1.alpha1 techs
|
||||
// 2.6.2.alpha1 techs
|
||||
//====================
|
||||
#define ENABLE_2_6_1_ALPHA1 1
|
||||
#define ENABLE_2_6_2_ALPHA1 1
|
||||
|
||||
// Enable export of binarized gcode
|
||||
#define ENABLE_BINARIZED_GCODE (1 && ENABLE_2_6_1_ALPHA1)
|
||||
#define ENABLE_BINARIZED_GCODE (1 && ENABLE_2_6_2_ALPHA1)
|
||||
#define ENABLE_BINARIZED_GCODE_DEBUG (1 && ENABLE_BINARIZED_GCODE)
|
||||
#ifdef _WIN32
|
||||
#define ENABLE_BINARIZED_GCODE_WIN_DEBUG (1 && ENABLE_BINARIZED_GCODE_DEBUG)
|
||||
#endif // _WIN32
|
||||
#define ENABLE_BINARIZED_GCODE_DEBUG_WINDOW (1 && ENABLE_BINARIZED_GCODE)
|
||||
|
||||
|
||||
|
@ -38,6 +38,11 @@
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
#include <windows.h>
|
||||
#include <debugapi.h>
|
||||
#endif // ENABLE_BINARIZED_GCODE_WIN_DEBUG
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
@ -364,13 +369,16 @@ void GCodeViewer::SequentialView::Marker::render()
|
||||
|
||||
void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, const std::vector<size_t>& lines_ends)
|
||||
{
|
||||
#if !ENABLE_BINARIZED_GCODE
|
||||
assert(! m_file.is_open());
|
||||
if (m_file.is_open())
|
||||
return;
|
||||
#endif // !ENABLE_BINARIZED_GCODE
|
||||
|
||||
m_filename = filename;
|
||||
m_lines_ends = lines_ends;
|
||||
|
||||
#if !ENABLE_BINARIZED_GCODE
|
||||
m_selected_line_id = 0;
|
||||
m_last_lines_size = 0;
|
||||
|
||||
@ -383,42 +391,217 @@ void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& fil
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to map file " << m_filename << ". Cannot show G-code window.";
|
||||
reset();
|
||||
}
|
||||
#endif // !ENABLE_BINARIZED_GCODE
|
||||
}
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, size_t curr_line_id)
|
||||
{
|
||||
auto update_lines = [this]() {
|
||||
m_lines_cache.clear();
|
||||
m_lines_cache.reserve(m_cache_range.size());
|
||||
FILE* file = boost::nowide::fopen(m_filename.c_str(), "rb");
|
||||
if (file != nullptr) {
|
||||
for (size_t id = *m_cache_range.start_id; id <= *m_cache_range.end_id; ++id) {
|
||||
assert(id > 0);
|
||||
// read line from file
|
||||
const size_t start = id == 1 ? 0 : m_lines_ends[id - 2];
|
||||
const size_t len = m_lines_ends[id - 1] - start;
|
||||
std::string gline(len, '\0');
|
||||
fseek(file, start, SEEK_SET);
|
||||
const size_t rsize = fread((void*)gline.data(), 1, len, file);
|
||||
if (ferror(file) || rsize != len) {
|
||||
m_lines_cache.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
std::string parameters;
|
||||
std::string comment;
|
||||
|
||||
// extract comment
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on);
|
||||
command = tokens.front();
|
||||
if (tokens.size() > 1)
|
||||
comment = ";" + tokens.back();
|
||||
|
||||
// extract gcode command and parameters
|
||||
if (!command.empty()) {
|
||||
boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on);
|
||||
command = tokens.front();
|
||||
if (tokens.size() > 1) {
|
||||
for (size_t i = 1; i < tokens.size(); ++i) {
|
||||
parameters += " " + tokens[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lines_cache.push_back({ command, parameters, comment });
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
};
|
||||
|
||||
static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT;
|
||||
static const ImVec4 SELECTION_RECT_COLOR = ImGuiWrapper::COL_ORANGE_DARK;
|
||||
static const ImVec4 COMMAND_COLOR = { 0.8f, 0.8f, 0.0f, 1.0f };
|
||||
static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f };
|
||||
static const ImVec4 ELLIPSIS_COLOR = { 0.0f, 0.7f, 0.0f, 1.0f };
|
||||
|
||||
if (!m_visible || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0)
|
||||
return;
|
||||
|
||||
// window height
|
||||
const float wnd_height = bottom - top;
|
||||
|
||||
// number of visible lines
|
||||
const float text_height = ImGui::CalcTextSize("0").y;
|
||||
const ImGuiStyle& style = ImGui::GetStyle();
|
||||
const size_t visible_lines_count = static_cast<size_t>((wnd_height - 2.0f * style.WindowPadding.y + style.ItemSpacing.y) / (text_height + style.ItemSpacing.y));
|
||||
|
||||
if (visible_lines_count == 0)
|
||||
return;
|
||||
|
||||
auto resize_range = [&](Range& range, size_t lines_count) {
|
||||
const size_t half_lines_count = lines_count / 2;
|
||||
range.start_id = (curr_line_id >= half_lines_count) ? curr_line_id - half_lines_count : 1;
|
||||
range.end_id = *range.start_id + lines_count - 1;
|
||||
if (*range.end_id >= m_lines_ends.size()) {
|
||||
range.end_id = m_lines_ends.size() - 1;
|
||||
range.start_id = *range.end_id - lines_count + 1;
|
||||
}
|
||||
};
|
||||
|
||||
// visible range
|
||||
Range visible_range;
|
||||
resize_range(visible_range, visible_lines_count);
|
||||
|
||||
// update cache if needed
|
||||
if (m_cache_range.empty() || !m_cache_range.contains(visible_range)) {
|
||||
resize_range(m_cache_range, 4 * visible_range.size());
|
||||
update_lines();
|
||||
}
|
||||
|
||||
// line number's column width
|
||||
const float id_width = ImGui::CalcTextSize(std::to_string(*visible_range.end_id).c_str()).x;
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
|
||||
auto add_item_to_line = [&imgui](const std::string& txt, const ImVec4& color, float spacing, size_t& current_length) {
|
||||
static const size_t LENGTH_THRESHOLD = 60;
|
||||
|
||||
if (txt.empty())
|
||||
return false;
|
||||
|
||||
std::string out_text = txt;
|
||||
bool reduced = false;
|
||||
if (current_length + out_text.length() > LENGTH_THRESHOLD) {
|
||||
out_text = out_text.substr(0, LENGTH_THRESHOLD - current_length);
|
||||
reduced = true;
|
||||
}
|
||||
|
||||
current_length += out_text.length();
|
||||
|
||||
ImGui::SameLine(0.0f, spacing);
|
||||
imgui.text_colored(color, out_text);
|
||||
if (reduced) {
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
imgui.text_colored(ELLIPSIS_COLOR, "...");
|
||||
}
|
||||
|
||||
return reduced;
|
||||
};
|
||||
|
||||
imgui.set_next_window_pos(0.0f, top, ImGuiCond_Always, 0.0f, 0.0f);
|
||||
imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::SetNextWindowBgAlpha(0.6f);
|
||||
imgui.begin(std::string("G-code"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
|
||||
// center the text in the window by pushing down the first line
|
||||
const float f_lines_count = static_cast<float>(visible_lines_count);
|
||||
ImGui::SetCursorPosY(0.5f * (wnd_height - f_lines_count * text_height - (f_lines_count - 1.0f) * style.ItemSpacing.y));
|
||||
|
||||
// render text lines
|
||||
size_t max_line_length = 0;
|
||||
for (size_t id = *visible_range.start_id; id <= *visible_range.end_id; ++id) {
|
||||
const Line& line = m_lines_cache[id - *m_cache_range.start_id];
|
||||
|
||||
// rect around the current selected line
|
||||
if (id == curr_line_id) {
|
||||
const float pos_y = ImGui::GetCursorScreenPos().y;
|
||||
const float half_ItemSpacing_y = 0.5f * style.ItemSpacing.y;
|
||||
const float half_padding_x = 0.5f * style.WindowPadding.x;
|
||||
ImGui::GetWindowDrawList()->AddRect({ half_padding_x, pos_y - half_ItemSpacing_y },
|
||||
{ ImGui::GetCurrentWindow()->Size.x - half_padding_x, pos_y + text_height + half_ItemSpacing_y },
|
||||
ImGui::GetColorU32(SELECTION_RECT_COLOR));
|
||||
}
|
||||
|
||||
const std::string id_str = std::to_string(id);
|
||||
// spacer to right align text
|
||||
ImGui::Dummy({ id_width - ImGui::CalcTextSize(id_str.c_str()).x, text_height });
|
||||
|
||||
size_t line_length = 0;
|
||||
// render line number
|
||||
bool stop_adding = add_item_to_line(id_str, LINE_NUMBER_COLOR, 0.0f, line_length);
|
||||
if (!stop_adding && !line.command.empty())
|
||||
// render command
|
||||
stop_adding = add_item_to_line(line.command, COMMAND_COLOR, -1.0f, line_length);
|
||||
if (!stop_adding && !line.parameters.empty())
|
||||
// render parameters
|
||||
stop_adding = add_item_to_line(line.parameters, PARAMETERS_COLOR, 0.0f, line_length);
|
||||
if (!stop_adding && !line.comment.empty())
|
||||
// render comment
|
||||
stop_adding = add_item_to_line(line.comment, COMMENT_COLOR, line.command.empty() ? -1.0f : 0.0f, line_length);
|
||||
|
||||
max_line_length = std::max(max_line_length, line_length);
|
||||
}
|
||||
|
||||
imgui.end();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// request an extra frame if window's width changed
|
||||
if (m_max_line_length != max_line_length) {
|
||||
m_max_line_length = max_line_length;
|
||||
imgui.set_requires_extra_frame();
|
||||
}
|
||||
}
|
||||
#else
|
||||
void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, uint64_t curr_line_id) const
|
||||
{
|
||||
auto update_lines = [this](uint64_t start_id, uint64_t end_id) {
|
||||
std::vector<Line> ret;
|
||||
ret.reserve(end_id - start_id + 1);
|
||||
for (uint64_t id = start_id; id <= end_id; ++id) {
|
||||
// read line from file
|
||||
const size_t start = id == 1 ? 0 : m_lines_ends[id - 2];
|
||||
const size_t len = m_lines_ends[id - 1] - start;
|
||||
std::string gline(m_file.data() + start, len);
|
||||
for (uint64_t id = start_id; id <= end_id; ++id) {
|
||||
// read line from file
|
||||
const size_t start = id == 1 ? 0 : m_lines_ends[id - 2];
|
||||
const size_t len = m_lines_ends[id - 1] - start;
|
||||
std::string gline(m_file.data() + start, len);
|
||||
|
||||
std::string command;
|
||||
std::string parameters;
|
||||
std::string comment;
|
||||
std::string command;
|
||||
std::string parameters;
|
||||
std::string comment;
|
||||
|
||||
// extract comment
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on);
|
||||
command = tokens.front();
|
||||
if (tokens.size() > 1)
|
||||
comment = ";" + tokens.back();
|
||||
|
||||
// extract gcode command and parameters
|
||||
if (!command.empty()) {
|
||||
boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on);
|
||||
// extract comment
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on);
|
||||
command = tokens.front();
|
||||
if (tokens.size() > 1) {
|
||||
for (size_t i = 1; i < tokens.size(); ++i) {
|
||||
parameters += " " + tokens[i];
|
||||
if (tokens.size() > 1)
|
||||
comment = ";" + tokens.back();
|
||||
|
||||
// extract gcode command and parameters
|
||||
if (!command.empty()) {
|
||||
boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on);
|
||||
command = tokens.front();
|
||||
if (tokens.size() > 1) {
|
||||
for (size_t i = 1; i < tokens.size(); ++i) {
|
||||
parameters += " " + tokens[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.push_back({ command, parameters, comment });
|
||||
}
|
||||
ret.push_back({ command, parameters, comment });
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -546,12 +729,15 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u
|
||||
imgui.end();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
|
||||
#if !ENABLE_BINARIZED_GCODE
|
||||
void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file()
|
||||
{
|
||||
if (m_file.is_open())
|
||||
m_file.close();
|
||||
}
|
||||
#endif // !ENABLE_BINARIZED_GCODE
|
||||
|
||||
void GCodeViewer::SequentialView::render(float legend_height)
|
||||
{
|
||||
|
@ -6,7 +6,9 @@
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GLModel.hpp"
|
||||
|
||||
#if !ENABLE_BINARIZED_GCODE
|
||||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
#endif // !ENABLE_BINARIZED_GCODE
|
||||
|
||||
#include <cstdint>
|
||||
#include <float.h>
|
||||
@ -672,6 +674,50 @@ public:
|
||||
void render();
|
||||
};
|
||||
|
||||
#if ENABLE_BINARIZED_GCODE
|
||||
class GCodeWindow
|
||||
{
|
||||
struct Line
|
||||
{
|
||||
std::string command;
|
||||
std::string parameters;
|
||||
std::string comment;
|
||||
};
|
||||
|
||||
struct Range
|
||||
{
|
||||
std::optional<size_t> start_id;
|
||||
std::optional<size_t> end_id;
|
||||
bool empty() const {
|
||||
return !start_id.has_value() || !end_id.has_value();
|
||||
}
|
||||
bool contains(const Range& other) const {
|
||||
return !this->empty() && !other.empty() && *this->start_id <= *other.start_id && *this->end_id >= other.end_id;
|
||||
}
|
||||
size_t size() const {
|
||||
return empty() ? 0 : *this->end_id - *this->start_id + 1;
|
||||
}
|
||||
};
|
||||
|
||||
bool m_visible{ true };
|
||||
std::string m_filename;
|
||||
// map for accessing data in file by line number
|
||||
std::vector<size_t> m_lines_ends;
|
||||
std::vector<Line> m_lines_cache;
|
||||
Range m_cache_range;
|
||||
size_t m_max_line_length{ 0 };
|
||||
|
||||
public:
|
||||
void load_gcode(const std::string& filename, const std::vector<size_t>& lines_ends);
|
||||
void reset() {
|
||||
m_lines_ends.clear();
|
||||
m_lines_cache.clear();
|
||||
m_filename.clear();
|
||||
}
|
||||
void toggle_visibility() { m_visible = !m_visible; }
|
||||
void render(float top, float bottom, size_t curr_line_id);
|
||||
};
|
||||
#else
|
||||
class GCodeWindow
|
||||
{
|
||||
struct Line
|
||||
@ -691,7 +737,7 @@ public:
|
||||
std::vector<Line> m_lines;
|
||||
|
||||
public:
|
||||
GCodeWindow() = default;
|
||||
GCodeWindow() = default;
|
||||
~GCodeWindow() { stop_mapping_file(); }
|
||||
void load_gcode(const std::string& filename, const std::vector<size_t>& lines_ends);
|
||||
void reset() {
|
||||
@ -707,6 +753,7 @@ public:
|
||||
|
||||
void stop_mapping_file();
|
||||
};
|
||||
#endif // ENABLE_BINARIZED_GCODE
|
||||
|
||||
struct Endpoints
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user