NEW: gcode viewer add recommended colour filament widget
Change-Id: I37f38a175bb3f4a574a4855f8fef04e704da259c
This commit is contained in:
parent
582b2d470f
commit
4014c61f88
|
@ -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 |
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue