Merge branch 'main' into feat/plugin-pages

This commit is contained in:
Ian Chua
2026-08-12 14:14:00 +08:00
committed by GitHub
339 changed files with 12281 additions and 1796 deletions

View File

@@ -23,14 +23,14 @@ inline coord_t meshfix_maximum_extrusion_area_deviation() { return scaled<coo
class WallToolPathsParams
{
public:
float min_bead_width;
float min_feature_size;
float min_length_factor;
float wall_transition_length;
float wall_transition_angle;
float wall_transition_filter_deviation;
int wall_distribution_count;
bool is_top_or_bottom_layer;
float min_bead_width = 0.f;
float min_feature_size = 0.f;
float min_length_factor = 0.5f;
float wall_transition_length = 0.f;
float wall_transition_angle = 10.f;
float wall_transition_filter_deviation = 0.f;
int wall_distribution_count = 1;
bool is_top_or_bottom_layer = false;
coord_t wall_maximum_resolution = meshfix_maximum_resolution();
coord_t wall_maximum_deviation = meshfix_maximum_deviation();

View File

@@ -4,6 +4,7 @@
#include "GUI_App.hpp"
#include "libslic3r/Preset.hpp"
#include "I18N.hpp"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <wx/colordlg.h>
#include <wx/dcgraph.h>
@@ -1075,54 +1076,105 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
// Sort the filaments
{
static std::unordered_map<wxString, int> sorted_names
{ {"Bambu PLA Basic", 0},
{"Bambu PLA Matte", 1},
{"Bambu PETG HF", 2},
{"Bambu ABS", 3},
{"Bambu PLA Silk", 4},
{"Bambu PLA-CF" , 5},
{"Bambu PLA Galaxy", 6},
{"Bambu PLA Metal", 7},
{"Bambu PLA Marble", 8},
{"Bambu PETG-CF", 9},
{"Bambu PETG Translucent", 10},
{"Bambu ABS-GF", 11}
std::unordered_map<wxString, int> selected_filament_ranks;
// Helper lambda to find a filament Preset by name. We can call this multiple times to walk the inheritance chain and find the base filament.
auto find_filament_by_name = [](const std::string& wanted, const PresetCollection& filaments) -> const Preset* {
for (auto it = filaments.begin(); it != filaments.end(); ++it) {
if (it->name == wanted) {
return &(*it);
}
}
return nullptr;
};
static std::vector<wxString> sorted_vendors { "Bambu Lab", "Generic" };
static std::vector<wxString> sorted_types { "PLA", "PETG", "ABS", "TPU" };
auto _filament_sorter = [&query_filament_vendors, &query_filament_types](const wxString& left, const wxString& right) -> bool
{
{ // Compare name order
const auto& iter1 = sorted_names.find(left);
int name_order1 = (iter1 != sorted_names.end()) ? iter1->second : INT_MAX;
// For each active filament preset, find its base filament alias and promote it in extruder order.
auto bundle = wxGetApp().preset_bundle;
const auto& preset_names = bundle->filament_presets;
for (size_t i = preset_names.size(); i-- > 0; ) {
std::string wanted = preset_names[i];
const int sort_rank = -static_cast<int>(preset_names.size() - i);
const Preset* match = nullptr;
const auto& iter2 = sorted_names.find(right);
int name_order2 = (iter2 != sorted_names.end()) ? iter2->second : INT_MAX;
if (name_order1 != name_order2)
do {
auto find_result = find_filament_by_name(wanted, bundle->filaments);
if (!find_result) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " No available filament name matches " << wanted;
break;
}
match = find_result;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Found available filament matching current preset name " << wanted
<< " - Name: " << match->name << " - Alias: " << match->alias
<< " - Inherits: " << match->inherits();
if (match->inherits().length() == 0) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " No more inherits so we reached the base filament";
break;
}
wanted = match->inherits();
} while (1); // Or loop while (match->alias.length() == 0) because existence of alias and inherits on a Preset seem to be exclusive
if (!match) {
continue;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Update filament rank to " + std::to_string(sort_rank) + " for preset Name: "
<< match->name << " - Alias: " << match->alias;
selected_filament_ranks.insert_or_assign(match->alias, sort_rank);
}
static const std::vector<wxString> sorted_vendors { "Generic" };
static const std::vector<wxString> sorted_types { "PLA", "PETG", "ABS", "TPU" };
auto priority_rank = [](const std::vector<wxString>& priorities, const wxString& value) {
const auto iter = std::find_if(priorities.begin(), priorities.end(), [&value](const wxString& priority) {
return priority.CmpNoCase(value) == 0;
});
return iter - priorities.begin();
};
auto _filament_sorter = [&query_filament_vendors, &query_filament_types, &selected_filament_ranks, &priority_rank](const wxString& left, const wxString& right) -> bool
{
{ // Compare selected filament order
const auto& iter1 = selected_filament_ranks.find(left);
int selected_order1 = (iter1 != selected_filament_ranks.end()) ? iter1->second : INT_MAX;
const auto& iter2 = selected_filament_ranks.find(right);
int selected_order2 = (iter2 != selected_filament_ranks.end()) ? iter2->second : INT_MAX;
if (selected_order1 != selected_order2)
{
return name_order1 < name_order2;
return selected_order1 < selected_order2;
}
}
{ // Compare vendor
auto iter1 = std::find(sorted_vendors.begin(), sorted_vendors.end(), query_filament_vendors[left]);
auto iter2 = std::find(sorted_vendors.begin(), sorted_vendors.end(), query_filament_vendors[right]);
if (iter1 != iter2)
{
return iter1 < iter2;
};
const wxString& vendor1 = query_filament_vendors.at(left);
const wxString& vendor2 = query_filament_vendors.at(right);
const auto rank1 = priority_rank(sorted_vendors, vendor1);
const auto rank2 = priority_rank(sorted_vendors, vendor2);
if (rank1 != rank2)
return rank1 < rank2;
const int vendor_compare = vendor1.CmpNoCase(vendor2);
if (vendor_compare != 0)
return vendor_compare < 0;
}
{ // Compare type
auto iter1 = std::find(sorted_types.begin(), sorted_types.end(), query_filament_types[left]);
auto iter2 = std::find(sorted_types.begin(), sorted_types.end(), query_filament_types[right]);
if (iter1 != iter2)
{
return iter1 < iter2;
}
const wxString& type1 = query_filament_types.at(left);
const wxString& type2 = query_filament_types.at(right);
const auto rank1 = priority_rank(sorted_types, type1);
const auto rank2 = priority_rank(sorted_types, type2);
if (rank1 != rank2)
return rank1 < rank2;
const int type_compare = type1.CmpNoCase(type2);
if (type_compare != 0)
return type_compare < 0;
}
return left < right;
const int name_compare = left.CmpNoCase(right);
return name_compare != 0 ? name_compare < 0 : left < right;
};
std::sort(filament_items.begin(), filament_items.end(), _filament_sorter);

View File

@@ -12,6 +12,7 @@
#include "libslic3r/GCode/AdaptivePAProcessor.hpp"
#include "Plater.hpp"
#include <algorithm>
#include <sstream>
#include <wx/msgdlg.h>
@@ -250,6 +251,59 @@ void ConfigManipulation::check_chamber_minimal_temperature(DynamicPrintConfig* c
}
}
void ConfigManipulation::layer_height_limits(double& min_layer_height, double& max_layer_height) const
{
const DynamicPrintConfig& printer_config = GUI::wxGetApp().preset_bundle->printers.get_edited_preset().config;
const std::vector<double>& min_limits = printer_config.option<ConfigOptionFloats>("min_layer_height")->values;
const std::vector<double>& max_limits = printer_config.option<ConfigOptionFloats>("max_layer_height")->values;
min_layer_height = *std::min_element(min_limits.begin(), min_limits.end());
max_layer_height = *std::max_element(max_limits.begin(), max_limits.end());
}
bool ConfigManipulation::check_layer_height(DynamicPrintConfig* config)
{
double min_layer_height = 0., max_layer_height = 0.;
layer_height_limits(min_layer_height, max_layer_height);
const double layer_height = config->opt_float("layer_height");
if (min_layer_height > EPSILON && layer_height < EPSILON) {
const wxString msg_text = wxString::Format(_L("Layer height is too small. It will be set to the minimum (%g mm)."), min_layer_height);
MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxOK);
dialog.SetButtonLabel(wxID_OK, _L("OK"));
is_msg_dlg_already_exist = true;
dialog.ShowModal();
is_msg_dlg_already_exist = false;
DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("layer_height", new ConfigOptionFloat(min_layer_height));
apply(config, &new_conf);
return true;
}
if (max_layer_height > EPSILON && layer_height > max_layer_height + EPSILON)
return layer_height_out_of_range_dialog(config, max_layer_height);
if (min_layer_height > EPSILON && layer_height < min_layer_height - EPSILON)
return layer_height_out_of_range_dialog(config, min_layer_height);
return false;
}
bool ConfigManipulation::layer_height_out_of_range_dialog(DynamicPrintConfig* config, double clamp_to)
{
wxString msg_text = _(L("Layer height is outside the limits set in Printer Settings -> Extruder -> Layer height limits, "
"this may cause printing quality issues."));
msg_text += "\n\n" + wxString::Format(_L("Adjust it to the limit (%g mm) automatically?"), clamp_to);
MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO);
dialog.SetButtonLabel(wxID_YES, _L("Adjust"));
dialog.SetButtonLabel(wxID_NO, _L("Ignore"));
is_msg_dlg_already_exist = true;
const bool adjust = dialog.ShowModal() == wxID_YES;
if (adjust) {
DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("layer_height", new ConfigOptionFloat(clamp_to));
apply(config, &new_conf);
}
is_msg_dlg_already_exist = false;
return adjust;
}
void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config, const bool is_plate_config)
{
// #ys_FIXME_to_delete
@@ -264,7 +318,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
// layer_height shouldn't be equal to zero
auto layer_height = config->opt_float("layer_height");
auto gpreset = GUI::wxGetApp().preset_bundle->printers.get_edited_preset();
if (layer_height < EPSILON)
{
const wxString msg_text = _(L("Layer height too small\nIt has been reset to 0.2"));
@@ -277,20 +330,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
is_msg_dlg_already_exist = false;
}
//BBS: limite the max layer_herght
auto max_lh = gpreset.config.opt_float("max_layer_height",0);
if (max_lh > 0.2 && layer_height > max_lh+ EPSILON)
{
const wxString msg_text = wxString::Format(L"Too large layer height.\nReset to %0.3f.", max_lh);
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *config;
is_msg_dlg_already_exist = true;
dialog.ShowModal();
new_conf.set_key_value("layer_height", new ConfigOptionFloat(max_lh));
apply(config, &new_conf);
is_msg_dlg_already_exist = false;
}
//BBS: ironing_spacing shouldn't be too small or equal to zero
if (config->opt_float("ironing_spacing") < 0.05)
{

View File

@@ -86,6 +86,9 @@ public:
void check_filament_max_volumetric_speed(DynamicPrintConfig *config);
void check_chamber_temperature(DynamicPrintConfig* config);
void check_chamber_minimal_temperature(DynamicPrintConfig* config);
bool check_layer_height(DynamicPrintConfig* config);
bool layer_height_out_of_range_dialog(DynamicPrintConfig* config, double clamp_to);
void layer_height_limits(double& min_layer_height, double& max_layer_height) const;
void set_is_BBL_Printer(bool is_bbl_printer) { is_BBL_Printer = is_bbl_printer; };
bool get_is_BBL_Printer() { return is_BBL_Printer; };
// SLA print

View File

@@ -6977,7 +6977,7 @@ void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) {
else
m_sel_plate_toolbar.show_stats_item = false;
if (force_selected && m_sel_plate_toolbar.show_stats_item)
if (force_selected && m_sel_plate_toolbar.show_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item)
m_sel_plate_toolbar.m_all_plates_stats_item->selected = true;
}

View File

@@ -139,7 +139,7 @@ bool ObjectSettings::update_settings_list()
optgroup->sidetext_width = 5;
optgroup->m_on_change = [this, config](const t_config_option_key& opt_id, const boost::any& value) {
this->update_config_values(config);
this->update_config_values(config, opt_id);
wxGetApp().obj_list()->changed_object(); };
// call back for rescaling of the extracolumn control
@@ -325,7 +325,7 @@ bool ObjectSettings::add_missed_options(ModelConfig* config_to, const DynamicPri
return is_added;
}
void ObjectSettings::update_config_values(ModelConfig* config)
void ObjectSettings::update_config_values(ModelConfig* config, const std::string& changed_opt_key)
{
const auto objects_model = wxGetApp().obj_list()->GetModel();
const auto item = wxGetApp().obj_list()->GetSelection();
@@ -403,6 +403,10 @@ void ObjectSettings::update_config_values(ModelConfig* config)
}
main_config.apply(config->get(), true);
if (printer_technology == ptFFF && changed_opt_key == "layer_height")
config_manipulation.check_layer_height(&main_config);
printer_technology == ptFFF ? config_manipulation.update_print_fff_config(&main_config) :
config_manipulation.update_print_sla_config(&main_config) ;

View File

@@ -66,7 +66,7 @@ public:
* we should add sparse_infill_pattern to avoid endless loop in update
*/
bool add_missed_options(ModelConfig *config_to, const DynamicPrintConfig &config_from);
void update_config_values(ModelConfig *config);
void update_config_values(ModelConfig *config, const std::string& changed_opt_key = "");
void UpdateAndShow(const bool show);
void msw_rescale();
void sys_color_changed();

View File

@@ -223,7 +223,7 @@ bool ObjectTableSettings::update_settings_list(bool is_object, bool is_multiple_
std::weak_ptr<ConfigOptionsGroup> weak_optgroup(optgroup);
optgroup->m_on_change = [this, is_object, object, config, group_category](const t_config_option_key &opt_id, const boost::any &value) {
this->m_parent->Freeze();
this->update_config_values(is_object, object, config, group_category);
this->update_config_values(is_object, object, config, group_category, opt_id);
wxGetApp().obj_list()->changed_object();
this->m_parent->Thaw();
//update_extra_column_visible_status(optgroup.get(), cat.second, config);
@@ -369,7 +369,7 @@ int ObjectTableSettings::update_extra_column_visible_status(ConfigOptionsGroup*
return count;
}
void ObjectTableSettings::update_config_values(bool is_object, ModelObject* object, ModelConfig* config, const std::string& category)
void ObjectTableSettings::update_config_values(bool is_object, ModelObject* object, ModelConfig* config, const std::string& category, const std::string& changed_opt_key)
{
int different_count = 0;
const auto printer_technology = wxGetApp().plater()->printer_technology();
@@ -403,6 +403,9 @@ void ObjectTableSettings::update_config_values(bool is_object, ModelObject* obje
config_manipulation.set_is_BBL_Printer(wxGetApp().preset_bundle->is_bbl_vendor());
if (printer_technology == ptFFF && changed_opt_key == "layer_height")
config_manipulation.check_layer_height(&main_config);
printer_technology == ptFFF ? config_manipulation.update_print_fff_config(&main_config) :
config_manipulation.update_print_sla_config(&main_config) ;

View File

@@ -70,7 +70,7 @@ public:
bool add_missed_options(ModelConfig *config_to, const DynamicPrintConfig &config_from);
//return visible count
int update_extra_column_visible_status(ConfigOptionsGroup* option_group, const std::vector<SimpleSettingData>& option_keys, ModelConfig* config);
void update_config_values(bool is_object, ModelObject* object, ModelConfig* config, const std::string& category);
void update_config_values(bool is_object, ModelObject* object, ModelConfig* config, const std::string& category, const std::string& changed_opt_key = "");
void UpdateAndShow(int row, const bool show, bool is_object, bool is_multiple_selection, ModelObject* object, ModelConfig* config, const std::string& category);
void ValueChanged(int row, bool is_object, ModelObject* object, ModelConfig* config, const std::string& category, const std::string& key);
void resetAllValues(int row, bool is_object, ModelObject* object, ModelConfig* config, const std::string& category);

View File

@@ -2809,12 +2809,26 @@ void ImGuiWrapper::init_font(bool compress)
}
}
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
ImFontConfig fallback_cfg = cfg;
fallback_cfg.MergeMode = true;
static constexpr ImWchar celsius_range[] = { 0x2103, 0x2103, 0 };
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &fallback_cfg, celsius_range);
}
bold_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + font_name_bold).c_str(), m_font_size, &cfg, ranges.Data);
if (bold_font == nullptr) {
bold_font = io.Fonts->AddFontDefault();
if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); }
}
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
ImFontConfig fallback_cfg = cfg;
fallback_cfg.MergeMode = true;
static constexpr ImWchar celsius_range[] = { 0x2103, 0x2103, 0 };
io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/HarmonyOS_Sans_SC_Bold.ttf").c_str(), m_font_size, &fallback_cfg, celsius_range);
}
if (m_glyph_ranges == ImGui::GetIO().Fonts->GetGlyphRangesThai()) {
default_font->Scale *= 1.25f;
bold_font->Scale *= 1.25f;

View File

@@ -45,24 +45,26 @@ void CreateFontStyleImagesJob::process(Ctl &ctl)
for (const ExPolygon &shape : shapes)
bounding_box.merge(BoundingBox(shape.contour.points));
for (ExPolygon &shape : shapes) shape.translate(-bounding_box.min);
// calculate conversion from FontPoint to screen pixels by size of font
double scale = get_text_shape_scale(item.prop, *item.font.font_file) * m_input.ppm;
scales[index] = scale;
//double scale = font_prop.size_in_mm * SCALING_FACTOR;
BoundingBoxf bb2(bounding_box.min.cast<double>(),
bounding_box.max.cast<double>());
if (bounding_box.size().x() < 1 || bounding_box.size().y() < 1)
continue; // or however the font job's degenerate-box case is handled
// Normalize to fit max_size, exactly like CreateFontImageJob does against m_input.size.
// Fit by height (matches row height), then clamp width if needed.
constexpr float preview_padding_px = 2.f; // margin for AA sampling, tune to your AA kernel radius
double scale = m_input.max_size.y() / (double) bounding_box.size().y();
BoundingBoxf bb2(bounding_box.min.cast<double>(), bounding_box.max.cast<double>());
bb2.scale(scale);
image.tex_size.x = std::ceil(bb2.max.x() - bb2.min.x());
image.tex_size.y = std::ceil(bb2.max.y() - bb2.min.y());
// crop image width
if (image.tex_size.x > m_input.max_size.x())
// crop width only if the (now height-normalized) text is too wide
image.tex_size.x = std::ceil(bb2.max.x() - bb2.min.x()) + 2 * preview_padding_px;
image.tex_size.y = std::ceil(bb2.max.y() - bb2.min.y()) + 2 * preview_padding_px;
if (image.tex_size.x > m_input.max_size.x())
image.tex_size.x = m_input.max_size.x();
// crop image height
if (image.tex_size.y > m_input.max_size.y())
image.tex_size.y = m_input.max_size.y();
scales[index] = scale;
}
// arrange bounding boxes

View File

@@ -111,18 +111,20 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
sizer->Add(m_radio_group, 0, wxEXPAND | wxTOP | wxLEFT, BORDER_W);
std::string inherits_str = sel_preset.inherits();
if (parent->m_mode == comDevelop && !inherits_str.empty()) {
if (parent->m_mode == comDevelop) {
// A new user copy of a system preset inherits from the selected system preset.
const std::string parent_name = sel_preset.is_system ? sel_preset.name : sel_preset.inherits();
const bool can_detach = !parent_name.empty();
wxBoxSizer *detach_sizer = new wxBoxSizer(wxHORIZONTAL);
auto detach_tooltip = _L("Copies all inherited values from the parent preset into this preset and removes the connection with the parent preset.");
auto detach_tooltip = _L("Copies all inherited values from the parent into this preset and removes the parent relationship. Presets compatible only with the parent may become unsupported.");
auto detach_checkbox = new ::CheckBox(parent);
detach_checkbox->SetToolTip(detach_tooltip);
auto detach_label = new wxStaticText(parent, wxID_ANY, _L("Detach from parent"));
detach_label->SetFont(::Label::Body_14);
detach_label->SetForegroundColour(wxColour("#363636"));
detach_label->SetToolTip(detach_tooltip);
detach_sizer->Add(detach_checkbox, 0, wxALIGN_LEFT | wxLEFT, BORDER_W);
@@ -130,27 +132,36 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
sizer->Add(detach_sizer, 0, wxEXPAND | wxTOP, BORDER_W);
sizer->AddSpacer(FromDIP(5));
auto parent_label = new wxStaticText(parent, wxID_ANY, inherits_str);
const wxString parent_text = can_detach ? from_u8(parent_name) : _L("Unique preset");
auto parent_label = new wxStaticText(parent, wxID_ANY, parent_text);
parent_label->SetFont(::Label::Body_12);
parent_label->SetForegroundColour(wxColour("#6B6B6B"));
parent_label->SetToolTip(_L("Parent preset"));
parent_label->SetToolTip(can_detach ? _L("Parent preset") : _L("This preset does not inherit from another preset."));
sizer->Add(parent_label, 0, wxEXPAND | wxLEFT, BORDER_W + FromDIP(24));
sizer->AddSpacer(FromDIP(5));
// Set initial state (unchecked by default)
detach_checkbox->SetValue(m_detach);
// Bind the checkbox event to update the detach state for this item
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent&) { m_detach = detach_checkbox->GetValue(); });
if (!can_detach) {
detach_checkbox->Disable();
detach_label->SetForegroundColour(wxColour("#6B6B6B"));
}
else {
// Set initial state (unchecked by default)
detach_checkbox->SetValue(m_detach);
// Bind the checkbox event to update the detach state for this item
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent&) { m_detach = detach_checkbox->GetValue(); });
auto on_toggle = [this, detach_checkbox]() {
detach_checkbox->SetValue(!detach_checkbox->GetValue());
wxCommandEvent ev(wxEVT_TOGGLEBUTTON, detach_checkbox->GetId());
ev.SetEventObject(detach_checkbox);
detach_checkbox->GetEventHandler()->ProcessEvent(ev);
};
detach_label->Bind(wxEVT_LEFT_DOWN, [on_toggle](wxMouseEvent& e) {if(!e.LeftDClick()) on_toggle();});
detach_label->Bind(wxEVT_LEFT_DCLICK, [on_toggle](wxMouseEvent& e) {on_toggle();});
detach_label->SetForegroundColour(wxColour("#363636"));
auto on_toggle = [this, detach_checkbox]() {
detach_checkbox->SetValue(!detach_checkbox->GetValue());
wxCommandEvent ev(wxEVT_TOGGLEBUTTON, detach_checkbox->GetId());
ev.SetEventObject(detach_checkbox);
detach_checkbox->GetEventHandler()->ProcessEvent(ev);
};
detach_label->Bind(wxEVT_LEFT_DOWN, [on_toggle](wxMouseEvent& e) {if(!e.LeftDClick()) on_toggle();});
detach_label->Bind(wxEVT_LEFT_DCLICK, [on_toggle](wxMouseEvent& e) {on_toggle();});
}
}
m_radio_group->Bind(wxEVT_COMMAND_RADIOBOX_SELECTED, [this](wxCommandEvent &e) {

View File

@@ -2136,43 +2136,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
m_last_sparse_infill_rotate_template_value = m_config->opt_string("sparse_infill_rotate_template");
}
if(opt_key=="layer_height"){
auto min_layer_height_from_nozzle=m_preset_bundle->full_config().option<ConfigOptionFloats>("min_layer_height")->values;
auto max_layer_height_from_nozzle=m_preset_bundle->full_config().option<ConfigOptionFloats>("max_layer_height")->values;
auto layer_height_floor = *std::min_element(min_layer_height_from_nozzle.begin(), min_layer_height_from_nozzle.end());
auto layer_height_ceil = *std::max_element(max_layer_height_from_nozzle.begin(), max_layer_height_from_nozzle.end());
const auto lh = m_config->opt_float("layer_height");
bool exceed_minimum_flag = lh < layer_height_floor;
bool exceed_maximum_flag = lh > layer_height_ceil;
if (exceed_maximum_flag || exceed_minimum_flag) {
if (lh < EPSILON) {
auto msg_text = _(L("Layer height is too small.\nIt will set to min_layer_height\n"));
MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxOK);
dialog.SetButtonLabel(wxID_OK, _L("OK"));
dialog.ShowModal();
auto new_conf = *m_config;
new_conf.set_key_value("layer_height", new ConfigOptionFloat(layer_height_floor));
m_config_manipulation.apply(m_config, &new_conf);
} else {
wxString msg_text = _(L("Layer height exceeds the limit in Printer Settings -> Extruder -> Layer height limits, "
"this may cause printing quality issues."));
msg_text += "\n\n" + _(L("Adjust to the set range automatically?\n"));
MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO);
dialog.SetButtonLabel(wxID_YES, _L("Adjust"));
dialog.SetButtonLabel(wxID_NO, _L("Ignore"));
auto answer = dialog.ShowModal();
auto new_conf = *m_config;
if (answer == wxID_YES) {
if (exceed_maximum_flag)
new_conf.set_key_value("layer_height", new ConfigOptionFloat(layer_height_ceil));
if (exceed_minimum_flag)
new_conf.set_key_value("layer_height", new ConfigOptionFloat(layer_height_floor));
m_config_manipulation.apply(m_config, &new_conf);
}
}
if (opt_key == "layer_height") {
if (m_config_manipulation.check_layer_height(m_config))
wxGetApp().plater()->update();
}
}
string opt_key_without_idx = opt_key.substr(0, opt_key.find('#'));