NEW: gcode viewer add recommended colour filament widget

Change-Id: I37f38a175bb3f4a574a4855f8fef04e704da259c
This commit is contained in:
Mack 2024-07-04 21:00:39 +08:00 committed by lane.wei
parent 582b2d470f
commit 4014c61f88
8 changed files with 232 additions and 13 deletions

View File

@ -0,0 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.2596 37.5131C25.5229 37.5131 27.3577 29.5764 27.3577 19.7859C27.3577 9.99536 25.5229 2.05859 23.2596 2.05859C22.3784 2.05859 21.3802 3.55703 20.7119 5.60405H22.2969C22.7771 6.93611 23.7442 11.4734 23.7442 20.5097C23.7442 29.546 22.4689 33.0115 22.2969 34.0043H20.8278C21.5273 36.4088 22.2967 37.5131 23.2596 37.5131Z" fill="#F2F2F2"/>
<path d="M20.7119 5.60405C21.3802 3.55703 22.3784 2.05859 23.2596 2.05859C25.5229 2.05859 27.3577 9.99536 27.3577 19.7859C27.3577 29.5764 25.5229 37.5131 23.2596 37.5131C22.2967 37.5131 21.4114 36.0767 20.7119 33.6722" stroke="#5C5C5C" stroke-width="2"/>
<path d="M22.3311 5.60352L8.93066 5.60352L9.23275 6.78533L10.139 12.399L10.4411 24.5126L9.83691 30.4217L8.93066 33.9672H22.3311C23.1389 30.7196 23.7327 25.7062 23.7327 20.0808C23.7327 14.1019 23.2274 8.8144 22.3311 5.60352Z" fill="#00AE42"/>
<path d="M8.62891 5.60352L22.3115 5.60352C23.2206 8.8144 23.7331 14.1019 23.7331 20.0808C23.7331 25.7062 23.1308 30.7196 22.3115 33.9672H8.62891" stroke="#5C5C5C"/>
<ellipse cx="6.514" cy="19.7859" rx="3.92708" ry="17.7273" fill="#F2F2F2" stroke="#5C5C5C" stroke-width="2"/>
<ellipse cx="6.21159" cy="20.081" rx="0.604167" ry="2.65909" fill="#5C5C5C"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -215,5 +215,7 @@ namespace ImGui
const wchar_t ClipboardBtnIcon = 0x0848;
const wchar_t ClipboardBtnDarkIcon = 0x0849;
// void MyFunction(const char* name, const MyMatrix44& v);
const wchar_t FilamentGreen = 0x0850;
}

View File

@ -13,11 +13,12 @@
#include <wx/mstream.h>
#include <wx/rawbmp.h>
#endif /* __WXGTK2__ */
#include <GL/glew.h>
#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include "3DScene.hpp"
namespace Slic3r { namespace GUI {
@ -541,6 +542,65 @@ bool BitmapCache::parse_color4(const std::string& scolor, unsigned char* rgba_ou
}
return true;
}
//BBS Replace svg green with the specified colour
bool BitmapCache::load_from_svg_file_change_color(const std::string &filename, unsigned width, unsigned height, ImTextureID &texture_id, const char *hexColor)
{
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
if (image == nullptr) {
return false;
}
unsigned int change_color = nsvg__parseColorHex(hexColor);
change_color |= (unsigned int) (1.0f * 255) << 24; // opacity
unsigned int green_color = 4282560000;
for (NSVGshape* shape = image->shapes; shape != nullptr; shape = shape->next) {
// find green color
if (shape->fill.color == green_color) {
shape->fill.color = change_color;
}
}
float scale = (float)width / image->width;
int n_pixels = width * height;
if (n_pixels <= 0) {
nsvgDelete(image);
return false;
}
NSVGrasterizer* rast = nsvgCreateRasterizer();
if (rast == nullptr) {
nsvgDelete(image);
return false;
}
std::vector<unsigned char> data(n_pixels * 4, 0);
nsvgRasterize(rast, image, 0, 0, scale, data.data(), width, height, width * 4);
bool compress = false;
GLint last_texture;
unsigned m_image_texture{ 0 };
unsigned char* pixels = (unsigned char*)(&data[0]);
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
glsafe(::glGenTextures(1, &m_image_texture));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_image_texture));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier
texture_id = (ImTextureID)(intptr_t)m_image_texture;
// Restore state
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
nsvgDeleteRasterizer(rast);
nsvgDelete(image);
return true;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -8,6 +8,7 @@
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <imgui/imgui.h>
struct NSVGimage;
@ -52,6 +53,9 @@ public:
static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
static bool parse_color4(const std::string& scolor, unsigned char* rgba_out);
static bool load_from_svg_file_change_color(const std::string &filename, unsigned width, unsigned height, ImTextureID &texture_id, const char *hexColor);
private:
std::map<std::string, wxBitmap*> m_map;
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
@ -61,4 +65,4 @@ private:
} // GUI
} // Slic3r
#endif /* SLIC3R_GUI_BITMAP_CACHE_HPP */
#endif // SLIC3R_GUI_BITMAP_CACHE_HPP

View File

@ -1012,6 +1012,16 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
m_gcode_result = &gcode_result;
m_only_gcode_in_preview = only_gcode;
std::vector<int> filament_maps = print.get_filament_maps();
std::vector<std::string> color_opt = print.config().option<ConfigOptionStrings>("filament_colour")->values;
std::vector<std::string> type_opt = print.config().option<ConfigOptionStrings>("filament_type")->values;
for (int i = 0; i < filament_maps.size(); ++i) {
if (filament_maps[i] == 1) {
m_left_extruder_filament.emplace_back(type_opt[i], color_opt[i]);
} else {
m_right_extruder_filament.emplace_back(type_opt[i], color_opt[i]);
}
}
m_sequential_view.gcode_window.load_gcode(gcode_result.filename, gcode_result.lines_ends);
//BBS: add only gcode mode
@ -4576,6 +4586,91 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
return;
}
void GCodeViewer::render_legend_color_arr_recommen(float window_padding)
{
ImGuiWrapper &imgui = *wxGetApp().imgui();
auto link_text = [&](std::string &label) {
ImVec2 wiki_part_size = ImGui::CalcTextSize(label.c_str());
ImColor HyperColor = ImColor(48, 221, 114, 255).Value;
ImGui::PushStyleColor(ImGuiCol_Text, HyperColor.Value);
imgui.text(label.c_str());
ImGui::PopStyleColor();
// click behavior
if (ImGui::IsMouseHoveringRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), true)) {
// underline
ImVec2 lineEnd = ImGui::GetItemRectMax();
lineEnd.y -= 2.0f;
ImVec2 lineStart = lineEnd;
lineStart.x = ImGui::GetItemRectMin().x;
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, HyperColor);
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left));
}
};
////BBS Color Arrangement Recommendation
ImGui::Dummy({ window_padding, window_padding });
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.title(_u8L("Color Arrangement Recommendation"));
//BBS AMS containers
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(window_padding * 3, 0));
ImGui::BeginChild("#AMS", ImVec2(0, 230.0f), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
{
// BBS save time;
imgui.text(_u8L("Since you set 1 AMS"));
ImGui::SameLine();
// BBS change button
link_text(_u8L("(change)"));
ImGui::SameLine();
imgui.text(_u8L(",this arrangement would be optimal."));
imgui.text(_u8L("It will save 738g filament and 23 minutes"));
float available_width = ImGui::GetContentRegionAvail().x;
float available_height = ImGui::GetContentRegionAvail().y;
float half_width = available_width * 0.5f;
float spacing = 12.0f * m_scale;
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.00f, 0.00f, 0.00f, 0.3f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(window_padding * 2, window_padding));
ImDrawList *child_begin_draw_list = ImGui::GetWindowDrawList();
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
child_begin_draw_list->AddRectFilled(cursor_pos, ImVec2(cursor_pos.x + half_width, cursor_pos.y + 24.0f * m_scale), IM_COL32(0, 0, 0, 64));
ImGui::BeginChild("#LeftAMS", ImVec2(half_width, available_height - 20 * m_scale), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
{
imgui.bold_text(_u8L("Left"));
ImGui::Dummy({window_padding, window_padding});
int index = 1;
for (const auto &extruder_filament : m_left_extruder_filament) {
imgui.filament_group(extruder_filament.first, extruder_filament.second.c_str());
if (index % 4 != 0) { ImGui::SameLine(0, spacing); }
}
ImGui::EndChild();
}
ImGui::SameLine();
cursor_pos = ImGui::GetCursorScreenPos();
child_begin_draw_list->AddRectFilled(cursor_pos, ImVec2(cursor_pos.x + half_width, cursor_pos.y + 24.0f * m_scale), IM_COL32(0, 0, 0, 64));
ImGui::BeginChild("#RightAMS", ImVec2(half_width, available_height - 20 * m_scale), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
{
imgui.bold_text(_u8L("Right"));
ImGui::Dummy({window_padding, window_padding});
int index = 1;
for (const auto &extruder_filament : m_right_extruder_filament) {
imgui.filament_group(extruder_filament.first, extruder_filament.second.c_str());
if (index % 4 != 0) { ImGui::SameLine(0, spacing); }
}
ImGui::EndChild();
}
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(1);
link_text(_u8L("Customize Arrangement"));
ImGui::EndChild();
}
ImGui::PopStyleVar(1);
}
void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin)
{
if (!m_legend_enabled)
@ -4868,10 +4963,15 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return ret;
};
//BBS display Color Scheme
//BBS Slicing Result title
ImGui::Dummy({ window_padding, window_padding });
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
std::string title = _u8L("Slicing Result");
imgui.bold_text(title);
ImVec2 longest_text_size = imgui.calc_text_size(_u8L("Since you set 1 AMS (change) ,this arrangement would be optimal."));
ImVec2 title_text_size = imgui.calc_text_size(title);
ImGui::SameLine(0, longest_text_size.x - title_text_size.x);
std::wstring btn_name;
if (m_fold)
btn_name = ImGui::UnfoldButtonIcon + boost::nowide::widen(std::string(""));
@ -4881,13 +4981,25 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.0f, 0.68f, 0.26f, 0.78f));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
//ImGui::PushItemWidth(
float button_width = ImGui::CalcTextSize(into_u8(btn_name).c_str()).x;
if (ImGui::Button(into_u8(btn_name).c_str(), ImVec2(button_width, 0))) {
m_fold = !m_fold;
}
ImGui::PopStyleColor(3);
ImGui::PopStyleVar(1);
if (m_fold) {
legend_height = ImGui::GetStyle().WindowPadding.y + ImGui::GetFrameHeight() + window_padding * 2.5;
imgui.end();
ImGui::PopStyleColor(6);
ImGui::PopStyleVar(2);
return;
}
render_legend_color_arr_recommen(window_padding);
//BBS display Color Scheme
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.bold_text(_u8L("Color Scheme"));
push_combo_style();
@ -4920,14 +5032,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
ImGui::SameLine();
ImGui::Dummy({ window_padding, window_padding });
if (m_fold) {
legend_height = ImGui::GetStyle().WindowPadding.y + ImGui::GetFrameHeight() + window_padding * 2.5;
imgui.end();
ImGui::PopStyleColor(6);
ImGui::PopStyleVar(2);
return;
}
// data used to properly align items in columns when showing time
std::vector<float> offsets;
std::vector<std::string> labels;

View File

@ -751,6 +751,11 @@ private:
bool m_only_gcode_in_preview {false};
std::vector<size_t> m_ssid_to_moveid_map;
//BBS: extruder dispensing filament
//std::pair<TYPE, CLOUR>
std::vector<std::pair<std::string, std::string>> m_left_extruder_filament;
std::vector<std::pair<std::string, std::string>> m_right_extruder_filament;
std::vector<TBuffer> m_buffers{ static_cast<size_t>(EMoveType::Extrude) };
// bounding box of toolpaths
BoundingBoxf3 m_paths_bounding_box;
@ -911,6 +916,7 @@ private:
//BBS: GUI refactor: add canvas size
void render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin);
void render_legend_color_arr_recommen(float window_padding);
void render_slider(int canvas_width, int canvas_height);
#if ENABLE_GCODE_VIEWER_STATISTICS

View File

@ -133,6 +133,7 @@ static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::PrevArrowBtnIcon, "notification_arrow_left" },
{ImGui::NextArrowBtnIcon, "notification_arrow_right" },
{ImGui::CompleteIcon, "notification_slicing_complete" },
{ImGui::FilamentGreen, "filament_green" }
};
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
@ -2840,6 +2841,39 @@ void ImGuiWrapper::clipboard_set(void* /* user_data */, const char* text)
}
}
void ImGuiWrapper::filament_group(const std::string &filament_type, const char *hex_color)
{
//ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImDrawList *draw_list = ImGui::GetWindowDrawList();
static ImTextureID transparent;
ImVec2 img_size = {30.0f, 45.0f};
ImVec2 text_size = ImGui::CalcTextSize(filament_type.c_str());
BitmapCache::load_from_svg_file_change_color(Slic3r::resources_dir() + "/images/filament_green.svg", img_size.x, img_size.y, transparent, hex_color);
ImGui::BeginGroup();
{
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
draw_list->AddImage(transparent, cursor_pos, {cursor_pos.x + img_size.x, cursor_pos.y + img_size.y}, {0, 0}, {1, 1}, ImGui::GetColorU32(ImVec4(1.f, 1.f, 1.f, 1.f)));
// image border test
// draw_list->AddRect(cursor_pos, {cursor_pos.x + img_size.x, cursor_pos.y + img_size.y}, IM_COL32(0, 0, 0, 255));
ImVec2 current_cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos({current_cursor.x + (img_size.x - text_size.x) * 0.5f, current_cursor.y + 40});
this->text(filament_type);
ImGui::EndGroup();
}
//ImGui::PopStyleVar(1);
}
void ImGuiWrapper::sub_title(const std::string &label)
{
ImDrawList *draw_list = ImGui::GetWindowDrawList();
text_colored(ImVec4(1.0f, 1.0f, 1.0f, 0.5f), label);
ImGui::SameLine();
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
float available_width = ImGui::GetContentRegionAvail().x;
draw_list->AddLine(ImVec2(cursor_pos.x, cursor_pos.y + 8.0f), ImVec2(cursor_pos.x + available_width, cursor_pos.y + 8.0f), IM_COL32(255, 255, 255, 100));
ImGui::NewLine();
}
bool IMTexture::load_from_svg_file(const std::string& filename, unsigned width, unsigned height, ImTextureID& texture_id)
{
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);

View File

@ -153,6 +153,8 @@ public:
void text_wrapped(const wxString &label, float wrap_width);
void tooltip(const char *label, float wrap_width);
void tooltip(const wxString &label, float wrap_width);
void filament_group(const std::string &filament_type, const char *hex_color);
void sub_title(const std::string &label);
// Float sliders: Manually inserted values aren't clamped by ImGui.Using this wrapper function does (when clamp==true).
@ -335,7 +337,6 @@ class IMTexture
public:
// load svg file to thumbnail data, specific width, height is thumbnailData width, height
static bool load_from_svg_file(const std::string& filename, unsigned width, unsigned height, ImTextureID &texture_id);
};