Merge branch 'master-remote' into SoftFever

# Conflicts:
#	bbl/i18n/BambuStudio.pot
#	bbl/i18n/de/BambuStudio_de.po
#	bbl/i18n/en/BambuStudio_en.po
#	bbl/i18n/es/BambuStudio_es.po
#	bbl/i18n/fr/BambuStudio_fr.po
#	bbl/i18n/hu/BambuStudio_hu.po
#	bbl/i18n/nl/BambuStudio_nl.po
#	bbl/i18n/sv/BambuStudio_sv.po
#	bbl/i18n/zh_cn/BambuStudio_zh_CN.po
#	resources/i18n/de/BambuStudio.mo
#	resources/i18n/en/BambuStudio.mo
#	resources/i18n/es/BambuStudio.mo
#	resources/i18n/fr/BambuStudio.mo
#	resources/i18n/hu/BambuStudio.mo
#	resources/i18n/nl/BambuStudio.mo
#	resources/i18n/sv/BambuStudio.mo
#	resources/i18n/zh_cn/BambuStudio.mo
#	resources/profiles/BBL.json
#	resources/profiles/Creality.json
#	resources/profiles/Voron.json
#	src/libslic3r/PrintConfig.cpp
#	src/libslic3r/TreeSupport.cpp
#	src/slic3r/GUI/DeviceManager.cpp
#	src/slic3r/GUI/ReleaseNote.cpp
#	version.inc
This commit is contained in:
SoftFever 2022-12-31 15:15:58 +08:00
commit 260156648d
104 changed files with 12137 additions and 1384 deletions

View file

@ -64,7 +64,7 @@ void AMSMaterialsSetting::create()
m_clrData->SetChooseFull(true);
m_clrData->SetChooseAlpha(false);
m_clr_picker = new Button(this, "", "");
m_clr_picker = new Button(this, wxEmptyString, wxEmptyString, wxBU_AUTODRAW);
m_clr_picker->SetCanFocus(false);
m_clr_picker->SetSize(FromDIP(50), FromDIP(25));
m_clr_picker->SetMinSize(wxSize(FromDIP(50), FromDIP(25)));
@ -364,7 +364,12 @@ void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
show_flag = true;
if (clr_dialog->ShowModal() == wxID_OK) {
m_clrData = &(clr_dialog->GetColourData());
m_clr_picker->SetBackgroundColor(m_clrData->GetColour());
m_clr_picker->SetBackgroundColor(wxColour(
m_clrData->GetColour().Red(),
m_clrData->GetColour().Green(),
m_clrData->GetColour().Blue(),
254
));
}
}
@ -374,13 +379,19 @@ bool AMSMaterialsSetting::Show(bool show)
m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
m_clr_picker->SetBackgroundColour(m_clr_picker->GetParent()->GetBackgroundColour());
}
return DPIDialog::Show(show);
}
void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max)
{
m_clr_picker->SetBackgroundColor(m_clrData->GetColour());
m_clr_picker->SetBackgroundColor(wxColour(
m_clrData->GetColour().Red(),
m_clrData->GetColour().Green(),
m_clrData->GetColour().Blue(),
254
));
if (!m_is_third) {
m_button_confirm->Hide();

View file

@ -83,7 +83,7 @@ protected:
Button * m_button_confirm;
wxStaticText* m_tip_readonly;
Button * m_button_close;
Button * m_clr_picker;
Button * m_clr_picker;
wxColourData * m_clrData;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament_mac;

View file

@ -200,6 +200,11 @@ void AMSSetting::create()
m_panel_img->Layout();
m_sizer_img->Fit(m_panel_img);
m_sizer_remain_block = new wxBoxSizer(wxVERTICAL);
m_sizer_remain_block->Add(m_sizer_remain, 0, wxEXPAND | wxTOP, FromDIP(8));
m_sizer_remain_block->Add(0, 0, 0, wxTOP, 8);
m_sizer_remain_block->Add(m_sizer_remain_tip, 0, wxLEFT, 18);
m_sizer_remain_block->Add(0, 0, 0, wxTOP, 15);
m_sizerl_body->Add(m_sizer_Insert_material, 0, wxEXPAND, 0);
m_sizerl_body->Add(0, 0, 0, wxTOP, 8);
@ -209,10 +214,7 @@ void AMSSetting::create()
m_sizerl_body->Add(0, 0, 0, wxTOP, 8);
m_sizerl_body->Add(m_sizer_starting_tip, 0, wxLEFT, 18);
m_sizerl_body->Add(0, 0, 0, wxTOP, 15);
m_sizerl_body->Add(m_sizer_remain, 0, wxEXPAND | wxTOP, FromDIP(8));
m_sizerl_body->Add(0, 0, 0, wxTOP, 8);
m_sizerl_body->Add(m_sizer_remain_tip, 0, wxLEFT, 18);
m_sizerl_body->Add(0, 0, 0, wxTOP, 15);
m_sizerl_body->Add(m_sizer_remain_block, 0, wxEXPAND, 0);
m_sizerl_body->Add(m_sizer_switch_filament, 0, wxEXPAND | wxTOP, FromDIP(8));
m_sizerl_body->Add(0, 0, 0, wxTOP, 8);
m_sizerl_body->Add(m_sizer_switch_filament_tip, 0, wxLEFT, 18);
@ -231,6 +233,17 @@ void AMSSetting::create()
this->Centre(wxBOTH);
wxGetApp().UpdateDlgDarkUI(this);
Bind(wxEVT_SHOW, [this](auto& e) {
if (this->IsShown()) {
if (ams_support_remain) {
m_sizer_remain_block->Show(true);
}
else {
m_sizer_remain_block->Show(false);
}
}
});
}
void AMSSetting::update_insert_material_read_mode(bool selected)

View file

@ -39,6 +39,7 @@ public:
wxString append_title(wxString text);
wxStaticText *append_text(wxString text);
MachineObject *obj{nullptr};
bool ams_support_remain{false};
int ams_id { 0 };
protected:
@ -72,6 +73,7 @@ protected:
wxBoxSizer *m_sizer_starting_tip_inline;
wxBoxSizer *m_sizer_remain_inline;
wxBoxSizer *m_sizer_switch_filament_inline;
wxBoxSizer *m_sizer_remain_block;
};
}} // namespace Slic3r::GUI

View file

@ -250,7 +250,7 @@ AboutDialog::AboutDialog()
#endif
version_font.SetPointSize(FromDIP(16));
version->SetFont(version_font);
version->SetForegroundColour(wxColour("#FFFFFE"));
version->SetForegroundColour(wxColour("#FFFFFD"));
version->SetBackgroundColour(wxColour("#00AF42"));
vesizer->Add(version, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));

View file

@ -456,7 +456,9 @@ void AuFile::on_set_cover()
{
if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>(); }
wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString();
fs::path path(into_path(m_file_name));
wxGetApp().plater()->model().model_info->cover_file = path.string();
//wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString();
auto full_path = m_file_path.branch_path();
auto full_root_path = full_path.branch_path();
@ -696,7 +698,8 @@ void AuFolderPanel::update_cover()
if (wxGetApp().plater()->model().model_info != nullptr) {
for (auto i = 0; i < m_aufiles_list.GetCount(); i++) {
AuFiles *aufile = m_aufiles_list[i];
if (wxGetApp().plater()->model().model_info->cover_file == aufile->file->m_file_name) {
if (wxString::FromUTF8(wxGetApp().plater()->model().model_info->cover_file) == aufile->file->m_file_name) {
aufile->file->set_cover(true);
} else {
aufile->file->set_cover(false);

View file

@ -257,17 +257,23 @@ void CameraPopup::check_func_supported()
allow_alter_resolution = (m_obj->is_function_supported(PrinterFunction::FUNC_ALTER_RESOLUTION) && m_obj->has_ipcam);
//check u2 version
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
MachineObject* obj = dev->get_selected_machine();
if (!obj) return;
//resolution supported
std::vector<std::string> resolution_supported = m_obj->get_resolution_supported();
auto support_count = resolution_supported.size();
for (int i = 0; i < (int)RESOLUTION_OPTIONS_NUM; ++i){
auto curr_res = to_resolution_msg_string(CameraResolution(i));
std::vector <std::string> ::iterator it = std::find(resolution_supported.begin(), resolution_supported.end(), curr_res);
if ((it == resolution_supported.end())||(support_count <= 1))
if ((it == resolution_supported.end())||(support_count <= 1) || !obj->is_support_1080dpi)
m_resolution_options[i] -> Hide();
}
//hide resolution if there is only one choice
if (support_count <= 1) {
if (support_count <= 1 || !obj->is_support_1080dpi) {
m_text_resolution->Hide();
}
}

View file

@ -271,6 +271,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
}
double sparse_infill_density = config->option<ConfigOptionPercent>("sparse_infill_density")->value;
auto timelapse_type = config->opt_enum<TimelapseType>("timelapse_type");
if (config->opt_bool("spiral_mode") &&
! (config->opt_int("wall_loops") == 1 &&
@ -279,12 +280,12 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
! config->opt_bool("enable_support") &&
config->opt_int("enforce_support_layers") == 0 &&
config->opt_bool("ensure_vertical_shell_thickness") &&
! config->opt_bool("detect_thin_wall")))
! config->opt_bool("detect_thin_wall") &&
config->opt_enum<TimelapseType>("timelapse_type") == TimelapseType::tlTraditional))
{
wxString msg_text = _(L("Spiral mode only works when wall loops is 1, \n"
"support is disabled, top shell layers is 0 and sparse infill density is 0\n"));
wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional"));
if (is_global_config)
msg_text += "\n" + _(L("Change these settings automatically? \n"
msg_text += "\n\n" + _(L("Change these settings automatically? \n"
"Yes - Change these settings and enable spiral mode automatically\n"
"No - Give up using spiral mode this time"));
MessageDialog dialog(m_msg_dlg_parent, msg_text, "",
@ -301,7 +302,9 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0));
new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(true));
new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false));
new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
sparse_infill_density = 0;
timelapse_type = TimelapseType::tlTraditional;
support = false;
}
else {
@ -310,6 +313,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
apply(config, &new_conf);
if (cb_value_change) {
cb_value_change("sparse_infill_density", sparse_infill_density);
cb_value_change("timelapse_type", timelapse_type);
if (!support)
cb_value_change("enable_support", false);
}
@ -574,19 +578,16 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"support_type", "support_on_build_plate_only", "support_critical_regions_only",
"support_object_xy_distance", "independent_support_layer_height"})
toggle_field(el, have_support_material);
toggle_field("support_threshold_angle", have_support_material && (support_type == stNormalAuto || support_type == stTreeAuto || support_type==stHybridAuto));
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter"})
toggle_field(el, config->opt_bool("enable_support") && (support_type == stTreeAuto || support_type == stTree || support_type == stHybridAuto));
toggle_field(el, support_is_tree);
// hide tree support settings when normal is selected
bool support_is_tree = std::set<SupportType>{stTreeAuto, stHybridAuto, stTree}.count(support_type) != 0;
toggle_line("tree_support_branch_distance", support_is_tree);
toggle_line("tree_support_branch_diameter", support_is_tree);
toggle_line("tree_support_branch_angle", support_is_tree);
toggle_line("tree_support_wall_count", support_is_tree);
toggle_line("max_bridge_length", support_is_tree);
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter", "max_bridge_length"})
toggle_line(el, support_is_tree);
// tree support use max_bridge_length instead of bridge_no_support
toggle_line("bridge_no_support", !support_is_tree);

View file

@ -1259,6 +1259,35 @@ bool MachineObject::is_recording()
return camera_recording;
}
void MachineObject::parse_version_func()
{
auto ota_version = module_vers.find("ota");
if (printer_type == "BL-P001" ||
printer_type == "BL-P002") {
if (ota_version != module_vers.end()) {
if (ota_version->second.sw_ver.compare("01.01.01.00") <= 0) {
ams_support_remain = false;
ams_support_auto_switch_filament_flag = false;
is_xcam_buildplate_supported = false;
xcam_support_recovery_step_loss = false;
is_support_send_to_sdcard = false;
is_support_1080dpi = false;
is_support_ai_monitoring = false;
is_support_ams_humidity = false;
} else {
ams_support_remain = true;
ams_support_auto_switch_filament_flag = true;
is_xcam_buildplate_supported = true;
xcam_support_recovery_step_loss = true;
is_support_send_to_sdcard = true;
is_support_1080dpi = true;
is_support_ai_monitoring = true;
is_support_ams_humidity = true;
}
}
}
}
int MachineObject::command_get_version(bool with_retry)
{
BOOST_LOG_TRIVIAL(info) << "command_get_version";
@ -1987,12 +2016,21 @@ bool MachineObject::is_function_supported(PrinterFunction func)
func_name = "FUNC_FIRSTLAYER_INSPECT";
break;
case FUNC_AI_MONITORING:
parse_version_func();
if (!is_support_ai_monitoring)
return false;
func_name = "FUNC_AI_MONITORING";
break;
case FUNC_BUILDPLATE_MARKER_DETECT:
parse_version_func();
if (!is_xcam_buildplate_supported)
return false;
func_name = "FUNC_BUILDPLATE_MARKER_DETECT";
break;
case FUNC_AUTO_RECOVERY_STEP_LOSS:
parse_version_func();
if (!xcam_support_recovery_step_loss)
return false;
func_name = "FUNC_AUTO_RECOVERY_STEP_LOSS";
break;
case FUNC_FLOW_CALIBRATION:
@ -2026,9 +2064,15 @@ bool MachineObject::is_function_supported(PrinterFunction func)
func_name = "FUNC_ALTER_RESOLUTION";
break;
case FUNC_SEND_TO_SDCARD:
parse_version_func();
if (!is_support_send_to_sdcard)
return false;
func_name = "FUNC_SEND_TO_SDCARD";
break;
case FUNC_AUTO_SWITCH_FILAMENT:
parse_version_func();
if (!ams_support_auto_switch_filament_flag)
return false;
func_name = "FUNC_AUTO_SWITCH_FILAMENT";
break;
case FUNC_VIRTUAL_CAMERA:
@ -2615,6 +2659,9 @@ int MachineObject::parse_json(std::string payload)
else {
if (jj["xcam"].contains("buildplate_marker_detector")) {
xcam_buildplate_marker_detector = jj["xcam"]["buildplate_marker_detector"].get<bool>();
is_xcam_buildplate_supported = true;
} else {
is_xcam_buildplate_supported = false;
}
}
}
@ -2874,6 +2921,8 @@ int MachineObject::parse_json(std::string payload)
}
if (tray_it->contains("remain")) {
curr_tray->remain = (*tray_it)["remain"].get<int>();
} else {
curr_tray->remain = -1;
}
try {
if (!ams_id.empty() && !curr_tray->id.empty()) {
@ -3021,6 +3070,7 @@ int MachineObject::parse_json(std::string payload)
ver_info.hw_ver = (*it)["hw_ver"].get<std::string>();
module_vers.emplace(ver_info.name, ver_info);
}
parse_version_func();
bool get_version_result = true;
if (j["info"].contains("result"))
if (j["info"]["result"].get<std::string>() == "fail")

View file

@ -423,8 +423,10 @@ public:
bool ams_insert_flag { false };
bool ams_power_on_flag { false };
bool ams_calibrate_remain_flag { false };
bool ams_support_auto_switch_filament_flag { true };
bool ams_auto_switch_filament_flag { false };
bool ams_support_use_ams { false };
bool ams_support_remain { true };
int ams_humidity;
int ams_user_setting_hold_count = 0;
AmsStatusMain ams_status_main;
@ -579,15 +581,23 @@ public:
bool xcam_ai_monitoring{ false };
int xcam_ai_monitoring_hold_count = 0;
std::string xcam_ai_monitoring_sensitivity;
bool is_xcam_buildplate_supported { true };
bool xcam_buildplate_marker_detector{ false };
int xcam_buildplate_marker_hold_count = 0;
bool xcam_support_recovery_step_loss { true };
bool xcam_auto_recovery_step_loss{ false };
int xcam_auto_recovery_hold_count = 0;
int ams_print_option_count = 0;
/*not support U2*/
bool is_support_1080dpi {false};
bool is_support_ai_monitoring {false};
bool is_support_ams_humidity {false};
/* sdcard */
MachineObject::SdcardState sdcard_state { NO_SDCARD };
MachineObject::SdcardState get_sdcard_state();
bool is_support_send_to_sdcard { true };
/* HMS */
std::vector<HMSItem> hms_list;
@ -622,6 +632,8 @@ public:
MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip);
~MachineObject();
void parse_version_func();
/* command commands */
int command_get_version(bool with_retry = true);
int command_request_push_all();

View file

@ -1249,7 +1249,7 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) {
m_is_dark = is_dark;
// Bed color
m_bed.on_change_color_mode(is_dark);
// GcodeViewer color
// GcodeViewer color
m_gcode_viewer.on_change_color_mode(is_dark);
// ImGui Style
wxGetApp().imgui()->on_change_color_mode(is_dark);
@ -3827,7 +3827,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
while (p->GetParent())
p = p->GetParent();
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
if (top_level_wnd && top_level_wnd->IsActive())
if (top_level_wnd && top_level_wnd->IsActive() && !wxGetApp().get_side_menu_popup_status())
m_canvas->SetFocus();
m_mouse.position = pos.cast<double>();
m_tooltip_enabled = false;
@ -4891,7 +4891,7 @@ void GLCanvas3D::update_sequential_clearance()
// the results are then cached for following displacements
if (m_sequential_print_clearance_first_displacement) {
m_sequential_print_clearance.m_hull_2d_cache.clear();
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_max_radius.value - EPSILON));
double mitter_limit = scale_(0.1);
m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
for (size_t i = 0; i < m_model->objects.size(); ++i) {
@ -5689,7 +5689,7 @@ void GLCanvas3D::_switch_toolbars_icon_filename()
m_assemble_view_toolbar.init(background_data);
m_separator_toolbar.init(background_data);
wxGetApp().plater()->get_collapse_toolbar().init(background_data);
// main toolbar
{
GLToolbarItem* item;

View file

@ -71,16 +71,16 @@ std::pair<bool, std::string> GLShadersManager::init()
// Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed
// triangle normals inside fragment shader have the right direction.
if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) {
//if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0))
valid &= append_shader("mm_gouraud", {"mm_gouraud_130.vs", "mm_gouraud_130.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
//if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled())
// valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
//else
// valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
}
else {
//if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0))
valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"});
//if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled())
// valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"});
//else
// valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"});
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"});
}
//BBS: add shader for outline

View file

@ -1892,6 +1892,9 @@ void GUI_App::init_app_config()
if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() )
dir = wxFileName::GetHomeDir() + wxS("/.config");
set_data_dir((dir + "/" + GetAppName()).ToUTF8().data());
boost::filesystem::path data_dir_path(data_dir());
if (!boost::filesystem::exists(data_dir_path))
boost::filesystem::create_directory(data_dir_path);
#endif
} else {
m_datadir_redefined = true;
@ -2492,11 +2495,14 @@ bool GUI_App::on_init_inner()
void GUI_App::copy_network_if_available()
{
if (app_config->get("update_network_plugin") != "true")
return;
std::string network_library, player_library, network_library_dst, player_library_dst;
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
auto plugin_folder = data_dir_path / "plugins";
auto cache_folder = data_dir_path / "ota";
std::string changelog_file = cache_folder.string() + "/network_plugins.json";
#if defined(_MSC_VER) || defined(_WIN32)
network_library = cache_folder.string() + "/bambu_networking.dll";
player_library = cache_folder.string() + "/BambuSource.dll";
@ -2545,6 +2551,9 @@ void GUI_App::copy_network_if_available()
fs::remove(player_library);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": Copying player library from" << player_library << " to " << player_library_dst<<" successfully.";
}
if (boost::filesystem::exists(changelog_file))
fs::remove(changelog_file);
app_config->set("update_network_plugin", "false");
}
bool GUI_App::on_init_network(bool try_backup)
@ -2905,6 +2914,16 @@ void GUI_App::set_label_clr_sys(const wxColour& clr)
*/
}
bool GUI_App::get_side_menu_popup_status()
{
return m_side_popup_status;
}
void GUI_App::set_side_menu_popup_status(bool status)
{
m_side_popup_status = status;
}
bool GUI_App::tabs_as_menu() const
{
return false;
@ -5717,5 +5736,21 @@ void GUI_App::disassociate_files(std::wstring extend)
#endif // __WXMSW__
bool is_support_filament(int extruder_id)
{
auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets;
auto &filaments = Slic3r::GUI::wxGetApp().preset_bundle->filaments;
if (extruder_id >= filament_presets.size()) return false;
Slic3r::Preset *filament = filaments.find_preset(filament_presets[extruder_id]);
if (filament == nullptr) return false;
Slic3r::ConfigOptionBools *support_option = dynamic_cast<Slic3r::ConfigOptionBools *>(filament->config.option("filament_is_support"));
if (support_option == nullptr) return false;
return support_option->get_at(0);
};
} // GUI
} //Slic3r

View file

@ -7,7 +7,6 @@
#include "ConfigWizard.hpp"
#include "OpenGLManager.hpp"
#include "libslic3r/Preset.hpp"
#include "wxExtensions.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
@ -53,7 +52,6 @@ class AppConfig;
class PresetBundle;
class PresetUpdater;
class ModelObject;
// class PrintHostJobQueue;
class Model;
class DeviceManager;
class NetworkAgent;
@ -284,6 +282,7 @@ private:
bool enable_sync = false;
bool m_is_dark_mode{ false };
bool m_adding_script_handler { false };
bool m_side_popup_status{false};
public:
std::string get_local_models_path();
bool OnInit() override;
@ -338,6 +337,9 @@ public:
void update_fonts(const MainFrame *main_frame = nullptr);
void set_label_clr_modified(const wxColour& clr);
void set_label_clr_sys(const wxColour& clr);
//update side popup status
bool get_side_menu_popup_status();
void set_side_menu_popup_status(bool status);
const wxColour& get_label_clr_modified(){ return m_color_label_modified; }
const wxColour& get_label_clr_sys() { return m_color_label_sys; }
@ -588,7 +590,9 @@ private:
DECLARE_APP(GUI_App)
wxDECLARE_EVENT(EVT_CONNECT_LAN_MODE_PRINT, wxCommandEvent);
} // GUI
bool is_support_filament(int extruder_id);
} // namespace GUI
} // Slic3r
#endif // slic3r_GUI_App_hpp_

View file

@ -78,7 +78,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
}},
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7},
{"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},
{"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25},
{"tree_support_branch_angle", "",10}, {"tree_support_wall_count", "",11},//tree support
{"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15},
{"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19},

View file

@ -171,6 +171,16 @@ void GridCellFilamentsEditor::Create(wxWindow* parent,
}
m_control = bitmap_combo;
wxGridCellEditor::Create(parent, id, evtHandler);
/* bitmap_combo->GetDropDown().Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& e) {
const wxString value = Combo()->GetValue();
if (value == m_value)
return false;
m_value = value;
return true;
e.Skip();
});*/
}
void GridCellFilamentsEditor::SetSize(const wxRect& rect)
@ -242,7 +252,7 @@ void GridCellFilamentsEditor::BeginEdit(int row, int col, wxGrid* grid)
// When dropping down the menu, a kill focus event
// happens after this point, so we can't reset the flag yet.
#if !defined(__WXGTK20__)
evtHandler->SetInSetFocus(false);
//evtHandler->SetInSetFocus(false);
#endif
}
}

View file

@ -540,10 +540,7 @@ int GLGizmoFdmSupports::get_selection_support_threshold_angle()
SupportType support_type = obj_cfg.option("support_type") ? obj_cfg.opt_enum<SupportType>("support_type") : glb_cfg.opt_enum<SupportType>("support_type");
int support_threshold_angle = obj_cfg.option("support_threshold_angle") ? obj_cfg.opt_int("support_threshold_angle") : glb_cfg.opt_int("support_threshold_angle");
bool auto_support = enable_support &&
(support_type == SupportType::stHybridAuto ||
support_type == SupportType::stTreeAuto ||
support_type == SupportType::stNormalAuto);
bool auto_support = enable_support && is_auto(support_type);
return auto_support ? support_threshold_angle : 0;
}
@ -725,8 +722,7 @@ void GLGizmoFdmSupports::init_print_instance()
const PrintObjectConfig& config = m_print_instance.print_object->config();
m_angle_threshold_deg = config.support_angle;
m_is_tree_support = config.enable_support.value &&
(config.support_type.value == stTreeAuto || config.support_type.value == stTree || config.support_type.value==stHybridAuto);
m_is_tree_support = config.enable_support.value && is_tree(config.support_type.value);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",get support_angle "<< m_angle_threshold_deg<<", is_tree "<<m_is_tree_support;
return;

View file

@ -321,16 +321,16 @@ void GLGizmoMmuSegmentation::show_tooltip_information(float caption_max, float x
std::vector<std::string> tip_items;
switch (m_tool_type) {
case ToolType::BRUSH:
tip_items = {"paint", "erase", "cursor_size", "clipping_of_view", "toggle_wireframe"};
tip_items = {"paint", "erase", "cursor_size", "clipping_of_view"};
break;
case ToolType::BUCKET_FILL:
tip_items = {"paint", "erase", "smart_fill_angle", "clipping_of_view", "toggle_wireframe"};
tip_items = {"paint", "erase", "smart_fill_angle", "clipping_of_view"};
break;
case ToolType::SMART_FILL:
// TODO:
break;
case ToolType::GAP_FILL:
tip_items = {"gap_area", "toggle_wireframe"};
tip_items = {"gap_area"};
break;
default:
break;
@ -357,7 +357,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
const float space_size = m_imgui->get_style_scaling() * 8;
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f),
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f),
m_imgui->calc_text_size(m_desc.at("reset_direction")).x + m_imgui->scaled(1.5f) + ImGui::GetStyle().FramePadding.x * 2);
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.5f);
const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f);

View file

@ -388,7 +388,7 @@ void ArrangeJob::prepare()
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
params.cleareance_radius = print.config().extruder_clearance_radius.value;
params.cleareance_radius = print.config().extruder_clearance_max_radius.value;
params.printable_height = print.config().printable_height.value;
params.allow_rotations = settings.enable_rotation;
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;

View file

@ -1361,9 +1361,6 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
update_side_button_style();
m_print_option_btn->Enable();
sizer->Add(FromDIP(15), 0, 0, 0, 0);
m_slice_option_btn->Enable();
m_print_option_btn->Enable();
sizer->Add(m_slice_option_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(1));

View file

@ -8,6 +8,7 @@
#include "MsgDialog.hpp"
#include "DownloadProgressDialog.hpp"
#include <boost/filesystem/string_file.hpp>
#undef pid_t
#include <boost/process.hpp>
#ifdef __WIN32__

View file

@ -135,6 +135,7 @@ enum class NotificationType
BBLSeqPrintInfo,
//BBL: plugin install hint
BBLPluginInstallHint,
BBLPluginUpdateAvailable,
BBLPreviewOnlyMode,
};
@ -873,6 +874,17 @@ private:
_u8L("Integration failed.") },
NotificationData{NotificationType::UndoDesktopIntegrationSuccess, NotificationLevel::RegularNotificationLevel, 10,
_u8L("Undo integration was successful.") },
NotificationData{NotificationType::BBLPluginUpdateAvailable, NotificationLevel::ImportantNotificationLevel, BBL_NOTICE_MAX_INTERVAL,
_u8L("New network plug-in available."),
_u8L("Details"),
[](wxEvtHandler* evnthndlr) {
//BBS set feishu release page by default
wxCommandEvent* evt = new wxCommandEvent(EVT_UPDATE_PLUGINS_WHEN_LAUNCH);
wxQueueEvent(wxGetApp().plater(), evt);
return true;
}},
NotificationData{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10,
_u8L("Undo integration failed.") },
NotificationData{NotificationType::ExportOngoing, NotificationLevel::RegularNotificationLevel, 0, _u8L("Exporting.")},

View file

@ -1198,6 +1198,28 @@ std::vector<int> PartPlate::get_extruders() const
return plate_extruders;
}
std::vector<int> PartPlate::get_used_extruders()
{
std::vector<int> used_extruders;
// if gcode.3mf file
if (m_model->objects.empty()) {
for (int i = 0; i < slice_filaments_info.size(); i++) {
used_extruders.push_back(slice_filaments_info[i].id + 1);
}
return used_extruders;
}
GCodeProcessorResult* result = get_slice_result();
if (!result)
return used_extruders;
PrintEstimatedStatistics& ps = result->print_statistics;
for (auto it = ps.volumes_per_extruder.begin(); it != ps.volumes_per_extruder.end(); it++) {
used_extruders.push_back(it->first + 1);
}
return used_extruders;
}
Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volume) const
{
Vec3d wipe_tower_size;

View file

@ -259,6 +259,7 @@ public:
Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const double w, const double wipe_volume) const;
std::vector<int> get_extruders() const;
std::vector<int> get_used_extruders();
/* instance related operations*/
//judge whether instance is bound in plate or not

View file

@ -160,6 +160,7 @@ wxDEFINE_EVENT(EVT_PUBLISH_FINISHED, wxCommandEvent);
wxDEFINE_EVENT(EVT_REPAIR_MODEL, wxCommandEvent);
wxDEFINE_EVENT(EVT_FILAMENT_COLOR_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_INSTALL_PLUGIN_NETWORKING, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, wxCommandEvent);
wxDEFINE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent);
wxDEFINE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent);
//BBS: change light/dark mode
@ -1101,7 +1102,7 @@ void Sidebar::update_presets(Preset::Type preset_type)
Tab* print_tab = wxGetApp().get_tab(Preset::TYPE_PRINT);
if (print_tab) {
print_tab->get_combo_box()->update();
}
}
break;
}
case Preset::TYPE_SLA_PRINT:
@ -1116,7 +1117,7 @@ void Sidebar::update_presets(Preset::Type preset_type)
{
update_all_preset_comboboxes();
p->show_preset_comboboxes();
/* update bed shape */
Tab* printer_tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
if (printer_tab) {
@ -2135,6 +2136,7 @@ private:
void update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool temp_snapshot_was_taken = false);
void on_action_export_to_sdcard(SimpleEvent&);
void on_action_export_to_sdcard_all(SimpleEvent&);
void update_plugin_when_launch(wxCommandEvent& event);
// path to project folder stored with no extension
boost::filesystem::path m_project_folder;
@ -2229,6 +2231,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->q->Bind(EVT_FILAMENT_COLOR_CHANGED, &priv::on_filament_color_changed, this);
this->q->Bind(EVT_INSTALL_PLUGIN_NETWORKING, &priv::install_network_plugin, this);
this->q->Bind(EVT_INSTALL_PLUGIN_HINT, &priv::show_install_plugin_hint, this);
this->q->Bind(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, &priv::update_plugin_when_launch, this);
this->q->Bind(EVT_PREVIEW_ONLY_MODE_HINT, &priv::show_preview_only_hint, this);
this->q->Bind(EVT_GLCANVAS_COLOR_MODE_CHANGED, &priv::on_change_color_mode, this);
this->q->Bind(wxEVT_SYS_COLOUR_CHANGED, &priv::on_apple_change_color_mode, this);
@ -6212,6 +6215,29 @@ void Plater::priv::install_network_plugin(wxCommandEvent &event)
return;
}
void Plater::priv::update_plugin_when_launch(wxCommandEvent &event)
{
std::string data_dir_str = data_dir();
boost::filesystem::path data_dir_path(data_dir_str);
auto cache_folder = data_dir_path / "ota";
std::string changelog_file = cache_folder.string() + "/network_plugins.json";
UpdatePluginDialog dlg(wxGetApp().mainframe);
dlg.update_info(changelog_file);
auto result = dlg.ShowModal();
auto app_config = wxGetApp().app_config;
if (!app_config) return;
if (result == wxID_OK) {
app_config->set("update_network_plugin", "true");
}
else if (result == wxID_NO) {
app_config->set("update_network_plugin", "false");
}
app_config->save();
}
void Plater::priv::show_install_plugin_hint(wxCommandEvent &event)
{
notification_manager->bbl_show_plugin_install_notification(into_u8(_L("Network Plug-in is not detected. Network related features are unavailable.")));
@ -7376,6 +7402,7 @@ Plater::Plater(wxWindow *parent, MainFrame *main_frame)
, p(new priv(this, main_frame))
{
// Initialization performed in the private c-tor
enable_wireframe(false);
}
bool Plater::Show(bool show)

View file

@ -87,6 +87,7 @@ wxDECLARE_EVENT(EVT_REPAIR_MODEL, wxCommandEvent);
wxDECLARE_EVENT(EVT_FILAMENT_COLOR_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_INSTALL_PLUGIN_NETWORKING, wxCommandEvent);
wxDECLARE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, wxCommandEvent);
wxDECLARE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent);

View file

@ -44,7 +44,7 @@ ReleaseNoteDialog::ReleaseNoteDialog(Plater *plater /*= nullptr*/)
m_sizer_body->Add(0, 0, 0, wxLEFT, FromDIP(38));
auto sm = create_scaled_bitmap("BambuStudio", nullptr, 70);
auto sm = create_scaled_bitmap("BambuStudio", nullptr, 70);
auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70)));
m_sizer_body->Add(brand, 0, wxALL, 0);
@ -85,8 +85,8 @@ void ReleaseNoteDialog::on_dpi_changed(const wxRect &suggested_rect)
{
}
void ReleaseNoteDialog::update_release_note(wxString release_note, std::string version)
{
void ReleaseNoteDialog::update_release_note(wxString release_note, std::string version)
{
m_text_up_info->SetLabel(wxString::Format(_L("version %s update information :"), version));
wxBoxSizer * sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_staticText_release_note = new wxStaticText(m_vebview_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0);
@ -97,34 +97,175 @@ void ReleaseNoteDialog::update_release_note(wxString release_note, std::string v
m_vebview_release_note->Fit();
}
void UpdateVersionDialog::alter_choice(wxCommandEvent& event)
{
wxGetApp().set_skip_version(m_remind_choice->GetValue());
}
UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
: DPIDialog(parent, wxID_ANY, _L("New version of Bambu Studio"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
UpdatePluginDialog::UpdatePluginDialog(wxWindow* parent /*= nullptr*/)
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _L("Network plug-in update"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0);
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(30));
wxBoxSizer* m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
auto sm = create_scaled_bitmap("BambuStudio", nullptr, 55);
auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(55), FromDIP(55)));
wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL);
m_text_up_info = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
m_text_up_info->SetFont(::Label::Head_13);
m_text_up_info->SetMaxSize(wxSize(FromDIP(260), -1));
m_text_up_info->Wrap(FromDIP(260));
m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30));
operation_tips = new ::Label(this, _L("Click OK to update the Network plug-in when Bambu Studio launches next time."));
operation_tips->SetFont(::Label::Body_12);
operation_tips->SetSize(wxSize(FromDIP(260), -1));
operation_tips->Wrap(FromDIP(260));
operation_tips->SetForegroundColour(*wxBLACK);
m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
m_vebview_release_note->SetScrollRate(5, 5);
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetMinSize(wxSize(FromDIP(260), FromDIP(150)));
m_vebview_release_note->SetMaxSize(wxSize(FromDIP(260), FromDIP(150)));
auto sizer_button = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
auto m_button_ok = new Button(this, _L("OK"));
m_button_ok->SetBackgroundColor(btn_bg_green);
m_button_ok->SetBorderColor(*wxWHITE);
m_button_ok->SetTextColor(wxColour(0xFFFFFE));
m_button_ok->SetFont(Label::Body_12);
m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetCornerRadius(FromDIP(12));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
EndModal(wxID_OK);
});
auto m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetBackgroundColor(btn_bg_white);
m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
m_button_cancel->SetFont(Label::Body_12);
m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_cancel->SetCornerRadius(FromDIP(12));
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
EndModal(wxID_NO);
});
sizer_button->AddStretchSpacer();
sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5));
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
m_sizer_right->Add(m_text_up_info, 0, 0, 0);
m_sizer_right->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_right->Add(operation_tips, 1, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_body->Add(0, 0, 0, wxLEFT, FromDIP(24));
m_sizer_body->Add(brand, 0, wxALL, 0);
m_sizer_body->Add(0, 0, 0, wxRIGHT, FromDIP(20));
m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(18));
m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0);
SetSizer(m_sizer_main);
Layout();
m_sizer_main->Fit(this);
Centre(wxBOTH);
wxGetApp().UpdateDlgDarkUI(this);
}
UpdatePluginDialog::~UpdatePluginDialog() {}
void UpdatePluginDialog::on_dpi_changed(const wxRect& suggested_rect)
{
}
void UpdatePluginDialog::update_info(std::string json_path)
{
std::string version_str, description_str;
wxString version;
wxString description;
try {
boost::nowide::ifstream ifs(json_path);
json j;
ifs >> j;
version_str = j["version"];
description_str = j["description"];
}
catch(nlohmann::detail::parse_error &err) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<json_path<<" got a nlohmann::detail::parse_error, reason = " << err.what();
return;
}
version = from_u8(version_str);
description = from_u8(description_str);
m_text_up_info->SetLabel(wxString::Format(_L("A new Network plug-in(%s) available, Do you want to install it?"), version));
m_text_up_info->SetMaxSize(wxSize(FromDIP(260), -1));
m_text_up_info->Wrap(FromDIP(260));
wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_text_label = new ::Label(m_vebview_release_note, description);
m_text_label->SetFont(::Label::Body_13);
m_text_label->SetForegroundColour(*wxBLACK);
m_text_label->SetMaxSize(wxSize(FromDIP(235), -1));
m_text_label->Wrap(FromDIP(235));
sizer_text_release_note->Add(m_text_label, 0, wxALL, 5);
m_vebview_release_note->SetSizer(sizer_text_release_note);
m_vebview_release_note->Layout();
m_vebview_release_note->Fit();
Layout();
Fit();
}
UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
: DPIDialog(parent, wxID_ANY, _L("New version of Bambu Studio"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
m_sizer_body->Add(0, 0, 0, wxLEFT, FromDIP(38));
auto sm = create_scaled_bitmap("BambuStudio", nullptr, 70);
auto brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70)));
m_brand = new wxStaticBitmap(this, wxID_ANY, sm, wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70)));
m_sizer_body->Add(brand, 0, wxALL, 0);
m_sizer_body->Add(0, 0, 0, wxRIGHT, FromDIP(25));
wxBoxSizer *m_sizer_right = new wxBoxSizer(wxVERTICAL);
@ -132,14 +273,12 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_text_up_info->SetFont(::Label::Head_14);
m_text_up_info->SetForegroundColour(wxColour(0x26, 0x2E, 0x30));
m_text_up_info->Wrap(-1);
m_sizer_right->Add(m_text_up_info, 0, 0, 0);
m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15));
m_simplebook_release_note = new wxSimplebook(this);
m_simplebook_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_scrollwindows_release_note = new wxScrolledWindow(m_simplebook_release_note, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL);
@ -151,7 +290,7 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
//m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
fs::path ph(data_dir());
ph /= "resources/tooltip/common/releasenote.html";
@ -174,7 +313,7 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
auto sizer_button = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
@ -184,7 +323,7 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_button_ok = new Button(this, _L("OK"));
m_button_ok->SetBackgroundColor(btn_bg_green);
m_button_ok->SetBorderColor(*wxWHITE);
m_button_ok->SetTextColor(*wxWHITE);
m_button_ok->SetTextColor(wxColour("#FFFFFE"));
m_button_ok->SetFont(Label::Body_12);
m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
@ -202,26 +341,32 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_cancel->SetCornerRadius(FromDIP(12));
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
EndModal(wxID_NO);
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
EndModal(wxID_NO);
});
m_sizer_main->Add(m_line_top, 0, wxEXPAND | wxBOTTOM, 0);
sizer_button->Add(m_remind_choice, 0, wxALL | wxEXPAND, FromDIP(5));
sizer_button->AddStretchSpacer();
sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5));
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
m_sizer_right->Add(m_simplebook_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(m_text_up_info, 0, wxBOTTOM|wxTOP, FromDIP(15));
m_sizer_right->Add(m_simplebook_release_note, 1, wxEXPAND | wxRIGHT, 0);
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_body->Add(m_brand, 0, wxTOP|wxRIGHT|wxLEFT, FromDIP(15));
m_sizer_body->Add(0, 0, 0, wxRIGHT, 0);
m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(8));
m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0);
m_sizer_main->Add(m_sizer_body, 1, wxEXPAND, 0);
m_sizer_main->Add(0, 0, 0, wxBOTTOM, 10);
SetSizer(m_sizer_main);
Layout();
m_sizer_main->Fit(this);
Fit();
SetMinSize(GetSize());
Centre(wxBOTH);
wxGetApp().UpdateDlgDarkUI(this);
@ -229,6 +374,11 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
UpdateVersionDialog::~UpdateVersionDialog() {}
void UpdateVersionDialog::alter_choice(wxCommandEvent& event)
{
wxGetApp().set_skip_version(m_remind_choice->GetValue());
}
wxWebView* UpdateVersionDialog::CreateTipView(wxWindow* parent)
{
wxWebView* tipView = WebView::CreateWebView(parent, "");
@ -312,26 +462,32 @@ std::vector<std::string> UpdateVersionDialog::splitWithStl(std::string str,std::
}
void UpdateVersionDialog::update_version_info(wxString release_note, wxString version)
{
{
//bbs check whether the web display is used
bool use_web_link = false;
std::string url_line = "";
/*auto split_array = splitWithStl(release_note.ToStdString(), "\r\n");
for (auto i = 0; i < split_array.size(); i++) {
std::string url = split_array[i];
if (std::strstr (url.c_str(), "http://") != NULL || std::strstr (url.c_str(), "https://") != NULL) {
use_web_link = true;
url_line = url;
break;
if (split_array.size() >= 3) {
for (auto i = 0; i < split_array.size(); i++) {
std::string url = split_array[i];
if (std::strstr(url.c_str(), "http://") != NULL || std::strstr(url.c_str(), "https://") != NULL) {
use_web_link = true;
url_line = url;
break;
}
}
}
if (use_web_link) {
m_brand->Hide();
m_text_up_info->Hide();
m_simplebook_release_note->SetSelection(1);
m_vebview_release_note->LoadURL(from_u8(url_line));
}
else {*/
m_simplebook_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetSelection(0);
m_text_up_info->SetLabel(wxString::Format(_L("Click to download new version in default browser: %s"), version));
wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
@ -341,7 +497,11 @@ void UpdateVersionDialog::update_version_info(wxString release_note, wxString ve
m_scrollwindows_release_note->SetSizer(sizer_text_release_note);
m_scrollwindows_release_note->Layout();
m_scrollwindows_release_note->Fit();
//}
SetMinSize(GetSize());
SetMaxSize(GetSize());
//}
Layout();
Fit();
}
SecondaryCheckDialog::SecondaryCheckDialog(wxWindow* parent, wxWindowID id, const wxString& title, enum ButtonStyle btn_style, const wxPoint& pos, const wxSize& size, long style, bool not_show_again_check)

View file

@ -53,6 +53,20 @@ public:
wxScrolledWindow *m_vebview_release_note {nullptr};
};
class UpdatePluginDialog : public DPIDialog
{
public:
UpdatePluginDialog(wxWindow* parent = nullptr);
~UpdatePluginDialog();
void on_dpi_changed(const wxRect& suggested_rect) override;
void update_info(std::string json_path);
wxStaticText* m_text_up_info{ nullptr };
Label* operation_tips{ nullptr };
wxScrolledWindow* m_vebview_release_note{ nullptr };
};
class UpdateVersionDialog : public DPIDialog
{
public:
@ -70,6 +84,7 @@ public:
void alter_choice(wxCommandEvent& event);
std::vector<std::string> splitWithStl(std::string str, std::string pattern);
wxStaticBitmap* m_brand{nullptr};
wxStaticText * m_text_up_info{nullptr};
wxWebView* m_vebview_release_note{nullptr};
wxSimplebook* m_simplebook_release_note{nullptr};

View file

@ -2927,7 +2927,7 @@ void SelectMachineDialog::set_default()
}
// material info
auto extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders();
auto extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_extruders();
BitmapCache bmcache;
MaterialHash::iterator iter = m_materialList.begin();

View file

@ -2707,7 +2707,7 @@ void Selection::paste_objects_from_clipboard()
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
auto point_offset = start_offset - start_point;
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_point(2)};
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
}
for (ModelInstance* inst : dst_object->instances)

View file

@ -892,6 +892,12 @@ void SendToPrinterDialog::update_show_status()
reset_timeout();
bool is_suppt = obj_->is_function_supported(PrinterFunction::FUNC_SEND_TO_SDCARD);
if (!is_suppt) {
show_status(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard);
return;
}
// reading done
if (obj_->is_in_upgrading()) {
show_status(PrintDialogStatus::PrintStatusInUpgrading);
@ -914,12 +920,6 @@ void SendToPrinterDialog::update_show_status()
show_status(PrintDialogStatus::PrintStatusNotOnTheSameLAN);
return;
}
bool is_suppt = obj_->is_function_supported(PrinterFunction::FUNC_SEND_TO_SDCARD);
if (!is_suppt) {
show_status(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard);
return;
}
show_status(PrintDialogStatus::PrintStatusReadingFinished);
}

View file

@ -1807,6 +1807,7 @@ void StatusPanel::update_ams(MachineObject *obj)
// update obj in sub dlg
if (m_ams_setting_dlg) {
m_ams_setting_dlg->obj = obj;
if (obj && m_ams_setting_dlg->IsShown()) {
m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag);
m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag);
@ -1842,7 +1843,7 @@ void StatusPanel::update_ams(MachineObject *obj)
for (auto ams = obj->amsList.begin(); ams != obj->amsList.end(); ams++) {
AMSinfo info;
info.ams_id = ams->first;
if (ams->second->is_exists && info.parse_ams_info(ams->second, obj->ams_calibrate_remain_flag)) ams_info.push_back(info);
if (ams->second->is_exists && info.parse_ams_info(ams->second, obj->ams_calibrate_remain_flag, obj->is_support_ams_humidity)) ams_info.push_back(info);
}
//if (obj->ams_exist_bits != last_ams_exist_bits || obj->tray_exist_bits != last_tray_exist_bits || obj->tray_is_bbl_bits != last_tray_is_bbl_bits ||
// obj->tray_read_done_bits != last_read_done_bits || obj->ams_version != last_ams_version) {
@ -2445,6 +2446,7 @@ void StatusPanel::on_ams_setting_click(SimpleEvent &event)
try {
int ams_id_int = atoi(ams_id.c_str());
m_ams_setting_dlg->ams_id = ams_id_int;
m_ams_setting_dlg->ams_support_remain = obj->ams_support_remain;
m_ams_setting_dlg->Show();
} catch (...) {
;

View file

@ -1418,6 +1418,65 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
}
}
// BBS popup a message to ask the user to set optimum parameters for tree support
if (opt_key == "support_type" || opt_key == "support_style") {
if (is_tree_slim(m_config->opt_enum<SupportType>("support_type"), m_config->opt_enum<SupportMaterialStyle>("support_style")) &&
!(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_int("support_interface_top_layers") == 0 && m_config->opt_int("tree_support_wall_count") == 2)) {
wxString msg_text = _L("We have added an experimental style \"Tree Slim\" that features smaller support volume but weaker strength.\n"
"We recommend using it with: 0 interface layers, 0 top distance, 2 walls.");
msg_text += "\n\n" + _L("Change these settings automatically? \n"
"Yes - Change these settings automatically\n"
"No - Do not change these settings for me");
MessageDialog dialog(wxGetApp().plater(), msg_text, "Suggestion", wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config;
if (dialog.ShowModal() == wxID_YES) {
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0));
new_conf.set_key_value("support_interface_top_layers", new ConfigOptionInt(0));
new_conf.set_key_value("tree_support_wall_count", new ConfigOptionInt(2));
m_config_manipulation.apply(m_config, &new_conf);
}
wxGetApp().plater()->update();
} else if ((m_config->opt_enum<SupportType>("support_type")==stTreeAuto && (m_config->opt_enum<SupportMaterialStyle>("support_style")==smsTreeStrong || m_config->opt_enum<SupportMaterialStyle>("support_style") == smsTreeHybrid)) &&
!((m_config->opt_float("support_top_z_distance") >=0.1 || is_support_filament(m_config->opt_int("support_interface_filament") - 1))
&& m_config->opt_int("support_interface_top_layers") >1) ) {
wxString msg_text = _L("For \"Tree Strong\" and \"Tree Hybrid\" styles, we recommend the following settings: at least 2 interface layers, at least 0.1mm top z distance or using support materials on interface.");
msg_text += "\n\n" + _L("Change these settings automatically? \n"
"Yes - Change these settings automatically\n"
"No - Do not change these settings for me");
MessageDialog dialog(wxGetApp().plater(), msg_text, "Suggestion", wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config;
if (dialog.ShowModal() == wxID_YES) {
if (!is_support_filament(m_config->opt_int("support_interface_filament") - 1) && m_config->opt_float("support_top_z_distance") < 0.1)
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0.2));
new_conf.set_key_value("support_interface_top_layers", new ConfigOptionInt(2));
m_config_manipulation.apply(m_config, &new_conf);
}
wxGetApp().plater()->update();
}
}
// BBS popup a message to ask the user to set optimum parameters for support interface if support materials are used
if (opt_key == "support_interface_filament") {
int interface_filament_id = m_config->opt_int("support_interface_filament") - 1; // the displayed id is based from 1, while internal id is based from 0
if (is_support_filament(interface_filament_id) && !(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_float("support_interface_spacing") == 0 &&
m_config->opt_enum<SupportMaterialInterfacePattern>("support_interface_pattern") == SupportMaterialInterfacePattern::smipConcentric)) {
wxString msg_text = _L("When using support material for the support interface, We recommend the following settings:\n"
"0 top z distance, 0 interface spacing, concentric pattern.");
msg_text += "\n\n" + _L("Change these settings automatically? \n"
"Yes - Change these settings automatically\n"
"No - Do not change these settings for me");
MessageDialog dialog(wxGetApp().plater(), msg_text, "Suggestion", wxICON_WARNING | wxYES | wxNO);
DynamicPrintConfig new_conf = *m_config;
if (dialog.ShowModal() == wxID_YES) {
new_conf.set_key_value("support_top_z_distance", new ConfigOptionFloat(0));
new_conf.set_key_value("support_interface_spacing", new ConfigOptionFloat(0));
new_conf.set_key_value("support_interface_pattern", new ConfigOptionEnum<SupportMaterialInterfacePattern>(SupportMaterialInterfacePattern::smipConcentric));
m_config_manipulation.apply(m_config, &new_conf);
}
wxGetApp().plater()->update();
}
}
// BBS
#if 0
if (opt_key == "extruders_count")
@ -1893,6 +1952,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Support"), L"param_support");
optgroup->append_single_option_line("enable_support", "support");
optgroup->append_single_option_line("support_type", "support#support-types");
optgroup->append_single_option_line("support_style", "support#support-styles");
optgroup->append_single_option_line("support_threshold_angle", "support#threshold-angle");
optgroup->append_single_option_line("support_on_build_plate_only");
optgroup->append_single_option_line("support_critical_regions_only");
@ -1908,7 +1968,6 @@ void TabPrint::build()
optgroup->append_single_option_line("support_interface_filament", "support#support-filament");
//optgroup = page->new_optgroup(L("Options for support material and raft"));
//optgroup->append_single_option_line("support_style");
//BBS
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");

View file

@ -35,11 +35,18 @@ wxDEFINE_EVENT(EVT_AMS_CLIBRATION_CANCEL, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_GUIDE_WIKI, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_RETRY, wxCommandEvent);
bool AMSinfo::parse_ams_info(Ams *ams, bool remain_flag)
bool AMSinfo::parse_ams_info(Ams *ams, bool remain_flag, bool humidity_flag)
{
if (!ams) return false;
this->ams_id = ams->id;
this->ams_humidity = ams->humidity;
if (humidity_flag) {
this->ams_humidity = ams->humidity;
}
else {
this->ams_humidity = -1;
}
cans.clear();
for (int i = 0; i < 4; i++) {
auto it = ams->trayList.find(std::to_string(i));
@ -917,7 +924,8 @@ void AMSRoad::doRender(wxDC &dc)
dc.DrawBitmap(ams_humidity_0.bmp(), wxPoint(size.x - ams_humidity_0.GetBmpSize().x - FromDIP(4), size.y - ams_humidity_0.GetBmpSize().y - FromDIP(8)));
}
else {
dc.DrawBitmap(ams_humidity_4.bmp(), wxPoint(size.x - ams_humidity_4.GetBmpSize().x - FromDIP(4), size.y - ams_humidity_4.GetBmpSize().y - FromDIP(8)));
/*dc.DrawBitmap(ams_humidity_4.bmp(), wxPoint(size.x - ams_humidity_4.GetBmpSize().x - FromDIP(4), size.y - ams_humidity_4.GetBmpSize().y - FromDIP(8)));*/
//to do ...
}
}
}

View file

@ -126,7 +126,7 @@ public:
int curreent_filamentstep;
int ams_humidity = 0;
bool parse_ams_info(Ams *ams, bool remain_flag = false);
bool parse_ams_info(Ams *ams, bool remain_flag = false, bool humidity_flag = false);
};
/*************************************************

View file

@ -2,6 +2,7 @@
#include "Label.hpp"
#include <wx/dcgraph.h>
#include "../GUI_App.hpp"
@ -17,7 +18,6 @@ SidePopup::SidePopup(wxWindow* parent)
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
}
SidePopup::~SidePopup()
@ -27,6 +27,7 @@ SidePopup::~SidePopup()
void SidePopup::OnDismiss()
{
Slic3r::GUI::wxGetApp().set_side_menu_popup_status(false);
wxPopupTransientWindow::OnDismiss();
}
@ -64,6 +65,7 @@ void SidePopup::Popup(wxWindow* focus)
else
Position(pos, {0, focus->GetSize().y + 12});
}
Slic3r::GUI::wxGetApp().set_side_menu_popup_status(true);
wxPopupTransientWindow::Popup();
}

View file

@ -611,24 +611,6 @@ void WipingPanel::update_warning_texts()
void WipingPanel::calc_flushing_volumes()
{
auto is_support_filament = [](int extruder_id) -> bool {
auto& filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets;
auto& filaments = Slic3r::GUI::wxGetApp().preset_bundle->filaments;
if (extruder_id >= filament_presets.size())
return false;
Slic3r::Preset* filament = filaments.find_preset(filament_presets[extruder_id]);
if (filament == nullptr)
return false;
Slic3r::ConfigOptionBools* support_option = dynamic_cast<Slic3r::ConfigOptionBools*>(filament->config.option("filament_is_support"));
if (support_option == nullptr)
return false;
return support_option->get_at(0);
};
for (int from_idx = 0; from_idx < m_colours.size(); from_idx++) {
const wxColour& from = m_colours[from_idx];
bool is_from_support = is_support_filament(from_idx);

View file

@ -33,6 +33,7 @@
#include <cstdint> // uint8_t
#include <ctype.h> // ::tolower, ::toupper
#include <cwctype> // ::towlower
#include <cstring> // memcpy
#include <cstdio>