Merge branch 'master-remote' into feature/1.5

Signed-off-by: SoftFever <softfeverever@gmail.com>

# 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/it/BambuStudio_it.po
#	bbl/i18n/nl/BambuStudio_nl.po
#	bbl/i18n/sv/BambuStudio_sv.po
#	bbl/i18n/zh_cn/BambuStudio_zh_CN.po
#	deps/Boost/Boost.cmake
#	deps/wxWidgets/wxWidgets.cmake
#	resources/config.json
#	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/it/BambuStudio.mo
#	resources/i18n/nl/BambuStudio.mo
#	resources/i18n/sv/BambuStudio.mo
#	resources/i18n/zh_cn/BambuStudio.mo
#	resources/images/tips_arrow.svg
#	resources/profiles/Anycubic.json
#	resources/profiles/Anycubic/filament/Anycubic Generic ABS.json
#	resources/profiles/Anycubic/filament/Anycubic Generic ASA.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PA-CF.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PA.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PC.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PETG.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PLA-CF.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PLA.json
#	resources/profiles/Anycubic/filament/Anycubic Generic PVA.json
#	resources/profiles/Anycubic/filament/Anycubic Generic TPU.json
#	resources/profiles/Anycubic/filament/fdm_filament_common.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro.json
#	resources/profiles/Anycubic/process/0.20mm Standard @4MaxPro.json
#	resources/profiles/Anycubic/process/fdm_process_common.json
#	resources/profiles/BBL.json
#	resources/profiles/BBL/machine/Bambu Lab P1P 0.2 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab P1P 0.6 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab P1P 0.8 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 0.2 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 0.4 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 0.6 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 0.8 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.2 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.4 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.6 nozzle.json
#	resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.8 nozzle.json
#	resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json
#	resources/profiles/Voron.json
#	resources/web/data/text.js
#	resources/web/image/printer/Anycubic 4Max Pro_cover.png
#	src/BambuStudio.cpp
#	src/libslic3r/GCode.cpp
#	src/libslic3r/GCode.hpp
#	src/libslic3r/GCode/GCodeProcessor.cpp
#	src/libslic3r/GCodeWriter.hpp
#	src/libslic3r/PerimeterGenerator.cpp
#	src/libslic3r/PresetBundle.cpp
#	src/libslic3r/Print.cpp
#	src/libslic3r/Print.hpp
#	src/libslic3r/PrintConfig.cpp
#	src/libslic3r/PrintConfig.hpp
#	src/libslic3r/PrintObject.cpp
#	src/slic3r/GUI/AMSMaterialsSetting.cpp
#	src/slic3r/GUI/AMSMaterialsSetting.hpp
#	src/slic3r/GUI/AmsMappingPopup.cpp
#	src/slic3r/GUI/AmsMappingPopup.hpp
#	src/slic3r/GUI/Auxiliary.cpp
#	src/slic3r/GUI/BackgroundSlicingProcess.cpp
#	src/slic3r/GUI/ConfigManipulation.cpp
#	src/slic3r/GUI/DeviceManager.cpp
#	src/slic3r/GUI/DeviceManager.hpp
#	src/slic3r/GUI/ExtrusionCalibration.cpp
#	src/slic3r/GUI/GCodeViewer.cpp
#	src/slic3r/GUI/GCodeViewer.hpp
#	src/slic3r/GUI/GUI_App.cpp
#	src/slic3r/GUI/IMSlider.cpp
#	src/slic3r/GUI/Jobs/PrintJob.cpp
#	src/slic3r/GUI/Jobs/PrintJob.hpp
#	src/slic3r/GUI/Jobs/SendJob.cpp
#	src/slic3r/GUI/Jobs/SendJob.hpp
#	src/slic3r/GUI/MainFrame.cpp
#	src/slic3r/GUI/MainFrame.hpp
#	src/slic3r/GUI/MediaPlayCtrl.cpp
#	src/slic3r/GUI/OptionsGroup.cpp
#	src/slic3r/GUI/PhysicalPrinterDialog.cpp
#	src/slic3r/GUI/Plater.cpp
#	src/slic3r/GUI/PrintHostDialogs.cpp
#	src/slic3r/GUI/Printer/BambuTunnel.h
#	src/slic3r/GUI/Printer/PrinterFileSystem.cpp
#	src/slic3r/GUI/Printer/gstbambusrc.c
#	src/slic3r/GUI/Printer/gstbambusrc.h
#	src/slic3r/GUI/ReleaseNote.cpp
#	src/slic3r/GUI/ReleaseNote.hpp
#	src/slic3r/GUI/SelectMachine.cpp
#	src/slic3r/GUI/SendToPrinter.cpp
#	src/slic3r/GUI/SetBedTypeDialog.cpp
#	src/slic3r/GUI/StatusPanel.cpp
#	src/slic3r/GUI/StatusPanel.hpp
#	src/slic3r/GUI/Tab.cpp
#	src/slic3r/GUI/Widgets/AMSControl.cpp
#	src/slic3r/GUI/Widgets/AMSControl.hpp
#	src/slic3r/GUI/Widgets/ImageSwitchButton.cpp
#	src/slic3r/GUI/Widgets/Label.cpp
#	src/slic3r/GUI/WipeTowerDialog.cpp
#	src/slic3r/Utils/Process.cpp
#	src/slic3r/Utils/bambu_networking.hpp
#	version.inc
This commit is contained in:
SoftFever 2023-03-08 00:08:26 +08:00
commit 5ef51f6c8a
339 changed files with 37169 additions and 5445 deletions

View file

@ -28,6 +28,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Widgets/SideMenuPopup.cpp
GUI/Widgets/DropDown.cpp
GUI/Widgets/DropDown.hpp
GUI/Widgets/PopupWindow.cpp
GUI/Widgets/PopupWindow.hpp
GUI/Widgets/Label.cpp
GUI/Widgets/Label.hpp
GUI/Widgets/Scrollbar.cpp
@ -205,6 +207,8 @@ set(SLIC3R_GUI_SOURCES
GUI/GUI_ObjectTableSettings.hpp
GUI/MeshUtils.cpp
GUI/MeshUtils.hpp
GUI/TickCode.cpp
GUI/TickCode.hpp
GUI/Tab.cpp
GUI/Tab.hpp
GUI/ParamsDialog.cpp
@ -273,12 +277,14 @@ set(SLIC3R_GUI_SOURCES
GUI/RemovableDriveManager.hpp
GUI/SendSystemInfoDialog.cpp
GUI/SendSystemInfoDialog.hpp
GUI/SetBedTypeDialog.cpp
GUI/SetBedTypeDialog.hpp
GUI/PlateSettingsDialog.cpp
GUI/PlateSettingsDialog.hpp
GUI/ImGuiWrapper.hpp
GUI/ImGuiWrapper.cpp
GUI/DeviceManager.hpp
GUI/DeviceManager.cpp
GUI/HttpServer.hpp
GUI/HttpServer.cpp
Config/Snapshot.cpp
Config/Snapshot.hpp
Config/Version.cpp
@ -364,6 +370,8 @@ set(SLIC3R_GUI_SOURCES
GUI/PublishDialog.hpp
GUI/RecenterDialog.cpp
GUI/RecenterDialog.hpp
GUI/PrivacyUpdateDialog.cpp
GUI/PrivacyUpdateDialog.hpp
GUI/BonjourDialog.cpp
GUI/BonjourDialog.hpp
GUI/BindDialog.cpp
@ -476,6 +484,10 @@ endif ()
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
target_include_directories(libslic3r_gui PRIVATE Utils)
if (WIN32)
target_include_directories(libslic3r_gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../deps/WebView2/include)
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES})
encoding_check(libslic3r_gui)

View file

@ -390,6 +390,8 @@ std::array<float, 4> GLVolume::MODEL_NEGTIVE_COL = {0.3f, 0.3f, 0.3f, 0.4f};
std::array<float, 4> GLVolume::SUPPORT_ENFORCER_COL = {0.3f, 0.3f, 1.0f, 0.4f};
std::array<float, 4> GLVolume::SUPPORT_BLOCKER_COL = {1.0f, 0.3f, 0.3f, 0.4f};
std::array<float, 4> GLVolume::MODEL_HIDDEN_COL = {0.f, 0.f, 0.f, 0.3f};
std::array<std::array<float, 4>, 5> GLVolume::MODEL_COLOR = { {
{ 1.0f, 1.0f, 0.0f, 1.f },
{ 1.0f, 0.5f, 0.5f, 1.f },
@ -430,6 +432,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, selected(false)
, disabled(false)
, printable(true)
, visible(true)
, is_active(true)
, zoom_to_volumes(true)
, shader_outside_printer_detection_enabled(false)
@ -521,6 +524,14 @@ void GLVolume::set_render_color()
render_color[2] = UNPRINTABLE_COLOR[2];
render_color[3] = UNPRINTABLE_COLOR[3];
}
//BBS set invisible color
if (!visible) {
render_color[0] = MODEL_HIDDEN_COL[0];
render_color[1] = MODEL_HIDDEN_COL[1];
render_color[2] = MODEL_HIDDEN_COL[2];
render_color[3] = MODEL_HIDDEN_COL[3];
}
}
std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume)
@ -684,6 +695,9 @@ void GLVolume::render(bool with_outline) const
break;
ModelObject* mo = model_objects[object_idx()];
if (volume_idx() >= mo->volumes.size())
break;
ModelVolume* mv = mo->volumes[volume_idx()];
if (mv->mmu_segmentation_facets.empty())
break;
@ -1149,7 +1163,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
std::vector<std::array<float, 4>> extruder_colors = get_extruders_colors();
std::vector<std::array<float, 4>> colors;
GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list();
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders();
std::vector<int> plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true);
TriangleMesh wipe_tower_shell = make_cube(width, depth, height);
for (int extruder_id : plate_extruders) {
if (extruder_id <= extruder_colors.size())

View file

@ -269,6 +269,7 @@ public:
static std::array<float, 4> MODEL_NEGTIVE_COL;
static std::array<float, 4> SUPPORT_ENFORCER_COL;
static std::array<float, 4> SUPPORT_BLOCKER_COL;
static std::array<float, 4> MODEL_HIDDEN_COL;
static void update_render_colors();
static void load_render_colors();
@ -286,6 +287,7 @@ public:
GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f);
GLVolume(const std::array<float, 4>& rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
virtual ~GLVolume() = default;
// BBS
protected:
@ -363,6 +365,8 @@ public:
bool disabled : 1;
// Is this object printable?
bool printable : 1;
// Is this object visible(in assemble view)?
bool visible : 1;
// Whether or not this volume is active for rendering
bool is_active : 1;
// Whether or not to use this volume when applying zoom_to_volumes()

View file

@ -121,12 +121,13 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent)
m_sizer_filament->Add(m_comboBox_filament, 1, wxALIGN_CENTER, 0);
m_readonly_filament = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_READONLY);
m_readonly_filament = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_READONLY | wxRIGHT);
m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x009688, (int)StateColor::Hovered),
std::make_pair(0xDBDBDB, (int)StateColor::Normal)));
m_readonly_filament->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [](auto& e) {
;
});
m_readonly_filament->SetFont(::Label::Body_14);
m_readonly_filament->SetLabelColor(AMS_MATERIALS_SETTING_GREY800);
m_readonly_filament->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [](auto& e) {});
m_readonly_filament->GetTextCtrl()->Hide();
m_sizer_filament->Add(m_readonly_filament, 1, wxALIGN_CENTER, 0);
m_readonly_filament->Hide();
@ -367,6 +368,13 @@ void AMSMaterialsSetting::enable_confirm_button(bool en)
else {
m_comboBox_filament->Show(en);
m_readonly_filament->Show(!en);
if ( !is_virtual_tray() ) {
m_tip_readonly->SetLabelText(_L("Setting AMS slot information while printing is not supported"));
}
else {
m_tip_readonly->SetLabelText(_L("Setting Virtual slot information while printing is not supported"));
}
m_tip_readonly->Show(!en);
}
}
@ -376,7 +384,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
wxString k_text = m_input_k_val->GetTextCtrl()->GetValue();
wxString n_text = m_input_n_val->GetTextCtrl()->GetValue();
if (is_virtual_tray()) {
if (is_virtual_tray() && obj && !obj->is_support_filament_edit_virtual_tray) {
if (!ExtrusionCalibration::check_k_validation(k_text)) {
wxString k_tips = _L("Please input a valid value (K in 0~0.5)");
wxString kn_tips = _L("Please input a valid value (K in 0~0.5, N in 0.6~2.0)");
@ -478,8 +486,12 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
}
// set filament
if (!is_virtual_tray()) {
obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
if (obj->is_support_filament_edit_virtual_tray || !is_virtual_tray()) {
if (is_virtual_tray()) {
obj->command_ams_filament_settings(255, VIRTUAL_TRAY_ID, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
} else {
obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
}
}
// set k / n value
@ -548,7 +560,10 @@ void AMSMaterialsSetting::update_widgets()
{
// virtual tray
if (is_virtual_tray()) {
m_panel_normal->Hide();
if (obj && obj->is_support_filament_edit_virtual_tray)
m_panel_normal->Show();
else
m_panel_normal->Hide();
m_panel_kn->Show();
} else if (obj && obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
m_panel_normal->Show();
@ -583,7 +598,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
m_input_k_val->GetTextCtrl()->SetValue(k);
m_input_n_val->GetTextCtrl()->SetValue(n);
if (is_virtual_tray()) {
if (is_virtual_tray() && obj && !obj->is_support_filament_edit_virtual_tray) {
m_button_confirm->Show();
update();
Layout();
@ -609,7 +624,8 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
m_panel_SN->Show();
m_comboBox_filament->Hide();
m_readonly_filament->Show();
m_readonly_filament->GetTextCtrl()->SetLabel("Bambu " + filament);
//m_readonly_filament->GetTextCtrl()->SetLabel("Bambu " + filament);
m_readonly_filament->SetLabel("Bambu " + filament);
m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min);
m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max);
@ -712,6 +728,31 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
if (preset_bundle) {
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
//check is it in the filament blacklist
bool in_blacklist = false;
std::string action;
std::string info;
std::string filamnt_type;
it->get_filament_type(filamnt_type);
if (it->vendor) {
DeviceManager::check_filaments_in_blacklist(it->vendor->name, filamnt_type, in_blacklist, action, info);
}
if (in_blacklist) {
if (action == "prohibition") {
MessageDialog msg_wingow(nullptr, info, _L("Error"), wxICON_WARNING | wxOK);
msg_wingow.ShowModal();
m_comboBox_filament->SetSelection(m_filament_selection);
return;
}
else if (action == "warning") {
MessageDialog msg_wingow(nullptr, info, _L("Warning"), wxICON_INFORMATION | wxOK);
msg_wingow.ShowModal();
}
}
// ) if nozzle_temperature_range is found
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
if (opt_min) {
@ -742,6 +783,8 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
}
if (!found_filament_type)
m_filament_type = "";
break;
}
}
}
@ -751,6 +794,8 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
if (m_input_nozzle_max->GetTextCtrl()->GetValue().IsEmpty()) {
m_input_nozzle_max->GetTextCtrl()->SetValue("220");
}
m_filament_selection = evt.GetSelection();
}
void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect) { this->Refresh(); }

View file

@ -98,13 +98,14 @@ protected:
TextInput* m_input_k_val;
wxStaticText* m_n_param;
TextInput* m_input_n_val;
int m_filament_selection;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament;
#else
ComboBox *m_comboBox_filament;
#endif
TextInput* m_readonly_filament;
TextInput* m_readonly_filament;
};
}} // namespace Slic3r::GUI

View file

@ -53,9 +53,9 @@ void AMSSetting::create()
m_sizer_Insert_material_tip->Add(0, 0, 0, wxLEFT, 10);
// tip line1
m_tip_Insert_material_line1 = new wxStaticText(m_panel_body, wxID_ANY,
_L("The AMS will automatically read the filament information when inserting a new Bambu Lab filament. This takes about 20 seconds."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_Insert_material_line1 = new Label(m_panel_body,
_L("The AMS will automatically read the filament information when inserting a new Bambu Lab filament. This takes about 20 seconds.")
);
m_tip_Insert_material_line1->SetFont(::Label::Body_13);
m_tip_Insert_material_line1->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_Insert_material_line1->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
@ -64,9 +64,9 @@ void AMSSetting::create()
m_sizer_Insert_material_tip_inline->Add(m_tip_Insert_material_line1, 0, wxEXPAND, 0);
// tip line2
m_tip_Insert_material_line2 = new wxStaticText(m_panel_body, wxID_ANY,
_L("Note: if new filament is inserted during printing, the AMS will not automatically read any information until printing is completed."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_Insert_material_line2 = new Label(m_panel_body,
_L("Note: if new filament is inserted during printing, the AMS will not automatically read any information until printing is completed.")
);
m_tip_Insert_material_line2->SetFont(::Label::Body_13);
m_tip_Insert_material_line2->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_Insert_material_line2->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
@ -75,10 +75,9 @@ void AMSSetting::create()
m_sizer_Insert_material_tip_inline->Add(m_tip_Insert_material_line2, 0, wxEXPAND | wxTOP, 8);
// tip line2
m_tip_Insert_material_line3 =
new wxStaticText(m_panel_body, wxID_ANY,
_L("When inserting a new filament, the AMS will not automatically read its information, leaving it blank for you to enter manually."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_Insert_material_line3 = new Label(m_panel_body,
_L("When inserting a new filament, the AMS will not automatically read its information, leaving it blank for you to enter manually.")
);
m_tip_Insert_material_line3->SetFont(::Label::Body_13);
m_tip_Insert_material_line3->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_Insert_material_line3->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
@ -109,18 +108,18 @@ void AMSSetting::create()
// tip line
m_sizer_starting_tip_inline = new wxBoxSizer(wxVERTICAL);
m_tip_starting_line1 = new wxStaticText(m_panel_body, wxID_ANY,
_L("The AMS will automatically read the information of inserted filament on start-up. It will take about 1 minute.The reading process will roll filament spools."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_starting_line1 = new Label(m_panel_body,
_L("The AMS will automatically read the information of inserted filament on start-up. It will take about 1 minute.The reading process will roll filament spools.")
);
m_tip_starting_line1->SetFont(::Label::Body_13);
m_tip_starting_line1->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_starting_line1->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
m_tip_starting_line1->Wrap(AMS_SETTING_BODY_WIDTH);
m_sizer_starting_tip_inline->Add(m_tip_starting_line1, 0, wxEXPAND, 0);
m_tip_starting_line2 = new wxStaticText(m_panel_body, wxID_ANY,
_L("The AMS will not automatically read information from inserted filament during startup and will continue to use the information recorded before the last shutdown."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_starting_line2 = new Label(m_panel_body,
_L("The AMS will not automatically read information from inserted filament during startup and will continue to use the information recorded before the last shutdown.")
);
m_tip_starting_line2->SetFont(::Label::Body_13);
m_tip_starting_line2->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_starting_line2->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
@ -148,9 +147,9 @@ void AMSSetting::create()
// tip line
m_sizer_remain_inline = new wxBoxSizer(wxVERTICAL);
m_tip_remain_line1 = new wxStaticText(m_panel_body, wxID_ANY,
_L("The AMS will estimate Bambu filament's remaining capacity after the filament info is updated. During printing, remaining capacity will be updated automatically."),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_remain_line1 = new Label(m_panel_body,
_L("The AMS will estimate Bambu filament's remaining capacity after the filament info is updated. During printing, remaining capacity will be updated automatically.")
);
m_tip_remain_line1->SetFont(::Label::Body_13);
m_tip_remain_line1->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_remain_line1->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
@ -178,9 +177,9 @@ void AMSSetting::create()
// tip line
m_sizer_switch_filament_inline = new wxBoxSizer(wxVERTICAL);
m_tip_switch_filament_line1 = new wxStaticText(m_panel_body, wxID_ANY,
_L("AMS will continue to another spool with the same properties of filament automatically when current filament runs out"),
wxDefaultPosition, wxDefaultSize, 0);
m_tip_switch_filament_line1 = new Label(m_panel_body,
_L("AMS will continue to another spool with the same properties of filament automatically when current filament runs out")
);
m_tip_switch_filament_line1->SetFont(::Label::Body_13);
m_tip_switch_filament_line1->SetForegroundColour(AMS_SETTING_GREY700);
m_tip_switch_filament_line1->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));

View file

@ -49,22 +49,22 @@ protected:
wxPanel * m_panel_body;
CheckBox * m_checkbox_Insert_material_auto_read;
wxStaticText *m_title_Insert_material_auto_read;
wxStaticText *m_tip_Insert_material_line1;
wxStaticText *m_tip_Insert_material_line2;
wxStaticText *m_tip_Insert_material_line3;
Label* m_tip_Insert_material_line1;
Label* m_tip_Insert_material_line2;
Label* m_tip_Insert_material_line3;
CheckBox * m_checkbox_starting_auto_read;
wxStaticText *m_title_starting_auto_read;
wxStaticText *m_tip_starting_line1;
wxStaticText *m_tip_starting_line2;
Label* m_tip_starting_line1;
Label* m_tip_starting_line2;
CheckBox * m_checkbox_remain;
wxStaticText *m_title_remain;
wxStaticText *m_tip_remain_line1;
Label* m_tip_remain_line1;
CheckBox* m_checkbox_switch_filament;
wxStaticText* m_title_switch_filament;
wxStaticText* m_tip_switch_filament_line1;
Label* m_tip_switch_filament_line1;
wxStaticText *m_tip_ams_img;
Button * m_button_auto_demarcate;

View file

@ -257,6 +257,13 @@ AboutDialog::AboutDialog()
version->SetBackgroundColour(wxColour("#009688"));
vesizer->Add(version, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
#if BBL_INTERNAL_TESTING
wxString build_time = wxString::Format("Build Time: %s", std::string(SLIC3R_BUILD_TIME));
wxStaticText* build_time_text = new wxStaticText(this, wxID_ANY, build_time, wxDefaultPosition, wxDefaultSize);
build_time_text->SetForegroundColour(wxColour("#FFFFFE"));
build_time_text->SetBackgroundColour(wxColour("#00AF42"));
vesizer->Add(build_time_text, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
#endif
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));
}

View file

@ -207,11 +207,11 @@ void MaterialItem::doRender(wxDC &dc)
}
AmsMapingPopup::AmsMapingPopup(wxWindow *parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
: PopupWindow(parent, wxBORDER_NONE)
{
SetSize(wxSize(FromDIP(300), -1));
SetMinSize(wxSize(FromDIP(300), -1));
SetMaxSize(wxSize(FromDIP(300), -1));
SetSize(wxSize(FromDIP(252), -1));
SetMinSize(wxSize(FromDIP(252), -1));
SetMaxSize(wxSize(FromDIP(252), -1));
Bind(wxEVT_PAINT, &AmsMapingPopup::paintEvent, this);
@ -243,21 +243,36 @@ void MaterialItem::doRender(wxDC &dc)
title_panel->Fit();
m_sizer_list = new wxBoxSizer(wxVERTICAL);
for (auto i = 0; i < AMS_TOTAL_COUNT; i++) {
auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
/*auto ams_mapping_item_container = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("ams_mapping_container", this, 78), wxDefaultPosition,
wxSize(FromDIP(230), FromDIP(78)), 0);*/
auto ams_mapping_item_container = new MappingContainer(this);
ams_mapping_item_container->SetSizer(sizer_mapping_list);
ams_mapping_item_container->Layout();
//ams_mapping_item_container->Hide();
m_amsmapping_container_sizer_list.push_back(sizer_mapping_list);
m_amsmapping_container_list.push_back(ams_mapping_item_container);
m_sizer_list->Add(ams_mapping_item_container, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, FromDIP(5));
}
m_warning_text = new wxStaticText(this, wxID_ANY, wxEmptyString);
m_warning_text->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00));
m_warning_text->SetFont(::Label::Body_12);
auto cant_not_match_tip = _L("Note: Only the AMS slots loaded with the same material type can be selected.");
m_warning_text->SetLabel(format_text(cant_not_match_tip));
m_warning_text->SetMinSize(wxSize(FromDIP(280), FromDIP(-1)));
m_warning_text->Wrap(FromDIP(280));
m_warning_text->SetMinSize(wxSize(FromDIP(248), FromDIP(-1)));
m_warning_text->Wrap(FromDIP(248));
m_sizer_main->Add(title_panel, 0, wxEXPAND | wxALL, FromDIP(2));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_main->Add(m_sizer_list, 0, wxEXPAND | wxALL, FromDIP(0));
m_sizer_main->Add(m_warning_text, 0, wxEXPAND | wxALL, FromDIP(10));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_main->Add(m_warning_text, 0, wxEXPAND | wxALL, FromDIP(6));
SetSizer(m_sizer_main);
Layout();
Fit();
}
wxString AmsMapingPopup::format_text(wxString &m_msg)
@ -315,15 +330,29 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
{
m_has_unmatch_filament = false;
m_mapping_item_list.clear();
if (m_amsmapping_sizer_list.size() > 0) {
for (wxBoxSizer *bz : m_amsmapping_sizer_list) { bz->Clear(true); }
m_amsmapping_sizer_list.clear();
//m_mapping_item_list.clear();
for (auto& ams_container : m_amsmapping_container_list) {
ams_container->Hide();
}
for (wxWindow *mitem : m_mapping_item_list) {
mitem->Destroy();
mitem = nullptr;
}
m_mapping_item_list.clear();
if (m_amsmapping_container_sizer_list.size() > 0) {
for (wxBoxSizer *siz : m_amsmapping_container_sizer_list) {
siz->Clear(true);
}
}
std::map<std::string, Ams *>::iterator ams_iter;
BOOST_LOG_TRIVIAL(trace) << "ams_mapping total count " << amsList.size();
int m_amsmapping_container_list_index = 0;
for (ams_iter = amsList.begin(); ams_iter != amsList.end(); ams_iter++) {
@ -355,7 +384,10 @@ void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
tray_datas.push_back(td);
}
add_ams_mapping(tray_datas);
m_amsmapping_container_list[m_amsmapping_container_list_index]->Show();
add_ams_mapping(tray_datas, m_amsmapping_container_list[m_amsmapping_container_list_index], m_amsmapping_container_sizer_list[m_amsmapping_container_list_index]);
m_amsmapping_container_list_index++;
}
@ -406,40 +438,38 @@ std::vector<TrayData> AmsMapingPopup::parse_ams_mapping(std::map<std::string, Am
return m_tray_data;
}
void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data, wxWindow* container, wxBoxSizer* sizer)
{
auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(0,0,0,wxLEFT,FromDIP(6));
for (auto i = 0; i < tray_data.size(); i++) {
wxBoxSizer *sizer_mapping_item = new wxBoxSizer(wxVERTICAL);
// set number
auto number = new wxStaticText(this, wxID_ANY, wxGetApp().transition_tridid(tray_data[i].id), wxDefaultPosition, wxDefaultSize, 0);
/* auto number = new wxStaticText(this, wxID_ANY, wxGetApp().transition_tridid(tray_data[i].id), wxDefaultPosition, wxDefaultSize, 0);
number->SetFont(::Label::Body_13);
number->SetForegroundColour(wxColour(0X6B, 0X6B, 0X6B));
number->Wrap(-1);
number->Wrap(-1);*/
// set button
MappingItem *m_filament_name = new MappingItem(this);
m_filament_name->SetSize(wxSize(FromDIP(62), FromDIP(22)));
m_filament_name->SetMinSize(wxSize(FromDIP(62), FromDIP(22)));
m_filament_name->SetMaxSize(wxSize(FromDIP(62), FromDIP(22)));
//m_filament_name->SetCornerRadius(5);
m_filament_name->SetFont(::Label::Body_12);
m_mapping_item_list.push_back(m_filament_name);
MappingItem *m_mapping_item = new MappingItem(container);
m_mapping_item->SetSize(wxSize(FromDIP(68 * 0.7), FromDIP(100 * 0.6)));
m_mapping_item->SetMinSize(wxSize(FromDIP(68 * 0.7), FromDIP(100 * 0.6)));
m_mapping_item->SetMaxSize(wxSize(FromDIP(68 * 0.7), FromDIP(100 * 0.6)));
//m_mapping_item->SetCornerRadius(5);
m_mapping_item->SetFont(::Label::Body_12);
m_mapping_item_list.push_back(m_mapping_item);
if (tray_data[i].type == NORMAL) {
if (is_match_material(tray_data[i].filament_type)) {
m_filament_name->set_data(tray_data[i].colour, tray_data[i].name, tray_data[i]);
m_mapping_item->set_data(tray_data[i].colour, tray_data[i].name, tray_data[i]);
} else {
m_filament_name->set_data(wxColour(0xEE,0xEE,0xEE), tray_data[i].name, tray_data[i], true);
m_mapping_item->set_data(wxColour(0xEE,0xEE,0xEE), tray_data[i].name, tray_data[i], true);
m_has_unmatch_filament = true;
}
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
m_mapping_item->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_mapping_item](wxMouseEvent &e) {
if (!is_match_material(tray_data[i].filament_type)) return;
m_filament_name->send_event(m_current_filament_id);
m_mapping_item->send_event(m_current_filament_id);
Dismiss();
});
}
@ -447,29 +477,30 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
// temp
if (tray_data[i].type == EMPTY) {
m_filament_name->set_data(wxColour(0xCE, 0xCE, 0xCE), "-", tray_data[i]);
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
m_filament_name->send_event(m_current_filament_id);
m_mapping_item->set_data(wxColour(0xCE, 0xCE, 0xCE), "-", tray_data[i]);
m_mapping_item->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_mapping_item](wxMouseEvent &e) {
m_mapping_item->send_event(m_current_filament_id);
Dismiss();
});
}
// third party
if (tray_data[i].type == THIRD) {
m_filament_name->set_data(wxColour(0xCE, 0xCE, 0xCE), "?", tray_data[i]);
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
m_filament_name->send_event(m_current_filament_id);
m_mapping_item->set_data(wxColour(0xCE, 0xCE, 0xCE), "?", tray_data[i]);
m_mapping_item->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_mapping_item](wxMouseEvent &e) {
m_mapping_item->send_event(m_current_filament_id);
Dismiss();
});
}
sizer_mapping_item->Add(number, 0, wxALIGN_CENTER_HORIZONTAL, 0);
sizer_mapping_item->Add(m_filament_name, 0, wxALIGN_CENTER_HORIZONTAL, 0);
sizer_mapping_list->Add(sizer_mapping_item, 0, wxALL, FromDIP(5));
m_amsmapping_sizer_list.push_back(sizer_mapping_list);
//sizer_mapping_item->Add(number, 0, wxALIGN_CENTER_HORIZONTAL, 0);
//sizer_mapping_item->Add(m_mapping_item, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_mapping_item->set_tray_index(wxGetApp().transition_tridid(tray_data[i].id));
sizer->Add(0,0,0,wxRIGHT,FromDIP(6));
sizer->Add(m_mapping_item, 0, wxTOP, FromDIP(1));
}
m_sizer_list->Add(sizer_mapping_list, 0, wxALIGN_CENTER_HORIZONTAL, 0);
}
void AmsMapingPopup::OnDismiss()
@ -479,7 +510,7 @@ void AmsMapingPopup::OnDismiss()
bool AmsMapingPopup::ProcessLeftDown(wxMouseEvent &event)
{
return wxPopupTransientWindow::ProcessLeftDown(event);
return PopupWindow::ProcessLeftDown(event);
}
void AmsMapingPopup::paintEvent(wxPaintEvent &evt)
@ -514,7 +545,7 @@ void MappingItem::send_event(int fliament_id)
wxString param = wxString::Format("%d|%d|%d|%s|%d", m_coloul.Red(), m_coloul.Green(), m_coloul.Blue(), number, fliament_id);
event.SetString(param);
event.SetEventObject(this->GetParent()->GetParent());
wxPostEvent(this->GetParent()->GetParent(), event);
wxPostEvent(this->GetParent()->GetParent()->GetParent(), event);
}
void MappingItem::msw_rescale()
@ -551,7 +582,7 @@ void MappingItem::render(wxDC &dc)
#endif
// materials name
dc.SetFont(::Label::Body_12);
dc.SetFont(::Label::Head_13);
auto txt_colour = m_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
txt_colour = m_unmatch ? wxColour(0xCE, 0xCE, 0xCE) : txt_colour;
@ -563,8 +594,15 @@ void MappingItem::render(wxDC &dc)
m_name = m_name.substr(0, 3) + "." + m_name.substr(m_name.length() - 1);
}*/
auto txt_size = dc.GetTextExtent(m_name);
dc.DrawText(m_name, wxPoint((GetSize().x - txt_size.x) / 2, (GetSize().y - txt_size.y) / 2));
auto txt_size = dc.GetTextExtent(m_tray_index);
auto top = (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2 + FromDIP(8);
dc.DrawText(m_tray_index, wxPoint((GetSize().x - txt_size.x) / 2, top));
top += txt_size.y + FromDIP(7);
dc.SetFont(::Label::Body_12);
txt_size = dc.GetTextExtent(m_name);
dc.DrawText(m_name, wxPoint((GetSize().x - txt_size.x) / 2, top));
}
void MappingItem::set_data(wxColour colour, wxString name, TrayData data, bool unmatch)
@ -582,21 +620,32 @@ void MappingItem::doRender(wxDC &dc)
{
dc.SetPen(m_coloul);
dc.SetBrush(wxBrush(m_coloul));
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y,5);
if (m_coloul == *wxWHITE) {
dc.SetPen(wxPen(wxColour(0xAC, 0xAC, 0xAC),1));
#ifdef __APPLE__
dc.DrawRoundedRectangle(1, 1, GetSize().x - 1, GetSize().y - 1, 5);
#else
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 5);
#endif // __APPLE__
dc.DrawRectangle(0, (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2, MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y);
}
// if (m_coloul == *wxWHITE) {
// dc.SetPen(wxPen(wxColour(0xAC, 0xAC, 0xAC), 1));
//#ifdef __APPLE__
// dc.DrawRectangle(1, 1, GetSize().x - 1, GetSize().y - 1);
//#else
// dc.DrawRectangle(0, 0, tray_size.x, tray_size.y);
//#endif // __APPLE__
// }
wxColour side_colour = wxColour(0xE4E4E4);
dc.SetPen(side_colour);
dc.SetBrush(wxBrush(side_colour));
#ifdef __APPLE__
dc.DrawRectangle(0, 0, FromDIP(4), GetSize().y);
dc.DrawRectangle(GetSize().x - FromDIP(4), 0, FromDIP(4), GetSize().y);
#else
dc.DrawRectangle(0, 0, FromDIP(4), GetSize().y);
dc.DrawRectangle(GetSize().x - FromDIP(4), 0, FromDIP(4), GetSize().y);
#endif // __APPLE__
}
AmsMapingTipPopup::AmsMapingTipPopup(wxWindow *parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
:PopupWindow(parent, wxBORDER_NONE)
{
SetBackgroundColour(*wxWHITE);
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
@ -696,11 +745,11 @@ void AmsMapingTipPopup::paintEvent(wxPaintEvent &evt)
void AmsMapingTipPopup::OnDismiss() {}
bool AmsMapingTipPopup::ProcessLeftDown(wxMouseEvent &event) {
return wxPopupTransientWindow::ProcessLeftDown(event); }
return PopupWindow::ProcessLeftDown(event); }
AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
:PopupWindow(parent, wxBORDER_NONE)
{
SetBackgroundColour(*wxWHITE);
@ -727,7 +776,7 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
m_staticText1->SetFont(::Label::Head_13);
m_staticText2 = new Label(this, _L("Green means that AMS humidity is normal, orange represent humidity is high, red represent humidity is too high.(Hygrometer: lower the better, The bars: higher the better)"));
m_staticText2 = new Label(this, _L("Green means that AMS humidity is normal, orange represent humidity is high, red represent humidity is too high.(Hygrometer: lower the better.)"));
m_staticText2->SetFont(::Label::Body_13);
m_staticText2->SetSize(wxSize(FromDIP(360), -1));
m_staticText2->SetMinSize(wxSize(FromDIP(360), -1));
@ -740,7 +789,7 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
m_staticText3->SetFont(::Label::Head_13);
m_staticText4 = new Label(this, _L("A desiccant status lower than two bars indicates that desiccant may be inactive. Please change the desiccant. (Higher is better)"));
m_staticText4 = new Label(this, _L("A desiccant status lower than two bars indicates that desiccant may be inactive. Please change the desiccant.(The bars: higher the better.)"));
m_staticText4->SetFont(::Label::Body_13);
m_staticText4->SetSize(wxSize(FromDIP(360), -1));
m_staticText4->SetMinSize(wxSize(FromDIP(360), -1));
@ -766,9 +815,9 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent)
main_sizer->Add(m_staticText_note, 0, wxALL | wxLEFT | wxRIGHT, 34);
m_button_confirm = new Button(this, _L("OK"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_confirm->SetBackgroundColor(btn_bg_green);
m_button_confirm->SetBorderColor(wxColour(0, 150, 136));
m_button_confirm->SetBorderColor(wxColour(0, 174, 66));
m_button_confirm->SetTextColor(wxColour(0xFFFFFE));
m_button_confirm->SetSize(wxSize(FromDIP(72), FromDIP(24)));
m_button_confirm->SetMinSize(wxSize(FromDIP(72), FromDIP(24)));
@ -814,11 +863,11 @@ void AmsHumidityTipPopup::paintEvent(wxPaintEvent& evt)
void AmsHumidityTipPopup::OnDismiss() {}
bool AmsHumidityTipPopup::ProcessLeftDown(wxMouseEvent& event) {
return wxPopupTransientWindow::ProcessLeftDown(event);
return PopupWindow::ProcessLeftDown(event);
}
AmsTutorialPopup::AmsTutorialPopup(wxWindow* parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
:PopupWindow(parent, wxBORDER_NONE)
{
Bind(wxEVT_PAINT, &AmsTutorialPopup::paintEvent, this);
SetBackgroundColour(*wxWHITE);
@ -916,12 +965,12 @@ void AmsTutorialPopup::paintEvent(wxPaintEvent& evt)
void AmsTutorialPopup::OnDismiss() {}
bool AmsTutorialPopup::ProcessLeftDown(wxMouseEvent& event) {
return wxPopupTransientWindow::ProcessLeftDown(event);
return PopupWindow::ProcessLeftDown(event);
}
AmsIntroducePopup::AmsIntroducePopup(wxWindow* parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
:PopupWindow(parent, wxBORDER_NONE)
{
Bind(wxEVT_PAINT, &AmsIntroducePopup::paintEvent, this);
SetBackgroundColour(*wxWHITE);
@ -1001,8 +1050,60 @@ void AmsIntroducePopup::paintEvent(wxPaintEvent& evt)
void AmsIntroducePopup::OnDismiss() {}
bool AmsIntroducePopup::ProcessLeftDown(wxMouseEvent& event) {
return wxPopupTransientWindow::ProcessLeftDown(event);
return PopupWindow::ProcessLeftDown(event);
}
MappingContainer::MappingContainer(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
Bind(wxEVT_PAINT, &MappingContainer::paintEvent, this);
ams_mapping_item_container = create_scaled_bitmap("ams_mapping_container", this, 78);
SetMinSize(wxSize(FromDIP(230), FromDIP(78)));
SetMaxSize(wxSize(FromDIP(230), FromDIP(78)));
}
MappingContainer::~MappingContainer()
{
}
void MappingContainer::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
render(dc);
}
void MappingContainer::render(wxDC& dc)
{
#ifdef __WXMSW__
wxSize size = GetSize();
wxMemoryDC memdc;
wxBitmap bmp(size.x, size.y);
memdc.SelectObject(bmp);
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
{
wxGCDC dc2(memdc);
doRender(dc2);
}
memdc.SelectObject(wxNullBitmap);
dc.DrawBitmap(bmp, 0, 0);
#else
doRender(dc);
#endif
}
void MappingContainer::doRender(wxDC& dc)
{
dc.DrawBitmap(ams_mapping_item_container, 0, 0);
}
}} // namespace Slic3r::GUI

View file

@ -34,6 +34,7 @@
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/ScrolledWindow.hpp"
#include "Widgets/PopupWindow.hpp"
#include <wx/simplebook.h>
#include <wx/hashmap.h>
@ -41,6 +42,7 @@ namespace Slic3r { namespace GUI {
#define MATERIAL_ITEM_SIZE wxSize(FromDIP(64), FromDIP(34))
#define MATERIAL_ITEM_REAL_SIZE wxSize(FromDIP(62), FromDIP(32))
#define MAPPING_ITEM_REAL_SIZE wxSize(FromDIP(48), FromDIP(45))
#define AMS_TOTAL_COUNT 4
enum TrayType {
@ -95,8 +97,11 @@ public:
MappingItem(wxWindow *parent);
~MappingItem();
void update_data(TrayData data);
void send_event(int fliament_id);
void update_data(TrayData data);
void send_event(int fliament_id);
void set_tray_index(wxString t_index) {m_tray_index = t_index;};
wxString m_tray_index;
wxColour m_coloul;
wxString m_name;
TrayData m_tray_data;
@ -109,7 +114,18 @@ public:
void doRender(wxDC &dc);
};
class AmsMapingPopup : public wxPopupTransientWindow
class MappingContainer : public wxPanel
{
public:
wxBitmap ams_mapping_item_container;
MappingContainer(wxWindow* parent);
~MappingContainer();
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
};
class AmsMapingPopup : public PopupWindow
{
public:
AmsMapingPopup(wxWindow *parent);
@ -118,7 +134,8 @@ public:
wxStaticText * m_warning_text{nullptr};
std::vector<std::string> m_materials_list;
std::vector<wxBoxSizer*> m_amsmapping_sizer_list;
std::vector<wxBoxSizer*> m_amsmapping_container_sizer_list;
std::vector<wxWindow*> m_amsmapping_container_list;
std::vector<MappingItem*> m_mapping_item_list;
bool m_has_unmatch_filament {false};
@ -130,7 +147,7 @@ public:
void update_materials_list(std::vector<std::string> list);
void set_tag_texture(std::string texture);
void update_ams_data(std::map<std::string, Ams *> amsList);
void add_ams_mapping(std::vector<TrayData> tray_data);
void add_ams_mapping(std::vector<TrayData> tray_data, wxWindow* container, wxBoxSizer* sizer);
void set_current_filament_id(int id){m_current_filament_id = id;};
int get_current_filament_id(){return m_current_filament_id;};
bool is_match_material(std::string material);
@ -141,7 +158,7 @@ public:
std::vector<TrayData> parse_ams_mapping(std::map<std::string, Ams*> amsList);
};
class AmsMapingTipPopup : public wxPopupTransientWindow
class AmsMapingTipPopup : public PopupWindow
{
public:
AmsMapingTipPopup(wxWindow *parent);
@ -161,7 +178,7 @@ public:
wxStaticText * m_tip_disable_ams;
};
class AmsHumidityTipPopup : public wxPopupTransientWindow
class AmsHumidityTipPopup : public PopupWindow
{
public:
AmsHumidityTipPopup(wxWindow* parent);
@ -181,7 +198,7 @@ public:
Button* m_button_confirm;
};
class AmsTutorialPopup : public wxPopupTransientWindow
class AmsTutorialPopup : public PopupWindow
{
public:
Label* text_title;
@ -203,7 +220,7 @@ public:
};
class AmsIntroducePopup : public wxPopupTransientWindow
class AmsIntroducePopup : public PopupWindow
{
public:
bool is_enable_ams = {false};

View file

@ -492,6 +492,7 @@ void AuFile::on_set_cover()
thumbnail_img.SaveFile(encode_path(middle_img_path.c_str()));
}
wxGetApp().plater()->set_plater_dirty(true);
auto evt = wxCommandEvent(EVT_AUXILIARY_UPDATE_COVER);
evt.SetString(s_default_folders[m_type]);
evt.SetEventObject(m_parent);
@ -1099,26 +1100,26 @@ void AuxiliaryPanel::update_all_cover()
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *m_sizer_designer = new wxBoxSizer(wxHORIZONTAL);
auto m_text_designer = new wxStaticText(this, wxID_ANY, _L("Author"), wxDefaultPosition, wxSize(120, -1), 0);
auto m_text_designer = new wxStaticText(this, wxID_ANY, _L("Author"), wxDefaultPosition, wxSize(180, -1), 0);
m_text_designer->Wrap(-1);
m_text_designer->SetForegroundColour(*wxBLACK);
m_sizer_designer->Add(m_text_designer, 0, wxALIGN_CENTER, 0);
m_input_designer = new ::TextInput(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(450), FromDIP(30)), wxTE_PROCESS_ENTER);
m_input_designer->GetTextCtrl()->SetFont(::Label::Body_14);
m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_sizer_designer->Add(m_input_designer, 0, wxALIGN_CENTER, 0);
wxBoxSizer *m_sizer_model_name = new wxBoxSizer(wxHORIZONTAL);
auto m_text_model_name = new wxStaticText(this, wxID_ANY, _L("Model Name"), wxDefaultPosition, wxSize(120, -1), 0);
auto m_text_model_name = new wxStaticText(this, wxID_ANY, _L("Model Name"), wxDefaultPosition, wxSize(180, -1), 0);
m_text_model_name->SetForegroundColour(*wxBLACK);
m_text_model_name->Wrap(-1);
m_sizer_model_name->Add(m_text_model_name, 0, wxALIGN_CENTER, 0);
m_imput_model_name = new ::TextInput(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition,wxSize(FromDIP(450),FromDIP(30)), wxTE_PROCESS_ENTER);
m_imput_model_name->GetTextCtrl()->SetFont(::Label::Body_14);
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_sizer_model_name->Add(m_imput_model_name, 0, wxALIGN_CENTER, 0);
/*
@ -1224,8 +1225,8 @@ void DesignerPanel::update_info()
void DesignerPanel::msw_rescale()
{
m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
}
}} // namespace Slic3r::GUI

View file

@ -119,7 +119,8 @@ void BBLStatusBarSend::set_range(int val)
void BBLStatusBarSend::clear_percent()
{
set_percent_text(wxEmptyString);
//set_percent_text(wxEmptyString);
m_cancelbutton->Hide();
}
void BBLStatusBarSend::show_progress(bool show)
@ -235,6 +236,7 @@ void BBLStatusBarSend::set_status_text(const wxString& txt)
wxString str;
format_text(m_status_text, m_self->FromDIP(280), txt, str);
m_status_text->SetLabelText(str);
m_self->Layout();
//if (is_english_text(str)) m_status_text->Wrap(m_self->FromDIP(280));
}
@ -279,6 +281,7 @@ bool BBLStatusBarSend::update_status(wxString &msg, bool &was_cancel, int percen
void BBLStatusBarSend::reset()
{
m_cancelbutton->Show();
set_status_text("");
m_was_cancelled = false;
set_progress(0);

View file

@ -263,7 +263,7 @@ void BBLTopbar::Init(wxFrame* parent)
m_publish_disable_bitmap = create_scaled_bitmap("topbar_publish_disable", nullptr, TOPBAR_ICON_SIZE);
m_publish_item->SetDisabledBitmap(m_publish_disable_bitmap);
this->EnableTool(m_publish_item->GetId(), false);
this->AddSpacer(FromDIP(12));
this->AddSpacer(FromDIP(4));
/*wxBitmap model_store_bitmap = create_scaled_bitmap("topbar_store", nullptr, TOPBAR_ICON_SIZE);
m_model_store_item = this->AddTool(ID_MODEL_STORE, "", model_store_bitmap);
@ -271,12 +271,12 @@ void BBLTopbar::Init(wxFrame* parent)
*/
//this->AddSeparator();
this->AddSpacer(FromDIP(6));
this->AddSpacer(FromDIP(4));
wxBitmap iconize_bitmap = create_scaled_bitmap("topbar_min", nullptr, TOPBAR_ICON_SIZE);
wxAuiToolBarItem* iconize_btn = this->AddTool(wxID_ICONIZE_FRAME, "", iconize_bitmap);
this->AddSpacer(FromDIP(6));
this->AddSpacer(FromDIP(4));
maximize_bitmap = create_scaled_bitmap("topbar_max", nullptr, TOPBAR_ICON_SIZE);
window_bitmap = create_scaled_bitmap("topbar_win", nullptr, TOPBAR_ICON_SIZE);
@ -287,7 +287,7 @@ void BBLTopbar::Init(wxFrame* parent)
maximize_btn = this->AddTool(wxID_MAXIMIZE_FRAME, "", maximize_bitmap);
}
this->AddSpacer(FromDIP(6));
this->AddSpacer(FromDIP(4));
wxBitmap close_bitmap = create_scaled_bitmap("topbar_close", nullptr, TOPBAR_ICON_SIZE);
wxAuiToolBarItem* close_btn = this->AddTool(wxID_CLOSE_FRAME, "", close_bitmap);

View file

@ -185,14 +185,9 @@ std::string BackgroundSlicingProcess::output_filepath_for_project(const boost::f
// from the G-code generator.
void BackgroundSlicingProcess::process_fff()
{
assert(m_print == m_fff_print);
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
m_fff_print->is_BBL_printer() =
preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(
&preset_bundle);
assert(m_print == m_fff_print);
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
m_fff_print->is_BBL_printer() = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
//BBS: add the logic to process from an existed gcode file
if (m_print->finished()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: skip slicing, to process previous gcode file")%__LINE__;

View file

@ -16,6 +16,7 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/Bonjour.hpp"
#include "Widgets/Button.hpp"
namespace Slic3r {
@ -60,6 +61,8 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
, timer_state(0)
, tech(tech)
{
SetBackgroundColour(*wxWHITE);
const int em = GUI::wxGetApp().em_unit();
list->SetMinSize(wxSize(80 * em, 30 * em));
@ -78,10 +81,39 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
vsizer->Add(list, 1, wxEXPAND | wxALL, em);
wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
button_sizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, em);
button_sizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, em);
// ^ Note: The Ok/Cancel labels are translated by wxWidgets
auto button_sizer = 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>(wxColour(0, 174, 66), 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(*wxWHITE);
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](auto &e) { this->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](auto &e) { this->EndModal(wxID_CANCEL); });
button_sizer->AddStretchSpacer();
button_sizer->Add(m_button_ok, 0, wxALL, FromDIP(5));
button_sizer->Add(m_button_cancel, 0, wxALL, FromDIP(5));
vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
SetSizerAndFit(vsizer);

View file

@ -33,7 +33,7 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
auto body_panel = new wxPanel(this, wxID_ANY);
body_panel->SetBackgroundColour(*wxWHITE);
auto cali_left_panel = new StaticBox(body_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(303), FromDIP(243)));
auto cali_left_panel = new StaticBox(body_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(303), -1));
cali_left_panel->SetBackgroundColor(BG_COLOR);
cali_left_panel->SetBorderColor(BG_COLOR);
@ -73,9 +73,7 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
cali_left_sizer->Add(0, 0, 0, wxTOP, FromDIP(5));
auto cali_left_text_body =
new wxStaticText(cali_left_panel, wxID_ANY,
_L("The calibration program detects the status of your device automatically to minimize deviation.\nIt keeps the device performing optimally."),
wxDefaultPosition, wxSize(FromDIP(260), -1), 0);
new Label(cali_left_panel, _L("The calibration program detects the status of your device automatically to minimize deviation.\nIt keeps the device performing optimally."));
cali_left_text_body->Wrap(FromDIP(260));
cali_left_text_body->SetForegroundColour(wxColour(0x6B, 0x6B, 0x6B));
cali_left_text_body->SetBackgroundColour(BG_COLOR);
@ -174,7 +172,6 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
Fit();
m_calibration_btn->Bind(wxEVT_LEFT_DOWN, &CalibrationDialog::on_start_calibration, this);
wxGetApp().UpdateDlgDarkUI(this);
}
CalibrationDialog::~CalibrationDialog() {}
@ -296,7 +293,10 @@ void CalibrationDialog::update_machine_obj(MachineObject *obj) { m_obj = obj; }
bool CalibrationDialog::Show(bool show)
{
if (show) { CentreOnParent(); }
if (show) {
wxGetApp().UpdateDlgDarkUI(this);
CentreOnParent();
}
return DPIDialog::Show(show);
}

View file

@ -12,9 +12,9 @@
namespace Slic3r {
namespace GUI {
wxIMPLEMENT_CLASS(CameraPopup, wxPopupTransientWindow);
wxIMPLEMENT_CLASS(CameraPopup, PopupWindow);
wxBEGIN_EVENT_TABLE(CameraPopup, wxPopupTransientWindow)
wxBEGIN_EVENT_TABLE(CameraPopup, PopupWindow)
EVT_MOUSE_EVENTS(CameraPopup::OnMouse )
EVT_SIZE(CameraPopup::OnSize)
EVT_SET_FOCUS(CameraPopup::OnSetFocus )
@ -24,10 +24,12 @@ wxEND_EVENT_TABLE()
wxDEFINE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
wxDEFINE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
#define CAMERAPOPUP_CLICK_INTERVAL 20
const wxColour TEXT_COL = wxColour(43, 52, 54);
CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
: wxPopupTransientWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS),
: PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS),
m_obj(obj)
{
#ifdef __WINDOWS__
@ -84,10 +86,26 @@ CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
main_sizer->Add(top_sizer, 0, wxALL, FromDIP(10));
auto url = wxString::Format(L"https://wiki.bambulab.com/%s/software/bambu-studio/virtual-camera", L"en");
vcamera_guide_link = new wxHyperlinkCtrl(m_panel, wxID_ANY, _L("Show \"Live Video\" guide page."),
url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
auto text = _L("Show \"Live Video\" guide page.");
wxBoxSizer* link_sizer = new wxBoxSizer(wxVERTICAL);
vcamera_guide_link = new Label(m_panel, text);
vcamera_guide_link->Wrap(-1);
vcamera_guide_link->SetForegroundColour(wxColour(0x1F, 0x8E, 0xEA));
auto text_size = vcamera_guide_link->GetTextExtent(text);
vcamera_guide_link->Bind(wxEVT_LEFT_DOWN, [this, url](wxMouseEvent& e) {wxLaunchDefaultBrowser(url); });
link_underline = new wxPanel(m_panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
link_underline->SetBackgroundColour(wxColour(0x1F, 0x8E, 0xEA));
link_underline->SetSize(wxSize(text_size.x, 1));
link_underline->SetMinSize(wxSize(text_size.x, 1));
vcamera_guide_link->Hide();
main_sizer->Add(vcamera_guide_link, 0, wxALL, FromDIP(15));
link_underline->Hide();
link_sizer->Add(vcamera_guide_link, 0, wxALL, 0);
link_sizer->Add(link_underline, 0, wxALL, 0);
main_sizer->Add(link_sizer, 0, wxALL, FromDIP(15));
m_panel->SetSizer(main_sizer);
m_panel->Layout();
@ -105,6 +123,10 @@ CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
m_panel->Bind(wxEVT_LEFT_UP, &CameraPopup::OnLeftUp, this);
#endif //APPLE
this->Bind(wxEVT_TIMER, &CameraPopup::stop_interval, this);
m_interval_timer = new wxTimer();
m_interval_timer->SetOwner(this);
check_func_supported();
wxGetApp().UpdateDarkUIWin(this);
}
@ -141,7 +163,9 @@ void CameraPopup::Popup(wxWindow *WXUNUSED(focus))
wxSize win_size = this->GetSize();
curr_position.x -= win_size.x;
this->SetPosition(curr_position);
wxPopupTransientWindow::Popup();
if (!m_is_in_interval)
PopupWindow::Popup();
}
wxWindow* CameraPopup::create_item_radiobox(wxString title, wxWindow* parent, wxString tooltip, int padding_left)
@ -225,10 +249,12 @@ void CameraPopup::sync_vcamera_state(bool show_vcamera)
if (is_vcamera_show) {
m_switch_vcamera->SetValue(true);
vcamera_guide_link->Show();
link_underline->Show();
}
else {
m_switch_vcamera->SetValue(false);
vcamera_guide_link->Hide();
link_underline->Hide();
}
rescale();
@ -248,12 +274,15 @@ void CameraPopup::check_func_supported()
if (m_obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_CAMERA) && m_obj->has_ipcam) {
m_text_vcamera->Show();
m_switch_vcamera->Show();
if (is_vcamera_show)
if (is_vcamera_show) {
vcamera_guide_link->Show();
link_underline->Show();
}
} else {
m_text_vcamera->Hide();
m_switch_vcamera->Hide();
vcamera_guide_link->Hide();
link_underline->Hide();
}
allow_alter_resolution = (m_obj->is_function_supported(PrinterFunction::FUNC_ALTER_RESOLUTION) && m_obj->has_ipcam);
@ -318,7 +347,7 @@ void CameraPopup::rescale()
m_panel->Layout();
main_sizer->Fit(m_panel);
SetClientSize(m_panel->GetSize());
wxPopupTransientWindow::Update();
PopupWindow::Update();
}
void CameraPopup::OnLeftUp(wxMouseEvent &event)
@ -367,18 +396,31 @@ void CameraPopup::OnLeftUp(wxMouseEvent &event)
}
}
void CameraPopup::start_interval()
{
m_interval_timer->Start(CAMERAPOPUP_CLICK_INTERVAL);
m_is_in_interval = true;
}
void CameraPopup::stop_interval(wxTimerEvent& event)
{
m_is_in_interval = false;
m_interval_timer->Stop();
}
void CameraPopup::OnDismiss() {
wxPopupTransientWindow::OnDismiss();
PopupWindow::OnDismiss();
this->start_interval();
}
bool CameraPopup::ProcessLeftDown(wxMouseEvent &event)
{
return wxPopupTransientWindow::ProcessLeftDown(event);
return PopupWindow::ProcessLeftDown(event);
}
bool CameraPopup::Show(bool show)
{
return wxPopupTransientWindow::Show(show);
return PopupWindow::Show(show);
}
void CameraPopup::OnSize(wxSizeEvent &event)

View file

@ -13,6 +13,7 @@
#include <wx/hyperlink.h>
#include "Widgets/SwitchButton.hpp"
#include "Widgets/RadioBox.hpp"
#include "Widgets/PopupWindow.hpp"
namespace Slic3r {
namespace GUI {
@ -20,13 +21,13 @@ namespace GUI {
wxDECLARE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
wxDECLARE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
class CameraPopup : public wxPopupTransientWindow
class CameraPopup : public PopupWindow
{
public:
CameraPopup(wxWindow *parent, MachineObject* obj = nullptr);
virtual ~CameraPopup() {}
// wxPopupTransientWindow virtual methods are all overridden to log them
// PopupWindow virtual methods are all overridden to log them
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
virtual void OnDismiss() wxOVERRIDE;
virtual bool ProcessLeftDown(wxMouseEvent &event) wxOVERRIDE;
@ -59,6 +60,8 @@ protected:
private:
MachineObject* m_obj { nullptr };
wxTimer* m_interval_timer{nullptr};
bool m_is_in_interval{ false };
wxStaticText* m_text_recording;
SwitchButton* m_switch_recording;
wxStaticText* m_text_vcamera;
@ -70,10 +73,13 @@ private:
std::vector<RadioBox*> resolution_rbtns;
std::vector<wxStaticText*> resolution_texts;
CameraResolution curr_sel_resolution = RESOLUTION_1080P;
wxHyperlinkCtrl* vcamera_guide_link { nullptr };
Label* vcamera_guide_link { nullptr };
wxPanel* link_underline{ nullptr };
bool is_vcamera_show = false;
bool allow_alter_resolution = false;
void start_interval();
void stop_interval(wxTimerEvent& event);
void OnMouse(wxMouseEvent &event);
void OnSize(wxSizeEvent &event);
void OnSetFocus(wxFocusEvent &event);

View file

@ -430,6 +430,19 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
m_support_material_overhangs_queried = false;
}
if (config->opt_bool("enable_support")) {
auto support_type = config->opt_enum<SupportType>("support_type");
auto support_style = config->opt_enum<SupportMaterialStyle>("support_style");
std::set<int> enum_set_normal = {0, 1, 2};
std::set<int> enum_set_tree = {0, 3, 4, 5};
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
if (set.find(support_style) == set.end()) {
DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("support_style", new ConfigOptionEnum<SupportMaterialStyle>(smsDefault));
apply(config, &new_conf);
}
}
if (config->option<ConfigOptionPercent>("sparse_infill_density")->value == 100) {
std::string sparse_infill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->serialize();
const auto &top_fill_pattern_values = config->def()->get("top_surface_pattern")->enum_values;
@ -480,6 +493,17 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
}
}
}
if (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject && config->opt_int("skirt_height") > 1 && config->opt_int("skirt_loops") > 0) {
const wxString msg_text = _(L("While printing by Object, the extruder may collide skirt.\nThus, reset the skirt layer to 1 to avoid that."));
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *config;
is_msg_dlg_already_exist = true;
dialog.ShowModal();
new_conf.set_key_value("skirt_height", new ConfigOptionInt(1));
apply(config, &new_conf);
is_msg_dlg_already_exist = false;
}
}
void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector<std::string> const &keys, std::map<ObjectBase *, ModelConfig *> const &configs)

View file

@ -148,7 +148,7 @@ void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event)
}
}
if (m_obj) {
m_obj->set_access_code(code.ToStdString());
m_obj->set_user_access_code(code.ToStdString());
wxGetApp().getDeviceManager()->set_selected_machine(m_obj->dev_id);
}
EndModal(wxID_OK);

View file

@ -136,6 +136,32 @@ wxColour AmsTray::get_color()
return AmsTray::decode_color(color);
}
void AmsTray::reset()
{
tag_uid = "";
setting_id = "";
filament_setting_id = "";
type = "";
sub_brands = "";
color = "";
weight = "";
diameter = "";
temp = "";
time = "";
bed_temp_type = "";
bed_temp = "";
nozzle_temp_max = "";
nozzle_temp_min = "";
xcam_info = "";
uuid = "";
k = 0.0f;
n = 0.0f;
is_bbl = false;
hold_count = 0;
remain = 0;
}
bool AmsTray::is_tray_info_ready()
{
if (color.empty())
@ -302,6 +328,11 @@ std::string MachineObject::get_printer_thumbnail_img_str()
return "printer_thumbnail";
}
std::string MachineObject::get_ftp_folder()
{
return DeviceManager::get_ftp_folder(printer_type);
}
void MachineObject::set_access_code(std::string code)
{
this->access_code = code;
@ -518,6 +549,10 @@ Ams *MachineObject::get_curr_Ams()
AmsTray *MachineObject::get_curr_tray()
{
if (m_tray_now.compare(std::to_string(VIRTUAL_TRAY_ID)) == 0) {
return &vt_tray;
}
Ams* curr_ams = get_curr_Ams();
if (!curr_ams) return nullptr;
@ -639,17 +674,6 @@ bool MachineObject::is_support_ams_mapping_version(std::string module, std::stri
return result;
}
bool MachineObject::is_only_support_cloud_print()
{
auto ap_ver_it = module_vers.find("rv1126");
if (ap_ver_it != module_vers.end()) {
if (ap_ver_it->second.sw_ver > "00.00.12.61") {
return false;
}
}
return true;
}
static float calc_color_distance(wxColour c1, wxColour c2)
{
float lab[2][3];
@ -1229,7 +1253,7 @@ void MachineObject::parse_state_changed_event()
{
// parse calibration done
if (last_mc_print_stage != mc_print_stage) {
if (mc_print_stage == 1 && boost::contains(m_gcode_file, "auto_cali_for_user.gcode")) {
if (mc_print_stage == 1 && boost::contains(m_gcode_file, "auto_cali_for_user")) {
calibration_done = true;
} else {
calibration_done = false;
@ -1322,6 +1346,7 @@ bool MachineObject::is_recording()
void MachineObject::parse_version_func()
{
auto ota_version = module_vers.find("ota");
auto esp32_version = module_vers.find("esp32");
if (printer_type == "BL-P001" ||
printer_type == "BL-P002") {
if (ota_version != module_vers.end()) {
@ -1348,9 +1373,13 @@ void MachineObject::parse_version_func()
}
} else if (printer_type == "C11") {
local_use_ssl = true;
is_cloud_print_only = true;
if (ota_version != module_vers.end()) {
is_support_send_to_sdcard = ota_version->second.sw_ver.compare("01.02.00.00") >= 0;
}
if (esp32_version != module_vers.end()) {
ams_support_auto_switch_filament_flag = esp32_version->second.sw_ver.compare("00.03.11.50") >= 0;
}
}
}
@ -1533,20 +1562,10 @@ int MachineObject::command_ams_switch(int tray_index, int old_temp, int new_temp
std::string gcode = "";
if (tray_index == 255) {
// unload gcode
gcode = "M620 S255\nM104 S250\nG28 X\nG91\nG1 Z3.0 F1200\nG90\n"
"G1 X70 F12000\nG1 Y245\nG1 Y265 F3000\nM109 S250\nG1 X120 F12000\n"
"G1 X20 Y50 F12000\nG1 Y-3\nT255\nM104 S0\nG1 X165 F5000\nG1 Y245\n"
"G91\nG1 Z-3.0 F1200\nG90\nM621 S255\n";
gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode");
} else {
// load gcode
gcode = "M620 S[next_extruder]\nM104 S250\nG28 X\nG91\n\nG1 Z3.0 F1200\nG90\n"
"G1 X70 F12000\nG1 Y245\nG1 Y265 F3000\nM109 S250\nG1 X120 F12000\nG1 X20 Y50 F12000\nG1 Y-3"
"\nT[next_extruder]\nG1 X54 F12000\nG1 Y265\nM400\nM106 P1 S0\nG92 E0\nG1 E40 F200\nM400"
"\nM109 S[new_filament_temp]\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM400\nM106 P1 S0\nG1 X70 F9000"
"\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000\nG1 X70 F6000\nG1 X100 F5000\nG1 X70 F15000"
"\nG1 X100 F5000\nG1 X70 F15000\nG1 X165 F5000\nG1 Y245\nG91\nG1 Z-3.0 F1200\nG90\nM621 S[next_extruder]\n";
// include VIRTUAL_TRAY_ID
gcode = DeviceManager::load_gcode(printer_type, "ams_load.gcode");
boost::replace_all(gcode, "[next_extruder]", std::to_string(tray_index));
boost::replace_all(gcode, "[new_filament_temp]", std::to_string(new_temp));
}
@ -1649,7 +1668,7 @@ int MachineObject::command_ams_select_tray(std::string tray_id)
int MachineObject::command_ams_control(std::string action)
{
//valid actions
if (action == "resume" || action == "reset" || action == "pause") {
if (action == "resume" || action == "reset" || action == "pause" || action == "done") {
json j;
j["print"]["command"] = "ams_control";
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
@ -1840,6 +1859,22 @@ int MachineObject::command_unload_filament()
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
return this->publish_json(j.dump());
}
else if (printer_type == "C11") {
std::string gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode");
if (gcode.empty()) {
return -1;
}
json j;
j["print"]["command"] = "gcode_line";
j["print"]["param"] = gcode;
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
if (m_agent)
j["print"]["user_id"] = m_agent->get_user_id();
return this->publish_json(j.dump());
}
else {
json j;
j["print"]["command"] = "unload_filament";
@ -2040,6 +2075,9 @@ void MachineObject::reset()
last_mc_print_stage = -1;
m_new_ver_list_exist = false;
extruder_axis_status = LOAD;
nozzle_diameter = 0.0f;
vt_tray.reset();
subtask_ = nullptr;
@ -2056,7 +2094,7 @@ int MachineObject::connect(bool is_anonymous)
std::string password;
if (!is_anonymous) {
username = "bblp";
password = access_code;
password = get_access_code();
}
if (m_agent) {
try {
@ -2624,6 +2662,19 @@ int MachineObject::parse_json(std::string payload)
}
#pragma endregion
try {
if (jj.contains("nozzle_diameter")) {
if (jj["nozzle_diameter"].is_number_float()) {
nozzle_diameter = jj["nozzle_diameter"].get<float>();
} else if (jj["nozzle_diameter"].is_string()) {
nozzle_diameter = stof(jj["nozzle_diameter"].get<std::string>().c_str());
}
}
}
catch(...) {
;
}
#pragma region upgrade
try {
if (jj.contains("upgrade_state")) {
@ -2656,29 +2707,36 @@ int MachineObject::parse_json(std::string payload)
this->command_get_version();
});
}
upgrade_display_state = jj["upgrade_state"]["dis_state"].get<int>();
if (upgrade_display_hold_count > 0)
upgrade_display_hold_count--;
else
upgrade_display_state = jj["upgrade_state"]["dis_state"].get<int>();
} else {
//BBS compatibility with old version
if (upgrade_status == "DOWNLOADING"
|| upgrade_status == "FLASHING"
|| upgrade_status == "UPGRADE_REQUEST"
|| upgrade_status == "PRE_FLASH_START"
|| upgrade_status == "PRE_FLASH_SUCCESS") {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingInProgress;
}
else if (upgrade_status == "UPGRADE_SUCCESS"
|| upgrade_status == "DOWNLOAD_FAIL"
|| upgrade_status == "FLASH_FAIL"
|| upgrade_status == "PRE_FLASH_FAIL"
|| upgrade_status == "UPGRADE_FAIL") {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingFinished;
}
if (upgrade_display_hold_count > 0)
upgrade_display_hold_count--;
else {
if (upgrade_new_version) {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingAvaliable;
//BBS compatibility with old version
if (upgrade_status == "DOWNLOADING"
|| upgrade_status == "FLASHING"
|| upgrade_status == "UPGRADE_REQUEST"
|| upgrade_status == "PRE_FLASH_START"
|| upgrade_status == "PRE_FLASH_SUCCESS") {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingInProgress;
}
else if (upgrade_status == "UPGRADE_SUCCESS"
|| upgrade_status == "DOWNLOAD_FAIL"
|| upgrade_status == "FLASH_FAIL"
|| upgrade_status == "PRE_FLASH_FAIL"
|| upgrade_status == "UPGRADE_FAIL") {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingFinished;
}
else {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingUnavaliable;
if (upgrade_new_version) {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingAvaliable;
}
else {
upgrade_display_state = (int)UpgradingDisplayState::UpgradingUnavaliable;
}
}
}
}
@ -3130,6 +3188,89 @@ int MachineObject::parse_json(std::string payload)
vt_tray.n = jj["vt_tray"]["n"].get<float>();
}
ams_support_virtual_tray = true;
if (vt_tray.hold_count > 0) {
vt_tray.hold_count--;
} else {
if (jj["vt_tray"].contains("tag_uid"))
vt_tray.tag_uid = jj["vt_tray"]["tag_uid"].get<std::string>();
else
vt_tray.tag_uid = "0";
if (jj["vt_tray"].contains("tray_info_idx") && jj["vt_tray"].contains("tray_type")) {
vt_tray.setting_id = jj["vt_tray"]["tray_info_idx"].get<std::string>();
std::string type = jj["vt_tray"]["tray_type"].get<std::string>();
if (vt_tray.setting_id == "GFS00") {
vt_tray.type = "PLA-S";
}
else if (vt_tray.setting_id == "GFS01") {
vt_tray.type = "PA-S";
}
else {
vt_tray.type = type;
}
}
else {
vt_tray.setting_id = "";
vt_tray.type = "";
}
if (jj["vt_tray"].contains("tray_sub_brands"))
vt_tray.sub_brands = jj["vt_tray"]["tray_sub_brands"].get<std::string>();
else
vt_tray.sub_brands = "";
if (jj["vt_tray"].contains("tray_weight"))
vt_tray.weight = jj["vt_tray"]["tray_weight"].get<std::string>();
else
vt_tray.weight = "";
if (jj["vt_tray"].contains("tray_diameter"))
vt_tray.diameter = jj["vt_tray"]["tray_diameter"].get<std::string>();
else
vt_tray.diameter = "";
if (jj["vt_tray"].contains("tray_temp"))
vt_tray.temp = jj["vt_tray"]["tray_temp"].get<std::string>();
else
vt_tray.temp = "";
if (jj["vt_tray"].contains("tray_time"))
vt_tray.time = jj["vt_tray"]["tray_time"].get<std::string>();
else
vt_tray.time = "";
if (jj["vt_tray"].contains("bed_temp_type"))
vt_tray.bed_temp_type = jj["vt_tray"]["bed_temp_type"].get<std::string>();
else
vt_tray.bed_temp_type = "";
if (jj["vt_tray"].contains("bed_temp"))
vt_tray.bed_temp = jj["vt_tray"]["bed_temp"].get<std::string>();
else
vt_tray.bed_temp = "";
if (jj["vt_tray"].contains("nozzle_temp_max"))
vt_tray.nozzle_temp_max = jj["vt_tray"]["nozzle_temp_max"].get<std::string>();
else
vt_tray.nozzle_temp_max = "";
if (jj["vt_tray"].contains("nozzle_temp_min"))
vt_tray.nozzle_temp_min = jj["vt_tray"]["nozzle_temp_min"].get<std::string>();
else
vt_tray.nozzle_temp_min = "";
if (jj["vt_tray"].contains("xcam_info"))
vt_tray.xcam_info = jj["vt_tray"]["xcam_info"].get<std::string>();
else
vt_tray.xcam_info = "";
if (jj["vt_tray"].contains("tray_uuid"))
vt_tray.uuid = jj["vt_tray"]["tray_uuid"].get<std::string>();
else
vt_tray.uuid = "0";
if (jj["vt_tray"].contains("tray_color")) {
auto color = jj["vt_tray"]["tray_color"].get<std::string>();
vt_tray.update_color_from_str(color);
}
else {
vt_tray.color = "";
}
if (jj["vt_tray"].contains("remain")) {
vt_tray.remain = jj["vt_tray"]["remain"].get<int>();
}
else {
vt_tray.remain = -1;
}
}
} else {
ams_support_virtual_tray = false;
}
@ -3159,24 +3300,39 @@ int MachineObject::parse_json(std::string payload)
if (jj["ams_id"].is_number()) {
int ams_id = jj["ams_id"].get<int>();
auto ams_it = amsList.find(std::to_string(ams_id));
if (ams_it != amsList.end()) {
int tray_id = jj["tray_id"].get<int>();
auto tray_it = ams_it->second->trayList.find(std::to_string(tray_id));
if (tray_it != ams_it->second->trayList.end()) {
BOOST_LOG_TRIVIAL(trace) << "ams_filament_setting, parse tray info";
tray_it->second->nozzle_temp_max = std::to_string(jj["nozzle_temp_max"].get<int>());
tray_it->second->nozzle_temp_min = std::to_string(jj["nozzle_temp_min"].get<int>());
tray_it->second->type = jj["tray_type"].get<std::string>();
tray_it->second->color = jj["tray_color"].get<std::string>();
tray_it->second->setting_id = jj["tray_info_idx"].get<std::string>();
// delay update
tray_it->second->set_hold_count();
} else {
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in trayList, tray_id=" << tray_id;
}
int tray_id = 0;
if (jj.contains("tray_id")) {
tray_id = jj["tray_id"].get<int>();
}
if (ams_id == 255 && tray_id == VIRTUAL_TRAY_ID) {
BOOST_LOG_TRIVIAL(trace) << "ams_filament_setting, parse tray info";
vt_tray.nozzle_temp_max = std::to_string(jj["nozzle_temp_max"].get<int>());
vt_tray.nozzle_temp_min = std::to_string(jj["nozzle_temp_min"].get<int>());
vt_tray.type = jj["tray_type"].get<std::string>();
vt_tray.color = jj["tray_color"].get<std::string>();
vt_tray.setting_id = jj["tray_info_idx"].get<std::string>();
// delay update
vt_tray.set_hold_count();
} else {
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in amsList, ams_id=" << ams_id;
auto ams_it = amsList.find(std::to_string(ams_id));
if (ams_it != amsList.end()) {
tray_id = jj["tray_id"].get<int>();
auto tray_it = ams_it->second->trayList.find(std::to_string(tray_id));
if (tray_it != ams_it->second->trayList.end()) {
BOOST_LOG_TRIVIAL(trace) << "ams_filament_setting, parse tray info";
tray_it->second->nozzle_temp_max = std::to_string(jj["nozzle_temp_max"].get<int>());
tray_it->second->nozzle_temp_min = std::to_string(jj["nozzle_temp_min"].get<int>());
tray_it->second->type = jj["tray_type"].get<std::string>();
tray_it->second->color = jj["tray_color"].get<std::string>();
tray_it->second->setting_id = jj["tray_info_idx"].get<std::string>();
// delay update
tray_it->second->set_hold_count();
} else {
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in trayList, tray_id=" << tray_id;
}
} else {
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in amsList, ams_id=" << ams_id;
}
}
}
} else if (jj["command"].get<std::string>() == "xcam_control_set") {
@ -3336,6 +3492,21 @@ int MachineObject::parse_json(std::string payload)
}
} catch (...) {}
// upgrade
try {
if (j.contains("upgrade")) {
if (j["upgrade"].contains("command")) {
if (j["upgrade"]["command"].get<std::string>() == "upgrade_confirm") {
this->upgrade_display_state == UpgradingInProgress;
upgrade_display_hold_count = HOLD_COUNT_MAX;
BOOST_LOG_TRIVIAL(info) << "ack of upgrade_confirm";
}
}
}
}
catch (...) {
;
}
// event info
try {
@ -3645,6 +3816,7 @@ void DeviceManager::on_machine_alive(std::string json_str)
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
if (config) {
obj->set_access_code(Slic3r::GUI::wxGetApp().app_config->get("access_code", dev_id));
obj->set_user_access_code(Slic3r::GUI::wxGetApp().app_config->get("user_access_code", dev_id));
}
localMachineList.insert(std::make_pair(dev_id, obj));
@ -3789,6 +3961,18 @@ bool DeviceManager::set_selected_machine(std::string dev_id)
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id;
auto my_machine_list = get_my_machine_list();
auto it = my_machine_list.find(dev_id);
// disconnect last
auto last_selected = my_machine_list.find(selected_machine);
if (last_selected != my_machine_list.end()) {
if (last_selected->second->connection_type() == "lan") {
if (last_selected->second->is_connecting())
return false;
m_agent->disconnect_printer();
}
}
// connect curr
if (it != my_machine_list.end()) {
if (selected_machine == dev_id) {
if (it->second->connection_type() != "lan") {
@ -3815,7 +3999,6 @@ bool DeviceManager::set_selected_machine(std::string dev_id)
it->second->reset_update_time();
}
} else {
m_agent->disconnect_printer();
it->second->reset();
it->second->connect();
it->second->set_lan_mode_connection_state(true);
@ -4007,6 +4190,7 @@ void DeviceManager::load_last_machine()
}
json DeviceManager::function_table = json::object();
json DeviceManager::filaments_blacklist = json::object();
std::string DeviceManager::parse_printer_type(std::string type_str)
{
@ -4036,6 +4220,20 @@ std::string DeviceManager::get_printer_display_name(std::string type_str)
return "";
}
std::string DeviceManager::get_ftp_folder(std::string type_str)
{
if (DeviceManager::function_table.contains("printers")) {
for (auto printer : DeviceManager::function_table["printers"]) {
if (printer.contains("model_id") && printer["model_id"].get<std::string>() == type_str) {
if (printer.contains("ftp_folder")) {
return printer["ftp_folder"].get<std::string>();
}
}
}
}
return "";
}
std::string DeviceManager::get_printer_thumbnail_img(std::string type_str)
{
if (DeviceManager::function_table.contains("printers")) {
@ -4115,4 +4313,96 @@ bool DeviceManager::load_functional_config(std::string config_file)
return true;
}
bool DeviceManager::load_filaments_blacklist_config(std::string config_file)
{
filaments_blacklist = json::object();
std::ifstream json_file(config_file.c_str());
try {
if (json_file.is_open()) {
json_file >> filaments_blacklist;
return true;
}
else {
BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = " << config_file;
}
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = " << config_file;
return false;
}
return true;
}
void DeviceManager::check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info)
{
in_blacklist = false;
if (filaments_blacklist.contains("blacklist")) {
for (auto prohibited_filament : filaments_blacklist["blacklist"]) {
std::string vendor;
std::string type;
std::string action;
std::string description;
if (prohibited_filament.contains("vendor") &&
prohibited_filament.contains("type") &&
prohibited_filament.contains("action") &&
prohibited_filament.contains("description"))
{
vendor = prohibited_filament["vendor"].get<std::string>();
type = prohibited_filament["type"].get<std::string>();
action = prohibited_filament["action"].get<std::string>();
description = prohibited_filament["description"].get<std::string>();
}
else {
return;
}
std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower);
std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower);
std::transform(tag_type.begin(), tag_type.end(), tag_type.begin(), ::tolower);
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
//third party
if (vendor == "third party") {
if ("bambulab" != vendor && tag_type == type) {
in_blacklist = true;
ac = action;
info = description;
return;
}
}
else {
if (vendor == tag_vendor && tag_type == type) {
in_blacklist = true;
ac = action;
info = description;
return;
}
}
}
}
}
std::string DeviceManager::load_gcode(std::string type_str, std::string gcode_file)
{
std::string gcode_full_path = Slic3r::resources_dir() + "/printers/" + gcode_file;
std::ifstream gcode(encode_path(gcode_full_path.c_str()).c_str());
try {
std::stringstream gcode_str;
if (gcode.is_open()) {
gcode_str << gcode.rdbuf();
gcode.close();
return gcode_str.str();
}
} catch(...) {
BOOST_LOG_TRIVIAL(error) << "load gcode file failed, file = " << gcode_file << ", path = " << gcode_full_path;
}
return "";
}
} // namespace Slic3r

View file

@ -178,6 +178,8 @@ public:
if (digit1 == -1 || digit2 == -1) break;
ret[j] = float(digit1 * 16 + digit2);
}
} else {
return wxColour(255, 255, 255);
}
return wxColour(ret[0], ret[1], ret[2]);
}
@ -216,6 +218,8 @@ public:
void update_color_from_str(std::string color);
wxColour get_color();
void reset();
bool is_tray_info_ready();
bool is_unset_third_filament();
std::string get_display_filament_type();
@ -401,15 +405,20 @@ public:
std::string dev_ip;
std::string dev_id;
bool local_use_ssl { false };
float nozzle_diameter { 0.0f };
std::string dev_connection_type; /* lan | cloud */
std::string connection_type() { return dev_connection_type; }
void set_dev_ip(std::string ip) {dev_ip = ip;};
bool has_access_right() { return !access_code.empty(); }
bool has_access_right() { return !get_access_code().empty(); }
std::string get_ftp_folder();
void set_access_code(std::string code);
std::string get_access_code();
void set_user_access_code(std::string code);
std::string get_user_access_code();
bool is_lan_mode_printer();
//PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN;
std::string printer_type; /* model_id */
@ -460,7 +469,7 @@ public:
int ams_version = 0;
std::string m_ams_id; // local ams : "0" ~ "3"
std::string m_tray_id; // local tray id : "0" ~ "3"
std::string m_tray_now; // tray_now : "0" ~ "15" or "255"
std::string m_tray_now; // tray_now : "0" ~ "15" or "254", "255"
std::string m_tray_tar; // tray_tar : "0" ~ "15" or "255"
int extrusion_cali_hold_count = 0;
@ -484,7 +493,6 @@ public:
bool can_unload_filament();
bool is_U0_firmware();
bool is_support_ams_mapping();
bool is_only_support_cloud_print();
static bool is_support_ams_mapping_version(std::string module, std::string version);
int ams_filament_mapping(std::vector<FilamentInfo> filaments, std::vector<FilamentInfo> &result, std::vector<int> exclude_id = std::vector<int>());
@ -530,6 +538,7 @@ public:
bool upgrade_new_version { false };
bool upgrade_consistency_request { false };
int upgrade_display_state = 0; // 0 : upgrade unavailable, 1: upgrade idle, 2: upgrading, 3: upgrade_finished
int upgrade_display_hold_count = 0;
PrinterFirmwareType firmware_type; // engineer|production
std::string upgrade_progress;
std::string upgrade_message;
@ -630,6 +639,8 @@ public:
bool is_support_1080dpi {false};
bool is_support_ai_monitoring {false};
bool is_support_ams_humidity {true};
bool is_support_filament_edit_virtual_tray {true};
bool is_cloud_print_only {false};
/* sdcard */
MachineObject::SdcardState sdcard_state { NO_SDCARD };
@ -827,14 +838,20 @@ public:
void load_last_machine();
static json function_table;
static json filaments_blacklist;
static std::string parse_printer_type(std::string type_str);
static std::string get_printer_display_name(std::string type_str);
static std::string get_printer_thumbnail_img(std::string type_str);
static std::string get_ftp_folder(std::string type_str);
static bool is_function_supported(std::string type_str, std::string function_name);
static std::vector<std::string> get_resolution_supported(std::string type_str);
static bool get_bed_temperature_limit(std::string type_str, int& limit);
static bool load_functional_config(std::string config_file);
static bool load_filaments_blacklist_config(std::string config_file);
static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info);
static std::string load_gcode(std::string type_str, std::string gcode_file);
};
} // namespace Slic3r

View file

@ -65,10 +65,10 @@ void ExtrusionCalibration::create()
#else
m_comboBox_nozzle_dia = new ComboBox(m_step_1_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, EXTRUSION_CALIBRATION_BED_COMBOX, 0, nullptr, wxCB_READONLY);
#endif
m_comboBox_nozzle_dia->AppendString("0.2");
m_comboBox_nozzle_dia->AppendString("0.4");
m_comboBox_nozzle_dia->AppendString("0.6");
m_comboBox_nozzle_dia->AppendString("0.8");
m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f", 0.2));
m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f", 0.4));
m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f", 0.6));
m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f", 0.8));
select_sizer->Add(m_comboBox_nozzle_dia, 0, wxEXPAND);
select_sizer->Add(0, EXTRUSION_CALIBRATION_WIDGET_GAP, 0, 0);
@ -170,10 +170,10 @@ void ExtrusionCalibration::create()
m_button_cali = new Button(m_step_1_panel, _L("Start calibration"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Disabled), std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_cali->SetBackgroundColor(m_btn_bg_green);
m_button_cali->SetFont(Label::Body_13);
m_button_cali->SetBorderColor({ std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Disabled), std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Enabled) });
m_button_cali->SetBorderColor({ std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Disabled), std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Enabled) });
m_button_cali->SetTextColor({ std::pair<wxColour, int>(wxColour(172, 172, 172), StateColor::Disabled), std::pair<wxColour, int>(EXTRUSION_CALIBRATION_GREY200, StateColor::Enabled) });
m_button_cali->SetCornerRadius(FromDIP(12));
m_button_cali->SetMinSize(wxSize(-1, FromDIP(24)));
@ -181,9 +181,9 @@ void ExtrusionCalibration::create()
m_cali_cancel = new Button(m_step_1_panel, _L("Cancel"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_cali_cancel->SetBackgroundColor(m_btn_bg_green);
m_cali_cancel->SetBorderColor(wxColour(0, 150, 136));
m_cali_cancel->SetBorderColor(wxColour(0, 174, 66));
m_cali_cancel->SetTextColor(EXTRUSION_CALIBRATION_GREY200);
m_cali_cancel->SetMinSize(EXTRUSION_CALIBRATION_BUTTON_SIZE);
m_cali_cancel->SetCornerRadius(FromDIP(12));
@ -256,10 +256,10 @@ void ExtrusionCalibration::create()
// save button
m_button_save_result = new Button(m_step_2_panel, _L("Save"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_save_result->SetBackgroundColor(m_btn_bg_green);
m_button_save_result->SetFont(Label::Body_13);
m_button_save_result->SetBorderColor(wxColour(0, 150, 136));
m_button_save_result->SetBorderColor(wxColour(0, 174, 66));
m_button_save_result->SetTextColor(EXTRUSION_CALIBRATION_GREY200);
m_button_save_result->SetMinSize(EXTRUSION_CALIBRATION_BUTTON_SIZE);
m_button_save_result->SetCornerRadius(FromDIP(12));
@ -660,8 +660,6 @@ void ExtrusionCalibration::update_combobox_filaments()
}
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
if (filament_it->setting_id.empty()) continue;
ConfigOption* printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings* printer_strs = dynamic_cast<ConfigOptionStrings*>(printer_opt);
for (auto printer_str : printer_strs->values) {

View file

@ -1021,6 +1021,9 @@ void Choice::BUILD()
if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit);
if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit);
if (m_opt.nullable)
m_last_meaningful_value = dynamic_cast<ConfigOptionEnumsGenericNullable const *>(m_opt.default_value.get())->get_at(0);
choice_ctrl* temp;
auto dynamic_list = dynamic_lists.find(m_opt.opt_key);
if (dynamic_list != dynamic_lists.end())
@ -1209,7 +1212,7 @@ void Choice::set_selection()
void Choice::set_value(const std::string& value, bool change_event) //! Redundant?
{
m_disable_change_event = !change_event;
m_disable_change_event = !change_event;
size_t idx=0;
for (auto el : m_opt.enum_values)
@ -1291,10 +1294,10 @@ void Choice::set_value(const boost::any& value, bool change_event)
if (m_opt_id.compare("host_type") == 0 && val != 0 &&
m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType
val--;
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern")
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style")
{
std::string key;
const t_config_enum_values& map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();
const t_config_enum_values& map_names = *m_opt.enum_keys_map;
for (auto it : map_names)
if (val == it.second) {
key = it.first;
@ -1305,6 +1308,12 @@ void Choice::set_value(const boost::any& value, bool change_event)
auto it = std::find(values.begin(), values.end(), key);
val = it == values.end() ? 0 : it - values.begin();
}
if (m_opt.nullable) {
if (val != ConfigOptionEnumsGenericNullable::nil_value())
m_last_meaningful_value = value;
else
val = -1;
}
field->SetSelection(val);
break;
}
@ -1370,9 +1379,11 @@ boost::any& Choice::get_value()
// BBS
if (m_opt.type == coEnum || m_opt.type == coEnums)
{
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") {
if (m_opt.nullable && field->GetSelection() == -1)
m_value = ConfigOptionEnumsGenericNullable::nil_value();
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style") {
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(ConfigOptionEnum<InfillPattern>::get_enum_values().at(key));
m_value = int(m_opt.enum_keys_map->at(key));
}
// Support ThirdPartyPrinter
else if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount()) {
@ -1404,6 +1415,20 @@ boost::any& Choice::get_value()
return m_value;
}
void Choice::set_last_meaningful_value()
{
if (m_opt.nullable) {
set_value(m_last_meaningful_value, false);
on_change_field();
}
}
void Choice::set_na_value()
{
dynamic_cast<choice_ctrl *>(window)->SetSelection(-1);
on_change_field();
}
void Choice::enable() { dynamic_cast<choice_ctrl*>(window)->Enable(); }
void Choice::disable() { dynamic_cast<choice_ctrl*>(window)->Disable(); }

View file

@ -386,6 +386,9 @@ public:
void set_values(const wxArrayString &values);
boost::any& get_value() override;
void set_last_meaningful_value() override;
void set_na_value() override;
void msw_rescale() override;
void enable() override ;//{ dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };

View file

@ -357,7 +357,8 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
glsafe(::glDisable(GL_BLEND));
static float last_window_width = 0.0f;
static size_t last_text_length = 0;
size_t text_line = 0;
static size_t last_text_line = 0;
const ImU32 text_name_clr = m_is_dark ? IM_COL32(255, 255, 255, 0.88 * 255) : IM_COL32(38, 46, 48, 255);
const ImU32 text_value_clr = m_is_dark ? IM_COL32(255, 255, 255, 0.4 * 255) : IM_COL32(144, 144, 144, 255);
@ -466,6 +467,7 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
default:
break;
}
text_line = 2;
}
else {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
@ -485,14 +487,15 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
sprintf(buf, "%s%.0f", speed.c_str(), m_curr_move.feedrate);
ImGui::PushItemWidth(item_size);
imgui.text(buf);
text_line = 1;
}
// force extra frame to automatically update window size
float window_width = ImGui::GetWindowWidth();
//size_t length = strlen(buf);
if (window_width != last_window_width /*|| length != last_text_length*/) {
if (window_width != last_window_width || text_line != last_text_line) {
last_window_width = window_width;
//last_text_length = length;
last_text_line = text_line;
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
imgui.set_requires_extra_frame();
#else
@ -945,7 +948,6 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode)
// BBS for first layer inspection
view_type_items.push_back(EViewType::FilamentId);
options_items.push_back(EMoveType::Seam);
options_items.push_back(EMoveType::Travel);
options_items.push_back(EMoveType::Retract);
options_items.push_back(EMoveType::Unretract);
@ -953,6 +955,8 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode)
if (mode == ConfigOptionMode::comDevelop) {
options_items.push_back(EMoveType::Tool_change);
}
//BBS: seam is not real move and extrusion, put at last line
options_items.push_back(EMoveType::Seam);
}
std::vector<int> GCodeViewer::get_plater_extruder()
@ -1794,11 +1798,13 @@ void GCodeViewer::update_layers_slider_mode()
}
void GCodeViewer::update_marker_curr_move() {
auto it = std::find_if(m_gcode_result->moves.begin(), m_gcode_result->moves.end(), [this](auto move) {
return move.gcode_id == static_cast<uint64_t>(m_sequential_view.gcode_ids[m_sequential_view.current.last]);
});
m_sequential_view.marker.update_curr_move(*it);
if ((int)m_last_result_id != -1) {
auto it = std::find_if(m_gcode_result->moves.begin(), m_gcode_result->moves.end(), [this](auto move) {
return move.gcode_id == static_cast<uint64_t>(m_sequential_view.gcode_ids[m_sequential_view.current.last]);
});
if (it != m_gcode_result->moves.end())
m_sequential_view.marker.update_curr_move(*it);
}
}
bool GCodeViewer::is_toolpath_move_type_visible(EMoveType type) const
@ -3080,6 +3086,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
}
m_plater_extruder = plater_extruder;
// replace layers for spiral vase mode
if (!gcode_result.spiral_vase_layers.empty()) {
m_layers.reset();
for (const auto& layer : gcode_result.spiral_vase_layers) {
m_layers.append(layer.first, { layer.second.first, layer.second.second });
}
}
// set layers z range
if (!m_layers.empty())
@ -3325,11 +3338,13 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
const bool top_layer_only = true;
SequentialView::Endpoints global_endpoints = { m_moves_count , 0 };
//BBS
SequentialView::Endpoints global_endpoints = { m_sequential_view.gcode_ids.size() , 0 };
SequentialView::Endpoints top_layer_endpoints = global_endpoints;
SequentialView* sequential_view = const_cast<SequentialView*>(&m_sequential_view);
if (top_layer_only || !keep_sequential_current_first) sequential_view->current.first = 0;
if (!keep_sequential_current_last) sequential_view->current.last = m_moves_count;
//BBS
if (!keep_sequential_current_last) sequential_view->current.last = m_sequential_view.gcode_ids.size();
// first pass: collect visible paths and update sequential view data
std::vector<std::tuple<unsigned char, unsigned int, unsigned int, unsigned int>> paths;
@ -3403,15 +3418,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
// update current sequential position
sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first;
if (global_endpoints.last == 0) {
m_no_render_path = true;
m_no_render_path = true;
sequential_view->current.last = global_endpoints.last;
} else {
m_no_render_path = false;
}
if (!m_no_render_path) {
sequential_view->current.last = keep_sequential_current_last ? std::clamp(sequential_view->current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last;
} else {
sequential_view->current.last = sequential_view->current.first;
}
// get the world position from the vertex buffer
@ -4125,6 +4136,214 @@ void GCodeViewer::render_shells()
// glsafe(::glDepthMask(GL_TRUE));
}
//BBS
void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessorResult*>& gcode_result_list, bool show /*= true*/) const {
if (!show)
return;
for (auto gcode_result : gcode_result_list) {
if (gcode_result->moves.size() == 0)
return;
}
ImGuiWrapper& imgui = *wxGetApp().imgui();
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0, 10.0 * m_scale));
ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f, 1.0f, 1.0f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(340.f * m_scale * imgui.scaled(1.0f / 15.0f), 0));
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), 0, ImVec2(0.5f, 0.5f));
ImGui::Begin(_L("Statistics of All Plates").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
std::vector<float> filament_diameters = gcode_result_list.front()->filament_diameters;
std::vector<float> filament_densities = gcode_result_list.front()->filament_densities;
std::vector<Color> filament_colors = decode_colors(wxGetApp().plater()->get_extruder_colors_from_plater_config(gcode_result_list.back()));
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
float window_padding = 4.0f * m_scale;
const float icon_size = ImGui::GetTextLineHeight() * 0.7;
std::vector<float> offsets;
std::map<int, double> volume_of_extruders_all_plates; // map<extruder_idx, volume>
std::map<int, double> flushed_volume_of_extruders_all_plates; // map<extruder_idx, flushed volume>
std::vector<double> model_used_filaments_m_all_plates;
std::vector<double> model_used_filaments_g_all_plates;
std::vector<double> flushed_filaments_m_all_plates;
std::vector<double> flushed_filaments_g_all_plates;
float total_time_all_plates = 0.0f;
bool show_detailed_statistics_page = false;
auto max_width = [](const std::vector<std::string>& items, const std::string& title, float extra_size = 0.0f) {
float ret = ImGui::CalcTextSize(title.c_str()).x;
for (const std::string& item : items) {
ret = std::max(ret, extra_size + ImGui::CalcTextSize(item.c_str()).x);
}
return ret;
};
auto calculate_offsets = [max_width, window_padding](const std::vector<std::pair<std::string, std::vector<::string>>>& title_columns, float extra_size = 0.0f) {
const ImGuiStyle& style = ImGui::GetStyle();
std::vector<float> offsets;
offsets.push_back(max_width(title_columns[0].second, title_columns[0].first, extra_size) + 3.0f * style.ItemSpacing.x + style.WindowPadding.x);
for (size_t i = 1; i < title_columns.size() - 1; i++)
offsets.push_back(offsets.back() + max_width(title_columns[i].second, title_columns[i].first) + style.ItemSpacing.x);
if (title_columns.back().first == _u8L("Display"))
offsets.back() = ImGui::GetWindowWidth() - ImGui::CalcTextSize(_u8L("Display").c_str()).x - ImGui::GetFrameHeight() / 2 - 2 * window_padding;
float average_col_width = ImGui::GetWindowWidth() / static_cast<float>(title_columns.size());
std::vector<float> ret;
ret.push_back(0);
for (size_t i = 1; i < title_columns.size(); i++) {
ret.push_back(std::max(offsets[i - 1], i * average_col_width));
}
return ret;
};
auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, this](const Color& color, const std::vector<std::pair<std::string, float>>& columns_offsets)
{
// render icon
ImVec2 pos = ImVec2(ImGui::GetCursorScreenPos().x + window_padding * 3, ImGui::GetCursorScreenPos().y);
draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale },
ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(20.0 * m_scale, 6.0 * m_scale));
// render selectable
ImGui::Dummy({ 0.0, 0.0 });
ImGui::SameLine();
// render column item
{
float dummy_size = ImGui::GetStyle().ItemSpacing.x + icon_size;
ImGui::SameLine(dummy_size);
imgui.text(columns_offsets[0].first);
for (auto i = 1; i < columns_offsets.size(); i++) {
ImGui::SameLine(columns_offsets[i].second);
imgui.text(columns_offsets[i].first);
}
}
ImGui::PopStyleVar(1);
};
auto append_headers = [&imgui](const std::vector<std::pair<std::string, float>>& title_offsets) {
for (size_t i = 0; i < title_offsets.size(); i++) {
ImGui::SameLine(title_offsets[i].second);
imgui.bold_text(title_offsets[i].first);
}
ImGui::Separator();
};
auto get_used_filament_from_volume = [this, imperial_units, &filament_diameters, &filament_densities](double volume, int extruder_id) {
double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
std::pair<double, double> ret = { koef * volume / (PI * sqr(0.5 * filament_diameters[extruder_id])),
volume * filament_densities[extruder_id] * 0.001 };
return ret;
};
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
// title and item data
{
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
for (auto plate : plate_list.get_nonempty_plate_list())
{
auto plate_print_statistics = plate->get_slice_result()->print_statistics;
auto plate_extruders = plate->get_extruders(true);
for (size_t extruder_id : plate_extruders) {
extruder_id -= 1;
if (plate_print_statistics.volumes_per_extruder.find(extruder_id) == plate_print_statistics.volumes_per_extruder.end())
continue;
double volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
volume_of_extruders_all_plates[extruder_id] += volume;
if (plate_print_statistics.flush_per_filament.find(extruder_id) == plate_print_statistics.flush_per_filament.end())
flushed_volume_of_extruders_all_plates[extruder_id] = 0;
else {
double flushed_volume = plate_print_statistics.flush_per_filament.at(extruder_id);
flushed_volume_of_extruders_all_plates[extruder_id] += flushed_volume;
}
}
const PrintEstimatedStatistics::Mode& plate_time_mode = plate_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
total_time_all_plates += plate_time_mode.time;
}
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(it->second, it->first);
model_used_filaments_m_all_plates.push_back(model_used_filament_m);
model_used_filaments_g_all_plates.push_back(model_used_filament_g);
}
for (auto it = flushed_volume_of_extruders_all_plates.begin(); it != flushed_volume_of_extruders_all_plates.end(); it++) {
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (flushed_filament_m != 0.0 || flushed_filament_g != 0.0)
show_detailed_statistics_page = true;
flushed_filaments_m_all_plates.push_back(flushed_filament_m);
flushed_filaments_g_all_plates.push_back(flushed_filament_g);
}
char buff[64];
double longest_str = 0.0;
for (auto i : model_used_filaments_g_all_plates) {
if (i > longest_str)
longest_str = i;
}
::sprintf(buff, "%.2f", longest_str);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, /*{_u8L("Tower"), total_filaments},*/ {_u8L("Total"), {buff}} }, icon_size);
if (!show_detailed_statistics_page)
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]} });
else
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, /*{_u8L("Tower"), offsets[3]},*/ {_u8L("Total"), offsets[3]} });// to add Tower
}
// item
{
size_t i = 0;
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
if (i < model_used_filaments_m_all_plates.size() && i < model_used_filaments_g_all_plates.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
char buf[64];
if (show_detailed_statistics_page) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
columns_offsets.push_back({ buf, offsets[2] });
}
append_item(filament_colors[it->first], columns_offsets);
}
i++;
}
ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1));
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.title(_u8L("Total Time Estimation"));
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.text(_u8L("Total time") + ":");
ImGui::SameLine();
imgui.text(short_time(get_time_dhms(total_time_all_plates)));
}
ImGui::End();
ImGui::PopStyleColor(6);
ImGui::PopStyleVar(3);
return;
}
void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin)
{
if (!m_legend_enabled)
@ -4283,8 +4502,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
const float step_size = range.step_size();
for (int i = static_cast<int>(Range_Colors.size()) - 1; i >= 0; --i) {
append_range_item(i, range.get_value_at_step(i), decimals);
}
}
};
@ -4376,6 +4593,11 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f);
};
auto move_time_and_percent = [time_mode](EMoveType move_type) {
auto it = std::find_if(time_mode.moves_times.begin(), time_mode.moves_times.end(), [move_type](const std::pair<EMoveType, float>& item) { return move_type == item.first; });
return (it != time_mode.moves_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f);
};
auto used_filament_per_role = [this, imperial_units](ExtrusionRole role) {
auto it = m_print_statistics.used_filaments_per_role.find(role);
if (it == m_print_statistics.used_filaments_per_role.end())
@ -4385,6 +4607,14 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return std::make_pair(it->second.first * koef, it->second.second);
};
// get used filament (meters and grams) from used volume in respect to the active extruder
auto get_used_filament_from_volume = [this, imperial_units](double volume, int extruder_id) {
double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
std::pair<double, double> ret = { koef * volume / (PI * sqr(0.5 * m_filament_diameters[extruder_id])),
volume * m_filament_densities[extruder_id] * 0.001 };
return ret;
};
//BBS display Color Scheme
ImGui::Dummy({ window_padding, window_padding });
ImGui::Dummy({ window_padding, window_padding });
@ -4449,7 +4679,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
std::vector<float> offsets;
std::vector<std::string> labels;
std::vector<std::string> times;
std::string travel_time;
std::vector<std::string> percents;
std::string travel_percent;
std::vector<double> model_used_filaments_m;
std::vector<double> model_used_filaments_g;
double total_model_used_filament_m = 0, total_model_used_filament_g = 0;
@ -4462,13 +4694,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
double koef = imperial_units ? GizmoObjectManipulation::in_to_mm : 1000.0;
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1;
// get used filament (meters and grams) from used volume in respect to the active extruder
auto get_used_filament_from_volume = [this, imperial_units](double volume, int extruder_id) {
double koef = imperial_units ? 1.0 / GizmoObjectManipulation::in_to_mm : 0.001;
std::pair<double, double> ret = { koef * volume / (PI * sqr(0.5 * m_filament_diameters[extruder_id])),
volume * m_filament_densities[extruder_id] * 0.001 };
return ret;
};
// extrusion paths section -> title
ImGui::Dummy({ window_padding, window_padding });
@ -4496,6 +4721,17 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
}
}
//BBS: get travel time and percent
{
auto [time, percent] = move_time_and_percent(EMoveType::Travel);
travel_time = (time > 0.0f) ? short_time(get_time_dhms(time)) : "";
if (percent == 0)
::sprintf(buffer, "0%%");
else
percent > 0.001 ? ::sprintf(buffer, "%.1f%%", percent * 100) : ::sprintf(buffer, "<0.1%%");
travel_percent = buffer;
}
offsets = calculate_offsets({ {_u8L("Line Type"), labels}, {_u8L("Time"), times}, {_u8L("Percent"), percents}, {_u8L("Display"), {""}}}, icon_size);
append_headers({{_u8L("Line Type"), offsets[0]}, {_u8L("Time"), offsets[1]}, {_u8L("Percent"), offsets[2]}, {_u8L("Display"), offsets[3]}});
break;
@ -4584,7 +4820,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
};
const bool visible = m_buffers[buffer_id(type)].visible;
if (type == EMoveType::Travel) {
//TODO display travel time
//BBS: only display travel time in FeatureType view
append_option_item_with_type(type, Travel_Colors[0], _u8L("Travel"), visible);
}
else if (type == EMoveType::Seam)
@ -4624,7 +4860,23 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
}
for(auto item : options_items) {
append_option_item(item, offsets);
if (item != EMoveType::Travel) {
append_option_item(item, offsets);
} else {
//BBS: show travel time in FeatureType view
const bool visible = m_buffers[buffer_id(item)].visible;
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ _u8L("Travel"), offsets[0] });
columns_offsets.push_back({ travel_time, offsets[1] });
columns_offsets.push_back({ travel_percent, offsets[2] });
append_item(EItemType::Rect, Travel_Colors[0], columns_offsets, true, visible, [this, item, visible]() {
m_buffers[buffer_id(item)].visible = !m_buffers[buffer_id(item)].visible;
// update buffers' render paths
refresh_render_paths(false, false);
update_moves_slider();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
}
}
break;
}
@ -4668,7 +4920,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
}
case EViewType::ColorPrint:
{
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z;
//BBS: replace model custom gcode with current plate custom gcode
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes : m_custom_gcode_per_print_z;
size_t total_items = 1;
for (size_t extruder_id : m_extruder_ids) {
total_items += color_print_ranges(extruder_id, custom_gcode_per_print_z).size();
@ -4722,13 +4975,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
char buf[64];
if (show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f g" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
@ -4850,7 +5103,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
auto generate_partial_times = [this, get_used_filament_from_volume](const TimesList& times, const std::vector<double>& used_filaments) {
PartialTimes items;
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z;
//BBS: replace model custom gcode with current plate custom gcode
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes : m_custom_gcode_per_print_z;
std::vector<Color> last_color(m_extruders_count);
for (size_t i = 0; i < m_extruders_count; ++i) {
last_color[i] = m_tools.m_tool_colors[i];
@ -5220,19 +5474,19 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
auto it = std::find_if(time_mode.roles_times.begin(), time_mode.roles_times.end(), [role](const std::pair<ExtrusionRole, float>& item) { return role == item.first; });
return (it != time_mode.roles_times.end()) ? it->second : 0.0f;
};
//BBS: start gcode is prepeare time
if (role_time(erCustom) != 0.0f) {
//BBS: start gcode is mostly same with prepeare time
if (time_mode.prepare_time != 0.0f) {
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.text(prepare_str + ":");
ImGui::SameLine(max_len);
imgui.text(short_time(get_time_dhms(role_time(erCustom))));
imgui.text(short_time(get_time_dhms(time_mode.prepare_time)));
}
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.text(print_str + ":");
ImGui::SameLine(max_len);
imgui.text(short_time(get_time_dhms(time_mode.time - role_time(erCustom))));
imgui.text(short_time(get_time_dhms(time_mode.time - time_mode.prepare_time)));
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
imgui.text(total_str + ":");
@ -5264,16 +5518,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
}
default : { assert(false); break; }
}
}
if (m_view_type == EViewType::ColorPrint) {
ImGui::Spacing();
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
offsets = calculate_offsets({ { _u8L("Options"), { ""}}, { _u8L("Display"), {""}} }, icon_size);
append_headers({ {_u8L("Options"), offsets[0] }, { _u8L("Display"), offsets[1]} });
for (auto item : options_items)
append_option_item(item, offsets);
}
if (m_view_type == EViewType::ColorPrint) {
ImGui::Spacing();
ImGui::Dummy({ window_padding, window_padding });
ImGui::SameLine();
offsets = calculate_offsets({ { _u8L("Options"), { ""}}, { _u8L("Display"), {""}} }, icon_size);
append_headers({ {_u8L("Options"), offsets[0] }, { _u8L("Display"), offsets[1]} });
for (auto item : options_items)
append_option_item(item, offsets);
}
legend_height = ImGui::GetCurrentWindow()->Size.y;
@ -5304,7 +5558,6 @@ void GCodeViewer::pop_combo_style()
}
void GCodeViewer::render_slider(int canvas_width, int canvas_height) {
m_moves_slider->render(canvas_width, canvas_height);
m_layers_slider->render(canvas_width, canvas_height);
}

View file

@ -809,6 +809,8 @@ public:
void reset_shell();
void load_shells(const Print& print, bool initialized, bool force_previewing = false);
void set_shells_on_preview(bool is_previewing) { m_shells.previewing = is_previewing; }
//BBS: add all plates filament statistics
void render_all_plates_stats(const std::vector<const GCodeProcessorResult*>& gcode_result_list, bool show = true) const;
//BBS: GUI refactor: add canvas width and height
void render(int canvas_width, int canvas_height, int right_margin);
//BBS

View file

@ -74,8 +74,8 @@ static constexpr const float TRACKBALLSIZE = 0.8f;
static const float SLIDER_DEFAULT_RIGHT_MARGIN = 10.0f;
static const float SLIDER_DEFAULT_BOTTOM_MARGIN = 10.0f;
static const float SLIDER_RIGHT_MARGIN = 115.0f;
static const float SLIDER_BOTTOM_MARGIN = 90.0f;
static const float SLIDER_RIGHT_MARGIN = 124.0f;
static const float SLIDER_BOTTOM_MARGIN = 64.0f;
float GLCanvas3D::DEFAULT_BG_LIGHT_COLOR[3] = { 0.906f, 0.906f, 0.906f };
float GLCanvas3D::DEFAULT_BG_LIGHT_COLOR_DARK[3] = { 0.329f, 0.329f, 0.353f };
@ -1160,6 +1160,7 @@ GLCanvas3D::~GLCanvas3D()
reset_volumes();
m_sel_plate_toolbar.del_all_item();
m_sel_plate_toolbar.del_stats_item();
}
void GLCanvas3D::post_event(wxEvent &&event)
@ -1608,6 +1609,11 @@ void GLCanvas3D::enable_main_toolbar(bool enable)
m_main_toolbar.set_enabled(enable);
}
void GLCanvas3D::reset_select_plate_toolbar_selection() {
if (m_sel_plate_toolbar.m_all_plates_stats_item)
m_sel_plate_toolbar.m_all_plates_stats_item->selected = false;
}
void GLCanvas3D::enable_select_plate_toolbar(bool enable)
{
m_sel_plate_toolbar.set_enabled(enable);
@ -1721,6 +1727,9 @@ float GLCanvas3D::get_collapse_toolbar_height()
return collapse_toolbar.is_enabled() ? collapse_toolbar.get_height() : 0;
}
bool GLCanvas3D::make_current_for_postinit() {
return _set_current();
}
void GLCanvas3D::render(bool only_init)
{
@ -1844,7 +1853,7 @@ void GLCanvas3D::render(bool only_init)
_render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id);
}
/* preview render */
else if (m_canvas_type == ECanvasType::CanvasPreview) {
else if (m_canvas_type == ECanvasType::CanvasPreview && m_render_preview) {
//BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//BBS: GUI refactor: add canvas size as parameters
@ -2045,6 +2054,17 @@ void GLCanvas3D::deselect_all()
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
}
void GLCanvas3D::set_selected_visible(bool visible)
{
for (unsigned int i : m_selection.get_volume_idxs()) {
GLVolume* volume = const_cast<GLVolume*>(m_selection.get_volume(i));
volume->visible = visible;
volume->color[3] = visible ? 1.f : GLVolume::MODEL_HIDDEN_COL[3];
volume->render_color[3] = volume->color[3];
volume->force_native_color = !visible;
}
}
void GLCanvas3D::delete_selected()
{
m_selection.erase();
@ -2383,8 +2403,21 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
}
for (int temp_idx = vol_idx; temp_idx < m_volumes.volumes.size() && !update_object_list; temp_idx++) {
if (!m_volumes.volumes[temp_idx]->is_wipe_tower)
// Volumes in m_volumes might not exist anymore, so we cannot
// directly check if they are is_wipe_towers, for which we do
// not want to update the object list. Instead, we do a kind of
// slow thing of seeing if they were in the deleted list, and if
// so, if they were a wipe tower.
bool was_deleted_wipe_tower = false;
for (int del_idx = 0; del_idx < deleted_wipe_towers.size(); del_idx++) {
if (deleted_wipe_towers[del_idx].volume_idx == temp_idx) {
was_deleted_wipe_tower = true;
break;
}
}
if (!was_deleted_wipe_tower) {
update_object_list = true;
}
}
for (int temp_idx = vol_idx; temp_idx < glvolumes_new.size() && !update_object_list; temp_idx++) {
if (!glvolumes_new[temp_idx]->is_wipe_tower)
@ -2536,8 +2569,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
if ((timelapse_enabled && wt) || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) {
if (wt && (timelapse_enabled || filaments_count > 1)) {
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
// If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated.
if (co != nullptr && co->value == PrintSequence::ByObject && ppl.get_plate(plate_id)->printable_instance_size() != 1)
continue;
DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
float x = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->get_at(plate_id);
float y = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->get_at(plate_id);
@ -3458,6 +3495,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
}
}
else return;
}
if (keyCode != WXK_TAB
@ -3529,6 +3567,28 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
if (m_gizmos.on_mouse_wheel(evt))
return;
if (m_canvas_type == CanvasAssembleView && (evt.AltDown() || evt.CmdDown())) {
float rotation = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
if (evt.AltDown()) {
auto clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position();
clp_dist = rotation < 0.f
? std::max(0., clp_dist - 0.01)
: std::min(1., clp_dist + 0.01);
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
}
else if (evt.CmdDown()) {
m_explosion_ratio = rotation < 0.f
? std::max(1., m_explosion_ratio - 0.01)
: std::min(3., m_explosion_ratio + 0.01);
if (m_explosion_ratio != GLVolume::explosion_ratio) {
for (GLVolume* volume : m_volumes.volumes) {
volume->set_bounding_boxes_as_dirty();
}
GLVolume::explosion_ratio = m_explosion_ratio;
}
}
return;
}
// Calculate the zoom delta and apply it to the current zoom factor
#ifdef SUPPORT_REVERSE_MOUSE_ZOOM
double direction_factor = (wxGetApp().app_config->get("reverse_mouse_wheel_zoom") == "1") ? -1.0 : 1.0;
@ -4235,6 +4295,10 @@ void GLCanvas3D::on_paint(wxPaintEvent& evt)
this->render();
}
void GLCanvas3D::force_set_focus() {
m_canvas->SetFocus();
};
void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
{
m_tooltip_enabled = false;
@ -5753,6 +5817,9 @@ bool GLCanvas3D::_init_toolbars()
if (!_init_separator_toolbar())
return false;
if (!_init_select_plate_toolbar())
return false;
#if 0
if (!_init_view_toolbar())
return false;
@ -5918,7 +5985,24 @@ bool GLCanvas3D::_init_main_toolbar()
//BBS: GUI refactor: GLToolbar
bool GLCanvas3D::_init_select_plate_toolbar()
{
return true;
std::string path = resources_dir() + "/images/";
IMToolbarItem* item = new IMToolbarItem();
bool result = item->image_texture.load_from_svg_file(path + "im_all_plates_stats.svg", false, false, false, 128);
result = result && item->image_texture_transparent.load_from_svg_file(path + "im_all_plates_stats_transparent.svg", false, false, false, 128);
m_sel_plate_toolbar.m_all_plates_stats_item = item;
return result;
}
void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) {
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
if (plate_list.get_nonempty_plate_list().size() > 1)
m_sel_plate_toolbar.show_stats_item = true;
else
m_sel_plate_toolbar.show_stats_item = false;
if (force_selected && m_sel_plate_toolbar.show_stats_item)
m_sel_plate_toolbar.m_all_plates_stats_item->selected = true;
}
bool GLCanvas3D::_update_imgui_select_plate_toolbar()
@ -5926,6 +6010,8 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar()
bool result = true;
if (!m_sel_plate_toolbar.is_enabled()) return false;
_update_select_plate_toolbar_stats_item();
m_sel_plate_toolbar.del_all_item();
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
@ -5941,6 +6027,7 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar()
}
m_sel_plate_toolbar.m_items.push_back(item);
}
m_sel_plate_toolbar.is_display_scrollbar = false;
return result;
}
@ -6565,7 +6652,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
return true;
}
}, with_outline);
if (m_canvas_type == CanvasAssembleView) {
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
const GLGizmosManager& gm = get_gizmos_manager();
shader->stop_using();
gm.render_painter_assemble_view();
@ -7031,20 +7118,26 @@ void GLCanvas3D::_render_main_toolbar()
//BBS: GUI refactor: GLToolbar adjust
//when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-up
void GLCanvas3D::_render_imgui_select_plate_toolbar() const
void GLCanvas3D::_render_imgui_select_plate_toolbar()
{
if (!m_sel_plate_toolbar.is_enabled())
if (!m_sel_plate_toolbar.is_enabled()) {
if (!m_render_preview)
m_render_preview = true;
return;
}
IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item;
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
for (int i = 0; i < plate_list.get_plate_count(); i++) {
if (i < m_sel_plate_toolbar.m_items.size()) {
if (i == plate_list.get_curr_plate_index())
if (i == plate_list.get_curr_plate_index() && !all_plates_stats_item->selected)
m_sel_plate_toolbar.m_items[i]->selected = true;
else
m_sel_plate_toolbar.m_items[i]->selected = false;
m_sel_plate_toolbar.m_items[i]->percent = plate_list.get_plate(i)->get_slicing_percent();
if (plate_list.get_plate(i)->is_slice_result_valid()) {
if (plate_list.get_plate(i)->is_slice_result_ready_for_print())
m_sel_plate_toolbar.m_items[i]->slice_state = IMToolbarItem::SliceState::SLICED;
@ -7058,6 +7151,46 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
m_sel_plate_toolbar.m_items[i]->slice_state = IMToolbarItem::SliceState::SLICING;
}
}
if (m_sel_plate_toolbar.show_stats_item) {
all_plates_stats_item->percent = 0.0f;
size_t sliced_plates_cnt = 0;
bool slice_failed = false;
for (auto plate : plate_list.get_nonempty_plate_list()) {
if (plate->is_slice_result_valid() && plate->is_slice_result_ready_for_print())
sliced_plates_cnt++;
if (plate->is_slice_result_valid() && !plate->is_slice_result_ready_for_print())
slice_failed = true;
}
all_plates_stats_item->percent = (float)(sliced_plates_cnt) / (float)(plate_list.get_nonempty_plate_list().size()) * 100.0f;
if (all_plates_stats_item->percent == 0.0f)
all_plates_stats_item->slice_state = IMToolbarItem::SliceState::UNSLICED;
else if (sliced_plates_cnt == plate_list.get_nonempty_plate_list().size())
all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICED;
else if (all_plates_stats_item->percent < 100.0f)
all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICING;
if (slice_failed)
all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICE_FAILED;
// Changing parameters does not invalid all plates, need extra logic to validate
bool gcode_result_valid = true;
for (auto gcode_result : plate_list.get_nonempty_plates_slice_results()) {
if (gcode_result->moves.size() == 0) {
gcode_result_valid = false;
}
}
if (all_plates_stats_item->selected && all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICED && gcode_result_valid) {
m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results());
m_render_preview = false;
}
else{
m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results(), false);
m_render_preview = true;
}
}else
m_render_preview = true;
// places the toolbar on the top_left corner of the 3d scene
#if ENABLE_RETINA_GL
@ -7081,7 +7214,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
float button_margin = frame_padding;
ImGuiWrapper& imgui = *wxGetApp().imgui();
int item_count = m_sel_plate_toolbar.m_items.size();
int item_count = m_sel_plate_toolbar.m_items.size() + (m_sel_plate_toolbar.show_stats_item ? 1 : 0);
bool show_scroll = item_count * (button_height + frame_padding * 2.0f + button_margin) - button_margin + 22.0f * f_scale > canvas_h ? true: false;
show_scroll = m_sel_plate_toolbar.is_display_scrollbar && show_scroll;
float window_height = std::min(item_count * (button_height + (frame_padding + margin_size) * 2.0f + button_margin) - button_margin + 28.0f * f_scale, canvas_h);
@ -7122,7 +7255,89 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec2 margin = ImVec2(margin_size, margin_size);
for (int i = 0; i < item_count; i++) {
if(m_sel_plate_toolbar.show_stats_item)
{
// draw image
ImVec2 button_start_pos = ImGui::GetCursorScreenPos();
if (all_plates_stats_item->selected) {
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
}
else {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
}
}
ImVec4 text_clr;
ImTextureID btn_texture_id;
if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED)
{
text_clr = ImVec4(0, 174.0f / 255.0f, 66.0f / 255.0f, 0.2f);
btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_texture_transparent.get_id());
}
else
{
text_clr = ImVec4(0, 174.0f / 255.0f, 66.0f / 255.0f, 1);
btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_texture.get_id());
}
if (ImGui::ImageButton2(btn_texture_id, size, {0,0}, {1,1}, frame_padding, bg_col, tint_col, margin)) {
if (all_plates_stats_item->slice_state != IMToolbarItem::SliceState::SLICE_FAILED) {
if (m_process && !m_process->running()) {
for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
m_sel_plate_toolbar.m_items[i]->selected = false;
}
all_plates_stats_item->selected = true;
wxCommandEvent evt = wxCommandEvent(EVT_GLTOOLBAR_SLICE_ALL);
wxPostEvent(wxGetApp().plater(), evt);
}
}
}
ImGui::PopStyleColor(3);
ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
ImVec2 size = ImVec2(button_width, button_height);
ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(0, 0, 0, 80));
}
else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING) {
ImVec2 size = ImVec2(button_width, button_height * all_plates_stats_item->percent / 100.0f);
ImVec2 rect_start_pos = ImVec2(start_pos.x, start_pos.y + size.y);
ImVec2 rect_end_pos = ImVec2(start_pos.x + button_width, start_pos.y + button_height);
ImGui::GetForegroundDrawList()->AddRectFilled(rect_start_pos, rect_end_pos, IM_COL32(0, 0, 0, 80));
}
else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
ImVec2 size = ImVec2(button_width, button_height);
ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(40, 1, 1, 64));
ImGui::GetForegroundDrawList()->AddRect(start_pos, end_pos, IM_COL32(208, 27, 27, 255), 0.0f, 0, 1.0f);
}
// draw text
GImGui->FontSize = 15.0f;
ImGui::PushStyleColor(ImGuiCol_Text, text_clr);
ImVec2 text_size = ImGui::CalcTextSize(("All Plates"));
ImVec2 text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, start_pos.y + 3.0f * button_height / 5.0f);
ImGui::RenderText(text_start_pos, ("All Plates"));
text_size = ImGui::CalcTextSize(("Stats"));
text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, text_start_pos.y + ImGui::GetTextLineHeight());
ImGui::RenderText(text_start_pos, ("Stats"));
ImGui::PopStyleColor();
ImGui::SetWindowFontScale(1.2f);
}
for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
IMToolbarItem* item = m_sel_plate_toolbar.m_items[i];
// draw image
@ -7134,11 +7349,16 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
if (item->selected) {
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
} else
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
}
if (ImGui::ImageButton2(item->texture_id, size, uv0, uv1, frame_padding, bg_col, tint_col, margin)) {
if (m_process && !m_process->running()) {
all_plates_stats_item->selected = false;
item->selected = true;
// begin to slicing plate
wxCommandEvent* evt = new wxCommandEvent(EVT_GLTOOLBAR_SELECT_SLICED_PLATE);
evt->SetInt(i);
@ -7146,10 +7366,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() const
}
}
if (item->selected)
ImGui::PopStyleColor(2);
else
ImGui::PopStyleColor(1);
ImGui::PopStyleColor(2);
ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
if (item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
@ -7341,60 +7558,59 @@ void GLCanvas3D::_render_paint_toolbar() const
float f_scale = 1.0;
#endif
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
ImGuiWrapper& imgui = *wxGetApp().imgui();
auto canvas_w = float(get_canvas_size().get_width());
int extruder_num = colors.size();
std::vector<std::string> filament_text_first_line;
std::vector<std::string> filament_text_second_line;
{
auto preset_bundle = wxGetApp().preset_bundle;
for (auto filament_name : preset_bundle->filament_presets) {
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
if (filament_name.compare(iter->name) == 0) {
std::string display_filament_type;
iter->config.get_filament_type(display_filament_type);
auto pos = display_filament_type.find(' ');
if (pos != std::string::npos) {
filament_text_first_line.push_back(display_filament_type.substr(0, pos));
filament_text_second_line.push_back(display_filament_type.substr(pos + 1));
}
else {
filament_text_first_line.push_back(display_filament_type);
filament_text_second_line.push_back("");
}
}
}
}
}
ImGuiWrapper& imgui = *wxGetApp().imgui();
float canvas_w = float(get_canvas_size().get_width());
int item_spacing = 8 * wxGetApp().toolbar_icon_scale() * f_scale;
float button_size = GLToolbar::Default_Icons_Size * f_scale * wxGetApp().toolbar_icon_scale() + item_spacing;
std::vector<std::string> filament_types;
{
auto preset_bundle = wxGetApp().preset_bundle;
for (auto filament_name : preset_bundle->filament_presets) {
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
if (filament_name.compare(iter->name) == 0) {
std::string display_filament_type;
iter->config.get_filament_type(display_filament_type);
filament_types.push_back(display_filament_type);
}
}
}
}
float button_size = GLToolbar::Default_Icons_Size * f_scale * wxGetApp().toolbar_icon_scale() + item_spacing;
imgui.set_next_window_pos(0.5f * (canvas_w + (button_size + item_spacing) * extruder_num), button_size + item_spacing * 2, ImGuiCond_Always, 1.0f, 1.0f);
imgui.set_next_window_pos(0.5f * canvas_w, 0, ImGuiCond_Always, 0.5f, 0.0f);
imgui.begin(_L("Paint Toolbar"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar);
bool disabled = !wxGetApp().plater()->can_fillcolor();
unsigned char rgb[3];
float cursor_y = ImGui::GetCursorPosY();
float max_text = 0;
for (int i = 0; i < extruder_num; i++) {
std::string item_text = (boost::format("%1%%2%") % (i + 1) % filament_types[i]).str();
ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
if (label_size.x > button_size)
label_size.x = button_size * 0.6;
max_text = std::max(max_text,label_size.x);
}
for (int i = 0; i < extruder_num; i++) {
if (filament_types.size() <= i) continue;
ImGui::SameLine(item_spacing / 2 + (button_size - max_text) / 2 + (button_size + item_spacing) * i);
ImGui::PushID(i);
if (i > 0)
ImGui::SameLine(0.0f, item_spacing);
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
ImGui::PushStyleColor(ImGuiCol_Button, ImColor(rgb[0], rgb[1], rgb[2]).Value);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor(rgb[0], rgb[1], rgb[2]).Value);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor(rgb[0], rgb[1], rgb[2]).Value);
if (disabled)
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
if (ImGui::Button("", ImVec2(button_size, button_size))) {
if (ImGui::Button(("##filament_button" + std::to_string(i)).c_str(), ImVec2(button_size, button_size))) {
wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, i + 1));
}
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));
ImGui::TextUnformatted(_L((boost::format("Shortcut key %1%") % (i + 1)).str()).ToUTF8().data());
ImGui::TextUnformatted((boost::format(_u8L("Shortcut key %1%")) % (i + 1)).str().c_str());
ImGui::PopStyleColor(1);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
@ -7402,82 +7618,30 @@ void GLCanvas3D::_render_paint_toolbar() const
ImGui::PopStyleColor(3);
if (disabled)
ImGui::PopItemFlag();
ImGui::PopID();
}
float text_offset_y = 3.0f * f_scale;
for (int i = 0; i < extruder_num; i++){
if (filament_types.size() <= i) continue;
//TODO use filament type from filament management, current use PLA by default
std::string item_text = (boost::format("%1%%2%") % (i + 1) % filament_types[i]).str();
const ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
int len = strlen(filament_types[i].c_str());
ImGui::SameLine(item_spacing / 2 + (button_size - max_text) / 2 + (button_size + item_spacing) * i);
int count = 0;
if (label_size.x > button_size)
{
for (int j = 0; j < filament_types[i].size(); j++)
{
if(std::isalpha(filament_types[i][j]))
count++;
else
break;
}
}
if (i > 8)
{
if (label_size.x > button_size)
{
if(count * ImGui::GetFontSize() > button_size){
if ((len - (count + 1)) <= 3)
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count) + "\n" + "\t" + filament_types[i].substr(count, len);
else
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n"+ filament_types[i].substr(count + 1, len);
} else {
if (count <= 4)
item_text = "\t" + std::to_string(i + 1) + "\n" + " " + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
else
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
}
}
else
{
item_text = (boost::format("\t%1%\n %2%") % (i + 1) % filament_types[i]).str();
}
}
else
{
if (label_size.x > button_size)
{
if(count * ImGui::GetFontSize() > button_size){
if ((len - (count + 1)) <= 3)
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count) + "\n" + "\t" + filament_types[i].substr(count, len);
else
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n"+ filament_types[i].substr(count + 1, len);
} else {
if (count <= 4)
item_text = "\t " + std::to_string(i + 1) + "\n" + " " + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
else
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
}
}
else
{
item_text = (boost::format("\t %1%\n\t%2%") % (i + 1) % filament_types[i]).str();
}
}
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
float gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
ImVec4 text_color = gray < 80 ? ImVec4(255, 255, 255, 255) : ImVec4(0, 0, 0, 255);
ImVec2 number_label_size = ImGui::CalcTextSize(std::to_string(i + 1).c_str());
ImGui::SetCursorPosY(cursor_y + text_offset_y);
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - number_label_size.x) / 2);
ImGui::TextColored(text_color, std::to_string(i + 1).c_str());
if (gray < 80){
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), item_text.c_str());
} else{
ImGui::TextColored(ImVec4(0.0f, 0.0f, 0.0f, 1.0f), item_text.c_str());
}
ImVec2 filament_first_line_label_size = ImGui::CalcTextSize(filament_text_first_line[i].c_str());
ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y);
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - filament_first_line_label_size.x) / 2);
ImGui::TextColored(text_color, filament_text_first_line[i].c_str());
ImVec2 filament_second_line_label_size = ImGui::CalcTextSize(filament_text_second_line[i].c_str());
ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y + filament_first_line_label_size.y);
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - filament_second_line_label_size.x) / 2);
ImGui::TextColored(text_color, filament_text_second_line[i].c_str());
}
ImGui::AlignTextToFramePadding();
imgui.end();
}

View file

@ -543,6 +543,7 @@ private:
bool m_dirty;
bool m_initialized;
//BBS: add flag to controll rendering
bool m_render_preview{ true };
bool m_enable_render { true };
bool m_apply_zoom_to_volumes_filter;
bool m_picking_enabled;
@ -785,6 +786,8 @@ public:
void enable_selection(bool enable);
void enable_main_toolbar(bool enable);
//BBS: GUI refactor: GLToolbar
void _update_select_plate_toolbar_stats_item(bool force_selected = false);
void reset_select_plate_toolbar_selection();
void enable_select_plate_toolbar(bool enable);
void enable_assemble_view_toolbar(bool enable);
void enable_return_toolbar(bool enable);
@ -847,6 +850,7 @@ public:
void select_all();
void deselect_all();
void set_selected_visible(bool visible);
void delete_selected();
void ensure_on_bed(unsigned int object_idx, bool allow_negative_z);
@ -893,6 +897,7 @@ public:
void on_gesture(wxGestureEvent& evt);
void on_paint(wxPaintEvent& evt);
void on_set_focus(wxFocusEvent& evt);
void force_set_focus();
Size get_canvas_size() const;
Vec2d get_local_mouse_position() const;
@ -1041,6 +1046,8 @@ public:
// If the Z screen space coordinate is not provided, a depth buffer value is substituted.
Vec3d _mouse_to_3d(const Point& mouse_pos, float* z = nullptr);
bool make_current_for_postinit();
private:
bool _is_shown_on_screen() const;
@ -1093,7 +1100,7 @@ private:
void _render_current_gizmo() const;
void _render_gizmos_overlay();
void _render_main_toolbar();
void _render_imgui_select_plate_toolbar() const;
void _render_imgui_select_plate_toolbar();
void _render_assemble_view_toolbar() const;
void _render_return_toolbar() const;
void _render_separator_toolbar_right() const;

View file

@ -584,12 +584,7 @@ bool GLTexture::generate_texture_from_text(const std::string& text_str, wxFont&
// draw message
memDC.SetTextForeground(*wxWHITE);
wxGCDC dc2(memDC);
dc2.SetFont(font);
dc2.SetBackground(wxBrush(background));
dc2.SetTextForeground(*wxWHITE);
dc2.DrawLabel(msg, wxRect(0, 0, m_width, m_height), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
memDC.DrawLabel(msg, wxRect(0, 0, m_width, m_height), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
memDC.SelectObject(wxNullBitmap);

View file

@ -39,6 +39,7 @@
#include <wx/textctrl.h>
#include <wx/splash.h>
#include <wx/fontutil.h>
#include <wx/glcanvas.h>
#include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp"
@ -86,8 +87,8 @@
//BBS: DailyTip and UserGuide Dialog
#include "WebDownPluginDlg.hpp"
#include "WebGuideDialog.hpp"
#include "WebUserLoginDialog.hpp"
#include "ReleaseNote.hpp"
#include "PrivacyUpdateDialog.hpp"
#include "ModelMall.hpp"
//#ifdef WIN32
@ -1016,25 +1017,31 @@ void GUI_App::post_init()
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
plater_->select_view_3D("3D");
//BBS init the opengl resource here
Size canvas_size = plater_->canvas3D()->get_canvas_size();
wxGetApp().imgui()->set_display_size(static_cast<float>(canvas_size.get_width()), static_cast<float>(canvas_size.get_height()));
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to init opengl";
wxGetApp().init_opengl();
#ifdef __linux__
if (plater_->canvas3D()->get_wxglcanvas()->IsShownOnScreen()&&plater_->canvas3D()->make_current_for_postinit()) {
#endif
Size canvas_size = plater_->canvas3D()->get_canvas_size();
wxGetApp().imgui()->set_display_size(static_cast<float>(canvas_size.get_width()), static_cast<float>(canvas_size.get_height()));
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to init opengl";
wxGetApp().init_opengl();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init opengl";
plater_->canvas3D()->init();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init opengl";
plater_->canvas3D()->init();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init canvas3D";
wxGetApp().imgui()->new_frame();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init canvas3D";
wxGetApp().imgui()->new_frame();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init imgui frame";
plater_->canvas3D()->enable_render(true);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init imgui frame";
plater_->canvas3D()->enable_render(true);
if (!slow_bootup) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to render a first frame for test";
plater_->canvas3D()->render(false);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test";
if (!slow_bootup) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to render a first frame for test";
plater_->canvas3D()->render(false);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test";
}
#ifdef __linux__
}
#endif
if (is_editor())
mainframe->select_tab(size_t(0));
mainframe->Thaw();
@ -1119,6 +1126,9 @@ void GUI_App::post_init()
//BBS: check new version
this->check_new_version_sf();
//BBS: check privacy version
if (is_user_login())
this->check_privacy_version(0);
});
}
@ -1155,6 +1165,9 @@ void GUI_App::post_init()
std::string functional_config_file = Slic3r::resources_dir() + "/config.json";
DeviceManager::load_functional_config(encode_path(functional_config_file.c_str()));
std::string filaments_blacklist_config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json";
DeviceManager::load_filaments_blacklist_config(encode_path(filaments_blacklist_config_file.c_str()));
// remove old log files over LOG_FILES_MAX_NUM
std::string log_addr = data_dir();
if (!log_addr.empty()) {
@ -1228,6 +1241,13 @@ void GUI_App::shutdown()
removable_drive_manager()->shutdown();
}
// destroy login dialog
if (login_dlg != nullptr) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": destroy login dialog");
delete login_dlg;
login_dlg = nullptr;
}
if (m_is_recreating_gui) return;
m_is_closing = true;
stop_sync_user_preset();
@ -1646,9 +1666,9 @@ void GUI_App::init_networking_callbacks()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": enter, m_agent=%1%")%m_agent;
if (m_agent) {
//set callbacks
m_agent->set_on_user_login_fn([this](int online_login, bool login) {
GUI::wxGetApp().request_user_login(online_login);
});
//m_agent->set_on_user_login_fn([this](int online_login, bool login) {
// GUI::wxGetApp().request_user_handle(online_login);
// });
m_agent->set_on_server_connected_fn([this]() {
if (m_is_closing) {
@ -1708,6 +1728,7 @@ void GUI_App::init_networking_callbacks()
event.SetString(obj->dev_id);
} else if (state == ConnectStatus::ConnectStatusFailed) {
obj->set_access_code("");
obj->set_user_access_code("");
m_device_manager->set_selected_machine("");
wxString text;
if (msg == "5") {
@ -1748,8 +1769,9 @@ void GUI_App::init_networking_callbacks()
obj->is_ams_need_update = false;
obj->parse_json(msg);
if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->amsList);
auto sel = this->m_device_manager->get_selected_machine();
if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj->amsList);
}
}
});
@ -1773,7 +1795,7 @@ void GUI_App::init_networking_callbacks()
if (obj) {
obj->parse_json(msg);
if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj->amsList);
}
}
});
@ -1856,10 +1878,8 @@ void GUI_App::init_download_path()
fs::path dp(down_path);
if (!fs::exists(dp)) {
if (!fs::create_directory(dp)) {
std::string user_down_path = wxStandardPaths::Get().GetUserDir(wxStandardPaths::Dir_Downloads).ToUTF8().data();
app_config->set("download_path", user_down_path);
}
std::string user_down_path = wxStandardPaths::Get().GetUserDir(wxStandardPaths::Dir_Downloads).ToUTF8().data();
app_config->set("download_path", user_down_path);
}
}
}
@ -1978,6 +1998,14 @@ void GUI_App::init_http_extra_header()
m_agent->set_extra_http_header(extra_headers);
}
void GUI_App::update_http_extra_header()
{
std::map<std::string, std::string> extra_headers = get_extra_header();
Slic3r::Http::set_extra_headers(extra_headers);
if (m_agent)
m_agent->set_extra_http_header(extra_headers);
}
std::string GUI_App::get_local_models_path()
{
std::string local_path = "";
@ -2064,7 +2092,7 @@ bool GUI_App::on_init_inner()
}
}
for (auto d : dialogStack)
d->EndModal(wxID_CANCEL);
d->EndModal(wxID_ABORT);
});
std::map<std::string, std::string> extra_headers = get_extra_header();
@ -2123,7 +2151,7 @@ bool GUI_App::on_init_inner()
#endif // __APPLE__
bool init_dark_color_mode = app_config->get("dark_color_mode") == "1";
bool init_dark_color_mode = dark_mode();
bool init_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1";
#ifdef __WINDOWS__
NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled);
@ -2138,7 +2166,7 @@ bool GUI_App::on_init_inner()
#ifdef _MSW_DARK_MODE
// app_config can be updated in check_older_app_config(), so check if dark_color_mode and sys_menu_enabled was changed
if (bool new_dark_color_mode = app_config->get("dark_color_mode") == "1";
if (bool new_dark_color_mode = dark_mode();
init_dark_color_mode != new_dark_color_mode) {
#ifdef __WINDOWS__
@ -2325,7 +2353,13 @@ bool GUI_App::on_init_inner()
// Suppress the '- default -' presets.
preset_bundle->set_default_suppressed(true);
Bind(EVT_SET_SELECTED_MACHINE, &GUI_App::on_set_selected_machine, this);
Bind(EVT_USER_LOGIN, &GUI_App::on_user_login, this);
Bind(EVT_USER_LOGIN_HANDLE, &GUI_App::on_user_login_handle, this);
Bind(EVT_CHECK_PRIVACY_VER, &GUI_App::on_check_privacy_update, this);
Bind(EVT_CHECK_PRIVACY_SHOW, &GUI_App::show_check_privacy_dlg, this);
Bind(EVT_SHOW_IP_DIALOG, &GUI_App::show_ip_address_enter_dialog_handler, this);
Bind(EVT_SHOW_IP_DIALOG, &GUI_App::show_ip_address_enter_dialog_handler, this);
@ -2334,6 +2368,8 @@ bool GUI_App::on_init_inner()
if (m_agent && m_agent->is_user_login()) {
enable_user_preset_folder(true);
} else {
enable_user_preset_folder(false);
}
// BBS if load user preset failed
@ -2349,13 +2385,11 @@ bool GUI_App::on_init_inner()
}
//}
if (app_config->get("sync_user_preset") == "true") {
//BBS loading user preset
BOOST_LOG_TRIVIAL(info) << "Loading user presets...";
scrn->SetText(_L("Loading user presets..."));
// Always async, not such startup step
//BOOST_LOG_TRIVIAL(info) << "Loading user presets...";
//scrn->SetText(_L("Loading user presets..."));
if (m_agent) {
start_sync_user_preset();
}
@ -2798,6 +2832,7 @@ void GUI_App::UpdateDarkUIWin(wxWindow* win)
void GUI_App::Update_dark_mode_flag()
{
m_is_dark_mode = dark_mode();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": switch the current dark mode status to %1% ")%m_is_dark_mode;
}
void GUI_App::UpdateDlgDarkUI(wxDialog* dlg)
@ -3075,6 +3110,11 @@ void GUI_App::ShowUserGuide() {
void GUI_App::ShowDownNetPluginDlg() {
try {
auto iter = std::find_if(dialogStack.begin(), dialogStack.end(), [](auto dialog) {
return dynamic_cast<DownloadProgressDialog *>(dialog) != nullptr;
});
if (iter != dialogStack.end())
return;
DownloadProgressDialog dlg(_L("Downloading Bambu Network Plug-in"));
dlg.ShowModal();
} catch (std::exception &e) {
@ -3082,14 +3122,24 @@ void GUI_App::ShowDownNetPluginDlg() {
}
}
void GUI_App::ShowUserLogin()
void GUI_App::ShowUserLogin(bool show)
{
// BBS: User Login Dialog
try {
ZUserLogin LoginDlg;
LoginDlg.ShowModal();
} catch (std::exception &e) {
// wxMessageBox(e.what(), "", MB_OK);
if (show) {
try {
if (!login_dlg)
login_dlg = new ZUserLogin();
else {
delete login_dlg;
login_dlg = new ZUserLogin();
}
login_dlg->ShowModal();
} catch (std::exception &e) {
;
}
} else {
if (login_dlg)
login_dlg->EndModal(wxID_OK);
}
}
@ -3168,7 +3218,7 @@ void GUI_App::force_colors_update()
{
#ifdef _MSW_DARK_MODE
#ifdef __WINDOWS__
NppDarkMode::SetDarkMode(app_config->get("dark_color_mode") == "1");
NppDarkMode::SetDarkMode(dark_mode());
if (WXHWND wxHWND = wxToolTip::GetToolTipCtrl())
NppDarkMode::SetDarkExplorerTheme((HWND)wxHWND);
NppDarkMode::SetDarkTitleBar(mainframe->GetHWND());
@ -3321,6 +3371,13 @@ bool GUI_App::check_login()
return result;
}
void GUI_App::request_user_handle(int online_login)
{
auto evt = new wxCommandEvent(EVT_USER_LOGIN_HANDLE);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
}
void GUI_App::request_user_login(int online_login)
{
auto evt = new wxCommandEvent(EVT_USER_LOGIN);
@ -3339,12 +3396,9 @@ void GUI_App::request_user_logout()
m_agent->user_logout();
m_agent->set_user_selected_machine("");
BOOST_LOG_TRIVIAL(info) << "preset_folder: set to empty, user_logout";
enable_user_preset_folder(false);
/* delete old user settings */
m_device_manager->clean_user_info();
GUI::wxGetApp().sidebar().load_ams_list({});
GUI::wxGetApp().remove_user_presets();
GUI::wxGetApp().sidebar().load_ams_list({}, {});
GUI::wxGetApp().stop_sync_user_preset();
#ifdef __WINDOWS__
@ -3375,11 +3429,6 @@ std::string GUI_App::handle_web_request(std::string cmd)
std::string web_cmd = j["command"].get<std::string>();
if (web_cmd == "request_model_download") {
/* json j_data = j["data"];
json import_j;*/
/* import_j["model_id"] = j["data"]["model_id"].get<std::string>();
import_j["profile_id"] = j["data"]["profile_id"].get<std::string>();*/
std::string download_url = "";
if (j["data"].contains("download_url"))
download_url = j["data"]["download_url"].get<std::string>();
@ -3575,7 +3624,7 @@ void GUI_App::request_model_download(std::string url, std::string filename)
if (!check_login()) return;
if (plater_) {
plater_->request_model_download(url, filename);
plater_->request_model_download();
}
}
@ -3685,7 +3734,15 @@ void GUI_App::enable_user_preset_folder(bool enable)
}
}
void GUI_App::on_user_login(wxCommandEvent &evt)
void GUI_App::on_set_selected_machine(wxCommandEvent &evt)
{
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev || m_agent) return;
dev->set_selected_machine(m_agent->get_user_selected_machine());
}
void GUI_App::on_user_login_handle(wxCommandEvent &evt)
{
if (!m_agent) { return; }
@ -3695,8 +3752,12 @@ void GUI_App::on_user_login(wxCommandEvent &evt)
// get machine list
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
dev->update_user_machine_list_info();
dev->set_selected_machine(m_agent->get_user_selected_machine());
boost::thread update_thread = boost::thread([this, dev] {
dev->update_user_machine_list_info();
auto evt = new wxCommandEvent(EVT_SET_SELECTED_MACHINE);
wxQueueEvent(this, evt);
});
// if (app_config->get("sync_user_preset") == "true") {
enable_user_preset_folder(true);
@ -3723,6 +3784,14 @@ void GUI_App::on_user_login(wxCommandEvent &evt)
}
}
void GUI_App::on_user_login(wxCommandEvent &evt)
{
if (!m_agent) { return; }
int online_login = evt.GetInt();
// check privacy before handle
check_privacy_version(online_login);
}
bool GUI_App::is_studio_active()
{
auto curr_time = std::chrono::system_clock::now();
@ -3947,6 +4016,113 @@ void GUI_App::set_skip_version(bool skip)
}
}
void GUI_App::show_check_privacy_dlg(wxCommandEvent& evt)
{
int online_login = evt.GetInt();
PrivacyUpdateDialog privacy_dlg(this->mainframe, wxID_ANY, _L("Privacy Policy Update"));
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CONFIRM, [this, online_login](wxCommandEvent &e) {
app_config->set("privacy_version", privacy_version_info.version_str);
app_config->set_bool("privacy_update_checked", true);
app_config->save();
request_user_handle(online_login);
});
privacy_dlg.Bind(EVT_PRIVACY_UPDATE_CANCEL, [this](wxCommandEvent &e) {
app_config->set_bool("privacy_update_checked", false);
app_config->save();
if (m_agent) {
m_agent->user_logout();
}
});
privacy_dlg.set_text(privacy_version_info.description);
privacy_dlg.on_show();
}
void GUI_App::on_show_check_privacy_dlg(int online_login)
{
auto evt = new wxCommandEvent(EVT_CHECK_PRIVACY_SHOW);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
}
bool GUI_App::check_privacy_update()
{
if (privacy_version_info.version_str.empty() || privacy_version_info.description.empty()
|| privacy_version_info.url.empty()) {
return false;
}
std::string local_privacy_ver = app_config->get("privacy_version");
auto curr_version = Semver::parse(local_privacy_ver);
auto remote_version = Semver::parse(privacy_version_info.version_str);
if (curr_version && remote_version) {
if (*remote_version > *curr_version || app_config->get("privacy_update_checked") != "true") {
return true;
}
}
return false;
}
void GUI_App::on_check_privacy_update(wxCommandEvent& evt)
{
int online_login = evt.GetInt();
bool result = check_privacy_update();
if (result)
on_show_check_privacy_dlg(online_login);
else
request_user_handle(online_login);
}
void GUI_App::check_privacy_version(int online_login)
{
update_http_extra_header();
std::string query_params = "?policy/privacy=00.00.00.00";
std::string url = get_http_url(app_config->get_country_code()) + query_params;
Slic3r::Http http = Slic3r::Http::get(url);
http.header("accept", "application/json")
.timeout_connect(TIMEOUT_CONNECT)
.timeout_max(TIMEOUT_RESPONSE)
.on_complete([this, online_login](std::string body, unsigned) {
try {
json j = json::parse(body);
if (j.contains("message")) {
if (j["message"].get<std::string>() == "success") {
if (j.contains("resources")) {
for (auto it = j["resources"].begin(); it != j["resources"].end(); it++) {
if (it->contains("type")) {
if ((*it)["type"] == std::string("policy/privacy")
&& it->contains("version")
&& it->contains("description")
&& it->contains("url")
&& it->contains("force_update")) {
privacy_version_info.version_str = (*it)["version"].get<std::string>();
privacy_version_info.description = (*it)["description"].get<std::string>();
privacy_version_info.url = (*it)["url"].get<std::string>();
privacy_version_info.force_upgrade = (*it)["force_update"].get<bool>();
break;
}
}
}
CallAfter([this, online_login]() {
auto evt = new wxCommandEvent(EVT_CHECK_PRIVACY_VER);
evt->SetInt(online_login);
wxQueueEvent(this, evt);
});
}
}
}
}
catch (...) {
request_user_handle(online_login);
}
})
.on_error([this, online_login](std::string body, std::string error, unsigned int status) {
request_user_handle(online_login);
BOOST_LOG_TRIVIAL(error) << "check privacy version error" << body;
}).perform();
}
void GUI_App::no_new_version()
{
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_NO_NEW_VERSION);
@ -3986,17 +4162,19 @@ void GUI_App::reload_settings()
m_agent->get_user_presets(&user_presets);
preset_bundle->load_user_presets(*app_config, user_presets, ForwardCompatibilitySubstitutionRule::Enable);
preset_bundle->save_user_presets(*app_config, get_delete_cache_presets());
mainframe->update_side_preset_ui();
}
}
//BBS reload when login
//BBS reload when logout
void GUI_App::remove_user_presets()
{
if (preset_bundle && m_agent) {
preset_bundle->remove_users_preset(*app_config);
std::string user_id = m_agent->get_user_id();
preset_bundle->remove_user_presets_directory(user_id);
// Not remove user preset cache
//std::string user_id = m_agent->get_user_id();
//preset_bundle->remove_user_presets_directory(user_id);
//update ui
mainframe->update_side_preset_ui();
@ -4110,9 +4288,9 @@ void GUI_App::sync_preset(Preset* preset)
}
}
void GUI_App::start_sync_user_preset(bool with_progress_dlg)
void GUI_App::start_sync_user_preset(bool load_immediately, bool with_progress_dlg)
{
if (!m_agent) return;
if (!m_agent || !m_agent->is_user_login()) return;
enable_user_preset_folder(true);
@ -4120,32 +4298,51 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
if (enable_sync)
return;
if (m_agent->is_user_login()) {
// get setting list, update setting list
std::string version = preset_bundle->get_vendor_profile_version(PresetBundle::BBL_BUNDLE).to_string();
if (with_progress_dlg) {
ProgressDialog dlg(_L("Loading"), "", 100, this->mainframe, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
dlg.Update(0, _L("Loading user preset"));
m_agent->get_setting_list(version,
[this, &dlg](int percent){
dlg.Update(percent, _L("Loading user preset"));
},
[this, &dlg]() {
dlg.GetValue();
bool cont = dlg.Update(dlg.GetValue(), _L("Loading user preset"));
return !cont;
});
} else {
m_agent->get_setting_list(version);
}
GUI::wxGetApp().reload_settings();
if (load_immediately) {
preset_bundle->load_user_presets(m_agent->get_user_id(), ForwardCompatibilitySubstitutionRule::Enable);
mainframe->update_side_preset_ui();
}
ProgressFn progressFn;
WasCancelledFn cancelFn;
std::function<void()> finishFn;
if (with_progress_dlg) {
auto dlg = new ProgressDialog(_L("Loading"), "", 100, this->mainframe, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
dlg->Update(0, _L("Loading user preset"));
progressFn = [this, dlg](int percent) {
CallAfter([=]{
dlg->Update(percent, _L("Loading user preset"));
});
};
cancelFn = [dlg]() {
return dlg->WasCanceled();
};
finishFn = [this, dlg] {
CallAfter([=]{
dlg->Destroy();
reload_settings();
});
};
}
else {
finishFn = [this] {
CallAfter([=] {
reload_settings();
});
};
}
BOOST_LOG_TRIVIAL(info) << "start_sync_service...";
//BBS
enable_sync = true;
m_sync_update_thread = Slic3r::create_thread(
[this] {
[this, progressFn, cancelFn, finishFn] {
// get setting list, update setting list
std::string version = preset_bundle->get_vendor_profile_version(PresetBundle::BBL_BUNDLE).to_string();
m_agent->get_setting_list(version, progressFn, cancelFn);
finishFn();
int count = 0, sync_count = 0;
std::vector<Preset> presets_to_sync;
while (enable_sync) {
@ -4182,12 +4379,13 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
unsigned int http_code = 200;
/* get list witch need to be deleted*/
std::vector<string>& delete_cache_presets = get_delete_cache_presets();
std::vector<string> delete_cache_presets = get_delete_cache_presets_lock();
for (auto it = delete_cache_presets.begin(); it != delete_cache_presets.end();) {
if ((*it).empty()) continue;
std::string del_setting_id = *it;
int result = m_agent->delete_setting(del_setting_id);
if (result == 0) {
preset_deleted_from_cloud(del_setting_id);
it = delete_cache_presets.erase(it);
BOOST_LOG_TRIVIAL(trace) << "sync_preset: sync operation: delete success! setting id = " << del_setting_id;
}
@ -4206,6 +4404,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
void GUI_App::stop_sync_user_preset()
{
remove_user_presets();
enable_user_preset_folder(false);
if (!enable_sync)
@ -4216,6 +4415,16 @@ void GUI_App::stop_sync_user_preset()
m_sync_update_thread.join();
}
void GUI_App::start_http_server()
{
if (!m_http_server.is_started())
m_http_server.start();
}
void GUI_App::stop_http_server()
{
m_http_server.stop();
}
bool GUI_App::switch_language()
{
if (select_language()) {
@ -4412,7 +4621,8 @@ bool GUI_App::load_language(wxString language, bool initial)
{"fr", wxString::FromUTF8("\x46\x72\x61\x6E\xC3\xA7\x61\x69\x73")},
{"it", wxString::FromUTF8("\x49\x74\x61\x6C\x69\x61\x6E\x6F")},
{"ru", wxString::FromUTF8("\xD1\x80\xD1\x83\xD1\x81\xD1\x81\xD0\xBA\xD0\xB8\xD0\xB9")},
{"hu", wxString::FromUTF8("Magyar")}
{"hu", wxString::FromUTF8("Magyar")},
{"ja", wxString::FromUTF8("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E")}
};
for (auto l : language_descptions) {
const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(l.first);
@ -4517,7 +4727,9 @@ bool GUI_App::load_language(wxString language, bool initial)
wxLANGUAGE_SPANISH,
wxLANGUAGE_SWEDISH,
wxLANGUAGE_DUTCH,
wxLANGUAGE_HUNGARIAN};
wxLANGUAGE_HUNGARIAN,
wxLANGUAGE_JAPANESE
};
std::string cur_language = app_config->get("language");
if (cur_language != "") {
//cleanup the language wrongly set before
@ -5027,7 +5239,12 @@ bool GUI_App::check_and_keep_current_preset_changes(const wxString& caption, con
static_cast<TabPrinter*>(tab)->cache_extruder_cnt();
}
}
tab->cache_config_diff(selected_options);
std::vector<std::string> selected_options2;
std::transform(selected_options.begin(), selected_options.end(), std::back_inserter(selected_options2), [](auto & o) {
auto i = o.find('#');
return i != std::string::npos ? o.substr(0, i) : o;
});
tab->cache_config_diff(selected_options2);
if (!is_called_from_configwizard)
tab->m_presets->discard_current_changes();
}
@ -5114,16 +5331,31 @@ void GUI_App::load_current_presets(bool active_preset_combox/*= false*/, bool ch
}
}
std::vector<std::string>& GUI_App::get_delete_cache_presets()
static std::mutex mutex_delete_cache_presets;
std::vector<std::string> & GUI_App::get_delete_cache_presets()
{
return need_delete_presets;
}
std::vector<std::string> GUI_App::get_delete_cache_presets_lock()
{
std::scoped_lock l(mutex_delete_cache_presets);
return need_delete_presets;
}
void GUI_App::delete_preset_from_cloud(std::string setting_id)
{
std::scoped_lock l(mutex_delete_cache_presets);
need_delete_presets.push_back(setting_id);
}
void GUI_App::preset_deleted_from_cloud(std::string setting_id)
{
std::scoped_lock l(mutex_delete_cache_presets);
need_delete_presets.erase(std::remove(need_delete_presets.begin(), need_delete_presets.end(), setting_id), need_delete_presets.end());
}
bool GUI_App::OnExceptionInMainLoop()
{
generic_exception_handle();

View file

@ -11,8 +11,10 @@
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/GUI/WebViewDialog.hpp"
#include "slic3r/GUI/WebUserLoginDialog.hpp"
#include "slic3r/GUI/HMS.hpp"
#include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp"
#include "slic3r/GUI/HttpServer.hpp"
#include "../Utils/PrintHost.hpp"
#include <wx/app.h>
@ -274,7 +276,11 @@ private:
bool m_networking_cancel_update { false };
std::shared_ptr<UpgradeNetworkJob> m_upgrade_network_job;
// login widget
ZUserLogin* login_dlg { nullptr };
VersionInfo version_info;
VersionInfo privacy_version_info;
static std::string version_display;
HMSQuery *hms_query { nullptr };
@ -283,7 +289,9 @@ private:
bool m_is_dark_mode{ false };
bool m_adding_script_handler { false };
bool m_side_popup_status{false};
HttpServer m_http_server;
public:
void check_filaments_in_blacklist(std::string tag_supplier, std::string tag_material, bool& in_blacklist, std::string& action, std::string& info);
std::string get_local_models_path();
bool OnInit() override;
bool initialized() const { return m_initialized; }
@ -380,7 +388,7 @@ public:
wxString transition_tridid(int trid_id);
void ShowUserGuide();
void ShowDownNetPluginDlg();
void ShowUserLogin();
void ShowUserLogin(bool show = true);
void ShowOnlyFilament();
//BBS
void request_login(bool show_user_info = false);
@ -388,7 +396,8 @@ public:
void get_login_info();
bool is_user_login();
void request_user_login(int online_login);
void request_user_login(int online_login = 0);
void request_user_handle(int online_login = 0);
void request_user_logout();
int request_user_unbind(std::string dev_id);
std::string handle_web_request(std::string cmd);
@ -401,7 +410,9 @@ public:
void handle_http_error(unsigned int status, std::string body);
void on_http_error(wxCommandEvent &evt);
void on_set_selected_machine(wxCommandEvent& evt);
void on_user_login(wxCommandEvent &evt);
void on_user_login_handle(wxCommandEvent& evt);
void enable_user_preset_folder(bool enable);
// BBS
@ -422,8 +433,16 @@ public:
void reload_settings();
void remove_user_presets();
void sync_preset(Preset* preset);
void start_sync_user_preset(bool with_progress_dlg = false);
void start_sync_user_preset(bool load_immediately = false, bool with_progress_dlg = false);
void stop_sync_user_preset();
void start_http_server();
void stop_http_server();
void on_show_check_privacy_dlg(int online_login = 0);
void show_check_privacy_dlg(wxCommandEvent& evt);
void on_check_privacy_update(wxCommandEvent &evt);
bool check_privacy_update();
void check_privacy_version(int online_login = 0);
static bool catch_error(std::function<void()> cb, const std::string& err);
@ -457,8 +476,10 @@ public:
bool checked_tab(Tab* tab);
//BBS: add preset combox re-active logic
void load_current_presets(bool active_preset_combox = false, bool check_printer_presets = true);
std::vector<std::string>& get_delete_cache_presets();
std::vector<std::string> &get_delete_cache_presets();
std::vector<std::string> get_delete_cache_presets_lock();
void delete_preset_from_cloud(std::string setting_id);
void preset_deleted_from_cloud(std::string setting_id);
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
@ -486,13 +507,21 @@ public:
Model& model();
NotificationManager * notification_manager();
std::string m_mall_model_download_url;
std::string m_mall_model_download_name;
ModelMallDialog* m_mall_home_dialog{ nullptr };
ModelMallDialog* m_mall_publish_dialog{ nullptr };
void set_download_model_url(std::string url) {m_mall_model_download_url = url;}
void set_download_model_name(std::string name) {m_mall_model_download_name = name;}
std::string get_download_model_url() {return m_mall_model_download_url;}
std::string get_download_model_name() {return m_mall_model_download_name;}
void load_url(wxString url);
void open_mall_page_dialog();
void open_publish_page_dialog();
void remove_mall_system_dialog();
void remove_mall_system_dialog();
void run_script(wxString js);
bool is_adding_script_handler() { return m_adding_script_handler; }
void set_adding_script_handler(bool status) { m_adding_script_handler = status; }
@ -574,6 +603,7 @@ private:
//BBS set extra header for http request
std::map<std::string, std::string> get_extra_header();
void init_http_extra_header();
void update_http_extra_header();
bool check_older_app_config(Semver current_version, bool backup);
void copy_older_config();
void window_pos_save(wxTopLevelWindow* window, const std::string &name);

View file

@ -432,6 +432,19 @@ std::vector<wxBitmap> MenuFactory::get_volume_bitmaps()
return volume_bmps;
}
void MenuFactory::append_menu_item_set_visible(wxMenu* menu)
{
bool has_one_shown = false;
const Selection& selection = plater()->canvas3D()->get_selection();
for (unsigned int i : selection.get_volume_idxs()) {
has_one_shown |= selection.get_volume(i)->visible;
}
append_menu_item(menu, wxID_ANY, has_one_shown ?_L("Hide") : _L("Show"), "",
[has_one_shown](wxCommandEvent&) { plater()->set_selected_visible(!has_one_shown); }, "", nullptr,
[]() { return true; }, m_parent);
}
void MenuFactory::append_menu_item_delete(wxMenu* menu)
{
#ifdef __WINDOWS__
@ -445,6 +458,19 @@ void MenuFactory::append_menu_item_delete(wxMenu* menu)
#endif
}
void MenuFactory::append_menu_item_edit_text(wxMenu *menu)
{
#ifdef __WINDOWS__
append_menu_item(
menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr,
[]() { return plater()->can_edit_text(); }, m_parent);
#else
append_menu_item(
menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr,
[]() { return plater()->can_edit_text(); }, m_parent);
#endif
}
wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType type) {
auto sub_menu = new wxMenu;
@ -735,6 +761,8 @@ void MenuFactory::append_menu_items_flush_options(wxMenu* menu)
bool show_flush_option_menu = false;
ObjectList* object_list = obj_list();
const Selection& selection = get_selection();
if (selection.get_object_idx() < 0)
return;
if (wxGetApp().plater()->get_partplate_list().get_curr_plate()->contains(selection.get_bounding_box())) {
auto plate_extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders();
for (auto extruder : plate_extruders) {
@ -784,7 +812,7 @@ void MenuFactory::append_menu_items_flush_options(wxMenu* menu)
{
i++;
wxMenuItem* item = node->GetData();
if (item->GetItemLabelText() == "Edit in Parameter Table")
if (item->GetItemLabelText() == _L("Edit in Parameter Table"))
break;
}
menu->Insert(i, wxID_ANY, _L("Flush Options"), flush_options_menu);
@ -1057,6 +1085,7 @@ void MenuFactory::create_bbl_part_menu()
wxMenu* menu = &m_part_menu;
append_menu_item_delete(menu);
append_menu_item_edit_text(menu);
append_menu_item_fix_through_netfabb(menu);
append_menu_item_simplify(menu);
append_menu_item_center(menu);
@ -1310,8 +1339,9 @@ wxMenu* MenuFactory::assemble_multi_selection_menu()
return nullptr;
wxMenu* menu = new MenuWithSeparators();
append_menu_item_fix_through_netfabb(menu);
append_menu_item_simplify(menu);
append_menu_item_set_visible(menu);
//append_menu_item_fix_through_netfabb(menu);
//append_menu_item_simplify(menu);
append_menu_item_delete(menu);
menu->AppendSeparator();
append_menu_item_change_extruder(menu);
@ -1328,18 +1358,36 @@ wxMenu* MenuFactory::plate_menu()
wxMenu* MenuFactory::assemble_object_menu()
{
wxMenu* menu = new MenuWithSeparators();
// Set Visible
append_menu_item_set_visible(menu);
// Delete
append_menu_item_delete(menu);
//// Object Repair
//append_menu_item_fix_through_netfabb(menu);
//// Object Simplify
//append_menu_item_simplify(menu);
menu->AppendSeparator();
// Set filament
append_menu_item_change_extruder(&m_assemble_object_menu);
// Enter per object parameters
append_menu_item_per_object_settings(&m_assemble_object_menu);
return &m_assemble_object_menu;
append_menu_item_change_extruder(menu);
//// Enter per object parameters
//append_menu_item_per_object_settings(menu);
return menu;
}
wxMenu* MenuFactory::assemble_part_menu()
{
append_menu_item_change_extruder(&m_assemble_part_menu);
append_menu_item_per_object_settings(&m_assemble_part_menu);
return &m_assemble_part_menu;
wxMenu* menu = new MenuWithSeparators();
append_menu_item_set_visible(menu);
append_menu_item_delete(menu);
//append_menu_item_simplify(menu);
menu->AppendSeparator();
append_menu_item_change_extruder(menu);
//append_menu_item_per_object_settings(menu);
return menu;
}
void MenuFactory::append_menu_item_clone(wxMenu* menu)
@ -1509,7 +1557,7 @@ void MenuFactory::append_menu_item_set_printable(wxMenu* menu)
}
}
wxString menu_text = all_printable ? L("Set Unprintable") : _L("Set Printable");
wxString menu_text = all_printable ? _L("Set Unprintable") : _L("Set Printable");
append_menu_item(menu, wxID_ANY, menu_text, "", [this, all_printable](wxCommandEvent&) {
Selection& selection = plater()->canvas3D()->get_selection();
selection.set_printable(!all_printable);

View file

@ -126,7 +126,9 @@ private:
void append_menu_item_reload_from_disk(wxMenu* menu);
void append_menu_item_replace_with_stl(wxMenu* menu);
void append_menu_item_change_extruder(wxMenu* menu);
void append_menu_item_set_visible(wxMenu* menu);
void append_menu_item_delete(wxMenu* menu);
void append_menu_item_edit_text(wxMenu *menu);
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
void append_menu_items_convert_unit(wxMenu* menu); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
void append_menu_items_flush_options(wxMenu* menu);

View file

@ -30,6 +30,7 @@
#include "slic3r/Utils/FixModelByWin10.hpp"
#include "libslic3r/Format/bbs_3mf.hpp"
#include "libslic3r/PrintConfig.hpp"
#ifdef __WXMSW__
#include "wx/uiaction.h"
@ -91,6 +92,9 @@ ObjectList::ObjectList(wxWindow* parent) :
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent& event) {
// detect the current mouse position here, to pass it to list_manipulation() method
// if we detect it later, the user may have moved the mouse pointer while calculations are performed, and this would mess-up the HitTest() call performed into list_manipulation()
if (!GetScreenRect().Contains(wxGetMousePosition())) {
return;
}
#ifndef __WXOSX__
const wxPoint mouse_pos = this->get_mouse_position_in_control();
#endif
@ -731,7 +735,7 @@ void ObjectList::printable_state_changed(const std::vector<ObjectVolumeID>& ov_i
obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
// update printable state on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
// update scene
wxGetApp().plater()->update();
@ -1397,8 +1401,21 @@ void ObjectList::key_event(wxKeyEvent& event)
void ObjectList::OnBeginDrag(wxDataViewEvent &event)
{
bool sequential_print = (wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
if (!sequential_print) {
int curr_obj_id = m_objects_model->GetIdByItem(event.GetItem());
PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list();
int from_plate = partplate_list.find_instance(curr_obj_id, 0);
if (from_plate == -1) {
event.Veto();
return;
}
auto curr_plate_seq = partplate_list.get_plate(from_plate)->get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has("print_sequence"))
curr_plate_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
}
if (curr_plate_seq != PrintSequence::ByObject) {
//drag forbidden under bylayer mode
event.Veto();
return;
@ -1777,7 +1794,7 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
if (type == ModelVolumeType::MODEL_PART)
// update printable state on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
if (items.size() > 1) {
m_selection_mode = smVolume;
@ -1923,11 +1940,9 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
ModelVolume* new_volume = model_object.add_volume(std::move(mesh), type);
new_volume->name = boost::filesystem::path(input_file).filename().string();
// adjust the position according to the bounding box
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
auto offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - v->get_instance_offset();
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
// BBS: object_mesh.get_init_shift() keep the relative position
TriangleMesh object_mesh = model_object.volumes[0]->mesh();
new_volume->set_offset(new_volume->mesh().get_init_shift() - object_mesh.get_init_shift());
// set a default extruder value, since user can't add it manually
// BBS
@ -2055,7 +2070,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
});
if (type == ModelVolumeType::MODEL_PART)
// update printable state on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
// apply the instance transform to all volumes and reset instance transform except the offset
apply_object_instance_transfrom_to_all_volumes(&model_object);
@ -2158,50 +2173,54 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name
#endif /* _DEBUG */
}
void ObjectList::load_mesh_part(const TriangleMesh& mesh, const wxString& name, bool center)
int ObjectList::load_mesh_part(const TriangleMesh &mesh, const wxString &name, const TextInfo &text_info, bool is_temp)
{
wxDataViewItem item = GetSelection();
// we can add volumes for Object or Instance
if (!item || !(m_objects_model->GetItemType(item) & (itObject | itInstance)))
return;
return -1;
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
if (obj_idx < 0) return;
if (obj_idx < 0)
return -1;
// Get object item, if Instance is selected
if (m_objects_model->GetItemType(item) & itInstance)
item = m_objects_model->GetItemById(obj_idx);
take_snapshot("Load Mesh Part");
ModelObject* mo = (*m_objects)[obj_idx];
Geometry::Transformation instance_transformation = mo->instances[0]->get_transformation();
// apply the instance transform to all volumes and reset instance transform except the offset
apply_object_instance_transfrom_to_all_volumes(mo);
apply_object_instance_transfrom_to_all_volumes(mo, !is_temp);
ModelVolume* mv = mo->add_volume(mesh);
Vec3d instance_bbox = mo->mesh().bounding_box().size();
Vec3d offset = Vec3d(0, 0, instance_bbox[2] / 2);
mv->set_offset(offset);
ModelVolume *mv = mo->add_volume(mesh);
mv->name = name.ToStdString();
if (!text_info.m_text.empty())
mv->set_text_info(text_info);
std::vector<ModelVolume*> volumes;
volumes.push_back(mv);
wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume* volume) {
return std::find(volumes.begin(), volumes.end(), volume) != volumes.end(); });
if (!is_temp) {
std::vector<ModelVolume *> volumes;
volumes.push_back(mv);
wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume *volume) {
return std::find(volumes.begin(), volumes.end(), volume) != volumes.end();
});
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object((size_t) obj_idx);
if (items.size() > 1) {
m_selection_mode = smVolume;
m_last_selected_item = wxDataViewItem(nullptr);
if (items.size() > 1) {
m_selection_mode = smVolume;
m_last_selected_item = wxDataViewItem(nullptr);
}
select_items(items);
selection_changed();
}
select_items(items);
selection_changed();
//BBS: notify partplate the modify
notify_instance_updated(obj_idx);
return mo->volumes.size() - 1;
}
//BBS
@ -4563,7 +4582,7 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set
}
// update printable state for new volumes on canvas3D
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object(new_obj_indx);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object(new_obj_indx);
update_info_items(new_obj_indx);
}
@ -4596,7 +4615,7 @@ void ObjectList::instances_to_separated_objects(const int obj_idx)
}
// update printable state for new volumes on canvas3D
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(object_idxs);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(object_idxs);
for (size_t object : object_idxs)
update_info_items(object);
}
@ -4707,10 +4726,13 @@ void ObjectList::fix_through_netfabb()
std::string res;
if (!fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res))
return false;
wxGetApp().plater()->changed_mesh(obj_idx);
//wxGetApp().plater()->changed_mesh(obj_idx);
object(obj_idx)->ensure_on_bed();
plater->changed_mesh(obj_idx);
plater->get_partplate_list().notify_instance_update(obj_idx, 0);
plater->sidebar().obj_list()->update_plate_values_for_items();
if (res.empty())
succes_models.push_back(model_name);
else
@ -4719,8 +4741,6 @@ void ObjectList::fix_through_netfabb()
update_item_error_icon(obj_idx, vol_idx);
update_info_items(obj_idx);
object(obj_idx)->ensure_on_bed();
return true;
};
@ -5037,7 +5057,7 @@ void ObjectList::reload_all_plates(bool notify_partplate)
m_prevent_canvas_selection_update = false;
// update printable states on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
// update scene
wxGetApp().plater()->update();
}
@ -5171,7 +5191,7 @@ void ObjectList::toggle_printable_state()
obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
// update printable state on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
// update scene
wxGetApp().plater()->update();
@ -5190,17 +5210,20 @@ bool ObjectList::has_paint_on_segmentation()
return m_objects_model->HasInfoItem(InfoItemType::MmuSegmentation);
}
void ObjectList::apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object) {
void ObjectList::apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object, bool need_update_assemble_matrix)
{
const Geometry::Transformation &instance_transformation = model_object->instances[0]->get_transformation();
Vec3d original_instance_center = instance_transformation.get_offset();
// apply the instance_transform(except offset) to assemble_transform
Geometry::Transformation instance_transformation_copy = instance_transformation;
instance_transformation_copy.set_offset(Vec3d(0, 0, 0)); // remove the effect of offset
const Transform3d & instance_inverse_matrix = instance_transformation_copy.get_matrix().inverse();
const Transform3d & assemble_matrix = model_object->instances[0]->get_assemble_transformation().get_matrix();
Transform3d new_assemble_transform = assemble_matrix * instance_inverse_matrix;
model_object->instances[0]->set_assemble_from_transform(new_assemble_transform);
if (need_update_assemble_matrix) {
// apply the instance_transform(except offset) to assemble_transform
Geometry::Transformation instance_transformation_copy = instance_transformation;
instance_transformation_copy.set_offset(Vec3d(0, 0, 0)); // remove the effect of offset
const Transform3d &instance_inverse_matrix = instance_transformation_copy.get_matrix().inverse();
const Transform3d &assemble_matrix = model_object->instances[0]->get_assemble_transformation().get_matrix();
Transform3d new_assemble_transform = assemble_matrix * instance_inverse_matrix;
model_object->instances[0]->set_assemble_from_transform(new_assemble_transform);
}
// apply the instance_transform to volumn
const Transform3d &transformation_matrix = instance_transformation.get_matrix();

View file

@ -27,6 +27,7 @@ class ModelConfig;
class ModelObject;
class ModelVolume;
class TriangleMesh;
struct TextInfo;
enum class ModelVolumeType : int;
// FIXME: broken build on mac os because of this is missing:
@ -283,7 +284,7 @@ public:
void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true);
// BBS
void switch_to_object_process();
void load_mesh_part(const TriangleMesh& mesh, const wxString& name, bool center = true);
int load_mesh_part(const TriangleMesh &mesh, const wxString &name, const TextInfo &text_info, bool is_temp);
void del_object(const int obj_idx, bool refresh_immediately = true);
void del_subobject_item(wxDataViewItem& item);
void del_settings_from_config(const wxDataViewItem& parent_item);
@ -454,7 +455,7 @@ private:
void OnEditingDone(wxDataViewEvent &event);
// apply the instance transform to all volumes and reset instance transform except the offset
void apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object);
void apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object, bool need_update_assemble_matrix = true);
std::vector<int> m_columns_width;
};

View file

@ -344,7 +344,10 @@ void GridCellFilamentsRenderer::Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &d
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(attr.GetBackgroundColour()));
dc.DrawRectangle(rect);
dc.DrawBitmap(*bitmap, wxPoint(rect.x + offset_x, rect.y + offset_y));
if ( grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) {
dc.DrawBitmap(*bitmap, wxPoint(rect.x + offset_x, rect.y + offset_y));
}
text_rect.x += bitmap_width + grid_cell_border_width * 2;
text_rect.width -= (bitmap_width + grid_cell_border_width * 2);
}
@ -1968,6 +1971,7 @@ void ObjectGridTable::construct_object_configs(ObjectGrid *object_grid)
{
ModelVolume* volume = object->volumes[j];
ObjectGridRow* volume_grid = new ObjectGridRow(i, j, row_volume);
volume_grid->model_volume_type = volume->type();
volume_grid->config = &(volume->config);
volume_grid->name.value = volume->name;
size_t pos = volume_grid->name.value.find_first_not_of(' ');
@ -2952,11 +2956,21 @@ void ObjectTablePanel::load_data()
break;
case coEnum:
if (col == ObjectGridTable::col_filaments) {
GridCellFilamentsEditor *filament_editor = new GridCellFilamentsEditor(grid_col->choice_count, grid_col->choices, false, &m_color_bitmaps);
m_object_grid->SetCellEditor(row, col, filament_editor);
m_object_grid->SetCellRenderer(row, col, new GridCellFilamentsRenderer());
} else {
GridCellChoiceEditor *combo_editor = new GridCellChoiceEditor(grid_col->choice_count, grid_col->choices);
if (grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) {
GridCellFilamentsEditor* filament_editor = new GridCellFilamentsEditor(grid_col->choice_count, grid_col->choices, false, &m_color_bitmaps);
m_object_grid->SetCellEditor(row, col, filament_editor);
m_object_grid->SetCellRenderer(row, col, new GridCellFilamentsRenderer());
}
else {
m_object_grid->SetCellEditor(row, col, new GridCellTextEditor());
auto gcfil = new GridCellFilamentsRenderer();
m_object_grid->SetCellRenderer(row, col, gcfil);
m_object_grid->SetReadOnly(row, col);
//m_object_grid->SetCellFitMode(row, col, wxGridFitMode::Ellipsize());
}
}
else {
GridCellChoiceEditor* combo_editor = new GridCellChoiceEditor(grid_col->choice_count, grid_col->choices);
m_object_grid->SetCellEditor(row, col, combo_editor);
m_object_grid->SetCellRenderer(row, col, new wxGridCellChoiceRenderer());
}

View file

@ -348,6 +348,7 @@ public:
ConfigOptionFloat ori_speed_perimeter;
ModelConfig* config;
ModelVolumeType model_volume_type;
ObjectGridRow(int obj_id, int vol_id, GridRowType type)
: object_id(obj_id), volume_id(vol_id), row_type(type)

View file

@ -385,9 +385,9 @@ void Preview::sys_color_changed()
void Preview::on_tick_changed(Type type)
{
if (type == Type::PausePrint) {
m_schedule_background_process();
}
//if (type == Type::PausePrint) {
// m_schedule_background_process();
//}
m_keep_current_preview_type = false;
reload_print(false);
}
@ -485,8 +485,7 @@ void Preview::update_layers_slider_mode()
// check if whole model uses just only one extruder
if (!plate_extruders.empty()) {
//const int extruder = objects[0]->config.has("extruder") ? objects[0]->config.option("extruder")->getInt() : 0;
const int extruder = plate_extruders[0];
only_extruder = extruder;
only_extruder = plate_extruders[0];
// auto is_one_extruder_printed_model = [objects, extruder]() {
// for (ModelObject *object : objects) {
// if (object->config.has("extruder") && object->config.option("extruder")->getInt() != extruder) /*return false*/;
@ -552,15 +551,16 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
// Detect and set manipulation mode for double slider
update_layers_slider_mode();
Plater * plater = wxGetApp().plater();
CustomGCode::Info ticks_info_from_model;
Plater* plater = wxGetApp().plater();
//BBS: replace model custom gcode with current plate custom gcode
CustomGCode::Info ticks_info_from_curr_plate;
if (wxGetApp().is_editor())
ticks_info_from_model = plater->model().custom_gcode_per_print_z;
ticks_info_from_curr_plate = plater->model().get_curr_plate_custom_gcodes();
else {
ticks_info_from_model.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_model.gcodes = m_canvas->get_custom_gcode_per_print_z();
ticks_info_from_curr_plate.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_curr_plate.gcodes = m_canvas->get_custom_gcode_per_print_z();
}
check_layers_slider_values(ticks_info_from_model.gcodes, layers_z);
check_layers_slider_values(ticks_info_from_curr_plate.gcodes, layers_z);
// first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM
m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
@ -581,9 +581,11 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
}
}
m_layers_slider->SetSelectionSpan(idx_low, idx_high);
m_layers_slider->SetTicksValues(ticks_info_from_model);
m_layers_slider->SetTicksValues(ticks_info_from_curr_plate);
bool sequential_print = (wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
auto curr_print_seq = curr_plate->get_real_print_seq();
bool sequential_print = (curr_print_seq == PrintSequence::ByObject);
m_layers_slider->SetDrawMode(sequential_print);
auto print_mode_stat = m_gcode_result->print_statistics.modes.front();
@ -688,7 +690,8 @@ void Preview::load_print_as_fff(bool keep_z_range, bool only_gcode)
if (!gcode_preview_data_valid) {
if (wxGetApp().is_editor())
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
//BBS
color_print_values = wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes;
else
color_print_values = m_canvas->get_custom_gcode_per_print_z();
colors.push_back("#808080"); // gray color for pause print or custom G-code
@ -703,7 +706,8 @@ void Preview::load_print_as_fff(bool keep_z_range, bool only_gcode)
if (IsShown()) {
m_canvas->set_selected_extruder(0);
if (gcode_preview_data_valid) {
bool is_slice_result_valid = wxGetApp().plater()->get_partplate_list().get_curr_plate()->is_slice_result_valid();
if (gcode_preview_data_valid && (is_slice_result_valid || m_only_gcode)) {
// Load the real G-code preview.
//BBS: add more log
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": will load gcode_preview from result, moves count %1%") % m_gcode_result->moves.size();
@ -734,7 +738,8 @@ void Preview::load_print_as_fff(bool keep_z_range, bool only_gcode)
(unsigned int)print->extruders().size() :
m_canvas->get_gcode_extruders_count();
std::vector<Item> gcodes = wxGetApp().is_editor() ?
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes :
//BBS
wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes :
m_canvas->get_custom_gcode_per_print_z();
const wxString choice = !gcodes.empty() ?
_L("Multicolor Print") :

View file

@ -430,7 +430,10 @@ bool load_image(const std::string &filename, wxImage &image)
result = image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_BMP);
} else if (boost::algorithm::iends_with(filename, ".jpg")) {
result = image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_JPEG);
} else {
} else if (boost::algorithm::iends_with(filename, ".jpeg")) {
result = image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_JPEG);
}
else {
return false;
}
return result;

View file

@ -128,6 +128,29 @@ void GLGizmoFdmSupports::render_painter_gizmo() const
glsafe(::glDisable(GL_BLEND));
}
// BBS
bool GLGizmoFdmSupports::on_key_down_select_tool_type(int keyCode) {
switch (keyCode)
{
case 'F':
m_current_tool = ImGui::FillButtonIcon;
break;
case 'S':
m_current_tool = ImGui::SphereButtonIcon;
break;
case 'C':
m_current_tool = ImGui::CircleButtonIcon;
break;
case 'G':
m_current_tool = ImGui::GapFillIcon;
break;
default:
return false;
break;
}
return true;
}
// BBS
void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
{
@ -865,42 +888,22 @@ void GLGizmoFdmSupports::run_thread()
goto _finished;
}
if (m_is_tree_support)
if (!m_print_instance.print_object->support_layers().size())
{
if (!m_print_instance.print_object->tree_support_layers().size())
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",no tree support layer found, update status to 100%\n";
print->set_status(100, L("Support Generated"));
goto _finished;
}
for (const TreeSupportLayer *support_layer : m_print_instance.print_object->tree_support_layers())
{
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
{
_3DScene::extrusionentity_to_verts(extrusion_entity, float(support_layer->print_z), m_print_instance.shift, *m_support_volume);
}
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished extrusionentity_to_verts, update status to 100%";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",no support layer found, update status to 100%\n";
print->set_status(100, L("Support Generated"));
goto _finished;
}
else
for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers())
{
if (!m_print_instance.print_object->support_layers().size())
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",no support layer found, update status to 100%\n";
print->set_status(100, L("Support Generated"));
goto _finished;
_3DScene::extrusionentity_to_verts(extrusion_entity, float(support_layer->print_z), m_print_instance.shift, *m_support_volume);
}
for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers())
{
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
{
_3DScene::extrusionentity_to_verts(extrusion_entity, float(support_layer->print_z), m_print_instance.shift, *m_support_volume);
}
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished extrusionentity_to_verts, update status to 100%";
print->set_status(100, L("Support Generated"));
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished extrusionentity_to_verts, update status to 100%";
print->set_status(100, L("Support Generated"));
record_timestamp();
}
catch (...) {

View file

@ -24,6 +24,9 @@ public:
state_ready
};
//BBS
bool on_key_down_select_tool_type(int keyCode);
protected:
void on_render_input_window(float x, float y, float bottom_limit) override;
std::string on_get_name() const override;

View file

@ -241,6 +241,34 @@ bool GLGizmoMmuSegmentation::on_number_key_down(int number)
return true;
}
bool GLGizmoMmuSegmentation::on_key_down_select_tool_type(int keyCode) {
switch (keyCode)
{
case 'F':
m_current_tool = ImGui::FillButtonIcon;
break;
case 'T':
m_current_tool = ImGui::TriangleButtonIcon;
break;
case 'S':
m_current_tool = ImGui::SphereButtonIcon;
break;
case 'C':
m_current_tool = ImGui::CircleButtonIcon;
break;
case 'H':
m_current_tool = ImGui::HeightRangeIcon;
break;
case 'G':
m_current_tool = ImGui::GapFillIcon;
break;
default:
return false;
break;
}
return true;
}
static void render_extruders_combo(const std::string &label,
const std::vector<std::string> &extruders,
const std::vector<std::array<float, 4>> &extruders_colors,

View file

@ -83,6 +83,7 @@ public:
// BBS
bool on_number_key_down(int number);
bool on_key_down_select_tool_type(int keyCode);
protected:
// BBS

View file

@ -261,7 +261,7 @@ protected:
static constexpr float CursorRadiusMin = 0.4f; // cannot be zero
static constexpr float CursorRadiusMax = 8.f;
static constexpr float CursorRadiusStep = 0.2f;
static constexpr float CursorHeightMin = 0.2f; // cannot be zero
static constexpr float CursorHeightMin = 0.1f; // cannot be zero
static constexpr float CursorHeightMax = 8.f;
static constexpr float CursorHeightStep = 0.2f;

View file

@ -226,10 +226,11 @@ void GLGizmoScale3D::on_render()
//draw connections
if (single_instance || single_volume) {
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
//if (single_instance || single_volume) {
glsafe(::glColor4fv(m_grabbers[4].color.data()));
render_grabbers_connection(4, 5);
}
//}
glsafe(::glColor4fv(m_grabbers[2].color.data()));
render_grabbers_connection(6, 7);

View file

@ -78,6 +78,23 @@ void GLGizmoSeam::render_painter_gizmo() const
glsafe(::glDisable(GL_BLEND));
}
// BBS
bool GLGizmoSeam::on_key_down_select_tool_type(int keyCode) {
switch (keyCode)
{
case 'S':
m_current_tool = ImGui::SphereButtonIcon;
break;
case 'C':
m_current_tool = ImGui::CircleButtonIcon;
break;
default:
return false;
break;
}
return true;
}
void GLGizmoSeam::render_triangles(const Selection& selection) const
{
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();

View file

@ -12,6 +12,9 @@ public:
void render_painter_gizmo() const override;
//BBS
bool on_key_down_select_tool_type(int keyCode);
protected:
// BBS
void on_set_state() override;

View file

@ -70,7 +70,7 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
{}
GLGizmoSimplify::~GLGizmoSimplify()
{
{
stop_worker_thread_request();
if (m_worker.joinable())
m_worker.join();
@ -173,10 +173,10 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
// Whether to trigger calculation after rendering is done.
bool start_process = false;
// Check selection of new volume
// Do not reselect object when processing
// Do not reselect object when processing
if (act_volume != m_volume) {
bool change_window_position = (m_volume == nullptr);
// select different model
@ -193,13 +193,13 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
// Start processing. If we switched from another object, process will
// stop the background thread and it will restart itself later.
start_process = true;
// set window position
if (m_move_to_center && change_window_position) {
m_move_to_center = false;
auto parent_size = m_parent.get_canvas_size();
auto parent_size = m_parent.get_canvas_size();
ImVec2 pos(parent_size.get_width() / 2 - m_gui_cfg->window_offset_x,
parent_size.get_height() / 2 - m_gui_cfg->window_offset_y);
parent_size.get_height() / 2 - m_gui_cfg->window_offset_y);
ImGui::SetNextWindowPos(pos, ImGuiCond_Always);
}else if (change_window_position) {
ImVec2 pos = ImGui::GetMousePos();
@ -212,7 +212,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
// maximal bottom right value
auto parent_size = m_parent.get_canvas_size();
ImVec2 br(
parent_size.get_width() - (2 * m_gui_cfg->window_offset_x + m_gui_cfg->window_padding),
parent_size.get_width() - (2 * m_gui_cfg->window_offset_x + m_gui_cfg->window_padding),
parent_size.get_height() - (2 * m_gui_cfg->window_offset_y + m_gui_cfg->window_padding));
if (pos.x > br.x) pos.x = br.x;
if (pos.y > br.y) pos.y = br.y;
@ -466,7 +466,7 @@ void GLGizmoSimplify::process()
m_worker.join();
}
// Copy configuration that will be used.
// Copy configuration that will be used.
m_state.config = m_configuration;
m_state.mv = m_volume;
m_state.status = State::running;
@ -542,11 +542,12 @@ void GLGizmoSimplify::apply_simplify() {
mv->set_mesh(std::move(*m_state.result));
m_state.result.reset();
mv->calculate_convex_hull();
mv->invalidate_convex_hull_2d();
mv->set_new_unique_id();
mv->get_object()->invalidate_bounding_box();
mv->get_object()->ensure_on_bed();
// fix hollowing, sla support points, modifiers, ...
// fix hollowing, sla support points, modifiers, ...
plater->changed_mesh(object_idx);
// Fix warning icon in object list
wxGetApp().obj_list()->update_item_error_icon(object_idx, -1);
@ -559,7 +560,7 @@ bool GLGizmoSimplify::on_is_activable() const
m_parent.get_selection().is_single_volume();
}
void GLGizmoSimplify::on_set_state()
void GLGizmoSimplify::on_set_state()
{
// Closing gizmo. e.g. selecting another one
if (GLGizmoBase::m_state == GLGizmoBase::Off) {
@ -574,12 +575,12 @@ void GLGizmoSimplify::on_set_state()
}
}
void GLGizmoSimplify::create_gui_cfg() {
void GLGizmoSimplify::create_gui_cfg() {
if (m_gui_cfg.has_value()) return;
int space_size = m_imgui->calc_text_size(":MM").x;
GuiCfg cfg;
cfg.top_left_width = std::max(m_imgui->calc_text_size(tr_mesh_name).x,
m_imgui->calc_text_size(tr_triangles).x)
m_imgui->calc_text_size(tr_triangles).x)
+ space_size;
const float radio_size = ImGui::GetFrameHeight();
@ -591,7 +592,7 @@ void GLGizmoSimplify::create_gui_cfg() {
cfg.input_width = cfg.bottom_left_width * 1.5;
cfg.window_offset_x = (cfg.bottom_left_width + cfg.input_width)/2;
cfg.window_offset_y = ImGui::GetTextLineHeightWithSpacing() * 5;
m_gui_cfg = cfg;
}
@ -605,7 +606,7 @@ void GLGizmoSimplify::request_rerender(bool force) {
}
void GLGizmoSimplify::set_center_position() {
m_move_to_center = true;
m_move_to_center = true;
}
@ -619,7 +620,7 @@ void GLGizmoSimplify::init_model(const indexed_triangle_set& its)
m_parent.toggle_model_objects_visibility(true); // selected volume may have changed
m_parent.toggle_model_objects_visibility(false, m_c->selection_info()->model_object(),
m_c->selection_info()->get_active_instance(), m_volume);
if (const Selection&sel = m_parent.get_selection(); sel.get_volume_idxs().size() == 1)
m_glmodel.set_color(-1, sel.get_volume(*sel.get_volume_idxs().begin())->color);
m_triangle_count = its.indices.size();

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,17 @@
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include "../GLTexture.hpp"
#include "../Camera.hpp"
#include "libslic3r/Model.hpp"
namespace Slic3r {
enum class ModelVolumeType : int;
class ModelVolume;
namespace GUI {
enum class SLAGizmoEventType : unsigned char;
class GLGizmoText : public GLGizmoBase
{
private:
@ -22,10 +26,21 @@ private:
bool m_bold = true;
bool m_italic = false;
float m_thickness = 2.f;
float m_embeded_depth = 0.f;
float m_rotate_angle = 0;
float m_text_gap = 0.f;
bool m_is_surface_text = false;
bool m_keep_horizontal = false;
mutable RaycastResult m_rr;
float m_combo_height = 0.0f;
float m_combo_width = 0.0f;
float m_scale;
Vec2d m_mouse_position = Vec2d::Zero();
Vec2d m_origin_mouse_position = Vec2d::Zero();
bool m_shift_down = false;
class TextureInfo {
public:
GLTexture* texture { nullptr };
@ -38,18 +53,46 @@ private:
std::vector<TextureInfo> m_textures;
std::vector<std::string> m_font_names;
bool m_is_modify = false;
bool m_need_update_text = false;
int m_object_idx = -1;
int m_volume_idx = -1;
int m_preview_text_volume_id = -1;
Vec3d m_mouse_position_world = Vec3d::Zero();
Vec3d m_mouse_normal_world = Vec3d::Zero();
Vec3d m_cut_plane_dir = Vec3d::UnitZ();
std::vector<Vec3d> m_position_points;
std::vector<Vec3d> m_normal_points;
// This map holds all translated description texts, so they can be easily referenced during layout calculations
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
std::map<std::string, wxString> m_desc;
public:
GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
~GLGizmoText();
void update_font_texture();
bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down);
bool is_mesh_point_clipped(const Vec3d &point, const Transform3d &trafo) const;
BoundingBoxf3 bounding_box() const;
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
virtual void on_update(const UpdateData &data) override;
void push_combo_style(const float scale);
void pop_combo_style();
void push_button_style(bool pressed);
@ -57,6 +100,21 @@ protected:
virtual void on_set_state() override;
virtual CommonGizmosDataID on_get_requirements() const override;
virtual void on_render_input_window(float x, float y, float bottom_limit);
void show_tooltip_information(float x, float y);
private:
ModelVolume *get_selected_single_volume(int& out_object_idx, int& out_volume_idx) const;
void reset_text_info();
bool update_text_positions(const std::vector<std::string>& texts);
TriangleMesh get_text_mesh(const char* text_str, const Vec3d &position, const Vec3d &normal, const Vec3d &text_up_dir);
bool update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector<Transform3d> &trafo_matrices);
void generate_text_volume(bool is_temp = true);
void delete_temp_preview_text_volume();
TextInfo get_text_info();
void load_from_text_info(const TextInfo &text_info);
};
} // namespace GUI

View file

@ -405,11 +405,12 @@ void GLGizmosManager::update_data()
enable_grabber(Rotate, 0, !is_wipe_tower);
enable_grabber(Rotate, 1, !is_wipe_tower);
bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
for (unsigned int i = 0; i < 6; ++i)
{
enable_grabber(Scale, i, enable_scale_xyz);
}
// BBS: when select multiple objects, uniform scale can be deselected, display the 0-5 grabbers
//bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
//for (unsigned int i = 0; i < 6; ++i)
//{
// enable_grabber(Scale, i, enable_scale_xyz);
//}
if (m_common_gizmos_data) {
m_common_gizmos_data->update(get_current()
@ -624,6 +625,8 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
return dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == MmuSegmentation)
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Text)
return dynamic_cast<GLGizmoText*>(m_gizmos[Text].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else
return false;
}
@ -756,7 +759,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
// mouse anywhere
if (evt.Moving()) {
m_tooltip = update_hover_state(mouse_pos);
if (m_current == MmuSegmentation || m_current == FdmSupports)
if (m_current == MmuSegmentation || m_current == FdmSupports || m_current == Text)
// BBS
gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
} else if (evt.LeftUp()) {
@ -839,8 +842,8 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
//if (evt.AltDown())
// transformation_type.set_independent();
selection.scale(get_scale(), transformation_type);
//if (control_down)
// selection.translate(get_scale_offset(), true);
if (control_down && m_gizmos[m_current].get()->get_hover_id() < 6)
selection.translate(get_scale_offset(), true);
// BBS
//wxGetApp().obj_manipul()->set_dirty();
break;
@ -869,7 +872,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
m_tooltip.clear();
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Text)
&& gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown()))
// the gizmo got the event and took some action, there is no need to do anything more
processed = true;
@ -1181,10 +1184,40 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
processed = simplify->on_esc_key_down();
}
// BBS
else if (m_current == MmuSegmentation && keyCode > '0' && keyCode <= '9') {
else if (m_current == MmuSegmentation) {
GLGizmoMmuSegmentation* mmu_seg = dynamic_cast<GLGizmoMmuSegmentation*>(get_current());
if (mmu_seg != nullptr)
processed = mmu_seg->on_number_key_down(keyCode - '0');
if (mmu_seg != nullptr) {
if (keyCode > '0' && keyCode <= '9') {
processed = mmu_seg->on_number_key_down(keyCode - '0');
}
else if (keyCode == 'F' || keyCode == 'T' || keyCode == 'S' || keyCode == 'C' || keyCode == 'H' || keyCode == 'G') {
processed = mmu_seg->on_key_down_select_tool_type(keyCode);
if (processed) {
// force extra frame to automatically update window size
wxGetApp().imgui()->set_requires_extra_frame();
}
}
}
}
else if (m_current == FdmSupports) {
GLGizmoFdmSupports* fdm_support = dynamic_cast<GLGizmoFdmSupports*>(get_current());
if (fdm_support != nullptr && keyCode == 'F' || keyCode == 'S' || keyCode == 'C' || keyCode == 'G') {
processed = fdm_support->on_key_down_select_tool_type(keyCode);
}
if (processed) {
// force extra frame to automatically update window size
wxGetApp().imgui()->set_requires_extra_frame();
}
}
else if (m_current == Seam) {
GLGizmoSeam* seam = dynamic_cast<GLGizmoSeam*>(get_current());
if (seam != nullptr && keyCode == 'S' || keyCode == 'C') {
processed = seam->on_key_down_select_tool_type(keyCode);
}
if (processed) {
// force extra frame to automatically update window size
wxGetApp().imgui()->set_requires_extra_frame();
}
}
}
@ -1504,7 +1537,7 @@ void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx) {
activate_gizmo(m_current == idx ? Undefined : (EType)idx);
// BBS
wxGetApp().obj_list()->select_object_item((EType)idx <= Scale);
wxGetApp().obj_list()->select_object_item((EType) idx <= Scale || (EType) idx == Text);
}
}

View file

@ -304,7 +304,12 @@ void GizmoObjectManipulation::change_scale_value(int axis, double value)
return;
Vec3d scale = m_cache.scale;
scale(axis) = value;
if (scale[axis] != 0 && std::abs(m_cache.size[axis] * value / scale[axis]) > MAX_NUM) {
scale[axis] *= MAX_NUM / m_cache.size[axis];
}
else {
scale(axis) = value;
}
this->do_scale(axis, scale);
@ -351,7 +356,8 @@ void GizmoObjectManipulation::do_scale(int axis, const Vec3d &scale) const
transformation_type.set_local();
}
if (m_uniform_scale || selection.requires_uniform_scale())
// BBS: when select multiple objects, uniform scale can be deselected
if (m_uniform_scale/* || selection.requires_uniform_scale()*/)
scaling_factor = scale(axis) * Vec3d::Ones();
selection.start_dragging();
@ -505,18 +511,6 @@ bool GizmoObjectManipulation::reset_button(ImGuiWrapper *imgui_wrapper, float ca
unit_size = std::max(nuit_max[i], unit_size);
}
for (int i = 0; i < 3; i++)
{
if (str == "scale") {
if (vec1[i] > 39062.46)vec1[i] = 39062.46;
if (vec2[i] > 9999.99)vec2[i] = 9999.99;
}
if (str == "move") {
if (vec1[i] > 9999.99)vec1[i] = 9999.99;
if (vec2[i] > 9999.99)vec2[i] = 9999.99;
}
}
return unit_size + 8.0;
}
@ -609,6 +603,7 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
for (int i = 0;i<display_position.size();i++)
{
if (display_position[i] > MAX_NUM)display_position[i] = MAX_NUM;
if (display_position[i] < -MAX_NUM)display_position[i] = -MAX_NUM;
}
m_buffered_position = display_position;
@ -842,6 +837,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
ImGui::BBLInputDouble(label_scale_values[0][2], &scale[2], 0.0f, 0.0f, "%.2f");
ImGui::SameLine(caption_max + (++index_unit) *unit_size + (++index) * space_size);
imgui_wrapper->text(_L("%"));
m_buffered_scale = scale;
if (m_show_clear_scale) {
ImGui::SameLine(caption_max + 3 * unit_size + 4 * space_size + end_text_size);
@ -878,9 +874,8 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
for (int i = 0;i<display_size.size();i++)
{
if (display_size[i] > MAX_NUM || scale[i]> MAX_NUM)display_size[i] = MAX_NUM;
if (std::abs(display_size[i]) > MAX_NUM) display_size[i] = MAX_NUM;
}
m_buffered_scale = scale;
m_buffered_size = display_size;
int size_sel = update(current_active_id, "size", original_size, m_buffered_size);
ImGui::PopStyleVar(1);
@ -889,16 +884,18 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
bool uniform_scale = this->m_uniform_scale;
const Selection &selection = m_glcanvas.get_selection();
bool uniform_scale_only = selection.is_multiple_full_object() || selection.is_multiple_full_instance() || selection.is_mixed() || selection.is_multiple_volume() || selection.is_multiple_modifier();
// BBS: when select multiple objects, uniform scale can be deselected
//const Selection &selection = m_glcanvas.get_selection();
//bool uniform_scale_only = selection.is_multiple_full_object() || selection.is_multiple_full_instance() || selection.is_mixed() || selection.is_multiple_volume() ||
// selection.is_multiple_modifier();
if (uniform_scale_only) {
imgui_wrapper->disabled_begin(true);
imgui_wrapper->bbl_checkbox(_L("uniform scale"), uniform_scale_only);
imgui_wrapper->disabled_end();
} else {
//if (uniform_scale_only) {
// imgui_wrapper->disabled_begin(true);
// imgui_wrapper->bbl_checkbox(_L("uniform scale"), uniform_scale_only);
// imgui_wrapper->disabled_end();
//} else {
imgui_wrapper->bbl_checkbox(_L("uniform scale"), uniform_scale);
}
//}
if (uniform_scale != this->m_uniform_scale) { this->set_uniform_scaling(uniform_scale); }
// for (int index = 0; index < 3; index++)

View file

@ -248,26 +248,27 @@ wxString HMSQuery::query_print_error_msg(int print_error)
int HMSQuery::check_hms_info()
{
int result = 0;
bool download_new_hms_info = true;
// load local hms json file
std::string version = "";
if (load_from_local(version) == 0) {
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info current version = " << version;
std::string new_version;
get_hms_info_version(new_version);
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info latest version = " << new_version;
if (!version.empty() && version == new_version) {
download_new_hms_info = false;
boost::thread check_thread = boost::thread([this] {
bool download_new_hms_info = true;
// load local hms json file
std::string version = "";
if (load_from_local(version) == 0) {
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info current version = " << version;
std::string new_version;
get_hms_info_version(new_version);
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info latest version = " << new_version;
if (!version.empty() && version == new_version) {
download_new_hms_info = false;
}
}
}
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info need download new hms info = " << download_new_hms_info;
// download if version is update
if (download_new_hms_info) {
result = download_hms_info();
}
return result;
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info need download new hms info = " << download_new_hms_info;
// download if version is update
if (download_new_hms_info) {
download_hms_info();
}
return;
});
return 0;
}
std::string get_hms_wiki_url(std::string error_code)

View file

@ -67,7 +67,7 @@ namespace {
void write_used_binary(const std::vector<std::string>& ids)
{
boost::nowide::ofstream file((boost::filesystem::path(data_dir()) / "cache" / "hints.cereal").string(), std::ios::binary);
boost::nowide::ofstream file((boost::filesystem::path(data_dir()) / "user" / "hints.cereal").string(), std::ios::binary);
cereal::BinaryOutputArchive archive(file);
HintsCerealData cd{ ids };
try
@ -81,7 +81,7 @@ namespace {
}
void read_used_binary(std::vector<std::string>& ids)
{
boost::filesystem::path path(boost::filesystem::path(data_dir()) / "cache" / "hints.cereal");
boost::filesystem::path path(boost::filesystem::path(data_dir()) / "user" / "hints.cereal");
if (!boost::filesystem::exists(path)) {
BOOST_LOG_TRIVIAL(warning) << "Failed to load to hints.cereal. File does not exists. " << path.string();
return;

View file

@ -0,0 +1,151 @@
#include "HttpServer.hpp"
#include <boost/log/trivial.hpp>
#include "GUI_App.hpp"
#include "slic3r/Utils/Http.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
namespace Slic3r {
namespace GUI {
static std::string parse_params(std::string url, std::string key)
{
size_t start = url.find(key);
if (start < 0) return "";
size_t eq = url.find('=', start);
if (eq < 0) return "";
std::string key_str = url.substr(start, eq - start);
if (key_str != key)
return "";
start += key.size() + 1;
size_t end = url.find('&', start);
if (end < 0)
return "";
std::string result = url.substr(start, end - start);
return result;
}
std::string http_headers::get_response()
{
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: get_response";
std::stringstream ssOut;
std::string url_str = Http::url_decode(url);
if (boost::contains(url_str, "access_token")) {
std::string sHTML = "<html><body><p>redirect to url </p></body></html>";
std::string redirect_url = parse_params(url_str, "redirect_url");
std::string access_token = parse_params(url_str, "access_token");
std::string refresh_token = parse_params(url_str, "refresh_token");
std::string expires_in_str = parse_params(url_str, "expires_in");
std::string refresh_expires_in_str = parse_params(url_str, "refresh_expires_in");
NetworkAgent* agent = wxGetApp().getAgent();
unsigned int http_code;
std::string http_body;
int result = agent->get_my_profile(access_token, &http_code, &http_body);
if (result == 0) {
std::string user_id;
std::string user_name;
std::string user_account;
std::string user_avatar;
try {
json user_j = json::parse(http_body);
if (user_j.contains("uid"))
user_id = std::to_string(user_j["uid"].get<int>());
if (user_j.contains("name"))
user_name = user_j["name"].get<std::string>();
if (user_j.contains("avatar"))
user_avatar = user_j["avatar"].get<std::string>();
if (user_j.contains("account"))
user_account = user_j["account"].get<std::string>();
} catch (...) {
;
}
json j;
j["data"]["refresh_token"] = refresh_token;
j["data"]["token"] = access_token;
j["data"]["expires_in"] = expires_in_str;
j["data"]["refresh_expires_in"] = refresh_expires_in_str;
j["data"]["user"]["uid"] = user_id;
j["data"]["user"]["name"] = user_name;
j["data"]["user"]["account"] = user_account;
j["data"]["user"]["avatar"] = user_avatar;
agent->change_user(j.dump());
if (agent->is_user_login()) {
wxGetApp().request_user_login(1);
}
GUI::wxGetApp().CallAfter([this] {
wxGetApp().ShowUserLogin(false);
});
std::string location_str = (boost::format("Location: %1%?result=success") % redirect_url).str();
ssOut << "HTTP/1.1 302 Found" << std::endl;
ssOut << location_str << std::endl;
ssOut << "content-type: text/html" << std::endl;
ssOut << "content-length: " << sHTML.length() << std::endl;
ssOut << std::endl;
ssOut << sHTML;
} else {
std::string error_str = "get_user_profile_error_" + std::to_string(result);
std::string location_str = (boost::format("Location: %1%?result=fail&error=%2%") % redirect_url % error_str).str();
ssOut << "HTTP/1.1 302 Found" << std::endl;
ssOut << location_str << std::endl;
ssOut << "content-type: text/html" << std::endl;
ssOut << "content-length: " << sHTML.length() << std::endl;
ssOut << std::endl;
ssOut << sHTML;
}
} else {
std::string sHTML = "<html><body><h1>404 Not Found</h1><p>There's nothing here.</p></body></html>";
ssOut << "HTTP/1.1 404 Not Found" << std::endl;
ssOut << "content-type: text/html" << std::endl;
ssOut << "content-length: " << sHTML.length() << std::endl;
ssOut << std::endl;
ssOut << sHTML;
}
return ssOut.str();
}
void accept_and_run(boost::asio::ip::tcp::acceptor& acceptor, boost::asio::io_service& io_service)
{
std::shared_ptr<session> sesh = std::make_shared<session>(io_service);
acceptor.async_accept(sesh->socket,
[sesh, &acceptor, &io_service](const boost::beast::error_code& accept_error)
{
accept_and_run(acceptor, io_service);
if (!accept_error)
{
session::interact(sesh);
}
});
}
HttpServer::HttpServer()
{
;
}
void HttpServer::start()
{
BOOST_LOG_TRIVIAL(info) << "start_http_service...";
start_http_server = true;
m_http_server_thread = Slic3r::create_thread(
[this] {
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint endpoint{ boost::asio::ip::tcp::v4(), LOCALHOST_PORT};
boost::asio::ip::tcp::acceptor acceptor { io_service, endpoint};
acceptor.listen();
accept_and_run(acceptor, io_service);
while (start_http_server) {
io_service.run();
}
});
}
void HttpServer::stop()
{
start_http_server = false;
if (m_http_server_thread.joinable())
m_http_server_thread.join();
}
} // GUI
} //Slic3r

View file

@ -0,0 +1,162 @@
#ifndef slic3r_Http_App_hpp_
#define slic3r_Http_App_hpp_
#include <mutex>
#include <stack>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <string>
#include <memory>
using namespace boost;
using namespace boost::system;
using namespace boost::asio;
#define LOCALHOST_PORT 13618
#define LOCALHOST_URL "http://localhost:"
namespace Slic3r {
namespace GUI {
class http_headers
{
std::string method;
std::string url;
std::string version;
std::map<std::string, std::string> headers;
public:
std::string get_response();
int content_length()
{
auto request = headers.find("content-length");
if (request != headers.end())
{
std::stringstream ssLength(request->second);
int content_length;
ssLength >> content_length;
return content_length;
}
return 0;
}
void on_read_header(std::string line)
{
//std::cout << "header: " << line << std::endl;
std::stringstream ssHeader(line);
std::string headerName;
std::getline(ssHeader, headerName, ':');
std::string value;
std::getline(ssHeader, value);
headers[headerName] = value;
}
void on_read_request_line(std::string line)
{
std::stringstream ssRequestLine(line);
ssRequestLine >> method;
ssRequestLine >> url;
ssRequestLine >> version;
std::cout << "request for resource: " << url << std::endl;
}
};
class session
{
asio::streambuf buff;
http_headers headers;
static void read_body(std::shared_ptr<session> pThis)
{
int nbuffer = 1000;
std::shared_ptr<std::vector<char>> bufptr = std::make_shared<std::vector<char>>(nbuffer);
asio::async_read(pThis->socket, boost::asio::buffer(*bufptr, nbuffer), [pThis](const boost::beast::error_code& e, std::size_t s)
{
});
}
static void read_next_line(std::shared_ptr<session> pThis)
{
asio::async_read_until(pThis->socket, pThis->buff, '\r', [pThis](const boost::beast::error_code& e, std::size_t s)
{
std::string line, ignore;
std::istream stream{ &pThis->buff };
std::getline(stream, line, '\r');
std::getline(stream, ignore, '\n');
pThis->headers.on_read_header(line);
if (line.length() == 0)
{
if (pThis->headers.content_length() == 0)
{
std::shared_ptr<std::string> str = std::make_shared<std::string>(pThis->headers.get_response());
asio::async_write(pThis->socket, boost::asio::buffer(str->c_str(), str->length()), [pThis, str](const boost::beast::error_code& e, std::size_t s)
{
std::cout << "done" << std::endl;
});
}
else
{
pThis->read_body(pThis);
}
}
else
{
pThis->read_next_line(pThis);
}
});
}
static void read_first_line(std::shared_ptr<session> pThis)
{
asio::async_read_until(pThis->socket, pThis->buff, '\r', [pThis](const boost::beast::error_code& e, std::size_t s)
{
std::string line, ignore;
std::istream stream{ &pThis->buff };
std::getline(stream, line, '\r');
std::getline(stream, ignore, '\n');
pThis->headers.on_read_request_line(line);
pThis->read_next_line(pThis);
});
}
public:
boost::asio::ip::tcp::socket socket;
session(io_service& io_service)
:socket(io_service)
{
}
static void interact(std::shared_ptr<session> pThis)
{
read_first_line(pThis);
}
};
class HttpServer {
public:
HttpServer();
boost::thread m_http_server_thread;
bool start_http_server = false;
bool is_started() { return start_http_server; }
void start();
void stop();
};
}
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,16 +1,9 @@
#ifndef slic3r_GUI_IMSlider_hpp_
#define slic3r_GUI_IMSlider_hpp_
#include "libslic3r/CustomGCode.hpp"
#include "wxExtensions.hpp"
#include "IMSlider_Utils.hpp"
#include "TickCode.hpp"
#include <imgui/imgui.h>
#include <wx/window.h>
#include <wx/control.h>
#include <wx/dc.h>
#include <wx/slider.h>
#include <vector>
#include <set>
class wxMenu;
@ -43,42 +36,6 @@ enum SelectedSlider {
ssHigher = 2
};
enum FocusedItem {
fiNone,
fiRevertIcon,
fiOneLayerIcon,
fiCogIcon,
fiColorBand,
fiActionIcon,
fiLowerThumb,
fiHigherThumb,
fiSmartWipeTower,
fiTick
};
enum ConflictType
{
ctNone,
ctModeConflict,
ctMeaninglessColorChange,
ctMeaninglessToolChange,
ctRedundant
};
enum MouseAction
{
maNone,
maAddMenu, // show "Add" context menu for NOTexist active tick
maEditMenu, // show "Edit" context menu for exist active tick
maCogIconMenu, // show context for "cog" icon
maForceColorEdit, // force color editing from colored band
maAddTick, // force tick adding
maDeleteTick, // force tick deleting
maCogIconClick, // LeftMouseClick on "cog" icon
maOneLayerIconClick, // LeftMouseClick on "one_layer" icon
maRevertIconClick, // LeftMouseClick on "revert" icon
};
enum DrawMode
{
dmRegular,
@ -94,116 +51,6 @@ enum LabelType
ltEstimatedTime,
};
enum VSliderMode
{
Regular,
Colored,
};
struct TickCode
{
bool operator<(const TickCode& other) const { return other.tick > this->tick; }
bool operator>(const TickCode& other) const { return other.tick < this->tick; }
int tick = 0;
Type type = ColorChange;
int extruder = 0;
std::string color;
std::string extra;
};
class TickCodeInfo
{
std::string custom_gcode;
std::string pause_print_msg;
bool m_suppress_plus = false;
bool m_suppress_minus = false;
bool m_use_default_colors= false;
// int m_default_color_idx = 0;
std::vector<std::string>* m_colors {nullptr};
ColorGenerator color_generator;
std::string get_color_for_tick(TickCode tick, Type type, const int extruder);
public:
std::set<TickCode> ticks {};
Mode mode = Undef;
bool empty() const { return ticks.empty(); }
void set_pause_print_msg(const std::string& message) { pause_print_msg = message; }
bool add_tick(const int tick, Type type, int extruder, double print_z);
bool edit_tick(std::set<TickCode>::iterator it, double print_z);
void switch_code(Type type_from, Type type_to);
bool switch_code_for_tick(std::set<TickCode>::iterator it, Type type_to, const int extruder);
void erase_all_ticks_with_code(Type type);
bool has_tick_with_code(Type type);
bool has_tick(int tick);
ConflictType is_conflict_tick(const TickCode& tick, Mode out_mode, int only_extruder, double print_z);
// Get used extruders for tick.
// Means all extruders(tools) which will be used during printing from current tick to the end
std::set<int> get_used_extruders_for_tick(int tick, int only_extruder, double print_z, Mode force_mode = Undef) const;
void suppress_plus (bool suppress) { m_suppress_plus = suppress; }
void suppress_minus(bool suppress) { m_suppress_minus = suppress; }
bool suppressed_plus () { return m_suppress_plus; }
bool suppressed_minus() { return m_suppress_minus; }
void set_default_colors(bool default_colors_on) { m_use_default_colors = default_colors_on; }
void set_extruder_colors(std::vector<std::string>* extruder_colors) { m_colors = extruder_colors; }
};
struct ExtrudersSequence
{
bool is_mm_intervals = true;
double interval_by_mm = 3.0;
int interval_by_layers = 10;
bool random_sequence { false };
bool color_repetition { false };
std::vector<size_t> extruders = { 0 };
bool operator==(const ExtrudersSequence& other) const
{
return (other.is_mm_intervals == this->is_mm_intervals ) &&
(other.interval_by_mm == this->interval_by_mm ) &&
(other.interval_by_layers == this->interval_by_layers ) &&
(other.random_sequence == this->random_sequence ) &&
(other.color_repetition == this->color_repetition ) &&
(other.extruders == this->extruders ) ;
}
bool operator!=(const ExtrudersSequence& other) const
{
return (other.is_mm_intervals != this->is_mm_intervals ) ||
(other.interval_by_mm != this->interval_by_mm ) ||
(other.interval_by_layers != this->interval_by_layers ) ||
(other.random_sequence != this->random_sequence ) ||
(other.color_repetition != this->color_repetition ) ||
(other.extruders != this->extruders ) ;
}
void add_extruder(size_t pos, size_t extruder_id = size_t(0))
{
extruders.insert(extruders.begin() + pos+1, extruder_id);
}
void delete_extruder(size_t pos)
{
if (extruders.size() == 1)
return;// last item can't be deleted
extruders.erase(extruders.begin() + pos);
}
void init(size_t extruders_count)
{
extruders.clear();
for (size_t extruder = 0; extruder < extruders_count; extruder++)
extruders.push_back(extruder);
}
};
class IMSlider
{
@ -262,7 +109,7 @@ public:
void UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); }
void on_mouse_wheel(wxMouseEvent& evt);
void post_ticks_changed_event(Type type = Custom);
void post_ticks_changed_event(Type type = Unknown);
bool check_ticks_changed_event(Type type);
bool switch_one_layer_mode();
void show_go_to_layer(bool show) { m_show_go_to_layer_dialog = show; }
@ -279,7 +126,6 @@ public:
}
Type get_post_tick_event_type() { return m_tick_change_event_type; }
ExtrudersSequence m_extruders_sequence;
float m_scale = 1.0;
void set_scale(float scale = 1.0);
void on_change_color_mode(bool is_dark);
@ -290,16 +136,16 @@ protected:
void do_go_to_layer(size_t layer_number);
void correct_lower_value();
void correct_higher_value();
bool horizontal_slider(const char* str_id, int* v, int v_min, int v_max, const ImVec2& pos, const ImVec2& size, float scale = 1.0);
bool horizontal_slider(const char* str_id, int* v, int v_min, int v_max, const ImVec2& size, float scale = 1.0);
void render_go_to_layer_dialog();
void render_input_custom_gcode();
void render_menu();
void draw_background(const ImRect& groove);
void draw_background_and_groove(const ImRect& bg_rect, const ImRect& groove);
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
void draw_ticks(const ImRect& slideable_region);
bool vertical_slider(const char* str_id, int* higher_value, int* lower_value,
std::string& higher_label, std::string& lower_label,
int v_min, int v_max, const ImVec2& pos, const ImVec2& size,
int v_min, int v_max, const ImVec2& size,
SelectedSlider& selection, bool one_layer_flag = false, float scale = 1.0f);
bool is_wipe_tower_layer(int tick) const;
@ -340,6 +186,7 @@ private:
bool m_enable_action_icon = true;
bool m_enable_cog_icon = false;
bool m_is_wipe_tower = false; // This flag indicates that there is multiple extruder print with wipe tower
bool m_is_spiral_vase = false;
bool m_display_lower = true;
bool m_display_higher = true;
int m_selected_tick_value = -1;
@ -362,7 +209,6 @@ private:
DrawMode m_draw_mode = dmRegular;
Mode m_mode = SingleExtruder;
VSliderMode m_vslider_mode = Regular;
int m_only_extruder = -1;
long m_style;

View file

@ -52,6 +52,11 @@ void IMToolbar::del_all_item()
m_items.clear();
}
void IMToolbar::del_stats_item()
{
delete m_all_plates_stats_item;
m_all_plates_stats_item = nullptr;
}
bool IMReturnToolbar::init()
{

View file

@ -27,10 +27,11 @@ public:
bool selected{ false };
float percent;
ImTextureID texture_id { 0 };
GLTexture image_texture;
GLTexture image_texture_transparent;
SliceState slice_state;
ImTextureID texture_id { 0 };
std::vector<unsigned char> image_data;
unsigned int image_width;
unsigned int image_height;
@ -47,6 +48,7 @@ public:
float icon_width;
float icon_height;
bool is_display_scrollbar;
bool show_stats_item{ false };
IMToolbar() {
icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH;
@ -54,7 +56,9 @@ public:
}
void del_all_item();
void del_stats_item();
IMToolbarItem* m_all_plates_stats_item = nullptr;
std::vector<IMToolbarItem*> m_items;
float fontScale;

View file

@ -82,6 +82,8 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::GapFillDarkIcon , "gap_fill_dark" },
{ImGui::SphereButtonDarkIcon , "toolbar_modifier_sphere_dark" },
{ImGui::TextSearchIcon , "im_text_search" },
{ImGui::TextSearchCloseIcon , "im_text_search_close" },
};
static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" },
@ -542,6 +544,123 @@ void ImGuiWrapper::set_next_window_size(float x, float y, ImGuiCond cond)
}
/* BBL style widgets */
bool ImGuiWrapper::bbl_combo_with_filter(const char* label, const std::string& preview_value, const std::vector<std::string>& all_items, std::vector<int>* filtered_items_idx, bool* is_filtered, float item_height)
{
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
static char pattern_buffer[256] = { 0 };
auto simple_match = [](const char* pattern, const char* str) {
wxString sub_str = wxString(pattern).Lower();
wxString main_str = wxString(str).Lower();
return main_str.Find(sub_str);
};
bool is_filtering = false;
bool is_new_open = false;
float sz = ImGui::GetFrameHeight();
ImVec2 arrow_size(sz, sz);
ImVec2 CursorPos = window->DC.CursorPos;
const ImRect arrow_bb(CursorPos, CursorPos + arrow_size);
float ButtonTextAlignX = g.Style.ButtonTextAlign.x;
g.Style.ButtonTextAlign.x = 0;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { sz, style.FramePadding.y});
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered));
if (button(preview_value + label, ImGui::CalcItemWidth(), 0))
{
ImGui::OpenPopup(label);
is_new_open = true;
}
g.Style.ButtonTextAlign.x = ButtonTextAlignX;
ImGui::PopStyleVar();
ImGui::PopStyleColor();
ImGui::BBLRenderArrow(window->DrawList, arrow_bb.Min + ImVec2(ImMax(0.0f, (arrow_size.x - g.FontSize) * 0.5f), ImMax(0.0f, (arrow_size.y - g.FontSize) * 0.5f)), ImGui::GetColorU32(ImGuiCol_Text), ImGuiDir_Down);
if (is_new_open)
memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
float item_rect_width = ImGui::GetItemRectSize().x;
float item_rect_height = item_height ? item_height : ImGui::GetItemRectSize().y;
ImGui::SetNextWindowPos({ CursorPos.x, ImGui::GetItemRectMax().y + 4 * m_style_scaling });
ImGui::SetNextWindowSize({ item_rect_width, 0 });
if (ImGui::BeginPopup(label))
{
ImGuiWindow* popup_window = ImGui::GetCurrentWindow();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8.0f * m_style_scaling, item_rect_height - g.FontSize) * 0.5f);
wchar_t ICON_SEARCH = *pattern_buffer != '\0' ? ImGui::TextSearchCloseIcon : ImGui::TextSearchIcon;
const ImVec2 label_size = ImGui::CalcTextSize(into_u8(ICON_SEARCH).c_str(), nullptr, true);
const ImVec2 search_icon_pos(ImGui::GetItemRectMax().x - label_size.x, popup_window->DC.CursorPos.y + style.FramePadding.y);
ImGui::RenderText(search_icon_pos, into_u8(ICON_SEARCH).c_str());
auto temp = popup_window->DC.CursorPos;
popup_window->DC.CursorPos = search_icon_pos;
ImGui::PushStyleColor(ImGuiCol_Button, {0, 0, 0, 0});
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_Border, { 0, 0, 0, 0 });
if (button("##invisible_clear_button", label_size.x, label_size.y))
{
if (*pattern_buffer != '\0')
memset(pattern_buffer, 0, IM_ARRAYSIZE(pattern_buffer));
}
ImGui::PopStyleColor(5);
popup_window->DC.CursorPos = temp;
ImGui::PushItemWidth(item_rect_width);
if (is_new_open)
ImGui::SetKeyboardFocusHere();
ImGui::InputText("##bbl_combo_with_filter_inputText", pattern_buffer, sizeof(pattern_buffer));
ImGui::PopItemWidth();
ImGui::PopStyleVar();
if (*pattern_buffer != '\0')
is_filtering = true;
if (is_filtering)
{
std::vector<std::pair<int, int> > filtered_items_with_priority;// std::pair<index, priority>
for (int i = 0; i < all_items.size(); i++)
{
int priority = simple_match(pattern_buffer, all_items[i].c_str());
if (priority != wxNOT_FOUND)
filtered_items_with_priority.push_back({ i, priority });
}
std::sort(filtered_items_with_priority.begin(), filtered_items_with_priority.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b) {return (b.second > a.second); });
for (auto item : filtered_items_with_priority)
{
filtered_items_idx->push_back(item.first);
}
}
*is_filtered = is_filtering;
popup_window->DC.CursorPos.y -= 1 * m_style_scaling;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1.0f, 1.0f) * m_style_scaling);
if (ImGui::BeginListBox("##bbl_combo_with_filter_listBox", { item_rect_width, item_rect_height * 7.75f})) {
ImGui::PopStyleVar(2);
return true;
}
else
{
ImGui::PopStyleVar(2);
ImGui::EndPopup();
return false;
}
}
else
return false;
}
bool ImGuiWrapper::bbl_input_double(const wxString& label, const double& value, const std::string& format)
{
//return ImGui::InputDouble(label.c_str(), const_cast<double *>(&value), 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal);
@ -1636,7 +1755,7 @@ static const ImWchar ranges_keyboard_shortcuts[] =
#endif // __APPLE__
std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height)
std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height, unsigned *outwidth, unsigned *outheight)
{
std::vector<unsigned char> empty_vector;
@ -1667,6 +1786,9 @@ std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name
::nsvgDeleteRasterizer(rast);
::nsvgDelete(image);
*outwidth = width;
*outheight = height;
return data;
}
@ -1951,11 +2073,12 @@ void ImGuiWrapper::init_font(bool compress)
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
assert(rect->Width == icon_sz);
assert(rect->Height == icon_sz);
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz);
unsigned outwidth, outheight;
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz, &outwidth, &outheight);
const ImU32* pIn = (ImU32*)raw_data.data();
for (int y = 0; y < icon_sz; y++) {
for (unsigned y = 0; y < outheight; y++) {
ImU32* pOut = (ImU32*)pixels + (rect->Y + y) * width + (rect->X);
for (int x = 0; x < icon_sz; x++)
for (unsigned x = 0; x < outwidth; x++)
*pOut++ = *pIn++;
}
}
@ -1967,11 +2090,12 @@ void ImGuiWrapper::init_font(bool compress)
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
assert(rect->Width == icon_sz);
assert(rect->Height == icon_sz);
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz);
unsigned outwidth, outheight;
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz, &outwidth, &outheight);
const ImU32* pIn = (ImU32*)raw_data.data();
for (int y = 0; y < icon_sz; y++) {
for (unsigned y = 0; y < outheight; y++) {
ImU32* pOut = (ImU32*)pixels + (rect->Y + y) * width + (rect->X);
for (int x = 0; x < icon_sz; x++)
for (unsigned x = 0; x < outwidth; x++)
*pOut++ = *pIn++;
}
}
@ -1983,11 +2107,12 @@ void ImGuiWrapper::init_font(bool compress)
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
assert(rect->Width == icon_sz);
assert(rect->Height == icon_sz);
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz);
unsigned outwidth, outheight;
std::vector<unsigned char> raw_data = load_svg(icon.second, icon_sz, icon_sz, &outwidth, &outheight);
const ImU32* pIn = (ImU32*)raw_data.data();
for (int y = 0; y < icon_sz; y++) {
for (unsigned y = 0; y < outheight; y++) {
ImU32* pOut = (ImU32*)pixels + (rect->Y + y) * width + (rect->X);
for (int x = 0; x < icon_sz; x++)
for (unsigned x = 0; x < outwidth; x++)
*pOut++ = *pIn++;
}
}

View file

@ -99,6 +99,7 @@ public:
void set_next_window_size(float x, float y, ImGuiCond cond);
/* BBL style widgets */
bool bbl_combo_with_filter(const char* label, const std::string& preview_value, const std::vector<std::string>& all_items, std::vector<int>* filtered_items_idx, bool* is_filtered, float item_height = 0.0f);
bool bbl_input_double(const wxString &label, const double &value, const std::string &format = "%0.2f");
bool bbl_slider_float(const std::string &label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {});
bool bbl_slider_float_style(const std::string &label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {});
@ -223,7 +224,7 @@ private:
void render_draw_data(ImDrawData *draw_data);
bool display_initialized() const;
void destroy_font();
std::vector<unsigned char> load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height);
std::vector<unsigned char> load_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height, unsigned *outwidth, unsigned *outheight);
static const char* clipboard_get(void* user_data);
static void clipboard_set(void* user_data, const char* text);

View file

@ -335,6 +335,7 @@ void ArrangeJob::prepare_partplate() {
return;
}
params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject;
Model& model = m_plater->model();
// Go through the objects and check if inside the selection

View file

@ -34,6 +34,12 @@ PrintJob::PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::
void PrintJob::prepare()
{
m_plater->get_print_job_data(&job_data);
if (&job_data) {
std::string temp_file = Slic3r::resources_dir() + "/check_access_code.txt";
auto check_access_code_path = temp_file.c_str();
BOOST_LOG_TRIVIAL(trace) << "sned_job: check_access_code_path = " << check_access_code_path;
job_data._temp_path = fs::path(check_access_code_path);
}
}
void PrintJob::on_exception(const std::exception_ptr &eptr)
@ -53,53 +59,60 @@ void PrintJob::on_success(std::function<void()> success)
wxString PrintJob::get_http_error_msg(unsigned int status, std::string body)
{
int code = 0;
std::string error;
std::string message;
wxString result;
if (status >= 400 && status < 500)
try {
json j = json::parse(body);
if (j.contains("code")) {
if (!j["code"].is_null())
code = j["code"].get<int>();
try {
int code = 0;
std::string error;
std::string message;
wxString result;
if (status >= 400 && status < 500)
try {
json j = json::parse(body);
if (j.contains("code")) {
if (!j["code"].is_null())
code = j["code"].get<int>();
}
if (j.contains("error")) {
if (!j["error"].is_null())
error = j["error"].get<std::string>();
}
if (j.contains("message")) {
if (!j["message"].is_null())
message = j["message"].get<std::string>();
}
switch (status) {
;
}
}
if (j.contains("error")) {
if (!j["error"].is_null())
error = j["error"].get<std::string>();
}
if (j.contains("message")) {
if (!j["message"].is_null())
message = j["message"].get<std::string>();
}
switch (status) {
catch (...) {
;
}
}
catch (...) {
else if (status == 503) {
return _L("Service Unavailable");
}
else {
wxString unkown_text = _L("Unkown Error.");
unkown_text += wxString::Format("status=%u, body=%s", status, body);
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
return unkown_text;
}
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
result = wxString::Format("code=%u, error=%s", code, from_u8(error));
return result;
} catch(...) {
;
}
else if (status == 503) {
return _L("Service Unavailable");
}
else {
wxString unkown_text = _L("Unkown Error.");
unkown_text += wxString::Format("status=%u, body=%s", status, body);
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
return unkown_text;
}
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
result = wxString::Format("code=%u, error=%s", code, from_u8(error));
return result;
}
return wxEmptyString;
}
void PrintJob::process()
{
/* display info */
wxString msg;
int curr_percent = 10;
NetworkAgent* m_agent = wxGetApp().getAgent();
AppConfig* config = wxGetApp().app_config;
if (this->connection_type == "lan") {
msg = _L("Sending print job over LAN");
@ -144,8 +157,34 @@ void PrintJob::process()
else
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
BBL::PrintParams params;
// local print access
params.dev_ip = m_dev_ip;
params.use_ssl = m_local_use_ssl;
params.username = "bblp";
params.password = m_access_code;
// check access code and ip address
if (this->connection_type == "lan") {
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
m_job_finished = true;
return;
}
}
params.dev_id = m_dev_id;
params.ftp_folder = m_ftp_folder;
//params.project_name = project_name;
params.project_name = m_project_name;
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
@ -161,12 +200,24 @@ void PrintJob::process()
params.ams_mapping_info = this->task_ams_mapping_info;
params.connection_type = this->connection_type;
params.task_use_ams = this->task_use_ams;
if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) {
ModelInfo* model_info = wxGetApp().model().model_info.get();
auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG);
if (origin_profile_id != model_info->metadata_items.end()) {
try {
params.origin_profile_id = stoi(origin_profile_id->second.c_str());
}
catch(...) {}
}
auto origin_model_id = model_info->metadata_items.find(BBL_DESIGNER_MODEL_ID_TAG);
if (origin_model_id != model_info->metadata_items.end()) {
try {
params.origin_model_id = origin_model_id->second;
}
catch(...) {}
}
}
// local print access
params.dev_ip = m_dev_ip;
params.use_ssl = m_local_use_ssl;
params.username = "bblp";
params.password = m_access_code;
wxString error_text;
wxString msg_text;
@ -247,9 +298,6 @@ void PrintJob::process()
return was_canceled();
};
NetworkAgent* m_agent = wxGetApp().getAgent();
if (params.connection_type != "lan") {
if (params.dev_ip.empty())
params.comments = "no_ip";
@ -260,32 +308,56 @@ void PrintJob::process()
else if (params.password.empty())
params.comments = "no_password";
if (!this->cloud_print_only
&& !params.password.empty()
&& !params.dev_ip.empty()
&& this->has_sdcard) {
// try to send local with record
BOOST_LOG_TRIVIAL(info) << "print_job: try to start local print with record";
this->update_status(curr_percent, _L("Sending print job over LAN"));
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
params.comments = "wrong_code";
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
params.comments = "upload_failed";
} else {
params.comments = (boost::format("failed(%1%)") % result).str();
//use ftp only
if (!wxGetApp().app_config->get("lan_mode_only").empty() && wxGetApp().app_config->get("lan_mode_only") == "1") {
if (params.password.empty() || params.dev_ip.empty()) {
error_text = wxString::Format("Access code:%s Ip address:%s", params.password, params.dev_ip);
result = BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED;
}
if (result < 0) {
// try to send with cloud
BOOST_LOG_TRIVIAL(warning) << "print_job: try to send with cloud";
else {
BOOST_LOG_TRIVIAL(info) << "print_job: use ftp send print only";
this->update_status(curr_percent, _L("Sending print job over LAN"));
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
if (result < 0) {
error_text = wxString::Format("Access code:%s Ip address:%s", params.password, params.dev_ip);
// try to send with cloud
BOOST_LOG_TRIVIAL(warning) << "print_job: use ftp send print failed";
}
}
}
else {
if (!this->cloud_print_only
&& !params.password.empty()
&& !params.dev_ip.empty()
&& this->has_sdcard) {
// try to send local with record
BOOST_LOG_TRIVIAL(info) << "print_job: try to start local print with record";
this->update_status(curr_percent, _L("Sending print job over LAN"));
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
params.comments = "wrong_code";
}
else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
params.comments = "upload_failed";
}
else {
params.comments = (boost::format("failed(%1%)") % result).str();
}
if (result < 0) {
// try to send with cloud
BOOST_LOG_TRIVIAL(warning) << "print_job: try to send with cloud";
this->update_status(curr_percent, _L("Sending print job through cloud service"));
result = m_agent->start_print(params, update_fn, cancel_fn);
}
}
else {
BOOST_LOG_TRIVIAL(info) << "print_job: send with cloud";
this->update_status(curr_percent, _L("Sending print job through cloud service"));
result = m_agent->start_print(params, update_fn, cancel_fn);
}
} else {
BOOST_LOG_TRIVIAL(info) << "print_job: send with cloud";
this->update_status(curr_percent, _L("Sending print job through cloud service"));
result = m_agent->start_print(params, update_fn, cancel_fn);
}
}
} else {
if (this->has_sdcard) {
this->update_status(curr_percent, _L("Sending print job over LAN"));
@ -344,4 +416,14 @@ void PrintJob::set_project_name(std::string name)
m_project_name = name;
}
void PrintJob::on_check_ip_address_fail(std::function<void()> func)
{
m_enter_ip_address_fun_fail = func;
}
void PrintJob::on_check_ip_address_success(std::function<void()> func)
{
m_enter_ip_address_fun_success = func;
}
}} // namespace Slic3r::GUI

View file

@ -29,6 +29,8 @@ class PrintJob : public PlaterJob
std::string m_dev_id;
bool m_job_finished{ false };
int m_print_job_completed_id = 0;
std::function<void()> m_enter_ip_address_fun_fail{ nullptr };
std::function<void()> m_enter_ip_address_fun_success{ nullptr };
protected:
@ -40,6 +42,7 @@ public:
std::string m_project_name;
std::string m_dev_ip;
std::string m_ftp_folder;
bool m_local_use_ssl { true };
std::string m_access_code;
std::string task_bed_type;
@ -78,6 +81,8 @@ public:
void process() override;
void finalize() override;
void set_project_name(std::string name);
void on_check_ip_address_fail(std::function<void()> func);
void on_check_ip_address_success(std::function<void()> func);
};
}} // namespace Slic3r::GUI

View file

@ -18,6 +18,7 @@ static wxString file_over_size_str = _L("The print file exceeds the max
static wxString print_canceled_str = _L("Task canceled");
static wxString upload_failed_str = _L("Failed uploading print file");
static wxString upload_login_failed_str = _L("Wrong Access code");
static wxString upload_no_space_left_str = _L("No space left on Printer SD card");
static wxString sending_over_lan_str = _L("Sending gcode file over LAN");
@ -39,7 +40,6 @@ void SendJob::prepare()
BOOST_LOG_TRIVIAL(trace) << "sned_job: check_access_code_path = " << check_access_code_path;
job_data._temp_path = fs::path(check_access_code_path);
}
}
void SendJob::on_exception(const std::exception_ptr &eptr)
@ -130,31 +130,33 @@ void SendJob::process()
params.use_ssl = m_local_use_ssl;
// check access code and ip address
if (m_is_check_mode) {
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
}
else {
m_enter_ip_address_fun_success();
}
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
m_job_finished = true;
return;
}
/* display info */
else if(m_is_check_mode && !m_check_and_continue){
m_enter_ip_address_fun_success();
m_job_finished = true;
return;
}
if (this->connection_type == "lan") {
/* display info */
msg = _L("Sending gcode file over LAN");
/* if (this->connection_type == "lan") {
msg = _L("Sending gcode file over LAN");
}
else {
msg = _L("Sending gcode file through cloud service");
}
}*/
int total_plate_num = m_plater->get_partplate_list().get_plate_count();
@ -313,9 +315,11 @@ void SendJob::process()
}
if (result < 0) {
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
if (result == BAMBU_NETWORK_ERR_NO_SPACE_LEFT_ON_DEVICE) {
msg_text = upload_no_space_left_str;
} else if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
msg_text = upload_login_failed_str;
} if (result == BAMBU_NETWORK_ERR_FILE_NOT_EXIST) {
} else if (result == BAMBU_NETWORK_ERR_FILE_NOT_EXIST) {
msg_text = file_is_not_exists_str;
} else if (result == BAMBU_NETWORK_ERR_FILE_OVER_SIZE) {
msg_text = file_over_size_str;

View file

@ -21,6 +21,7 @@ class SendJob : public PlaterJob
bool m_job_finished{ false };
int m_print_job_completed_id = 0;
bool m_is_check_mode{false};
bool m_check_and_continue{false};
std::function<void()> m_success_fun{nullptr};
std::function<void()> m_enter_ip_address_fun_fail{nullptr};
std::function<void()> m_enter_ip_address_fun_success{nullptr};
@ -54,6 +55,7 @@ public:
wxString get_http_error_msg(unsigned int status, std::string body);
void set_check_mode() {m_is_check_mode = true;};
void check_and_continue() {m_check_and_continue = true;};
bool is_finished() { return m_job_finished; }
void process() override;
void on_success(std::function<void()> success);

View file

@ -177,7 +177,13 @@ void KBShortcutsDialog::fill_shortcuts()
{ ctrl + "S", L("Save Project") },
{ ctrl + alt + "S", L("Save Project as") },
// File>Import
{ ctrl + "I", L("Import geometry data from STL/STEP/3MF/OBJ/AMF files.") },
{ ctrl + "I", L("Import geometry data from STL/STEP/3MF/OBJ/AMF files") },
// File>Export
{ ctrl + "G", L("Export plate sliced file")},
// Slice plate
{ ctrl + "R", L("Slice plate")},
// Send to Print
{ ctrl + "Shift" + "G", L("Print plate")},
// Edit
{ ctrl + "X", L("Cut") },
{ ctrl + "C", L("Copy to clipboard") },

View file

@ -72,9 +72,15 @@ namespace GUI {
wxDEFINE_EVENT(EVT_SELECT_TAB, wxCommandEvent);
wxDEFINE_EVENT(EVT_HTTP_ERROR, wxCommandEvent);
wxDEFINE_EVENT(EVT_USER_LOGIN, wxCommandEvent);
wxDEFINE_EVENT(EVT_USER_LOGIN_HANDLE, wxCommandEvent);
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDEFINE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDEFINE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
// BBS: backup
wxDEFINE_EVENT(EVT_BACKUP_POST, wxCommandEvent);
wxDEFINE_EVENT(EVT_LOAD_URL, wxCommandEvent);
@ -522,7 +528,19 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
}
return;}
#endif
if (evt.CmdDown() && evt.GetKeyCode() == 'J') { m_printhost_queue_dlg->Show(); return; }
if (evt.CmdDown() && evt.GetKeyCode() == 'R') { if (m_slice_enable) { wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); this->m_tabpanel->SetSelection(tpPreview); } return; }
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'G') {
m_plater->apply_background_progress();
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
if (m_print_enable) {
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE));
}
evt.Skip();
return;
}
else if (evt.CmdDown() && evt.GetKeyCode() == 'G') { if (can_export_gcode()) { wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); } evt.Skip(); return; }
if (evt.CmdDown() && evt.GetKeyCode() == 'J') { m_printhost_queue_dlg->Show(); return; }
if (evt.CmdDown() && evt.GetKeyCode() == 'N') { m_plater->new_project(); return;}
if (evt.CmdDown() && evt.GetKeyCode() == 'O') { m_plater->load_project(); return;}
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'S') { if (can_save_as()) m_plater->save_project(true); return;}
@ -693,6 +711,8 @@ void MainFrame::update_layout()
{
// jump to 3deditor under preview_only mode
if (evt.GetId() == tp3DEditor){
m_plater->update(true);
if (!preview_only_hint())
return;
}
@ -942,6 +962,7 @@ void MainFrame::init_tabpanel()
}
m_plater = new Plater(this, this);
m_plater->SetBackgroundColour(*wxWHITE);
m_plater->Hide();
wxGetApp().plater_ = m_plater;
@ -1017,11 +1038,9 @@ bool MainFrame::preview_only_hint()
preview_only_to_editor = true;
});
confirm_dlg.update_btn_label(_L("Yes"), _L("No"));
auto filename = wxString((m_plater->get_preview_only_filename()).c_str(), wxConvUTF8);
//if size of filename is beyond limit
auto format_filename = confirm_dlg.format_text(filename, FromDIP(240));
auto filename = m_plater->get_preview_only_filename();
confirm_dlg.update_text(format_filename + _L(" will be closed before creating a new model. Do you want to continue?"));
confirm_dlg.update_text(filename + " " + _L("will be closed before creating a new model. Do you want to continue?"));
confirm_dlg.on_show();
if (preview_only_to_editor) {
m_plater->new_project();
@ -1354,9 +1373,9 @@ wxBoxSizer* MainFrame::create_side_tools()
m_slice_select = eSlicePlate;
m_print_select = ePrintPlate;
m_slice_btn = new SideButton(this, _L("Slice"), "");
m_slice_btn = new SideButton(this, _L("Slice plate"), "");
m_slice_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
m_print_btn = new SideButton(this, _L("Print"), "");
m_print_btn = new SideButton(this, _L("Print plate"), "");
m_print_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
update_side_button_style();
@ -2108,12 +2127,12 @@ void MainFrame::init_menubar_as_editor()
[this](wxCommandEvent&) { if (m_plater) m_plater->export_core_3mf(); }, "menu_export_sliced_file", nullptr,
[this](){return can_export_model(); }, this);
// BBS export .gcode.3mf
append_menu_item(export_menu, wxID_ANY, _L("Export plate sliced file") + dots/* + "\tCtrl+G"*/, _L("Export current sliced file"),
append_menu_item(export_menu, wxID_ANY, _L("Export plate sliced file") + dots + "\tCtrl+G", _L("Export current sliced file"),
[this](wxCommandEvent&) { if (m_plater) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); }, "menu_export_sliced_file", nullptr,
[this](){return can_export_gcode(); }, this);
append_menu_item(export_menu, wxID_ANY, _L("Export all plate sliced file") + dots/* + "\tCtrl+G"*/, _L("Export all plate sliced file"),
[this](wxCommandEvent&) { if (m_plater) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); }, "menu_export_sliced_file", nullptr,
[this](wxCommandEvent&) { if (m_plater) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE)); }, "menu_export_sliced_file", nullptr,
[this]() {return can_export_all_gcode(); }, this);
append_menu_item(export_menu, wxID_ANY, _L("Export G-code") + dots/* + "\tCtrl+G"*/, _L("Export current plate as G-code"),
@ -2730,8 +2749,8 @@ struct ConfigsOverwriteConfirmDialog : MessageDialog
{
ConfigsOverwriteConfirmDialog(wxWindow *parent, wxString name, bool exported)
: MessageDialog(parent,
wxString::Format(exported ? _("A file exists with the same name: %s, do you wan't to override it.") :
_("A config exists with the same name: %s, do you wan't to override it."),
wxString::Format(exported ? _L("A file exists with the same name: %s, do you want to override it.") :
_L("A config exists with the same name: %s, do you want to override it."),
name),
_L(exported ? "Overwrite file" : "Overwrite config"),
wxYES_NO | wxNO_DEFAULT)
@ -3065,7 +3084,7 @@ void MainFrame::set_print_button_to_default(PrintSelectType select_type)
m_print_btn->SetLabel(_L("Print"));
m_print_select = eSendGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_enable = get_enable_print_status() && can_send_gcode();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else {
@ -3293,7 +3312,7 @@ void MainFrame::on_select_default_preset(SimpleEvent& evt)
{
case wxID_YES: {
wxGetApp().app_config->set_bool("sync_user_preset", true);
wxGetApp().start_sync_user_preset(true);
wxGetApp().start_sync_user_preset(true, true);
break;
}
case wxID_NO:

View file

@ -386,9 +386,15 @@ public:
wxDECLARE_EVENT(EVT_HTTP_ERROR, wxCommandEvent);
wxDECLARE_EVENT(EVT_USER_LOGIN, wxCommandEvent);
wxDECLARE_EVENT(EVT_USER_LOGIN_HANDLE, wxCommandEvent);
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDECLARE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDECLARE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
} // GUI
} //Slic3r

View file

@ -81,16 +81,6 @@ MarkdownTip::MarkdownTip()
_timer = new wxTimer;
_timer->Bind(wxEVT_TIMER, &MarkdownTip::OnTimer, this);
Bind(EVT_WEBVIEW_RECREATED, [this](auto &evt) {
Hide();
_lastTip.clear();
#ifdef __WXMSW__
_tipView = dynamic_cast<wxWebView *>(evt.GetEventObject());
GetSizer()->Add(_tipView, wxSizerFlags().Expand().Proportion(1));
Layout();
#endif
});
}
MarkdownTip::~MarkdownTip() { delete _timer; }

View file

@ -13,13 +13,9 @@
#include <boost/process.hpp>
#ifdef __WIN32__
#include <boost/process/windows.hpp>
#elif __APPLE__
#else
#include <sys/ipc.h>
#include <sys/shm.h>
#else
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#endif
namespace Slic3r {
@ -31,6 +27,9 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w
{
SetBackgroundColour(*wxWHITE);
m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this);
#if wxUSE_GSTREAMER_PLAYER
m_media_ctrl->Bind(wxEVT_MEDIA_LOADED, &MediaPlayCtrl::onStateChanged, this);
#endif
m_button_play = new Button(this, "", "media_play", wxBORDER_NONE);
m_button_play->SetCanFocus(false);
@ -87,7 +86,7 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
m_lan_ip = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->dev_ip : "";
m_lan_passwd = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->get_access_code() : "";
m_tutk_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
m_device_busy = obj->is_in_prepare();
m_device_busy = obj->is_in_prepare() || obj->is_in_upgrading();
} else {
m_camera_exists = false;
m_lan_mode = false;
@ -141,8 +140,10 @@ void MediaPlayCtrl::Play()
m_button_play->SetIcon("media_stop");
SetStatus(_L("Initializing..."));
NetworkAgent *agent = wxGetApp().getAgent();
std::string agent_version = agent ? agent->get_version() : "";
if (!m_lan_ip.empty() && (!m_lan_mode || !m_lan_passwd.empty()) && !m_device_busy) {
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + "&device=" + m_machine + "&version=" + agent_version;
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("dump_video") == "true") {
@ -182,9 +183,12 @@ void MediaPlayCtrl::Play()
return;
}
NetworkAgent* agent = wxGetApp().getAgent();
if (agent) {
agent->get_camera_url(m_machine, [this, m = m_machine](std::string url) {
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent_version](std::string url) {
if (boost::algorithm::starts_with(url, "bambu:///")) {
url += "&device=" + m;
url += "&version=" + v;
}
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl camera_url: " << url << ", machine: " << m_machine;
CallAfter([this, m, url] {
if (m != m_machine) return;
@ -233,14 +237,16 @@ void MediaPlayCtrl::Stop(wxString const &msg)
SetStatus(msg, false);
}
++m_failed_retry;
if (m_failed_code != 0 && !m_tutk_support && m_failed_retry > 1) {
if (m_failed_code != 0 && !m_tutk_support && (m_failed_retry > 1 || m_user_triggered)) {
m_next_retry = wxDateTime(); // stop retry
if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to start liveview)"))) {
m_failed_retry = 0;
m_user_triggered = true;
m_next_retry = wxDateTime::Now();
return;
}
}
m_user_triggered = false;
if (m_next_retry.IsValid())
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(5 * m_failed_retry);
}
@ -252,6 +258,7 @@ void MediaPlayCtrl::TogglePlay()
Stop();
} else {
m_failed_retry = 0;
m_user_triggered = true;
m_next_retry = wxDateTime::Now();
Play();
}
@ -315,8 +322,12 @@ void MediaPlayCtrl::ToggleStream()
}
NetworkAgent *agent = wxGetApp().getAgent();
if (!agent) return;
agent->get_camera_url(m_machine, [this, m = m_machine](std::string url) {
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent->get_version()](std::string url) {
if (boost::algorithm::starts_with(url, "bambu:///")) {
url += "&device=" + m;
url += "&version=" + v;
}
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
CallAfter([this, m, url] {
if (m != m_machine) return;
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
@ -327,7 +338,7 @@ void MediaPlayCtrl::ToggleStream()
}
std::string file_url = data_dir() + "/cameratools/url.txt";
boost::nowide::ofstream file(file_url);
auto url2 = encode_path((url + "&device=" + m).c_str());
auto url2 = encode_path(url.c_str());
file.write(url2.c_str(), url2.size());
file.close();
m_streaming = true;
@ -354,11 +365,11 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
Stop();
return;
}
if (last_state == MEDIASTATE_LOADING && state == wxMEDIASTATE_STOPPED) {
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED || event.GetEventType() == wxEVT_MEDIA_LOADED)) {
wxSize size = m_media_ctrl->GetVideoSize();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
m_failed_code = m_media_ctrl->GetLastError();
if (size.GetWidth() > 1000) {
if (size.GetWidth() > 1000 || (event.GetEventType() == wxEVT_MEDIA_LOADED)) {
m_last_state = state;
SetStatus(_L("Playing..."), false);
m_failed_retry = 0;
@ -442,14 +453,6 @@ void MediaPlayCtrl::media_proc()
}
}
#ifdef __WIN32__
struct detach_process
: public ::boost::process::detail::windows::handler_base_ext
{
template<class Executor> void on_setup(Executor &exec) const { exec.creation_flags |= ::boost::winapi::CREATE_NO_WINDOW_; }
};
#endif
bool MediaPlayCtrl::start_stream_service(bool *need_install)
{
#ifdef __WIN32__
@ -487,16 +490,16 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install)
std::string file_dll2 = data_dir() + "/plugins/BambuSource.dll";
if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2))
boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists);
boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::std_out > intermediate, detach_process(),
boost::process::start_dir(start_dir), boost::process::limit_handles);
boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::std_in < intermediate, detach_process(), boost::process::limit_handles);
boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir), boost::process::windows::create_no_window,
boost::process::std_out > intermediate, boost::process::limit_handles);
boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window,
boost::process::std_in < intermediate, boost::process::limit_handles);
#else
boost::filesystem::permissions(file_source, boost::filesystem::owner_exe | boost::filesystem::add_perms);
boost::filesystem::permissions(file_ffmpeg, boost::filesystem::owner_exe | boost::filesystem::add_perms);
// TODO: limit_handles has bugs on posix
boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::std_out > intermediate,
boost::process::start_dir(start_dir));
boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::std_in < intermediate);
boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir),
boost::process::std_out > intermediate, boost::process::limit_handles);
boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::std_in < intermediate, boost::process::limit_handles);
#endif
process_source.detach();
process_ffmpeg.detach();
@ -521,7 +524,7 @@ bool MediaPlayCtrl::get_stream_url(std::string *url)
}
}
CloseHandle(shm);
#elif __APPLE__
#else
std::string file_url = data_dir() + "/cameratools/url.txt";
key_t key = ::ftok(file_url.c_str(), 1000);
int shm = ::shmget(key, 1024, 0);
@ -539,18 +542,6 @@ bool MediaPlayCtrl::get_stream_url(std::string *url)
url = nullptr;
}
}
#else
int shm = ::shm_open("bambu_stream_url", O_RDONLY, 0);
if (shm == -1) return false;
if (url) {
char *addr = (char *) ::mmap(nullptr, 1024, PROT_READ, MAP_SHARED, shm, 0);
if (addr != MAP_FAILED) {
*url = addr;
::munmap(addr, 1024);
url = nullptr;
}
}
::close(shm);
#endif
return url == nullptr;
}

View file

@ -83,6 +83,7 @@ private:
boost::thread m_thread;
bool m_streaming = false;
bool m_user_triggered = false;
int m_failed_retry = 0;
int m_failed_code = 0;
wxDateTime m_next_retry;

View file

@ -147,7 +147,10 @@ namespace GUI {
filename = j["data"]["filename"].get<std::string>();
if (download_url.empty()) return;
wxGetApp().plater()->request_model_download(download_url, filename);
wxGetApp().set_download_model_url(download_url);
wxGetApp().set_download_model_name(filename);
wxGetApp().plater()->request_model_download();
}
else if(strCmd == "request_close_publish_window") {
this->Hide();

View file

@ -153,7 +153,7 @@ MonitorPanel::~MonitorPanel()
if (!dev) return;
MachineObject *obj_ = dev->get_selected_machine();
if (obj_)
GUI::wxGetApp().sidebar().load_ams_list(obj_->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_->amsList);
}
void MonitorPanel::init_tabpanel()
@ -228,7 +228,7 @@ void MonitorPanel::set_default()
/* reset side tool*/
//m_bitmap_wifi_signal->SetBitmap(wxNullBitmap);
wxGetApp().sidebar().load_ams_list({});
wxGetApp().sidebar().load_ams_list({}, {});
}
wxWindow* MonitorPanel::create_side_tools()
@ -309,7 +309,7 @@ void MonitorPanel::on_update_all(wxMouseEvent &event)
MachineObject *obj_ = dev->get_selected_machine();
if (obj_)
GUI::wxGetApp().sidebar().load_ams_list(obj_->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_->amsList);
Layout();
Refresh();
@ -478,6 +478,9 @@ bool MonitorPanel::Show(bool show)
obj = dev->get_selected_machine();
if (obj == nullptr) {
dev->load_last_machine();
obj = dev->get_selected_machine();
if (obj)
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj->amsList);
} else {
obj->reset_update_time();
}

View file

@ -357,8 +357,21 @@ void NotificationManager::PopNotification::count_lines()
if (text.empty())
return;
// handle with marks
if (pos_start == string::npos && pos_end == string::npos) {
pos_start = text.find(error_start);
if (pos_start != string::npos) {
text.erase(pos_start, error_start.length());
pos_end = text.find(error_end);
if (pos_end != string::npos) {
text.erase(pos_end, error_end.length());
}
}
m_text1 = text;
}
m_endlines.clear();
while (last_end < text.length() - 1)
while (last_end < text.length())
{
size_t next_hard_end = text.find_first_of('\n', last_end);
if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) {
@ -481,7 +494,14 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
if (m_text1.size() > m_endlines[i])
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
imgui.text(line.c_str());
if (pos_start != string::npos && pos_end != string::npos&& m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
push_style_color(ImGuiCol_Text, m_ErrorColor, m_state == EState::FadingOut, m_current_fade_opacity);
imgui.text(line.c_str());
ImGui::PopStyleColor();
}
else {
imgui.text(line.c_str());
}
}
}
//hyperlink text
@ -819,6 +839,7 @@ void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiW
void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
auto scale = wxGetApp().plater()->get_current_canvas3D()->get_scale();
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
@ -836,20 +857,15 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
{
button_text = ImGui::EjectHoverButton;
//tooltip
long time_now = wxGetLocalTime();
if (m_hover_time > 0 && m_hover_time < time_now) {
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
//ImGui::BeginTooltip();
//imgui.text(_u8L("Eject drive") + " " + GUI::shortkey_ctrl_prefix() + "T");
//ImGui::EndTooltip();
ImGui::PopStyleColor();
}
if (m_hover_time == 0)
m_hover_time = time_now;
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 });
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8 * scale, 1 * scale });
ImGui::BeginTooltip();
imgui.text(_u8L("Safely remove hardware."));
ImGui::EndTooltip();
ImGui::PopStyleColor(2);
ImGui::PopStyleVar();
}
else
m_hover_time = 0;
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
@ -1248,7 +1264,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slice ok."), m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") };
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slice ok.") };
update(data);
m_state = EState::Shown;
}
@ -1549,8 +1565,8 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
void NotificationManager::on_change_color_mode(bool is_dark) {
m_is_dark = is_dark;
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications){
notification->on_change_color_mode(is_dark);
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications){
notification->on_change_color_mode(is_dark);
}
}
@ -2322,7 +2338,6 @@ size_t NotificationManager::get_notification_count() const
return ret;
}
void NotificationManager::bbl_show_plateinfo_notification(const std::string &text)
{
NotificationData data{NotificationType::BBLPlateInfo, NotificationLevel::PrintInfoNotificationLevel, BBL_NOTICE_MAX_INTERVAL, text};
@ -2339,6 +2354,30 @@ void NotificationManager::bbl_show_plateinfo_notification(const std::string &tex
push_notification_data(std::move(notification), 0);
}
void NotificationManager::bbl_close_3mf_warn_notification()
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications)
if (notification->get_type() == NotificationType::BBL3MFInfo) {
notification->close();
}
}
void NotificationManager::bbl_show_3mf_warn_notification(const std::string &text)
{
NotificationData data{NotificationType::BBL3MFInfo, NotificationLevel::ErrorNotificationLevel, BBL_NOTICE_MAX_INTERVAL, text};
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::BBL3MFInfo) {
notification->reinit();
notification->update(data);
return;
}
}
auto notification = std::make_unique<NotificationManager::PopNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0);
}
void NotificationManager::bbl_close_plateinfo_notification()
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications)
@ -2347,6 +2386,7 @@ void NotificationManager::bbl_close_plateinfo_notification()
}
}
void NotificationManager::bbl_show_preview_only_notification(const std::string &text)
{
NotificationData data{NotificationType::BBLPreviewOnlyMode, NotificationLevel::WarningNotificationLevel, 0, text};

View file

@ -123,6 +123,8 @@ enum class NotificationType
ArrangeOngoing,
// BBL: Plate Info ,Design For @YangLeDuo
BBLPlateInfo,
// BBL: 3MF warnings
BBL3MFInfo,
// BBL: Some Objects Info, Design For @YangLeDuo
BBLObjectInfo,
// BBL: Objects have empty layer when Slicing
@ -282,6 +284,10 @@ public:
void bbl_show_plateinfo_notification(const std::string &text);
void bbl_close_plateinfo_notification();
//BBS-- 3mf warning
void bbl_show_3mf_warn_notification(const std::string &text);
void bbl_close_3mf_warn_notification();
//BBS--preview only mode
void bbl_show_preview_only_notification(const std::string &text);
void bbl_close_preview_only_notification();
@ -488,6 +494,11 @@ private:
std::string m_hypertext;
// Aditional text after hypertext - currently not used
std::string m_text2;
// mark for render operation
size_t pos_start = string::npos;
size_t pos_end = string::npos;
std::string error_start = "<Error>";
std::string error_end = "</Error>";
// inner variables to position notification window, texts and buttons correctly

View file

@ -952,14 +952,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
case coInts:
ret = config.option<ConfigOptionIntsNullable>(opt_key)->get_at(idx);
break;
case coPoints:
if (opt_key == "bed_shape")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
else if (opt_key == "thumbnails")
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
break;
case coEnums:
ret = config.option<ConfigOptionEnumsGenericNullable>(opt_key)->get_at(idx);
break;
default:
break;
}
@ -1233,13 +1228,22 @@ void ExtruderOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const
wxString OptionsGroup::get_url(const std::string& path_end)
{
//BBS
wxString str = from_u8(path_end);
auto pos = str.find(L'#');
if (pos != size_t(-1)) {
pos++;
wxString anchor = str.Mid(pos).Lower();
anchor.Replace(L" ", "-");
str = str.Left(pos) + anchor;
}
// Softfever: point to sf wiki for seam parameters
if (path_end == "Seam") {
return wxString::Format(L"https://github.com/SoftFever/BambuStudio-SoftFever/wiki/%s", from_u8(path_end));
}
else {
//BBS
return wxString::Format(L"https://wiki.bambulab.com/%s/software/bambu-studio/%s", L"en", from_u8(path_end));
return wxString::Format(L"https://wiki.bambulab.com/%s/software/bambu-studio/%s", L"en", str);
}
}

View file

@ -134,7 +134,7 @@ void ParamsPanel::Highlighter::set_timer_owner(wxEvtHandler *owner, int timerid
m_timer.SetOwner(owner, timerid);
}
void ParamsPanel::Highlighter::init(std::pair<wxStaticBitmap *, bool *> params, wxWindow *parent)
void ParamsPanel::Highlighter::init(std::pair<wxWindow *, bool *> params, wxWindow *parent)
{
if (m_timer.IsRunning()) invalidate();
if (!params.first || !params.second) return;
@ -185,7 +185,6 @@ void ParamsPanel::Highlighter::blink()
ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
: wxPanel( parent, id, pos, size, style, name )
{
init_bitmaps();
// BBS: new layout
SetBackgroundColour(*wxWHITE);
#if __WXOSX__
@ -223,7 +222,7 @@ ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, c
m_mode_region->SetMaxSize({em_unit(this) * 12, -1});
m_mode_region->SetLabels(_L("Global"), _L("Objects"));
//m_mode_region->GetSize(&width, &height);
m_tips_arrow = new wxStaticBitmap(m_top_panel, wxID_ANY, m_tips_arrow_icon);
m_tips_arrow = new ScalableButton(m_top_panel, wxID_ANY, "tips_arrow");
m_tips_arrow->Hide();
m_title_view = new Label(m_top_panel, _L("Advance"));
@ -348,11 +347,6 @@ ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, c
//m_import_from_file->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { wxGetApp().mainframe->load_config_file(); });
}
void ParamsPanel::init_bitmaps()
{
m_tips_arrow_icon = create_scaled_bitmap("tips_arrow", nullptr, 24);
}
void ParamsPanel::create_layout()
{
#ifdef __WINDOWS__
@ -370,19 +364,18 @@ void ParamsPanel::create_layout()
m_mode_sizer->Add(m_process_icon, 0, wxALIGN_CENTER);
m_mode_sizer->AddSpacer(FromDIP(11));
m_mode_sizer->Add( m_title_label, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(9));
m_mode_sizer->Add( m_mode_region, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(9));
m_mode_sizer->Add( m_tips_arrow, 0, wxALIGN_CENTER);
m_mode_sizer->AddStretchSpacer(2);
m_mode_sizer->Add(m_mode_region, 0, wxALIGN_CENTER);
m_mode_sizer->AddStretchSpacer(1);
m_mode_sizer->Add(m_tips_arrow, 0, wxALIGN_CENTER);
m_mode_sizer->AddStretchSpacer(8);
m_mode_sizer->Add( m_title_view, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(9));
m_mode_sizer->Add( m_mode_view, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(16));
m_mode_sizer->Add( m_setting_btn, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(16));
m_mode_sizer->Add( m_compare_btn, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(2));
m_mode_sizer->Add(m_mode_view, 0, wxALIGN_CENTER);
m_mode_sizer->AddStretchSpacer(2);
m_mode_sizer->Add(m_setting_btn, 0, wxALIGN_CENTER);
m_mode_sizer->AddSpacer(FromDIP(2));
m_mode_sizer->Add(m_compare_btn, 0, wxALIGN_CENTER);
m_mode_sizer->AddSpacer(FromDIP(8));
//m_mode_sizer->Add( m_search_btn, 0, wxALIGN_CENTER );
@ -649,6 +642,7 @@ void ParamsPanel::msw_rescale()
if (m_setting_btn) m_setting_btn->msw_rescale();
if (m_search_btn) m_search_btn->msw_rescale();
if (m_compare_btn) m_compare_btn->msw_rescale();
if (m_tips_arrow) m_tips_arrow->msw_rescale();
m_left_sizer->SetMinSize(wxSize(40 * em_unit(this), -1));
if (m_mode_sizer)
m_mode_sizer->SetMinSize(-1, 3 * em_unit(this));

View file

@ -82,7 +82,7 @@ class ParamsPanel : public wxPanel
ScalableButton* m_process_icon{ nullptr };
wxStaticText* m_title_label { nullptr };
SwitchButton* m_mode_region { nullptr };
wxStaticBitmap* m_tips_arrow{ nullptr };
ScalableButton *m_tips_arrow{nullptr};
bool m_tips_arror_blink{false};
wxStaticText* m_title_view { nullptr };
SwitchButton* m_mode_view { nullptr };
@ -116,7 +116,6 @@ class ParamsPanel : public wxPanel
wxBitmap m_toggle_on_icon;
wxBitmap m_toggle_off_icon;
wxBitmap m_tips_arrow_icon;
wxPanel* m_current_tab { nullptr };
@ -125,12 +124,12 @@ class ParamsPanel : public wxPanel
struct Highlighter
{
void set_timer_owner(wxEvtHandler *owner, int timerid = wxID_ANY);
void init(std::pair<wxStaticBitmap *, bool *>, wxWindow *parent = nullptr);
void init(std::pair<wxWindow *, bool *>, wxWindow *parent = nullptr);
void blink();
void invalidate();
private:
wxStaticBitmap *m_bitmap { nullptr };
wxWindow * m_bitmap{nullptr};
bool * m_show_blink_ptr{nullptr};
int m_blink_counter{0};
wxTimer m_timer;
@ -143,7 +142,6 @@ class ParamsPanel : public wxPanel
ParamsPanel( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1800,1080 ), long style = wxTAB_TRAVERSAL, const wxString& type = wxEmptyString );
~ParamsPanel();
void init_bitmaps();
void rebuild_panels();
void create_layout();
//clear the right page

View file

@ -133,7 +133,7 @@ void PartPlate::init()
m_print = nullptr;
}
BedType PartPlate::get_bed_type(bool check_global/*= true*/) const
BedType PartPlate::get_bed_type() const
{
std::string bed_type_key = "curr_bed_type";
@ -141,32 +141,26 @@ BedType PartPlate::get_bed_type(bool check_global/*= true*/) const
assert(m_plater != nullptr);
if (m_config.has(bed_type_key)) {
BedType bed_type = m_config.opt_enum<BedType>(bed_type_key);
if (bed_type != btDefault)
return bed_type;
return bed_type;
}
if (!check_global)
return btDefault;
if (m_plater) {
// In GUI mode
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
if (proj_cfg.has(bed_type_key))
return proj_cfg.opt_enum<BedType>(bed_type_key);
}
return BedType::btPC;
return btDefault;
}
void PartPlate::set_bed_type(BedType bed_type)
{
std::string bed_type_key = "curr_bed_type";
std::string bed_type_key = "curr_bed_type";
// should be called in GUI context
assert(m_plater != nullptr);
// should be called in GUI context
assert(m_plater != nullptr);
// update slice state
BedType old_real_bed_type = get_bed_type();
if (old_real_bed_type == btDefault) {
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
if (proj_cfg.has(bed_type_key))
old_real_bed_type = proj_cfg.opt_enum<BedType>(bed_type_key);
}
BedType new_real_bed_type = bed_type;
if (bed_type == BedType::btDefault) {
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
@ -177,18 +171,74 @@ void PartPlate::set_bed_type(BedType bed_type)
update_slice_result_valid_state(false);
}
if (bed_type == BedType::btDefault)
m_config.erase(bed_type_key);
else
m_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
if (m_plater)
m_plater->update_project_dirty_from_presets();
if (bed_type == BedType::btDefault)
m_config.erase(bed_type_key);
else
m_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
}
void PartPlate::reset_bed_type()
{
m_config.erase("curr_bed_type");
m_config.erase("curr_bed_type");
}
void PartPlate::set_print_seq(PrintSequence print_seq)
{
std::string print_seq_key = "print_sequence";
// should be called in GUI context
assert(m_plater != nullptr);
// update slice state
PrintSequence old_real_print_seq = get_print_seq();
if (old_real_print_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has(print_seq_key))
old_real_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>(print_seq_key)->value;
}
PrintSequence new_real_print_seq = print_seq;
if (print_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has(print_seq_key))
new_real_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>(print_seq_key)->value;
}
if (old_real_print_seq != new_real_print_seq) {
update_slice_result_valid_state(false);
}
//print_seq_same_global = same_global;
if (print_seq == PrintSequence::ByDefault)
m_config.erase(print_seq_key);
else
m_config.set_key_value(print_seq_key, new ConfigOptionEnum<PrintSequence>(print_seq));
}
PrintSequence PartPlate::get_print_seq() const
{
std::string print_seq_key = "print_sequence";
// should be called in GUI context
assert(m_plater != nullptr);
if (m_config.has(print_seq_key)) {
PrintSequence print_seq = m_config.opt_enum<PrintSequence>(print_seq_key);
return print_seq;
}
return PrintSequence::ByDefault;
}
PrintSequence PartPlate::get_real_print_seq() const
{
PrintSequence curr_plate_seq = get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has("print_sequence")) curr_plate_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
}
return curr_plate_seq;
}
bool PartPlate::valid_instance(int obj_id, int instance_id)
@ -545,7 +595,7 @@ void PartPlate::render_logo(bool bottom) const
//canvas.request_extra_frame();
}
if (m_vbo_id == 0) {
unsigned int* vbo_id_ptr = const_cast<unsigned int*>(&m_vbo_id);
glsafe(::glGenBuffers(1, vbo_id_ptr));
@ -561,13 +611,19 @@ void PartPlate::render_logo(bool bottom) const
m_partplate_list->load_bedtype_textures();
// btDefault should be skipped
int bed_type_idx = (int)get_bed_type();
auto curr_bed_type = get_bed_type();
if (curr_bed_type == btDefault) {
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
if (proj_cfg.has(std::string("curr_bed_type")))
curr_bed_type = proj_cfg.opt_enum<BedType>(std::string("curr_bed_type"));
}
int bed_type_idx = (int)curr_bed_type;
for (auto &part : m_partplate_list->bed_texture_info[bed_type_idx].parts) {
if (part.texture) {
if (part.buffer && part.buffer->get_vertices_count() > 0
//&& part.vbo_id != 0
) {
if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
part.offset = Vec2d(m_origin.x(), m_origin.y());
part.update_buffer();
}
@ -739,18 +795,18 @@ void PartPlate::render_icons(bool bottom, int hover_id) const
render_icon_texture(position_id, tex_coords_id, m_lock_icon, m_partplate_list->m_lockopen_texture, m_lock_vbo_id);
}
if (m_partplate_list->render_bedtype_setting) {
if (m_partplate_list->render_plate_settings) {
if (hover_id == 5) {
if (get_bed_type(false) == BedType::btDefault)
render_icon_texture(position_id, tex_coords_id, m_bedtype_icon, m_partplate_list->m_bedtype_hovered_texture, m_bedtype_vbo_id);
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault)
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_hovered_texture, m_plate_settings_vbo_id);
else
render_icon_texture(position_id, tex_coords_id, m_bedtype_icon, m_partplate_list->m_bedtype_changed_hovered_texture, m_bedtype_vbo_id);
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_hovered_texture, m_plate_settings_vbo_id);
}
else {
if (get_bed_type(false) == BedType::btDefault)
render_icon_texture(position_id, tex_coords_id, m_bedtype_icon, m_partplate_list->m_bedtype_texture, m_bedtype_vbo_id);
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault)
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_texture, m_plate_settings_vbo_id);
else
render_icon_texture(position_id, tex_coords_id, m_bedtype_icon, m_partplate_list->m_bedtype_changed_texture, m_bedtype_vbo_id);
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_texture, m_plate_settings_vbo_id);
}
}
@ -1088,8 +1144,8 @@ void PartPlate::on_render_for_picking() const {
m_grabber_color[1] = color[1];
m_grabber_color[2] = color[2];
m_grabber_color[3] = color[3];
if (m_partplate_list->render_bedtype_setting)
render_rectangle_for_picking(m_bedtype_icon, m_grabber_color);
if (m_partplate_list->render_plate_settings)
render_rectangle_for_picking(m_plate_settings_icon, m_grabber_color);
}
std::array<float, 4> PartPlate::picking_color_component(int idx) const
@ -1126,9 +1182,9 @@ void PartPlate::release_opengl_resource()
glsafe(::glDeleteBuffers(1, &m_lock_vbo_id));
m_lock_vbo_id = 0;
}
if (m_bedtype_vbo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_bedtype_vbo_id));
m_bedtype_vbo_id = 0;
if (m_plate_settings_vbo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_plate_settings_vbo_id));
m_plate_settings_vbo_id = 0;
}
if (m_plate_idx_vbo_id > 0) {
glsafe(::glDeleteBuffers(1, &m_plate_idx_vbo_id));
@ -1136,7 +1192,7 @@ void PartPlate::release_opengl_resource()
}
}
std::vector<int> PartPlate::get_extruders() const
std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
{
std::vector<int> plate_extruders;
// if gcode.3mf file
@ -1152,6 +1208,7 @@ std::vector<int> PartPlate::get_extruders() const
int glb_support_intf_extr = glb_config.opt_int("support_interface_filament");
int glb_support_extr = glb_config.opt_int("support_filament");
bool glb_support = glb_config.opt_bool("enable_support");
glb_support |= glb_config.opt_int("raft_layers") > 0;
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
if (!contain_instance_totally(obj_idx, 0))
@ -1165,8 +1222,13 @@ std::vector<int> PartPlate::get_extruders() const
bool obj_support = false;
const ConfigOption* obj_support_opt = mo->config.option("enable_support");
if (obj_support_opt != nullptr)
obj_support = obj_support_opt->getBool();
const ConfigOption *obj_raft_opt = mo->config.option("raft_layers");
if (obj_support_opt != nullptr || obj_raft_opt != nullptr) {
if (obj_support_opt != nullptr)
obj_support = obj_support_opt->getBool();
if (obj_raft_opt != nullptr)
obj_support |= obj_raft_opt->getInt() > 0;
}
else
obj_support = glb_support;
@ -1192,6 +1254,16 @@ std::vector<int> PartPlate::get_extruders() const
plate_extruders.push_back(glb_support_extr);
}
if (conside_custom_gcode) {
//BBS
if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
if (item.type == CustomGCode::Type::ToolChange)
plate_extruders.push_back(item.extruder);
}
}
}
std::sort(plate_extruders.begin(), plate_extruders.end());
auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
@ -1223,7 +1295,7 @@ std::vector<int> PartPlate::get_used_extruders()
Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volume) const
{
Vec3d wipe_tower_size;
std::vector<int> plate_extruders = get_extruders();
std::vector<int> plate_extruders = get_extruders(true);
double layer_height = 0.08f; // hard code layer height
double max_height = 0.f;
wipe_tower_size.setZero();
@ -1673,6 +1745,29 @@ int PartPlate::remove_instance(int obj_id, int instance_id)
return result;
}
//translate instance on the plate
void PartPlate::translate_all_instance(Vec3d position)
{
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
{
int obj_id = it->first;
int instance_id = it->second;
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
{
ModelObject* object = m_model->objects[obj_id];
if ((instance_id >= 0) && (instance_id < object->instances.size()))
{
ModelInstance* instance = object->instances[instance_id];
const Vec3d& offset = instance->get_offset();
instance->set_offset(offset + position);
}
}
}
return;
}
//update instance exclude state
void PartPlate::update_instance_exclude_status(int obj_id, int instance_id, BoundingBoxf3* bounding_box)
{
@ -1722,6 +1817,26 @@ void PartPlate::update_object_index(int obj_idx_removed, int obj_idx_max)
}
int PartPlate::printable_instance_size()
{
int size = 0;
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
int obj_id = it->first;
int instance_id = it->second;
if (obj_id >= m_model->objects.size())
continue;
ModelObject * object = m_model->objects[obj_id];
ModelInstance *instance = object->instances[instance_id];
if ((instance->printable) && (instance_outside_set.find(std::pair(obj_id, instance_id)) == instance_outside_set.end())) {
size++;
}
}
return size;
}
//whether it is has printable instances
bool PartPlate::has_printable_instances()
{
@ -1917,17 +2032,27 @@ void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon)
bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod)
{
if ((m_shape == shape)&&(m_exclude_area == exclude_areas)
Pointfs new_shape, new_exclude_areas;
for (const Vec2d& p : shape) {
new_shape.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
}
for (const Vec2d& p : exclude_areas) {
new_exclude_areas.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
}
if ((m_shape == new_shape)&&(m_exclude_area == new_exclude_areas)
&&(m_height_to_lid == height_to_lid)&&(m_height_to_rod == height_to_rod)) {
BOOST_LOG_TRIVIAL(trace) << "PartPlate same shape";
BOOST_LOG_TRIVIAL(info) << "PartPlate same shape, skip directly";
return false;
}
m_height_to_lid = height_to_lid;
m_height_to_rod = height_to_rod;
if ((m_shape != shape) || (m_exclude_area != exclude_areas))
if ((m_shape != new_shape) || (m_exclude_area != new_exclude_areas))
{
m_shape.clear();
/*m_shape.clear();
for (const Vec2d& p : shape) {
m_shape.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
}
@ -1935,7 +2060,9 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve
m_exclude_area.clear();
for (const Vec2d& p : exclude_areas) {
m_exclude_area.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
}
}*/
m_shape = std::move(new_shape);
m_exclude_area = std::move(new_exclude_areas);
calc_bounding_boxes();
@ -1970,7 +2097,7 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve
calc_vertex_for_icons(1, m_orient_icon);
calc_vertex_for_icons(2, m_arrange_icon);
calc_vertex_for_icons(3, m_lock_icon);
calc_vertex_for_icons(4, m_bedtype_icon);
calc_vertex_for_icons(4, m_plate_settings_icon);
//calc_vertex_for_number(0, (m_plate_index < 9), m_plate_idx_icon);
calc_vertex_for_number(0, false, m_plate_idx_icon);
}
@ -2188,10 +2315,13 @@ int PartPlate::load_gcode_from_file(const std::string& filename)
int ret = 0;
// process gcode
m_print->apply(*m_model, wxGetApp().preset_bundle->full_config());
DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config();
full_config.apply(m_config, true);
m_print->apply(*m_model, full_config);
//BBS: need to apply two times, for after the first apply, the m_print got its object,
//which will affect the config when new_full_config.normalize_fdm(used_filaments);
m_print->apply(*m_model, wxGetApp().preset_bundle->full_config());
m_print->apply(*m_model, full_config);
// BBS: use backup path to save temp gcode
// auto path = get_tmp_gcode_path();
// if (boost::filesystem::exists(boost::filesystem::path(path))) {
@ -2372,6 +2502,23 @@ Vec3d PartPlateList::compute_origin(int i, int cols)
return origin;
}
//compute the origin for printable plate with index i using new width
Vec3d PartPlateList::compute_origin_using_new_size(int i, int new_width, int new_depth)
{
Vec3d origin;
int row, col;
row = i / m_plate_cols;
col = i % m_plate_cols;
origin(0) = col * (new_width * (1. + LOGICAL_PART_PLATE_GAP));
origin(1) = -row * (new_depth * (1. + LOGICAL_PART_PLATE_GAP));
origin(2) = 0;
return origin;
}
//compute the origin for printable plate with index i
Vec3d PartPlateList::compute_origin_for_unprintable()
{
@ -2489,32 +2636,32 @@ void PartPlateList::generate_icon_textures()
//if (m_bedtype_texture.get_id() == 0)
{
file_name = path + (m_is_dark ? "plate_set_bedtype_dark.svg" : "plate_set_bedtype.svg");
if (!m_bedtype_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
file_name = path + (m_is_dark ? "plate_settings_dark.svg" : "plate_settings.svg");
if (!m_plate_settings_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name;
}
}
//if (m_bedtype_changed_texture.get_id() == 0)
{
file_name = path + (m_is_dark ? "plate_set_bedtype_changed_dark.svg" : "plate_set_bedtype_changed.svg");
if (!m_bedtype_changed_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
file_name = path + (m_is_dark ? "plate_settings_changed_dark.svg" : "plate_settings_changed.svg");
if (!m_plate_settings_changed_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name;
}
}
//if (m_bedtype_hovered_texture.get_id() == 0)
{
file_name = path + (m_is_dark ? "plate_set_bedtype_hover_dark.svg" : "plate_set_bedtype_hover.svg");
if (!m_bedtype_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
file_name = path + (m_is_dark ? "plate_settings_hover_dark.svg" : "plate_settings_hover.svg");
if (!m_plate_settings_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name;
}
}
//if (m_bedtype_changed_hovered_texture.get_id() == 0)
{
file_name = path + (m_is_dark ? "plate_set_bedtype_changed_hover_dark.svg" : "plate_set_bedtype_changed_hover.svg");
if (!m_bedtype_changed_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
file_name = path + (m_is_dark ? "plate_settings_changed_hover_dark.svg" : "plate_settings_changed_hover.svg");
if (!m_plate_settings_changed_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name;
}
}
@ -2575,10 +2722,10 @@ void PartPlateList::release_icon_textures()
m_locked_hovered_texture.reset();
m_lockopen_texture.reset();
m_lockopen_hovered_texture.reset();
m_bedtype_texture.reset();
m_bedtype_changed_texture.reset();
m_bedtype_hovered_texture.reset();
m_bedtype_changed_hovered_texture.reset();
m_plate_settings_texture.reset();
m_plate_settings_texture.reset();
m_plate_settings_texture.reset();
m_plate_settings_hovered_texture.reset();
for (int i = 0;i < MAX_PLATE_COUNT; i++) {
m_idx_textures[i].reset();
@ -2603,7 +2750,7 @@ void PartPlateList::release_icon_textures()
}
//this may be happened after machine changed
void PartPlateList::reset_size(int width, int depth, int height)
void PartPlateList::reset_size(int width, int depth, int height, bool reload_objects, bool update_shapes)
{
Vec3d origin1, origin2;
@ -2615,7 +2762,13 @@ void PartPlateList::reset_size(int width, int depth, int height)
m_plate_depth = depth;
m_plate_height = height;
update_all_plates_pos_and_size(false, false);
reload_all_objects();
if (update_shapes) {
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
}
if (reload_objects)
reload_all_objects();
else
clear(false, false, false, -1);
}
return;
@ -2967,6 +3120,25 @@ PartPlate* PartPlateList::get_selected_plate()
return m_plate_list[m_current_plate];
}
std::vector<PartPlate*> PartPlateList::get_nonempty_plate_list()
{
std::vector<PartPlate*> nonempty_plate_list;
for (auto plate : m_plate_list){
if (plate->get_extruders().size() != 0) {
nonempty_plate_list.push_back(plate);
}
}
return nonempty_plate_list;
}
std::vector<const GCodeProcessorResult*> PartPlateList::get_nonempty_plates_slice_results() {
std::vector<const GCodeProcessorResult*> nonempty_plates_slice_result;
for (auto plate : get_nonempty_plate_list()) {
nonempty_plates_slice_result.push_back(plate->get_slice_result());
}
return nonempty_plates_slice_result;
}
//select plate
int PartPlateList::select_plate(int index)
{
@ -2989,11 +3161,15 @@ int PartPlateList::select_plate(int index)
m_current_plate = index;
m_plate_list[m_current_plate]->set_selected();
//BBS
if(m_model)
m_model->curr_plate_index = index;
//BBS update bed origin
if (m_intialized && m_plater) {
Vec2d pos = compute_shape_position(index, m_plate_cols);
m_plater->set_bed_position(pos);
wxQueueEvent(m_plater, new SimpleEvent(EVT_GLCANVAS_PLATE_SELECT));
//wxQueueEvent(m_plater, new SimpleEvent(EVT_GLCANVAS_PLATE_SELECT));
}
return 0;
@ -3886,10 +4062,10 @@ void PartPlateList::render_for_picking_pass()
return 0;
}*/
void PartPlateList::set_render_option(bool bedtype_texture, bool bedtype_setting)
void PartPlateList::set_render_option(bool bedtype_texture, bool plate_settings)
{
render_bedtype_logo = bedtype_texture;
render_bedtype_setting = bedtype_setting;
render_bedtype_logo = bedtype_texture;
render_plate_settings = plate_settings;
}
int PartPlateList::select_plate_by_obj(int obj_index, int instance_index)
@ -4246,8 +4422,8 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
plate_data_item->objects_and_instances.emplace_back(it->first, it->second);
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<boost::format(": plate %1%, gcode_filename=%2%, with_slice_info=%3%, slice_valid %4%")
%i %m_plate_list[i]->m_gcode_result->filename % with_slice_info %m_plate_list[i]->is_slice_result_valid();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<boost::format(": plate %1%, gcode_filename=%2%, with_slice_info=%3%, slice_valid %4%, object item count %5%.")
%i %m_plate_list[i]->m_gcode_result->filename % with_slice_info %m_plate_list[i]->is_slice_result_valid()%plate_data_item->objects_and_instances.size();
if (with_slice_info) {
if (m_plate_list[i]->get_slice_result() && m_plate_list[i]->is_slice_result_valid()) {
@ -4421,7 +4597,7 @@ void PartPlateList::BedTextureInfo::TexturePart::update_buffer()
rectangle.push_back(Vec2d(x+w, y+h));
rectangle.push_back(Vec2d(x, y+h));
ExPolygon poly;
for (int i = 0; i < 4; i++) {
const Vec2d & p = rectangle[i];
for (auto& p : rectangle) {

View file

@ -133,15 +133,12 @@ private:
mutable unsigned int m_orient_vbo_id{ 0 };
GeometryBuffer m_lock_icon;
mutable unsigned int m_lock_vbo_id{ 0 };
GeometryBuffer m_bedtype_icon;
mutable unsigned int m_bedtype_vbo_id{ 0 };
GeometryBuffer m_plate_settings_icon;
mutable unsigned int m_plate_settings_vbo_id{ 0 };
GeometryBuffer m_plate_idx_icon;
mutable unsigned int m_plate_idx_vbo_id{ 0 };
GLTexture m_texture;
// plate render option
bool is_same_bedtype_with_global = true;
mutable float m_grabber_color[4];
float m_scale_factor{ 1.0f };
GLUquadricObject* m_quadric;
@ -213,11 +210,21 @@ public:
//clear alll the instances in plate
void clear(bool clear_sliced_result = true);
BedType get_bed_type(bool check_global = true) const;
BedType get_bed_type() const;
void set_bed_type(BedType bed_type);
void reset_bed_type();
DynamicPrintConfig* config() { return &m_config; }
// set print sequence per plate
//bool print_seq_same_global = true;
void set_print_seq(PrintSequence print_seq = PrintSequence::ByDefault);
PrintSequence get_print_seq() const;
// Get the real effective print sequence of current plate.
// If curr_plate's print_seq is ByDefault, use the global sequence
// @return PrintSequence::{ByLayer,ByObject}
PrintSequence get_real_print_seq() const;
//static const int plate_x_offset = 20; //mm
//static const double plate_x_gap = 0.2;
ThumbnailData thumbnail_data;
@ -258,7 +265,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_extruders(bool conside_custom_gcode = false) const;
std::vector<int> get_used_extruders();
/* instance related operations*/
@ -283,6 +290,9 @@ public:
//remove instance from plate
int remove_instance(int obj_id, int instance_id);
//translate instance on the plate
void translate_all_instance(Vec3d position);
//update instance exclude state
void update_instance_exclude_status(int obj_id, int instance_id, BoundingBoxf3* bounding_box = nullptr);
@ -292,6 +302,8 @@ public:
//whether it is empty
bool empty() { return obj_to_instance_set.empty(); }
int printable_instance_size();
//whether it is has printable instances
bool has_printable_instances();
@ -482,14 +494,14 @@ class PartPlateList : public ObjectBase
GLTexture m_locked_hovered_texture;
GLTexture m_lockopen_texture;
GLTexture m_lockopen_hovered_texture;
GLTexture m_bedtype_texture;
GLTexture m_bedtype_changed_texture;
GLTexture m_bedtype_hovered_texture;
GLTexture m_bedtype_changed_hovered_texture;
GLTexture m_plate_settings_texture;
GLTexture m_plate_settings_changed_texture;
GLTexture m_plate_settings_hovered_texture;
GLTexture m_plate_settings_changed_hovered_texture;
GLTexture m_idx_textures[MAX_PLATE_COUNT];
// set render option
bool render_bedtype_logo = true;
bool render_bedtype_setting = true;
bool render_plate_settings = true;
bool m_is_dark = false;
@ -559,11 +571,13 @@ public:
~PartPlateList();
//this may be happened after machine changed
void reset_size(int width, int depth, int height);
void reset_size(int width, int depth, int height, bool reload_objects = true, bool update_shapes = false);
//clear all the instances in the plate, but keep the plates
void clear(bool delete_plates = false, bool release_print_list = false, bool except_locked = false, int plate_index = -1);
//clear all the instances in the plate, and delete the plates, only keep the first default plate
void reset(bool do_init);
//compute the origin for printable plate with index i using new width
Vec3d compute_origin_using_new_size(int i, int new_width, int new_depth);
//reset partplate to init states
void reinit();
@ -571,6 +585,11 @@ public:
//get the plate stride
double plate_stride_x();
double plate_stride_y();
void get_plate_size(int& width, int& depth, int& height) {
width = m_plate_width;
depth = m_plate_depth;
height = m_plate_height;
}
/*basic plate operations*/
//create an empty plate and return its index
@ -607,6 +626,10 @@ public:
PartPlate* get_selected_plate();
std::vector<PartPlate*> get_nonempty_plate_list();
std::vector<const GCodeProcessorResult*> get_nonempty_plates_slice_results();
Vec3d get_current_plate_origin() { return compute_origin(m_current_plate, m_plate_cols); }
Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); }
Pointfs get_exclude_area() { return m_exclude_areas; }
@ -683,7 +706,7 @@ public:
void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
void render(bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1);
void render_for_picking_pass();
void set_render_option(bool bedtype_texture, bool bedtype_settings);
void set_render_option(bool bedtype_texture, bool plate_settings);
BoundingBoxf3& get_bounding_box() { return m_bounding_box; }
//int select_plate_by_hover_id(int hover_id);
int select_plate_by_obj(int obj_index, int instance_index);

View file

@ -0,0 +1,158 @@
#include "PlateSettingsDialog.hpp"
namespace Slic3r { namespace GUI {
wxDEFINE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent);
PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
:DPIDialog(parent, id, title, pos, size, style)
{
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(FromDIP(400), -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(5));
wxFlexGridSizer* top_sizer = new wxFlexGridSizer(0, 2, FromDIP(5), 0);
top_sizer->AddGrowableCol(0,1);
top_sizer->SetFlexibleDirection(wxBOTH);
top_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
m_bed_type_choice = new ComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240),-1), 0, NULL, wxCB_READONLY );
for (BedType i = btDefault; i < btCount; i = BedType(int(i) + 1)) {
m_bed_type_choice->Append(to_bed_type_name(i));
}
wxStaticText* m_bed_type_txt = new wxStaticText(this, wxID_ANY, _L("Bed type"));
m_bed_type_txt->SetFont(Label::Body_14);
top_sizer->Add(m_bed_type_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
top_sizer->Add(m_bed_type_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5));
wxBoxSizer* m_sizer_selectbox = new wxBoxSizer(wxHORIZONTAL);
m_print_seq_choice = new ComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240),-1), 0, NULL, wxCB_READONLY );
m_print_seq_choice->Append(_L("Same as Global Print Sequence"));
for (auto i = PrintSequence::ByLayer; i < PrintSequence::ByDefault; i = PrintSequence(int(i) + 1)) {
m_print_seq_choice->Append(to_print_sequence_name(i));
}
wxStaticText* m_print_seq_txt = new wxStaticText(this, wxID_ANY, _L("Print sequence"));
m_print_seq_txt->SetFont(Label::Body_14);
top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT |wxALL, FromDIP(5));
top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5));
m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxALL, FromDIP(30));
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>(wxColour(0, 174, 66), 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));
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("#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)));
m_button_ok->SetCornerRadius(FromDIP(12));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
wxCommandEvent evt(EVT_SET_BED_TYPE_CONFIRM, GetId());
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(evt);
if (this->IsModal())
EndModal(wxID_YES);
else
this->Close();
});
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) {
if (this->IsModal())
EndModal(wxID_NO);
else
this->Close();
});
sizer_button->AddStretchSpacer();
sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5));
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
sizer_button->Add(FromDIP(30),0, 0, 0);
m_sizer_main->Add(sizer_button, 0, wxEXPAND, FromDIP(20));
SetSizer(m_sizer_main);
Layout();
m_sizer_main->Fit(this);
CenterOnParent();
wxGetApp().UpdateDlgDarkUI(this);
}
PlateSettingsDialog::~PlateSettingsDialog()
{
}
void PlateSettingsDialog::sync_bed_type(BedType type)
{
if (m_bed_type_choice != nullptr) {
m_bed_type_choice->SetSelection(int(type));
}
}
void PlateSettingsDialog::sync_print_seq(int print_seq)
{
if (m_print_seq_choice != nullptr) {
m_print_seq_choice->SetSelection(print_seq);
}
}
wxString PlateSettingsDialog::to_bed_type_name(BedType bed_type) {
switch (bed_type) {
case btDefault:
return _L("Same as Global Bed Type");
case btPC:
return _L("Cool Plate");
case btEP:
return _L("Engineering Plate");
case btPEI:
return _L("High Temp Plate");
case btPTE:
return _L("Textured PEI Plate");
default:
return _L("Same as Global Bed Type");
}
return _L("Same as Global Bed Type");
}
wxString PlateSettingsDialog::to_print_sequence_name(PrintSequence print_seq) {
switch (print_seq) {
case PrintSequence::ByLayer:
return _L("By Layer");
case PrintSequence::ByObject:
return _L("By Object");
default:
return _L("By Layer");
}
return _L("By Layer");
}
void PlateSettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
{
m_button_ok->Rescale();
m_button_cancel->Rescale();
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,61 @@
#ifndef slic3r_GUI_PlateSettingsDialog_hpp_
#define slic3r_GUI_PlateSettingsDialog_hpp_
#include "Plater.hpp"
#include "PartPlate.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/RadioBox.hpp"
#include "Widgets/ComboBox.hpp"
namespace Slic3r { namespace GUI {
wxDECLARE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent);
class PlateSettingsDialog : public DPIDialog
{
public:
enum ButtonStyle {
ONLY_CONFIRM = 0,
CONFIRM_AND_CANCEL = 1,
MAX_STYLE_NUM = 2
};
PlateSettingsDialog(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& title = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxCLOSE_BOX | wxCAPTION
);
~PlateSettingsDialog();
void sync_bed_type(BedType type);
void sync_print_seq(int print_seq = 0);
wxString to_bed_type_name(BedType bed_type);
wxString to_print_sequence_name(PrintSequence print_seq);
void on_dpi_changed(const wxRect& suggested_rect) override;
int get_print_seq_choice() {
int choice = 0;
if (m_print_seq_choice != nullptr)
choice = m_print_seq_choice->GetSelection();
return choice;
};
int get_bed_type_choice() {
int choice = 0;
if (m_bed_type_choice != nullptr)
choice = m_bed_type_choice->GetSelection();
return choice;
};
protected:
ComboBox* m_print_seq_choice { nullptr };
ComboBox* m_bed_type_choice { nullptr };
Button* m_button_ok;
Button* m_button_cancel;
};
}} // namespace Slic3r::GUI
#endif

View file

@ -128,7 +128,7 @@
#include "PhysicalPrinterDialog.hpp"
#include "PrintHostDialogs.hpp"
#include "SetBedTypeDialog.hpp"
#include "PlateSettingsDialog.hpp"
using boost::optional;
namespace fs = boost::filesystem;
@ -137,7 +137,7 @@ using Slic3r::Preset;
using Slic3r::GUI::format_wxstr;
using namespace nlohmann;
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 512, 512 };
namespace Slic3r {
namespace GUI {
@ -334,6 +334,7 @@ struct Sidebar::priv
bool is_collapsed {false};
Search::OptionsSearcher searcher;
std::string ams_list_device;
priv(Plater *plater) : plater(plater) {}
~priv();
@ -1360,7 +1361,7 @@ void Sidebar::on_filaments_change(size_t num_filaments)
sizer->Hide(p->m_flushing_volume_btn);
}
p->m_panel_filament_title->Layout();
Layout();
p->m_panel_filament_title->Refresh();
update_ui_from_settings();
dynamic_filament_list.update();
@ -1374,13 +1375,12 @@ void Sidebar::on_bed_type_change(BedType bed_type)
m_bed_type_list->SetSelection(sel_idx);
}
void Sidebar::load_ams_list(std::map<std::string, Ams *> const &list)
void Sidebar::load_ams_list(std::string const &device, std::map<std::string, Ams *> const &list)
{
std::vector<DynamicPrintConfig> filament_ams_list;
for (auto ams : list) {
char n = ams.first.front() - '0' + 'A';
for (auto tray : ams.second->trayList) {
if (tray.second->setting_id.empty()) continue;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__
<< boost::format(": ams %1% tray %2% id %3% color %4%") % ams.first % tray.first % tray.second->setting_id % tray.second->color;
char t = tray.first.front() - '0' + '1';
@ -1392,6 +1392,8 @@ void Sidebar::load_ams_list(std::map<std::string, Ams *> const &list)
filament_ams_list.emplace_back(std::move(ams));
}
}
p->ams_list_device = device;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1% items") % filament_ams_list.size();
wxGetApp().preset_bundle->filament_ams_list = filament_ams_list;
for (auto c : p->combos_filament)
c->update();
@ -1407,10 +1409,34 @@ void Sidebar::sync_ams_list()
dlg.ShowModal();
return;
}
MessageDialog dlg(this,
_L("Sync filaments with AMS will drop all current selected filament presets and colors. Do you want to continue?"),
_L("Sync filaments with AMS"), wxYES_NO);
if (dlg.ShowModal() != wxID_YES) return;
std::string ams_filament_ids = wxGetApp().app_config->get("ams_filament_ids", p->ams_list_device);
std::vector<std::string> list2;
if (!ams_filament_ids.empty())
boost::algorithm::split(list2, ams_filament_ids, boost::algorithm::is_any_of(","));
struct SyncAmsDialog : MessageDialog {
SyncAmsDialog(wxWindow * parent, bool first): MessageDialog(parent,
first
? _L("Sync filaments with AMS will drop all current selected filament presets and colors. Do you want to continue?")
: _L("Already did a synchronization, do you want to sync only changes or resync all?"),
_L("Sync filaments with AMS"), 0)
{
if (first) {
add_button(wxID_YES, true, _L("Yes"));
} else {
add_button(wxID_OK, true, _L("Sync"));
add_button(wxID_YES, false, _L("Resync"));
}
add_button(wxID_CANCEL, false, _L("Cancel"));
}
} dlg(this, ams_filament_ids.empty());
auto res = dlg.ShowModal();
if (res == wxID_CANCEL) return;
list2.resize(list.size());
for (int i = 0; i < list.size(); ++i) {
auto filament_id = list[i].opt_string("filament_id", 0u);
list[i].set_key_value("filament_changed", new ConfigOptionBool{res == wxID_YES || list2[i] != filament_id});
list2[i] = filament_id;
}
unsigned int unknowns = 0;
auto n = wxGetApp().preset_bundle->sync_ams_list(unknowns);
if (n == 0) {
@ -1420,6 +1446,8 @@ void Sidebar::sync_ams_list()
dlg.ShowModal();
return;
}
ams_filament_ids = boost::algorithm::join(list2, ",");
wxGetApp().app_config ->set("ams_filament_ids", p->ams_list_device, ams_filament_ids);
if (unknowns > 0) {
MessageDialog dlg(this,
_L("There are some unknown filaments mapped to generic preset. Please update Bambu Studio or restart Bambu Studio to check if there is an update to system presets."),
@ -1429,7 +1457,7 @@ void Sidebar::sync_ams_list()
wxGetApp().plater()->on_filaments_change(n);
for (auto &c : p->combos_filament)
c->update();
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]);
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
dynamic_filament_list.update();
}
@ -1680,6 +1708,10 @@ struct Plater::priv
bool m_is_slicing {false};
bool m_is_publishing {false};
int m_cur_slice_plate;
//BBS: m_slice_all in .gcode.3mf file case, set true when slice all
bool m_slice_all_only_has_gcode{ false };
bool m_need_update{false};
//BBS: add popup object table logic
//ObjectTableDialog* m_popup_table{ nullptr };
@ -1791,6 +1823,11 @@ struct Plater::priv
priv(Plater *q, MainFrame *main_frame);
~priv();
bool need_update() const { return m_need_update; }
void set_need_update(bool need_update) { m_need_update = need_update; }
void set_plater_dirty(bool is_dirty) { dirty_state.set_plater_dirty(is_dirty); }
bool is_project_dirty() const { return dirty_state.is_dirty(); }
bool is_presets_dirty() const { return dirty_state.is_presets_dirty(); }
void update_project_dirty_from_presets()
@ -2064,6 +2101,7 @@ struct Plater::priv
bool can_delete() const;
bool can_delete_all() const;
bool can_edit_text() const;
bool can_add_plate() const;
bool can_delete_plate() const;
bool can_increase_instances() const;
@ -2407,20 +2445,23 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
preview->get_wxglcanvas()->Bind(EVT_CUSTOMEVT_TICKSCHANGED, [this](wxCommandEvent& event) {
Type tick_event_type = (Type)event.GetInt();
Model &model = wxGetApp().plater()->model();
model.custom_gcode_per_print_z = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->GetTicksValues();
preview->on_tick_changed(tick_event_type);
Model& model = wxGetApp().plater()->model();
//BBS: replace model custom gcode with current plate custom gcode
model.plates_custom_gcodes[model.curr_plate_index] = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->GetTicksValues();
// BBS set to invalid state only
if (tick_event_type == Type::ToolChange || tick_event_type == Type::Custom || tick_event_type == Type::Template) {
if (tick_event_type == Type::ToolChange || tick_event_type == Type::Custom || tick_event_type == Type::Template || tick_event_type == Type::PausePrint) {
PartPlate *plate = this->q->get_partplate_list().get_curr_plate();
if (plate) {
plate->update_slice_result_valid_state(false);
}
}
preview->on_tick_changed(tick_event_type);
// update slice and print button
wxGetApp().mainframe->update_slice_print_status(MainFrame::SlicePrintEventType::eEventSliceUpdate, true, false);
set_need_update(true);
});
}
if (wxGetApp().is_gcode_viewer())
@ -2893,6 +2934,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
std::vector<size_t> empty_result;
bool dlg_cont = true;
bool is_user_cancel = false;
bool translate_old = false;
int current_width, current_depth, current_height;
if (input_files.empty()) { return std::vector<size_t>(); }
@ -3155,7 +3198,17 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
return empty_result;
}
Semver old_version(1, 5, 9);
if ((en_3mf_file_type == En3mfType::From_BBS) && (file_version < old_version) && load_model && load_config && !config_loaded.empty()) {
translate_old = true;
partplate_list.get_plate_size(current_width, current_depth, current_height);
}
if (load_config) {
if (translate_old) {
//set the size back
partplate_list.reset_size(current_width + Bed3D::Axes::DefaultTipRadius, current_depth + Bed3D::Axes::DefaultTipRadius, current_height, false);
}
partplate_list.load_from_3mf_structure(plate_data);
partplate_list.update_slice_context_to_current_plate(background_process);
this->preview->update_gcode_result(partplate_list.get_current_slice_result());
@ -3194,11 +3247,26 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
config.apply(static_cast<const ConfigBase &>(FullPrintConfig::defaults()));
// and place the loaded config over the base.
config += std::move(config_loaded);
std::map<std::string, std::string> validity = config.validate();
if (!validity.empty()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("Param values in 3mf error: ");
for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("%1%: %2%")%it->first %it->second;
//
NotificationManager *notify_manager = q->get_notification_manager();
std::string error_message = L("Invalid values found in the 3mf:");
error_message += "\n";
for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
error_message += "-" + it->first + ": " + it->second + "\n";
error_message += "\n";
error_message += L("Please correct them in the param tabs");
notify_manager->bbl_show_3mf_warn_notification(error_message);
}
}
if (!config_substitutions.empty()) show_substitutions_info(config_substitutions.substitutions, filename.string());
this->model.custom_gcode_per_print_z = model.custom_gcode_per_print_z;
// BBS
this->model.plates_custom_gcodes = model.plates_custom_gcodes;
this->model.design_info = model.design_info;
this->model.model_info = model.model_info;
}
@ -3532,6 +3600,21 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (new_model) delete new_model;
//BBS: translate old 3mf to correct positions
if (translate_old) {
//translate the objects
int plate_count = partplate_list.get_plate_count();
for (int index = 1; index < plate_count; index ++) {
PartPlate* cur_plate = (PartPlate *)partplate_list.get_plate(index);
Vec3d cur_origin = cur_plate->get_origin();
Vec3d new_origin = partplate_list.compute_origin_using_new_size(index, current_width, current_depth);
cur_plate->translate_all_instance(new_origin - cur_origin);
}
partplate_list.reset_size(current_width, current_depth, current_height, true, true);
}
//BBS: add gcode loading logic in the end
q->m_exported_file = false;
q->skip_thumbnail_invalid = false;
@ -4020,7 +4103,8 @@ void Plater::priv::delete_all_objects_from_model()
sidebar->obj_list()->delete_all_objects_from_list();
object_list_changed();
model.custom_gcode_per_print_z.gcodes.clear();
//BBS
model.plates_custom_gcodes.clear();
}
void Plater::priv::reset(bool apply_presets_change)
@ -4070,7 +4154,8 @@ void Plater::priv::reset(bool apply_presets_change)
else
wxGetApp().load_current_presets(false, false);
model.custom_gcode_per_print_z.gcodes.clear();
//BBS
model.plates_custom_gcodes.clear();
// BBS
m_saved_timestamp = m_backup_timestamp = size_t(-1);
@ -5009,15 +5094,12 @@ void Plater::priv::reload_from_disk()
new_volume->config.apply(old_volume->config);
new_volume->set_type(old_volume->type());
new_volume->set_material_id(old_volume->material_id());
#if 0// ENABLE_WORLD_COORDINATE
new_volume->set_transformation(Geometry::translation_transform(old_volume->source.transform.get_offset()) *
old_volume->get_transformation().get_matrix_no_offset() * old_volume->source.transform.get_matrix_no_offset());
new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
#else
new_volume->set_transformation(Geometry::assemble_transform(old_volume->source.transform.get_offset()) * old_volume->get_transformation().get_matrix(true) *
old_volume->source.transform.get_matrix(true));
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
#endif // ENABLE_WORLD_COORDINATE
Transform3d transform = Transform3d::Identity();
transform.translate(new_volume->source.mesh_offset - old_volume->source.mesh_offset);
new_volume->set_transformation(old_volume->get_transformation().get_matrix() * old_volume->source.transform.get_matrix(true) *
transform * new_volume->source.transform.get_matrix(true).inverse());
new_volume->source.object_idx = old_volume->source.object_idx;
new_volume->source.volume_idx = old_volume->source.volume_idx;
assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
@ -5262,6 +5344,9 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
return;
}
//BBS: wish to reset all plates stats item selected state when back to View3D Tab
preview->get_canvas3d()->reset_select_plate_toolbar_selection();
wxPanel* old_panel = current_panel;
//#if BBL_HAS_FIRST_PAGE
if (!old_panel) {
@ -5470,7 +5555,7 @@ void Plater::priv::on_select_bed_type(wxCommandEvent &evt)
//update slice status
auto plate_list = partplate_list.get_plate_list();
for (auto plate : plate_list) {
if (plate->get_bed_type(false) == btDefault) {
if (plate->get_bed_type() == btDefault) {
plate->update_slice_result_valid_state(false);
}
}
@ -5553,12 +5638,9 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
Slic3r::put_other_changes();
// update slice state and set bedtype default for 3rd-party printer
bool is_bbl_vendor_preset = wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle);
auto plate_list = partplate_list.get_plate_list();
for (auto plate : plate_list) {
plate->update_slice_result_valid_state(false);
if (!is_bbl_vendor_preset)
plate->set_bed_type(btDefault);
}
}
@ -5765,6 +5847,20 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
//BBS: add project slice logic
bool is_finished = !m_slice_all || (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
//BBS: slice .gcode.3mf file related logic, assign is_finished again
bool only_has_gcode_need_preview = false;
auto plate_list = this->partplate_list.get_plate_list();
bool has_print_instances = false;
for (auto plate : plate_list)
has_print_instances = has_print_instances || plate->has_printable_instances();
if (this->model.objects.empty() && !has_print_instances)
only_has_gcode_need_preview = true;
if (only_has_gcode_need_preview && m_slice_all_only_has_gcode) {
is_finished = (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
if (is_finished)
m_slice_all_only_has_gcode = false;
}
// Stop the background task, wait until the thread goes into the "Idle" state.
// At this point of time the thread should be either finished or canceled,
// so the following call just confirms, that the produced data were consumed.
@ -5964,6 +6060,8 @@ void Plater::priv::on_action_add_plate(SimpleEvent&)
if (q != nullptr) {
take_snapshot("add partplate");
this->partplate_list.create_plate();
int new_plate = this->partplate_list.get_plate_count() - 1;
this->partplate_list.select_plate(new_plate);
update();
// BBS set default view
@ -6013,12 +6111,15 @@ void Plater::priv::on_action_slice_all(SimpleEvent&)
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
m_slice_all = true;
m_slice_all_only_has_gcode = true;
m_cur_slice_plate = 0;
//select plate
q->select_plate(m_cur_slice_plate);
q->reslice();
if (!m_is_publishing)
q->select_view_3D("Preview");
//BBS: wish to select all plates stats item
preview->get_canvas3d()->_update_select_plate_toolbar_stats_item(true);
}
}
@ -6398,7 +6499,9 @@ PlateBBoxData Plater::priv::generate_first_layer_bbox()
std::vector<BBoxData>& id_bboxes = bboxdata.bbox_objs;
BoundingBoxf bbox_all;
auto print = this->background_process.m_fff_print;
bboxdata.is_seq_print = (print->config().print_sequence == PrintSequence::ByObject);
auto curr_plate = this->partplate_list.get_curr_plate();
auto curr_plate_seq = curr_plate->get_real_print_seq();
bboxdata.is_seq_print = (curr_plate_seq == PrintSequence::ByObject);
bboxdata.first_extruder = print->get_tool_ordering().first_extruder();
bboxdata.bed_type = bed_type_to_gcode_string(print->config().curr_bed_type.value);
// get nozzle diameter
@ -6890,7 +6993,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar
double z = config->opt_float("printable_height");
//Pointfs& exclude_areas = config->option<ConfigOptionPoints>("bed_exclude_area")->values;
partplate_list.reset_size(max.x() - min.x(), max.y() - min.y(), z);
partplate_list.reset_size(max.x() - min.x() - Bed3D::Axes::DefaultTipRadius, max.y() - min.y() - Bed3D::Axes::DefaultTipRadius, z);
partplate_list.set_shapes(shape, exclude_areas, custom_texture, height_to_lid, height_to_rod);
Vec2d new_shape_position = partplate_list.get_current_shape_position();
@ -6909,6 +7012,24 @@ bool Plater::priv::can_delete_all() const
return !model.objects.empty();
}
bool Plater::priv::can_edit_text() const
{
const Selection &selection = view3D->get_canvas3d()->get_selection();
if (selection.is_single_full_instance())
return true;
if (selection.is_single_volume()) {
const GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin());
int out_object_idx = gl_volume->object_idx();
ModelObject * model_object = selection.get_model()->objects[out_object_idx];
int out_volume_idx = gl_volume->volume_idx();
ModelVolume * model_volume = model_object->volumes[out_volume_idx];
if (model_volume)
return !model_volume->get_text_info().m_text.empty();
}
return false;
}
bool Plater::priv::can_add_plate() const
{
return q->get_partplate_list().get_plate_count() < PartPlateList::MAX_PLATES_COUNT;
@ -7413,6 +7534,7 @@ bool Plater::Show(bool show)
bool Plater::is_project_dirty() const { return p->is_project_dirty(); }
bool Plater::is_presets_dirty() const { return p->is_presets_dirty(); }
void Plater::set_plater_dirty(bool is_dirty) { p->set_plater_dirty(is_dirty); }
void Plater::update_project_dirty_from_presets() { p->update_project_dirty_from_presets(); }
int Plater::save_project_if_dirty(const wxString& reason) { return p->save_project_if_dirty(reason); }
void Plater::reset_project_dirty_after_save() { p->reset_project_dirty_after_save(); }
@ -7452,8 +7574,10 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
m_only_gcode = false;
m_exported_file = false;
m_loading_project = false;
get_notification_manager()->bbl_close_plateinfo_notification();
get_notification_manager()->bbl_close_preview_only_notification();
get_notification_manager()->bbl_close_3mf_warn_notification();
if (!silent)
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
@ -7478,7 +7602,12 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
Model m;
model().load_from(m); // new id avoid same path name
//select first plate
get_partplate_list().select_plate(0);
SimpleEvent event(EVT_GLCANVAS_PLATE_SELECT);
p->on_plate_selected(event);
p->load_auxiliary_files();
wxGetApp().app_config->update_last_backup_dir(model().get_backup_path());
@ -7521,10 +7650,21 @@ void Plater::load_project(wxString const& filename2,
//BBS: add only gcode mode
bool previous_gcode = m_only_gcode;
// BBS
if (m_loading_project) {
//some error cases happens
//return directly
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": current loading other project, return directly");
return;
}
else
m_loading_project = true;
m_only_gcode = false;
m_exported_file = false;
get_notification_manager()->bbl_close_plateinfo_notification();
get_notification_manager()->bbl_close_preview_only_notification();
get_notification_manager()->bbl_close_3mf_warn_notification();
auto path = into_path(filename);
@ -7585,6 +7725,8 @@ void Plater::load_project(wxString const& filename2,
up_to_date(true, true);
wxGetApp().params_panel()->switch_to_object_if_has_object_configs();
m_loading_project = false;
}
// BBS: save logic
@ -7624,15 +7766,15 @@ int Plater::save_project(bool saveAs)
//BBS import model by model id
void Plater::import_model_id(const std::string& download_info)
{
std::string download_url = "";
std::string filename = "";
std::string download_url = wxGetApp().get_download_model_url();
std::string filename = wxGetApp().get_download_model_name();
auto selection_data_arr = wxSplit(download_info, '|');
/* auto selection_data_arr = wxSplit(download_info, '|');
if (selection_data_arr.size() == 2) {
download_url = selection_data_arr[0].ToStdString();
filename = selection_data_arr[1].ToStdString();
}
if (selection_data_arr.size() == 2) {
download_url = selection_data_arr[0].ToStdString();
filename = selection_data_arr[1].ToStdString();
}*/
bool download_ok = false;
@ -7809,10 +7951,9 @@ void Plater::download_project(const wxString& project_id)
return;
}
void Plater::request_model_download(std::string url, std::string filename)
void Plater::request_model_download()
{
wxCommandEvent* event = new wxCommandEvent(EVT_IMPORT_MODEL_ID);
event->SetString(wxString::Format("%s|%s", wxString(url), wxString(filename)));
wxQueueEvent(this, event);
}
@ -8365,7 +8506,13 @@ void Plater::force_update_all_plate_thumbnails()
}
// BBS: backup
std::vector<size_t> Plater::load_files(const std::vector<fs::path>& input_files, LoadStrategy strategy, bool ask_multi) { return p->load_files(input_files, strategy, ask_multi); }
std::vector<size_t> Plater::load_files(const std::vector<fs::path>& input_files, LoadStrategy strategy, bool ask_multi) {
//BBS: wish to reset state when load a new file
p->m_slice_all_only_has_gcode = false;
//BBS: wish to reset all plates stats item selected state when load a new file
p->preview->get_canvas3d()->reset_select_plate_toolbar_selection();
return p->load_files(input_files, strategy, ask_multi);
}
// To be called when providing a list of files to the GUI slic3r on command line.
std::vector<size_t> Plater::load_files(const std::vector<std::string>& input_files, LoadStrategy strategy, bool ask_multi)
@ -8997,7 +9144,17 @@ void Plater::add_file()
}
}
void Plater::update() { p->update(); }
void Plater::update(bool conside_update_flag)
{
if (conside_update_flag) {
if (need_update()) {
p->update();
p->set_need_update(false);
}
}
else
p->update();
}
void Plater::object_list_changed() { p->object_list_changed(); }
@ -9091,6 +9248,18 @@ void Plater::delete_all_objects_from_model()
p->delete_all_objects_from_model();
}
void Plater::set_selected_visible(bool visible)
{
if (p->get_curr_selection().is_empty())
return;
Plater::TakeSnapshot snapshot(this, "Set Selected Objects Visible in AssembleView");
p->m_ui_jobs.cancel_all();
p->get_current_canvas3D()->set_selected_visible(visible);
}
void Plater::remove_selected()
{
/*if (p->get_selection().is_empty())
@ -10358,6 +10527,24 @@ bool Plater::update_filament_colors_in_full_config()
return true;
}
void Plater::config_change_notification(const DynamicPrintConfig &config, const std::string& key)
{
GLCanvas3D* view3d_canvas = get_view3D_canvas3D();
if (key == std::string("print_sequence")) {
auto seq_print = config.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
if (seq_print && view3d_canvas && view3d_canvas->is_initialized() && view3d_canvas->is_rendering_enabled()) {
NotificationManager* notify_manager = get_notification_manager();
if (seq_print->value == PrintSequence::ByObject) {
std::string info_text = _u8L("Print By Object: \nSuggest to use auto-arrange to avoid collisions when printing.");
notify_manager->bbl_show_seqprintinfo_notification(info_text);
}
else
notify_manager->bbl_close_seqprintinfo_notification();
}
}
// notification for more options
}
void Plater::on_config_change(const DynamicPrintConfig &config)
{
bool update_scheduled = false;
@ -10435,20 +10622,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
if (bed_shape_changed)
set_bed_shape();
GLCanvas3D* view3d_canvas = get_view3D_canvas3D();
auto seq_print = config.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
if ( seq_print && view3d_canvas && view3d_canvas->is_initialized() && view3d_canvas->is_rendering_enabled() ) {
NotificationManager *notify_manager = get_notification_manager();
if (seq_print->value == PrintSequence::ByObject) {
std::string info_text = _u8L("Print By Object: \nSuggest to use auto-arrange to avoid collisions when printing.");
notify_manager->bbl_show_seqprintinfo_notification(info_text);
//always show label when switch to sequence print
//if (print_sequence_changed)
// this->show_view3D_labels(true);
}
else
notify_manager->bbl_close_seqprintinfo_notification();
}
config_change_notification(config, std::string("print_sequence"));
if (update_scheduled)
update();
@ -10553,7 +10727,6 @@ std::vector<std::string> Plater::get_extruder_colors_from_plater_config(const GC
std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessorResult* const result) const
{
std::vector<std::string> colors = get_extruder_colors_from_plater_config(result);
colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size());
if (wxGetApp().is_gcode_viewer() && result != nullptr) {
for (const CustomGCode::Item& code : result->custom_gcode_per_print_z) {
@ -10562,7 +10735,9 @@ std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessor
}
}
else {
for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z.gcodes) {
//BBS
colors.reserve(colors.size() + p->model.get_curr_plate_custom_gcodes().gcodes.size());
for (const CustomGCode::Item& code : p->model.get_curr_plate_custom_gcodes().gcodes) {
if (code.type == CustomGCode::ColorChange)
colors.emplace_back(code.color);
}
@ -11197,6 +11372,10 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click)
{
//select plate
ret = p->partplate_list.select_plate(plate_index);
if (!ret) {
SimpleEvent event(EVT_GLCANVAS_PLATE_SELECT);
p->on_plate_selected(event);
}
if ((!ret)&&(p->background_process.can_switch_print()))
{
//select successfully
@ -11317,15 +11496,38 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click)
//set the plate type
ret = select_plate(plate_index);
if (!ret) {
SetBedTypeDialog dlg(this, wxID_ANY, _L("Select Bed Type"));
PlateSettingsDialog dlg(this, wxID_ANY, _L("Plate Settings"));
PartPlate* curr_plate = p->partplate_list.get_curr_plate();
dlg.sync_bed_type(curr_plate->get_bed_type(false));
dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index](wxCommandEvent& e) {
dlg.sync_bed_type(curr_plate->get_bed_type());
auto curr_print_seq = curr_plate->get_print_seq();
if (curr_print_seq != PrintSequence::ByDefault) {
dlg.sync_print_seq(int(curr_print_seq) + 1);
}
else
dlg.sync_print_seq(0);
dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index, &dlg](wxCommandEvent& e) {
PartPlate *curr_plate = p->partplate_list.get_curr_plate();
BedType old_bed_type = curr_plate->get_bed_type(false);
auto type = (BedType)(e.GetInt());
p->partplate_list.get_curr_plate()->set_bed_type(type);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select bed type %1% for plate %2% at plate side")%type %plate_index;
BedType old_bed_type = curr_plate->get_bed_type();
auto bt_sel = BedType(dlg.get_bed_type_choice());
if (old_bed_type != bt_sel) {
curr_plate->set_bed_type(bt_sel);
update_project_dirty_from_presets();
set_plater_dirty(true);
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select bed type %1% for plate %2% at plate side")%bt_sel %plate_index;
int ps_sel = dlg.get_print_seq_choice();
if (ps_sel != 0)
curr_plate->set_print_seq(PrintSequence(ps_sel - 1));
else
curr_plate->set_print_seq(PrintSequence::ByDefault);
update_project_dirty_from_presets();
set_plater_dirty(true);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select print sequence %1% for plate %2% at plate side")%ps_sel %plate_index;
auto plate_config = *(curr_plate->config());
wxGetApp().plater()->config_change_notification(plate_config, std::string("print_sequence"));
});
dlg.ShowModal();
@ -11468,13 +11670,15 @@ void Plater::show_object_info()
wxString info_manifold;
int non_manifold_edges = 0;
auto mesh_errors = p->sidebar->obj_list()->get_mesh_errors_info(&info_manifold, &non_manifold_edges);
info_text += into_u8(info_manifold);
#ifndef __WINDOWS__
if (non_manifold_edges > 0) {
info_text += into_u8("\n" + _L("Tips:") + "\n" +_L("\"Fix Model\" feature is currently only on Windows. Please repair the model on Bambu Studio(windows) or CAD softwares."));
info_manifold += into_u8("\n" + _L("Tips:") + "\n" +_L("\"Fix Model\" feature is currently only on Windows. Please repair the model on Bambu Studio(windows) or CAD softwares."));
}
#endif //APPLE & LINUX
info_manifold = "<Error>" + info_manifold + "</Error>";
info_text += into_u8(info_manifold);
notify_manager->bbl_show_objectsinfo_notification(info_text, is_windows10()&&(non_manifold_edges > 0), !(p->current_panel == p->view3D));
}
@ -11496,7 +11700,8 @@ void Plater::post_process_string_object_exception(StringObjectException &err)
break;
}
}
err.string = format(_L("Plate %d: %s does not support filament %s (%s)."), err.params[0], err.params[1], err.params[2], filament_name);
err.string = format(_L("Plate% d: %s is not suggested to be used to print filament %s(%s). If you still want to do this printing, please set this filament's bed temperature to non zero."),
err.params[0], err.params[1], err.params[2], filament_name);
err.string += "\n";
}
} catch (...) {
@ -11590,6 +11795,14 @@ void Plater::show_status_message(std::string s)
BOOST_LOG_TRIVIAL(trace) << "show_status_message:" << s;
}
void Plater::edit_text()
{
auto &manager = get_view3D_canvas3D()->get_gizmos_manager();
manager.open_gizmo(GLGizmosManager::Text);
update();
}
bool Plater::can_edit_text() const { return p->can_edit_text(); }
bool Plater::can_delete() const { return p->can_delete(); }
bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_add_model() const { return !is_background_process_slicing(); }
@ -11729,6 +11942,16 @@ void Plater::bring_instance_forward()
p->bring_instance_forward();
}
bool Plater::need_update() const
{
return p->need_update();
}
void Plater::set_need_update(bool need_update)
{
p->set_need_update(need_update);
}
// BBS
//BBS: add popup logic for table object
bool Plater::PopupObjectTable(int object_id, int volume_id, const wxPoint& position)

View file

@ -125,7 +125,7 @@ public:
void on_filaments_change(size_t num_filaments);
// BBS
void on_bed_type_change(BedType bed_type);
void load_ams_list(std::map<std::string, Ams *> const &list);
void load_ams_list(std::string const & device, std::map<std::string, Ams *> const &list);
void sync_ams_list();
ObjectList* obj_list();
@ -189,6 +189,7 @@ public:
bool is_project_dirty() const;
bool is_presets_dirty() const;
void set_plater_dirty(bool is_dirty);
void update_project_dirty_from_presets();
int save_project_if_dirty(const wxString& reason);
void reset_project_dirty_after_save();
@ -212,7 +213,7 @@ public:
//BBS download project by project id
void import_model_id(const std::string& download_info);
void download_project(const wxString& project_id);
void request_model_download(std::string url, std::string filename);
void request_model_download();
void request_download_project(std::string project_id);
// BBS: check snapshot
bool up_to_date(bool saved, bool backup);
@ -265,7 +266,7 @@ public:
const wxString& get_last_loaded_gcode() const { return m_last_loaded_gcode; }
void update();
void update(bool conside_update_flag = false);
//BBS
void object_list_changed();
void stop_jobs();
@ -303,6 +304,7 @@ public:
void trigger_restore_project(int skip_confirm = 0);
void delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); // BBS support refresh immediately
void delete_all_objects_from_model(); //BBS delete all objects from model
void set_selected_visible(bool visible);
void remove_selected();
void increase_instances(size_t num = 1);
void decrease_instances(size_t num = 1);
@ -388,6 +390,7 @@ public:
// BBS
void on_bed_type_change(BedType bed_type);
bool update_filament_colors_in_full_config();
void config_change_notification(const DynamicPrintConfig &config, const std::string& key);
void on_config_change(const DynamicPrintConfig &config);
void force_filament_colors_update();
void force_print_bed_update();
@ -453,6 +456,10 @@ public:
//BBS:
void fill_color(int extruder_id);
//BBS:
void edit_text();
bool can_edit_text() const;
bool can_delete() const;
bool can_delete_all() const;
bool can_add_model() const;
@ -567,6 +574,9 @@ public:
void bring_instance_forward();
bool need_update() const;
void set_need_update(bool need_update);
// ROII wrapper for suppressing the Undo / Redo snapshot to be taken.
class SuppressSnapshots
{
@ -692,6 +702,7 @@ private:
bool m_only_gcode { false };
bool m_exported_file { false };
bool skip_thumbnail_invalid { false };
bool m_loading_project {false };
std::string m_preview_only_filename;
int m_valid_plates_count { 0 };

View file

@ -110,8 +110,6 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(
auto language_name = vlist[i]->Description;
if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_CHINESE_SIMPLIFIED)) {
//language_name = _L(vlist[i]->Description);
//language_name = _L("Chinese (Simplified)");
language_name = wxString::FromUTF8("\xe4\xb8\xad\xe6\x96\x87\x28\xe7\xae\x80\xe4\xbd\x93\x29");
}
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_SPANISH)) {
@ -132,6 +130,9 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_HUNGARIAN)) {
language_name = wxString::FromUTF8("Magyar");
}
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_JAPANESE)) {
language_name = wxString::FromUTF8("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E");
}
if (app_config->get(param) == vlist[i]->CanonicalName) {
m_current_language_selected = i;
@ -157,7 +158,7 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(
if (wxGetApp().plater()->is_project_dirty()) {
auto result = MessageDialog(static_cast<wxWindow*>(this), _L("The current project has unsaved changes, save it before continue?"),
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Save"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal();
if (result == wxID_YES) {
wxGetApp().plater()->save_project();
}
@ -241,7 +242,7 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin
auto region_index = e.GetSelection();
auto region = local_regions[region_index];
auto area = "";
/*auto area = "";
if (region == "CHN" || region == "China")
area = "CN";
else if (region == "USA")
@ -253,7 +254,7 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin
else if (region == "North America")
area = "US";
else
area = "Others";
area = "Others";*/
NetworkAgent* agent = wxGetApp().getAgent();
AppConfig* config = GUI::wxGetApp().app_config;
@ -265,10 +266,11 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin
return;
} else {
wxGetApp().request_user_logout();
config->set("region", region.ToStdString());
auto area = config->get_country_code();
if (agent) {
agent->set_country_code(area);
}
config->set("region", region.ToStdString());
EndModal(wxID_CANCEL);
}
} else {
@ -497,7 +499,7 @@ wxBoxSizer* PreferencesDialog::create_item_darkmode_checkbox(wxString title, wxW
#ifdef _MSW_DARK_MODE
wxGetApp().force_colors_update();
wxGetApp().update_ui_from_settings();
set_dark_mode();
set_dark_mode();
#endif
SimpleEvent evt = SimpleEvent(EVT_GLCANVAS_COLOR_MODE_CHANGED);
wxPostEvent(wxGetApp().plater(), evt);
@ -729,7 +731,7 @@ void PreferencesDialog::create()
Layout();
Fit();
int screen_height = wxGetDisplaySize().GetY();
if (this->GetSize().GetY() > screen_height)
if (this->GetSize().GetY() > screen_height)
this->SetSize(this->GetSize().GetX() + FromDIP(40), screen_height * 4 / 5);
CenterOnParent();
@ -789,7 +791,9 @@ wxWindow* PreferencesDialog::create_general_page()
wxLANGUAGE_SPANISH,
wxLANGUAGE_SWEDISH,
wxLANGUAGE_DUTCH,
wxLANGUAGE_HUNGARIAN };
wxLANGUAGE_HUNGARIAN,
wxLANGUAGE_JAPANESE
};
auto translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY);
std::vector<const wxLanguageInfo *> language_infos;
@ -848,7 +852,7 @@ wxWindow* PreferencesDialog::create_general_page()
auto title_darkmode = create_item_title(_L("Dark Mode"), page, _L("Dark Mode"));
auto item_darkmode = create_item_darkmode_checkbox(_L("Enable Dark mode"), page,_L("Enable Dark mode"), 50, "dark_color_mode");
#endif
sizer_page->Add(title_general_settings, 0, wxEXPAND, 0);
sizer_page->Add(item_language, 0, wxTOP, FromDIP(3));
@ -953,9 +957,10 @@ void PreferencesDialog::create_shortcuts_page()
sizer_page->Fit(page);
}
wxBoxSizer* PreferencesDialog::create_debug_page()
wxWindow* PreferencesDialog::create_debug_page()
{
//wxBoxSizer *sizer_page = new wxBoxSizer(wxVERTICAL);
auto page = new wxWindow(m_scrolledWindow, wxID_ANY);
page->SetBackgroundColour(*wxWHITE);
m_developer_mode_def = app_config->get("developer_mode");
m_dump_video_def = app_config->get("dump_video");
@ -964,19 +969,19 @@ wxBoxSizer* PreferencesDialog::create_debug_page()
wxBoxSizer *bSizer = new wxBoxSizer(wxVERTICAL);
auto title_develop_mode = create_item_title(_L("Develop mode"), m_scrolledWindow, _L("Develop mode"));
auto item_develop_mode = create_item_checkbox(_L("Develop mode"), m_scrolledWindow, _L("Develop mode"), 50, "developer_mode");
auto item_dump_video = create_item_checkbox(_L("Dump video"), m_scrolledWindow, _L("Dump video"), 50, "dump_video");
auto title_develop_mode = create_item_title(_L("Develop mode"), page, _L("Develop mode"));
auto item_develop_mode = create_item_checkbox(_L("Develop mode"), page, _L("Develop mode"), 50, "developer_mode");
auto item_dump_video = create_item_checkbox(_L("Dump video"), page, _L("Dump video"), 50, "dump_video");
auto title_log_level = create_item_title(_L("Log Level"), m_scrolledWindow, _L("Log Level"));
auto title_log_level = create_item_title(_L("Log Level"), page, _L("Log Level"));
auto log_level_list = std::vector<wxString>{_L("fatal"), _L("error"), _L("warning"), _L("info"), _L("debug"), _L("trace")};
auto loglevel_combox = create_item_loglevel_combobox(_L("Log Level"), m_scrolledWindow, _L("Log Level"), log_level_list);
auto loglevel_combox = create_item_loglevel_combobox(_L("Log Level"), page, _L("Log Level"), log_level_list);
auto title_host = create_item_title(_L("Host Setting"), m_scrolledWindow, _L("Host Setting"));
auto radio1 = create_item_radiobox(_L("DEV host: api-dev.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "dev_host");
auto radio2 = create_item_radiobox(_L("QA host: api-qa.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "qa_host");
auto radio3 = create_item_radiobox(_L("PRE host: api-pre.bambu-lab.com/v1"), m_scrolledWindow, wxEmptyString, 50, 1, "pre_host");
auto radio4 = create_item_radiobox(_L("Product host"), m_scrolledWindow, wxEmptyString, 50, 1, "product_host");
auto title_host = create_item_title(_L("Host Setting"), page, _L("Host Setting"));
auto radio1 = create_item_radiobox(_L("DEV host: api-dev.bambu-lab.com/v1"), page, wxEmptyString, 50, 1, "dev_host");
auto radio2 = create_item_radiobox(_L("QA host: api-qa.bambu-lab.com/v1"), page, wxEmptyString, 50, 1, "qa_host");
auto radio3 = create_item_radiobox(_L("PRE host: api-pre.bambu-lab.com/v1"), page, wxEmptyString, 50, 1, "pre_host");
auto radio4 = create_item_radiobox(_L("Product host"), page, wxEmptyString, 50, 1, "product_host");
if (m_iot_environment_def == ENV_DEV_HOST) {
on_select_radio("dev_host");
@ -994,7 +999,7 @@ wxBoxSizer* PreferencesDialog::create_debug_page()
std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Normal));
StateColor btn_bd_white(std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
Button* debug_button = new Button(m_scrolledWindow, _L("debug save button"));
Button* debug_button = new Button(page, _L("debug save button"));
debug_button->SetBackgroundColor(btn_bg_white);
debug_button->SetBorderColor(btn_bd_white);
debug_button->SetFont(Label::Body_13);
@ -1063,7 +1068,9 @@ wxBoxSizer* PreferencesDialog::create_debug_page()
wxGetApp().request_user_logout();
agent->set_country_code(country_code);
}
wxMessageBox(_L("Switch cloud environment, Please login again!"));
ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, _L("Warning"), ConfirmBeforeSendDialog::ButtonStyle::ONLY_CONFIRM);
confirm_dlg.update_text(_L("Switch cloud environment, Please login again!"));
confirm_dlg.on_show();
}
// bbs backup
@ -1098,7 +1105,11 @@ wxBoxSizer* PreferencesDialog::create_debug_page()
bSizer->Add(radio3, 0, wxEXPAND | wxTOP, FromDIP(3));
bSizer->Add(radio4, 0, wxEXPAND | wxTOP, FromDIP(3));
bSizer->Add(debug_button, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(15));
return bSizer;
page->SetSizer(bSizer);
page->Layout();
bSizer->Fit(page);
return page;
}
void PreferencesDialog::on_select_radio(std::string param)

View file

@ -122,7 +122,7 @@ public:
void create_gui_page();
void create_sync_page();
void create_shortcuts_page();
wxBoxSizer* create_debug_page();
wxWindow* create_debug_page();
void on_select_radio(std::string param);
wxString get_select_radio(int groupid);

View file

@ -376,8 +376,14 @@ void PresetComboBox::add_ams_filaments(std::string selected, bool alias_name)
auto &filaments = m_collection->get_presets();
for (auto &f : m_preset_bundle->filament_ams_list) {
std::string filament_id = f.opt_string("filament_id", 0u);
if (filament_id.empty()) continue;
auto iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_id](auto &f) { return f.is_compatible && f.is_system && f.filament_id == filament_id; });
if (iter == filaments.end()) {
auto filament_type = "Generic " + f.opt_string("filament_type", 0u);
iter = std::find_if(filaments.begin(), filaments.end(),
[&filament_type](auto &f) { return f.is_compatible && f.is_system && boost::algorithm::starts_with(f.name, filament_type); });
}
if (iter == filaments.end()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
continue;

View file

@ -23,11 +23,6 @@ extern "C" {
#ifndef __cplusplus
#include <stdbool.h>
/* We need these workarounds since we're compiling C source, not C++. */
typedef enum Bambu_StreamType Bambu_StreamType;
typedef struct Bambu_StreamInfo Bambu_StreamInfo;
typedef struct Bambu_Sample Bambu_Sample;
#endif
#ifdef _WIN32
@ -40,31 +35,33 @@ typedef void* Bambu_Tunnel;
typedef void (*Logger)(void * context, int level, tchar const* msg);
enum Bambu_StreamType
typedef enum __Bambu_StreamType
{
VIDE,
AUDI
};
} Bambu_StreamType;
enum Bambu_VideoSubType
typedef enum __Bambu_VideoSubType
{
AVC1,
};
MJPG,
} Bambu_VideoSubType;
enum Bambu_AudioSubType
typedef enum __Bambu_AudioSubType
{
MP4A
};
} Bambu_AudioSubType;
enum Bambu_FormatType
typedef enum __Bambu_FormatType
{
video_avc_packet,
video_avc_byte_stream,
video_jpeg,
audio_raw,
audio_adts
};
} Bambu_FormatType;
struct Bambu_StreamInfo
typedef struct __Bambu_StreamInfo
{
Bambu_StreamType type;
int sub_type;
@ -84,33 +81,34 @@ struct Bambu_StreamInfo
} format;
int format_type;
int format_size;
int max_frame_size;
unsigned char const * format_buffer;
};
} Bambu_StreamInfo;
enum Bambu_SampleFlag
typedef enum __Bambu_SampleFlag
{
f_sync = 1
};
} Bambu_SampleFlag;
struct Bambu_Sample
typedef struct __Bambu_Sample
{
int itrack;
int size;
int flags;
unsigned char const * buffer;
unsigned long long decode_time;
};
} Bambu_Sample;
enum Bambu_Error
typedef enum __Bambu_Error
{
Bambu_success,
Bambu_stream_end,
Bambu_would_block,
Bambu_would_block,
Bambu_buffer_limit
};
} Bambu_Error;
#ifdef BAMBU_DYNAMIC
struct BambuLib {
typedef struct __BambuLib {
#endif
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Create)(Bambu_Tunnel* tunnel, char const* path);
@ -148,7 +146,7 @@ BAMBU_EXPORT char const* BAMBU_FUNC(Bambu_GetLastErrorMsg)();
BAMBU_EXPORT void BAMBU_FUNC(Bambu_FreeLogMsg)(tchar const* msg);
#ifdef BAMBU_DYNAMIC
};
} BambuLib;
#endif
#ifdef __cplusplus

View file

@ -895,7 +895,7 @@ StaticBambuLib &StaticBambuLib::get()
{
static StaticBambuLib lib;
// first load the library
if (lib.Bambu_Open)
return lib;
@ -910,6 +910,8 @@ StaticBambuLib &StaticBambuLib::get()
GET_FUNC(Bambu_Create);
GET_FUNC(Bambu_Open);
GET_FUNC(Bambu_StartStream);
GET_FUNC(Bambu_GetStreamCount);
GET_FUNC(Bambu_GetStreamInfo);
GET_FUNC(Bambu_SendMessage);
GET_FUNC(Bambu_ReadSample);
GET_FUNC(Bambu_Close);
@ -922,6 +924,6 @@ StaticBambuLib &StaticBambuLib::get()
return lib;
}
extern "C" struct BambuLib *bambulib_get() {
extern "C" BambuLib *bambulib_get() {
return &StaticBambuLib::get();
}

View file

@ -2,7 +2,7 @@
* integration with proprietary Bambu Lab blob for getting raw h.264 video
*
* Copyright (C) 2023 Joshua Wise <joshua@accelerated.tech>
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@ -62,10 +62,10 @@
#ifdef __cplusplus
extern "C"
#else
extern
extern
#endif
struct BambuLib *bambulib_get();
static struct BambuLib *_lib = NULL;
BambuLib *bambulib_get();
BambuLib *_lib = NULL;
#define BAMBULIB(x) (_lib->x)
#else
@ -78,7 +78,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_bambusrc_debug);
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS("video/x-h264,framerate=0/1,parsed=(boolean)false,stream-format=(string)byte-stream"));
GST_STATIC_CAPS_ANY);
//GST_STATIC_CAPS("video/x-h264,framerate=0/1,parsed=(boolean)false,stream-format=(string)byte-stream"));
enum
{
@ -264,22 +265,22 @@ gst_bambusrc_create (GstPushSrc * psrc, GstBuffer ** outbuf)
GstBambuSrc *src;
src = GST_BAMBUSRC (psrc);
(void) src;
GST_DEBUG_OBJECT (src, "create()");
int rv;
struct Bambu_Sample sample;
Bambu_Sample sample;
if (!src->tnl) {
return GST_FLOW_ERROR;
}
while ((rv = BAMBULIB(Bambu_ReadSample)(src->tnl, &sample)) == Bambu_would_block) {
GST_DEBUG_OBJECT(src, "create would block");
usleep(33333); /* 30Hz */
}
if (rv == Bambu_stream_end) {
return GST_FLOW_EOS;
}
@ -287,7 +288,7 @@ gst_bambusrc_create (GstPushSrc * psrc, GstBuffer ** outbuf)
if (rv != Bambu_success) {
return GST_FLOW_ERROR;
}
#if GLIB_CHECK_VERSION(2,68,0)
gpointer sbuf = g_memdup2(sample.buffer, sample.size);
#else
@ -299,12 +300,33 @@ gst_bambusrc_create (GstPushSrc * psrc, GstBuffer ** outbuf)
* need to feed this in too -- otherwise the GStreamer pipeline gets upset
* and starts triggering QoS events.
*/
if (!src->sttime) {
src->sttime = sample.decode_time * 100ULL;
if (src->video_type == AVC1) {
if (!src->sttime) {
src->sttime = sample.decode_time * 100ULL;
}
GST_BUFFER_DTS(*outbuf) = sample.decode_time * 100ULL - src->sttime;
GST_BUFFER_PTS(*outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION(*outbuf) = GST_CLOCK_TIME_NONE;
}
GST_BUFFER_DTS(*outbuf) = sample.decode_time * 100ULL - src->sttime;
GST_BUFFER_PTS(*outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION(*outbuf) = GST_CLOCK_TIME_NONE;
else {
if (!src->sttime) {
//only available from 1.18
//src->sttime = gst_element_get_current_clock_time((GstElement *)psrc);
src->sttime = gst_clock_get_time(((GstElement *)psrc)->clock);
//if (GST_CLOCK_TIME_NONE == src->sttime)
// src->sttime
GST_DEBUG_OBJECT(src,
"sttime init to %llu.",
src->sttime);
}
//GST_BUFFER_DTS(*outbuf) = gst_element_get_current_clock_time((GstElement *)psrc) - src->sttime;
GST_BUFFER_DTS(*outbuf) = gst_clock_get_time(((GstElement *)psrc)->clock) - src->sttime;
GST_BUFFER_PTS(*outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION(*outbuf) = GST_CLOCK_TIME_NONE;
}
GST_DEBUG_OBJECT(src,
"sttime:%llu, DTS:%llu, PTS: %llu~",
src->sttime, GST_BUFFER_DTS(*outbuf), GST_BUFFER_PTS(*outbuf));
return GST_FLOW_OK;
}
@ -321,13 +343,13 @@ gst_bambusrc_start (GstBaseSrc * bsrc)
GstBambuSrc *src = GST_BAMBUSRC (bsrc);
GST_DEBUG_OBJECT (src, "start(\"%s\")", src->location);
if (src->tnl) {
BAMBULIB(Bambu_Close)(src->tnl);
BAMBULIB(Bambu_Destroy)(src->tnl);
src->tnl = NULL;
}
#ifdef BAMBU_DYNAMIC
if (!_lib) {
_lib = bambulib_get();
@ -339,15 +361,15 @@ gst_bambusrc_start (GstBaseSrc * bsrc)
if (BAMBULIB(Bambu_Create)(&src->tnl, src->location) != Bambu_success) {
return FALSE;
}
BAMBULIB(Bambu_SetLogger)(src->tnl, _log, (void *)src);
if (BAMBULIB(Bambu_Open)(src->tnl) != Bambu_success) {
BAMBULIB(Bambu_Destroy)(src->tnl);
src->tnl = NULL;
return FALSE;
}
int rv;
int rv, n = 0;
while ((rv = BAMBULIB(Bambu_StartStream)(src->tnl, 1 /* video */)) == Bambu_would_block) {
usleep(100000);
}
@ -358,6 +380,21 @@ gst_bambusrc_start (GstBaseSrc * bsrc)
return FALSE;
}
src->video_type = AVC1;
n = BAMBULIB(Bambu_GetStreamCount)(src->tnl);
GST_INFO_OBJECT (src, "Bambu_GetStreamCount returned stream count=%d",n);
for (int i = 0; i < n; ++i) {
Bambu_StreamInfo info;
BAMBULIB(Bambu_GetStreamInfo)(src->tnl, i, &info);
GST_INFO_OBJECT (src, "stream %d type=%d, sub_type=%d", i, info.type, info.sub_type);
if (info.type == VIDE) {
src->video_type = info.sub_type;
GST_INFO_OBJECT (src, " width %d height=%d, frame_rate=%d",
info.format.video.width, info.format.video.height, info.format.video.frame_rate);
}
}
src->sttime = 0;
return TRUE;
}
@ -383,9 +420,9 @@ gst_bambusrc_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstBambuSrc *src;
src = GST_BAMBUSRC (element);
(void) src;
switch (transition) {
@ -429,7 +466,7 @@ static gboolean
gst_bambusrc_is_seekable (GstBaseSrc * bsrc)
{
GstBambuSrc *src = GST_BAMBUSRC (bsrc);
(void) src;
return FALSE;
@ -522,7 +559,7 @@ static void
gst_bambusrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
{
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
iface->get_type = gst_bambusrc_uri_get_type;
iface->get_protocols = gst_bambusrc_uri_get_protocols;
iface->get_uri = gst_bambusrc_uri_get_uri;
@ -543,7 +580,7 @@ void gstbambusrc_register()
if (did_register)
return;
did_register = 1;
gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, "bambusrc", "Bambu Lab source", gstbambusrc_init, "0.0.1", "GPL", "BambuStudio", "BambuStudio", "https://github.com/bambulab/BambuStudio");
}

View file

@ -2,7 +2,7 @@
* integration with proprietary Bambu Lab blob for getting raw h.264 video
*
* Copyright (C) 2023 Joshua Wise <joshua@accelerated.tech>
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@ -64,6 +64,7 @@ struct _GstBambuSrc
gchar *location;
Bambu_Tunnel tnl;
GstClockTime sttime;
int video_type;
};
extern void gstbambusrc_register();

View file

@ -0,0 +1,211 @@
#include "PrivacyUpdateDialog.hpp"
#include "GUI_App.hpp"
#include "BitmapCache.hpp"
#include <wx/dcgraph.h>
#include <slic3r/GUI/I18N.hpp>
namespace Slic3r { namespace GUI {
wxDEFINE_EVENT(EVT_PRIVACY_UPDATE_CONFIRM, wxCommandEvent);
wxDEFINE_EVENT(EVT_PRIVACY_UPDATE_CANCEL, wxCommandEvent);
static std::string url_encode(const std::string& value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
std::string::value_type c = (*i);
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << std::uppercase;
escaped << '%' << std::setw(2) << int((unsigned char)c);
escaped << std::nouppercase;
}
return escaped.str();
}
PrivacyUpdateDialog::PrivacyUpdateDialog(wxWindow* parent, wxWindowID id, const wxString& title, enum ButtonStyle btn_style, const wxPoint& pos, const wxSize& size, long style)
:DPIDialog(parent, id, title, pos, size, style)
{
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);
m_sizer_main = new wxBoxSizer(wxVERTICAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(540), 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(5));
wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL);
m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15));
//webview
m_vebview_release_note = CreateTipView(this);
if (m_vebview_release_note == nullptr) {
wxLogError("Could not init m_browser");
return;
}
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetSize(wxSize(FromDIP(540), FromDIP(340)));
m_vebview_release_note->SetMinSize(wxSize(FromDIP(540), FromDIP(340)));
fs::path ph(data_dir());
ph /= "resources/tooltip/privacyupdate.html";
if (!fs::exists(ph)) {
ph = resources_dir();
ph /= "tooltip/privacyupdate.html";
}
m_host_url = ph.string();
std::replace(m_host_url.begin(), m_host_url.end(), '\\', '/');
m_host_url = "file:///" + m_host_url;
m_vebview_release_note->LoadURL(from_u8(m_host_url));
m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15));
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>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(220, 220, 220), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Normal));
#ifndef __WINDOWS__
m_vebview_release_note->Bind(wxEVT_WEBVIEW_LOADED, [this](auto& e) {
#else
m_vebview_release_note->Bind(wxEVT_WEBVIEW_NAVIGATED, [this](auto& e) {
#endif
if (!m_mkdown_text.empty()) {
ShowReleaseNote(m_mkdown_text);
}
e.Skip();
});
m_vebview_release_note->Bind(wxEVT_WEBVIEW_NAVIGATING , &PrivacyUpdateDialog::OnNavigating, this);
m_button_ok = new Button(this, _L("Accept"));
m_button_ok->SetBackgroundColor(btn_bg_green);
m_button_ok->SetBorderColor(*wxWHITE);
m_button_ok->SetTextColor(wxColour("#FFFFFE"));
m_button_ok->SetFont(Label::Body_12);
m_button_ok->SetSize(wxSize(-1, FromDIP(36)));
m_button_ok->SetMinSize(wxSize(-1, FromDIP(36)));
m_button_ok->SetCornerRadius(FromDIP(3));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
wxCommandEvent evt(EVT_PRIVACY_UPDATE_CONFIRM, GetId());
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(evt);
this->on_hide();
});
m_button_cancel = new Button(this, _L("Log Out"));
m_button_cancel->SetBackgroundColor(btn_bg_white);
m_button_cancel->SetBorderColor(*wxWHITE);
m_button_cancel->SetFont(Label::Body_12);
m_button_cancel->SetSize(wxSize(-1, FromDIP(36)));
m_button_cancel->SetMinSize(wxSize(-1, FromDIP(36)));
m_button_cancel->SetCornerRadius(FromDIP(3));
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
wxCommandEvent evt(EVT_PRIVACY_UPDATE_CANCEL);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(evt);
this->on_hide();
});
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) {e.Veto(); });
if (btn_style != CONFIRM_AND_CANCEL)
m_button_cancel->Hide();
else
m_button_cancel->Show();
sizer_button->Add(m_button_cancel, 1, wxALL | wxEXPAND, FromDIP(10));
sizer_button->Add(m_button_ok, 1, wxALL | wxEXPAND, FromDIP(10));
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(5));
m_sizer_right->Add(0, 0, 0, wxTOP, FromDIP(10));
m_sizer_main->Add(m_sizer_right, 0, wxBOTTOM | wxEXPAND, FromDIP(5));
SetSizer(m_sizer_main);
Layout();
m_sizer_main->Fit(this);
CenterOnParent();
wxGetApp().UpdateDlgDarkUI(this);
}
wxWebView* PrivacyUpdateDialog::CreateTipView(wxWindow* parent)
{
wxWebView* tipView = WebView::CreateWebView(parent, "");
return tipView;
}
void PrivacyUpdateDialog::OnNavigating(wxWebViewEvent& event)
{
wxString jump_url = event.GetURL();
if (jump_url != m_host_url) {
event.Veto();
wxLaunchDefaultBrowser(jump_url);
}
else {
event.Skip();
}
}
bool PrivacyUpdateDialog::ShowReleaseNote(std::string content)
{
auto script = "window.showMarkdown('" + url_encode(content) + "', true);";
RunScript(script);
return true;
}
void PrivacyUpdateDialog::RunScript(std::string script)
{
WebView::RunScript(m_vebview_release_note, script);
script.clear();
}
void PrivacyUpdateDialog::on_show()
{
wxGetApp().UpdateDlgDarkUI(this);
this->ShowModal();
}
void PrivacyUpdateDialog::on_hide()
{
EndModal(wxID_OK);
}
void PrivacyUpdateDialog::update_btn_label(wxString ok_btn_text, wxString cancel_btn_text)
{
m_button_ok->SetLabel(ok_btn_text);
m_button_cancel->SetLabel(cancel_btn_text);
rescale();
}
PrivacyUpdateDialog::~PrivacyUpdateDialog()
{
}
void PrivacyUpdateDialog::on_dpi_changed(const wxRect& suggested_rect)
{
rescale();
}
void PrivacyUpdateDialog::rescale()
{
m_button_ok->Rescale();
m_button_cancel->Rescale();
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,56 @@
#ifndef slic3r_GUI_PrivacyUpdateDialog_hpp_
#define slic3r_GUI_PrivacyUpdateDialog_hpp_
#include "GUI_Utils.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/WebView.hpp"
#include <wx/webview.h>
#include <wx/simplebook.h>
namespace Slic3r { namespace GUI {
wxDECLARE_EVENT(EVT_PRIVACY_UPDATE_CONFIRM, wxCommandEvent);
wxDECLARE_EVENT(EVT_PRIVACY_UPDATE_CANCEL, wxCommandEvent);
class PrivacyUpdateDialog : public DPIDialog
{
public:
enum ButtonStyle {
ONLY_CONFIRM = 0,
CONFIRM_AND_CANCEL = 1,
MAX_STYLE_NUM = 2
};
PrivacyUpdateDialog(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& title = wxEmptyString,
enum ButtonStyle btn_style = CONFIRM_AND_CANCEL,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxPD_APP_MODAL| wxCAPTION
);
wxWebView* CreateTipView(wxWindow* parent);
void OnNavigating(wxWebViewEvent& event);
bool ShowReleaseNote(std::string content);
void RunScript(std::string script);
void set_text(std::string str) { m_mkdown_text = str; };
void on_show();
void on_hide();
void update_btn_label(wxString ok_btn_text, wxString cancel_btn_text);
void rescale();
~PrivacyUpdateDialog();
void on_dpi_changed(const wxRect& suggested_rect);
wxBoxSizer* m_sizer_main;
wxWebView* m_vebview_release_note{ nullptr };
Label* m_staticText_release_note{ nullptr };
Button* m_button_ok;
Button* m_button_cancel;
std::string m_mkdown_text;
std::string m_host_url;
};
}} // namespace Slic3r::GUI
#endif

View file

@ -17,7 +17,8 @@ namespace GUI {
void ProjectDirtyStateManager::update_from_undo_redo_stack(bool dirty)
{
m_plater_dirty = dirty;
if (!m_plater_dirty)
m_plater_dirty = dirty;
if (const Plater *plater = wxGetApp().plater(); plater && wxGetApp().initialized())
wxGetApp().mainframe->update_title();
}

View file

@ -14,6 +14,7 @@ public:
void reset_after_save();
void reset_initial_presets();
void set_plater_dirty(bool is_dirty) { m_plater_dirty = is_dirty; }
bool is_dirty() const { return m_plater_dirty || m_project_config_dirty || m_presets_dirty; }
bool is_presets_dirty() const { return m_presets_dirty; }

View file

@ -10,9 +10,6 @@
const wxColour text_color(107, 107, 107);
wxString hint1 = _L("Please home all axes (click ");
wxString hint2 = _L(") to locate the toolhead's position. This prevents device moving beyond the printable boundary and causing equipment wear.");
namespace Slic3r { namespace GUI {
RecenterDialog::RecenterDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
: DPIDialog(parent, id, _L("Confirm"), pos, size, style)
@ -20,6 +17,9 @@ RecenterDialog::RecenterDialog(wxWindow* parent, wxWindowID id, const wxString&
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
hint1 = _L("Please home all axes (click ");
hint2 = _L(") to locate the toolhead's position. This prevents device moving beyond the printable boundary and causing equipment wear.");
init_bitmap();
SetBackgroundColour(*wxWHITE);
@ -130,7 +130,7 @@ void RecenterDialog::render(wxDC& dc) {
break;
}
else {
fisrt_line = hint2.SubString(0, i);
fisrt_line = hint2.SubString(0, i - 1);
remaining_line = hint2.SubString(i, hint2.length());
break;
}

View file

@ -15,6 +15,8 @@ private:
Button* m_button_close;
wxStaticBitmap* m_bitmap_home;
ScalableBitmap m_home_bmp;
wxString hint1;
wxString hint2;
void init_bitmap();
void OnPaint(wxPaintEvent& event);

Some files were not shown because too many files have changed in this diff Show more