diff --git a/bbl/i18n/list.txt b/bbl/i18n/list.txt
index 920971a51..1b1a3fd4b 100644
--- a/bbl/i18n/list.txt
+++ b/bbl/i18n/list.txt
@@ -172,4 +172,6 @@ src/slic3r/GUI/SendMultiMachinePage.cpp
src/slic3r/GUI/MultiMachinePage.cpp
src/slic3r/GUI/MultiMachineManagerPage.cpp
src/slic3r/GUI/MultiTaskManagerPage.cpp
-src/slic3r/GUI/MultiMachine.cpp
\ No newline at end of file
+src/slic3r/GUI/MultiMachine.cpp
+src/slic3r/GUI/FilamentMapDialog.cpp
+src/slic3r/GUI/FilamentGroupPopup.cpp
\ No newline at end of file
diff --git a/resources/images/capsule_tag_off.svg b/resources/images/capsule_tag_off.svg
new file mode 100644
index 000000000..2127760b7
--- /dev/null
+++ b/resources/images/capsule_tag_off.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/images/capsule_tag_on.svg b/resources/images/capsule_tag_on.svg
new file mode 100644
index 000000000..39726becb
--- /dev/null
+++ b/resources/images/capsule_tag_on.svg
@@ -0,0 +1,4 @@
+
diff --git a/resources/images/flush_mode_panel_icon.svg b/resources/images/flush_mode_panel_icon.svg
new file mode 100644
index 000000000..2e9cfc710
--- /dev/null
+++ b/resources/images/flush_mode_panel_icon.svg
@@ -0,0 +1,7 @@
+
diff --git a/resources/images/map_mode_off.svg b/resources/images/map_mode_off.svg
new file mode 100644
index 000000000..5400ff63e
--- /dev/null
+++ b/resources/images/map_mode_off.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/images/map_mode_off_hovered.svg b/resources/images/map_mode_off_hovered.svg
new file mode 100644
index 000000000..78e2beb06
--- /dev/null
+++ b/resources/images/map_mode_off_hovered.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/images/map_mode_on.svg b/resources/images/map_mode_on.svg
new file mode 100644
index 000000000..df1c78b77
--- /dev/null
+++ b/resources/images/map_mode_on.svg
@@ -0,0 +1,4 @@
+
diff --git a/resources/images/map_mode_on_hovered.svg b/resources/images/map_mode_on_hovered.svg
new file mode 100644
index 000000000..eb5bf9cd1
--- /dev/null
+++ b/resources/images/map_mode_on_hovered.svg
@@ -0,0 +1,4 @@
+
diff --git a/resources/images/match_mode_panel_icon.svg b/resources/images/match_mode_panel_icon.svg
new file mode 100644
index 000000000..01fc724da
--- /dev/null
+++ b/resources/images/match_mode_panel_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp
index d3e37c272..cbf5f4fd4 100644
--- a/src/libslic3r/AppConfig.cpp
+++ b/src/libslic3r/AppConfig.cpp
@@ -265,6 +265,18 @@ void AppConfig::set_defaults()
set_bool("auto_calculate_when_filament_change", true);
}
+ if (get("ignore_ext_filament_in_filament_map").empty()){
+ set_bool("ignore_ext_filament_in_filament_map", false);
+ }
+
+ if (get("pop_up_filament_map_mode").empty()){
+ set_bool("pop_up_filament_map_mode", true);
+ }
+
+ if (get("prefered_filament_map_mode").empty()){
+ set("prefered_filament_map_mode",ConfigOptionEnum::get_enum_names()[FilamentMapMode::fmmAutoForFlush]);
+ }
+
if (get("show_home_page").empty()) {
set_bool("show_home_page", true);
}
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index 58e9186b5..03ae50a22 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -286,6 +286,10 @@ set(SLIC3R_GUI_SOURCES
GUI/Field.hpp
GUI/DragDropPanel.cpp
GUI/DragDropPanel.hpp
+ GUI/CapsuleButton.cpp
+ GUI/CapsuleButton.hpp
+ GUI/FilamentMapPanel.cpp
+ GUI/FilamentMapPanel.hpp
GUI/FilamentMapDialog.cpp
GUI/FilamentMapDialog.hpp
GUI/OptionsGroup.cpp
@@ -406,6 +410,8 @@ set(SLIC3R_GUI_SOURCES
GUI/InstanceCheck.hpp
GUI/Search.cpp
GUI/Search.hpp
+ GUI/FilamentGroupPopup.hpp
+ GUI/FilamentGroupPopup.cpp
GUI/NotificationManager.cpp
GUI/NotificationManager.hpp
GUI/UnsavedChangesDialog.cpp
diff --git a/src/slic3r/GUI/CapsuleButton.cpp b/src/slic3r/GUI/CapsuleButton.cpp
new file mode 100644
index 000000000..ed544e982
--- /dev/null
+++ b/src/slic3r/GUI/CapsuleButton.cpp
@@ -0,0 +1,117 @@
+#include "GUI_App.hpp"
+#include "CapsuleButton.hpp"
+#include "wx/graphics.h"
+#include "Widgets/Label.hpp"
+#include "wx/dcgraph.h"
+
+namespace Slic3r { namespace GUI {
+CapsuleButton::CapsuleButton(wxWindow *parent, wxWindowID id, const wxString &label, bool selected) : wxPanel(parent, id)
+{
+ SetBackgroundColour(*wxWHITE);
+ SetBackgroundStyle(wxBG_STYLE_PAINT);
+
+ m_hovered = false;
+ m_selected = selected;
+
+ auto sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ std::string icon_name = selected ? "capsule_tag_on" : "capsule_tag_off";
+ auto bmp = create_scaled_bitmap(icon_name, nullptr, FromDIP(16));
+
+ m_btn = new wxBitmapButton(this, wxID_ANY, bmp, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
+ m_btn->SetBackgroundColour(*wxWHITE);
+
+ m_label = new Label(this, label);
+
+ sizer->AddSpacer(FromDIP(8));
+ sizer->Add(m_btn, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, FromDIP(6));
+ sizer->AddSpacer(FromDIP(8));
+ sizer->Add(m_label, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, FromDIP(6));
+ sizer->AddSpacer(FromDIP(8));
+
+ SetSizer(sizer);
+ Layout();
+ Fit();
+
+ auto forward_click_to_parent = [this](auto &event) {
+ wxCommandEvent click_event(wxEVT_BUTTON, GetId());
+ click_event.SetEventObject(this);
+ this->ProcessEvent(click_event);
+ };
+
+ m_btn->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+ m_label->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+ this->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+
+ Bind(wxEVT_PAINT, &CapsuleButton::OnPaint, this);
+ Bind(wxEVT_ENTER_WINDOW, &CapsuleButton::OnEnterWindow, this);
+ Bind(wxEVT_LEAVE_WINDOW, &CapsuleButton::OnLeaveWindow, this);
+
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+}
+void CapsuleButton::OnPaint(wxPaintEvent &event)
+{
+ wxAutoBufferedPaintDC dc(this);
+ wxGraphicsContext *gc = wxGraphicsContext::Create(dc);
+
+ if (gc) {
+ dc.Clear();
+ wxRect rect = GetClientRect();
+ gc->SetBrush(wxTransparentColour);
+ gc->DrawRoundedRectangle(0, 0, rect.width, rect.height, 0);
+ wxColour bg_color = m_selected ? wxColour("#EBF9F0") : wxColour("#FFFFFF");
+ wxColour border_color = m_hovered || m_selected ? wxColour("#00AE42") : wxColour("#CECECE");
+ int cornerRadius = 5;
+ gc->SetBrush(wxBrush(bg_color));
+ gc->SetPen(wxPen(border_color, 2));
+ gc->DrawRoundedRectangle(1, 1, rect.width - 2, rect.height - 2, cornerRadius);
+ delete gc;
+ }
+}
+void CapsuleButton::Select(bool selected)
+{
+ m_selected = selected;
+ UpdateStatus();
+ Refresh();
+}
+
+void CapsuleButton::OnEnterWindow(wxMouseEvent &event)
+{
+ if (!m_hovered) {
+ m_hovered = true;
+ UpdateStatus();
+ Refresh();
+ }
+ event.Skip();
+}
+
+void CapsuleButton::OnLeaveWindow(wxMouseEvent &event)
+{
+ if (m_hovered) {
+ wxPoint pos = this->ScreenToClient(wxGetMousePosition());
+ if (this->GetClientRect().Contains(pos)) return;
+ m_hovered = false;
+ UpdateStatus();
+ Refresh();
+ }
+ event.Skip();
+}
+
+void CapsuleButton::UpdateStatus()
+{
+ const wxColour selected_color = wxColour("#EBF9F0");
+ const wxColour normal_color = wxColour("#FFFFFF");
+
+ std::string icon_name = m_selected ? "capsule_tag_on" : "capsule_tag_off";
+ auto bmp = create_scaled_bitmap(icon_name, nullptr, FromDIP(16));
+ m_btn->SetBitmap(bmp);
+
+ if (m_selected) {
+ m_label->SetBackgroundColour(selected_color);
+ m_btn->SetBackgroundColour(selected_color);
+ } else {
+ m_label->SetBackgroundColour(normal_color);
+ m_btn->SetBackgroundColour(normal_color);
+ }
+}
+}} // namespace Slic3r::GUI
\ No newline at end of file
diff --git a/src/slic3r/GUI/CapsuleButton.hpp b/src/slic3r/GUI/CapsuleButton.hpp
new file mode 100644
index 000000000..87d516752
--- /dev/null
+++ b/src/slic3r/GUI/CapsuleButton.hpp
@@ -0,0 +1,28 @@
+#ifndef CAPSULE_BUTTON_HPP
+#define CAPSULE_BUTTON_HPP
+
+#include "GUI.hpp"
+#include "wxExtensions.hpp"
+
+namespace Slic3r { namespace GUI {
+class CapsuleButton : public wxPanel
+{
+public:
+ CapsuleButton(wxWindow *parent, wxWindowID id, const wxString &label, bool selected);
+ void Select(bool selected);
+protected:
+ void OnPaint(wxPaintEvent &event);
+private:
+ void OnEnterWindow(wxMouseEvent &event);
+ void OnLeaveWindow(wxMouseEvent &event);
+ void UpdateStatus();
+
+ wxBitmapButton *m_btn;
+ Label *m_label;
+
+ bool m_hovered;
+ bool m_selected;
+};
+}} // namespace Slic3r::GUI
+
+#endif
\ No newline at end of file
diff --git a/src/slic3r/GUI/DragDropPanel.cpp b/src/slic3r/GUI/DragDropPanel.cpp
index f3b60cf91..c7f110200 100644
--- a/src/slic3r/GUI/DragDropPanel.cpp
+++ b/src/slic3r/GUI/DragDropPanel.cpp
@@ -1,4 +1,5 @@
#include "DragDropPanel.hpp"
+#include "Widgets/Label.hpp"
#include
namespace Slic3r { namespace GUI {
@@ -9,6 +10,27 @@ struct CustomData
unsigned char r, g, b;
};
+
+wxColor Hex2Color(const std::string& str)
+{
+ if (str.empty() || (str.length() != 9 && str.length() != 7) || str[0] != '#')
+ throw std::invalid_argument("Invalid hex color format");
+
+ auto hexToByte = [](const std::string& hex)->unsigned char
+ {
+ unsigned int byte;
+ std::istringstream(hex) >> std::hex >> byte;
+ return static_cast(byte);
+ };
+ auto r = hexToByte(str.substr(1, 2));
+ auto g = hexToByte(str.substr(3, 2));
+ auto b = hexToByte(str.substr(5, 2));
+ unsigned char a = 255;
+ if (str.size() == 9)
+ a = hexToByte(str.substr(7, 2));
+ return wxColor(r, g, b, a);
+}
+
// Custom data object used to store information that needs to be backed up during drag and drop
class ColorDataObject : public wxCustomDataObject
{
@@ -150,21 +172,24 @@ DragDropPanel::DragDropPanel(wxWindow *parent, const wxString &label, bool is_au
auto title_sizer = new wxBoxSizer(wxHORIZONTAL);
title_panel->SetSizer(title_sizer);
- wxStaticText *staticText = new wxStaticText(this, wxID_ANY, label);
- staticText->SetBackgroundColour(0xEEEEEE);
- title_sizer->Add(staticText, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
+ Label* static_text = new Label(this, label);
+ static_text->SetFont(Label::Head_13);
+ static_text->SetBackgroundColour(0xEEEEEE);
+
+ title_sizer->Add(static_text, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
m_sizer->Add(title_panel, 0, wxEXPAND);
m_sizer->AddSpacer(20);
- m_grid_item_sizer = new wxGridSizer(0, 5, FromDIP(10), 0); // row = 0, col = 3, 10 10 is space
- m_sizer->Add(m_grid_item_sizer);
+ m_grid_item_sizer = new wxGridSizer(0, 6, FromDIP(5),FromDIP(5)); // row = 0, col = 3, 10 10 is space
+ m_sizer->Add(m_grid_item_sizer, 1, wxEXPAND);
// set droptarget
auto drop_target = new ColorDropTarget(this);
SetDropTarget(drop_target);
SetSizer(m_sizer);
+ Layout();
Fit();
}
@@ -172,7 +197,7 @@ void DragDropPanel::AddColorBlock(const wxColour &color, int filament_id, bool u
{
ColorPanel *panel = new ColorPanel(this, color, filament_id);
panel->SetMinSize(wxSize(FromDIP(32), FromDIP(40)));
- m_grid_item_sizer->Add(panel, 0, wxALIGN_CENTER | wxLEFT, FromDIP(10));
+ m_grid_item_sizer->Add(panel, 0, wxALIGN_CENTER);
m_filament_blocks.push_back(panel);
if (update_ui) {
m_filament_blocks.front()->Refresh(); // FIX BUG: STUDIO-8467
diff --git a/src/slic3r/GUI/DragDropPanel.hpp b/src/slic3r/GUI/DragDropPanel.hpp
index 3bcb6ecf6..51e41e04b 100644
--- a/src/slic3r/GUI/DragDropPanel.hpp
+++ b/src/slic3r/GUI/DragDropPanel.hpp
@@ -11,6 +11,9 @@
namespace Slic3r { namespace GUI {
+
+wxColor Hex2Color(const std::string& str);
+
class ColorPanel;
class DragDropPanel : public wxPanel
{
diff --git a/src/slic3r/GUI/FilamentGroupPopup.cpp b/src/slic3r/GUI/FilamentGroupPopup.cpp
new file mode 100644
index 000000000..1cd65efa5
--- /dev/null
+++ b/src/slic3r/GUI/FilamentGroupPopup.cpp
@@ -0,0 +1,318 @@
+#include "FilamentGroupPopup.hpp"
+#include "FilamentMapDialog.hpp"
+#include "GUI_App.hpp"
+#include "MsgDialog.hpp"
+#include "I18N.hpp"
+#include "wx/dcgraph.h"
+
+namespace Slic3r { namespace GUI {
+
+static const wxString AutoForFlushLabel = _L("Filament-Saving Mode");
+static const wxString AutoForMatchLabel = _L("Convenient Mode");
+static const wxString ManualLabel = _L("Manual Mode");
+
+static const wxString AutoForFlushDesp = _L("(Arrage after slicing)");
+static const wxString AutoForMatchDesp = _L("(Arrange before slicing)");
+static const wxString ManualDesp = "";
+
+static const wxString AutoForFlushDetail = _L("Disregrad the filaments in AMS. Optimize filament usage "
+ "by calculating the best allocation for the left and right "
+ "nozzles. Arrange the filaments according on the printer according to "
+ "the slicing results.");
+static const wxString AutoForMatchDetail = _L("Based on the current filaments in the AMS, allocate the "
+ "filaments to the left and right nozzles.");
+static const wxString ManualDetail = _L("Mannully allocate the filaments for the left and right nozzles.");
+
+static bool is_multi_extruder()
+{
+ const auto &preset_bundle = wxGetApp().preset_bundle;
+ const auto &full_config = preset_bundle->full_config();
+ const auto nozzle_diameters = full_config.option("nozzle_diameter");
+ return nozzle_diameters->size() > 1;
+}
+
+FilamentMapMode get_prefered_map_mode()
+{
+ const static std::map enum_keys_map = ConfigOptionEnum::get_enum_values();
+ auto &app_config = wxGetApp().app_config;
+ std::string mode_str = app_config->get("prefered_filament_map_mode");
+ auto iter = enum_keys_map.find(mode_str);
+ if (iter == enum_keys_map.end()) {
+ BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("Could not get prefered_filament_map_mode from app config, use AutoForFlsuh mode");
+ return FilamentMapMode::fmmAutoForFlush;
+ }
+ return FilamentMapMode(iter->second);
+}
+
+static void set_prefered_map_mode(FilamentMapMode mode)
+{
+ const static std::vector enum_values = ConfigOptionEnum::get_enum_names();
+ auto &app_config = wxGetApp().app_config;
+ std::string mode_str;
+ if (mode < enum_values.size()) mode_str = enum_values[mode];
+
+ if (mode_str.empty()) BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("Set empty prefered_filament_map_mode to app config");
+ app_config->set("prefered_filament_map_mode", mode_str);
+}
+
+static bool get_pop_up_remind_flag()
+{
+ auto &app_config = wxGetApp().app_config;
+ return app_config->get_bool("pop_up_filament_map_mode");
+}
+
+static void set_pop_up_remind_flag(bool remind)
+{
+ auto &app_config = wxGetApp().app_config;
+ app_config->set_bool("pop_up_filament_map_mode", remind);
+}
+
+bool is_pop_up_required()
+{
+ FilamentMapMode mode = get_prefered_map_mode();
+ bool is_manual_mode_ = FilamentMapMode::fmmManual == mode;
+ bool is_multi_extruder_ = is_multi_extruder();
+ return is_multi_extruder_ && is_manual_mode_;
+}
+
+FilamentGroupPopup::FilamentGroupPopup(wxWindow *parent) : PopupWindow(parent, wxBORDER_NONE)
+{
+ wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL);
+ const int horizontal_margin = FromDIP(16);
+ const int vertical_margin = FromDIP(15);
+ const int vertical_padding = FromDIP(12);
+ const int ratio_spacing = FromDIP(4);
+
+ const wxColor background_color = wxColor(255, 255, 255);
+ SetBackgroundColour(background_color);
+
+ radio_btns.resize(ButtonType::btCount);
+ button_labels.resize(ButtonType::btCount);
+ button_desps.resize(ButtonType::btCount);
+ detail_infos.resize(ButtonType::btCount);
+ std::vector btn_texts = {AutoForFlushLabel, AutoForMatchLabel, ManualLabel};
+ std::vector btn_desps = {AutoForFlushDesp, AutoForMatchDesp, ManualDesp};
+ std::vector mode_details = {AutoForFlushDetail, AutoForMatchDetail, ManualDetail};
+
+ top_sizer->AddSpacer(vertical_margin);
+
+ auto checked_bmp = create_scaled_bitmap("map_mode_on", nullptr, 16);
+ auto unchecked_bmp = create_scaled_bitmap("map_mode_off", nullptr, 16);
+
+ for (size_t idx = 0; idx < ButtonType::btCount; ++idx) {
+ wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
+ radio_btns[idx] = new wxBitmapButton(this, idx, unchecked_bmp, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
+ radio_btns[idx]->SetBackgroundColour(background_color);
+
+ button_labels[idx] = new wxStaticText(this, wxID_ANY, btn_texts[idx]);
+ button_labels[idx]->SetBackgroundColour(background_color);
+ button_labels[idx]->SetForegroundColour(wxColor("#262E30"));
+ button_labels[idx]->SetFont(Label::Head_14);
+
+ button_desps[idx] = new wxStaticText(this, wxID_ANY, btn_desps[idx]);
+ button_desps[idx]->SetBackgroundColour(background_color);
+ button_desps[idx]->SetForegroundColour(wxColor("#262E30"));
+ button_desps[idx]->SetFont(Label::Body_14);
+
+ button_sizer->Add(radio_btns[idx], 0, wxALIGN_CENTER_VERTICAL);
+ button_sizer->AddSpacer(ratio_spacing);
+ button_sizer->Add(button_labels[idx], 0, wxALIGN_CENTER_VERTICAL);
+ button_sizer->Add(button_desps[idx], 0, wxALIGN_CENTER_VERTICAL);
+
+ wxBoxSizer *label_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ detail_infos[idx] = new wxStaticText(this, wxID_ANY, mode_details[idx]);
+ detail_infos[idx]->SetBackgroundColour(background_color);
+ detail_infos[idx]->SetForegroundColour(wxColor("#6B6B6B"));
+ detail_infos[idx]->SetFont(Label::Body_12);
+ detail_infos[idx]->Wrap(FromDIP(320));
+
+ label_sizer->AddSpacer(radio_btns[idx]->GetRect().width + ratio_spacing);
+ label_sizer->Add(detail_infos[idx], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL);
+
+ top_sizer->Add(button_sizer, 0, wxLEFT | wxRIGHT, horizontal_margin);
+ top_sizer->Add(label_sizer, 0, wxLEFT | wxRIGHT, horizontal_margin);
+ top_sizer->AddSpacer(vertical_padding);
+
+ radio_btns[idx]->Bind(wxEVT_BUTTON, [this, idx](wxCommandEvent &event) {
+ event.SetInt(idx);
+ OnRadioBtn(event);
+ });
+
+ radio_btns[idx]->Bind(wxEVT_ENTER_WINDOW, [this, idx](wxMouseEvent &) { UpdateButtonStatus(idx); });
+
+ radio_btns[idx]->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &) { UpdateButtonStatus(); });
+
+ button_labels[idx]->Bind(wxEVT_LEFT_UP, [this, idx](wxMouseEvent &) {
+ wxCommandEvent event;
+ event.SetInt(idx);
+ OnRadioBtn(event);
+ });
+
+ button_labels[idx]->Bind(wxEVT_ENTER_WINDOW, [this, idx](wxMouseEvent &) { UpdateButtonStatus(idx); });
+ button_labels[idx]->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &) { UpdateButtonStatus(); });
+ }
+
+ {
+ wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ wiki_link = new wxStaticText(this, wxID_ANY, _L("More info on wiki"));
+ wiki_link->SetBackgroundColour(background_color);
+ wiki_link->SetForegroundColour(wxColor("#00AE42"));
+ wiki_link->SetFont(Label::Body_12.Underlined());
+ wiki_link->SetCursor(wxCursor(wxCURSOR_HAND));
+ wiki_link->Bind(wxEVT_LEFT_DOWN, [](wxMouseEvent &) { wxLaunchDefaultBrowser("http//:example.com"); });
+
+ remind_checkbox = new wxCheckBox(this, wxID_ANY, _L("Don't remind me again"));
+ remind_checkbox->SetBackgroundColour(background_color);
+ remind_checkbox->SetForegroundColour(wxColor("#6B6B6B"));
+ remind_checkbox->SetFont(Label::Body_12);
+ remind_checkbox->Bind(wxEVT_CHECKBOX, &FilamentGroupPopup::OnRemindBtn, this);
+
+ button_sizer->Add(wiki_link, 0, wxLEFT, horizontal_margin);
+ button_sizer->AddStretchSpacer();
+ button_sizer->Add(remind_checkbox, 0, wxRIGHT, horizontal_margin);
+
+ top_sizer->Add(button_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, horizontal_margin);
+ }
+
+ top_sizer->AddSpacer(vertical_margin);
+ SetSizerAndFit(top_sizer);
+
+ m_mode = get_prefered_map_mode();
+ m_timer = new wxTimer(this);
+
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+
+ Bind(wxEVT_TIMER, &FilamentGroupPopup::OnTimer, this);
+ Bind(wxEVT_ENTER_WINDOW, &FilamentGroupPopup::OnEnterWindow, this);
+ Bind(wxEVT_LEAVE_WINDOW, &FilamentGroupPopup::OnLeaveWindow, this);
+}
+
+void FilamentGroupPopup::DrawRoundedCorner(int radius)
+{
+#ifdef __WIN32__
+ HWND hwnd = GetHWND();
+ if (hwnd) {
+ HRGN hrgn = CreateRoundRectRgn(0, 0, GetRect().GetWidth(), GetRect().GetHeight(), radius, radius);
+ SetWindowRgn(hwnd, hrgn, TRUE);
+
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ SetLayeredWindowAttributes(hwnd, 0, 0, LWA_COLORKEY);
+ }
+#else
+ wxClientDC dc(this);
+ wxGraphicsContext *gc = wxGraphicsContext::Create(dc);
+ if (gc) {
+ gc->SetBrush(*wxWHITE_BRUSH);
+ gc->SetPen(*wxTRANSPARENT_PEN);
+ wxRect rect(0, 0, GetSize().GetWidth(), GetSize().GetHeight());
+ wxGraphicsPath path = wxGraphicsRenderer::GetDefaultRenderer()->CreatePath();
+ path.AddRoundedRectangle(0, 0, rect.width, rect.height, radius);
+ gc->DrawPath(path);
+ delete gc;
+ }
+#endif
+}
+
+void FilamentGroupPopup::Init(bool connect_status)
+{
+ radio_btns[ButtonType::btForMatch]->Enable(connect_status);
+ button_labels[ButtonType::btForMatch]->Enable(connect_status);
+
+ m_mode = get_prefered_map_mode();
+
+ wxCheckBoxState check_state = get_pop_up_remind_flag() ? wxCheckBoxState::wxCHK_UNCHECKED : wxCheckBoxState::wxCHK_CHECKED;
+ remind_checkbox->Set3StateValue(check_state);
+
+ UpdateButtonStatus();
+}
+
+void FilamentGroupPopup::tryPopup(bool connect_status)
+{
+ auto canPopup = [this]() {
+ bool is_multi_extruder_ = is_multi_extruder();
+ bool pop_up_flag = get_pop_up_remind_flag();
+ return is_multi_extruder_ && pop_up_flag;
+ };
+
+ if (canPopup()) {
+ DrawRoundedCorner(16);
+ Init(connect_status);
+ ResetTimer();
+ PopupWindow::Popup();
+ }
+}
+
+void FilamentGroupPopup::tryClose() { StartTimer(); }
+
+void FilamentGroupPopup::StartTimer() { m_timer->StartOnce(300); }
+
+void FilamentGroupPopup::ResetTimer()
+{
+ if (m_timer->IsRunning()) { m_timer->Stop(); }
+}
+
+void FilamentGroupPopup::OnRadioBtn(wxCommandEvent &event)
+{
+ m_mode = mode_list.at(event.GetInt());
+
+ set_prefered_map_mode(m_mode);
+
+ UpdateButtonStatus(m_mode);
+}
+
+void FilamentGroupPopup::OnRemindBtn(wxCommandEvent &event)
+{
+ bool is_checked = remind_checkbox->IsChecked();
+ set_pop_up_remind_flag(!is_checked);
+
+ if (is_checked) {
+ MessageDialog dialog(nullptr, _L("No further pop up.You can go to \"Preferences\" to reopen the pop up."), _L("Tips"), wxICON_INFORMATION | wxOK);
+ dialog.ShowModal();
+ Dismiss();
+ }
+}
+
+void FilamentGroupPopup::OnTimer(wxTimerEvent &event) { Dismiss(); }
+
+void FilamentGroupPopup::OnLeaveWindow(wxMouseEvent &)
+{
+ wxPoint pos = this->ScreenToClient(wxGetMousePosition());
+ if (this->GetClientRect().Contains(pos)) return;
+ StartTimer();
+}
+
+void FilamentGroupPopup::OnEnterWindow(wxMouseEvent &) { ResetTimer(); }
+
+void FilamentGroupPopup::UpdateButtonStatus(int hover_idx)
+{
+ auto checked_bmp = create_scaled_bitmap("map_mode_on", nullptr, 16);
+ auto unchecked_bmp = create_scaled_bitmap("map_mode_off", nullptr, 16);
+ auto checked_hover_bmp = create_scaled_bitmap("map_mode_on_hovered", nullptr);
+ auto unchecked_hover_bmp = create_scaled_bitmap("map_mode_off_hovered", nullptr);
+
+ for (int i = 0; i < ButtonType::btCount; ++i) {
+ // process checked and unchecked status
+ if (mode_list.at(i) == m_mode) {
+ if (i == hover_idx)
+ radio_btns[i]->SetBitmap(checked_hover_bmp);
+ else
+ radio_btns[i]->SetBitmap(checked_bmp);
+ button_labels[i]->SetFont(Label::Head_14);
+ } else {
+ if (i == hover_idx)
+ radio_btns[i]->SetBitmap(unchecked_hover_bmp);
+ else
+ radio_btns[i]->SetBitmap(unchecked_bmp);
+ button_labels[i]->SetFont(Label::Body_14);
+ }
+ }
+
+ if (m_mode == FilamentMapMode::fmmAutoForMatch)
+ remind_checkbox->Enable(false);
+ else
+ remind_checkbox->Enable(true);
+}
+
+}} // namespace Slic3r::GUI
\ No newline at end of file
diff --git a/src/slic3r/GUI/FilamentGroupPopup.hpp b/src/slic3r/GUI/FilamentGroupPopup.hpp
new file mode 100644
index 000000000..6486b2c32
--- /dev/null
+++ b/src/slic3r/GUI/FilamentGroupPopup.hpp
@@ -0,0 +1,54 @@
+#ifndef FILAMENT_GROUP_HOVER_HPP
+#define FILAMENT_GROUP_HOVER_HPP
+
+#include
+#include
+#include "wxExtensions.hpp"
+#include "Widgets/PopupWindow.hpp"
+
+namespace Slic3r { namespace GUI {
+
+bool is_pop_up_required();
+FilamentMapMode get_prefered_map_mode();
+
+class FilamentGroupPopup : public PopupWindow
+{
+public:
+ FilamentGroupPopup(wxWindow *parent);
+ void tryPopup(bool connect_status);
+ void tryClose();
+
+ FilamentMapMode GetSelectedMode() const { return m_mode; }
+
+private:
+ void StartTimer();
+ void ResetTimer();
+
+ void OnRadioBtn(wxCommandEvent &event);
+ void OnLeaveWindow(wxMouseEvent &);
+ void OnEnterWindow(wxMouseEvent &);
+ void OnTimer(wxTimerEvent &event);
+ void OnRemindBtn(wxCommandEvent &event);
+
+ void Init(bool connect_status);
+ void UpdateButtonStatus(int hover_idx = -1);
+ void DrawRoundedCorner(int radius);
+
+private:
+ enum ButtonType { btForFlush, btForMatch, btManual, btCount };
+
+ const std::vector mode_list = {fmmAutoForFlush, fmmAutoForMatch, fmmManual};
+
+ FilamentMapMode m_mode;
+ wxTimer *m_timer;
+
+ std::vector radio_btns;
+ std::vector button_labels;
+ std::vector button_desps;
+ std::vector detail_infos;
+
+ wxStaticText *wiki_link;
+ wxCheckBox *remind_checkbox;
+};
+}} // namespace Slic3r::GUI
+#endif
\ No newline at end of file
diff --git a/src/slic3r/GUI/FilamentMapDialog.cpp b/src/slic3r/GUI/FilamentMapDialog.cpp
index 2ee92c966..af5a8ebe8 100644
--- a/src/slic3r/GUI/FilamentMapDialog.cpp
+++ b/src/slic3r/GUI/FilamentMapDialog.cpp
@@ -3,210 +3,118 @@
#include "Widgets/Button.hpp"
#include "Widgets/SwitchButton.hpp"
#include "I18N.hpp"
+#include "GUI_App.hpp"
+#include "CapsuleButton.hpp"
+#include "SelectMachine.hpp"
namespace Slic3r { namespace GUI {
-const wxString manual_tips = _L("we will slice according to this grouping method:");
-
-const wxString manual_below_tips = _L("Tips:\n"
- "You can drag the filaments to change which extruder they are assigned to.\n"
- "But your filament arrangement may not be the most filament-efficient.");
-
-const wxString auto_tips = _L("Automatic filament grouping will be performed to reduce flushing consumption\n"
- "and filament changes during the slicing process.\n"
- "The recommended results will be displayed below after slicing:");
-
-const wxString auto_tips_with_result = _L("Automatic filament grouping will be performed to reduce flushing consumption\n"
- "and filament changes during the slicing process.\n"
- "The recommended results are shown below:");
-
-wxColour hex_to_color(const std::string &hex)
-{
- if ((hex.length() != 7 && hex.length() != 9) || hex[0] != '#') {
- throw std::invalid_argument("Invalid hex color format");
- }
-
- unsigned int r, g, b, a = 255;
- std::stringstream ss;
-
- // r
- ss << std::hex << hex.substr(1, 2);
- ss >> r;
- ss.clear();
- ss.str("");
-
- // g
- ss << std::hex << hex.substr(3, 2);
- ss >> g;
- ss.clear();
- ss.str("");
-
- // b
- ss << std::hex << hex.substr(5, 2);
- ss >> b;
-
- // a
- if (hex.length() == 9) {
- ss.clear();
- ss.str("");
- ss << std::hex << hex.substr(7, 2);
- ss >> a;
- }
-
- return wxColour(r, g, b, a);
-}
-
-FilamentMapDialog::FilamentMapDialog(wxWindow *parent,
- const DynamicPrintConfig *config,
- const std::vector &filament_map,
- const std::vector &extruders,
- bool is_auto,
- bool has_auto_result
-)
+FilamentMapDialog::FilamentMapDialog(wxWindow *parent,
+ const std::vector &filament_color,
+ const std::vector &filament_map,
+ const std::vector &filaments,
+ const FilamentMapMode mode,
+ bool show_default)
: wxDialog(parent, wxID_ANY, _L("Filament arrangement method of plate"), wxDefaultPosition, wxSize(2000, 1500))
- , m_config(config)
+ , m_filament_color(filament_color)
, m_filament_map(filament_map)
- , m_has_auto_result(has_auto_result)
{
SetBackgroundColour(*wxWHITE);
+ SetMinSize(wxSize(FromDIP(550), -1));
+ SetMaxSize(wxSize(FromDIP(550), -1));
+
+ if (mode < fmmManual)
+ m_page_type = PageType::ptAuto;
+ else if (mode == fmmManual)
+ m_page_type = PageType::ptManual;
+ else
+ m_page_type = PageType::ptDefault;
+
wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
+ main_sizer->AddSpacer(FromDIP(22));
- m_mode_switch_btn = new SwitchButton(this);
- m_mode_switch_btn->SetMaxSize({em_unit(this) * 12, -1});
- m_mode_switch_btn->SetLabels(_L("Customize"), _L("Auto"));
- m_mode_switch_btn->Bind(wxEVT_TOGGLEBUTTON, &FilamentMapDialog::on_switch_mode, this);
- m_mode_switch_btn->SetValue(is_auto);
- main_sizer->Add(m_mode_switch_btn, 0, wxCENTER | wxALL, 10);
+ wxBoxSizer *mode_sizer = new wxBoxSizer(wxHORIZONTAL);
- m_tip_text = new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
- main_sizer->Add(m_tip_text, 0, wxALIGN_LEFT | wxLEFT, 15);
+ m_auto_btn = new CapsuleButton(this, PageType::ptAuto, _L("Auto"), false);
+ m_manual_btn = new CapsuleButton(this, PageType::ptManual, _L("Custom"), false);
+ if (show_default)
+ m_default_btn = new CapsuleButton(this, PageType::ptDefault, _L("Default"), true);
+ else
+ m_default_btn = nullptr;
- m_extruder_panel_sizer = new wxBoxSizer(wxHORIZONTAL);
+ const int button_padding = FromDIP(2);
+ mode_sizer->AddStretchSpacer();
+ mode_sizer->Add(m_auto_btn, 1, wxALIGN_CENTER | wxLEFT | wxRIGHT, button_padding);
+ mode_sizer->Add(m_manual_btn, 1, wxALIGN_CENTER | wxLEFT | wxRIGHT, button_padding);
+ if (show_default) mode_sizer->Add(m_default_btn, 1, wxALIGN_CENTER | wxLEFT | wxRIGHT, button_padding);
+ mode_sizer->AddStretchSpacer();
- m_manual_left_panel = new DragDropPanel(this, wxT("Left nozzle:"), false);
- m_manual_right_panel = new DragDropPanel(this, wxT("Right nozzle:"), false);
+ main_sizer->Add(mode_sizer, 0, wxEXPAND);
+ main_sizer->AddSpacer(FromDIP(24));
- std::vector filament_color = config->option("filament_colour")->values;
- for (size_t i = 0; i < filament_map.size(); ++i) {
- auto iter = std::find(extruders.begin(), extruders.end(), i + 1);
- if (iter == extruders.end())
- continue;
+ auto panel_sizer = new wxBoxSizer(wxHORIZONTAL);
+ FilamentMapMode default_auto_mode = (mode < FilamentMapMode::fmmManual ? mode : FilamentMapMode::fmmAutoForFlush);
+ m_manual_map_panel = new FilamentMapManualPanel(this, m_filament_color, filaments, filament_map);
+ m_auto_map_panel = new FilamentMapAutoPanel(this, default_auto_mode);
+ if (show_default)
+ m_default_map_panel = new FilamentMapDefaultPanel(this);
+ else
+ m_default_map_panel = nullptr;
- if (filament_map[i] == 1) {
- m_manual_left_panel->AddColorBlock(hex_to_color(filament_color[i]), i + 1);
- }
- else if (filament_map[i] == 2) {
- m_manual_right_panel->AddColorBlock(hex_to_color(filament_color[i]), i + 1);
- }
- else {
- assert(false);
- }
- }
+ panel_sizer->Add(m_manual_map_panel, 0, wxALIGN_CENTER | wxEXPAND);
+ panel_sizer->Add(m_auto_map_panel, 0, wxALIGN_CENTER | wxEXPAND);
+ if (show_default) panel_sizer->Add(m_default_map_panel, 0, wxALIGN_CENTER | wxEXPAND);
+ main_sizer->Add(panel_sizer, 0, wxEXPAND);
- m_switch_filament_btn = new ScalableButton(this, wxID_ANY, "switch_filament_maps");
- m_switch_filament_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_switch_filaments, this);
- m_switch_filament_btn->SetCanFocus(false);
- // just for placeholder for auto
- m_switch_filament_btn_auto = new ScalableButton(this, wxID_ANY, "switch_filament_maps");
- m_switch_filament_btn_auto->Enable(false);
-
- m_extruder_panel_sizer->Add(m_manual_left_panel, 1, wxEXPAND | wxALL, 5);
- m_extruder_panel_sizer->Add(m_switch_filament_btn, 0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
- m_extruder_panel_sizer->Add(m_manual_right_panel, 1, wxEXPAND | wxALL, 5);
- m_manual_left_panel->Layout();
- m_manual_left_panel->Fit();
- m_manual_right_panel->Layout();
- m_manual_right_panel->Fit();
-
- m_auto_left_panel = new DragDropPanel(this, wxT("Left nozzle:"), true);
- m_auto_right_panel = new DragDropPanel(this, wxT("Right nozzle:"), true);
-
- for (size_t i = 0; i < filament_map.size(); ++i) {
- auto iter = std::find(extruders.begin(), extruders.end(), i + 1);
- if (iter == extruders.end()) continue;
-
- if (filament_map[i] == 1) {
- m_auto_left_panel->AddColorBlock(hex_to_color(filament_color[i]), i + 1);
- } else if (filament_map[i] == 2) {
- m_auto_right_panel->AddColorBlock(hex_to_color(filament_color[i]), i + 1);
- } else {
- assert(false);
- }
- }
-
- m_extruder_panel_sizer->Add(m_auto_left_panel, 1, wxEXPAND | wxALL, 5);
- m_extruder_panel_sizer->Add(m_switch_filament_btn_auto, 0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
- m_extruder_panel_sizer->Add(m_auto_right_panel, 1, wxEXPAND | wxALL, 5);
- m_auto_left_panel->Layout();
- m_auto_left_panel->Fit();
- m_auto_right_panel->Layout();
- m_auto_right_panel->Fit();
-
- main_sizer->Add(m_extruder_panel_sizer, 1, wxEXPAND | wxALL, 10);
-
- m_below_tip_text = new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
- m_below_tip_text->SetLabel(manual_below_tips);
- main_sizer->Add(m_below_tip_text, 0, wxALIGN_LEFT | wxLEFT, 15);
-
- if (is_auto) {
- m_manual_left_panel->Hide();
- m_manual_right_panel->Hide();
- m_switch_filament_btn->Hide();
- m_below_tip_text->Hide();
- if (m_has_auto_result) {
- m_tip_text->SetLabel(auto_tips_with_result);
- }
- else {
- m_auto_left_panel->Hide();
- m_auto_right_panel->Hide();
- m_switch_filament_btn_auto->Hide();
- m_tip_text->SetLabel(auto_tips);
- }
- }
- else {
- m_auto_left_panel->Hide();
- m_auto_right_panel->Hide();
- m_switch_filament_btn_auto->Hide();
- m_tip_text->SetLabel(manual_tips);
- m_below_tip_text->Show();
- }
-
- wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
- Button * ok_btn = new Button(this, _L("OK"));
- Button * cancel_btn = new Button(this, _L("Cancel"));
- button_sizer->Add(ok_btn, 0, wxALL, 5);
- button_sizer->Add(cancel_btn, 0, wxALL, 5);
+ wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
+ m_ok_btn = new Button(this, _L("OK"));
+ m_cancel_btn = new Button(this, _L("Cancel"));
+ button_sizer->Add(m_ok_btn, 0, wxALL, 5);
+ button_sizer->Add(m_cancel_btn, 0, wxALL, 5);
main_sizer->Add(button_sizer, 0, wxALIGN_CENTER | wxALL, 10);
- ok_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_ok, this);
- cancel_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_cancle, this);
+ m_ok_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_ok, this);
+ m_cancel_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_cancle, this);
+
+ m_auto_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_switch_mode, this);
+ m_manual_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_switch_mode, this);
+ if (show_default) m_default_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_switch_mode, this);
SetSizer(main_sizer);
Layout();
Fit();
CenterOnParent();
+ GUI::wxGetApp().UpdateDarkUIWin(this);
}
-bool FilamentMapDialog::is_auto() const
+FilamentMapMode FilamentMapDialog::get_mode()
{
- if (m_mode_switch_btn->GetValue()) {
- return true;
- }
- return false;
+ if (m_page_type == PageType::ptAuto)
+ return m_auto_map_panel->GetMode();
+ if (m_page_type == PageType::ptManual)
+ return fmmManual;
+ return fmmDefault;
+}
+
+int FilamentMapDialog::ShowModal()
+{
+ update_panel_status(m_page_type);
+ return wxDialog::ShowModal();
}
void FilamentMapDialog::on_ok(wxCommandEvent &event)
{
- if (!is_auto()) {
- std::vector left_filaments = m_manual_left_panel->GetAllFilaments();
- std::vector right_filaments = m_manual_right_panel->GetAllFilaments();
+ if (m_page_type == PageType::ptManual) {
+ std::vector left_filaments = m_manual_map_panel->GetLeftFilaments();
+ std::vector right_filaments = m_manual_map_panel->GetRightFilaments();
for (int i = 0; i < m_filament_map.size(); ++i) {
if (std::find(left_filaments.begin(), left_filaments.end(), i + 1) != left_filaments.end()) {
m_filament_map[i] = 1;
- } else if (std::find(right_filaments.begin(), right_filaments.end(), i + 1) != right_filaments.end()) {
+ }
+ else if (std::find(right_filaments.begin(), right_filaments.end(), i + 1) != right_filaments.end()) {
m_filament_map[i] = 2;
}
}
@@ -215,63 +123,62 @@ void FilamentMapDialog::on_ok(wxCommandEvent &event)
EndModal(wxID_OK);
}
-void FilamentMapDialog::on_cancle(wxCommandEvent &event)
+void FilamentMapDialog::on_cancle(wxCommandEvent &event) { EndModal(wxID_CANCEL); }
+
+void FilamentMapDialog::update_panel_status(PageType page)
{
- EndModal(wxID_CANCEL);
+ if (page == PageType::ptDefault) {
+ if (m_default_btn && m_default_map_panel) {
+ m_default_btn->Select(true);
+ m_default_map_panel->Show();
+ }
+
+ m_manual_btn->Select(false);
+ m_manual_map_panel->Hide();
+
+ m_auto_btn->Select(false);
+ m_auto_map_panel->Hide();
+ }
+ if (page == PageType::ptManual) {
+ if (m_default_btn && m_default_map_panel) {
+ m_default_btn->Select(false);
+ m_default_map_panel->Hide();
+ }
+ m_manual_btn->Select(true);
+ m_manual_map_panel->Show();
+
+ m_auto_btn->Select(false);
+ m_auto_map_panel->Hide();
+ }
+ if (page == PageType::ptAuto) {
+ if (m_default_btn && m_default_map_panel) {
+ m_default_btn->Select(false);
+ m_default_map_panel->Hide();
+ }
+ m_manual_btn->Select(false);
+ m_manual_map_panel->Hide();
+
+ m_auto_btn->Select(true);
+ m_auto_map_panel->Show();
+ }
+ Layout();
+ Fit();
}
void FilamentMapDialog::on_switch_mode(wxCommandEvent &event)
{
- bool value = dynamic_cast(event.GetEventObject())->GetValue();
- if (value) { // auto
- m_manual_left_panel->Hide();
- m_manual_right_panel->Hide();
- m_switch_filament_btn->Hide();
- m_below_tip_text->Hide();
- if (m_has_auto_result) {
- m_auto_left_panel->Show();
- m_auto_right_panel->Show();
- m_switch_filament_btn_auto->Show();
- m_tip_text->SetLabel(auto_tips_with_result);
- }
- else {
- m_auto_left_panel->Hide();
- m_auto_right_panel->Hide();
- m_switch_filament_btn_auto->Hide();
- m_tip_text->SetLabel(auto_tips);
- }
- } else { // manual
- m_manual_left_panel->Show();
- m_manual_right_panel->Show();
- m_switch_filament_btn->Show();
- m_below_tip_text->Show();
+ int win_id = event.GetId();
+ m_page_type = PageType(win_id);
- m_auto_left_panel->Hide();
- m_auto_right_panel->Hide();
- m_switch_filament_btn_auto->Hide();
-
- m_tip_text->SetLabel(manual_tips);
- }
- Layout();
- Fit();
+ update_panel_status(m_page_type);
event.Skip();
}
-void FilamentMapDialog::on_switch_filaments(wxCommandEvent &event)
+void FilamentMapDialog::set_modal_btn_labels(const wxString &ok_label, const wxString &cancel_label)
{
- std::vector left_blocks = m_manual_left_panel->get_filament_blocks();
- std::vector right_blocks = m_manual_right_panel->get_filament_blocks();
-
- for (ColorPanel* block : left_blocks) {
- m_manual_right_panel->AddColorBlock(block->GetColor(), block->GetFilamentId(), false);
- m_manual_left_panel->RemoveColorBlock(block, false);
- }
- for (auto block : right_blocks) {
- m_manual_left_panel->AddColorBlock(block->GetColor(), block->GetFilamentId(), false);
- m_manual_right_panel->RemoveColorBlock(block, false);
- }
- Layout();
- Fit();
+ m_ok_btn->SetLabel(ok_label);
+ m_cancel_btn->SetLabel(cancel_label);
}
+
}} // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/FilamentMapDialog.hpp b/src/slic3r/GUI/FilamentMapDialog.hpp
index d1f883fa4..abdc19f17 100644
--- a/src/slic3r/GUI/FilamentMapDialog.hpp
+++ b/src/slic3r/GUI/FilamentMapDialog.hpp
@@ -2,10 +2,13 @@
#define slic3r_FilamentMapDialog_hpp_
#include "GUI.hpp"
+#include "FilamentMapPanel.hpp"
#include
#include
#include
#include
+#include "SelectMachine.hpp"
+#include "CapsuleButton.hpp"
class SwitchButton;
class ScalableButton;
@@ -17,42 +20,52 @@ class DynamicPrintConfig;
namespace GUI {
class DragDropPanel;
+
class FilamentMapDialog : public wxDialog
{
+ enum PageType {
+ ptAuto,
+ ptManual,
+ ptDefault
+ };
public:
FilamentMapDialog(wxWindow *parent,
- const DynamicPrintConfig *config,
+ const std::vector& filament_color,
const std::vector &filament_map,
- const std::vector &extruders,
- bool is_auto,
- bool has_auto_result
+ const std::vector &filaments,
+ const FilamentMapMode mode,
+ bool show_default=true
);
- bool is_auto() const;
+ FilamentMapMode get_mode();
const std::vector& get_filament_maps() const { return m_filament_map; }
+ int ShowModal();
+ void set_modal_btn_labels(const wxString& left_label, const wxString& right_label);
private:
void on_ok(wxCommandEvent &event);
void on_cancle(wxCommandEvent &event);
void on_switch_mode(wxCommandEvent &event);
- void on_switch_filaments(wxCommandEvent &event);
+
+ void update_panel_status(PageType page);
+
+ private:
+ FilamentMapManualPanel* m_manual_map_panel;
+ FilamentMapAutoPanel* m_auto_map_panel;
+ FilamentMapDefaultPanel* m_default_map_panel;
+
+ CapsuleButton* m_auto_btn;
+ CapsuleButton* m_manual_btn;
+ CapsuleButton* m_default_btn;
+
+ Button* m_ok_btn;
+ Button* m_cancel_btn;
+
+ PageType m_page_type;
private:
- wxStaticText * m_tip_text;
- wxStaticText * m_below_tip_text;
- SwitchButton * m_mode_switch_btn;
- wxBoxSizer * m_extruder_panel_sizer;
- DragDropPanel* m_manual_left_panel;
- DragDropPanel* m_manual_right_panel;
- DragDropPanel* m_auto_left_panel;
- DragDropPanel* m_auto_right_panel;
- ScalableButton* m_switch_filament_btn;
- ScalableButton* m_switch_filament_btn_auto; // for placeholder
-
-private:
- const DynamicPrintConfig* m_config;
std::vector m_filament_map;
- bool m_has_auto_result;
+ std::vector m_filament_color;
};
}} // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/FilamentMapPanel.cpp b/src/slic3r/GUI/FilamentMapPanel.cpp
new file mode 100644
index 000000000..2f150efeb
--- /dev/null
+++ b/src/slic3r/GUI/FilamentMapPanel.cpp
@@ -0,0 +1,324 @@
+#include "FilamentMapPanel.hpp"
+#include "GUI_App.hpp"
+#include "wx/graphics.h"
+
+namespace Slic3r { namespace GUI {
+FilamentMapManualPanel::FilamentMapManualPanel(wxWindow *parent,
+ const std::vector &color,
+ const std::vector &filament_list,
+ const std::vector &filament_map)
+ : wxPanel(parent), m_filament_map(filament_map), m_filament_color(color), m_filament_list(filament_list)
+{
+ SetBackgroundColour(wxColor(255, 255, 255));
+
+ auto top_sizer = new wxBoxSizer(wxVERTICAL);
+
+ m_description = new Label(this, _L("We will slice according to this grouping method:"));
+ top_sizer->Add(m_description, 0, wxALIGN_LEFT | wxLEFT, FromDIP(15));
+ top_sizer->AddSpacer(FromDIP(8));
+
+ auto drag_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ m_left_panel = new DragDropPanel(this, wxT("Left Nozzle:"), false);
+ m_right_panel = new DragDropPanel(this, wxT("Right Nozzle:"), false);
+ m_switch_btn = new ScalableButton(this, wxID_ANY, "switch_filament_maps");
+
+ for (size_t idx = 0; idx < m_filament_map.size(); ++idx) {
+ auto iter = std::find(m_filament_list.begin(), m_filament_list.end(), idx + 1);
+ if (iter == m_filament_list.end()) continue;
+ wxColor color = Hex2Color(m_filament_color[idx]);
+ if (m_filament_map[idx] == 1) {
+ m_left_panel->AddColorBlock(color, idx + 1);
+ } else {
+ assert(m_filament_map[idx] == 2);
+ m_right_panel->AddColorBlock(color, idx + 1);
+ }
+ }
+ drag_sizer->Add(m_left_panel, 1, wxALIGN_CENTER | wxEXPAND | wxLEFT, FromDIP(20));
+ drag_sizer->AddSpacer(FromDIP(7));
+ drag_sizer->Add(m_switch_btn, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(1));
+ drag_sizer->AddSpacer(FromDIP(7));
+ drag_sizer->Add(m_right_panel, 1, wxALIGN_CENTER | wxEXPAND | wxRIGHT, FromDIP(20));
+
+ top_sizer->Add(drag_sizer, 0, wxALIGN_CENTER|wxEXPAND);
+
+ m_tips = new Label(this, _L("Tips: You can drag the filaments to change which extruder they are assigned to.\n"
+ "But your filament arrangement may not be the most filament-efficient."));
+ m_tips->SetFont(Label::Body_14);
+ m_tips->SetForegroundColour(wxColour("#6B6B6B"));
+ top_sizer->AddSpacer(FromDIP(8));
+ top_sizer->Add(m_tips, 0, wxALIGN_LEFT | wxLEFT, FromDIP(15));
+
+ m_switch_btn->Bind(wxEVT_BUTTON, &FilamentMapManualPanel::OnSwitchFilament, this);
+
+ SetSizer(top_sizer);
+ Layout();
+ Fit();
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+}
+
+void FilamentMapManualPanel::OnSwitchFilament(wxCommandEvent &)
+{
+ auto left_blocks = m_left_panel->get_filament_blocks();
+ auto right_blocks = m_right_panel->get_filament_blocks();
+
+ for (auto &block : left_blocks) {
+ m_right_panel->AddColorBlock(block->GetColor(), block->GetFilamentId(), false);
+ m_left_panel->RemoveColorBlock(block, false);
+ }
+
+ for (auto &block : right_blocks) {
+ m_left_panel->AddColorBlock(block->GetColor(), block->GetFilamentId(), false);
+ m_right_panel->RemoveColorBlock(block, false);
+ }
+
+ Layout();
+ Fit();
+}
+
+void FilamentMapManualPanel::Hide()
+{
+ m_left_panel->Hide();
+ m_right_panel->Hide();
+ m_switch_btn->Hide();
+ wxPanel::Hide();
+}
+
+void FilamentMapManualPanel::Show()
+{
+ m_left_panel->Show();
+ m_right_panel->Show();
+ m_switch_btn->Show();
+ wxPanel::Show();
+}
+
+GUI::FilamentMapBtnPanel::FilamentMapBtnPanel(wxWindow *parent, const wxString &label, const wxString &detail, const std::string &icon) : wxPanel(parent)
+{
+ SetBackgroundColour(*wxWHITE);
+ SetBackgroundStyle(wxBG_STYLE_PAINT);
+ m_hover = false;
+
+ const int horizontal_margin = FromDIP(12);
+
+ auto sizer = new wxBoxSizer(wxVERTICAL);
+
+ auto bmp = create_scaled_bitmap(icon, nullptr, 20);
+ m_btn = new wxBitmapButton(this, wxID_ANY, bmp, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
+ m_btn->SetBackgroundColour(*wxWHITE);
+
+ m_label = new wxStaticText(this, wxID_ANY, label);
+ m_label->SetFont(Label::Head_14);
+
+ auto label_sizer = new wxBoxSizer(wxHORIZONTAL);
+ label_sizer->AddStretchSpacer();
+ label_sizer->Add(m_btn, 0, wxALIGN_CENTER|wxEXPAND);
+ label_sizer->Add(m_label, 0, wxALIGN_CENTER|wxEXPAND);
+ label_sizer->AddStretchSpacer();
+
+ sizer->AddSpacer(FromDIP(32));
+ sizer->Add(label_sizer, 0, wxALIGN_CENTER | wxEXPAND);
+ sizer->AddSpacer(FromDIP(24));
+
+ auto detail_sizer = new wxBoxSizer(wxHORIZONTAL);
+ m_detail = new Label(this, detail);
+ m_detail->SetFont(Label::Body_12);
+ m_detail->SetForegroundColour(wxColour("#6B6B6B"));
+ m_detail->Wrap(FromDIP(180));
+
+ detail_sizer->AddStretchSpacer();
+ detail_sizer->Add(m_detail, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, horizontal_margin);
+ detail_sizer->AddStretchSpacer();
+
+ sizer->Add(detail_sizer, 0, wxALIGN_CENTER | wxEXPAND);
+ sizer->AddSpacer(FromDIP(10));
+
+ SetSizer(sizer);
+ Layout();
+ Fit();
+
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+
+ auto forward_click_to_parent = [this](wxMouseEvent &event) {
+ wxCommandEvent click_event(wxEVT_LEFT_DOWN, GetId());
+ click_event.SetEventObject(this);
+ this->ProcessEvent(click_event);
+ };
+
+ m_btn->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+ m_label->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+ m_detail->Bind(wxEVT_LEFT_DOWN, forward_click_to_parent);
+
+ Bind(wxEVT_PAINT, &FilamentMapBtnPanel::OnPaint, this);
+ Bind(wxEVT_ENTER_WINDOW, &FilamentMapBtnPanel::OnEnterWindow, this);
+ Bind(wxEVT_LEAVE_WINDOW, &FilamentMapBtnPanel::OnLeaveWindow, this);
+}
+
+void FilamentMapBtnPanel::OnPaint(wxPaintEvent &event)
+{
+ wxAutoBufferedPaintDC dc(this);
+ wxGraphicsContext *gc = wxGraphicsContext::Create(dc);
+
+ if (gc) {
+ dc.Clear();
+ wxRect rect = GetClientRect();
+ gc->SetBrush(wxTransparentColour);
+ gc->DrawRoundedRectangle(0, 0, rect.width, rect.height, 0);
+ wxColour bg_color = m_selected ? wxColour("#EBF9F0") : wxColour("#FFFFFF");
+ wxColour border_color = m_hover || m_selected ? wxColour("#00AE42") : wxColour("#CECECE");
+ int cornerRadius = 8;
+ gc->SetBrush(wxBrush(bg_color));
+ gc->SetPen(wxPen(border_color, 2));
+ gc->DrawRoundedRectangle(1, 1, rect.width - 2, rect.height - 2, cornerRadius);
+ delete gc;
+ }
+}
+
+void FilamentMapBtnPanel::UpdateStatus()
+{
+ const wxColour selected_color = wxColour("#EBF9F0");
+ const wxColour normal_color = wxColour("#FFFFFF");
+ if (m_selected) {
+ m_btn->SetBackgroundColour(selected_color);
+ m_label->SetBackgroundColour(selected_color);
+ m_detail->SetBackgroundColour(selected_color);
+ } else {
+ m_btn->SetBackgroundColour(normal_color);
+ m_label->SetBackgroundColour(normal_color);
+ m_detail->SetBackgroundColour(normal_color);
+ }
+}
+
+void FilamentMapBtnPanel::OnEnterWindow(wxMouseEvent &event)
+{
+ if (!m_hover) {
+ m_hover = true;
+ UpdateStatus();
+ Refresh();
+ event.Skip();
+ }
+}
+
+void FilamentMapBtnPanel::OnLeaveWindow(wxMouseEvent &event)
+{
+ if (m_hover) {
+ wxPoint pos = this->ScreenToClient(wxGetMousePosition());
+ if (this->GetClientRect().Contains(pos)) return;
+ m_hover = false;
+ UpdateStatus();
+ Refresh();
+ event.Skip();
+ }
+}
+
+void FilamentMapBtnPanel::Select(bool selected)
+{
+ m_selected = selected;
+ UpdateStatus();
+ Refresh();
+}
+
+void GUI::FilamentMapBtnPanel::Hide()
+{
+ m_btn->Hide();
+ m_label->Hide();
+ m_detail->Hide();
+ wxPanel::Hide();
+}
+void GUI::FilamentMapBtnPanel::Show()
+{
+ m_btn->Show();
+ m_label->Show();
+ m_detail->Show();
+ wxPanel::Show();
+}
+
+FilamentMapAutoPanel::FilamentMapAutoPanel(wxWindow *parent, FilamentMapMode mode) : wxPanel(parent)
+{
+ static const wxString AutoForFlushDetail = _L("Disregrad the filaments in AMS. Optimize filament usage "
+ "by calculating the best allocation for the left and right "
+ "nozzles. Arrange the filaments according on the printer according to "
+ "the slicing results.");
+ static const wxString AutoForMatchDetail = _L("Based on the current filaments in the AMS, allocate the "
+ "filaments to the left and right nozzles.");
+ auto sizer = new wxBoxSizer(wxHORIZONTAL);
+ m_flush_panel = new FilamentMapBtnPanel(this, _L("Material-Saving Mode"), AutoForFlushDetail, "flush_mode_panel_icon");
+ m_match_panel = new FilamentMapBtnPanel(this, _L("Convenient Mode"), AutoForMatchDetail,"match_mode_panel_icon");
+
+ sizer->AddStretchSpacer();
+ sizer->Add(m_flush_panel, 1, wxEXPAND);
+ sizer->AddSpacer(FromDIP(12));
+ sizer->Add(m_match_panel, 1, wxEXPAND);
+ sizer->AddStretchSpacer();
+
+ m_flush_panel->Bind(wxEVT_LEFT_DOWN, [this](auto &event) { this->OnModeSwitch(FilamentMapMode::fmmAutoForFlush); });
+
+ m_match_panel->Bind(wxEVT_LEFT_DOWN, [this](auto &event) { this->OnModeSwitch(FilamentMapMode::fmmAutoForMatch); });
+
+ m_mode = mode;
+ UpdateStatus();
+
+ SetSizerAndFit(sizer);
+ Layout();
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+}
+void FilamentMapAutoPanel::Hide()
+{
+ m_flush_panel->Hide();
+ m_match_panel->Hide();
+ wxPanel::Hide();
+}
+
+void FilamentMapAutoPanel::Show()
+{
+ m_flush_panel->Show();
+ m_match_panel->Show();
+ wxPanel::Show();
+}
+
+void FilamentMapAutoPanel::UpdateStatus()
+{
+ if (m_mode == fmmAutoForFlush) {
+ m_flush_panel->Select(true);
+ m_match_panel->Select(false);
+ } else {
+ m_flush_panel->Select(false);
+ m_match_panel->Select(true);
+ }
+}
+
+void FilamentMapAutoPanel::OnModeSwitch(FilamentMapMode mode)
+{
+ m_mode = mode;
+ UpdateStatus();
+}
+
+FilamentMapDefaultPanel::FilamentMapDefaultPanel(wxWindow *parent) : wxPanel(parent)
+{
+ auto sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ m_label = new Label(this, _L("The material allocation for the current disk follows the global settings."));
+ m_label->SetFont(Label::Body_14);
+ m_label->SetBackgroundColour(*wxWHITE);
+
+ sizer->AddStretchSpacer();
+ sizer->Add(m_label, 1, wxEXPAND|wxALIGN_CENTER);
+ sizer->AddStretchSpacer();
+
+ SetSizerAndFit(sizer);
+ Layout();
+ GUI::wxGetApp().UpdateDarkUIWin(this);
+}
+
+void FilamentMapDefaultPanel::Hide()
+{
+ m_label->Hide();
+ wxPanel::Hide();
+}
+
+void FilamentMapDefaultPanel::Show()
+{
+ m_label->Show();
+ wxPanel::Show();
+}
+
+}} // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/FilamentMapPanel.hpp b/src/slic3r/GUI/FilamentMapPanel.hpp
new file mode 100644
index 000000000..8f7826013
--- /dev/null
+++ b/src/slic3r/GUI/FilamentMapPanel.hpp
@@ -0,0 +1,89 @@
+
+#ifndef FILAMENT_MAP_PANEL_HPP
+#define FILAMENT_MAP_PANEL_HPP
+
+#include "GUI.hpp"
+#include "DragDropPanel.hpp"
+#include "Widgets/SwitchButton.hpp"
+
+namespace Slic3r { namespace GUI {
+
+class FilamentMapManualPanel : public wxPanel
+{
+public:
+ FilamentMapManualPanel(wxWindow *parent, const std::vector &color, const std::vector &filament_list, const std::vector &filament_map);
+
+ std::vector GetFilamentMaps() const { return m_filament_map; }
+ std::vector GetLeftFilaments() const { return m_left_panel->GetAllFilaments(); }
+ std::vector GetRightFilaments() const { return m_right_panel->GetAllFilaments(); }
+
+ void Hide();
+ void Show();
+
+private:
+ void OnSwitchFilament(wxCommandEvent &);
+ DragDropPanel *m_left_panel;
+ DragDropPanel *m_right_panel;
+
+ Label *m_description;
+ Label *m_tips;
+
+ ScalableButton *m_switch_btn;
+
+ std::vector m_filament_map;
+ std::vector m_filament_list;
+ std::vector m_filament_color;
+};
+
+class FilamentMapBtnPanel : public wxPanel
+{
+public:
+ FilamentMapBtnPanel(wxWindow *parent, const wxString &label, const wxString &detail, const std::string &icon_path);
+ void Hide();
+ void Show();
+ void Select(bool selected);
+protected:
+ void OnPaint(wxPaintEvent &event);
+private:
+ void OnEnterWindow(wxMouseEvent &event);
+ void OnLeaveWindow(wxMouseEvent &evnet);
+
+ void UpdateStatus();
+
+ wxBitmapButton *m_btn;
+ wxStaticText *m_label;
+ Label *m_detail;
+ bool m_hover{false};
+ bool m_selected{false};
+};
+
+class FilamentMapAutoPanel : public wxPanel
+{
+public:
+ FilamentMapAutoPanel(wxWindow *parent, FilamentMapMode mode);
+ void Hide();
+ void Show();
+ FilamentMapMode GetMode() const { return m_mode; }
+
+private:
+ void OnModeSwitch(FilamentMapMode mode);
+ void UpdateStatus();
+
+ FilamentMapBtnPanel *m_flush_panel;
+ FilamentMapBtnPanel *m_match_panel;
+ FilamentMapMode m_mode;
+};
+
+class FilamentMapDefaultPanel : public wxPanel
+{
+public:
+ FilamentMapDefaultPanel(wxWindow *parent);
+ void Hide();
+ void Show();
+
+private:
+ Label *m_label;
+};
+}} // namespace Slic3r::GUI
+
+#endif
\ No newline at end of file
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 7b87b957b..0269191f1 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -4626,7 +4626,7 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding)
Plater *plater = wxGetApp().plater();
wxCommandEvent evt(EVT_OPEN_FILAMENT_MAP_SETTINGS_DIALOG);
evt.SetEventObject(plater);
- evt.SetInt(0b0010); //0010 means from gcode view, manual mode
+ evt.SetInt(1); // 1 means from gcode viewer
wxPostEvent(plater, evt);
}
}
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 8c7afd289..32b3fb186 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -60,6 +60,7 @@
#include "ConfigWizard.hpp"
#include "Widgets/WebView.hpp"
#include "DailyTips.hpp"
+#include "FilamentMapDialog.hpp"
#ifdef _WIN32
#include
@@ -1593,6 +1594,8 @@ wxBoxSizer* MainFrame::create_side_tools()
sizer->Layout();
+ m_filament_group_popup = new FilamentGroupPopup(m_slice_btn);
+
m_slice_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
m_plater->reset_check_status();
@@ -1602,14 +1605,62 @@ wxBoxSizer* MainFrame::create_side_tools()
//this->m_plater->select_view_3D("Preview");
m_plater->exit_gizmo();
m_plater->update(true, true);
- if (m_slice_select == eSliceAll)
- wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL));
- else
- wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE));
- this->m_tabpanel->SetSelection(tpPreview);
+ bool slice = true;
+
+ auto full_config = wxGetApp().preset_bundle->full_config();
+ std::vectorg_filament_map = full_config.option("filament_map")->values;
+ FilamentMapMode g_filament_map_mode = get_prefered_map_mode();
+ if (is_pop_up_required()) {
+ auto filament_colors = full_config.option("filament_colour")->values;
+ g_filament_map.resize(filament_colors.size());
+ std::vector filament_lists(filament_colors.size());
+ std::iota(filament_lists.begin(), filament_lists.end(), 1);
+
+ FilamentMapDialog filament_dlg(this,
+ filament_colors,
+ g_filament_map,
+ filament_lists,
+ FilamentMapMode::fmmManual,
+ false
+ );
+ auto ret = filament_dlg.ShowModal();
+ if (ret == wxID_OK) {
+ g_filament_map_mode = filament_dlg.get_mode();
+ g_filament_map = filament_dlg.get_filament_maps();
+ }
+ else {
+ slice = false;
+ }
+ }
+
+ if (slice) {
+ m_plater->set_global_filament_map_mode(g_filament_map_mode);
+ if (g_filament_map_mode == FilamentMapMode::fmmManual)
+ m_plater->set_global_filament_map(g_filament_map);
+ if (m_slice_select == eSliceAll)
+ wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL));
+ else
+ wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE));
+ this->m_tabpanel->SetSelection(tpPreview);
+ }
});
+ m_slice_btn->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent& event) {
+ m_filament_group_popup->SetSize(wxSize(FromDIP(380),-1));
+ wxPoint pos = m_slice_btn->ClientToScreen(wxPoint(0, 0));
+ pos.y += m_slice_btn->GetRect().height * 1.25;
+ pos.x -= (m_slice_option_btn->GetRect().width + m_filament_group_popup->GetRect().width * 0.6);
+
+ m_filament_group_popup->SetPosition(pos);
+ m_filament_group_popup->tryPopup(m_plater->check_ams_status());
+ });
+
+ m_slice_btn->Bind(wxEVT_LEAVE_WINDOW, [this](auto& event) {
+ m_filament_group_popup->tryClose();
+ });
+
+
m_print_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
//this->m_plater->select_view_3D("Preview");
@@ -3868,6 +3919,7 @@ void MainFrame::technology_changed()
m_menubar->SetMenuLabel(id, pt == ptSLA ? _omitL("Material Settings") : _L("Filament Settings"));
}
+
//
// Called after the Preferences dialog is closed and the program settings are saved.
// Update the UI based on the current preferences.
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 4e24d31c3..452be1f54 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -27,6 +27,8 @@
#include "UnsavedChangesDialog.hpp"
#include "Widgets/SideButton.hpp"
#include "Widgets/SideMenuPopup.hpp"
+#include "FilamentGroupPopup.hpp"
+
// BBS
#include "BBLTopbar.hpp"
@@ -339,6 +341,7 @@ public:
void technology_changed();
+
//BBS
void load_url(wxString url);
void load_printer_url(wxString url);
@@ -391,6 +394,8 @@ public:
SideButton* m_slice_option_btn{ nullptr };
SideButton* m_print_btn{ nullptr };
SideButton* m_print_option_btn{ nullptr };
+
+ FilamentGroupPopup* m_filament_group_popup{ nullptr };
mutable bool m_slice_enable{ true };
mutable bool m_print_enable{ true };
bool get_enable_slice_status();
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 40b539316..dc779d6f7 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -15352,9 +15352,9 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) {
void Plater::open_filament_map_setting_dialog(wxCommandEvent &evt)
{
PartPlate* curr_plate = p->partplate_list.get_curr_plate();
- int value = evt.GetInt();
- bool is_auto = value & 1; //0000 means manual, 0001 means auto
- bool need_slice = value & (1 << 1); //0010 means from gcode view, 0000 means not from gcode view
+ int value = evt.GetInt(); //1 means from gcode view
+ bool force_manual = value == 1; // If from gcode view, should display manual page
+ bool need_slice = value ==1; // If from gcode view, should slice
const auto& project_config = wxGetApp().preset_bundle->project_config;
auto filament_colors = config()->option("filament_colour")->values;
@@ -15363,20 +15363,22 @@ void Plater::open_filament_map_setting_dialog(wxCommandEvent &evt)
if (plate_filament_maps.size() != filament_colors.size()) // refine it later, save filament map to app config
plate_filament_maps.resize(filament_colors.size(), 1);
+ FilamentMapMode display_mode = force_manual ? FilamentMapMode::fmmManual : plate_filament_map_mode;
+
FilamentMapDialog filament_dlg(this,
- config(),
+ filament_colors,
plate_filament_maps,
curr_plate->get_extruders(true),
- plate_filament_map_mode < FilamentMapMode::fmmManual,
- false
+ display_mode,
+ true
);
if (filament_dlg.ShowModal() == wxID_OK) {
std::vector new_filament_maps = filament_dlg.get_filament_maps();
- std::vector old_filament_maps = plate_filament_maps;
+ std::vector old_filament_maps = curr_plate->get_filament_maps();
FilamentMapMode old_map_mode = plate_filament_map_mode;
- FilamentMapMode new_map_mode = filament_dlg.is_auto() ? fmmAutoForFlush : fmmManual;
+ FilamentMapMode new_map_mode = filament_dlg.get_mode();
bool need_invalidate = (old_map_mode != new_map_mode ||
old_filament_maps != new_filament_maps);
@@ -15575,7 +15577,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
if (!ret) {
PartPlate * curr_plate = p->partplate_list.get_curr_plate();
wxCommandEvent evt(EVT_OPEN_FILAMENT_MAP_SETTINGS_DIALOG);
- evt.SetInt(curr_plate->get_filament_map_mode() < FilamentMapMode::fmmManual ? 1 : 0);
+ evt.SetInt(0); // 0 means not from gcodeviewer
evt.SetEventObject(this);
wxPostEvent(this, evt);
} else {
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 907b9e619..7c3dfb536 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -446,6 +446,7 @@ public:
void on_filaments_delete(size_t extruders_count, size_t filament_id, int replace_filament_id = -1);
// BBS
void on_bed_type_change(BedType bed_type,bool is_gcode_file = false);
+
bool update_filament_colors_in_full_config();
void config_change_notification(const DynamicPrintConfig &config, const std::string& key);
void on_config_change(const DynamicPrintConfig &config);
diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp
index 73dc492a7..0c8e0d8cb 100644
--- a/src/slic3r/GUI/Preferences.cpp
+++ b/src/slic3r/GUI/Preferences.cpp
@@ -1242,6 +1242,10 @@ wxWindow* PreferencesDialog::create_general_page()
auto item_darkmode = create_item_darkmode_checkbox(_L("Enable dark mode"), page,_L("Enable dark mode"), 50, "dark_color_mode");
#endif
+ auto title_filament_group = create_item_title(_L("Filament Group"), page, _L("Filament Group"));
+ auto item_ignore_ext_filament = create_item_checkbox(_L("Ignore ext filament when auto grouping."), page, _L("Ignore ext filament when auto grouping"), 50, "ignore_ext_filament_when_group");
+ auto item_pop_filament_group_mode = create_item_checkbox(_L("Pop up to select filament map mode."), page, _L("Pop up to select filament map mode"), 50, "pop_up_filament_map_mode");
+
auto title_user_experience = create_item_title(_L("User Experience"), page, _L("User Experience"));
auto item_priv_policy = create_item_checkbox(_L("Join Customer Experience Improvement Program."), page, "", 50, "privacyuse");
wxHyperlinkCtrl* hyperlink = new wxHyperlinkCtrl(page, wxID_ANY, _L("What data would be collected?"), "https://bambulab.com/en/policies/privacy");
@@ -1312,6 +1316,10 @@ wxWindow* PreferencesDialog::create_general_page()
sizer_page->Add(item_darkmode, 0, wxEXPAND, FromDIP(3));
#endif
+ sizer_page->Add(title_filament_group, 0, wxTOP | wxEXPAND, FromDIP(20));
+ sizer_page->Add(item_ignore_ext_filament, 0, wxEXPAND, FromDIP(3));
+ sizer_page->Add(item_pop_filament_group_mode, 0, wxEXPAND, FromDIP(3));
+
sizer_page->Add(title_user_experience, 0, wxTOP | wxEXPAND, FromDIP(20));
sizer_page->Add(item_priv_policy, 0, wxTOP, FromDIP(3));