Skip to content
1 change: 1 addition & 0 deletions localization/i18n/list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ src/slic3r/GUI/CaliHistoryDialog.cpp
src/slic3r/GUI/BonjourDialog.cpp
src/slic3r/GUI/calib_dlg.cpp
src/slic3r/GUI/PrintHostDialogs.cpp
src/slic3r/GUI/ThirdPartyFilamentMapPanel.cpp
src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp
src/slic3r/GUI/NetworkTestDialog.cpp
src/slic3r/GUI/CreatePresetsDialog.cpp
Expand Down
5 changes: 5 additions & 0 deletions src/slic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,10 @@ set(SLIC3R_GUI_SOURCES
# Last on purpose: a new source in the middle of the list reshuffles the unity batches (HomeVaults.cpp
# and HomeVendors.cpp share file-local names and must not land in one batch).
GUI/FavoriteFilamentsUI.cpp
GUI/ThirdPartyFilamentMap.cpp
GUI/ThirdPartyFilamentMap.hpp
GUI/ThirdPartyFilamentMapPanel.cpp
GUI/ThirdPartyFilamentMapPanel.hpp
)

add_subdirectory(GUI/DeviceTab)
Expand Down Expand Up @@ -1281,6 +1285,7 @@ slic3r_unity_build(libslic3r_gui SKIP
GUI/Tab.cpp # ::CheckBox vs GUI::CheckBox (Field.hpp)
GUI/AMSMaterialsSetting.cpp # ::CheckBox members vs GUI::CheckBox (Field.hpp)
GUI/AmsMappingPopup.cpp # ::CheckBox members vs GUI::CheckBox (Field.hpp)
GUI/ThirdPartyFilamentMapPanel.cpp # includes AmsMappingPopup.hpp (::CheckBox vs GUI::CheckBox)
GUI/CalibrationWizardPage.cpp # ::CheckBox members vs GUI::CheckBox (Field.hpp)
GUI/ExtrusionCalibration.cpp # ::CheckBox members vs GUI::CheckBox (Field.hpp)
)
Expand Down
78 changes: 70 additions & 8 deletions src/slic3r/GUI/AmsMappingPopup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
#include "Widgets/ProgressDialog.hpp"
#include "Widgets/RoundedRectangle.hpp"
#include "Widgets/StaticBox.hpp"
#include "Widgets/StateColor.hpp"

#include <wx/progdlg.h>
#include <wx/clipbrd.h>
#include <wx/control.h>
#include <wx/dcgraph.h>
#include <wx/graphics.h>
#include <miniz.h>
Expand Down Expand Up @@ -69,6 +71,22 @@ void MaterialItem::set_ams_info(wxColour col, wxString txt, int ctype, std::vect
if (need_refresh) { Refresh();}
}

void MaterialItem::set_dropdown_visible(bool visible)
{
if (m_dropdown_visible == visible)
return;
m_dropdown_visible = visible;
Refresh();
}

void MaterialItem::set_nozzle_badge(const wxString &badge)
{
if (m_nozzle_badge == badge)
return;
m_nozzle_badge = badge;
Refresh();
}

void MaterialItem::disable()
{
if (IsEnabled()) {
Expand Down Expand Up @@ -160,8 +178,32 @@ void MaterialItem::render(wxDC &dc)
dc.SetFont(::Label::Body_10);
}

auto material_txt_size = dc.GetTextExtent(m_material_name);
dc.DrawText(m_material_name, wxPoint((MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2, (FromDIP(28) - material_txt_size.y) / 2));
wxString material_txt = m_material_name;
auto material_txt_size = dc.GetTextExtent(material_txt);
int name_x = (MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2;
wxSize badge_ts(0, 0);
int badge_w = 0;
int badge_h = 0;
if (!m_nozzle_badge.empty()) {
// Pill sized to Body_10 text: a fixed 12 DIP circle clips "10" and is shorter than the glyph.
dc.SetFont(::Label::Body_10);
badge_ts = dc.GetTextExtent(m_nozzle_badge);
const int pad = FromDIP(2);
badge_w = badge_ts.x + 2 * pad;
badge_h = badge_ts.y + 2 * pad;
const int name_x_pad = badge_w + FromDIP(4);
const int name_max_w = GetSize().x - name_x_pad - FromDIP(4);
dc.SetFont(::Label::Body_13);
if (dc.GetTextExtent(material_txt).x > GetSize().x - 10)
dc.SetFont(::Label::Body_10);
if (dc.GetTextExtent(material_txt).x > name_max_w) {
dc.SetFont(::Label::Body_10);
material_txt = wxControl::Ellipsize(material_txt, dc, wxELLIPSIZE_END, name_max_w);
}
material_txt_size = dc.GetTextExtent(material_txt);
name_x = std::max((MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2, name_x_pad);
}
dc.DrawText(material_txt, wxPoint(name_x, (FromDIP(28) - material_txt_size.y) / 2));

// mapping num
dc.SetFont(::Label::Body_10);
Expand All @@ -179,6 +221,24 @@ void MaterialItem::render(wxDC &dc)

auto mapping_txt_size = dc.GetTextExtent(mapping_txt);
dc.DrawText(mapping_txt, wxPoint((MATERIAL_ITEM_SIZE.x - mapping_txt_size.x) / 2, FromDIP(30) + (FromDIP(16) - mapping_txt_size.y) / 2));

if (!m_nozzle_badge.empty()) {
const wxPoint o(FromDIP(2), FromDIP(2));
const wxColour badge_bg = StateColor::darkModeColorFor(wxColour(0x26, 0x2E, 0x30));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(badge_bg));
dc.SetFont(::Label::Body_10);
if (badge_w <= 0 || badge_h <= 0) {
badge_ts = dc.GetTextExtent(m_nozzle_badge);
const int pad = FromDIP(2);
badge_w = badge_ts.x + 2 * pad;
badge_h = badge_ts.y + 2 * pad;
}
dc.DrawRoundedRectangle(o.x, o.y, badge_w, badge_h, std::min(badge_w, badge_h) / 2);
dc.SetTextForeground(badge_bg.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30));
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
dc.DrawText(m_nozzle_badge, o.x + (badge_w - badge_ts.x) / 2, o.y + (badge_h - badge_ts.y) / 2);
}
}

void MaterialItem::doRender(wxDC &dc)
Expand Down Expand Up @@ -273,12 +333,14 @@ void MaterialItem::doRender(wxDC &dc)
}
#endif
//arrow
if ( (acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) &&
(acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) {
dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_white.GetBmpSize().y);
}
else {
dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_gray.GetBmpSize().y);
if (m_dropdown_visible) {
if ( (acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) &&
(acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) {
dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_white.GetBmpSize().y);
}
else {
dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_gray.GetBmpSize().y);
}
}


Expand Down
5 changes: 5 additions & 0 deletions src/slic3r/GUI/AmsMappingPopup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,14 @@ class MaterialItem: public wxPanel

bool m_selected {false};
bool m_warning{false};
// Optional extras for ThirdPartyFilamentMapPanel. Defaults keep the Bambu send dialog unchanged.
bool m_dropdown_visible {true};
wxString m_nozzle_badge;

void msw_rescale();
void set_ams_info(wxColour col, wxString txt, int ctype=0, std::vector<wxColour> cols= std::vector<wxColour>());
void set_dropdown_visible(bool visible);
void set_nozzle_badge(const wxString &badge);

void disable();
void enable();
Expand Down
4 changes: 4 additions & 0 deletions src/slic3r/GUI/Plater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24464,6 +24464,7 @@ static std::vector<SendPlateFilament> plate_filaments_for_send(int plate_idx)
const ConfigOptionStrings* colours = bundle->project_config.option<ConfigOptionStrings>("filament_colour");
const ConfigOptionStrings* types = full.option<ConfigOptionStrings>("filament_type");
const ConfigOptionInts* temps = full.option<ConfigOptionInts>("nozzle_temperature");
const ConfigOptionInts* fil_map = bundle->project_config.option<ConfigOptionInts>("filament_map");
std::map<size_t, double> volumes;
if (plate && plate->is_slice_result_valid() && plate->get_slice_result())
for (const auto& kv : plate->get_slice_result()->print_statistics.total_volumes_per_extruder)
Expand All @@ -24474,6 +24475,9 @@ static std::vector<SendPlateFilament> plate_filaments_for_send(int plate_idx)
f.colour = (colours && i < colours->values.size()) ? colours->values[i] : std::string();
f.type = (types && i < types->values.size()) ? types->values[i] : std::string();
f.nozzle_temp = (temps && i < temps->values.size()) ? temps->values[i] : 0;
// filament_map is 1-based (SelectMachine / Bambu dual-nozzle). -1 when the plate is single-nozzle.
if (fil_map && i < fil_map->values.size() && fil_map->values[i] > 0)
f.nozzle_id = fil_map->values[i] - 1;
// The remembered CANVAS mapping keys on the preset as people know it: its alias, else its name.
if (const Preset* fp = bundle->filaments.find_preset(bundle->filament_presets[i]))
f.alias = fp->alias.empty() ? fp->name : fp->alias;
Expand Down
Loading
Loading