Merge branch 'master-remote' into feature/merge_remote_1.3

# Conflicts:
#	bbl/i18n/zh_cn/BambuStudio_zh_CN.po
#	resources/i18n/zh_cn/BambuStudio.mo
#	resources/profiles/Voron.json
#	resources/profiles/Voron/filament/Voron Generic ABS.json
#	resources/profiles/Voron/filament/Voron Generic ASA.json
#	resources/profiles/Voron/filament/Voron Generic PA-CF.json
#	resources/profiles/Voron/filament/Voron Generic PA.json
#	resources/profiles/Voron/filament/Voron Generic PC.json
#	resources/profiles/Voron/filament/Voron Generic PETG.json
#	resources/profiles/Voron/filament/Voron Generic PLA-CF.json
#	resources/profiles/Voron/filament/Voron Generic PLA.json
#	resources/profiles/Voron/filament/Voron Generic PVA.json
#	resources/profiles/Voron/filament/Voron Generic TPU.json
#	resources/profiles/Voron/filament/fdm_filament_abs.json
#	resources/profiles/Voron/filament/fdm_filament_asa.json
#	resources/profiles/Voron/filament/fdm_filament_common.json
#	resources/profiles/Voron/filament/fdm_filament_pa.json
#	resources/profiles/Voron/filament/fdm_filament_pc.json
#	resources/profiles/Voron/filament/fdm_filament_pet.json
#	resources/profiles/Voron/filament/fdm_filament_pla.json
#	resources/profiles/Voron/filament/fdm_filament_pva.json
#	resources/profiles/Voron/filament/fdm_filament_tpu.json
#	resources/profiles/Voron/machine/Voron 0.1 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron 0.1.json
#	resources/profiles/Voron/machine/Voron 2.4 250 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron 2.4 250.json
#	resources/profiles/Voron/machine/Voron 2.4 300 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron 2.4 300.json
#	resources/profiles/Voron/machine/Voron 2.4 350 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron 2.4 350.json
#	resources/profiles/Voron/machine/Voron Trident 250 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron Trident 250.json
#	resources/profiles/Voron/machine/Voron Trident 300 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron Trident 300.json
#	resources/profiles/Voron/machine/Voron Trident 350 0.4 nozzle.json
#	resources/profiles/Voron/machine/Voron Trident 350.json
#	resources/profiles/Voron/machine/fdm_klipper_common.json
#	resources/profiles/Voron/process/0.08mm Extra Fine @Voron.json
#	resources/profiles/Voron/process/0.12mm Fine @Voron.json
#	resources/profiles/Voron/process/0.15mm Optimal @Voron.json
#	resources/profiles/Voron/process/0.20mm Standard @Voron.json
#	resources/profiles/Voron/process/0.24mm Draft @Voron.json
#	resources/profiles/Voron/process/0.28mm Extra Draft @Voron.json
#	resources/profiles/Voron/process/fdm_process_voron_common.json
#	src/libslic3r/Preset.cpp
#	src/libslic3r/PrintConfig.cpp
#	src/libslic3r/PrintConfig.hpp
#	src/libslic3r/PrintObject.cpp
#	src/slic3r/GUI/BackgroundSlicingProcess.cpp
#	src/slic3r/GUI/Field.cpp
#	src/slic3r/GUI/GLToolbar.cpp
#	src/slic3r/GUI/GLToolbar.hpp
#	src/slic3r/GUI/MainFrame.cpp
#	src/slic3r/GUI/MainFrame.hpp
#	src/slic3r/GUI/NotificationManager.cpp
#	src/slic3r/GUI/PhysicalPrinterDialog.cpp
#	src/slic3r/GUI/PhysicalPrinterDialog.hpp
#	src/slic3r/GUI/Plater.cpp
#	src/slic3r/GUI/Plater.hpp
#	src/slic3r/GUI/PrintHostDialogs.cpp
#	src/slic3r/GUI/PrintHostDialogs.hpp
#	src/slic3r/Utils/PrintHost.cpp
This commit is contained in:
SoftFever 2022-10-20 23:12:00 +08:00
commit 35455e6533
278 changed files with 14888 additions and 2414 deletions

View file

@ -205,6 +205,8 @@ set(SLIC3R_GUI_SOURCES
GUI/ParamsDialog.hpp
GUI/ParamsPanel.cpp
GUI/ParamsPanel.hpp
GUI/PrintHostDialogs.cpp
GUI/PrintHostDialogs.hpp
GUI/AmsWidgets.cpp
GUI/AmsWidgets.hpp
GUI/MediaFilePanel.cpp
@ -215,6 +217,8 @@ set(SLIC3R_GUI_SOURCES
GUI/MonitorBasePanel.h
GUI/UpgradePanel.cpp
GUI/UpgradePanel.hpp
GUI/HintNotification.hpp
GUI/HintNotification.cpp
GUI/HMSPanel.hpp
GUI/HMSPanel.cpp
GUI/MonitorPage.cpp
@ -303,10 +307,14 @@ set(SLIC3R_GUI_SOURCES
GUI/Jobs/ProgressIndicator.hpp
GUI/Jobs/PrintJob.hpp
GUI/Jobs/PrintJob.cpp
GUI/Jobs/SendJob.hpp
GUI/Jobs/SendJob.cpp
GUI/Jobs/BindJob.hpp
GUI/Jobs/BindJob.cpp
GUI/Jobs/NotificationProgressIndicator.hpp
GUI/Jobs/NotificationProgressIndicator.cpp
GUI/PhysicalPrinterDialog.hpp
GUI/PhysicalPrinterDialog.cpp
GUI/ProgressStatusBar.hpp
GUI/ProgressStatusBar.cpp
GUI/BBLStatusBar.hpp
@ -348,10 +356,14 @@ set(SLIC3R_GUI_SOURCES
GUI/PublishDialog.hpp
GUI/RecenterDialog.cpp
GUI/RecenterDialog.hpp
GUI/BonjourDialog.cpp
GUI/BonjourDialog.hpp
GUI/BindDialog.cpp
GUI/BindDialog.hpp
GUI/SelectMachine.hpp
GUI/SelectMachine.cpp
GUI/SendToPrinter.hpp
GUI/SendToPrinter.cpp
GUI/AmsMappingPopup.hpp
GUI/AmsMappingPopup.cpp
GUI/ReleaseNote.hpp
@ -389,6 +401,10 @@ set(SLIC3R_GUI_SOURCES
Utils/minilzo_extension.cpp
Utils/ColorSpaceConvert.hpp
Utils/ColorSpaceConvert.cpp
Utils/OctoPrint.hpp
Utils/OctoPrint.cpp
Utils/PrintHost.hpp
Utils/PrintHost.cpp
Utils/NetworkAgent.cpp
Utils/NetworkAgent.hpp
Utils/OctoPrint.cpp

View file

@ -251,7 +251,9 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig
m_extended_bounding_box = this->calc_extended_bounding_box(false);
//BBS: add part plate logic
/*#if 0
//BBS add default bed
#if 1
ExPolygon poly{ Polygon::new_scale(printable_area) };
#else
ExPolygon poly;
@ -265,7 +267,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig
const BoundingBox& bed_bbox = poly.contour.bounding_box();
calc_gridlines(poly, bed_bbox);
m_polygon = offset(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0];*/
m_polygon = offset(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0];
if (with_reset) {
this->release_VBOs();
@ -375,7 +377,7 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box(bool consider_model_offset) cons
return out;
}
/*void Bed3D::calc_triangles(const ExPolygon& poly)
void Bed3D::calc_triangles(const ExPolygon& poly)
{
if (! m_triangles.set_from_triangles(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z))
BOOST_LOG_TRIVIAL(error) << "Unable to create bed triangles";
@ -406,7 +408,7 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
if (!m_gridlines.set_from_lines(gridlines, GROUND_Z))
BOOST_LOG_TRIVIAL(error) << "Unable to create bed grid lines\n";
}*/
}
// Try to match the print bed shape with the shape of an active profile. If such a match exists,
// return the print bed model.
@ -611,6 +613,36 @@ void Bed3D::update_model_offset() const
const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box();
}
GeometryBuffer Bed3D::update_bed_triangles() const
{
GeometryBuffer new_triangles;
Vec3d shift = m_extended_bounding_box.center();
shift(2) = -0.03;
Vec3d* model_offset_ptr = const_cast<Vec3d*>(&m_model_offset);
*model_offset_ptr = shift;
//BBS: TODO: hack for default bed
BoundingBoxf3 build_volume;
if (!m_build_volume.valid()) return new_triangles;
(*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x();
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y();
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
std::vector<Vec2d> new_bed_shape;
for (auto point: m_bed_shape) {
Vec2d new_point(point.x() + model_offset_ptr->x(), point.y() + model_offset_ptr->y());
new_bed_shape.push_back(new_point);
}
ExPolygon poly{ Polygon::new_scale(new_bed_shape) };
if (!new_triangles.set_from_triangles(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z)) {
;
}
// update extended bounding box
const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box();
return new_triangles;
}
void Bed3D::render_model() const
{
if (m_model_filename.empty())
@ -654,9 +686,11 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const
void Bed3D::render_default(bool bottom) const
{
/*const_cast<GLTexture*>(&m_texture)->reset();
bool picking = false;
const_cast<GLTexture*>(&m_texture)->reset();
unsigned int triangles_vcount = m_triangles.get_vertices_count();
GeometryBuffer default_triangles = update_bed_triangles();
if (triangles_vcount > 0) {
bool has_model = !m_model.get_filename().empty();
@ -671,7 +705,7 @@ void Bed3D::render_default(bool bottom) const
glsafe(::glDepthMask(GL_FALSE));
glsafe(::glColor4fv(picking ? PICKING_MODEL_COLOR.data() : DEFAULT_MODEL_COLOR.data()));
glsafe(::glNormal3d(0.0f, 0.0f, 1.0f));
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data()));
glsafe(::glVertexPointer(3, GL_FLOAT, default_triangles.get_vertex_data_size(), (GLvoid*)default_triangles.get_vertices_data()));
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount));
glsafe(::glDepthMask(GL_TRUE));
}
@ -683,14 +717,14 @@ void Bed3D::render_default(bool bottom) const
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 1.0f));
else
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.6f));
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data()));
glsafe(::glVertexPointer(3, GL_FLOAT, default_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data()));
glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)m_gridlines.get_vertices_count()));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisable(GL_BLEND));
}*/
}
}
void Bed3D::release_VBOs()

View file

@ -1,7 +1,7 @@
#ifndef slic3r_3DBed_hpp_
#define slic3r_3DBed_hpp_
//#include "GLTexture.hpp"
#include "GLTexture.hpp"
#include "3DScene.hpp"
#include "GLModel.hpp"
@ -90,10 +90,10 @@ private:
// Print volume bounding box exteded with axes and model.
BoundingBoxf3 m_extended_bounding_box;
// Slightly expanded print bed polygon, for collision detection.
//Polygon m_polygon;
//GeometryBuffer m_triangles;
//GeometryBuffer m_gridlines;
//GLTexture m_texture;
Polygon m_polygon;
GeometryBuffer m_triangles;
GeometryBuffer m_gridlines;
GLTexture m_texture;
// temporary texture shown until the main texture has still no levels compressed
//GLTexture m_temp_texture;
GLModel m_model;
@ -148,6 +148,8 @@ private:
void calc_triangles(const ExPolygon& poly);
void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
void update_model_offset() const;
//BBS: with offset
GeometryBuffer update_bed_triangles() const;
static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape);
void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
bool show_axes);

View file

@ -869,6 +869,10 @@ void GLVolume::render(bool with_outline) const
std::array<float, 4> body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
shader->set_uniform("uniform_color", body_color);
//if (GUI::wxGetApp().plater()->is_show_wireframe())
// shader->set_uniform("show_wireframe", true);
//else
// shader->set_uniform("show_wireframe", false);
shader->set_uniform("is_outline", true);
glsafe(::glPopMatrix());
glsafe(::glPushMatrix());

View file

@ -244,7 +244,11 @@ AboutDialog::AboutDialog()
// version
{
vesizer->Add(0, FromDIP(165), 1, wxEXPAND, FromDIP(5));
#if BBL_INTERNAL_TESTING
auto version_string = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
#else
auto version_string = _L("Version") + " " + std::string(SLIC3R_VERSION);
#endif
wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize);
wxFont version_font = GetFont();
#ifdef __WXMSW__

View file

@ -139,6 +139,8 @@ void AuFile::enter_rename_mode()
{
m_input_name->Show();
m_text_name->Hide();
auto name = m_file_name.SubString(0, (m_file_name.Find(".") - 1));
m_input_name->GetTextCtrl()->SetLabelText(name);
Layout();
}

View file

@ -158,7 +158,7 @@ void CalibrationDialog::on_dpi_changed(const wxRect &suggested_rect) {}
void CalibrationDialog::update_cali(MachineObject *obj)
{
if (!obj) return;
if (obj->is_in_calibration() || obj->is_calibration_done()) {
if (obj->is_calibration_running() || obj->is_calibration_done()) {
if (obj->is_calibration_done()) {
m_calibration_btn->Enable();
m_calibration_btn->SetLabel(_L("Completed"));

View file

@ -560,9 +560,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : { "ironing_flow", "ironing_spacing", "ironing_speed" })
toggle_field(el, has_ironing);
bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" })
toggle_field(el, have_sequential_printing);
// bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
// for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" })
// toggle_field(el, have_sequential_printing);
bool have_ooze_prevention = config->opt_bool("ooze_prevention");
toggle_field("standby_temperature_delta", have_ooze_prevention);

View file

@ -9,7 +9,7 @@ namespace Slic3r { namespace GUI {
wxDEFINE_EVENT(EVT_CONFIRM_HINT, wxCommandEvent);
ConfirmHintDialog::ConfirmHintDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
ConfirmHintDialog::ConfirmHintDialog(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();
@ -46,6 +46,11 @@ ConfirmHintDialog::ConfirmHintDialog(wxWindow* parent, wxWindowID id, const wxSt
button_sizer->AddSpacer(FromDIP(20));
button_sizer->Add(m_button_close);
if (btn_style == CONFIRM_AND_CANCEL)
m_button_close->Show();
else
m_button_close->Hide();
main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
main_sizer->AddSpacer(wxSize(FromDIP(475), FromDIP(100)).y);
main_sizer->Add(button_sizer, 0, wxBOTTOM | wxRIGHT | wxEXPAND, FromDIP(25));
@ -99,8 +104,13 @@ void ConfirmHintDialog::render(wxDC& dc) {
auto text_size = dc.GetTextExtent(count_txt);
if (text_size.x + pos_firm_up_hint.x + FromDIP(25) < wxSize(FromDIP(475), FromDIP(100)).x)
{
if (firm_up_hint[i] == ' ' || firm_up_hint[i] == '\n')
if (firm_up_hint[i] == ' ') {
new_line_pos = i;
} else if (firm_up_hint[i] == '\n') {
fisrt_line = firm_up_hint.SubString(0, i);
remaining_line = firm_up_hint.SubString(i + 1, firm_up_hint.length());
break;
}
}
else {
if (!is_ch) {
@ -109,7 +119,7 @@ void ConfirmHintDialog::render(wxDC& dc) {
break;
}
else {
fisrt_line = firm_up_hint.SubString(0, i);
fisrt_line = firm_up_hint.SubString(0, i - 1);
remaining_line = firm_up_hint.SubString(i, firm_up_hint.length());
break;
}
@ -118,7 +128,6 @@ void ConfirmHintDialog::render(wxDC& dc) {
}
dc.DrawText(fisrt_line, pos_firm_up_hint);
count_txt = "";
new_line_pos = 0;
for (int i = 0; i < remaining_line.length(); i++) {
@ -162,11 +171,19 @@ void ConfirmHintDialog::on_button_close(wxCommandEvent& event) {
this->Close();
}
bool ConfirmHintDialog::Show(bool show)
{
if (show) { CentreOnParent(); }
return DPIDialog::Show(show);
}
void ConfirmHintDialog::on_dpi_changed(const wxRect& suggested_rect) {
m_button_confirm->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_confirm->SetCornerRadius(FromDIP(12));
m_button_close->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_close->SetCornerRadius(FromDIP(12));
if (m_button_close->IsShown()) {
m_button_close->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_close->SetCornerRadius(FromDIP(12));
}
Layout();
}

View file

@ -27,9 +27,16 @@ private:
void on_dpi_changed(const wxRect& suggested_rect) override;
public:
enum ButtonStyle {
ONLY_CONFIRM = 0,
CONFIRM_AND_CANCEL = 1,
MAX_STYLE_NUM = 2
};
ConfirmHintDialog(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 = wxCLOSE_BOX | wxCAPTION);
@ -38,6 +45,8 @@ public:
void SetHint(const wxString &hint);
bool Show(bool show) override;
~ConfirmHintDialog();
};
}} // namespace Slic3r::GUI

View file

@ -358,6 +358,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string
mc_print_sub_stage = 0;
mc_left_time = 0;
home_flag = -1;
hw_switch_state = 0;
printing_speed_lvl = PrintingSpeedLevel::SPEED_LEVEL_INVALID;
}
@ -1046,6 +1047,18 @@ bool MachineObject::is_axis_at_home(std::string axis)
}
}
bool MachineObject::is_filament_at_extruder()
{
if (hw_switch_state == 1)
return true;
else if (hw_switch_state == 0)
return false;
else {
//default
return true;
}
}
wxString MachineObject::get_curr_stage()
{
if (stage_list_info.empty()) {
@ -1359,6 +1372,19 @@ int MachineObject::command_ams_select_tray(std::string tray_id)
return this->publish_gcode(gcode_cmd);
}
int MachineObject::command_ams_control(std::string action)
{
//valid actions
if (action == "resume" || action == "reset" || action == "pause") {
json j;
j["print"]["command"] = "ams_control";
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
j["print"]["param"] = action;
return this->publish_json(j.dump());
}
return -1;
}
int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval)
{
@ -1726,6 +1752,12 @@ bool MachineObject::is_function_supported(PrinterFunction func)
return DeviceManager::is_function_supported(printer_type, func_name);
}
bool MachineObject::is_support_print_with_timelapse()
{
//TODO version check, set true by default
return true;
}
int MachineObject::publish_json(std::string json_str, int qos)
{
if (is_lan_mode_printer()) {
@ -1820,6 +1852,9 @@ int MachineObject::parse_json(std::string payload)
if (jj.contains("home_flag")) {
home_flag = jj["home_flag"].get<int>();
}
if (jj.contains("hw_switch_state")) {
hw_switch_state = jj["hw_switch_state"].get<int>();
}
if (jj.contains("mc_remaining_time")) {
if (jj["mc_remaining_time"].is_string())

View file

@ -466,6 +466,7 @@ public:
int mc_left_time; /* left time in seconds */
int last_mc_print_stage;
int home_flag;
int hw_switch_state;
bool is_system_printing();
int print_error;
@ -476,6 +477,8 @@ public:
bool is_axis_at_home(std::string axis);
bool is_filament_at_extruder();
wxString get_curr_stage();
// return curr stage index of stage list
int get_curr_stage_idx();
@ -561,6 +564,7 @@ public:
int command_ams_filament_settings(int ams_id, int tray_id, std::string setting_id, std::string tray_color, std::string tray_type, int nozzle_temp_min, int nozzle_temp_max);
int command_ams_select_tray(std::string tray_id);
int command_ams_refresh_rfid(std::string tray_id);
int command_ams_control(std::string action);
int command_set_chamber_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000);
int command_set_work_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000);
@ -605,6 +609,7 @@ public:
bool is_online() { return m_is_online; }
bool is_info_ready();
bool is_function_supported(PrinterFunction func);
bool is_support_print_with_timelapse();
/* Msg for display MsgFn */

View file

@ -31,6 +31,13 @@ namespace GUI {
DownloadProgressDialog::DownloadProgressDialog(wxString title)
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
{
wxString download_failed_url = wxT("https://wiki.bambulab.com/e/en/software/bambu-studio/failed-to-get-network-plugin");
wxString install_failed_url = wxT("https://wiki.bambulab.com/e/en/software/bambu-studio/failed-to-get-network-plugin");
wxString download_failed_msg = _L("Failed to download the plug-in. Please check your firewall settings and vpn software, check and retry.");
wxString install_failed_msg = _L("Failed to install the plug-in. Please check whether it is blocked or deleted by anti-virus software.");
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
@ -39,14 +46,68 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title)
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0);
m_status_bar = std::make_shared<BBLStatusBarSend>(this);
m_simplebook_status = new wxSimplebook(this);
m_simplebook_status->SetSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMinSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMaxSize(wxSize(FromDIP(400), FromDIP(70)));
//mode normal
m_status_bar = std::make_shared<BBLStatusBarSend>(m_simplebook_status);
m_panel_download = m_status_bar->get_panel();
m_panel_download->SetSize(wxSize(FromDIP(340), -1));
m_panel_download->SetMinSize(wxSize(FromDIP(340), -1));
m_panel_download->SetMaxSize(wxSize(FromDIP(340), -1));
m_sizer_main->Add(m_panel_download, 0, wxALL, FromDIP(20));
m_panel_download->SetSize(wxSize(FromDIP(400), FromDIP(70)));
m_panel_download->SetMinSize(wxSize(FromDIP(400), FromDIP(70)));
m_panel_download->SetMaxSize(wxSize(FromDIP(400), FromDIP(70)));
//mode Download Failed
auto m_panel_download_failed = new wxPanel(m_simplebook_status, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* sizer_download_failed = new wxBoxSizer(wxVERTICAL);
auto m_statictext_download_failed = new wxStaticText(m_panel_download_failed, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
m_statictext_download_failed->SetLabel(format_text(m_statictext_download_failed, download_failed_msg, FromDIP(360)));
m_statictext_download_failed->Wrap(FromDIP(360));
sizer_download_failed->Add(m_statictext_download_failed, 0, wxALIGN_CENTER | wxALL, 5);
auto m_download_hyperlink = new wxHyperlinkCtrl(m_panel_download_failed, wxID_ANY, _L("click here to see more info"), download_failed_url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
sizer_download_failed->Add(m_download_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_panel_download_failed->SetSizer(sizer_download_failed);
m_panel_download_failed->Layout();
sizer_download_failed->Fit(m_panel_download_failed);
//mode Installed failed
auto m_panel_install_failed = new wxPanel(m_simplebook_status, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* sizer_install_failed = new wxBoxSizer(wxVERTICAL);
auto m_statictext_install_failed = new wxStaticText(m_panel_install_failed, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
m_statictext_install_failed->SetLabel(format_text(m_statictext_install_failed, install_failed_msg,FromDIP(360)));
m_statictext_install_failed->Wrap(FromDIP(360));
sizer_install_failed->Add(m_statictext_install_failed, 0, wxALIGN_CENTER | wxALL, 5);
auto m_install_hyperlink = new wxHyperlinkCtrl(m_panel_install_failed, wxID_ANY, _L("click here to see more info"), install_failed_url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
sizer_install_failed->Add(m_install_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_panel_download_failed->SetSizer(sizer_install_failed);
m_panel_download_failed->Layout();
sizer_install_failed->Fit(m_panel_install_failed);
m_sizer_main->Add(m_simplebook_status, 0, wxALL, FromDIP(20));
m_sizer_main->Add(0, 0, 1, wxBOTTOM, 10);
m_simplebook_status->AddPage(m_status_bar->get_panel(), wxEmptyString, true);
m_simplebook_status->AddPage(m_panel_download_failed, wxEmptyString, false);
m_simplebook_status->AddPage(m_panel_install_failed, wxEmptyString, false);
SetSizer(m_sizer_main);
Layout();
Fit();
@ -55,9 +116,31 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title)
Bind(wxEVT_CLOSE_WINDOW, &DownloadProgressDialog::on_close, this);
}
wxString DownloadProgressDialog::format_text(wxStaticText* st, wxString str, int warp)
{
if (wxGetApp().app_config->get("language") != "zh_CN") { return str; }
wxString out_txt = str;
wxString count_txt = "";
int new_line_pos = 0;
for (int i = 0; i < str.length(); i++) {
auto text_size = st->GetTextExtent(count_txt);
if (text_size.x < warp) {
count_txt += str[i];
}
else {
out_txt.insert(i - 1, '\n');
count_txt = "";
}
}
return out_txt;
}
bool DownloadProgressDialog::Show(bool show)
{
if (show) {
m_simplebook_status->SetSelection(0);
m_upgrade_job = std::make_shared<UpgradeNetworkJob>(m_status_bar);
m_upgrade_job->set_event_handle(this);
m_status_bar->set_progress(0);
@ -71,9 +154,23 @@ bool DownloadProgressDialog::Show(bool show)
);
});
Bind(EVT_UPGRADE_NETWORK_FAILED, [this](wxCommandEvent& evt) {
//download failed
Bind(EVT_DOWNLOAD_NETWORK_FAILED, [this](wxCommandEvent& evt) {
m_status_bar->change_button_label(_L("Close"));
m_status_bar->set_progress(0);
this->m_simplebook_status->SetSelection(1);
m_status_bar->set_cancel_callback_fina(
[this]() {
this->Close();
}
);
});
//install failed
Bind(EVT_INSTALL_NETWORK_FAILED, [this](wxCommandEvent& evt) {
m_status_bar->change_button_label(_L("Close"));
m_status_bar->set_progress(0);
this->m_simplebook_status->SetSelection(2);
m_status_bar->set_cancel_callback_fina(
[this]() {
this->Close();

View file

@ -12,6 +12,7 @@
#include <wx/richmsgdlg.h>
#include <wx/textctrl.h>
#include <wx/statline.h>
#include <wx/simplebook.h>
#include "Widgets/Button.hpp"
#include "BBLStatusBar.hpp"
#include "BBLStatusBarSend.hpp"
@ -37,11 +38,14 @@ protected:
public:
DownloadProgressDialog(wxString title);
wxString format_text(wxStaticText* st, wxString str, int warp);
~DownloadProgressDialog();
void on_dpi_changed(const wxRect &suggested_rect) override;
void update_release_note(std::string release_note, std::string version);
wxSimplebook* m_simplebook_status{nullptr};
std::shared_ptr<BBLStatusBarSend> m_status_bar;
std::shared_ptr<UpgradeNetworkJob> m_upgrade_job { nullptr };
wxPanel * m_panel_download;

View file

@ -1235,7 +1235,9 @@ void Choice::set_value(const boost::any& value, bool change_event)
// BBS
case coEnums: {
int val = boost::any_cast<int>(value);
if (m_opt_id.compare("host_type") == 0 && val != 0 &&
// Support ThirdPartyPrinter
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")
@ -1317,15 +1319,15 @@ boost::any& Choice::get_value()
// BBS
if (m_opt.type == coEnum || m_opt.type == coEnums)
{
if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount()) {
// for case, when PrusaLink isn't used as a HostType
m_value = field->GetSelection()+1;
}
else 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") {
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(ConfigOptionEnum<InfillPattern>::get_enum_values().at(key));
}
else
// Support ThirdPartyPrinter
else if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount()) {
// for case, when PrusaLink isn't used as a HostType
m_value = field->GetSelection() + 1;
} else
m_value = field->GetSelection();
}
else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) {

View file

@ -334,6 +334,13 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
static const ImU32 text_value_clr = IM_COL32(144, 144, 144, 255);
static const ImU32 window_bg_clr = IM_COL32(255, 255, 255, 255);
auto it = std::find_if(moves.begin(), moves.end(), [&curr_line_id](auto move) {
return move.gcode_id == curr_line_id;
});
if (it == moves.end()) {
return;
}
ImGuiWrapper& imgui = *wxGetApp().imgui();
//BBS: GUI refactor: add canvas size from parameters
imgui.set_next_window_pos(0.5f * static_cast<float>(canvas_width), static_cast<float>(canvas_height), ImGuiCond_Always, 0.5f, 1.0f);
@ -352,19 +359,101 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
std::string x = ImGui::ColorMarkerStart + std::string("X: ") + ImGui::ColorMarkerEnd;
std::string y = ImGui::ColorMarkerStart + std::string("Y: ") + ImGui::ColorMarkerEnd;
std::string z = ImGui::ColorMarkerStart + std::string("Z: ") + ImGui::ColorMarkerEnd;
std::string height = ImGui::ColorMarkerStart + _u8L("Height: ") + ImGui::ColorMarkerEnd;
std::string width = ImGui::ColorMarkerStart + _u8L("Width: ") + ImGui::ColorMarkerEnd;
std::string speed = ImGui::ColorMarkerStart + _u8L("Speed: ") + ImGui::ColorMarkerEnd;
std::string flow = ImGui::ColorMarkerStart + _u8L("Flow: ") + ImGui::ColorMarkerEnd;
const float item_size = imgui.calc_text_size("X: 000.000 ").x;
const float item_spacing = imgui.get_item_spacing().x;
const float window_padding = ImGui::GetStyle().WindowPadding.x;
std::ostringstream buffer;
char buf[1024];
if (view_type == EViewType::Feedrate) {
auto it = std::find_if(moves.begin(), moves.end(), [&curr_line_id](auto move) {
if (move.gcode_id == curr_line_id)
return true;
else
return false;
});
if (it != moves.end()) {
switch (view_type){
case EViewType::Height: {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
sprintf(buf, "%s%.3f", z.c_str(), position.z());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.2f", height.c_str(), it->height);
ImGui::PushItemWidth(item_size);
imgui.text(buf);
break;
}
case EViewType::Width: {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
sprintf(buf, "%s%.3f", z.c_str(), position.z());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.2f", width.c_str(), it->width);
ImGui::PushItemWidth(item_size);
imgui.text(buf);
break;
}
case EViewType::Feedrate: {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
sprintf(buf, "%s%.3f", z.c_str(), position.z());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.2f", speed.c_str(), it->feedrate);
ImGui::PushItemWidth(item_size);
imgui.text(buf);
break;
}
case EViewType::VolumetricRate: {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
sprintf(buf, "%s%.3f", z.c_str(), position.z());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
ImGui::SameLine(window_padding + item_size + item_spacing);
sprintf(buf, "%s%.2f", flow.c_str(), it->volumetric_rate());
ImGui::PushItemWidth(item_size);
imgui.text(buf);
break;
}
default:
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
imgui.text(buf);
@ -372,54 +461,16 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.3f", z.c_str(), position.z());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.f", speed.c_str(), it->feedrate);
imgui.text(buf);
}
}
else if (view_type == EViewType::VolumetricRate) {
auto it = std::find_if(moves.begin(), moves.end(), [&curr_line_id](auto move) {
if (move.gcode_id == curr_line_id)
return true;
else
return false;
});
if (it != moves.end()) {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
imgui.text(buf);
sprintf(buf, "%s%.3f", z.c_str(), position.z());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.f", flow.c_str(), it->volumetric_rate());
imgui.text(buf);
}
}
else {
sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.3f", y.c_str(), position.y() - plate->get_origin().y());
imgui.text(buf);
ImGui::SameLine();
sprintf(buf, "%s%.3f", z.c_str() , position.z());
imgui.text(buf);
}
// force extra frame to automatically update window size
float width = ImGui::GetWindowWidth();
float window_width = ImGui::GetWindowWidth();
//size_t length = strlen(buf);
if (width != last_window_width /*|| length != last_text_length*/) {
last_window_width = width;
if (window_width != last_window_width /*|| length != last_text_length*/) {
last_window_width = window_width;
//last_text_length = length;
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
imgui.set_requires_extra_frame();
@ -3085,8 +3136,8 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p
const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
const PrintConfig& config = print.config();
if (print.enable_timelapse_print()
|| (extruders_count > 1 && config.enable_prime_tower && (config.print_sequence == PrintSequence::ByLayer))) {
if (config.enable_prime_tower &&
(print.enable_timelapse_print() || (extruders_count > 1 && (config.print_sequence == PrintSequence::ByLayer)))) {
const float depth = print.wipe_tower_data(extruders_count).depth;
const float brim_width = print.wipe_tower_data(extruders_count).brim_width;
@ -4703,7 +4754,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
append_option_item(item,offsets);
//BBS display filament change times
if (m_print_statistics.total_filamentchanges > 0) {
if (m_print_statistics.total_filamentchanges > 0 && ( total_flushed_filament_m > 0 || total_flushed_filament_g > 0)) {
std::string flushed_filament_title_str = _u8L("Flushed filament");
std::string flushed_filament_str = _u8L("Filament");
std::string total_flushed_filament_str = _u8L("Total");

View file

@ -1935,7 +1935,7 @@ 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 || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) {
if ((timelapse_enabled && wt) || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) {
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
float x = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->get_at(plate_id);
@ -1978,6 +1978,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_selection.volumes_changed(map_glvolume_old_to_new);
m_gizmos.update_data();
m_gizmos.update_assemble_view_data();
m_gizmos.refresh_on_off_state();
// Update the toolbar
@ -2409,6 +2410,10 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
{
//case WXK_BACK:
case WXK_DELETE: { post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; }
// BBS
#ifdef __APPLE__
case WXK_BACK: { post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; }
#endif
case WXK_ESCAPE: { deselect_all(); break; }
//case WXK_F5: {
// if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
@ -2661,6 +2666,12 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
#if !BBL_RELEASE_TO_PUBLIC
wxGetApp().plater()->toggle_render_statistic_dialog();
m_dirty = true;
#endif
}
else if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_RETURN) {
#if !BBL_RELEASE_TO_PUBLIC
wxGetApp().plater()->toggle_show_wireframe();
m_dirty = true;
#endif
}
else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
@ -2694,7 +2705,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
else if (keyCode == WXK_CONTROL)
m_dirty = true;
else if (m_gizmos.is_enabled() && !m_selection.is_empty()) {
else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
translationProcessor.process(evt);
//switch (keyCode)
@ -2774,7 +2785,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
else if (keyCode == WXK_CONTROL)
m_dirty = true;
else if (m_gizmos.is_enabled() && !m_selection.is_empty()) {
else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
// auto do_rotate = [this](double angle_z_rad) {
// m_selection.start_dragging();
// m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint));
@ -3351,6 +3362,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
//BBS do not limit rotate in assemble view
camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target);
//camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, rotate_target);
auto clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position();
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
}
else {
#ifdef SUPPORT_FEEE_CAMERA
@ -5720,7 +5733,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else
m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
if (m_canvas_type == CanvasAssembleView) {
m_volumes.set_clipping_plane(m_gizmos.get_assemble_view_clipping_plane().get_data());
}
else {
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
}
//BBS: remove sinking logic
//m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances());
@ -5761,6 +5779,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
shader->start_using();
}
}
break;
}
case GLVolumeCollection::ERenderType::Transparent:
@ -5774,6 +5793,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
return true;
}
}, with_outline);
if (m_canvas_type == CanvasAssembleView) {
const GLGizmosManager& gm = get_gizmos_manager();
shader->stop_using();
gm.render_painter_assemble_view();
shader->start_using();
}
break;
}
}
@ -5959,7 +5984,7 @@ void GLCanvas3D::_render_overlays()
_check_and_update_toolbar_icon_scale();
_render_explosion_control();
_render_assemble_control();
_render_assemble_info();
// main toolbar and undoredo toolbar need to be both updated before rendering because both their sizes are needed
@ -6167,6 +6192,8 @@ void GLCanvas3D::_render_gizmos_overlay()
const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale());
m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
#endif /* __WXMSW__ */
if (m_canvas_type == CanvasAssembleView)
return;
m_gizmos.render_overlay();
@ -6664,7 +6691,7 @@ void GLCanvas3D::_render_paint_toolbar() const
}
//BBS
void GLCanvas3D::_render_explosion_control() const
void GLCanvas3D::_render_assemble_control() const
{
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
@ -6679,26 +6706,45 @@ void GLCanvas3D::_render_explosion_control() const
auto canvas_h = float(get_canvas_size().get_height());
const float text_padding = 7.0f;
ImVec2 text_size = imgui->calc_text_size(_L("Explosion Ratio"));
const float slider_width = 130.0f;
const float text_size_x = std::max(imgui->calc_text_size(_L("Explosion Ratio")).x, imgui->calc_text_size(_L("Section View")).x);
const float slider_width = 75.0f;
const float value_size = imgui->calc_text_size("3.00").x + text_padding * 2;
const float item_spacing = imgui->get_item_spacing().x;
ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
ImVec2 window_size = ImVec2(text_size.x + slider_width + value_size + item_spacing * 2 + window_padding.x * 2, window_padding.y * 2 + text_size.y);
// 13.0f is bottom margin
imgui->set_next_window_pos(canvas_w * 0.5 - window_size.x * 0.5, canvas_h - window_size.y - 13.0f, ImGuiCond_Always, 0.0f, 0.0f);
imgui->begin(_L("Explosion Ratio"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
imgui->set_next_window_pos(canvas_w / 2, canvas_h - 13.0f * get_scale(), ImGuiCond_Always, 0.5f, 1.0f);
imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::AlignTextToFramePadding();
imgui->text(_L("Explosion Ratio"));
ImGui::SameLine(window_padding.x + text_size.x + item_spacing);
ImGui::PushItemWidth(slider_width);
bool slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
ImGui::SameLine(window_padding.x + text_size.x + slider_width + item_spacing * 2);
ImGui::PushItemWidth(value_size);
bool input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
{
imgui->text(_L("Section View"));
ImGui::SameLine(window_padding.x + text_size_x + item_spacing);
ImGui::PushItemWidth(slider_width);
static float clp_dist = 0.f;
bool view_slider_changed = imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 2);
ImGui::PushItemWidth(value_size);
bool view_input_changed = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
if (view_slider_changed || view_input_changed)
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
}
{
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 6 + value_size);
imgui->text(_L("Explosion Ratio"));
ImGui::SameLine(window_padding.x + 2 * text_size_x + slider_width + item_spacing * 7 + value_size);
ImGui::PushItemWidth(slider_width);
bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
ImGui::SameLine(window_padding.x + 2 * text_size_x + 2 * slider_width + item_spacing * 8 + value_size);
ImGui::PushItemWidth(value_size);
bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
}
imgui->end();

View file

@ -978,7 +978,7 @@ private:
// BBS
//void _render_view_toolbar() const;
void _render_paint_toolbar() const;
void _render_explosion_control() const;
void _render_assemble_control() const;
void _render_assemble_info() const;
#if ENABLE_SHOW_CAMERA_TARGET
void _render_camera_target() const;

View file

@ -45,11 +45,20 @@ std::pair<bool, std::string> GLShadersManager::init()
// used to render extrusion and travel paths as lines in gcode preview
valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" });
// used to render objects in 3d editor
valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" }
if (0) {
valid &= append_shader("gouraud", { "gouraud_130.vs", "gouraud_130.fs" }
#if ENABLE_ENVIRONMENT_MAP
, { "ENABLE_ENVIRONMENT_MAP"sv }
#endif // ENABLE_ENVIRONMENT_MAP
);
}
else {
valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" }
#if ENABLE_ENVIRONMENT_MAP
, { "ENABLE_ENVIRONMENT_MAP"sv }
#endif // ENABLE_ENVIRONMENT_MAP
);
}
// used to render variable layers heights in 3d editor
valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" });
// used to render highlight contour around selected triangles inside the multi-material gizmo

View file

@ -25,8 +25,10 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_ALL, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_PLATE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_EXPORT_GCODE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_GCODE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_UPLOAD_GCODE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_EXPORT_SLICED_FILE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);

View file

@ -25,8 +25,10 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_PLATE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_EXPORT_GCODE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_GCODE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_UPLOAD_GCODE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_EXPORT_SLICED_FILE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);

View file

@ -280,6 +280,15 @@ public:
memDc.SetTextForeground(wxColor(134, 134, 134));
memDc.DrawLabel(m_constant_text.version, version_rect, wxALIGN_LEFT | wxALIGN_BOTTOM);
#if BBL_INTERNAL_TESTING
wxSize text_rect = memDc.GetTextExtent("Internal Version");
int start_x = (title_rect.GetLeft() + version_rect.GetRight()) / 2 - text_rect.GetWidth();
int start_y = version_rect.GetBottom() + 10;
wxRect internal_sign_rect(wxPoint(start_x, start_y), wxSize(text_rect));
memDc.SetFont(m_constant_text.title_font);
memDc.DrawLabel("Internal Version", internal_sign_rect, wxALIGN_TOP | wxALIGN_LEFT);
#endif
// load bitmap for logo
BitmapCache bmp_cache;
int logo_margin = FromDIP(72 * m_scale);
@ -545,7 +554,11 @@ private:
title = wxGetApp().is_editor() ? SLIC3R_APP_FULL_NAME : GCODEVIEWER_APP_NAME;
// dynamically get the version to display
#if BBL_INTERNAL_TESTING
version = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
#else
version = _L("Version") + " " + std::string(SLIC3R_VERSION);
#endif
// credits infornation
credits = title;
@ -1052,9 +1065,9 @@ void GUI_App::post_init()
}*/
// BBS: to be checked
#if SUPPORT_SHOW_HINTS
#if 1
// show "Did you know" notification
if (app_config->get("show_hints") == "1" && ! is_gcode_viewer())
if (app_config->get("show_hints") == "true" && ! is_gcode_viewer())
plater_->get_notification_manager()->push_hint_notification(true);
#endif
@ -1176,13 +1189,14 @@ GUI_App::GUI_App()
{
//app config initializes early becasuse it is used in instance checking in BambuStudio.cpp
this->init_app_config();
this->init_download_path();
reset_to_active();
}
void GUI_App::shutdown()
{
BOOST_LOG_TRIVIAL(info) << "shutdown";
BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown enter";
if (m_removable_drive_manager) {
removable_drive_manager()->shutdown();
@ -1202,6 +1216,7 @@ void GUI_App::shutdown()
delete m_agent;
m_agent = nullptr;
}
BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown exit";
}
@ -1608,6 +1623,8 @@ void GUI_App::init_networking_callbacks()
return;
}
GUI::wxGetApp().CallAfter([this] {
if (m_is_closing)
return;
BOOST_LOG_TRIVIAL(trace) << "static: server connected";
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
});
@ -1618,6 +1635,8 @@ void GUI_App::init_networking_callbacks()
return;
}
GUI::wxGetApp().CallAfter([this, dev_id] {
if (m_is_closing)
return;
/* request_pushing */
MachineObject* obj = m_device_manager->get_my_machine(dev_id);
if (obj) {
@ -1677,6 +1696,8 @@ void GUI_App::init_networking_callbacks()
return;
}
CallAfter([this, dev_id, msg] {
if (m_is_closing)
return;
MachineObject* obj = this->m_device_manager->get_user_machine(dev_id);
if (obj) {
obj->is_ams_need_update = false;
@ -1696,6 +1717,8 @@ void GUI_App::init_networking_callbacks()
return;
}
CallAfter([this, dev_id, msg] {
if (m_is_closing)
return;
MachineObject* obj = m_device_manager->get_my_machine(dev_id);
if (!obj) {
obj = m_device_manager->get_local_machine(dev_id);
@ -1766,6 +1789,26 @@ static boost::optional<Semver> parse_semver_from_ini(std::string path)
return Semver::parse(body);
}
void GUI_App::init_download_path()
{
std::string down_path = app_config->get("download_path");
if (down_path.empty()) {
std::string user_down_path = wxStandardPaths::Get().GetUserDir(wxStandardPaths::Dir_Downloads).ToUTF8().data();
app_config->set("download_path", user_down_path);
}
else {
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);
}
}
}
}
void GUI_App::init_app_config()
{
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
@ -1899,7 +1942,8 @@ bool GUI_App::on_init_inner()
std::time_t t = std::time(0);
std::tm* now_time = std::localtime(&t);
std::stringstream buf;
buf << std::put_time(now_time, "debug_%a_%b_%d_%H_%M_%S.log");
buf << std::put_time(now_time, "debug_%a_%b_%d_%H_%M_%S_");
buf << get_current_pid() << ".log";
std::string log_filename = buf.str();
#if !BBL_RELEASE_TO_PUBLIC
set_log_path_and_level(log_filename, 5);
@ -1929,6 +1973,7 @@ bool GUI_App::on_init_inner()
#endif
wxGetApp().Bind(wxEVT_QUERY_END_SESSION, [this](auto & e) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< "received wxEVT_QUERY_END_SESSION";
if (mainframe) {
wxCloseEvent e2(wxEVT_CLOSE_WINDOW);
e2.SetCanVeto(true);
@ -2097,8 +2142,9 @@ bool GUI_App::on_init_inner()
if (!skip_this_version
|| evt.GetInt() != 0) {
UpdateVersionDialog dialog(this->mainframe);
//dialog.update_version_info(extmsg, version_info.version_str);
dialog.update_version_info(version_info.description);
wxString extmsg = wxString::FromUTF8(version_info.description);
dialog.update_version_info(extmsg, version_info.version_str);
//dialog.update_version_info(version_info.description);
if (evt.GetInt() != 0) {
dialog.m_remind_choice->Hide();
}
@ -2719,6 +2765,7 @@ void GUI_App::check_printer_presets()
void GUI_App::recreate_GUI(const wxString& msg_name)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "recreate_GUI enter";
m_is_recreating_gui = true;
mainframe->shutdown();
@ -2766,6 +2813,8 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
// });
m_is_recreating_gui = false;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "recreate_GUI exit";
}
void GUI_App::system_info()
@ -2925,6 +2974,7 @@ void GUI_App::persist_window_geometry(wxTopLevelWindow *window, bool default_max
const std::string name = into_u8(window->GetName());
window->Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent &event) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": received wxEVT_CLOSE_WINDOW, trigger save for window_mainframe";
window_pos_save(window, "mainframe");
event.Skip();
});

View file

@ -305,7 +305,8 @@ public:
wxGLContext* init_glcontext(wxGLCanvas& canvas);
bool init_opengl();
static unsigned get_colour_approx_luma(const wxColour &colour);
void init_download_path();
static unsigned get_colour_approx_luma(const wxColour& colour);
static bool dark_mode();
const wxColour get_label_default_clr_system();
const wxColour get_label_default_clr_modified();

View file

@ -181,8 +181,7 @@ ObjectList::ObjectList(wxWindow* parent) :
entries[index++].Set(wxACCEL_CTRL, (int)'A', wxID_SELECTALL);
entries[index++].Set(wxACCEL_CTRL, (int)'Z', wxID_UNDO);
entries[index++].Set(wxACCEL_CTRL, (int)'Y', wxID_REDO);
entries[index++].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
//entries[index++].Set(wxACCEL_NORMAL, WXK_BACK, wxID_DELETE);
entries[index++].Set(wxACCEL_NORMAL, WXK_BACK, wxID_DELETE);
//entries[index++].Set(wxACCEL_NORMAL, int('+'), wxID_ADD);
//entries[index++].Set(wxACCEL_NORMAL, WXK_NUMPAD_ADD, wxID_ADD);
//entries[index++].Set(wxACCEL_NORMAL, int('-'), wxID_REMOVE);
@ -5041,6 +5040,15 @@ void ObjectList::apply_object_instance_transfrom_to_all_volumes(ModelObject *mod
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);
// apply the instance_transform to volumn
const Transform3d &transformation_matrix = instance_transformation.get_matrix();
for (ModelVolume *volume : model_object->volumes) {
const Transform3d &volume_matrix = volume->get_matrix();

View file

@ -2681,6 +2681,7 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
SetSize(wxSize(-1, FromDIP(450)));
SetMinSize(wxSize(-1, FromDIP(450)));
SetMaxSize(wxSize(-1, FromDIP(450)));
//m_search_line = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
@ -3228,7 +3229,7 @@ void ObjectTablePanel::resetAllValuesInSideWindow(int row, bool is_object, Model
// ObjectTableDialog
// ----------------------------------------------------------------------------
ObjectTableDialog::ObjectTableDialog(wxWindow* parent, Plater* platerObj, Model *modelObj, wxSize maxSize)
: GUI::DPIDialog(parent, wxID_ANY, _L("Object/Part Setting"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
: GUI::DPIDialog(parent, wxID_ANY, _L("Object/Part Setting"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
,
m_model(modelObj), m_plater(platerObj)
{
@ -3369,12 +3370,27 @@ void ObjectTableDialog::OnText(wxKeyEvent &evt)
void ObjectTableDialog::OnSize(wxSizeEvent& event)
{
wxSize new_size = event.GetSize();
/* wxSize new_size = event.GetSize();
if ((new_size.GetWidth() > g_dialog_max_width) || (new_size.GetHeight() > g_dialog_max_height)) {
int width = (new_size.GetWidth() > g_dialog_max_width) ? new_size.GetWidth() : g_dialog_max_width;
int width = (new_size.GetWidth() > g_dialog_max_width) ? new_size.GetWidth() : g_dialog_max_width;
int height = (new_size.GetHeight() > g_dialog_max_height) ? new_size.GetHeight() : g_dialog_max_height;
this->SetMaxSize(wxSize(width, height));
}*/
if (event.GetSize().y <= FromDIP(450)) {
SetMaxSize(wxSize(GetSize().x, -1));
SetMinSize(wxSize(GetSize().x, -1));
SetSize(wxSize(GetSize().x, -1));
return;
}
SetMaxSize(wxSize(GetSize().x, -1));
SetMinSize(wxSize(GetSize().x, -1));
SetSize(wxSize(GetSize().x, -1));
m_obj_panel->SetSize(wxSize(-1, GetSize().y));
m_obj_panel->SetMinSize(wxSize(-1, GetSize().y));
m_obj_panel->SetMaxSize(wxSize(-1, GetSize().y));
event.Skip();
}

View file

@ -506,7 +506,8 @@ void Preview::update_layers_slider_from_canvas(wxKeyEvent &event)
IMSlider *m_layers_slider = m_canvas->get_gcode_viewer().get_layers_slider();
IMSlider *m_moves_slider = m_canvas->get_gcode_viewer().get_moves_slider();
if (key == 'L') {
m_layers_slider->switch_one_layer_mode();
if(!m_layers_slider->switch_one_layer_mode())
event.Skip();
m_canvas->set_as_dirty();
}
/*else if (key == WXK_SHIFT)
@ -767,7 +768,7 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint
m_canvas->set_process(process);
m_canvas->set_type(GLCanvas3D::ECanvasType::CanvasAssembleView);
m_canvas->set_config(config);
m_canvas->enable_gizmos(false);
m_canvas->enable_gizmos(true);
m_canvas->enable_selection(true);
m_canvas->enable_main_toolbar(false);
m_canvas->enable_labels(false);

View file

@ -438,7 +438,7 @@ void GLGizmoAdvancedCut::on_render_input_window(float x, float y, float bottom_l
// Rotation input box
ImGui::PushItemWidth(caption_size);
m_imgui->text(_L("Rotation:"));
m_imgui->text(_L("Rotation") + " ");
ImGui::SameLine(caption_size + 1 * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::BBLInputDouble("##cut_rotation_x", &rotation[0], 0.0f, 0.0f, "%.2f");
@ -471,7 +471,7 @@ void GLGizmoAdvancedCut::on_render_input_window(float x, float y, float bottom_l
double movement = m_movement;
ImGui::PushItemWidth(caption_size);
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Movement:"));
m_imgui->text(_L("Movement") + " ");
ImGui::SameLine(caption_size + 1 * space_size);
ImGui::PushItemWidth(3 * unit_size + 2 * space_size);
ImGui::BBLInputDouble("##cut_movement", &movement, 0.0f, 0.0f, "%.2f");
@ -497,7 +497,7 @@ void GLGizmoAdvancedCut::on_render_input_window(float x, float y, float bottom_l
double height = m_height;
ImGui::PushItemWidth(caption_size);
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Height:"));
m_imgui->text(_L("Height") + " ");
ImGui::SameLine(caption_size + 1 * space_size);
ImGui::PushItemWidth(3 * unit_size + 2 * space_size);
ImGui::BBLInputDouble("##cut_height", &height, 0.0f, 0.0f, "%.2f");

View file

@ -79,23 +79,25 @@ bool GLGizmoFdmSupports::on_init()
// BBS
m_shortcut_key = WXK_CONTROL_L;
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["cursor_size"] = _L("Pen size") + ": ";
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
m_desc["clipping_of_view_caption"] = _L("Alt + Mouse wheel");
m_desc["clipping_of_view"] = _L("Section view");
m_desc["cursor_size_caption"] = _L("Ctrl + Mouse wheel");
m_desc["cursor_size"] = _L("Pen size");
m_desc["enforce_caption"] = _L("Left mouse button");
m_desc["enforce"] = _L("Enforce supports");
m_desc["block_caption"] = _L("Right mouse button") + ": ";
m_desc["block_caption"] = _L("Right mouse button");
m_desc["block"] = _L("Block supports");
m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": ";
m_desc["remove"] = _L("Erase painting");
m_desc["remove_caption"] = _L("Shift + Left mouse button");
m_desc["remove"] = _L("Erase");
m_desc["remove_all"] = _L("Erase all painting");
m_desc["highlight_by_angle"] = _L("Highlight overhang areas") + ": ";
m_desc["highlight_by_angle"] = _L("Highlight overhang areas");
m_desc["gap_fill"] = _L("Gap fill");
m_desc["perform"] = _L("Perform");
m_desc["gap_area_caption"] = _L("Ctrl + Mouse wheel");
m_desc["gap_area"] = _L("Gap area");
m_desc["brush_size"] = _L("Set pen size");
m_desc["brush_size_caption"] = _L("Ctrl + Mouse wheel") + ": ";
m_desc["tool_type"] = _L("Tool type");
m_desc["smart_fill_angle"] = _L("Smart fill angle") + ": ";
m_desc["smart_fill_angle_caption"] = _L("Ctrl + Mouse wheel");
m_desc["smart_fill_angle"] = _L("Smart fill angle");
memset(&m_print_instance, sizeof(m_print_instance), 0);
return true;
@ -224,7 +226,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
float caption_max = 0.f;
float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 4>{"enforce", "block", "remove", "brush_size"}) {
for (const auto &t : std::array<std::string, 5>{"enforce", "block", "remove", "cursor_size", "clipping_of_view"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
}
@ -461,6 +463,8 @@ void GLGizmoFdmSupports::show_tooltip_information(float caption_max, float x, fl
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 15.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
@ -475,7 +479,24 @@ void GLGizmoFdmSupports::show_tooltip_information(float caption_max, float x, fl
m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
};
for (const auto &t : std::array<std::string, 4>{"enforce", "block", "remove", "brush_size"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
std::vector<std::string> tip_items;
switch (m_tool_type) {
case ToolType::BRUSH:
tip_items = {"enforce", "block", "remove", "cursor_size", "clipping_of_view"};
break;
case ToolType::BUCKET_FILL:
break;
case ToolType::SMART_FILL:
tip_items = {"enforce", "block", "remove", "smart_fill_angle", "clipping_of_view"};
break;
case ToolType::GAP_FILL:
tip_items = {"gap_area"};
break;
default:
break;
}
for (const auto &t : tip_items) draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t));
ImGui::EndTooltip();
}
ImGui::PopStyleVar(1);

View file

@ -97,18 +97,20 @@ bool GLGizmoMmuSegmentation::on_init()
// BBS
m_shortcut_key = WXK_CONTROL_N;
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["cursor_size"] = _L("Pen size") + ": ";
m_desc["clipping_of_view_caption"] = _L("Alt + Mouse wheel");
m_desc["clipping_of_view"] = _L("Section view");
m_desc["cursor_size_caption"] = _L("Ctrl + Mouse wheel");
m_desc["cursor_size"] = _L("Pen size");
m_desc["cursor_type"] = _L("Pen shape");
// BBS
m_desc["paint_caption"] = _L("Left mouse button") + ": ";
m_desc["paint_caption"] = _L("Left mouse button");
m_desc["paint"] = _L("Paint");
m_desc["erase_caption"] = _L("Right mouse button") + ": ";
m_desc["erase_caption"] = _L("Shift + Left mouse button");
m_desc["erase"] = _L("Erase");
m_desc["shortcut_key_caption"] = _L("Key 1~9") + ": ";
m_desc["shortcut_key_caption"] = _L("Key 1~9");
m_desc["shortcut_key"] = _L("Choose filament");
m_desc["edge_detection"] = _L("Edge detection");
m_desc["gap_area_caption"] = _L("Ctrl + Mouse wheel");
m_desc["gap_area"] = _L("Gap area");
m_desc["perform"] = _L("Perform");
@ -123,12 +125,10 @@ bool GLGizmoMmuSegmentation::on_init()
m_desc["tool_smart_fill"] = _L("Smart fill");
m_desc["tool_bucket_fill"] = _L("Bucket fill");
m_desc["smart_fill_angle_caption"] = _L("Ctrl + Mouse wheel");
m_desc["smart_fill_angle"] = _L("Smart fill angle");
m_desc["brush_size"] = _L("Set pen size");
m_desc["brush_size_caption"] = _L("Ctrl + Mouse wheel") + ": ";
// BBS
m_desc["height_range_caption"] = _L("Ctrl + Mouse wheel");
m_desc["height_range"] = _L("Height range");
init_extruders_data();
@ -297,6 +297,8 @@ void GLGizmoMmuSegmentation::show_tooltip_information(float caption_max, float x
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 15.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
@ -310,7 +312,24 @@ void GLGizmoMmuSegmentation::show_tooltip_information(float caption_max, float x
m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
};
for (const auto &t : std::array<std::string, 3>{"paint", "erase", "brush_size"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
std::vector<std::string> tip_items;
switch (m_tool_type) {
case ToolType::BRUSH:
tip_items = {"paint", "erase", "cursor_size", "clipping_of_view"};
break;
case ToolType::BUCKET_FILL:
tip_items = {"paint", "erase", "smart_fill_angle", "clipping_of_view"};
break;
case ToolType::SMART_FILL:
// TODO:
break;
case ToolType::GAP_FILL:
tip_items = {"gap_area"};
break;
default:
break;
}
for (const auto &t : tip_items) draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t));
ImGui::EndTooltip();
}
ImGui::PopStyleVar(1);
@ -347,7 +366,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
float caption_max = 0.f;
float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 3>{"paint", "erase", "brush_size"}) {
for (const auto &t : std::array<std::string, 6>{"paint", "erase", "cursor_size", "smart_fill_angle", "height_range", "clipping_of_view"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
}
@ -537,7 +556,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
if (m_detect_geometry_edge) {
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc["smart_fill_angle"] + ":");
m_imgui->text(m_desc["smart_fill_angle"]);
std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Face angle threshold,"
"placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_left_width);

View file

@ -90,7 +90,7 @@ protected:
void on_set_state() override;
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_selected_extruder_idx + 1); }
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType::NONE; }
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(-1); }
void on_render_input_window(float x, float y, float bottom_limit) override;
std::string on_get_name() const override;

View file

@ -495,21 +495,22 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
if (action == SLAGizmoEventType::MouseWheelUp
|| action == SLAGizmoEventType::MouseWheelDown) {
if (control_down) {
//BBS
if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::HEIGHT_RANGE) {
m_cursor_height = action == SLAGizmoEventType::MouseWheelDown ? std::max(m_cursor_height - this->get_cursor_height_step(), this->get_cursor_height_min()) :
std::min(m_cursor_height + this->get_cursor_height_step(), this->get_cursor_height_max());
m_parent.set_as_dirty();
return true;
}
if (m_tool_type == ToolType::BRUSH && (m_cursor_type == TriangleSelector::CursorType::SPHERE || m_cursor_type == TriangleSelector::CursorType::CIRCLE)) {
m_cursor_radius = action == SLAGizmoEventType::MouseWheelDown ? std::max(m_cursor_radius - this->get_cursor_radius_step(), this->get_cursor_radius_min()) :
std::min(m_cursor_radius + this->get_cursor_radius_step(), this->get_cursor_radius_max());
m_parent.set_as_dirty();
return true;
}
double pos = m_c->object_clipper()->get_position();
pos = action == SLAGizmoEventType::MouseWheelDown
? std::max(0., pos - 0.01)
: std::min(1., pos + 0.01);
m_c->object_clipper()->set_position(pos, true);
return true;
}
else if (alt_down) {
if (m_tool_type == ToolType::SMART_FILL) {
if (m_tool_type == ToolType::BUCKET_FILL || m_tool_type == ToolType::SMART_FILL) {
m_smart_fill_angle = action == SLAGizmoEventType::MouseWheelDown ? std::max(m_smart_fill_angle - SmartFillAngleStep, SmartFillAngleMin)
: std::min(m_smart_fill_angle + SmartFillAngleStep, SmartFillAngleMax);
m_parent.set_as_dirty();
@ -527,7 +528,22 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
return true;
}
return false;
if (m_tool_type == ToolType::GAP_FILL) {
TriangleSelectorPatch::gap_area = action == SLAGizmoEventType::MouseWheelDown ?
std::max(TriangleSelectorPatch::gap_area - TriangleSelectorPatch::GapAreaStep, TriangleSelectorPatch::GapAreaMin) :
std::min(TriangleSelectorPatch::gap_area + TriangleSelectorPatch::GapAreaStep, TriangleSelectorPatch::GapAreaMax);
m_parent.set_as_dirty();
return true;
}
}
else if (alt_down) {
// BBS
double pos = m_c->object_clipper()->get_position();
pos = action == SLAGizmoEventType::MouseWheelDown
? std::max(0., pos - 0.01)
: std::min(1., pos + 0.01);
m_c->object_clipper()->set_position(pos, true);
return true;
}
}
@ -544,6 +560,16 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
return false;
EnforcerBlockerType new_state = EnforcerBlockerType::NONE;
// BBS
if (action == SLAGizmoEventType::Dragging) {
if (m_button_down == Button::Right && this->get_right_button_state_type() == EnforcerBlockerType(-1))
return false;
}
else {
if (action == SLAGizmoEventType::RightDown && this->get_right_button_state_type() == EnforcerBlockerType(-1))
return false;
}
if (! shift_down) {
if (action == SLAGizmoEventType::Dragging)
new_state = m_button_down == Button::Left ? this->get_left_button_state_type() : this->get_right_button_state_type();

View file

@ -142,6 +142,7 @@ public:
constexpr static float GapAreaMin = 0.f;
constexpr static float GapAreaMax = 5.f;
constexpr static float GapAreaStep = 0.2f;
// BBS: fix me
static float gap_area;

View file

@ -120,16 +120,6 @@ void GLGizmoScale3D::on_start_dragging()
void GLGizmoScale3D::on_update(const UpdateData& data)
{
bool uniform_scale = false;
AppConfig* config = wxGetApp().app_config;
if (config)
uniform_scale = config->get("uniform_scale") == "1" ? true : false;
if (uniform_scale) {
do_scale_uniform(data);
return;
}
if ((m_hover_id == 0) || (m_hover_id == 1))
do_scale_along_axis(X, data);
else if ((m_hover_id == 2) || (m_hover_id == 3))

View file

@ -29,16 +29,18 @@ bool GLGizmoSeam::on_init()
{
m_shortcut_key = WXK_CONTROL_P;
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["clipping_of_view_caption"] = _L("Alt + Mouse wheel");
m_desc["clipping_of_view"] = _L("Section view");
m_desc["reset_direction"] = _L("Reset direction");
m_desc["cursor_size"] = _L("Brush size") + ": ";
m_desc["cursor_type"] = _L("Brush shape") + ": ";
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
m_desc["cursor_size_caption"] = _L("Ctrl + Mouse wheel");
m_desc["cursor_size"] = _L("Brush size");
m_desc["cursor_type"] = _L("Brush shape");
m_desc["enforce_caption"] = _L("Left mouse button");
m_desc["enforce"] = _L("Enforce seam");
m_desc["block_caption"] = _L("Right mouse button") + ": ";
m_desc["block_caption"] = _L("Right mouse button");
m_desc["block"] = _L("Block seam");
m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": ";
m_desc["remove"] = _L("Remove selection");
m_desc["remove_caption"] = _L("Shift + Left mouse button");
m_desc["remove"] = _L("Erase");
m_desc["remove_all"] = _L("Erase all painting");
m_desc["circle"] = _L("Circle");
m_desc["sphere"] = _L("Sphere");
@ -125,6 +127,8 @@ void GLGizmoSeam::show_tooltip_information(float caption_max, float x, float y)
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 35.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
@ -138,7 +142,7 @@ void GLGizmoSeam::show_tooltip_information(float caption_max, float x, float y)
m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
};
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
for (const auto &t : std::array<std::string, 5>{"enforce", "block", "remove", "cursor_size", "clipping_of_view"}) draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t));
ImGui::EndTooltip();
}
ImGui::PopStyleVar(1);
@ -187,7 +191,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
float caption_max = 0.f;
float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) {
for (const auto &t : std::array<std::string, 6>{"enforce", "block", "remove", "cursor_size", "clipping_of_view"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
}

View file

@ -141,35 +141,6 @@ std::string GLGizmoSimplify::on_get_name() const
return _u8L("Simplify");
}
void GLGizmoSimplify::push_simplify_style()
{
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, ImVec2(0.05f, 0.50f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(50 / 255.0f, 58 / 255.0f, 61 / 255.0f, 1.00f)); // 1
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGuiWrapper::COL_WINDOW_BG); // 2
ImGui::PushStyleColor(ImGuiCol_TitleBg, ImGuiWrapper::COL_TITLE_BG); // 3
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, ImGuiWrapper::COL_TITLE_BG); // 4
ImGui::PushStyleColor(ImGuiCol_Separator, ImGuiWrapper::COL_SEPARATOR); // 5
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.00f, 1.00f, 1.00f, 1.00f)); // 6
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); // 7
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); // 8
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 9
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 10
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f)); // 11
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.00f, 1.00f, 1.00f, 1.00f)); // 12
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, ImGuiWrapper::COL_GREEN_LIGHT);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
}
void GLGizmoSimplify::pop_simplify_style()
{
ImGui::PopStyleColor(14);
ImGui::PopStyleVar(5);
}
void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limit)
{
create_gui_cfg();
@ -260,7 +231,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
float slider_width = m_imgui->scaled(5.0f);
push_simplify_style();
m_imgui->push_common_window_style(m_parent.get_scale());
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse;
m_imgui->begin(on_get_name(), flag);
@ -412,7 +383,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
ImGui::PopStyleColor(1);
m_imgui->end();
pop_simplify_style();
m_imgui->pop_common_window_style();
if (start_process)
process();
}

View file

@ -48,8 +48,6 @@ private:
void process();
void stop_worker_thread_request();
void worker_finished();
void push_simplify_style();
void pop_simplify_style();
void create_gui_cfg();
void request_rerender(bool force = false);

View file

@ -541,5 +541,172 @@ void SupportsClipper::render_cut() const
}
using namespace AssembleViewDataObjects;
AssembleViewDataPool::AssembleViewDataPool(GLCanvas3D* canvas)
: m_canvas(canvas)
{
using c = AssembleViewDataID;
m_data[c::ModelObjectsInfo].reset(new ModelObjectsInfo(this));
m_data[c::ModelObjectsClipper].reset(new ModelObjectsClipper(this));
}
void AssembleViewDataPool::update(AssembleViewDataID required)
{
assert(check_dependencies(required));
for (auto& [id, data] : m_data) {
if (int(required) & int(AssembleViewDataID(id)))
data->update();
else
if (data->is_valid())
data->release();
}
}
ModelObjectsInfo* AssembleViewDataPool::model_objects_info() const
{
ModelObjectsInfo* sel_info = dynamic_cast<ModelObjectsInfo*>(m_data.at(AssembleViewDataID::ModelObjectsInfo).get());
assert(sel_info);
return sel_info->is_valid() ? sel_info : nullptr;
}
ModelObjectsClipper* AssembleViewDataPool::model_objects_clipper() const
{
ModelObjectsClipper* oc = dynamic_cast<ModelObjectsClipper*>(m_data.at(AssembleViewDataID::ModelObjectsClipper).get());
// ObjectClipper is used from outside the gizmos to report current clipping plane.
// This function can be called when oc is nullptr.
return (oc && oc->is_valid()) ? oc : nullptr;
}
#ifndef NDEBUG
// Check the required resources one by one and return true if all
// dependencies are met.
bool AssembleViewDataPool::check_dependencies(AssembleViewDataID required) const
{
// This should iterate over currently required data. Each of them should
// be asked about its dependencies and it must check that all dependencies
// are also in required and before the current one.
for (auto& [id, data] : m_data) {
// in case we don't use this, the deps are irrelevant
if (!(int(required) & int(AssembleViewDataID(id))))
continue;
AssembleViewDataID deps = data->get_dependencies();
assert(int(deps) == (int(deps) & int(required)));
}
return true;
}
#endif // NDEBUG
void ModelObjectsInfo::on_update()
{
if (!get_pool()->get_canvas()->get_model()->objects.empty()) {
m_model_objects = get_pool()->get_canvas()->get_model()->objects;
}
}
void ModelObjectsInfo::on_release()
{
m_model_objects.clear();
}
//int ModelObjectsInfo::get_active_instance() const
//{
// const Selection& selection = get_pool()->get_canvas()->get_selection();
// return selection.get_instance_idx();
//}
void ModelObjectsClipper::on_update()
{
const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects();
if (model_objects.empty())
return;
// which mesh should be cut?
std::vector<const TriangleMesh*> meshes;
if (meshes.empty())
for (auto mo : model_objects) {
for (const ModelVolume* mv : mo->volumes)
meshes.push_back(&mv->mesh());
}
if (meshes != m_old_meshes) {
m_clippers.clear();
for (const TriangleMesh* mesh : meshes) {
m_clippers.emplace_back(new MeshClipper);
m_clippers.back()->set_mesh(*mesh);
}
m_old_meshes = meshes;
m_active_inst_bb_radius = get_pool()->get_canvas()->volumes_bounding_box().radius();
}
}
void ModelObjectsClipper::on_release()
{
m_clippers.clear();
m_old_meshes.clear();
m_clp.reset();
m_clp_ratio = 0.;
}
void ModelObjectsClipper::render_cut() const
{
if (m_clp_ratio == 0.)
return;
const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects();
size_t clipper_id = 0;
for (const ModelObject* mo : model_objects) {
Geometry::Transformation assemble_objects_trafo = mo->instances[0]->get_assemble_transformation();
auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly();
for (const ModelVolume* mv : mo->volumes) {
Geometry::Transformation vol_trafo = mv->get_transformation();
Geometry::Transformation trafo = assemble_objects_trafo * vol_trafo;
trafo.set_offset(trafo.get_offset() + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0) + offset_to_assembly * (GLVolume::explosion_ratio - 1.0));
auto& clipper = m_clippers[clipper_id];
clipper->set_plane(*m_clp);
clipper->set_transformation(trafo);
glsafe(::glPushMatrix());
// BBS
glsafe(::glColor3f(0.25f, 0.25f, 0.25f));
clipper->render_cut();
glsafe(::glPopMatrix());
++clipper_id;
}
}
}
void ModelObjectsClipper::set_position(double pos, bool keep_normal)
{
Vec3d camera_dir = wxGetApp().plater()->get_camera().get_dir_forward();
Vec3d normal = -camera_dir;
const Vec3d& center = get_pool()->get_canvas()->volumes_bounding_box().center();
float dist = normal.dot(center);
if (pos < 0.)
pos = m_clp_ratio;
m_clp_ratio = pos;
m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius * GLVolume::explosion_ratio) - m_clp_ratio * 2 * m_active_inst_bb_radius * GLVolume::explosion_ratio)));
get_pool()->get_canvas()->set_as_dirty();
}
} // namespace GUI
} // namespace Slic3r

View file

@ -39,6 +39,7 @@ enum class SLAGizmoEventType : unsigned char {
class CommonGizmosDataBase;
class AssembleViewDataBase;
namespace CommonGizmosDataObjects {
class SelectionInfo;
class InstancesHider;
@ -48,6 +49,11 @@ namespace CommonGizmosDataObjects {
class SupportsClipper;
}
namespace AssembleViewDataObjects {
class ModelObjectsInfo;
class ModelObjectsClipper;
}
// Some of the gizmos use the same data that need to be updated ocassionally.
// It is also desirable that the data are not recalculated when the gizmos
// are just switched, but on the other hand, they should be released when
@ -306,9 +312,120 @@ private:
} // namespace CommonGizmosDataObjects
enum class AssembleViewDataID {
None = 0,
ModelObjectsInfo = 1 << 0,
ModelObjectsClipper = 1 << 4,
};
class AssembleViewDataPool {
public:
AssembleViewDataPool(GLCanvas3D* canvas);
// Update all resources and release what is not used.
// Accepts a bitmask of currently required resources.
void update(AssembleViewDataID required);
// Getters for the data that need to be accessed from the gizmos directly.
AssembleViewDataObjects::ModelObjectsInfo* model_objects_info() const;
AssembleViewDataObjects::ModelObjectsClipper* model_objects_clipper() const;
GLCanvas3D* get_canvas() const { return m_canvas; }
private:
std::map<AssembleViewDataID, std::unique_ptr<AssembleViewDataBase>> m_data;
GLCanvas3D* m_canvas;
#ifndef NDEBUG
bool check_dependencies(AssembleViewDataID required) const;
#endif
};
// Base class for a wrapper object managing a single resource.
// Each of the enum values above (safe None) will have an object of this kind.
class AssembleViewDataBase {
public:
// Pass a backpointer to the pool, so the individual
// objects can communicate with one another.
explicit AssembleViewDataBase(AssembleViewDataPool* cgdp)
: m_common{ cgdp } {}
virtual ~AssembleViewDataBase() {}
// Update the resource.
void update() { on_update(); m_is_valid = true; }
// Release any data that are stored internally.
void release() { on_release(); m_is_valid = false; }
// Returns whether the resource is currently maintained.
bool is_valid() const { return m_is_valid; }
#ifndef NDEBUG
// Return a bitmask of all resources that this one relies on.
// The dependent resource must have higher ID than the one
// it depends on.
virtual AssembleViewDataID get_dependencies() const { return AssembleViewDataID::None; }
#endif // NDEBUG
protected:
virtual void on_release() = 0;
virtual void on_update() = 0;
AssembleViewDataPool* get_pool() const { return m_common; }
private:
bool m_is_valid = false;
AssembleViewDataPool* m_common = nullptr;
};
namespace AssembleViewDataObjects
{
class ModelObjectsInfo : public AssembleViewDataBase
{
public:
explicit ModelObjectsInfo(AssembleViewDataPool* cgdp)
: AssembleViewDataBase(cgdp) {}
ModelObjectPtrs model_objects() const { return m_model_objects; }
//int get_active_instance() const;
float get_sla_shift() const { return m_z_shift; }
protected:
void on_update() override;
void on_release() override;
private:
ModelObjectPtrs m_model_objects;
float m_z_shift = 0.f;
};
class ModelObjectsClipper : public AssembleViewDataBase
{
public:
explicit ModelObjectsClipper(AssembleViewDataPool* cgdp)
: AssembleViewDataBase(cgdp) {}
#ifndef NDEBUG
AssembleViewDataID get_dependencies() const override { return AssembleViewDataID::ModelObjectsInfo; }
#endif // NDEBUG
void set_position(double pos, bool keep_normal);
double get_position() const { return m_clp_ratio; }
ClippingPlane* get_clipping_plane() const { return m_clp.get(); }
void render_cut() const;
protected:
void on_update() override;
void on_release() override;
private:
std::vector<const TriangleMesh*> m_old_meshes;
std::vector<std::unique_ptr<MeshClipper>> m_clippers;
std::unique_ptr<ClippingPlane> m_clp;
double m_clp_ratio = 0.;
double m_active_inst_bb_radius = 0.;
};
}
} // namespace GUI
} // namespace Slic3r

View file

@ -155,6 +155,7 @@ bool GLGizmosManager::init()
//m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++));
m_common_gizmos_data.reset(new CommonGizmosDataPool(&m_parent));
m_assemble_view_data.reset(new AssembleViewDataPool(&m_parent));
for (auto& gizmo : m_gizmos) {
if (! gizmo->init()) {
@ -341,6 +342,16 @@ void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos)
curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos));
}
void GLGizmosManager::update_assemble_view_data()
{
if (m_assemble_view_data) {
if (m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView)
m_assemble_view_data->update(AssembleViewDataID(0));
else
m_assemble_view_data->update(AssembleViewDataID((int)AssembleViewDataID::ModelObjectsInfo | (int)AssembleViewDataID::ModelObjectsClipper));
}
}
void GLGizmosManager::update_data()
{
if (!m_enabled)
@ -359,10 +370,11 @@ void GLGizmosManager::update_data()
enable_grabber(Scale, i, enable_scale_xyz);
}
if (m_common_gizmos_data)
if (m_common_gizmos_data) {
m_common_gizmos_data->update(get_current()
? get_current()->get_requirements()
: CommonGizmosDataID(0));
? get_current()->get_requirements()
: CommonGizmosDataID(0));
}
if (selection.is_single_full_instance())
{
@ -587,6 +599,18 @@ ClippingPlane GLGizmosManager::get_clipping_plane() const
}
}
ClippingPlane GLGizmosManager::get_assemble_view_clipping_plane() const
{
if (!m_assemble_view_data
|| !m_assemble_view_data->model_objects_clipper()
|| m_assemble_view_data->model_objects_clipper()->get_position() == 0.)
return ClippingPlane::ClipsNothing();
else {
const ClippingPlane& clp = *m_assemble_view_data->model_objects_clipper()->get_clipping_plane();
return ClippingPlane(-clp.get_normal(), clp.get_data()[3]);
}
}
bool GLGizmosManager::wants_reslice_supports_on_undo() const
{
return (m_current == SlaSupports
@ -614,6 +638,12 @@ void GLGizmosManager::render_painter_gizmo() const
gizmo->render_painter_gizmo();
}
void GLGizmosManager::render_painter_assemble_view() const
{
if (m_assemble_view_data)
m_assemble_view_data->model_objects_clipper()->render_cut();
}
void GLGizmosManager::render_current_gizmo_for_picking_pass() const
{
if (! m_enabled || m_current == Undefined)
@ -649,7 +679,14 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt)
if (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) {
float rot = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown()
// BBS
#ifdef __WXOSX_MAC__
, evt.RawControlDown()
#else
, evt.ControlDown()
#endif
))
processed = true;
}
@ -675,7 +712,8 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
if (evt.Moving()) {
m_tooltip = update_hover_state(mouse_pos);
if (m_current == MmuSegmentation || m_current == FdmSupports)
gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown());
// BBS
gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
} else if (evt.LeftUp()) {
if (m_mouse_capture.left) {
processed = true;

View file

@ -146,6 +146,7 @@ private:
std::map<int, void*> icon_list;
public:
std::unique_ptr<AssembleViewDataPool> m_assemble_view_data;
enum MENU_ICON_NAME {
IC_TOOLBAR_RESET = 0,
IC_TOOLBAR_RESET_HOVER,
@ -222,6 +223,7 @@ public:
void update(const Linef3& mouse_ray, const Point& mouse_pos);
void update_data();
void update_assemble_view_data();
EType get_current_type() const { return m_current; }
GLGizmoBase* get_current() const;
@ -265,6 +267,7 @@ public:
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_clipping_plane() const;
ClippingPlane get_assemble_view_clipping_plane() const;
bool wants_reslice_supports_on_undo() const;
bool is_in_editing_mode(bool error_notification = false) const;
@ -273,6 +276,7 @@ public:
void render_current_gizmo() const;
void render_current_gizmo_for_picking_pass() const;
void render_painter_gizmo() const;
void render_painter_assemble_view() const;
void render_overlay() const;

View file

@ -89,13 +89,6 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
m_new_position = volume->get_instance_offset();
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
if (m_world_coordinates && ! m_uniform_scale &&
! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling.
m_uniform_scale = true;
}
if (m_world_coordinates) {
m_new_rotate_label_string = L("Rotate");
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
@ -463,9 +456,6 @@ void GizmoObjectManipulation::set_uniform_scaling(const bool new_value)
}
}
m_uniform_scale = new_value;
AppConfig* config = wxGetApp().app_config;
if (config)
config->set("uniform_scale", new_value ? "1": "0");
}
static const char* label_values[2][3] = {
@ -897,9 +887,6 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
ImGui::Separator();
AppConfig* config = wxGetApp().app_config;
if (config)
this->m_uniform_scale = config->get("uniform_scale") == "1" ? true : false;
bool uniform_scale = this->m_uniform_scale;
const Selection &selection = m_glcanvas.get_selection();

View file

@ -81,7 +81,6 @@ public:
Vec3d m_buffered_size;
bool m_new_enabled {true};
bool m_uniform_scale {true};
bool m_uniform_config {false};
// Does the object manipulation panel work in World or Local coordinates?
bool m_world_coordinates = true;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,122 @@
#ifndef slic3r_GUI_HintNotification_hpp_
#define slic3r_GUI_HintNotification_hpp_
#include "NotificationManager.hpp"
namespace Slic3r {namespace GUI {
// Database of hints updatable
struct HintData
{
std::string id_string;
std::string text;
size_t weight;
bool was_displayed;
std::string hypertext;
std::string follow_text;
std::string disabled_tags;
std::string enabled_tags;
bool runtime_disable; // if true - hyperlink will check before every click if not in disabled mode
std::string documentation_link;
std::function<void(void)> callback{ nullptr };
};
class HintDatabase
{
public:
static HintDatabase& get_instance()
{
static HintDatabase instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
HintDatabase()
: m_hint_id(0)
{}
public:
~HintDatabase();
HintDatabase(HintDatabase const&) = delete;
void operator=(HintDatabase const&) = delete;
// return true if HintData filled;
HintData* get_hint(bool new_hint = true);
size_t get_count() {
if (!m_initialized)
return 0;
return m_loaded_hints.size();
}
// resets m_initiailized to false and writes used if was initialized
// used when reloading in runtime - like change language
void uninit();
private:
void init();
void load_hints_from_file(const boost::filesystem::path& path);
bool is_used(const std::string& id);
void set_used(const std::string& id);
void clear_used();
// Returns position in m_loaded_hints with next hint chosed randomly with weights
size_t get_next();
size_t m_hint_id;
bool m_initialized{ false };
std::vector<HintData> m_loaded_hints;
bool m_sorted_hints{ false };
std::vector<std::string> m_used_ids;
bool m_used_ids_loaded{ false };
};
// Notification class - shows current Hint ("Did you know")
class NotificationManager::HintNotification : public NotificationManager::PopNotification
{
public:
HintNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool new_hint)
: PopNotification(n, id_provider, evt_handler)
{
retrieve_data(new_hint);
}
virtual void init() override;
void open_next() { retrieve_data(); }
protected:
virtual void set_next_window_size(ImGuiWrapper& imgui) override;
virtual void count_spaces() override;
virtual void count_lines() override;
virtual bool on_text_click() override;
virtual void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
virtual void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
virtual void render_minimize_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y) override {}
void render_preferences_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y);
void render_right_arrow_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
void render_documentation_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
void render_logo(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
// recursion counter -1 tells to retrieve same hint as last time
void retrieve_data(bool new_hint = true);
void open_documentation();
bool m_has_hint_data{ false };
std::function<void(void)> m_hypertext_callback;
std::string m_disabled_tags;
std::string m_enabled_tags;
bool m_runtime_disable;
std::string m_documentation_link;
float m_close_b_y{ 0 };
float m_close_b_w{ 0 };
// hover of buttons
long m_docu_hover_time{ 0 };
long m_prefe_hover_time{ 0 };
};
} //namespace Slic3r
} //namespace GUI
#endif //slic3r_GUI_HintNotification_hpp_

View file

@ -88,14 +88,21 @@ bool check_color_change(PrintObject *object, size_t frst_layer_id, size_t layers
static std::string gcode(Type type)
{
const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config();
Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config();
switch (type) {
//BBS
//case ColorChange: return config.color_change_gcode;
case PausePrint: return config.machine_pause_gcode;
//case Template: return config.template_custom_gcode;
case Template: return config.opt_string("template_custom_gcode");
default: return "";
}
//const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config();
//switch (type) {
////BBS
////case ColorChange: return config.color_change_gcode;
//case PausePrint: return config.machine_pause_gcode;
//case Template: return config.template_custom_gcode;
//default: return "";
//}
}
static std::string short_and_splitted_time(const std::string &time)
@ -222,9 +229,9 @@ bool TickCodeInfo::add_tick(const int tick, Type type, const int extruder, doubl
std::string extra;
if (type == Custom) // custom Gcode
{
/*extra = get_custom_code(custom_gcode, print_z);
if (extra.empty()) return false;
custom_gcode = extra;*/
//extra = get_custom_code(custom_gcode, print_z);
//if (extra.empty()) return false;
//custom_gcode = extra;
} else if (type == PausePrint) {
//BBS do not set pause extra message
//extra = get_pause_print_msg(pause_print_msg, print_z);
@ -262,9 +269,10 @@ bool TickCodeInfo::edit_tick(std::set<TickCode>::iterator it, double print_z)
if (it->color == edited_value) return false;
changed_tick.color = edited_value;
} else if (it->type == Template) {
if (gcode(Template) == edited_value) return false;
changed_tick.extra = edited_value;
changed_tick.type = Custom;
//if (gcode(Template) == edited_value) return false;
//changed_tick.extra = edited_value;
//changed_tick.type = Custom;
;
} else if (it->type == Custom || it->type == PausePrint) {
if (it->extra == edited_value) return false;
changed_tick.extra = edited_value;
@ -625,6 +633,21 @@ void IMSlider::post_ticks_changed_event(Type type)
m_is_need_post_tick_changed_event = true;
}
void IMSlider::add_custom_gcode(std::string custom_gcode)
{
if (m_selection == ssUndef) return;
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
const auto it = m_ticks.ticks.find(TickCode{ tick });
if (it != m_ticks.ticks.end()) {
m_ticks.ticks.erase(it);
}
m_ticks.ticks.emplace(TickCode{ tick, Custom, std::max<int>(1, m_only_extruder), "", custom_gcode });
post_ticks_changed_event(Custom);
}
void IMSlider::add_code_as_tick(Type type, int selected_extruder)
{
if (m_selection == ssUndef) return;
@ -682,8 +705,11 @@ bool IMSlider::check_ticks_changed_event(Type type)
// switch on/off one layer mode
void IMSlider::switch_one_layer_mode()
bool IMSlider::switch_one_layer_mode()
{
if (m_show_custom_gcode_window)
return false;
m_is_one_layer = !m_is_one_layer;
if (!m_is_one_layer) {
SetLowerValue(m_min_value);
@ -692,6 +718,7 @@ void IMSlider::switch_one_layer_mode()
m_selection == ssLower ? correct_lower_value() : correct_higher_value();
if (m_selection == ssUndef) m_selection = ssHigher;
set_as_dirty();
return true;
}
void IMSlider::draw_background(const ImRect& groove) {
@ -1194,6 +1221,8 @@ bool IMSlider::render(int canvas_width, int canvas_height)
float scale = (float) wxGetApp().em_unit() / 10.0f;
render_input_custom_gcode();
if (is_horizontal()) {
float pos_x = std::max(LEFT_MARGIN, 0.2f * canvas_width);
float pos_y = (canvas_height - HORIZONTAL_SLIDER_SIZE.y * m_scale);
@ -1247,6 +1276,70 @@ bool IMSlider::render(int canvas_width, int canvas_height)
return result;
}
void IMSlider::render_input_custom_gcode()
{
if (!m_show_custom_gcode_window)
return;
ImGuiWrapper& imgui = *wxGetApp().imgui();
static bool move_to_center = true;
if (move_to_center) {
move_to_center = false;
auto pos_x = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_width() / 2;
auto pos_y = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_height() / 2;
imgui.set_next_window_pos(pos_x, pos_y, ImGuiCond_Always, 0.5f, 0.5f);
}
imgui.push_common_window_style(m_scale);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.f * m_scale);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 3) * m_scale);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 7) * m_scale);
int windows_flag =
ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_AlwaysAutoResize
| ImGuiWindowFlags_NoResize
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoScrollWithMouse;
imgui.begin(_u8L("Custom G-code"), windows_flag);
imgui.text(_u8L("Enter Custom G-code used on current layer:"));
int text_height = 6;
ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height));
//text_height = 5;
//for (int i = 0; m_custom_gcode[i] != '\0'; ++i){
// if ('\n' == m_custom_gcode[i] && text_height < 12)
// ++text_height;
//}
ImGui::NewLine();
ImGui::SameLine(ImGui::GetStyle().WindowPadding.x * 14);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f / 255.f, 174.f / 255.f, 66.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(61.f / 255.f, 203.f / 255.f, 115.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(27.f / 255.f, 136.f / 255.f, 68.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.f, 1.f, 1.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f));
if (imgui.bbl_button(_L("OK"))) {
m_show_custom_gcode_window = false;
add_custom_gcode(m_custom_gcode);
move_to_center = true;
}
ImGui::PopStyleColor(5);
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(255.f / 255.f, 255.f / 255.f, 255.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(238.f / 255.f, 238.f / 255.f, 238.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(206.f / 255.f, 206.f / 255.f, 206.f / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.f, 0.f, 0.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(38.f / 255.0f, 46.f / 255.0f, 48.f / 255.0f, 1.00f));
if (imgui.bbl_button(_L("Cancel"))) {
m_show_custom_gcode_window = false;
move_to_center = true;
}
ImGui::PopStyleColor(5);
imgui.end();
ImGui::PopStyleVar(3);
imgui.pop_common_window_style();
}
void IMSlider::render_menu()
{
ImGuiWrapper::push_menu_style(m_scale);
@ -1267,6 +1360,14 @@ void IMSlider::render_menu()
if (menu_item_with_icon(_u8L("Add Pause").c_str(), "")) {
add_code_as_tick(PausePrint);
}
if (menu_item_with_icon(_u8L("Add Custom G-code").c_str(), "")) {
m_show_custom_gcode_window = true;
}
if (!gcode(Template).empty()) {
if (menu_item_with_icon(_u8L("Add Custom Template").c_str(), "")) {
add_code_as_tick(Template);
}
}
}
//BBS render this menu item only when extruder_num > 1

View file

@ -261,15 +261,18 @@ public:
void UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); }
void add_custom_gcode(std::string custom_gcode);
void add_code_as_tick(Type type, int selected_extruder = -1);
void post_ticks_changed_event(Type type = Custom);
bool check_ticks_changed_event(Type type);
void switch_one_layer_mode();
bool switch_one_layer_mode();
bool render(int canvas_width, int canvas_height);
void render_menu();
void render_input_custom_gcode();
//BBS update scroll value changed
bool is_dirty() { return m_dirty; }
void set_as_dirty(bool dirty = true) { m_dirty = dirty; }
@ -327,6 +330,7 @@ private:
bool m_is_one_layer = false;
bool m_is_focused = false;
bool m_show_menu = false;
bool m_show_custom_gcode_window = false;
bool m_force_mode_apply = true;
bool m_enable_action_icon = true;
bool m_enable_cog_icon = false;
@ -367,6 +371,8 @@ private:
Type m_tick_change_event_type;
std::vector<double> m_alternate_values;
char m_custom_gcode[1024] = { 0 };
};
}

View file

@ -1687,6 +1687,33 @@ void ImGuiWrapper::pop_menu_style()
ImGuiWrapper::pop_toolbar_style();
}
void ImGuiWrapper::push_common_window_style(const float scale) {
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 10.0f) * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, ImVec2(0.05f, 0.50f) * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(38 / 255.0f, 46 / 255.0f, 48 / 255.0f, 1.00f)); // 1
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGuiWrapper::COL_WINDOW_BG); // 2
ImGui::PushStyleColor(ImGuiCol_TitleBg, ImGuiWrapper::COL_TITLE_BG); // 3
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, ImGuiWrapper::COL_TITLE_BG); // 4
ImGui::PushStyleColor(ImGuiCol_Separator, ImGuiWrapper::COL_SEPARATOR); // 5
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.00f, 1.00f, 1.00f, 1.00f)); // 6
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); // 7
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); // 8
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 9
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 10
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f)); // 11
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.00f, 1.00f, 1.00f, 1.00f)); // 12
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, ImGuiWrapper::COL_GREEN_LIGHT); // 13
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); // 14
}
void ImGuiWrapper::pop_common_window_style() {
ImGui::PopStyleColor(14);
ImGui::PopStyleVar(5);
}
void ImGuiWrapper::init_font(bool compress)
{
destroy_font();

View file

@ -192,6 +192,8 @@ public:
static void pop_toolbar_style();
static void push_menu_style(const float scale);
static void pop_menu_style();
static void push_common_window_style(const float scale);
static void pop_common_window_style();
//BBS
static int TOOLBAR_WINDOW_FLAGS;

View file

@ -8,6 +8,12 @@
#include <wx/dcgraph.h>
#ifdef __WXMSW__
#include <shellapi.h>
#endif
#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp"
#endif
BEGIN_EVENT_TABLE(Slic3r::GUI::ImageGrid, wxPanel)
@ -102,7 +108,8 @@ void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
void Slic3r::GUI::ImageGrid::SetSelecting(bool selecting)
{
m_selecting = selecting;
if (!m_selecting) m_file_sys->SelectAll(false);
if (m_file_sys)
m_file_sys->SelectAll(false);
Refresh();
}
@ -140,29 +147,53 @@ void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
{
if (action == 0) {
m_file_sys->DeleteFiles(index);
} else {
} else if (action == 1) {
if (index != -1) {
auto &file = m_file_sys->GetFile(index);
if (file.IsDownload() && file.progress >= -1) {
if (file.progress >= 100) {
if (!m_file_sys->DownloadCheckFile(index)) {
wxMessageBox(wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), _L("Error"), wxOK);
Refresh();
return;
}
#ifdef __WXMSW__
wxExecute("cmd /c start " + from_u8(m_save_path + "\\" + file.name), wxEXEC_HIDE_CONSOLE);
auto wfile = boost::filesystem::path(file.path).wstring();
SHELLEXECUTEINFO info{sizeof(info), 0, NULL, L"open", wfile.c_str(), L"", SW_HIDE};
::ShellExecuteEx(&info);
#else
wxShell("open " + m_save_path + "/" + file.name);
wxShell("open " + file.path);
#endif
} else {
m_file_sys->DownloadCancel(index);
}
return;
}
if (m_save_path.empty()) {
wxDirDialog dlg(NULL, _L("Choose save directory"), "", wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
if (dlg.ShowModal() == wxID_CANCEL)
return;
m_save_path = dlg.GetPath().ToUTF8().data();
}
m_file_sys->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
} else if (action == 2) {
if (index != -1) {
auto &file = m_file_sys->GetFile(index);
if (file.IsDownload() && file.progress >= -1) {
if (file.progress >= 100) {
if (!m_file_sys->DownloadCheckFile(index)) {
wxMessageBox(wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)), _L("Error"), wxOK);
Refresh();
return;
}
#ifdef __WIN32__
wxExecute(L"explorer.exe /select," + from_u8(file.path));
#elif __APPLE__
openFolderForFile(from_u8(file.path));
#else
#endif
} else {
m_file_sys->DownloadCancel(index);
}
return;
}
}
m_file_sys->DownloadFiles(index, m_save_path);
m_file_sys->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
}
}
@ -188,8 +219,10 @@ void ImageGrid::UpdateLayout()
if (!m_file_sys) return;
wxSize size = GetClientSize();
wxSize mask_size{0, 60 * em_unit(this) / 10};
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
mask_size.y = 20 * em_unit(this) / 10;
size.y -= mask_size.y;
}
int cell_width = m_cell_size.GetWidth();
int cell_height = m_cell_size.GetHeight();
int ncol = (size.GetWidth() - cell_width + m_image_size.GetWidth()) / cell_width;
@ -254,7 +287,9 @@ std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
if (index >= m_file_sys->GetCount()) { return {HIT_NONE, -1}; }
if (!m_selecting) {
wxRect hover_rect{0, m_image_size.y - 40, m_image_size.GetWidth(), 40};
if (hover_rect.Contains(off.x, off.y)) { return {HIT_ACTION, index * 2 + off.x * 2 / hover_rect.GetWidth()}; } // Two buttons
auto & file = m_file_sys->GetFile(index);
int btn = file.IsDownload() && file.progress >= 100 ? 3 : 2;
if (hover_rect.Contains(off.x, off.y)) { return {HIT_ACTION, index * 4 + off.x * btn / hover_rect.GetWidth()}; } // Two buttons
}
return {HIT_ITEM, index};
}
@ -316,7 +351,7 @@ void ImageGrid::mouseReleased(wxMouseEvent& event)
if (m_hit_type == HIT_ITEM)
Select(m_hit_item);
else if (m_hit_type == HIT_ACTION)
DoAction(m_hit_item / 2, m_hit_item & 1);
DoAction(m_hit_item / 4, m_hit_item & 3);
else if (m_hit_type == HIT_MODE)
SetGroupMode(static_cast<PrinterFileSystem::GroupMode>(2 - m_hit_item));
else if (m_hit_type == HIT_STATUS)
@ -349,8 +384,12 @@ void Slic3r::GUI::ImageGrid::changedEvent(wxCommandEvent& evt)
{
evt.Skip();
BOOST_LOG_TRIVIAL(info) << "ImageGrid::changedEvent: " << evt.GetEventType() << " index: " << evt.GetInt() << " name: " << evt.GetString() << " extra: " << evt.GetExtraLong();
if (evt.GetEventType() == EVT_MODE_CHANGED
|| evt.GetEventType() == EVT_FILE_CHANGED)
if (evt.GetEventType() == EVT_FILE_CHANGED) {
if (evt.GetInt() == -1)
m_file_sys->DownloadCheckFiles(wxGetApp().app_config->get("download_path"));
UpdateFileSystem();
}
else if (evt.GetEventType() == EVT_MODE_CHANGED)
UpdateFileSystem();
else
Refresh();
@ -365,13 +404,16 @@ void ImageGrid::paintEvent(wxPaintEvent& evt)
size_t Slic3r::GUI::ImageGrid::firstItem(wxSize const &size, wxPoint &off)
{
int size_y = size.y;
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
size_y -= m_mask.GetHeight();
int offx = (size.x - (m_col_count - 1) * m_cell_size.GetWidth() - m_image_size.GetWidth()) / 2;
int offy = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
m_cell_size.GetHeight() - m_image_size.GetHeight() - m_row_offset * m_cell_size.GetHeight() / 4 + m_row_offset / 4 * m_cell_size.GetHeight() :
size.y - (size.y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight() * m_cell_size.GetHeight();
size_y - (size_y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight() * m_cell_size.GetHeight();
int index = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
m_row_offset / 4 * m_col_count :
((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size.y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size_y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
offy += m_mask.GetHeight();
off = wxPoint{offx, offy};
@ -455,7 +497,7 @@ void ImageGrid::render(wxDC& dc)
constexpr wchar_t const * formats[] = {_T("%Y-%m-%d"), _T("%Y-%m"), _T("%Y")};
size_t start = index;
size_t end = index;
size_t hit_image = m_selecting ? size_t(-1) : m_hit_type == HIT_ITEM ? m_hit_item : m_hit_type == HIT_ACTION ? m_hit_item / 2 :size_t(-1);
size_t hit_image = m_selecting ? size_t(-1) : m_hit_type == HIT_ITEM ? m_hit_item : m_hit_type == HIT_ACTION ? m_hit_item / 4 :size_t(-1);
// Draw items with background
while (off.y < size.y)
{
@ -475,15 +517,17 @@ void ImageGrid::render(wxDC& dc)
dc.DrawBitmap(m_mask, pt);
}
}
bool show_download_state_always = true;
// Draw checked icon
if (m_selecting)
if (m_selecting && !show_download_state_always)
dc.DrawBitmap(file.IsSelect() ? m_checked_icon.bmp() : m_unchecked_icon.bmp(),
pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
// can' handle alpha
// can't handle alpha
// dc.GradientFillLinear({pt.x, pt.y, m_image_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
wxString nonHoverText;
wxString secondAction = _L("Download");
wxString thirdAction;
int states = 0;
// Draw download progress
if (file.IsDownload()) {
@ -495,7 +539,8 @@ void ImageGrid::render(wxDC& dc)
nonHoverText = _L("Download failed");
states = StateColor::Checked;
} else if (file.progress >= 100) {
secondAction = _L("Open");
secondAction = _L("Play");
thirdAction = _L("Open Folder");
nonHoverText = _L("Download finished");
} else {
secondAction = _L("Cancel");
@ -505,10 +550,14 @@ void ImageGrid::render(wxDC& dc)
// Draw buttons on hovered item
wxRect rect{pt.x, pt.y + m_image_size.y - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
if (hit_image == index) {
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, nullptr}, rect, m_hit_type == HIT_ACTION ? m_hit_item & 1 : -1, states);
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, thirdAction.IsEmpty() ? nullptr : (wxChar const *) thirdAction, nullptr}, rect,
m_hit_type == HIT_ACTION ? m_hit_item & 3 : -1, states);
} else if (!nonHoverText.IsEmpty()) {
renderButtons(dc, {(wxChar const *) nonHoverText, nullptr}, rect, -1, states);
}
if (m_selecting && show_download_state_always)
dc.DrawBitmap(file.IsSelect() ? m_checked_icon.bmp() : m_unchecked_icon.bmp(),
pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
} else {
auto date = wxDateTime((time_t) file.time).Format(_L(formats[m_file_sys->GetGroupMode()]));
dc.DrawText(date, pt + wxPoint{24, 16});
@ -569,12 +618,12 @@ void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts,
for (size_t i = 0; i < texts.size(); ++i) {
int states2 = hit == i ? state : 0;
// Draw button background
rect.Deflate(10, 5);
//dc.Blit(rect.GetTopLeft(), rect.GetSize(), &mdc, {m_buttonBackgroundColor.colorIndexForStates(states) * 128, 0});
//dc.DrawBitmap(m_button_background, rect2.GetTopLeft());
// Draw button splitter
if (i > 0) dc.DrawLine(rect.GetLeftTop(), rect.GetLeftBottom());
// Draw button text
rect.Deflate(10, 5);
renderText(dc, texts[i], rect, states | states2);
rect.Inflate(10, 5);
rect.Offset(rect.GetWidth(), 0);

View file

@ -96,8 +96,6 @@ private:
wxBitmap m_status_icon;
wxString m_status_msg;
std::string m_save_path;
ScalableBitmap m_checked_icon;
ScalableBitmap m_unchecked_icon;
StateColor m_buttonBackgroundColor;

View file

@ -503,10 +503,6 @@ void ArrangeJob::process()
if (params.is_seq_print)
params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius));
if (params.avoid_extrusion_cali_region)
m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
double brim_max = 0;
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.brim_width); });
@ -531,6 +527,9 @@ void ArrangeJob::process()
std::for_each(m_selected.begin(), m_selected.end(), [&](auto& ap) {ap.inflation = params.min_obj_distance / 2; });
std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto& ap) {ap.inflation = ap.is_virt_object ? scaled(params.brim_skirt_distance) : params.min_obj_distance / 2; });
if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer"))
m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
m_plater->get_partplate_list().preprocess_exclude_areas(params.excluded_regions, 1);
// shrink bed by moving to center by dist

View file

@ -103,7 +103,10 @@ void BindJob::process()
msg = _L("Logging in");
}
if (code != 0) {
msg = _L("Login failed") + wxString::Format("(code=%d,info=%s)", code, info);
msg = _L("Login failed") + wxString::Format("(code=%d,info=%s). ", code, info);
if (code == BAMBU_NETWORK_ERR_TIMEOUT) {
msg += _L("Please check the printer network connection.");
}
}
update_status(curr_percent, msg);
}

View file

@ -85,6 +85,7 @@ wxString PrintJob::get_http_error_msg(unsigned int status, std::string body)
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;
}
@ -151,6 +152,7 @@ void PrintJob::process()
params.task_layer_inspect = this->task_layer_inspect;
params.task_record_timelapse= this->task_record_timelapse;
params.ams_mapping = this->task_ams_mapping;
params.ams_mapping_info = this->task_ams_mapping_info;
params.connection_type = this->connection_type;
params.task_use_ams = this->task_use_ams;

View file

@ -47,6 +47,7 @@ public:
bool task_record_timelapse;
bool task_layer_inspect;
std::string task_ams_mapping;
std::string task_ams_mapping_info;
std::string connection_type;
bool cloud_print_only { false };
bool has_sdcard { false };

View file

@ -0,0 +1,314 @@
#include "SendJob.hpp"
#include "libslic3r/MTUtils.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
namespace Slic3r {
namespace GUI {
static wxString check_gcode_failed_str = _L("Abnormal print file data. Please slice again");
static wxString printjob_cancel_str = _L("Task canceled");
static wxString timeout_to_upload_str = _L("Upload task timed out. Please check the network problem and try again");
static wxString failed_in_cloud_service_str = _L("Cloud service connection failed. Please try again.");
static wxString file_is_not_exists_str = _L("Print file not found, please slice again");
static wxString file_over_size_str = _L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again");
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 sending_over_lan_str = _L("Sending gcode file over LAN");
static wxString sending_over_cloud_str = _L("Sending gcode file through cloud service");
SendJob::SendJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::string dev_id)
: PlaterJob{ std::move(pri), plater },
m_dev_id(dev_id)
{
m_print_job_completed_id = plater->get_send_finished_event();
}
void SendJob::prepare()
{
m_plater->get_print_job_data(&job_data);
}
void SendJob::on_exception(const std::exception_ptr &eptr)
{
try {
if (eptr)
std::rethrow_exception(eptr);
} catch (std::exception &e) {
PlaterJob::on_exception(eptr);
}
}
wxString SendJob::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>();
}
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 (...) {
;
}
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);
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;
}
inline std::string get_transform_string(int bytes)
{
float ms = (float)bytes / 1024.0f / 1024.0f;
float ks = (float)bytes / 1024.0f;
char buffer[32];
if (ms > 0)
::sprintf(buffer, "%.1fM", ms);
else if (ks > 0)
::sprintf(buffer, "%.1fK", ks);
else
::sprintf(buffer, "%.1fK", ks);
return buffer;
}
void SendJob::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 gcode file over LAN");
}
else {
msg = _L("Sending gcode file through cloud service");
}
int result = -1;
unsigned int http_code;
std::string http_body;
int total_plate_num = m_plater->get_partplate_list().get_plate_count();
PartPlate* plate = m_plater->get_partplate_list().get_plate(job_data.plate_idx);
if (plate == nullptr) {
plate = m_plater->get_partplate_list().get_curr_plate();
if (plate == nullptr)
return;
}
/* check gcode is valid */
if (!plate->is_valid_gcode_file()) {
update_status(curr_percent, check_gcode_failed_str);
return;
}
if (was_canceled()) {
update_status(curr_percent, printjob_cancel_str);
return;
}
std::string project_name = wxGetApp().plater()->get_project_name().ToUTF8().data();
int curr_plate_idx = 0;
if (job_data.plate_idx >= 0)
curr_plate_idx = job_data.plate_idx + 1;
else if (job_data.plate_idx == PLATE_CURRENT_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
BBL::PrintParams params;
params.dev_id = m_dev_id;
//params.project_name = wxGetApp().plater()->get_project_name().ToUTF8().data();
params.project_name = wxGetApp().plater()->get_project_name().utf8_string();
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
params.filename = job_data._3mf_path.string();
params.config_filename = job_data._3mf_config_path.string();
params.plate_index = curr_plate_idx;
params.ams_mapping = this->task_ams_mapping;
params.connection_type = this->connection_type;
params.task_use_ams = this->task_use_ams;
// local print access
params.dev_ip = m_dev_ip;
params.username = "bblp";
params.password = m_access_code;
wxString error_text;
wxString msg_text;
auto update_fn = [this, &msg, &curr_percent, &error_text](int stage, int code, std::string info) {
if (stage == SendingPrintJobStage::PrintingStageCreate) {
if (this->connection_type == "lan") {
msg = _L("Sending gcode file over LAN");
} else {
msg = _L("Sending gcode file to sdcard");
}
curr_percent = 25;
}
else if (stage == SendingPrintJobStage::PrintingStageUpload) {
if (code == 0 && !info.empty()) {
if (this->connection_type == "lan") {
msg = _L("Sending gcode file over LAN");
}
else {
msg = _L("Sending gcode file to sdcard");
}
msg += wxString::Format("(%s)", info);
curr_percent = 40;
this->update_status(curr_percent, msg);
}
}
else if (stage == SendingPrintJobStage::PrintingStageFinished) {
curr_percent = 100;
msg = wxString::Format(_L("Successfully sent. Close current page in %s s"), info);
}
else {
if (this->connection_type == "lan") {
msg = _L("Sending gcode file over LAN");
}
else {
msg = _L("Sending gcode file over LAN");
//msg = _L("Sending gcode file through cloud service");
}
}
if (code != 0) {
error_text = this->get_http_error_msg(code, info);
msg += wxString::Format("[%s]", error_text);
}
this->update_status(curr_percent, msg);
};
auto cancel_fn = [this]() {
return was_canceled();
};
if (params.connection_type != "lan") {
if (params.dev_ip.empty())
params.comments = "no_ip";
else if (this->cloud_print_only)
params.comments = "low_version";
else if (!this->has_sdcard)
params.comments = "no_sdcard";
else if (params.password.empty())
params.comments = "no_password";
if (!params.password.empty()
&& !params.dev_ip.empty()
&& this->has_sdcard) {
// try to send local with record
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode to printer";
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
result = m_agent->start_send_gcode_to_sdcard(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(info) << "send_job: try to send gcode file to printer";
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
}
} else {
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode file to printer";
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
}
} else {
if (this->has_sdcard) {
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn);
} else {
this->update_status(curr_percent, _L("An SD card needs to be inserted before printing via LAN."));
return;
}
}
if (was_canceled()) {
update_status(curr_percent, printjob_cancel_str);
return;
}
if (result < 0) {
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
msg_text = upload_failed_str;
} 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;
} else if (result == BAMBU_NETWORK_ERR_CHECK_MD5_FAILED) {
msg_text = failed_in_cloud_service_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_PARAMS) {
msg_text = upload_failed_str;
} else if (result == BAMBU_NETWORK_ERR_CANCELED) {
msg_text = print_canceled_str;
} else if (result == BAMBU_NETWORK_ERR_TIMEOUT) {
msg_text = timeout_to_upload_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
msg_text = upload_failed_str;
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
msg_text = upload_failed_str;
} else {
update_status(curr_percent, failed_in_cloud_service_str);
}
if (!error_text.IsEmpty())
msg_text += wxString::Format("[%s]", error_text);
update_status(curr_percent, msg_text);
BOOST_LOG_TRIVIAL(error) << "send_job: failed, result = " << result;
} else {
BOOST_LOG_TRIVIAL(error) << "send_job: send ok.";
//m_success_fun();
wxCommandEvent* evt = new wxCommandEvent(m_print_job_completed_id);
evt->SetString(m_dev_id);
wxQueueEvent(m_plater, evt);
m_job_finished = true;
}
}
void SendJob::on_success(std::function<void()> success)
{
m_success_fun = success;
}
void SendJob::finalize() {
if (was_canceled()) return;
Job::finalize();
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,60 @@
#ifndef SendJOB_HPP
#define SendJOB_HPP
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include "PlaterJob.hpp"
#include "PrintJob.hpp"
namespace fs = boost::filesystem;
namespace Slic3r {
namespace GUI {
typedef std::function<void(int status, int code, std::string msg)> OnUpdateStatusFn;
typedef std::function<bool()> WasCancelledFn;
class SendJob : public PlaterJob
{
PrintPrepareData job_data;
std::string m_dev_id;
bool m_job_finished{ false };
int m_print_job_completed_id = 0;
std::function<void()> m_success_fun{nullptr};
protected:
void prepare() override;
void on_exception(const std::exception_ptr &) override;
public:
SendJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id = "");
std::string m_dev_ip;
std::string m_access_code;
std::string task_bed_type;
std::string task_ams_mapping;
std::string connection_type;
bool cloud_print_only { false };
bool has_sdcard { false };
bool task_use_ams { true };
wxWindow* m_parent{nullptr};
int status_range() const override
{
return 100;
}
wxString get_http_error_msg(unsigned int status, std::string body);
bool is_finished() { return m_job_finished; }
void process() override;
void on_success(std::function<void()> success);
void finalize() override;
};
}}
#endif

View file

@ -9,7 +9,8 @@ namespace GUI {
wxDEFINE_EVENT(EVT_UPGRADE_UPDATE_MESSAGE, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPGRADE_NETWORK_SUCCESS, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPGRADE_NETWORK_FAILED, wxCommandEvent);
wxDEFINE_EVENT(EVT_DOWNLOAD_NETWORK_FAILED, wxCommandEvent);
wxDEFINE_EVENT(EVT_INSTALL_NETWORK_FAILED, wxCommandEvent);
UpgradeNetworkJob::UpgradeNetworkJob(std::shared_ptr<ProgressIndicator> pri)
@ -88,7 +89,7 @@ void UpgradeNetworkJob::process()
if (result < 0) {
update_status(0, _L("Download failed"));
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
wxCommandEvent event(EVT_DOWNLOAD_NETWORK_FAILED);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
return;
@ -112,7 +113,7 @@ void UpgradeNetworkJob::process()
if (result != 0) {
update_status(0, _L("Install failed"));
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
wxCommandEvent event(EVT_INSTALL_NETWORK_FAILED);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
return;

View file

@ -49,7 +49,8 @@ public:
wxDECLARE_EVENT(EVT_UPGRADE_UPDATE_MESSAGE, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPGRADE_NETWORK_SUCCESS, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPGRADE_NETWORK_FAILED, wxCommandEvent);
wxDECLARE_EVENT(EVT_DOWNLOAD_NETWORK_FAILED, wxCommandEvent);
wxDECLARE_EVENT(EVT_INSTALL_NETWORK_FAILED, wxCommandEvent);
}} // namespace Slic3r::GUI

View file

@ -200,6 +200,25 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
// Font is already set in DPIFrame constructor
*/
#ifdef __APPLE__
m_reset_title_text_colour_timer = new wxTimer();
m_reset_title_text_colour_timer->SetOwner(this);
Bind(wxEVT_TIMER, [this](auto& e) {
set_title_colour_after_set_title(GetHandle());
m_reset_title_text_colour_timer->Stop();
});
this->Bind(wxEVT_FULLSCREEN, [this](wxFullScreenEvent& e) {
set_tag_when_enter_full_screen(e.IsFullScreen());
if (!e.IsFullScreen()) {
if (m_reset_title_text_colour_timer) {
m_reset_title_text_colour_timer->Stop();
m_reset_title_text_colour_timer->Start(500);
}
}
e.Skip();
});
#endif
#ifdef __APPLE__
// Initialize the docker task bar icon.
switch (wxGetApp().get_app_mode()) {
@ -375,7 +394,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
// declare events
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< "received close_widow event";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": mainframe received close_widow event";
if (event.CanVeto() && m_plater->get_view3D_canvas3D()->get_gizmos_manager().is_in_editing_mode(true)) {
// prevents to open the save dirty project dialog
event.Veto();
@ -428,7 +447,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
this->shutdown();
// propagate event
event.Skip();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< "finished process close_widow event";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": mainframe finished process close_widow event";
});
//FIXME it seems this method is not called on application start-up, at least not on Windows. Why?
@ -499,6 +518,7 @@ 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() == '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 (m_plater) m_plater->save_project(true); return;}
@ -702,6 +722,7 @@ void MainFrame::update_layout()
// Called when closing the application and when switching the application language.
void MainFrame::shutdown()
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter";
// BBS: backup
Slic3r::set_backup_callback(nullptr);
#ifdef _WIN32
@ -763,6 +784,8 @@ void MainFrame::shutdown()
wxGetApp().shutdown();
// BBS: why clear ?
//wxGetApp().plater_ = nullptr;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown exit";
}
void MainFrame::update_title()
@ -772,8 +795,8 @@ void MainFrame::update_title()
void MainFrame::update_title_colour_after_set_title()
{
#ifdef __WXOSX__
set_title_colour_after_set_title();
#ifdef __APPLE__
set_title_colour_after_set_title(GetHandle());
#endif
}
@ -1269,8 +1292,12 @@ wxBoxSizer* MainFrame::create_side_tools()
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_GCODE));
else if (m_print_select == eSendGcode)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE));
else if (m_print_select == eUploadGcode)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_UPLOAD_GCODE));
else if (m_print_select == eExportSlicedFile)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE));
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE));
else if (m_print_select == eSendToPrinter)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER));
});
// only support single plate currently
@ -1322,60 +1349,92 @@ wxBoxSizer* MainFrame::create_side_tools()
p->Dismiss();
});
#endif
SideButton* print_plate_btn = new SideButton(p, _L("Print"), "");
print_plate_btn->SetCornerRadius(0);
print_plate_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
#if ENABEL_PRINT_ALL
p->append_button(print_all_btn);
#endif
if (wxGetApp().preset_bundle
&& !wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle)) {
// ThirdParty Buttons
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
export_gcode_btn->SetCornerRadius(0);
export_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export G-code file"));
m_print_select = eExportGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
// upload and print
SideButton* send_gcode_btn = new SideButton(p, _L("Print"), "");
send_gcode_btn->SetCornerRadius(0);
send_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Print"));
m_print_select = eSendGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
// upload only
/*SideButton* upload_gcode_btn = new SideButton(p, _L("Send"), "");
upload_gcode_btn->SetCornerRadius(0);
upload_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send"));
m_print_select = eUploadGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});*/
p->append_button(send_gcode_btn);
//p->append_button(upload_gcode_btn);
p->append_button(export_gcode_btn);
} else {
//Bambu Studio Buttons
SideButton* print_plate_btn = new SideButton(p, _L("Print"), "");
print_plate_btn->SetCornerRadius(0);
/*SideButton* send_to_printer_btn = new SideButton(p, _L("Send"), "");
send_to_printer_btn->SetCornerRadius(0);*/
SideButton* export_sliced_file_btn = new SideButton(p, _L("Export sliced file"), "");
export_sliced_file_btn->SetCornerRadius(0);
print_plate_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Print"));
m_print_select = ePrintPlate;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
});
SideButton* send_gcode_btn = new SideButton(p, _L("Send"), "");
send_gcode_btn->SetCornerRadius(0);
send_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send to print"));
m_print_select = eSendGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status() && can_send_gcode();
/*send_to_printer_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send"));
m_print_select = eSendToPrinter;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
});*/
SideButton* export_sliced_file_3mf_btn = new SideButton(p, _L("Export sliced file (.3mf)"), "");
export_sliced_file_3mf_btn->SetCornerRadius(0);
export_sliced_file_3mf_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export Sliced File (.3mf)"));
export_sliced_file_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export Sliced File"));
m_print_select = eExportSlicedFile;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
});
p->append_button(print_plate_btn);
//p->append_button(send_to_printer_btn);
p->append_button(export_sliced_file_btn);
}
SideButton* export_sliced_file_gcode_btn = new SideButton(p, _L("Export sliced file (.gcode)"), "");
export_sliced_file_gcode_btn->SetCornerRadius(0);
export_sliced_file_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export Sliced File (.gcode)"));
m_print_select = eExportGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
#if ENABEL_PRINT_ALL
p->append_button(print_all_btn);
#endif
p->append_button(print_plate_btn);
p->append_button(send_gcode_btn);
p->append_button(export_sliced_file_3mf_btn);
p->append_button(export_sliced_file_gcode_btn);
p->Popup(m_print_btn);
}
);
@ -1461,13 +1520,34 @@ bool MainFrame::get_enable_print_status()
enable = false;
}
}
else if (m_print_select == eSendGcode)
{
if (!current_plate->is_slice_result_valid())
enable = false;
if (!can_send_gcode())
enable = false;
}
else if (m_print_select == eUploadGcode)
{
if (!current_plate->is_slice_result_valid())
enable = false;
if (!can_send_gcode())
enable = false;
}
else if (m_print_select == eExportSlicedFile)
{
if (!current_plate->is_slice_result_ready_for_print())
{
enable = false;
}
}
}
else if (m_print_select == eSendToPrinter)
{
if (!current_plate->is_slice_result_ready_for_print())
{
enable = false;
}
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": m_print_select %1%, enable= %2% ")%m_print_select %enable;
@ -1680,6 +1760,10 @@ static wxMenu* generate_help_menu()
append_menu_item(helpMenu, wxID_ANY, about_title, about_title,
[](wxCommandEvent&) { Slic3r::GUI::about(); });
#endif
append_menu_item(helpMenu, wxID_ANY, _L("Show Tip of the Day"), _L("Show Tip of the Day"), [](wxCommandEvent&) {
wxGetApp().plater()->get_notification_manager()->push_hint_notification(false);
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
append_menu_item(helpMenu, wxID_ANY, _L("Open Network Test"), _L("Open Network Test"), [](wxCommandEvent&) {
NetworkTestDialog dlg(wxGetApp().mainframe);
@ -2613,6 +2697,28 @@ void MainFrame::on_config_changed(DynamicPrintConfig* config) const
m_plater->on_config_change(*config); // propagate config change events to the plater
}
void MainFrame::set_print_button_to_default(PrintSelectType select_type)
{
if (select_type == PrintSelectType::ePrintPlate) {
m_print_btn->SetLabel(_L("Print"));
m_print_select = ePrintPlate;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else if (select_type == PrintSelectType::eSendGcode) {
m_print_btn->SetLabel(_L("Print"));
m_print_select = eSendGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else {
//unsupport
return;
}
}
void MainFrame::add_to_recent_projects(const wxString& filename)
{
if (wxFileExists(filename))

View file

@ -84,6 +84,7 @@ protected:
class MainFrame : public DPIFrame
{
bool m_loaded {false};
wxTimer* m_reset_title_text_colour_timer{ nullptr };
wxString m_qs_last_input_file = wxEmptyString;
wxString m_qs_last_output_file = wxEmptyString;
@ -167,17 +168,6 @@ class MainFrame : public DPIFrame
ESettingsLayout m_layout{ ESettingsLayout::Unknown };
//BBS GUI refactor
enum PrintSelectType
{
ePrintAll = 0,
ePrintPlate = 1,
eExportSlicedFile = 2,
eExportGcode = 3,
eSendGcode = 4,
};
enum SliceSelectType
{
eSliceAll = 0,
@ -193,7 +183,6 @@ protected:
#endif
public:
MainFrame();
~MainFrame() = default;
@ -208,6 +197,18 @@ public:
tpProject = 4,
};
//BBS GUI refactor
enum PrintSelectType
{
ePrintAll = 0,
ePrintPlate = 1,
eExportSlicedFile = 2,
eExportGcode = 3,
eSendGcode = 4,
eSendToPrinter = 5,
eUploadGcode = 6
};
//BBS: add slice&&print status update logic
enum SlicePrintEventType
{
@ -288,6 +289,7 @@ public:
void select_view(const std::string& direction);
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
void on_config_changed(DynamicPrintConfig* cfg) const ;
void set_print_button_to_default(PrintSelectType select_type);
bool can_save() const;
bool can_save_as() const;

View file

@ -73,7 +73,8 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
type_sizer->Add(m_button_timelapse, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
type_sizer->Add(m_button_video, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
m_type_panel->SetSizer(type_sizer);
//top_sizer->Add(m_type_panel, 0, wxALIGN_CENTER_VERTICAL);
m_type_panel->Hide();
// top_sizer->Add(m_type_panel, 0, wxALIGN_CENTER_VERTICAL);
// File management
m_manage_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
@ -82,19 +83,18 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
m_button_delete->SetToolTip(L("Delete selected files from printer."));
m_button_download = new ::Button(m_manage_panel, _L("Download"));
m_button_download->SetToolTip(L("Download selected files from printer."));
m_button_management = new ::Button(m_manage_panel, _L("Management"));
m_button_management = new ::Button(m_manage_panel, _L("Select"));
m_button_management->SetToolTip(L("Batch manage files."));
for (auto b : {m_button_delete, m_button_download, m_button_management}) {
b->SetBackgroundColor(StateColor());
b->SetFont(Label::Body_12);
b->SetCornerRadius(12);
b->SetPaddingSize({10, 6});
b->SetCanFocus(false);
}
m_button_delete->SetBorderColor(wxColor("#FF6F00"));
m_button_delete->SetTextColor(wxColor("#FF6F00"));
m_button_delete->SetBorderColorNormal(wxColor("#FF6F00"));
m_button_delete->SetTextColorNormal(wxColor("#FF6F00"));
m_button_management->SetBorderWidth(0);
m_button_management->SetBackgroundColor(wxColor("#00AE42"));
m_button_management->SetBackgroundColorNormal(wxColor("#00AE42"));
wxBoxSizer *manage_sizer = new wxBoxSizer(wxHORIZONTAL);
manage_sizer->AddStretchSpacer(1);
@ -166,15 +166,16 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
// File management
m_button_management->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) {
e.Skip();
bool selecting = !m_image_grid->IsSelecting();
m_image_grid->SetSelecting(selecting);
m_button_management->SetLabel(selecting ? _L("Finish") : _L("Management"));
m_manage_panel->GetSizer()->Show(m_button_download, selecting);
m_manage_panel->GetSizer()->Show(m_button_delete, selecting);
m_manage_panel->Layout();
SetSelecting(!m_image_grid->IsSelecting());
});
m_button_download->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) {
m_image_grid->DoActionOnSelection(1);
SetSelecting(false);
});
m_button_delete->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) {
m_image_grid->DoActionOnSelection(0);
SetSelecting(false);
});
m_button_download->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { m_image_grid->DoActionOnSelection(1); });
m_button_delete->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { m_image_grid->DoActionOnSelection(0); });
auto onShowHide = [this](auto &e) {
e.Skip();
@ -214,6 +215,8 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
fs->Unbind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this);
fs->Stop(true);
}
m_button_management->Enable(false);
SetSelecting(false);
if (m_machine.empty()) {
m_image_grid->SetStatus(m_bmp_failed.bmp(), _L("No printers."));
} else if (m_lan_ip.empty() && (m_lan_mode && !m_tutk_support)) {
@ -223,8 +226,26 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
fs->Attached();
m_image_grid->SetFileType(m_last_type);
m_image_grid->SetFileSystem(fs);
fs->Bind(EVT_FILE_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
return;
m_button_management->Enable(fs->GetCount() > 0);
if (fs->GetCount() == 0)
SetSelecting(false);
});
fs->Bind(EVT_SELECT_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
return;
m_button_delete->Enable(e.GetInt() > 0);
m_button_download->Enable(e.GetInt() > 0);
});
fs->Bind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this);
fs->Bind(EVT_STATUS_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
return;
@ -271,6 +292,15 @@ void MediaFilePanel::Rescale()
m_image_grid->Rescale();
}
void MediaFilePanel::SetSelecting(bool selecting)
{
m_image_grid->SetSelecting(selecting);
m_button_management->SetLabel(selecting ? _L("Cancel") : _L("Select"));
m_manage_panel->GetSizer()->Show(m_button_download, selecting);
m_manage_panel->GetSizer()->Show(m_button_delete, selecting);
m_manage_panel->Layout();
}
void MediaFilePanel::modeChanged(wxCommandEvent& e1)
{
e1.Skip();

View file

@ -39,6 +39,8 @@ public:
public:
void Rescale();
void SetSelecting(bool selecting);
private:
void modeChanged(wxCommandEvent & e);

View file

@ -71,11 +71,13 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
{
std::string machine = obj ? obj->dev_id : "";
if (obj && obj->is_function_supported(PrinterFunction::FUNC_CAMERA_VIDEO)) {
m_lan_mode = obj->is_lan_mode_printer();
m_camera_exists = obj->has_ipcam;
m_lan_mode = obj->is_lan_mode_printer();
m_lan_ip = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->dev_ip : "";
m_lan_passwd = obj->access_code;
m_lan_passwd = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->access_code : "";
m_tutk_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
} else {
m_camera_exists = false;
m_lan_mode = false;
m_lan_ip.clear();
m_lan_passwd.clear();
@ -93,7 +95,7 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
if (m_next_retry.IsValid())
Play();
else
SetStatus("");
SetStatus("", false);
}
void MediaPlayCtrl::Play()
@ -102,12 +104,17 @@ void MediaPlayCtrl::Play()
return;
if (!IsShownOnScreen())
return;
if (m_last_state != MEDIASTATE_IDLE) {
return;
}
if (m_machine.empty()) {
Stop();
SetStatus(_L("Initialize failed (No Device)!"));
return;
}
if (m_last_state != MEDIASTATE_IDLE) {
if (!m_camera_exists) {
Stop();
SetStatus(_L("Initialize failed (No Camera Device)!"));
return;
}
@ -135,9 +142,17 @@ void MediaPlayCtrl::Play()
return;
}
if (m_lan_mode && !m_tutk_support) { // not support tutk
if (m_lan_mode) {
Stop();
SetStatus(_L("Initialize failed (Not supported)!"));
SetStatus(m_lan_passwd.empty()
? _L("Initialize failed (Not supported with LAN-only mode)!")
: _L("Initialize failed (Not accessible in LAN-only mode)!"));
return;
}
if (!m_tutk_support) { // not support tutk
Stop();
SetStatus(_L("Initialize failed (Not supported without remote video tunnel)!"));
return;
}
@ -145,14 +160,13 @@ void MediaPlayCtrl::Play()
if (agent) {
agent->get_camera_url(m_machine, [this, m = m_machine](std::string url) {
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
if (m != m_machine) return;
CallAfter([this, url] {
CallAfter([this, m, url] {
if (m != m_machine) return;
m_url = url;
if (m_last_state == MEDIASTATE_INITIALIZING) {
if (url.empty()) {
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
Stop();
m_failed_code = 1;
SetStatus(_L("Initialize failed [%d]!"));
SetStatus(wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
} else {
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
@ -179,7 +193,10 @@ void MediaPlayCtrl::Stop()
m_tasks.push_back("<stop>");
m_cond.notify_all();
m_last_state = MEDIASTATE_IDLE;
SetStatus(_L("Stopped."));
if (m_failed_code)
SetStatus(_L("Stopped [%d]!"), true);
else
SetStatus(_L("Stopped."), false);
if (m_failed_code >= 100) // not keep retry on local error
m_next_retry = wxDateTime();
}
@ -200,7 +217,7 @@ void MediaPlayCtrl::TogglePlay()
}
}
void MediaPlayCtrl::SetStatus(wxString const& msg2)
void MediaPlayCtrl::SetStatus(wxString const &msg2, bool hyperlink)
{
auto msg = wxString::Format(msg2, m_failed_code);
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data();
@ -211,10 +228,11 @@ void MediaPlayCtrl::SetStatus(wxString const& msg2)
#endif // __WXMSW__
m_label_status->SetLabel(msg);
long style = m_label_status->GetWindowStyle() & ~LB_HYPERLINK;
if (m_failed_code && msg != msg2) {
if (hyperlink) {
style |= LB_HYPERLINK;
}
m_label_status->SetWindowStyle(style);
m_label_status->InvalidateBestSize();
Layout();
}
@ -271,6 +289,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent& event)
}
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) &&
state == wxMEDIASTATE_STOPPED) {
m_failed_code = m_media_ctrl->GetLastError();
Stop();
return;
}
@ -280,7 +299,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent& event)
m_failed_code = m_media_ctrl->GetLastError();
if (size.GetWidth() > 1000) {
m_last_state = state;
SetStatus(_L("Playing..."));
SetStatus(_L("Playing..."), false);
m_failed_retry = 0;
boost::unique_lock lock(m_mutex);
m_tasks.push_back("<play>");
@ -291,9 +310,9 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent& event)
if (m_failed_code == 0)
m_failed_code = 2;
SetStatus(_L("Load failed [%d]!"));
} else {
m_last_state = last_state;
}
} else {
m_last_state = state;
}
}

View file

@ -44,7 +44,7 @@ protected:
void TogglePlay();
void SetStatus(wxString const & msg);
void SetStatus(wxString const &msg, bool hyperlink = true);
private:
void media_proc();
@ -61,6 +61,7 @@ private:
std::string m_lan_ip;
std::string m_lan_user;
std::string m_lan_passwd;
bool m_camera_exists = false;
bool m_lan_mode = false;
bool m_tutk_support = false;
wxString m_url;

View file

@ -177,16 +177,19 @@ MonitorPanel::~MonitorPanel()
m_connection_info->SetTextColor(*wxWHITE);
m_connection_info->SetFont(::Label::Body_13);
m_connection_info->SetCornerRadius(0);
m_connection_info->SetSize(wxSize(FromDIP(220), FromDIP(25)));
m_connection_info->SetMinSize(wxSize(FromDIP(220), FromDIP(25)));
m_connection_info->SetMaxSize(wxSize(FromDIP(220), FromDIP(25)));
m_connection_info->SetSize(wxSize(FromDIP(-1), FromDIP(25)));
m_connection_info->SetMinSize(wxSize(FromDIP(-1), FromDIP(25)));
m_connection_info->SetMaxSize(wxSize(FromDIP(-1), FromDIP(25)));
wxBoxSizer* connection_sizer = new wxBoxSizer(wxVERTICAL);
m_hyperlink = new wxHyperlinkCtrl(m_connection_info, wxID_ANY, _L("Failed to connect to the server"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
connection_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_hyperlink->SetBackgroundColour(wxColour(255, 111, 0));
m_connection_info->SetSizer(connection_sizer);
m_connection_info->Layout();
connection_sizer->Fit(m_connection_info);
m_connection_info->Hide();
/*sizer_boxv->Add(m_connection_info, 0, wxALIGN_CENTER, 0);
sizer_boxh->Add(sizer_boxv, 1, wxALIGN_CENTER, 0);
warning_panel->SetSizer(sizer_boxh);
warning_panel->Layout();*/
sizer_side_tools->Add(m_connection_info, 0, wxEXPAND, 0);
@ -201,13 +204,11 @@ MonitorPanel::~MonitorPanel()
m_status_info_panel = new StatusPanel(m_tabpanel);
m_tabpanel->AddPage(m_status_info_panel, _L("Status"), "", true);
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel = new MediaFilePanel(m_tabpanel);
m_tabpanel->AddPage(m_media_file_panel, _L("Media"), "", false);
m_upgrade_panel = new UpgradePanel(m_tabpanel);
m_tabpanel->AddPage(m_upgrade_panel, _L("Update"), "", false);
#endif
m_hms_panel = new HMSPanel(m_tabpanel);
m_tabpanel->AddPage(m_hms_panel, _L("HMS"),"", false);
@ -254,10 +255,8 @@ void MonitorPanel::msw_rescale()
m_tabpanel->Rescale();
//m_status_add_machine_panel->msw_rescale();
m_status_info_panel->msw_rescale();
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel->Rescale();
m_upgrade_panel->msw_rescale();
#endif
m_hms_panel->msw_rescale();
m_connection_info->SetCornerRadius(0);
@ -318,6 +317,7 @@ void MonitorPanel::on_printer_clicked(wxMouseEvent &event)
if (!m_side_tools->is_in_interval()) {
wxPoint pos = m_side_tools->ClientToScreen(wxPoint(0, 0));
pos.y += m_side_tools->GetRect().height;
pos.x = pos.x < 0? 0:pos.x;
m_select_machine.Position(pos, wxSize(0, 0));
#ifdef __linux__
@ -407,15 +407,11 @@ void MonitorPanel::update_all()
}
m_status_info_panel->obj = obj;
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(obj);
#endif
m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj);
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel->SetMachineObject(obj);
#endif
update_status(obj);
@ -514,9 +510,14 @@ void MonitorPanel::show_status(int status)
if (((status & (int) MonitorStatus::MONITOR_DISCONNECTED) != 0) || ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)) {
if ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER))
m_connection_info->SetLabel(_L("Failed to connect to the server"));
m_hyperlink->SetLabel(_L("Failed to connect to the server"));
//m_connection_info->SetLabel(_L("Failed to connect to the server"));
else
m_connection_info->SetLabel(_L("Failed to connect to the printer"));
m_hyperlink->SetLabel(_L("Failed to connect to the printer"));
//m_connection_info->SetLabel(_L("Failed to connect to the printer"));
m_hyperlink->Show();
m_connection_info->SetLabel(wxEmptyString);
m_connection_info->Show();
m_connection_info->SetBackgroundColor(wxColour(255, 111, 0));
m_connection_info->SetBorderColor(wxColour(255, 111, 0));
@ -526,6 +527,7 @@ void MonitorPanel::show_status(int status)
} else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
m_connection_info->Hide();
} else if ((status & (int) MonitorStatus::MONITOR_CONNECTING) != 0) {
m_hyperlink->Hide();
m_connection_info->SetLabel(_L("Connecting..."));
m_connection_info->SetBackgroundColor(wxColour(0, 174, 66));
m_connection_info->SetBorderColor(wxColour(0, 174, 66));

View file

@ -84,6 +84,7 @@ private:
UpgradePanel* m_upgrade_panel;
HMSPanel* m_hms_panel;
Button * m_connection_info{nullptr};
wxHyperlinkCtrl* m_hyperlink{nullptr};
/* side tools */
SideTools* m_side_tools{nullptr};

View file

@ -1,5 +1,6 @@
#include "NotificationManager.hpp"
#include "HintNotification.hpp"
#include "GUI.hpp"
#include "ImGuiWrapper.hpp"
#include "wxExtensions.hpp"
@ -1009,7 +1010,7 @@ void NotificationManager::PrintHostUploadNotification::init()
}
void NotificationManager::PrintHostUploadNotification::count_spaces()
{
//determine line width
//determine line width
m_line_height = ImGui::CalcTextSize("A").y;
m_left_indentation = m_line_height;
@ -1078,7 +1079,6 @@ void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper&
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2));
break;
}
imgui.text(text.c_str());
}
@ -1983,7 +1983,27 @@ int NotificationManager::progress_indicator_get_range() const
void NotificationManager::push_hint_notification(bool open_next)
{
return;
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::DidYouKnowHint) {
(dynamic_cast<HintNotification*>(notification.get()))->open_next();
return;
}
}
NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::HintNotificationLevel, 300, "" };
// from user - open now
if (!open_next) {
push_notification_data(std::make_unique<NotificationManager::HintNotification>(data, m_id_provider, m_evt_handler, open_next), 0);
stop_delayed_notifications_of_type(NotificationType::DidYouKnowHint);
// at startup - delay for half a second to let other notification pop up, than try every 30 seconds
// show only if no notifications are shown
}
else {
auto condition = [&self = std::as_const(*this)]() {
return self.get_notification_count() == 0;
};
push_delayed_notification_data(std::make_unique<NotificationManager::HintNotification>(data, m_id_provider, m_evt_handler, open_next), condition, 500, 30000);
}
}
bool NotificationManager::is_hint_notification_open()

View file

@ -257,7 +257,8 @@ public:
const t_opt_map& opt_map() const throw() { return m_opt_map; }
void set_config_category_and_type(const wxString &category, int type) { m_config_category = category; m_config_type = type; }
void set_config(DynamicPrintConfig* config) { m_config = config; m_modelconfig = nullptr; }
void set_config(DynamicPrintConfig* config) {
m_config = config; m_modelconfig = nullptr; }
Option get_option(const std::string& opt_key, int opt_index = -1);
Line create_single_option_line(const std::string& title, const std::string& path = std::string(), int idx = -1) /*const*/{
Option option = get_option(title, idx);

View file

@ -275,11 +275,61 @@ ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, c
wxVSCROLL) // hide hori-bar will cause hidden field mis-position
{
// ShowScrollBar(GetHandle(), SB_BOTH, FALSE);
Bind(wxEVT_SCROLL_CHANGED, [this](auto &e) {
wxWindow *child = dynamic_cast<wxWindow *>(e.GetEventObject());
if (child != this)
EnsureVisible(child);
});
}
virtual bool ShouldScrollToChildOnFocus(wxWindow *child)
{
EnsureVisible(child);
return false;
}
void EnsureVisible(wxWindow* win)
{
const wxRect viewRect(m_targetWindow->GetClientRect());
const wxRect winRect(m_targetWindow->ScreenToClient(win->GetScreenPosition()), win->GetSize());
if (viewRect.Contains(winRect)) {
return;
}
if (winRect.GetWidth() > viewRect.GetWidth() || winRect.GetHeight() > viewRect.GetHeight()) {
return;
}
int stepx, stepy;
GetScrollPixelsPerUnit(&stepx, &stepy);
int startx, starty;
GetViewStart(&startx, &starty);
// first in vertical direction:
if (stepy > 0) {
int diff = 0;
if (winRect.GetTop() < 0) {
diff = winRect.GetTop();
} else if (winRect.GetBottom() > viewRect.GetHeight()) {
diff = winRect.GetBottom() - viewRect.GetHeight() + 1;
// round up to next scroll step if we can't get exact position,
// so that the window is fully visible:
diff += stepy - 1;
}
starty = (starty * stepy + diff) / stepy;
}
// then horizontal:
if (stepx > 0) {
int diff = 0;
if (winRect.GetLeft() < 0) {
diff = winRect.GetLeft();
} else if (winRect.GetRight() > viewRect.GetWidth()) {
diff = winRect.GetRight() - viewRect.GetWidth() + 1;
// round up to next scroll step if we can't get exact position,
// so that the window is fully visible:
diff += stepx - 1;
}
startx = (startx * stepx + diff) / stepx;
}
Scroll(startx, starty);
}
};
m_page_view = new PageScrolledWindow(page_parent);

View file

@ -4106,7 +4106,7 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
ps.total_used_filament *= 1000; //koef
gcode_result->toolpath_outside = plate_data_list[i]->toolpath_outside;
m_plate_list[index]->slice_filaments_info = plate_data_list[i]->slice_filaments_info;
gcode_result->warnings = plate_data_list[i]->warnings;
if (!plate_data_list[i]->thumbnail_file.empty()) {
if (boost::filesystem::exists(plate_data_list[i]->thumbnail_file)) {
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file);

View file

@ -347,6 +347,7 @@ public:
Print* fff_print() { return m_print; }
//return the slice result
GCodeProcessorResult* get_slice_result() { return m_gcode_result; }
std::string get_tmp_gcode_path();
std::string get_temp_config_3mf_path();
//this API should only be used for command line usage

View file

@ -49,13 +49,51 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent) :
#ifndef _WIN32
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif
// input the preset name
Tab *tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
m_presets = tab->get_presets();
const Preset &sel_preset = m_presets->get_selected_preset();
std::string suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");
std::string preset_name = sel_preset.is_default ? "Untitled" : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.name;
auto input_sizer = new wxBoxSizer(wxVERTICAL);
wxStaticText *label_top = new wxStaticText(this, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as"))) % into_u8(tab->title())).str()));
label_top->SetFont(::Label::Body_13);
label_top->SetForegroundColour(wxColour(38,46,48));
m_input_area = new RoundedRectangle(this, wxColor(172, 172, 172), wxDefaultPosition, wxSize(-1,-1), 3, 1);
m_input_area->SetMinSize(wxSize(FromDIP(360), FromDIP(32)));
wxBoxSizer *input_sizer_h = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *input_sizer_v = new wxBoxSizer(wxVERTICAL);
m_input_ctrl = new wxTextCtrl(m_input_area, -1, from_u8(preset_name), wxDefaultPosition, wxSize(wxSize(FromDIP(360), FromDIP(32)).x, -1), 0 | wxBORDER_NONE);
m_input_ctrl->SetBackgroundColour(wxColour(255, 255, 255));
m_input_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent &) { update(); });
input_sizer_v->Add(m_input_ctrl, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 12);
input_sizer_h->Add(input_sizer_v, 0, wxALIGN_CENTER, 0);
m_input_area->SetSizer(input_sizer_h);
m_input_area->Layout();
m_valid_label = new wxStaticText(this, wxID_ANY, "");
m_valid_label->SetForegroundColour(wxColor(255, 111, 0));
input_sizer->Add(label_top, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, BORDER_W);
input_sizer->Add(m_input_area, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, BORDER_W);
input_sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W);
m_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config);
build_printhost_settings(m_optgroup);
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxButton* btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
wxGetApp().UpdateDarkUI(btnOK);
btnOK->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::OnOK, this);
@ -65,12 +103,13 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent) :
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
// topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
topSizer->Add(input_sizer , 0, wxEXPAND | wxALL, BORDER_W);
topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W);
topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W);
SetSizer(topSizer);
topSizer->SetSizeHints(this);
this->CenterOnScreen();
this->CenterOnParent();
}
PhysicalPrinterDialog::~PhysicalPrinterDialog()
@ -99,7 +138,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
auto printhost_browse = [=](wxWindow* parent)
{
auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots);
auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "printer_host_browser", _L("Browse") + " " + dots);
m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) {
BonjourDialog dialog(this, Preset::printer_technology(*m_config));
if (dialog.show_and_lookup()) {
@ -112,7 +151,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
};
auto print_host_test = [=](wxWindow* parent) {
auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test"));
auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "printer_host_test", _L("Test"));
m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
@ -139,7 +178,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
auto print_host_printers = [this, create_sizer_with_btn](wxWindow* parent) {
//add_scaled_button(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")), wxBU_LEFT | wxBU_EXACTFIT);
auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")));
auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "monitor_signal_strong", _(L("Refresh Printers")));
ScalableButton* btn = m_printhost_port_browse_btn;
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { update_printers(); });
@ -174,7 +213,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
Line cafile_line = m_optgroup->create_single_option_line(option);
auto printhost_cafile_browse = [=](wxWindow* parent) {
auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots);
auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "monitor_signal_strong", _L("Browse") + " " + dots);
m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, m_optgroup](wxCommandEvent e) {
static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*");
wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
@ -270,8 +309,88 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
void PhysicalPrinterDialog::update_printhost_buttons()
{
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
m_printhost_browse_btn->Enable(host->has_auto_discovery());
if (host) {
m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
m_printhost_browse_btn->Enable(host->has_auto_discovery());
}
}
void PhysicalPrinterDialog::update_preset_input() {
m_preset_name = into_u8(m_input_ctrl->GetValue());
m_valid_type = Valid;
wxString info_line;
const char *unusable_symbols = "<>[]:/\\|?*\"";
const std::string unusable_suffix = PresetCollection::get_suffix_modified(); //"(modified)";
for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
info_line = _L("Name is invalid;") + "\n" + _L("illegal characters:") + " " + unusable_symbols;
m_valid_type = NoValid;
break;
}
}
if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
info_line = _L("Name is invalid;") + "\n" + _L("illegal suffix:") + "\n\t" + from_u8(PresetCollection::get_suffix_modified());
m_valid_type = NoValid;
}
if (m_valid_type == Valid &&
(m_preset_name == "Default Setting" || m_preset_name == "Default Filament" || m_preset_name == "Default Printer")) {
info_line = _L("Name is unavailable.");
m_valid_type = NoValid;
}
const Preset *existing = m_presets->find_preset(m_preset_name, false);
if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) {
info_line = _L("Overwrite a system profile is not allowed");
m_valid_type = NoValid;
}
if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name()) {
if (existing->is_compatible)
info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists.")) % m_preset_name).str());
else
info_line = from_u8((boost::format(_u8L("Preset \"%1%\" already exists and is incompatible with current printer.")) % m_preset_name).str());
info_line += "\n" + _L("Please note that saving action will replace this preset");
m_valid_type = Warning;
}
if (m_valid_type == Valid && m_preset_name.empty()) {
info_line = _L("The name is not allowed to be empty.");
m_valid_type = NoValid;
}
if (m_valid_type == Valid && m_preset_name.find_first_of(' ') == 0) {
info_line = _L("The name is not allowed to start with space character.");
m_valid_type = NoValid;
}
if (m_valid_type == Valid && m_preset_name.find_last_of(' ') == m_preset_name.length() - 1) {
info_line = _L("The name is not allowed to end with space character.");
m_valid_type = NoValid;
}
if (m_valid_type == Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) {
info_line = _L("The name cannot be the same as a preset alias name.");
m_valid_type = NoValid;
}
m_valid_label->SetLabel(info_line);
m_input_area->Refresh();
m_valid_label->Show(!info_line.IsEmpty());
if (m_valid_type == NoValid) {
if (btnOK)
btnOK->Disable();
}
else {
if (btnOK)
btnOK->Enable();
}
}
void PhysicalPrinterDialog::update(bool printer_change)
@ -317,6 +436,8 @@ void PhysicalPrinterDialog::update(bool printer_change)
m_optgroup->show_field("printhost_port", supports_multiple_printers);
m_printhost_port_browse_btn->Show(supports_multiple_printers);
update_preset_input();
update_printhost_buttons();
this->SetSize(this->GetBestSize());
@ -395,7 +516,7 @@ void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect)
void PhysicalPrinterDialog::OnOK(wxEvent& event)
{
wxGetApp().get_tab(Preset::TYPE_PRINTER)->save_preset();
wxGetApp().get_tab(Preset::TYPE_PRINTER)->save_preset("", false, false, true, m_preset_name );
event.Skip();
}

View file

@ -7,6 +7,7 @@
#include "libslic3r/Preset.hpp"
#include "GUI_Utils.hpp"
#include "Widgets/RoundedRectangle.hpp"
class wxString;
class wxTextCtrl;
@ -34,6 +35,10 @@ class PhysicalPrinterDialog : public DPIDialog
ScalableButton* m_printhost_client_cert_browse_btn {nullptr};
ScalableButton* m_printhost_port_browse_btn {nullptr};
RoundedRectangle* m_input_area {nullptr};
wxStaticText* m_valid_label {nullptr};
wxTextCtrl* m_input_ctrl {nullptr};
wxButton* btnOK {nullptr};
void build_printhost_settings(ConfigOptionsGroup* optgroup);
void OnOK(wxEvent& event);
@ -42,8 +47,19 @@ public:
PhysicalPrinterDialog(wxWindow* parent);
~PhysicalPrinterDialog();
enum ValidationType
{
Valid,
NoValid,
Warning
};
PresetCollection* m_presets {nullptr};
ValidationType m_valid_type;
std::string m_preset_name;
void update(bool printer_change = false);
void update_host_type(bool printer_change);
void update_preset_input();
void update_printhost_buttons();
void update_printers();

View file

@ -84,6 +84,7 @@
#include "Jobs/NotificationProgressIndicator.hpp"
#include "BackgroundSlicingProcess.hpp"
#include "SelectMachine.hpp"
#include "SendToPrinter.hpp"
#include "PublishDialog.hpp"
#include "ConfigWizard.hpp"
#include "../Utils/ASCIIFolding.hpp"
@ -151,6 +152,8 @@ wxDEFINE_EVENT(EVT_PUBLISH, wxCommandEvent);
// BBS: backup & restore
wxDEFINE_EVENT(EVT_RESTORE_PROJECT, wxCommandEvent);
wxDEFINE_EVENT(EVT_PRINT_FINISHED, wxCommandEvent);
wxDEFINE_EVENT(EVT_SEND_FINISHED, wxCommandEvent);
wxDEFINE_EVENT(EVT_PUBLISH_FINISHED, wxCommandEvent);
//BBS: repair model
wxDEFINE_EVENT(EVT_REPAIR_MODEL, wxCommandEvent);
wxDEFINE_EVENT(EVT_FILAMENT_COLOR_CHANGED, wxCommandEvent);
@ -504,17 +507,17 @@ Sidebar::Sidebar(Plater *parent)
combo_printer->edit_btn = edit_btn;
p->combo_printer = combo_printer;
ScalableButton* connection_btn = new ScalableButton(p->m_panel_printer_content, wxID_ANY, "monitor_signal_strong");
connection_btn = new ScalableButton(p->m_panel_printer_content, wxID_ANY, "monitor_signal_strong");
connection_btn->SetBackgroundColour(wxColour(255, 255, 255));
connection_btn->SetToolTip(_L("Connection"));
connection_btn->Bind(wxEVT_BUTTON, [this, combo_printer](wxCommandEvent)
{
PhysicalPrinterDialog dlg(this->GetParent());
dlg.ShowModal();
});
{
PhysicalPrinterDialog dlg(this->GetParent());
dlg.ShowModal();
});
wxBoxSizer *vsizer_printer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *hsizer_printer = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* vsizer_printer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* hsizer_printer = new wxBoxSizer(wxHORIZONTAL);
hsizer_printer->Add(combo_printer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
hsizer_printer->Add(edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
@ -706,7 +709,7 @@ Sidebar::Sidebar(Plater *parent)
bSizer39->Add(del_btn, 0, wxALIGN_CENTER_VERTICAL, FromDIP(5));
bSizer39->Add(FromDIP(20), 0, 0, 0, 0);
ScalableButton *ams_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "ams_fila_sync", wxEmptyString, wxDefaultSize, wxDefaultPosition,
ams_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "ams_fila_sync", wxEmptyString, wxDefaultSize, wxDefaultPosition,
wxBU_EXACTFIT | wxNO_BORDER, false, 18);
ams_btn->SetToolTip(_L("Sync material list from AMS"));
ams_btn->Bind(wxEVT_BUTTON, [this, scrolled_sizer](wxCommandEvent &e) {
@ -906,6 +909,21 @@ void Sidebar::update_all_preset_comboboxes()
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
bool is_bbl_preset = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
if (is_bbl_preset) {
//only show connection button for not-BBL printer
connection_btn->Hide();
//only show sync-ams button for BBL printer
ams_btn->Show();
//update print button default value for bbl or third-party printer
wxGetApp().mainframe->set_print_button_to_default(MainFrame::PrintSelectType::ePrintPlate);
} else {
connection_btn->Show();
ams_btn->Hide();
wxGetApp().mainframe->set_print_button_to_default(MainFrame::PrintSelectType::eSendGcode);
}
// Update the print choosers to only contain the compatible presets, update the dirty flags.
//BBS
@ -1472,6 +1490,7 @@ struct Plater::priv
MenuFactory menus;
SelectMachineDialog* m_select_machine_dlg = nullptr;
SendToPrinterDialog* m_send_to_sdcard_dlg = nullptr;
PublishDialog *m_publish_dlg = nullptr;
// Data
@ -1594,6 +1613,7 @@ struct Plater::priv
std::string label_btn_send;
bool show_render_statistic_dialog{ false };
bool show_wireframe{ false };
static const std::regex pattern_bundle;
static const std::regex pattern_3mf;
@ -1671,6 +1691,7 @@ struct Plater::priv
// BBS
void hide_select_machine_dlg() { m_select_machine_dlg->EndModal(wxID_OK); }
void hide_send_to_printer_dlg() { m_send_to_sdcard_dlg->EndModal(wxID_OK); }
void update_preview_bottom_toolbar();
@ -1850,6 +1871,7 @@ struct Plater::priv
void on_action_print_all(SimpleEvent&);
void on_action_export_gcode(SimpleEvent&);
void on_action_send_gcode(SimpleEvent&);
void on_action_upload_gcode(SimpleEvent&);
void on_action_export_sliced_file(SimpleEvent&);
void on_action_select_sliced_plate(wxCommandEvent& evt);
@ -1931,14 +1953,14 @@ struct Plater::priv
void update_fff_scene_only_shells(bool only_shells = true);
//BBS: add popup object table logic
bool PopupObjectTable(int object_id, int volume_id, const wxPoint& position);
void on_action_send_to_printer();
private:
void update_fff_scene();
void update_sla_scene();
void undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator it_snapshot);
void update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool temp_snapshot_was_taken = false);
void on_action_export_to_sdcard(SimpleEvent&);
// path to project folder stored with no extension
boost::filesystem::path m_project_folder;
@ -2201,7 +2223,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
preview->on_tick_changed(tick_event_type);
// BBS set to invalid state only
if (tick_event_type == Type::ToolChange) {
if (tick_event_type == Type::ToolChange || tick_event_type == Type::Custom || tick_event_type == Type::Template) {
PartPlate *plate = this->q->get_partplate_list().get_curr_plate();
if (plate) {
plate->update_slice_result_valid_state(false);
@ -2239,11 +2261,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
q->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
q->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this);
q->Bind(EVT_GLTOOLBAR_SEND_GCODE, &priv::on_action_send_gcode, this);
q->Bind(EVT_GLTOOLBAR_UPLOAD_GCODE, &priv::on_action_upload_gcode, this);
q->Bind(EVT_GLTOOLBAR_EXPORT_SLICED_FILE, &priv::on_action_export_sliced_file, this);
q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER, &priv::on_action_export_to_sdcard, this);
q->Bind(EVT_GLCANVAS_PLATE_SELECT, &priv::on_plate_selected, this);
q->Bind(EVT_DOWNLOAD_PROJECT, &priv::on_action_download_project, this);
q->Bind(EVT_IMPORT_MODEL_ID, &priv::on_action_request_model_id, this);
q->Bind(EVT_PRINT_FINISHED, [q](wxCommandEvent &evt) { q->print_job_finished(evt); });
q->Bind(EVT_SEND_FINISHED, [q](wxCommandEvent &evt) { q->send_job_finished(evt); });
q->Bind(EVT_PUBLISH_FINISHED, [q](wxCommandEvent &evt) { q->publish_job_finished(evt);});
//q->Bind(EVT_GLVIEWTOOLBAR_ASSEMBLE, [q](SimpleEvent&) { q->select_view_3D("Assemble"); });
}
@ -2514,6 +2540,16 @@ wxColour Plater::get_next_color_for_filament()
return colors[curr_color_filamenet++ % 7];
}
wxString Plater::get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning)
{
if (warning.msg == BED_TEMP_TOO_HIGH_THAN_FILAMENT) {
return _L("The bed temperature exceeds filament's vitrification temperature. Please open the front door of printer before printing to avoid nozzle clog.");
}
else {
return wxString(warning.msg);
}
}
void Plater::priv::apply_free_camera_correction(bool apply/* = true*/)
{
bool use_perspective_camera = get_config("use_perspective_camera").compare("true") == 0;
@ -3467,8 +3503,12 @@ fs::path Plater::priv::get_export_file_path(GUI::FileType file_type)
// for 3mf take the path from the project filename, if any
output_file = into_path(get_project_filename(".3mf"));
if (output_file.empty())
output_file = into_path(get_project_name() + ".3mf");
//bbs name the project using the part name
if (output_file.empty()) {
if (get_project_name() != _L("Untitled")) {
output_file = into_path(get_project_name() + ".3mf");
}
}
if (output_file.empty())
{
@ -5647,6 +5687,14 @@ void Plater::priv::on_action_print_plate(SimpleEvent&)
m_select_machine_dlg->ShowModal();
}
void Plater::priv::on_action_send_to_printer()
{
if (!m_send_to_sdcard_dlg) m_send_to_sdcard_dlg = new SendToPrinterDialog(q);
m_send_to_sdcard_dlg->prepare(partplate_list.get_curr_plate_index());
m_send_to_sdcard_dlg->ShowModal();
}
void Plater::priv::on_action_select_sliced_plate(wxCommandEvent &evt)
{
if (q != nullptr) {
@ -5677,11 +5725,19 @@ void Plater::priv::on_action_export_gcode(SimpleEvent&)
}
}
void Plater::priv::on_action_upload_gcode(SimpleEvent&)
{
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export gcode event\n";
q->send_gcode_legacy(-1, nullptr, true);
}
}
void Plater::priv::on_action_send_gcode(SimpleEvent&)
{
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export gcode event\n" ;
q->send_gcode_legacy();
q->send_gcode_legacy(-1, nullptr, false);
}
}
@ -5693,6 +5749,14 @@ void Plater::priv::on_action_export_sliced_file(SimpleEvent&)
}
}
void Plater::priv::on_action_export_to_sdcard(SimpleEvent&)
{
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export sliced file event\n";
q->send_to_printer();
}
}
//BBS: add plate select logic
void Plater::priv::on_plate_selected(SimpleEvent&)
{
@ -6072,11 +6136,22 @@ void Plater::get_print_job_data(PrintPrepareData* data)
data->_3mf_config_path = p->m_print_job_data._3mf_config_path;
}
}
int Plater::get_print_finished_event()
{
return EVT_PRINT_FINISHED;
}
int Plater::get_send_finished_event()
{
return EVT_SEND_FINISHED;
}
int Plater::get_publish_finished_event()
{
return EVT_PUBLISH_FINISHED;
}
void Plater::priv::set_current_canvas_as_dirty()
{
if (current_panel == view3D)
@ -7123,6 +7198,11 @@ void Plater::add_model(bool imperial_units/* = false*/)
auto strategy = LoadStrategy::LoadModel;
if (imperial_units) strategy = strategy | LoadStrategy::ImperialUnits;
if (!load_files(paths, strategy, ask_multi).empty()) {
if (get_project_name() == _L("Untitled") && paths.size() > 0) {
p->set_project_filename(wxString(paths[0].string()));
}
wxGetApp().mainframe->update_title();
}
}
@ -8315,6 +8395,11 @@ void Plater::export_gcode(bool prefer_removable)
}
}
void Plater::send_to_printer()
{
p->on_action_send_to_printer();
}
//BBS export gcode 3mf to file
void Plater::export_gcode_3mf()
{
@ -8952,7 +9037,7 @@ void Plater::reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &
// and let the background processing start.
this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART);
}
void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool upload_only)
{
// if physical_printer is selected, send gcode for this printer
// DynamicPrintConfig* physical_printer_config = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config();
@ -8989,7 +9074,7 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
wxBusyCursor wait;
upload_job.printhost->get_groups(groups);
}
PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups);
if (dlg.ShowModal() == wxID_OK) {
upload_job.upload_data.upload_path = dlg.filename();
@ -9020,7 +9105,7 @@ int Plater::send_gcode(int plate_idx, Export3mfProgressFn proFn)
return -1;
}
SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithGcode;
SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithGcode | SaveStrategy::SkipAuxiliary;
#if !BBL_RELEASE_TO_PUBLIC
//only save model in QA environment
std::string sel = get_app_config()->get("iot_environment");
@ -9053,7 +9138,7 @@ int Plater::export_config_3mf(int plate_idx, Export3mfProgressFn proFn)
return -1;
}
SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithSliceInfo;
SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithSliceInfo | SaveStrategy::SkipAuxiliary;
result = export_3mf(p->m_print_job_data._3mf_config_path, strategy, plate_idx, proFn);
return result;
@ -9074,6 +9159,26 @@ void Plater::print_job_finished(wxCommandEvent &evt)
curr_monitor->get_tabpanel()->ChangeSelection(MonitorPanel::PrinterTab::PT_STATUS);
}
void Plater::send_job_finished(wxCommandEvent& evt)
{
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
dev->set_selected_machine(evt.GetString().ToStdString());
p->hide_send_to_printer_dlg();
//p->main_frame->request_select_tab(MainFrame::TabPosition::tpMonitor);
////jump to monitor and select device status panel
//MonitorPanel* curr_monitor = p->main_frame->m_monitor;
//if (curr_monitor)
// curr_monitor->get_tabpanel()->ChangeSelection(MonitorPanel::PrinterTab::PT_STATUS);
}
void Plater::publish_job_finished(wxCommandEvent &evt)
{
p->m_publish_dlg->EndModal(wxID_OK);
GUI::wxGetApp().load_url(evt.GetString());
}
// Called when the Eject button is pressed.
void Plater::eject_drive()
{
@ -10459,6 +10564,16 @@ bool Plater::is_render_statistic_dialog_visible() const
return p->show_render_statistic_dialog;
}
void Plater::toggle_show_wireframe()
{
p->show_wireframe = !p->show_wireframe;
}
bool Plater::is_show_wireframe() const
{
return p->show_wireframe;
}
/*Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name)
: TakeSnapshot(plater, from_u8(snapshot_name)) {}
@ -10526,4 +10641,4 @@ SuppressBackgroundProcessingUpdate::~SuppressBackgroundProcessingUpdate()
wxGetApp().plater()->schedule_background_process(m_was_scheduled);
}
}} // namespace Slic3r::GUI
}} // namespace Slic3r::GUI

View file

@ -20,6 +20,7 @@
#include "PartPlate.hpp"
#include "GUI_App.hpp"
#include "Jobs/PrintJob.hpp"
#include "Jobs/SendJob.hpp"
#include "libslic3r/Model.hpp"
class wxButton;
@ -160,6 +161,8 @@ private:
wxBoxSizer* m_scrolled_sizer = nullptr;
ComboBox* m_bed_type_list = nullptr;
ScalableButton* connection_btn = nullptr;
ScalableButton* ams_btn = nullptr;
};
class Plater: public wxPanel
@ -232,6 +235,7 @@ public:
static void setPrintSpeedTable(Slic3r::GlobalSpeedMap& printSpeedMap);
static void setExtruderParams(std::map<size_t, Slic3r::ExtruderParams>& extParas);
static wxColour get_next_color_for_filament();
static wxString get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning);
// BBS: restore
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, LoadStrategy strategy = LoadStrategy::LoadModel | LoadStrategy::LoadConfig, bool ask_multi = false);
@ -296,6 +300,7 @@ public:
void segment(size_t obj_idx, size_t instance_idx, double smoothing_alpha=0.5, int segment_number=5);
void merge(size_t obj_idx, std::vector<int>& vol_indeces);
void send_to_printer();
void export_gcode(bool prefer_removable);
void export_gcode_3mf();
void export_core_3mf();
@ -330,10 +335,12 @@ public:
/* -1: send current gcode if not specified
* -2: send all gcode to target machine */
int send_gcode(int plate_idx = -1, Export3mfProgressFn proFn = nullptr);
void send_gcode_legacy(int plate_idx = -1, Export3mfProgressFn proFn = nullptr);
void send_gcode_legacy(int plate_idx = -1, Export3mfProgressFn proFn = nullptr, bool upload_only = false);
int export_config_3mf(int plate_idx = -1, Export3mfProgressFn proFn = nullptr);
//BBS jump to nonitor after print job finished
void print_job_finished(wxCommandEvent &evt);
void send_job_finished(wxCommandEvent& evt);
void publish_job_finished(wxCommandEvent& evt);
void eject_drive();
void take_snapshot(const std::string &snapshot_name);
@ -397,6 +404,8 @@ public:
//BBS: add print job releated functions
void get_print_job_data(PrintPrepareData* data);
int get_print_finished_event();
int get_send_finished_event();
int get_publish_finished_event();
void set_current_canvas_as_dirty();
void unbind_canvas_event_handlers();
@ -613,6 +622,9 @@ public:
void toggle_render_statistic_dialog();
bool is_render_statistic_dialog_visible() const;
void toggle_show_wireframe();
bool is_show_wireframe() const;
// Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu.
bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition);
bool PopupMenu(wxMenu *menu, int x, int y) { return this->PopupMenu(menu, wxPoint(x, y)); }
@ -675,4 +687,4 @@ private:
} // namespace GUI
} // namespace Slic3r
#endif
#endif

View file

@ -457,9 +457,12 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
m_sizer_checkbox->Add(checkbox, 0, wxALIGN_CENTER, 0);
m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 8);
auto checkbox_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxSize(-1, -1), 0);
auto checkbox_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0);
checkbox_title->SetForegroundColour(DESIGN_GRAY900_COLOR);
checkbox_title->SetFont(::Label::Body_13);
auto size = checkbox_title->GetTextExtent(title);
checkbox_title->SetMinSize(wxSize(size.x + FromDIP(40), -1));
checkbox_title->Wrap(-1);
m_sizer_checkbox->Add(checkbox_title, 0, wxALIGN_CENTER | wxALL, 3);
@ -526,6 +529,57 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
return m_sizer_checkbox;
}
wxWindow* PreferencesDialog::create_item_downloads(wxWindow* parent, int padding_left, std::string param)
{
wxString download_path = wxString::FromUTF8(app_config->get("download_path"));
auto item_panel = new wxWindow(parent, wxID_ANY);
item_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer* m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL);
m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23);
auto m_staticTextPath = new wxStaticText(item_panel, wxID_ANY, download_path, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
//m_staticTextPath->SetMaxSize(wxSize(FromDIP(440), -1));
m_staticTextPath->SetForegroundColour(DESIGN_GRAY600_COLOR);
m_staticTextPath->SetFont(::Label::Body_13);
m_staticTextPath->Wrap(-1);
auto m_button_download = new Button(item_panel, _L("Browse"));
StateColor abort_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
m_button_download->SetBackgroundColor(abort_bg);
StateColor abort_bd(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
m_button_download->SetBorderColor(abort_bd);
StateColor abort_text(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
m_button_download->SetTextColor(abort_text);
m_button_download->SetFont(Label::Body_10);
m_button_download->SetMinSize(wxSize(FromDIP(58), FromDIP(22)));
m_button_download->SetSize(wxSize(FromDIP(58), FromDIP(22)));
m_button_download->SetCornerRadius(FromDIP(12));
m_button_download->Bind(wxEVT_BUTTON, [this, m_staticTextPath, item_panel](auto& e) {
wxString defaultPath = wxT("/");
wxDirDialog dialog(this, _L("Choose Download Directory"), defaultPath, wxDD_NEW_DIR_BUTTON);
if (dialog.ShowModal() == wxID_OK) {
wxString download_path = dialog.GetPath();
std::string download_path_str = download_path.ToUTF8().data();
app_config->set("download_path", download_path_str);
m_staticTextPath->SetLabelText(download_path);
item_panel->Layout();
}
});
m_sizer_checkbox->Add(m_staticTextPath, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
m_sizer_checkbox->Add(m_button_download, 0, wxALL, FromDIP(5));
item_panel->SetSizer(m_sizer_checkbox);
item_panel->Layout();
return item_panel;
}
wxWindow *PreferencesDialog ::create_item_radiobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, int groupid, std::string param)
{
wxWindow *item = new wxWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(28)));
@ -688,6 +742,8 @@ wxWindow* PreferencesDialog::create_general_page()
std::vector<wxString> Units = {_L("Metric"), _L("Imperial")};
auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units);
auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints");
auto title_sync_settings = create_item_title(_L("User sync"), page, _L("User sync"));
auto item_user_sync = create_item_checkbox(_L("Auto sync user presets(Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset");
@ -709,10 +765,15 @@ wxWindow* PreferencesDialog::create_general_page()
auto item_backup = create_item_checkbox(_L("Auto-Backup"), page,_L("Auto-Backup"), 50, "backup_switch");
auto item_backup_interval = create_item_backup_input(_L("Backup interval"), page, _L("Backup interval"), "backup_interval");
//downloads
auto title_downloads = create_item_title(_L("Downloads"), page, _L("Downloads"));
auto item_downloads = create_item_downloads(page,50,"download_path");
sizer_page->Add(title_general_settings, 0, wxEXPAND, 0);
sizer_page->Add(item_language, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_region, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_currency, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
sizer_page->Add(title_sync_settings, 0, wxTOP | wxEXPAND, FromDIP(20));
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
#ifdef _WIN32
@ -726,6 +787,9 @@ wxWindow* PreferencesDialog::create_general_page()
sizer_page->Add(item_backup_interval, 0, wxTOP,FromDIP(3));
//sizer_page->Add(0, 0, 0, wxTOP, 26);
sizer_page->Add(title_downloads, 0, wxTOP| wxEXPAND, FromDIP(20));
sizer_page->Add(item_downloads, 0, wxEXPAND, FromDIP(3));
page->SetSizer(sizer_page);
page->Layout();

View file

@ -20,6 +20,7 @@ namespace Slic3r { namespace GUI {
#define DESIGN_SELECTOR_NOMORE_COLOR wxColour(248, 248, 248)
#define DESIGN_GRAY900_COLOR wxColour(38, 46, 48)
#define DESIGN_GRAY800_COLOR wxColour(50, 58, 61)
#define DESIGN_GRAY600_COLOR wxColour(144, 144, 144)
#define DESIGN_GRAY400_COLOR wxColour(166, 169, 170)
class Selector
@ -106,7 +107,8 @@ public:
wxBoxSizer *create_item_language_combobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param, std::vector<const wxLanguageInfo *> vlist);
wxBoxSizer *create_item_loglevel_combobox(wxString title, wxWindow *parent, wxString tooltip, std::vector<wxString> vlist);
wxBoxSizer *create_item_checkbox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param);
wxBoxSizer *create_item_backup_checkbox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param);
wxWindow* create_item_downloads(wxWindow* parent, int padding_left, std::string param);
wxBoxSizer* create_item_backup_checkbox(wxString title, wxWindow* parent, wxString tooltip, int padding_left, std::string param);
wxBoxSizer *create_item_backup_input(wxString title, wxWindow *parent, wxString tooltip, std::string param);
wxBoxSizer *create_item_multiple_combobox(
wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string parama, std::vector<wxString> vlista, std::vector<wxString> vlistb);
@ -125,7 +127,6 @@ public:
void create_select_domain_widget();
void Split(const std::string &src, const std::string &separator, std::vector<wxString> &dest);
int m_current_language_selected = {0};
protected:

View file

@ -50,8 +50,9 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _L("Use forward slashes ( / ) as a directory separator if needed."));
label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
content_sizer->Add(txt_filename, 0, wxEXPAND);
content_sizer->Add(label_dir_hint);
content_sizer->Add(txt_filename, 0, wxEXPAND | wxALL, FromDIP(10));
content_sizer->Add(FromDIP(10), FromDIP(10), 0, 0);
content_sizer->Add(label_dir_hint, 0, 0, FromDIP(10));
content_sizer->AddSpacer(VERT_SPACING);
if (combo_groups != nullptr) {

View file

@ -1,28 +1,35 @@
#pragma once
#ifndef _BAMBU__TUNNEL_H_
#define _BAMBU__TUNNEL_H_
#ifdef BAMBU_DYNAMIC
# define BAMBU_EXPORT
# define BAMBU_FUNC(x) (*x)
#else
# ifdef __WIN32__
# define BAMBU_EXPORT __declspec(dllexport)
# ifdef _WIN32
# ifdef BAMBU_EXPORTS
# define BAMBU_EXPORT __declspec(dllexport)
# else
# define BAMBU_EXPORT __declspec(dllimport)
# endif // BAMBU_EXPORTS
# else
# define BAMBU_EXPORT
# endif // __WIN32__
# define BAMBU_FUNC(x) x
#endif
#endif // BAMBU_DYNAMIC
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct Bambu_Session;
#ifdef __WIN32__
typedef wchar_t Bambu_Message;
#ifdef _WIN32
typedef wchar_t tchar;
#else
typedef char Bambu_Message;
typedef char tchar;
#endif
typedef void (*Logger)(Bambu_Session * session, int level, Bambu_Message const * msg);
typedef void* Bambu_Tunnel;
typedef void (*Logger)(void * context, int level, tchar const* msg);
enum Bambu_StreamType
{
@ -89,48 +96,39 @@ enum Bambu_Error
{
Bambu_success,
Bambu_stream_end,
Bambu_would_block
};
struct Bambu_Session
{
int gSID = -1;
int avIndex = -1;
int block = 0;
int block_next = 0;
Logger logger = nullptr;
void * buffer = nullptr;
int buffer_size = 0;
void * extra = 0;
void * dump_file1 = nullptr;
void * dump_file2 = nullptr;
void Log(int unused, int level, wchar_t const * format, ...);
Bambu_would_block,
Bambu_buffer_limit
};
#ifdef BAMBU_DYNAMIC
struct BambuLib {
#endif
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Open)(Bambu_Session* session, char const* uid);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Create)(Bambu_Tunnel* tunnel, char const* path);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_StartStream)(Bambu_Session* session);
BAMBU_EXPORT void BAMBU_FUNC(Bambu_SetLogger)(Bambu_Tunnel tunnel, Logger logger, void * context);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_GetStreamCount)(Bambu_Session* session);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Open)(Bambu_Tunnel tunnel);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_GetStreamInfo)(Bambu_Session* session, int index, Bambu_StreamInfo* info);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_StartStream)(Bambu_Tunnel tunnel, bool video);
BAMBU_EXPORT unsigned long BAMBU_FUNC(Bambu_GetDuration)(Bambu_Session* session);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_GetStreamCount)(Bambu_Tunnel tunnel);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Seek)(Bambu_Session* session, unsigned long time);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_GetStreamInfo)(Bambu_Tunnel tunnel, int index, Bambu_StreamInfo* info);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_ReadSample)(Bambu_Session* session, Bambu_Sample* sample);
BAMBU_EXPORT unsigned long BAMBU_FUNC(Bambu_GetDuration)(Bambu_Tunnel tunnel);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_SendMessage)(Bambu_Session* session, int ctrl, char const* data, int len);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Seek)(Bambu_Tunnel tunnel, unsigned long time);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_RecvMessage)(Bambu_Session* session, int* ctrl, char* data, int* len);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_ReadSample)(Bambu_Tunnel tunnel, Bambu_Sample* sample);
BAMBU_EXPORT void BAMBU_FUNC(Bambu_Close)(Bambu_Session* session);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_SendMessage)(Bambu_Tunnel tunnel, int ctrl, char const* data, int len);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_RecvMessage)(Bambu_Tunnel tunnel, int* ctrl, char* data, int* len);
BAMBU_EXPORT void BAMBU_FUNC(Bambu_Close)(Bambu_Tunnel tunnel);
BAMBU_EXPORT void BAMBU_FUNC(Bambu_Destroy)(Bambu_Tunnel tunnel);
BAMBU_EXPORT int BAMBU_FUNC(Bambu_Init)();
@ -138,7 +136,7 @@ BAMBU_EXPORT void BAMBU_FUNC(Bambu_Deinit)();
BAMBU_EXPORT char const* BAMBU_FUNC(Bambu_GetLastErrorMsg)();
BAMBU_EXPORT void BAMBU_FUNC(Bambu_FreeLogMsg)(Bambu_Message const* msg);
BAMBU_EXPORT void BAMBU_FUNC(Bambu_FreeLogMsg)(tchar const* msg);
#ifdef BAMBU_DYNAMIC
};
@ -147,3 +145,5 @@ BAMBU_EXPORT void BAMBU_FUNC(Bambu_FreeLogMsg)(Bambu_Message const* msg);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _BAMBU__TUNNEL_H_

View file

@ -2,6 +2,7 @@
#include "libslic3r/Utils.hpp"
#include "../../Utils/NetworkAgent.hpp"
#include "../BitmapCache.hpp"
#include <boost/algorithm/hex.hpp>
#include <boost/uuid/detail/md5.hpp>
@ -10,9 +11,14 @@
#include <cstring>
#ifndef NDEBUG
//#define PRINTER_FILE_SYSTEM_TEST
#endif
wxDEFINE_EVENT(EVT_STATUS_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_MODE_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
wxDEFINE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
@ -22,21 +28,26 @@ static wxBitmap default_thumbnail;
struct StaticBambuLib : BambuLib {
static StaticBambuLib & get();
static int Fake_Bambu_Open(Bambu_Session * session, char const* uid) { return -2; }
static int Fake_Bambu_Create(Bambu_Tunnel*, char const*) { return -2; }
};
PrinterFileSystem::PrinterFileSystem()
: BambuLib(StaticBambuLib::get())
{
if (!default_thumbnail.IsOk())
default_thumbnail = wxImage(Slic3r::encode_path(Slic3r::var("live_stream_default.png").c_str()));
default_thumbnail = *Slic3r::GUI::BitmapCache().load_svg("printer_file", 0, 0);
m_session.owner = this;
//auto time = wxDateTime::Now();
//for (int i = 0; i < 240; ++i) {
// m_file_list.push_back({"", time.GetTicks(), 0, default_thumbnail, FF_DOWNLOAD, i - 130});
// time.Add(wxDateSpan::Days(-1));
//}
//BuildGroups();
#ifdef PRINTER_FILE_SYSTEM_TEST
auto time = wxDateTime::Now();
for (int i = 0; i < 100; ++i) {
auto name = wxString::Format(L"img-%03d.jpg", i + 1);
wxImage im(L"D:\\work\\pic\\" + name);
m_file_list.push_back({name.ToUTF8().data(), time.GetTicks(), 26937, im, i < 20 ? FF_DOWNLOAD : 0, i * 10 - 40});
time.Add(wxDateSpan::Days(-1));
}
m_file_list[0].thumbnail = default_thumbnail;
BuildGroups();
#endif
}
PrinterFileSystem::~PrinterFileSystem()
@ -102,6 +113,7 @@ void PrinterFileSystem::ListAllFiles()
iter1->thumbnail = iter2->thumbnail;
iter1->flags = iter2->flags;
iter1->progress = iter2->progress;
iter1->path = iter2->path;
++iter1; ++iter2;
} else if (*iter1 < *iter2) {
++iter1;
@ -154,6 +166,7 @@ void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path)
if ((file.flags & FF_DOWNLOAD) != 0 && file.progress >= 0) continue;
file.flags |= FF_DOWNLOAD;
file.progress = -1;
file.path = (boost::filesystem::path(path) / file.name).string();
++n;
}
if (n == 0) return;
@ -165,9 +178,40 @@ void PrinterFileSystem::DownloadFiles(size_t index, std::string const &path)
return;
file.flags |= FF_DOWNLOAD;
file.progress = -1;
file.path = (boost::filesystem::path(path) / file.name).string();
}
if ((m_task_flags & FF_DOWNLOAD) == 0)
DownloadNextFile(path);
DownloadNextFile();
}
void PrinterFileSystem::DownloadCheckFiles(std::string const &path)
{
for (size_t i = 0; i < m_file_list.size(); ++i) {
auto &file = m_file_list[i];
if ((file.flags & FF_DOWNLOAD) != 0 && file.progress >= 0) continue;
auto path2 = boost::filesystem::path(path) / file.name;
boost::system::error_code ec;
if (boost::filesystem::file_size(path2, ec) == file.size) {
file.flags |= FF_DOWNLOAD;
file.progress = 100;
file.path = path2.string();
}
}
}
bool PrinterFileSystem::DownloadCheckFile(size_t index)
{
if (index >= m_file_list.size()) return false;
auto &file = m_file_list[index];
if ((file.flags & FF_DOWNLOAD) == 0) return false;
if (!boost::filesystem::exists(file.path)) {
file.flags &= ~FF_DOWNLOAD;
file.progress = 0;
file.path.clear();
SendChangedEvent(EVT_DOWNLOAD, index, file.path);
return false;
}
return true;
}
void PrinterFileSystem::DownloadCancel(size_t index)
@ -201,17 +245,30 @@ size_t PrinterFileSystem::GetIndexAtTime(boost::uint32_t time)
void PrinterFileSystem::ToggleSelect(size_t index)
{
if (index < m_file_list.size()) m_file_list[index].flags ^= FF_SELECT;
if (index < m_file_list.size()) {
m_file_list[index].flags ^= FF_SELECT;
if (m_file_list[index].flags & FF_SELECT)
++m_select_count;
else
--m_select_count;
}
SendChangedEvent(EVT_SELECT_CHANGED, m_select_count);
}
void PrinterFileSystem::SelectAll(bool select)
{
if (select)
if (select) {
for (auto &f : m_file_list) f.flags |= FF_SELECT;
else
m_select_count = m_file_list.size();
} else {
for (auto &f : m_file_list) f.flags &= ~FF_SELECT;
m_select_count = 0;
}
SendChangedEvent(EVT_SELECT_CHANGED, m_select_count);
}
size_t PrinterFileSystem::GetSelectCount() const { return m_select_count; }
void PrinterFileSystem::SetFocusRange(size_t start, size_t count)
{
m_lock_start = start;
@ -234,7 +291,7 @@ int PrinterFileSystem::RecvData(std::function<int(Bambu_Sample& sample)> const &
int result = 0;
while (true) {
Bambu_Sample sample;
result = Bambu_ReadSample(&m_session, &sample);
result = Bambu_ReadSample(m_session.tunnel, &sample);
if (result == Bambu_success) {
result = callback(sample);
if (result == 1)
@ -320,7 +377,7 @@ void PrinterFileSystem::DeleteFilesContinue()
std::vector<size_t> indexes;
std::vector<std::string> names;
for (size_t i = 0; i < m_file_list.size(); ++i)
if ((m_file_list[i].flags & FF_SELECT) && !m_file_list[i].name.empty()) {
if ((m_file_list[i].flags & FF_DELETED) && !m_file_list[i].name.empty()) {
indexes.push_back(i);
names.push_back(m_file_list[i].name);
if (names.size() >= 64)
@ -338,14 +395,14 @@ void PrinterFileSystem::DeleteFilesContinue()
FILE_DEL, req, nullptr,
[indexes, names, this](int, Void const &) {
// TODO:
for (size_t i = indexes.size() - 1; i >= 0; --i)
for (size_t i = indexes.size() - 1; i != size_t(-1); --i)
FileRemoved(indexes[i], names[i]);
SendChangedEvent(EVT_FILE_CHANGED);
SendChangedEvent(EVT_FILE_CHANGED, indexes.size());
DeleteFilesContinue();
});
}
void PrinterFileSystem::DownloadNextFile(std::string const &path)
void PrinterFileSystem::DownloadNextFile()
{
size_t index = size_t(-1);
for (size_t i = 0; i < m_file_list.size(); ++i) {
@ -363,16 +420,16 @@ void PrinterFileSystem::DownloadNextFile(std::string const &path)
SendChangedEvent(EVT_DOWNLOAD, index, m_file_list[index].name);
struct Download
{
int index;
std::string name;
std::string path;
size_t index;
std::string name;
std::string path;
boost::filesystem::ofstream ofs;
boost::uuids::detail::md5 boost_md5;
boost::uuids::detail::md5 boost_md5;
};
std::shared_ptr<Download> download(new Download);
download->index = index;
download->name = m_file_list[index].name;
download->path = path;
download->path = m_file_list[index].path;
m_task_flags |= FF_DOWNLOAD;
m_download_seq = SendRequest<Progress>(
FILE_DOWNLOAD, req,
@ -382,7 +439,7 @@ void PrinterFileSystem::DownloadNextFile(std::string const &path)
prog.size = resp["offset"];
prog.total = resp["total"];
if (prog.size == 0) {
download->ofs.open(download->path + "/" + download->name, std::ios::binary);
download->ofs.open(download->path, std::ios::binary);
if (!download->ofs) return FILE_OPEN_ERR;
}
// receive data
@ -412,9 +469,9 @@ void PrinterFileSystem::DownloadNextFile(std::string const &path)
return result;
},
[this, download](int result, Progress const &data) {
if (download->index >= 0)
if (download->index != size_t(-1))
download->index = FindFile(download->index, download->name);
if (download->index >= 0) {
if (download->index != size_t(-1)) {
int progress = data.size * 100 / data.total;
if (result > CONTINUE)
progress = -2;
@ -423,10 +480,10 @@ void PrinterFileSystem::DownloadNextFile(std::string const &path)
file.flags &= ~FF_DOWNLOAD;
else if (file.progress != progress) {
file.progress = progress;
SendChangedEvent(EVT_DOWNLOAD, download->index, m_file_list[download->index].name, data.size);
SendChangedEvent(EVT_DOWNLOAD, download->index, file.path, data.size);
}
}
if (result != CONTINUE) DownloadNextFile(download->path);
if (result != CONTINUE) DownloadNextFile();
});
}
@ -556,15 +613,15 @@ void PrinterFileSystem::SendChangedEvent(wxEventType type, size_t index, std::st
wxPostEvent(this, event);
}
void PrinterFileSystem::DumpLog(Bambu_Session *session, int level, Bambu_Message const *msg)
void PrinterFileSystem::DumpLog(void * thiz, int, tchar const *msg)
{
BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem: " << msg;
StaticBambuLib::get().Bambu_FreeLogMsg(msg);
static_cast<PrinterFileSystem*>(thiz)->Bambu_FreeLogMsg(msg);
}
boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callback_t2 const &callback)
{
if (m_session.gSID < 0) {
if (m_session.tunnel == nullptr) {
boost::unique_lock l(m_mutex);
m_cond.notify_all();
return 0;
@ -640,7 +697,7 @@ void PrinterFileSystem::RecvMessageThread()
if (!m_messages.empty()) {
auto & msg = m_messages.front();
l.unlock();
int n = Bambu_SendMessage(&m_session, CTRL_TYPE, msg.c_str(), msg.length());
int n = Bambu_SendMessage(m_session.tunnel, CTRL_TYPE, msg.c_str(), msg.length());
l.lock();
if (n == 0)
m_messages.pop_front();
@ -650,7 +707,7 @@ void PrinterFileSystem::RecvMessageThread()
}
}
l.unlock();
int n = Bambu_ReadSample(&m_session, &sample);
int n = Bambu_ReadSample(m_session.tunnel, &sample);
l.lock();
if (n == 0) {
HandleResponse(l, sample);
@ -726,9 +783,12 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock<boost::mutex> &l, Bamb
void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int result)
{
if (m_session.gSID >= 0) {
if (m_session.tunnel) {
auto tunnel = m_session.tunnel;
m_session.tunnel = nullptr;
l.unlock();
Bambu_Close(&m_session);
Bambu_Close(tunnel);
Bambu_Destroy(tunnel);
l.lock();
}
if (m_session.owner == nullptr)
@ -761,11 +821,16 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
l.unlock();
m_status = Status::Connecting;
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
m_session.logger = &PrinterFileSystem::DumpLog;
int ret = Bambu_Open(&m_session, url.c_str() + 9); // skip bambu:/// sync
Bambu_Tunnel tunnel = nullptr;
int ret = Bambu_Create(&tunnel, url.c_str());
if (ret == 0) {
Bambu_SetLogger(tunnel, DumpLog, this);
ret = Bambu_Open(tunnel);
}
if (ret == 0)
ret = Bambu_StartStream(&m_session);
ret = Bambu_StartStream(tunnel, false);
l.lock();
m_session.tunnel = tunnel;
if (ret == 0)
break;
m_last_error = ret;
@ -776,7 +841,11 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
}
m_status = Status::ListSyncing;
SendChangedEvent(EVT_STATUS_CHANGED, m_status);
#ifdef PRINTER_FILE_SYSTEM_TEST
PostCallback([this] { SendChangedEvent(EVT_FILE_CHANGED); });
#else
PostCallback([this] { ListAllFiles(); });
#endif
}
@ -818,6 +887,9 @@ StaticBambuLib &StaticBambuLib::get()
{
static StaticBambuLib lib;
// first load the library
if (lib.Bambu_Open)
return lib;
if (!module) {
module = Slic3r::NetworkAgent::get_bambu_source_entry();
@ -827,14 +899,17 @@ StaticBambuLib &StaticBambuLib::get()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", can not Load Library";
}
GET_FUNC(Bambu_Create);
GET_FUNC(Bambu_Open);
GET_FUNC(Bambu_StartStream);
GET_FUNC(Bambu_SendMessage);
GET_FUNC(Bambu_ReadSample);
GET_FUNC(Bambu_Close);
GET_FUNC(Bambu_Destroy);
GET_FUNC(Bambu_SetLogger);
GET_FUNC(Bambu_FreeLogMsg);
if (!lib.Bambu_Open)
lib.Bambu_Open = Fake_Bambu_Open;
lib.Bambu_Create = Fake_Bambu_Create;
return lib;
}

View file

@ -18,6 +18,7 @@ using nlohmann::json;
wxDECLARE_EVENT(EVT_STATUS_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_MODE_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_FILE_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_SELECT_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_THUMBNAIL, wxCommandEvent);
wxDECLARE_EVENT(EVT_DOWNLOAD, wxCommandEvent);
@ -95,6 +96,7 @@ public:
wxBitmap thumbnail;
int flags = 0;
int progress = -1; // -1: waiting
std::string path;
bool IsSelect() const { return flags & FF_SELECT; }
bool IsDownload() const { return flags & FF_DOWNLOAD; }
@ -124,6 +126,10 @@ public:
void DownloadFiles(size_t index, std::string const &path);
void DownloadCheckFiles(std::string const &path);
bool DownloadCheckFile(size_t index);
void DownloadCancel(size_t index);
size_t GetCount() const;
@ -134,6 +140,8 @@ public:
void SelectAll(bool select);
size_t GetSelectCount() const;
void SetFocusRange(size_t start, size_t count);
File const &GetFile(size_t index);
@ -164,7 +172,7 @@ private:
void DeleteFilesContinue();
void DownloadNextFile(std::string const &path);
void DownloadNextFile();
void UpdateFocusThumbnail();
@ -174,7 +182,7 @@ private:
void SendChangedEvent(wxEventType type, size_t index = (size_t)-1, std::string const &str = {}, long extra = 0);
static void DumpLog(Bambu_Session *session, int level, Bambu_Message const *msg);
static void DumpLog(void* context, int level, tchar const *msg);
private:
template<typename T> using Translator = std::function<int(json const &, T &, unsigned char const *)>;
@ -260,13 +268,15 @@ protected:
std::vector<size_t> m_group_month;
private:
size_t m_select_count = 0;
size_t m_lock_start = 0;
size_t m_lock_end = 0;
int m_task_flags = 0;
private:
struct Session : Bambu_Session
struct Session
{
Bambu_Tunnel tunnel = nullptr;
PrinterFileSystem * owner;
};
Session m_session;

View file

@ -57,12 +57,12 @@ ReleaseNoteDialog::ReleaseNoteDialog(Plater *plater /*= nullptr*/)
m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15));
m_scrollwindw_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL);
m_scrollwindw_release_note->SetScrollRate(5, 5);
m_scrollwindw_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_scrollwindw_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL);
m_vebview_release_note->SetScrollRate(5, 5);
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_sizer_right->Add(m_scrollwindw_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(30));
m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0);
@ -84,11 +84,11 @@ void ReleaseNoteDialog::update_release_note(wxString release_note, std::string v
{
m_text_up_info->SetLabel(wxString::Format(_L("version %s update information :"), version));
wxBoxSizer * sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_staticText_release_note = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0);
auto m_staticText_release_note = new wxStaticText(m_vebview_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0);
m_staticText_release_note->Wrap(FromDIP(530));
sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5);
m_scrollwindw_release_note->SetSizer(sizer_text_release_note);
m_scrollwindw_release_note->Layout();
m_vebview_release_note->SetSizer(sizer_text_release_note);
m_vebview_release_note->Layout();
}
void UpdateVersionDialog::alter_choice(wxCommandEvent& event)
@ -130,12 +130,22 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(15));
m_simplebook_release_note = new wxSimplebook(this);
m_simplebook_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_simplebook_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_scrollwindows_release_note = new wxScrolledWindow(m_simplebook_release_note, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(430)), wxVSCROLL);
m_scrollwindows_release_note->SetScrollRate(5, 5);
m_scrollwindows_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
//webview
m_scrollwindw_release_note = CreateTipView(this);
m_scrollwindw_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_scrollwindw_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430)));
m_scrollwindw_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430)));
m_scrollwindw_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note = CreateTipView(m_simplebook_release_note);
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note->SetMinSize(wxSize(FromDIP(560), FromDIP(430)));
m_vebview_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
fs::path ph(data_dir());
ph /= "resources/tooltip/common/releasenote.html";
@ -146,7 +156,10 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
auto url = ph.string();
std::replace(url.begin(), url.end(), '\\', '/');
url = "file:///" + url;
m_scrollwindw_release_note->LoadURL(from_u8(url));
m_vebview_release_note->LoadURL(from_u8(url));
m_simplebook_release_note->AddPage(m_scrollwindows_release_note, wxEmptyString, false);
m_simplebook_release_note->AddPage(m_vebview_release_note, wxEmptyString, false);
m_remind_choice = new wxCheckBox( this, wxID_ANY, _L("Don't remind me of this version again"), wxDefaultPosition, wxDefaultSize, 0 );
@ -193,7 +206,7 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
m_sizer_right->Add(m_scrollwindw_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(m_simplebook_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(8));
@ -263,7 +276,7 @@ bool UpdateVersionDialog::ShowReleaseNote(std::string content)
void UpdateVersionDialog::RunScript(std::string script)
{
WebView::RunScript(m_scrollwindw_release_note, script);
WebView::RunScript(m_vebview_release_note, script);
script.clear();
}
@ -272,32 +285,177 @@ void UpdateVersionDialog::on_dpi_changed(const wxRect &suggested_rect) {
m_button_cancel->Rescale();
}
void UpdateVersionDialog::update_version_info(std::string url)
{
/*m_text_up_info->SetLabel(wxString::Format(_L("Click to download new version in default browser: %s"), version));
wxBoxSizer *sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_staticText_release_note = new wxStaticText(m_scrollwindw_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0);
m_staticText_release_note->Wrap(FromDIP(530));
sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5);
m_scrollwindw_release_note->SetSizer(sizer_text_release_note);
m_scrollwindw_release_note->Layout();*/
std::vector<std::string> UpdateVersionDialog::splitWithStl(std::string str,std::string pattern)
{
std::string::size_type pos;
std::vector<std::string> result;
str += pattern;
int size = str.size();
for (int i = 0; i < size; i++)
{
pos = str.find(pattern, i);
if (pos < size)
{
std::string s = str.substr(i, pos - i);
result.push_back(s);
i = pos + pattern.size() - 1;
}
}
return result;
}
if (url.empty()) {
fs::path ph(data_dir());
ph /= "resources/tooltip/common/releasenote.html";
if (!fs::exists(ph)) {
ph = resources_dir();
ph /= "tooltip/releasenote.html";
}
auto url = ph.string();
std::replace(url.begin(), url.end(), '\\', '/');
url = "file:///" + url;
m_scrollwindw_release_note->LoadURL(from_u8(url));
void UpdateVersionDialog::update_version_info(wxString release_note, wxString version)
{
//bbs check whether the web display is used
bool use_web_link = false;
std::string url_line = "";
auto split_array = splitWithStl(release_note.ToStdString(), "###");
for (auto i = 0; i < split_array.size(); i++) {
std::string url = split_array[i];
if (std::strstr (url.c_str(), "http://") != NULL || std::strstr (url.c_str(), "https://") != NULL) {
use_web_link = true;
url_line = url;
break;
}
}
if (use_web_link) {
m_simplebook_release_note->SetSelection(1);
m_vebview_release_note->LoadURL(from_u8(url_line));
}
else {
m_scrollwindw_release_note->LoadURL(from_u8(url));
m_simplebook_release_note->SetSelection(0);
m_text_up_info->SetLabel(wxString::Format(_L("Click to download new version in default browser: %s"), version));
wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_staticText_release_note = new wxStaticText(m_scrollwindows_release_note, wxID_ANY, release_note, wxDefaultPosition, wxDefaultSize, 0);
m_staticText_release_note->Wrap(FromDIP(530));
sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5);
m_scrollwindows_release_note->SetSizer(sizer_text_release_note);
m_scrollwindows_release_note->Layout();
}
}
SecondaryCheckDialog::SecondaryCheckDialog(wxWindow* parent)
:DPIDialog(parent, wxID_ANY, _L("Confirm"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(480), 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));
m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
m_vebview_release_note->SetScrollRate(0, 5);
m_vebview_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_vebview_release_note->SetSize(wxSize(FromDIP(280), FromDIP(280)));
m_vebview_release_note->SetMinSize(wxSize(FromDIP(280), FromDIP(280)));
m_vebview_release_note->SetMaxSize(wxSize(FromDIP(280), FromDIP(280)));
auto sizer_button = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
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](wxMouseEvent& e) {
EndModal(wxID_YES);
});
m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetBackgroundColor(*wxWHITE);
m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
m_button_cancel->SetFont(Label::Body_12);
m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_cancel->SetCornerRadius(FromDIP(12));
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
EndModal(wxID_NO);
});
sizer_button->AddStretchSpacer();
sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5));
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20));
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20));
SetSizer(m_sizer_right);
Layout();
m_sizer_main->Fit(this);
CenterOnParent();
}
void SecondaryCheckDialog::update_text(wxString text)
{
wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
auto m_staticText_release_note = new wxStaticText(m_vebview_release_note, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
m_staticText_release_note->SetSize(wxSize(FromDIP(260), -1));
m_staticText_release_note->SetMaxSize(wxSize(FromDIP(260), -1));
m_staticText_release_note->SetMinSize(wxSize(FromDIP(260), -1));
text = format_text(m_staticText_release_note, text, FromDIP(240));
m_staticText_release_note->SetLabelText(text);
m_staticText_release_note->Wrap(FromDIP(240));
sizer_text_release_note->Add(m_staticText_release_note, 0, wxALIGN_CENTER, 5);
m_vebview_release_note->SetSizer(sizer_text_release_note);
m_vebview_release_note->Layout();
//Fit();
}
wxString SecondaryCheckDialog::format_text(wxStaticText* st, wxString str, int warp)
{
if (wxGetApp().app_config->get("language") != "zh_CN") { return str; }
wxString out_txt = str;
wxString count_txt = "";
int new_line_pos = 0;
for (int i = 0; i < str.length(); i++) {
auto text_size = st->GetTextExtent(count_txt);
if (text_size.x < warp) {
count_txt += str[i];
}
else {
out_txt.insert(i - 1, '\n');
count_txt = "";
}
}
return out_txt;
}
SecondaryCheckDialog::~SecondaryCheckDialog()
{
}
void SecondaryCheckDialog::on_dpi_changed(const wxRect& suggested_rect)
{
}
}} // namespace Slic3r::GUI

View file

@ -47,7 +47,7 @@ public:
void update_release_note(wxString release_note, std::string version);
wxStaticText * m_text_up_info{nullptr};
wxScrolledWindow *m_scrollwindw_release_note {nullptr};
wxScrolledWindow *m_vebview_release_note {nullptr};
};
class UpdateVersionDialog : public DPIDialog
@ -63,11 +63,14 @@ public:
bool ShowReleaseNote(std::string content);
void RunScript(std::string script);
void on_dpi_changed(const wxRect& suggested_rect) override;
void update_version_info(std::string url);
void update_version_info(wxString release_note, wxString version);
void alter_choice(wxCommandEvent& event);
std::vector<std::string> splitWithStl(std::string str, std::string pattern);
wxStaticText * m_text_up_info{nullptr};
wxWebView* m_scrollwindw_release_note{nullptr};
wxWebView* m_vebview_release_note{nullptr};
wxSimplebook* m_simplebook_release_note{nullptr};
wxScrolledWindow* m_scrollwindows_release_note{nullptr};
wxBoxSizer * sizer_text_release_note{nullptr};
wxStaticText * m_staticText_release_note{nullptr};
wxCheckBox* m_remind_choice;
@ -75,6 +78,20 @@ public:
Button* m_button_cancel;
};
class SecondaryCheckDialog : public DPIDialog
{
public:
SecondaryCheckDialog(wxWindow* parent);
void update_text(wxString text);
wxString format_text(wxStaticText* st, wxString str, int warp);
~SecondaryCheckDialog();
void on_dpi_changed(const wxRect& suggested_rect) override;
wxScrolledWindow *m_vebview_release_note {nullptr};
Button* m_button_ok;
Button* m_button_cancel;
};
}} // namespace Slic3r::GUI
#endif

View file

@ -388,6 +388,19 @@ std::string SavePresetDialog::get_name(Preset::Type type)
return "";
}
void SavePresetDialog::input_name_from_other(std::string new_preset_name) {
//only work for one-item
Item* curr_item = m_items[0];
curr_item->m_input_ctrl->SetValue(new_preset_name);
}
void SavePresetDialog::confirm_from_other() {
for (Item *item : m_items) {
item->accept();
if (item->type() == Preset::TYPE_PRINTER) update_physical_printers(item->preset_name());
}
}
// BBS: add project relate
bool SavePresetDialog::get_save_to_project_selection(Preset::Type type)
{

View file

@ -97,6 +97,8 @@ public:
std::string get_name();
std::string get_name(Preset::Type type);
void input_name_from_other(std::string new_preset_name);
void confirm_from_other();
bool enable_ok_btn() const;
void add_info_for_edit_ph_printer(wxBoxSizer *sizer);

View file

@ -365,8 +365,8 @@ void OptionsSearcher::show_dialog(Preset::Type type, wxWindow *parent, wxTextCtr
{
if (parent == nullptr || input == nullptr) return;
auto search_dialog = new SearchDialog(this, type, parent, input, ssearch_btn);
wxPoint pos = parent->ClientToScreen(wxPoint(0, 0));
pos.y += parent->GetRect().height;
wxPoint pos = input->GetParent()->ClientToScreen(wxPoint(0, 0));
pos.y += input->GetParent()->GetRect().height;
search_dialog->SetPosition(pos);
search_dialog->Popup();
}
@ -644,7 +644,7 @@ void SearchDialog::Dismiss()
void SearchDialog::Die()
{
Destroy();
wxPopupTransientWindow::Dismiss();
wxCommandEvent event(wxCUSTOMEVT_EXIT_SEARCH);
wxPostEvent(search_line, event);
}

View file

@ -21,6 +21,8 @@
#include "Plater.hpp"
#include "BitmapCache.hpp"
#include "BindDialog.hpp"
#include "ConfirmHintDialog.hpp"
#include "ReleaseNote.hpp"
namespace Slic3r { namespace GUI {
@ -38,6 +40,8 @@ wxDEFINE_EVENT(EVT_EDIT_PRINT_NAME, wxCommandEvent);
#define LIST_REFRESH_INTERVAL 200
#define MACHINE_LIST_REFRESH_INTERVAL 2000
#define WRAP_GAP FromDIP(10)
static wxString task_canceled_text = _L("Task canceled");
@ -88,6 +92,8 @@ std::string get_print_status_info(PrintDialogStatus status)
return "PrintStatusLanModeNoSdcard";
case PrintStatusNoSdcard:
return "PrintStatusNoSdcard";
case PrintStatusTimelapseNoSdcard:
return "PrintStatusTimelapseNoSdcard";
}
return "unknown";
}
@ -395,13 +401,13 @@ SelectMachinePopup::SelectMachinePopup(wxWindow *parent)
m_sizxer_scrolledWindow->Fit(m_scrolledWindow);
#if !BBL_RELEASE_TO_PUBLIC && defined(__WINDOWS__)
m_sizer_search_bar = new wxBoxSizer(wxVERTICAL);
m_search_bar = new wxSearchCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_sizer_search_bar = new wxBoxSizer(wxVERTICAL);
m_search_bar = new wxSearchCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_search_bar->ShowSearchButton( true );
m_search_bar->ShowCancelButton( false );
m_sizer_search_bar->Add( m_search_bar, 1, wxALL| wxEXPAND, 1 );
m_sizer_main->Add(m_sizer_search_bar, 0, wxALL | wxEXPAND, FromDIP(2));
m_search_bar->Bind( wxEVT_COMMAND_TEXT_UPDATED, &SelectMachinePopup::update_machine_list, this );
m_sizer_main->Add(m_sizer_search_bar, 0, wxALL | wxEXPAND, FromDIP(2));
m_search_bar->Bind( wxEVT_COMMAND_TEXT_UPDATED, &SelectMachinePopup::update_machine_list, this );
#endif
auto own_title = create_title_panel(_L("My Device"));
m_sizer_my_devices = new wxBoxSizer(wxVERTICAL);
@ -550,6 +556,7 @@ void SelectMachinePopup::update_other_devices()
this->Freeze();
m_scrolledWindow->Freeze();
int i = 0;
for (auto &elem : m_free_machine_list) {
MachineObject * mobj = elem.second;
/* do not show printer bind state is empty */
@ -568,9 +575,9 @@ void SelectMachinePopup::update_other_devices()
op = m_other_list_machine_panel[i]->mPanel;
op->Show();
#if !BBL_RELEASE_TO_PUBLIC && defined(__WINDOWS__)
if (!search_for_printer(mobj)) {
op->Hide();
}
if (!search_for_printer(mobj)) {
op->Hide();
}
#endif
} else {
op = new MachineObjectPanel(m_scrolledWindow, wxID_ANY);
@ -626,13 +633,37 @@ void SelectMachinePopup::update_other_devices()
m_other_list_machine_panel[j]->mPanel->update_machine_info(nullptr);
m_other_list_machine_panel[j]->mPanel->Hide();
}
m_sizer_other_devices->Layout();
if (m_placeholder_panel != nullptr) {
m_scrolledWindow->RemoveChild(m_placeholder_panel);
m_placeholder_panel->Destroy();
m_placeholder_panel = nullptr;
}
m_placeholder_panel = new wxWindow(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxSize(-1,FromDIP(26)));
wxBoxSizer* placeholder_sizer = new wxBoxSizer(wxVERTICAL);
auto m_hyperlink = new wxHyperlinkCtrl(m_placeholder_panel, wxID_ANY, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
placeholder_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_placeholder_panel->SetSizer(placeholder_sizer);
m_placeholder_panel->Layout();
placeholder_sizer->Fit(m_placeholder_panel);
m_placeholder_panel->SetBackgroundColour(*wxWHITE);
m_sizer_other_devices->Add(m_placeholder_panel, 0, wxEXPAND, 0);
//m_sizer_other_devices->Layout();
if(m_other_devices_count != i) {
m_scrolledWindow->Fit();
}
m_scrolledWindow->Layout();
m_scrolledWindow->Fit();
m_scrolledWindow->Thaw();
Layout();
Fit();
this->Thaw();
m_scrolledWindow->Thaw();
Layout();
Fit();
this->Thaw();
m_other_devices_count = i;
BOOST_LOG_TRIVIAL(trace) << "SelectMachinePopup update_other_devices end";
}
@ -653,6 +684,7 @@ void SelectMachinePopup::update_user_devices()
this->Freeze();
m_scrolledWindow->Freeze();
int i = 0;
for (auto& elem : m_bind_machine_list) {
MachineObject* mobj = elem.second;
MachineObjectPanel* op = nullptr;
@ -660,9 +692,9 @@ void SelectMachinePopup::update_user_devices()
op = m_user_list_machine_panel[i]->mPanel;
op->Show();
#if !BBL_RELEASE_TO_PUBLIC && defined(__WINDOWS__)
if (!search_for_printer(mobj)) {
op->Hide();
}
if (!search_for_printer(mobj)) {
op->Hide();
}
#endif
} else {
op = new MachineObjectPanel(m_scrolledWindow, wxID_ANY);
@ -752,27 +784,31 @@ void SelectMachinePopup::update_user_devices()
m_user_list_machine_panel[j]->mPanel->Hide();
}
//m_sizer_my_devices->Layout();
if (m_my_devices_count != i) {
m_scrolledWindow->Fit();
}
m_scrolledWindow->Layout();
m_scrolledWindow->Fit();
m_scrolledWindow->Thaw();
Layout();
Fit();
this->Thaw();
Layout();
Fit();
this->Thaw();
m_my_devices_count = i;
}
bool SelectMachinePopup::search_for_printer(MachineObject* obj)
{
std::string search_text = std::string((m_search_bar->GetValue()).mb_str());
if (search_text.empty()) {
return true;
}
auto name = obj->dev_name;
auto ip = obj->dev_ip;
auto name_it = name.find(search_text);
auto ip_it = ip.find(search_text);
if ((name_it != std::string::npos)||(ip_it != std::string::npos)) {
return true;
}
std::string search_text = std::string((m_search_bar->GetValue()).mb_str());
if (search_text.empty()) {
return true;
}
auto name = obj->dev_name;
auto ip = obj->dev_ip;
auto name_it = name.find(search_text);
auto ip_it = ip.find(search_text);
if ((name_it != std::string::npos)||(ip_it != std::string::npos)) {
return true;
}
return false;
}
@ -954,7 +990,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
wxBoxSizer *m_sizer_printer = new wxBoxSizer(wxHORIZONTAL);
m_stext_printer_title = new wxStaticText(this, wxID_ANY, L("Printer"), wxDefaultPosition, wxSize(-1, -1), 0);
m_stext_printer_title = new wxStaticText(this, wxID_ANY, _L("Printer"), wxDefaultPosition, wxSize(-1, -1), 0);
m_stext_printer_title->SetFont(::Label::Head_14);
m_stext_printer_title->Wrap(-1);
m_stext_printer_title->SetForegroundColour(m_colour_bold_color);
@ -984,17 +1020,21 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_statictext_printer_msg->SetFont(::Label::Body_13);
m_statictext_printer_msg->Hide();
m_sizer_select = new wxGridSizer(0, 2, 0, 0);
//m_sizer_select = new wxGridSizer(0, 2, 0, 0);
m_sizer_select = new wxWrapSizer();
select_bed = create_item_checkbox(_L("Bed Leveling"), this, _L("Bed Leveling"), "bed_leveling");
select_flow = create_item_checkbox(_L("Flow Calibration"), this, _L("Flow Calibration"), "flow_cali");
select_timelapse = create_item_checkbox(_L("Timelapse"), this, _L("Timelapse"), "timelapse");
select_use_ams = create_ams_checkbox(_L("Enable AMS"), this, _L("Enable AMS"));
m_sizer_select->Add(select_bed);
m_sizer_select->Add(select_flow);
m_sizer_select->Add(select_use_ams);
m_sizer_select->Add(select_bed, 0, wxLEFT | wxRIGHT, WRAP_GAP);
m_sizer_select->Add(select_flow, 0, wxLEFT | wxRIGHT, WRAP_GAP);
m_sizer_select->Add(select_timelapse, 0, wxLEFT | wxRIGHT, WRAP_GAP);
m_sizer_select->Add(select_use_ams, 0, wxLEFT | wxRIGHT, WRAP_GAP);
select_bed->Show(true);
select_flow->Show(true);
select_timelapse->Show(false);
select_use_ams->Show(true);
// line schedule
@ -1007,11 +1047,23 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
// perpare mode
m_panel_prepare = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_panel_prepare->SetBackgroundColour(m_colour_def_color);
// m_panel_prepare->SetBackgroundColour(wxColour(135,206,250));
//m_panel_prepare->SetBackgroundColour(wxColour(135,206,250));
wxBoxSizer *m_sizer_prepare = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *m_sizer_pcont = new wxBoxSizer(wxHORIZONTAL);
m_sizer_prepare->Add(0, 0, 1, wxTOP, FromDIP(22));
m_sizer_prepare->Add(0, 0, 1, wxTOP, FromDIP(12));
auto hyperlink_sizer = new wxBoxSizer( wxHORIZONTAL );
auto m_hyperlink = new wxHyperlinkCtrl(m_panel_prepare, wxID_ANY, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
//auto linkimg = new wxStaticBitmap(m_panel_prepare, wxID_ANY, create_scaled_bitmap("link_wiki_img", this, 18), wxDefaultPosition, wxSize(FromDIP(18), FromDIP(18)), 0);
hyperlink_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
//hyperlink_sizer->Add(linkimg, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
m_sizer_prepare->Add(hyperlink_sizer, 0, wxALIGN_CENTER | wxALL, 5);
m_sizer_pcont->Add(0, 0, 1, wxEXPAND, 0);
m_button_ensure = new Button(m_panel_prepare, _L("Send"));
m_button_ensure->SetBackgroundColor(btn_bg_enable);
@ -1021,7 +1073,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_button_ensure->SetMinSize(SELECT_MACHINE_DIALOG_BUTTON_SIZE);
m_button_ensure->SetCornerRadius(FromDIP(12));
m_button_ensure->Bind(wxEVT_BUTTON, &SelectMachineDialog::on_ok, this);
m_button_ensure->Bind(wxEVT_BUTTON, &SelectMachineDialog::on_ok_btn, this);
m_sizer_pcont->Add(m_button_ensure, 0, wxEXPAND | wxBOTTOM, FromDIP(10));
m_sizer_prepare->Add(m_sizer_pcont, 0, wxEXPAND, 0);
m_panel_prepare->SetSizer(m_sizer_prepare);
@ -1131,23 +1183,23 @@ wxWindow *SelectMachineDialog::create_ams_checkbox(wxString title, wxWindow *par
auto img_ams_tip = new wxStaticBitmap(checkbox, wxID_ANY, create_scaled_bitmap("enable_ams", this, 16), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)), 0);
sizer_checkbox->Add(img_ams_tip, 0, wxALIGN_CENTER | wxLEFT, FromDIP(5));
img_ams_tip->Bind(wxEVT_ENTER_WINDOW, [this, img_ams_tip](auto &e) {
wxPoint pos = img_ams_tip->ClientToScreen(wxPoint(0, 0));
pos.y += img_ams_tip->GetRect().height;
m_mapping_tip_popup.Position(pos, wxSize(0,0));
img_ams_tip->Bind(wxEVT_ENTER_WINDOW, [this, img_ams_tip](auto& e) {
wxPoint img_pos = img_ams_tip->ClientToScreen(wxPoint(0, 0));
wxPoint popup_pos(img_pos.x, img_pos.y + img_ams_tip->GetRect().height);
m_mapping_tip_popup.Position(popup_pos, wxSize(0, 0));
m_mapping_tip_popup.Popup();
});
img_ams_tip->Bind(wxEVT_LEAVE_WINDOW, [this, img_ams_tip](wxMouseEvent &e) {
auto region = m_mapping_tip_popup.GetClientRect();
if(e.GetPosition().x > region.GetLeftTop().x && e.GetPosition().y > region.GetLeftTop().y && e.GetPosition().x < region.GetRightBottom().x && e.GetPosition().x < region.GetRightBottom().y)
;
else
if (m_mapping_tip_popup.ClientToScreen(wxPoint(0, 0)).y < img_pos.y) {
m_mapping_tip_popup.Dismiss();
popup_pos = wxPoint(img_pos.x, img_pos.y - m_mapping_tip_popup.GetRect().height);
m_mapping_tip_popup.Position(popup_pos, wxSize(0, 0));
m_mapping_tip_popup.Popup();
}
});
m_mapping_tip_popup.Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {
m_mapping_tip_popup.Dismiss();
});
img_ams_tip->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) {
m_mapping_tip_popup.Dismiss();
});
checkbox->SetSizer(sizer_checkbox);
checkbox->Layout();
@ -1177,10 +1229,12 @@ wxWindow *SelectMachineDialog::create_item_checkbox(wxString title, wxWindow *pa
sizer_checkbox->Add(sizer_check, 0, wxEXPAND, FromDIP(5));
sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(11));
auto text = new wxStaticText(checkbox, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0);
auto text = new wxStaticText(checkbox, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
text->SetFont(::Label::Body_13);
text->SetForegroundColour(wxColour(107, 107, 107));
text->Wrap(-1);
text->SetMinSize(wxSize(FromDIP(120), -1));
text->SetMaxSize(wxSize(FromDIP(120), -1));
sizer_checkbox->Add(text, 0, wxBOTTOM | wxEXPAND | wxTOP, FromDIP(5));
checkbox->SetSizer(sizer_checkbox);
@ -1209,6 +1263,13 @@ void SelectMachineDialog::update_select_layout(MachineObject *obj)
select_bed->Hide();
}
if (obj && obj->is_function_supported(PrinterFunction::FUNC_TIMELAPSE)
&& obj->is_support_print_with_timelapse()) {
//always hide timelapse
select_timelapse->Hide();
} else {
select_timelapse->Hide();
}
Fit();
}
@ -1319,7 +1380,8 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_)
if (result == 0) {
print_ams_mapping_result(m_ams_mapping_result);
std::string ams_array;
get_ams_mapping_result(ams_array);
std::string mapping_info;
get_ams_mapping_result(ams_array, mapping_info);
if (ams_array.empty()) {
reset_ams_material();
BOOST_LOG_TRIVIAL(info) << "ams_mapping_array=[]";
@ -1345,7 +1407,7 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_)
return true;
}
bool SelectMachineDialog::get_ams_mapping_result(std::string &mapping_array_str)
bool SelectMachineDialog::get_ams_mapping_result(std::string &mapping_array_str, std::string &ams_mapping_info)
{
if (m_ams_mapping_result.empty())
return false;
@ -1363,16 +1425,39 @@ bool SelectMachineDialog::get_ams_mapping_result(std::string &mapping_array_str)
return false;
} else {
json j = json::array();
json mapping_info_json = json::array();
for (int i = 0; i < wxGetApp().preset_bundle->filament_presets.size(); i++) {
int tray_id = -1;
json mapping_item;
mapping_item["ams"] = tray_id;
mapping_item["targetColor"] = "";
mapping_item["filamentId"] = "";
mapping_item["filamentType"] = "";
for (int k = 0; k < m_ams_mapping_result.size(); k++) {
if (m_ams_mapping_result[k].id == i) {
tray_id = m_ams_mapping_result[k].tray_id;
mapping_item["ams"] = tray_id;
mapping_item["filamentType"] = m_filaments[k].type;
auto it = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i]);
if (it != nullptr) {
mapping_item["filamentId"] = it->filament_id;
}
//convert #RRGGBB to RRGGBBAA
if (m_filaments[k].color.size() > 6) {
mapping_item["sourceColor"] = m_filaments[k].color.substr(1, 6) + "FF";
} else {
mapping_item["sourceColor"] = m_filaments[k].color;
}
mapping_item["targetColor"] = m_ams_mapping_result[k].color;
}
}
j.push_back(tray_id);
mapping_info_json.push_back(mapping_item);
}
mapping_array_str = j.dump();
ams_mapping_info = mapping_info_json.dump();
return valid_mapping_result;
}
return true;
@ -1464,6 +1549,22 @@ void SelectMachineDialog::update_print_status_msg(wxString msg, bool is_warning,
}
}
bool SelectMachineDialog::has_tips(MachineObject* obj)
{
if (!obj) return false;
// must set to a status if return true
if (select_timelapse->IsShown() &&
m_checkbox_list["timelapse"]->GetValue()) {
if (!obj->has_sdcard()) {
show_status(PrintDialogStatus::PrintStatusTimelapseNoSdcard);
return true;
}
}
return false;
}
void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxString> params)
{
if (m_print_status != status)
@ -1564,7 +1665,8 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
Enable_Send_Button(false);
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusAmsMappingValid) {
update_print_status_msg(wxEmptyString, false, false);
wxString msg_text = _L("Filaments to AMS slots mappings have been established. You can click a filament above to change its mapping AMS slot");
update_print_status_msg(msg_text, false, false);
Enable_Send_Button(true);
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusRefreshingMachineList) {
@ -1592,6 +1694,11 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
update_print_status_msg(msg_text, true, true);
Enable_Send_Button(true);
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusTimelapseNoSdcard) {
wxString msg_text = _L("An SD card needs to be inserted to recording timelapse");
update_print_status_msg(msg_text, true, true);
Enable_Send_Button(true);
Enable_Refresh_Button(true);
}
}
@ -1638,7 +1745,71 @@ void SelectMachineDialog::on_cancel(wxCloseEvent &event)
this->EndModal(wxID_CANCEL);
}
void SelectMachineDialog::on_ok(wxCommandEvent &event)
bool SelectMachineDialog::is_same_printer_model()
{
bool result = true;
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return result;
MachineObject* obj_ = dev->get_selected_machine();
assert(obj_->dev_id == m_printer_last_select);
if (obj_ == nullptr) {
return result;
}
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) != obj_->printer_type) {
BOOST_LOG_TRIVIAL(info) << "printer_model: source = " << preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
BOOST_LOG_TRIVIAL(info) << "printer_model: target = " << obj_->printer_type;
return false;
}
return true;
}
void SelectMachineDialog::on_ok_btn(wxCommandEvent &event)
{
wxString confirm_text = _L("Please check the following infomation:\n");
//Check Printer Model Id
bool is_same_printer_type = is_same_printer_model();
if (!is_same_printer_type)
confirm_text += _L("The printer type used to generate G-code is not the same type as the currently selected physical printer. It is recommend to re-slice by selecting the same printer type.\n");
//Check slice warnings
bool has_slice_warnings = false;
PartPlate* plate = m_plater->get_partplate_list().get_curr_plate();
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
MachineObject* obj_ = dev->get_selected_machine();
for (auto warning : plate->get_slice_result()->warnings) {
if (warning.msg == BED_TEMP_TOO_HIGH_THAN_FILAMENT) {
if ((obj_->printer_type == "BL-P001" || obj_->printer_type == "BL-P002")) {
confirm_text += Plater::get_slice_warning_string(warning) + "\n";
has_slice_warnings = true;
}
}
else {
has_slice_warnings = true;
}
}
}
if (!is_same_printer_type
|| has_slice_warnings
) {
wxString confirm_title = _L("Confirm");
SecondaryCheckDialog confirm_dlg(this);
confirm_dlg.update_text(confirm_text);
if (confirm_dlg.ShowModal() == wxID_YES) {
this->on_ok();
}
} else {
this->on_ok();
}
}
void SelectMachineDialog::on_ok()
{
BOOST_LOG_TRIVIAL(info) << "print_job: on_ok to send";
m_is_canceled = false;
@ -1690,7 +1861,8 @@ void SelectMachineDialog::on_ok(wxCommandEvent &event)
// get ams_mapping_result
std::string ams_mapping_array;
get_ams_mapping_result(ams_mapping_array);
std::string ams_mapping_info;
get_ams_mapping_result(ams_mapping_array, ams_mapping_info);
result = m_plater->send_gcode(m_print_plate_idx, [this](int export_stage, int current, int total, bool &cancel) {
if (this->m_is_canceled) return;
@ -1730,10 +1902,13 @@ void SelectMachineDialog::on_ok(wxCommandEvent &event)
m_print_job->m_dev_ip = obj_->dev_ip;
m_print_job->m_access_code = obj_->access_code;
m_print_job->connection_type = obj_->connection_type();
if (obj_->is_support_ams_mapping())
if (obj_->is_support_ams_mapping()) {
m_print_job->task_ams_mapping = ams_mapping_array;
else
m_print_job->task_ams_mapping_info = ams_mapping_info;
} else {
m_print_job->task_ams_mapping = "";
m_print_job->task_ams_mapping_info = "";
}
m_print_job->has_sdcard = obj_->has_sdcard();
@ -1741,13 +1916,16 @@ void SelectMachineDialog::on_ok(wxCommandEvent &event)
m_print_job->cloud_print_only = true;
}
bool timelapse_option = select_timelapse->IsShown() ? m_checkbox_list["timelapse"]->GetValue() : true;
m_print_job->set_print_config(
MachineBedTypeString[0],
m_checkbox_list["bed_leveling"]->GetValue(),
m_checkbox_list["flow_cali"]->GetValue(),
false,
false,
true);
timelapse_option);
if (obj_->has_ams()) {
m_print_job->task_use_ams = ams_check->GetValue();
@ -1755,6 +1933,7 @@ void SelectMachineDialog::on_ok(wxCommandEvent &event)
m_print_job->task_use_ams = false;
}
BOOST_LOG_TRIVIAL(info) << "print_job: timelapse_option = " << timelapse_option;
BOOST_LOG_TRIVIAL(info) << "print_job: use_ams = " << m_print_job->task_use_ams;
m_print_job->on_success([this]() { finish_mode(); });
@ -1809,6 +1988,9 @@ void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt)
for (auto i = 0; i < m_ams_mapping_result.size(); i++) {
if (m_ams_mapping_result[i].id == wxAtoi(selection_data_arr[4])) {
m_ams_mapping_result[i].tray_id = evt.GetInt();
auto ams_colour = wxColour(wxAtoi(selection_data_arr[0]), wxAtoi(selection_data_arr[1]), wxAtoi(selection_data_arr[2]));
auto color = wxString::Format("%sFF", ams_colour.GetAsString(wxC2S_HTML_SYNTAX).substr(1, ams_colour.GetAsString(wxC2S_HTML_SYNTAX).size()-1));
m_ams_mapping_result[i].color = color.ToStdString();
}
BOOST_LOG_TRIVIAL(trace) << "The ams mapping result: id is " << m_ams_mapping_result[i].id << "tray_id is " << m_ams_mapping_result[i].tray_id;
}
@ -1973,6 +2155,8 @@ void SelectMachineDialog::on_selection_changed(wxCommandEvent &event)
obj->command_get_version();
obj->command_request_push_all();
dev->set_selected_machine(m_printer_last_select);
// Has changed machine unrecoverably
GUI::wxGetApp().sidebar().load_ams_list(obj->amsList);
update_select_layout(obj);
} else {
BOOST_LOG_TRIVIAL(error) << "on_selection_changed dev_id not found";
@ -2007,10 +2191,14 @@ void SelectMachineDialog::update_show_status()
NetworkAgent* agent = Slic3r::GUI::wxGetApp().getAgent();
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!agent) return;
if (!agent) {
update_ams_check(nullptr);
return;
}
if (!dev) return;
MachineObject* obj_ = dev->get_my_machine(m_printer_last_select);
if (!obj_) {
update_ams_check(nullptr);
if (agent) {
if (agent->is_user_login()) {
show_status(PrintDialogStatus::PrintStatusInvalidPrinter);
@ -2075,13 +2263,11 @@ void SelectMachineDialog::update_show_status()
show_status(PrintDialogStatus::PrintStatusInPrinting);
return;
}
else if (!obj_->is_function_supported(PrinterFunction::FUNC_PRINT_WITHOUT_SD)) {
else if (!obj_->is_function_supported(PrinterFunction::FUNC_PRINT_WITHOUT_SD) && !obj_->has_sdcard()) {
show_status(PrintDialogStatus::PrintStatusNoSdcard);
return;
}
// check sdcard when if lan mode printer
if (obj_->is_lan_mode_printer()) {
if (!obj_->has_sdcard()) {
@ -2092,7 +2278,8 @@ void SelectMachineDialog::update_show_status()
// no ams
if (!obj_->has_ams()) {
show_status(PrintDialogStatus::PrintStatusReadingFinished);
if (!has_tips(obj_))
show_status(PrintDialogStatus::PrintStatusReadingFinished);
return;
}
@ -2144,10 +2331,13 @@ void SelectMachineDialog::update_show_status()
}
else {
if (obj_->is_valid_mapping_result(m_ams_mapping_result)) {
show_status(PrintDialogStatus::PrintStatusAmsMappingValid);
if (!has_tips(obj_))
show_status(PrintDialogStatus::PrintStatusAmsMappingValid);
return;
}
else {
show_status(PrintDialogStatus::PrintStatusAmsMappingInvalid);
return;
}
}
}
@ -2250,6 +2440,7 @@ void SelectMachineDialog::set_default()
// checkbox default values
m_checkbox_list["bed_leveling"]->SetValue(true);
m_checkbox_list["flow_cali"]->SetValue(true);
m_checkbox_list["timelapse"]->SetValue(true);
ams_check->SetValue(true);
// thumbmail

View file

@ -195,6 +195,9 @@ public:
bool was_dismiss() { return m_dismiss; }
private:
int m_my_devices_count{0};
int m_other_devices_count{0};
wxWindow* m_placeholder_panel{nullptr};
wxBoxSizer * m_sizer_body{nullptr};
wxBoxSizer * m_sizer_my_devices{nullptr};
wxBoxSizer * m_sizer_other_devices{nullptr};
@ -249,7 +252,9 @@ enum PrintDialogStatus {
PrintStatusSending,
PrintStatusSendingCanceled,
PrintStatusLanModeNoSdcard,
PrintStatusNoSdcard
PrintStatusNoSdcard,
PrintStatusTimelapseNoSdcard,
PrintStatusNotOnTheSameLAN
};
std::string get_print_status_info(PrintDialogStatus status);
@ -308,7 +313,8 @@ protected:
int m_current_filament_id;
bool m_is_in_sending_mode { false };
wxGridSizer *m_sizer_select;
//wxGridSizer *m_sizer_select;
wxWrapSizer *m_sizer_select;
wxBoxSizer * sizer_thumbnail;
wxGridSizer *m_sizer_material;
wxBoxSizer * m_sizer_main;
@ -323,6 +329,7 @@ protected:
wxWindow *select_bed{nullptr};
wxWindow *select_flow{nullptr};
wxWindow *select_timelapse { nullptr };
wxWindow *select_use_ams{nullptr};
CheckBox *ams_check{nullptr};
@ -346,11 +353,14 @@ public:
void sync_ams_mapping_result(std::vector<FilamentInfo>& result);
bool do_ams_mapping(MachineObject *obj_);
bool get_ams_mapping_result(std::string &mapping_array_str);
bool get_ams_mapping_result(std::string &mapping_array_str, std::string &ams_mapping_info);
void prepare(int print_plate_idx);
bool has_tips(MachineObject* obj);
void show_status(PrintDialogStatus status, std::vector<wxString> params = std::vector<wxString>());
PrintDialogStatus get_status() { return m_print_status; }
bool is_same_printer_model();
bool Show(bool show);
/* model */
@ -386,7 +396,8 @@ protected:
// Virtual event handlers, overide them in your derived class
void update_printer_combobox(wxCommandEvent &event);
void on_cancel(wxCloseEvent &event);
void on_ok(wxCommandEvent &event);
void on_ok_btn(wxCommandEvent &event);
void on_ok();
void on_refresh(wxCommandEvent &event);
void on_set_finish_mapping(wxCommandEvent &evt);
void on_print_job_cancel(wxCommandEvent &evt);

View file

@ -1105,6 +1105,12 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
else
v.set_instance_scaling_factor(scale);
}
// update the instance assemble transform
ModelObject* object = m_model->objects[v.object_idx()];
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
}
else if (is_single_volume() || is_single_modifier())
v.set_volume_scaling_factor(scale);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,162 @@
#ifndef slic3r_GUI_SendToSDcard_hpp_
#define slic3r_GUI_SendToSDcard_hpp_
#include <wx/wx.h>
#include <wx/intl.h>
#include <wx/collpane.h>
#include <wx/dataview.h>
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/dataview.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/hyperlink.h>
#include <wx/button.h>
#include <wx/dialog.h>
#include <wx/popupwin.h>
#include <wx/spinctrl.h>
#include <wx/artprov.h>
#include <wx/wrapsizer.h>
#include <wx/srchctrl.h>
#include "SelectMachine.hpp"
#include "GUI_Utils.hpp"
#include "wxExtensions.hpp"
#include "DeviceManager.hpp"
#include "Plater.hpp"
#include "BBLStatusBar.hpp"
#include "BBLStatusBarSend.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/ScrolledWindow.hpp"
#include <wx/simplebook.h>
#include <wx/hashmap.h>
namespace Slic3r {
namespace GUI {
class SendToPrinterDialog : public DPIDialog
{
private:
void init_model();
void init_bind();
void init_timer();
int m_print_plate_idx;
PrintDialogStatus m_print_status { PrintStatusInit };
std::string m_printer_last_select;
std::vector<wxString> m_bedtype_list;
std::map<std::string, ::CheckBox*> m_checkbox_list;
wxColour m_colour_def_color{ wxColour(255, 255, 255) };
wxColour m_colour_bold_color{ wxColour(38, 46, 48) };
protected:
Plater* m_plater{ nullptr };
wxPanel* m_line_top{ nullptr };
wxPanel* m_panel_image{ nullptr };
wxStaticText* m_stext_time{ nullptr };
wxStaticText* m_stext_weight{ nullptr };
wxPanel* m_line_materia{ nullptr };
wxStaticText* m_stext_printer_title{ nullptr };
wxStaticText* m_statictext_printer_msg{ nullptr };
wxStaticBitmap* m_staticbitmap{ nullptr };
ThumbnailPanel* m_thumbnailPanel{ nullptr };
::ComboBox* m_comboBox_printer{ nullptr };
::ComboBox* m_comboBox_bed{ nullptr };
wxStaticText* m_staticText_bed_title{ nullptr };
wxPanel* m_line_schedule{ nullptr };
wxPanel* m_panel_sending{ nullptr };
wxStaticText* m_stext_sending{ nullptr };
wxPanel* m_panel_prepare{ nullptr };
Button* m_button_refresh{ nullptr };
Button* m_button_ensure{ nullptr };
wxPanel* m_panel_finish{ nullptr };
wxSimplebook* m_simplebook{ nullptr };
wxStaticText* m_statictext_finish{ nullptr };
StateColor btn_bg_enable;
int m_current_filament_id;
bool m_is_in_sending_mode{ false };
wxBoxSizer* sizer_thumbnail;
wxBoxSizer* m_sizer_main;
wxBoxSizer* m_sizer_bottom;
bool enable_prepare_mode{true};
bool m_need_adaptation_screen{ false };
wxPanel* m_scrollable_region;
wxBoxSizer* m_sizer_scrollable_region;
void stripWhiteSpace(std::string& str);
wxString format_text(wxString& m_msg);
void update_priner_status_msg(wxString msg, bool is_warning = false);
void update_print_status_msg(wxString msg, bool is_warning = false, bool is_printer = true);
public:
SendToPrinterDialog(Plater* plater = nullptr);
~SendToPrinterDialog();
void prepare_mode();
void sending_mode();
void prepare(int print_plate_idx);
bool Show(bool show);
/* model */
wxObjectDataPtr<MachineListModel> machine_model;
std::shared_ptr<BBLStatusBarSend> m_status_bar;
bool m_export_3mf_cancel{ false };
bool m_is_canceled{ false };
protected:
std::vector<MachineObject*> m_list;
wxDataViewCtrl* m_dataViewListCtrl_machines{ nullptr };
wxStaticText* m_staticText_left{ nullptr };
wxHyperlinkCtrl* m_hyperlink_add_machine{ nullptr };
wxGauge* m_gauge_job_progress{ nullptr };
wxPanel* m_panel_status{ nullptr };
wxButton* m_button_cancel{ nullptr };
std::string m_print_info;
int timeout_count = 0;
bool is_timeout();
void reset_timeout();
void update_user_printer();
void update_show_status();
wxTimer* m_refresh_timer{ nullptr };
std::shared_ptr<SendJob> m_send_job{nullptr};
// Virtual event handlers, overide them in your derived class
void update_printer_combobox(wxCommandEvent& event);
void on_cancel(wxCloseEvent& event);
void on_ok(wxCommandEvent& event);
void on_refresh(wxCommandEvent& event);
void on_print_job_cancel(wxCommandEvent& evt);
void set_default();
void on_timer(wxTimerEvent& event);
void on_selection_changed(wxCommandEvent& event);
void Enable_Refresh_Button(bool en);
void show_status(PrintDialogStatus status, std::vector<wxString> params = std::vector<wxString>());
void Enable_Send_Button(bool en);
void on_dpi_changed(const wxRect& suggested_rect) override;
void update_user_machine_list();
std::vector<std::string> sort_string(std::vector<std::string> strArray);
};
}
}
#endif

View file

@ -177,6 +177,7 @@ void StatusBasePanel::init_bitmaps()
m_thumbnail_sdcard = ScalableBitmap(this, "monitor_sdcard_thumbnail", 120);
//m_bitmap_camera = create_scaled_bitmap("monitor_camera", nullptr, 18);
m_bitmap_extruder = *cache.load_png("monitor_extruder", FromDIP(28), FromDIP(70), false, false);
m_bitmap_extruder_load = *cache.load_png("monitor_extruder_load", FromDIP(28), FromDIP(70), false, false);
m_bitmap_sdcard_state_on = create_scaled_bitmap("sdcard_state_on", nullptr, 20);
m_bitmap_sdcard_state_off = create_scaled_bitmap("sdcard_state_off", nullptr, 20);
}
@ -741,7 +742,7 @@ wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent)
m_switch_nozzle_fan->SetLabels(_L("Part Cooling"), _L("Part Cooling"));
m_switch_nozzle_fan->SetPadding(FromDIP(3));
m_switch_nozzle_fan->SetBorderWidth(FromDIP(2));
m_switch_nozzle_fan->SetFont(SWITCH_FONT);
m_switch_nozzle_fan->SetFont(::Label::Body_10);
m_switch_nozzle_fan->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int) StateColor::Normal)));
line_sizer->Add(m_switch_nozzle_fan, 1, wxALIGN_CENTER | wxALL, 0);
@ -754,7 +755,7 @@ wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent)
m_switch_printing_fan->SetMinSize(MISC_BUTTON_SIZE);
m_switch_printing_fan->SetPadding(FromDIP(3));
m_switch_printing_fan->SetBorderWidth(FromDIP(2));
m_switch_printing_fan->SetFont(SWITCH_FONT);
m_switch_printing_fan->SetFont(::Label::Body_10);
m_switch_printing_fan->SetLabels(_L("Aux Cooling"), _L("Aux Cooling"));
m_switch_printing_fan->SetTextColor(
StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int) StateColor::Normal)));
@ -770,11 +771,11 @@ void StatusBasePanel::reset_temp_misc_control()
{
// reset temp string
m_tempCtrl_nozzle->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle->GetTextCtrl()->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_bed->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_bed->GetTextCtrl()->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_bed->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_frame->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_frame->GetTextCtrl()->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_frame->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_button_unload->Show();
m_tempCtrl_nozzle->Enable(true);
@ -1103,6 +1104,8 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
Bind(EVT_AMS_REFRESH_RFID, &StatusPanel::on_ams_refresh_rfid, this);
Bind(EVT_AMS_ON_SELECTED, &StatusPanel::on_ams_selected, this);
Bind(EVT_AMS_ON_FILAMENT_EDIT, &StatusPanel::on_filament_edit, this);
Bind(EVT_AMS_GUIDE_WIKI, &StatusPanel::on_ams_guide, this);
Bind(EVT_AMS_RETRY, &StatusPanel::on_ams_retry, this);
m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this);
m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this);
@ -1305,6 +1308,13 @@ void StatusPanel::update(MachineObject *obj)
update_temp_ctrl(obj);
update_misc_ctrl(obj);
if (obj && obj->is_filament_at_extruder()) {
m_bitmap_extruder_img->SetBitmap(m_bitmap_extruder_load);
}
else {
m_bitmap_extruder_img->SetBitmap(m_bitmap_extruder);
}
// BBS hide tasklist info
// update_tasklist(obj);
update_ams(obj);
@ -1351,7 +1361,7 @@ void StatusPanel::update(MachineObject *obj)
m_tempCtrl_frame->Enable();
} else {
m_tempCtrl_frame->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_frame->GetTextCtrl()->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_frame->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_frame->Disable();
}
@ -1386,6 +1396,7 @@ void StatusPanel::update_error_message()
}
if (before_error_code != obj->print_error) {
before_error_code = obj->print_error;
if (wxGetApp().get_hms_query()) {
char buf[32];
::sprintf(buf, "%08X", obj->print_error);
@ -1398,11 +1409,11 @@ void StatusPanel::update_error_message()
print_error_str);
show_error_message(error_msg);
//hint dialog
ConfirmHintDialog print_error_dlg(this->GetParent(), wxID_ANY, _L("Warning"));
BOOST_LOG_TRIVIAL(info) << "Print error! " << error_msg;
ConfirmHintDialog print_error_dlg(this->GetParent(), wxID_ANY, _L("Warning"), ConfirmHintDialog::ButtonStyle::ONLY_CONFIRM);
print_error_dlg.SetHint(error_msg);
print_error_dlg.ShowModal();
}
before_error_code = obj->print_error;
}
}
@ -1764,7 +1775,7 @@ void StatusPanel::update_cali(MachineObject *obj)
{
if (!obj) return;
if (obj->is_in_calibration()) {
if (obj->is_calibration_running()) {
m_calibration_btn->SetLabel(_L("Calibrating"));
if (calibration_dlg && calibration_dlg->IsShown()) {
m_calibration_btn->Disable();
@ -1840,7 +1851,8 @@ void StatusPanel::update_subtask(MachineObject *obj)
{
if (!obj) return;
if (obj->is_system_printing()) {
if (obj->is_system_printing()
|| obj->is_in_calibration()) {
reset_printing_values();
} else if (obj->is_in_printing() || obj->print_status == "FINISH") {
if (obj->is_in_prepare()) {
@ -2103,11 +2115,17 @@ void StatusPanel::on_set_nozzle_temp()
}
void StatusPanel::on_ams_load(SimpleEvent &event)
{
BOOST_LOG_TRIVIAL(info) << "on_ams_load";
on_ams_load_curr();
}
void StatusPanel::on_ams_load_curr()
{
if (obj) {
std::string curr_ams_id = m_ams_control->GetCurentAms();
std::string curr_can_id = m_ams_control->GetCurrentCan(curr_ams_id);
std::map<std::string, Ams *>::iterator it = obj->amsList.find(curr_ams_id);
std::map<std::string, Ams*>::iterator it = obj->amsList.find(curr_ams_id);
if (it == obj->amsList.end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed";
return;
@ -2118,8 +2136,8 @@ void StatusPanel::on_ams_load(SimpleEvent &event)
return;
}
AmsTray *curr_tray = obj->get_curr_tray();
AmsTray *targ_tray = obj->get_ams_tray(curr_ams_id, curr_can_id);
AmsTray* curr_tray = obj->get_curr_tray();
AmsTray* targ_tray = obj->get_ams_tray(curr_ams_id, curr_can_id);
if (curr_tray && targ_tray) {
int old_temp = -1;
int new_temp = -1;
@ -2128,12 +2146,14 @@ void StatusPanel::on_ams_load(SimpleEvent &event)
old_temp = (atoi(curr_tray->nozzle_temp_min.c_str()) + atoi(curr_tray->nozzle_temp_max.c_str())) / 2;
if (!targ_tray->nozzle_temp_max.empty() && !targ_tray->nozzle_temp_min.empty())
new_temp = (atoi(targ_tray->nozzle_temp_min.c_str()) + atoi(targ_tray->nozzle_temp_max.c_str())) / 2;
} catch (...) {
}
catch (...) {
;
}
int tray_index = atoi(curr_ams_id.c_str()) * 4 + atoi(tray_it->second->id.c_str());
obj->command_ams_switch(tray_index, old_temp, new_temp);
} else {
}
else {
int tray_index = atoi(curr_ams_id.c_str()) * 4 + atoi(tray_it->second->id.c_str());
obj->command_ams_switch(tray_index, -1, -1);
}
@ -2257,6 +2277,20 @@ void StatusPanel::on_ams_selected(wxCommandEvent &event)
}
}
void StatusPanel::on_ams_guide(wxCommandEvent& event)
{
wxString ams_wiki_url = "https://wiki.bambulab.com/en/software/bambu-studio/use-ams-on-bambu-studio";
wxLaunchDefaultBrowser(ams_wiki_url);
}
void StatusPanel::on_ams_retry(wxCommandEvent& event)
{
BOOST_LOG_TRIVIAL(info) << "on_ams_retry";
if (obj) {
obj->command_ams_control("resume");
}
}
void StatusPanel::on_bed_temp_kill_focus(wxFocusEvent &event)
{
event.Skip();

View file

@ -81,6 +81,7 @@ protected:
ScalableBitmap m_bitmap_use_time;
ScalableBitmap m_bitmap_use_weight;
wxBitmap m_bitmap_extruder;
wxBitmap m_bitmap_extruder_load;
CameraRecordingStatus m_state_recording{CameraRecordingStatus::RECORDING_NONE};
CameraTimelapseStatus m_state_timelapse{CameraTimelapseStatus::TIMELAPSE_NONE};
@ -300,11 +301,14 @@ protected:
/* extruder apis */
void on_ams_load(SimpleEvent &event);
void on_ams_load_curr();
void on_ams_unload(SimpleEvent &event);
void on_ams_setting_click(SimpleEvent &event);
void on_filament_edit(wxCommandEvent &event);
void on_ams_refresh_rfid(wxCommandEvent &event);
void on_ams_selected(wxCommandEvent &event);
void on_ams_guide(wxCommandEvent &event);
void on_ams_retry(wxCommandEvent &event);
void on_switch_speed(wxCommandEvent &event);
void on_lamp_switch(wxCommandEvent &event);

View file

@ -318,7 +318,7 @@ void Tab::create_preset_tab()
this->GetParent()->Update();
this->GetParent()->Layout();
wxGetApp().plater()->search(false, m_type, m_search_item, m_search_input, m_btn_search);
wxGetApp().plater()->search(false, m_type, m_top_panel->GetParent(), m_search_input, m_btn_search);
m_search_input->SetFocus();
Thaw();
@ -1382,19 +1382,14 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
auto timelapse_type = m_config->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth;
if (!boost::any_cast<bool>(value) && timelapse_enabled) {
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by timeplase. Are you sure you want to disable both of them?"),
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by smooth timeplase. If whthout prime tower, there will be flaws on the model. Are you sure you want to disable prime tower?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) {
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(TimelapseType::tlNone));
m_config_manipulation.apply(m_config, &new_conf);
wxGetApp().plater()->update();
}
else {
if (dlg.ShowModal() == wxID_NO) {
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
m_config_manipulation.apply(m_config, &new_conf);
}
wxGetApp().plater()->update();
}
update_wiping_button_visibility();
}
@ -1403,7 +1398,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
if (opt_key == "timelapse_type") {
bool wipe_tower_enabled = m_config->option<ConfigOptionBool>("enable_prime_tower")->value;
if (!wipe_tower_enabled && boost::any_cast<int>(value) == int(TimelapseType::tlSmooth)) {
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by timelapse. Do you want to enable both of them?"),
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by smooth timelapse. If whthout prime tower, there will be flaws on the model. Do you want to enable prime tower?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) {
DynamicPrintConfig new_conf = *m_config;
@ -1411,11 +1406,6 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
m_config_manipulation.apply(m_config, &new_conf);
wxGetApp().plater()->update();
}
else {
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(TimelapseType::tlNone));
m_config_manipulation.apply(m_config, &new_conf);
}
} else {
wxGetApp().plater()->update();
}
@ -1515,8 +1505,14 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category)
Field* field = get_field(opt_key);
// focused selected field
if (field)
if (field) {
set_focus(field->getWindow());
if (!field->getWindow()->HasFocus()) {
wxScrollEvent evt(wxEVT_SCROLL_CHANGED);
evt.SetEventObject(field->getWindow());
wxPostEvent(m_page_view, evt);
}
}
//else if (category == "Single extruder MM setup") {
// // When we show and hide "Single extruder MM setup" page,
// // related options are still in the search list
@ -1807,9 +1803,9 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
optgroup->append_single_option_line("sparse_infill_density");
optgroup->append_single_option_line("sparse_infill_pattern");
optgroup->append_single_option_line("top_surface_pattern");
optgroup->append_single_option_line("bottom_surface_pattern");
optgroup->append_single_option_line("sparse_infill_pattern", "fill-patterns#infill types and their properties of sparse");
optgroup->append_single_option_line("top_surface_pattern", "fill-patterns#Infill of the top surface and bottom surface");
optgroup->append_single_option_line("bottom_surface_pattern", "fill-patterns#Infill of the top surface and bottom surface");
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
optgroup->append_single_option_line("infill_wall_overlap");
@ -1932,19 +1928,7 @@ void TabPrint::build()
optgroup->append_single_option_line("print_sequence");
optgroup->append_single_option_line("spiral_mode", "spiral-vase");
optgroup->append_single_option_line("timelapse_type", "Timelapse");
//BBS: todo remove clearance to machine
#if 0
//line = { L("Extruder radius"), "" };
//line.append_option(optgroup->get_option("extruder_clearance_radius"));
//optgroup->append_line(line);
////BBS: new line for extruder_clearance_height_to_lid as there is not enough space for a single line
//line = { L("Height to rod"), "" };
//line.append_option(optgroup->get_option("extruder_clearance_height_to_rod"));
//optgroup->append_line(line);
//line = { L("Height to lid"), "" };
//line.append_option(optgroup->get_option("extruder_clearance_height_to_lid"));
//optgroup->append_line(line);
#endif
optgroup->append_single_option_line("fuzzy_skin");
optgroup->append_single_option_line("fuzzy_skin_point_distance");
optgroup->append_single_option_line("fuzzy_skin_thickness");
@ -2888,6 +2872,11 @@ void TabPrinter::build_fff()
optgroup->append_single_option_line("machine_load_filament_time");
optgroup->append_single_option_line("machine_unload_filament_time");
optgroup = page->new_optgroup(L("Extruder Clearance"));
optgroup->append_single_option_line("extruder_clearance_radius");
optgroup->append_single_option_line("extruder_clearance_height_to_rod");
optgroup->append_single_option_line("extruder_clearance_height_to_lid");
optgroup = page->new_optgroup(L("Accessory") /*, L"param_accessory"*/);
optgroup->append_single_option_line("nozzle_type");
optgroup->append_single_option_line("auxiliary_fan");
@ -2953,6 +2942,15 @@ void TabPrinter::build_fff()
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Template Custom G-code"), L"param_gcode", 0);
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, opt_key, value);
};
option = optgroup->get_option("template_custom_gcode");
option.opt.is_code = true;
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
#if 0
//page = add_options_page(L("Dependencies"), "advanced");
// optgroup = page->new_optgroup(L("Profile dependencies"));
@ -3417,17 +3415,26 @@ void TabPrinter::toggle_options()
if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA)
return;
bool have_multiple_extruders = m_extruders_count > 1;
if (m_active_page->title() == "Custom G-code") {
toggle_option("change_filament_gcode", have_multiple_extruders);
//BBS: whether the preset is Bambu Lab printer
bool is_BBL_printer = false;
if (m_preset_bundle) {
is_BBL_printer = m_preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(m_preset_bundle);
}
if (m_active_page->title() == "General") {
bool have_multiple_extruders = m_extruders_count > 1;
//if (m_active_page->title() == "Custom G-code") {
// toggle_option("change_filament_gcode", have_multiple_extruders);
//}
if (m_active_page->title() == "Basic information") {
toggle_option("single_extruder_multi_material", have_multiple_extruders);
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware;
// Disable silent mode for non-marlin firmwares.
toggle_option("silent_mode", is_marlin_flavor);
//BBS: extruder clearance of BBL printer can't be edited.
for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" })
toggle_option(el, !is_BBL_printer);
}
wxString extruder_number;
@ -3476,9 +3483,10 @@ void TabPrinter::toggle_options()
|| m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlinFirmware);
bool silent_mode = m_config->opt_bool("silent_mode");
int max_field = silent_mode ? 2 : 1;
//BBS: limits of BBL printer can't be edited.
for (const std::string &opt : Preset::machine_limits_options())
for (int i = 0; i < max_field; ++ i)
toggle_option(opt, true, i);
toggle_option(opt, !is_BBL_printer, i);
}
}
@ -4285,12 +4293,21 @@ void Tab::compare_preset()
// Wizard calls save_preset with a name "My Settings", otherwise no name is provided and this method
// opens a Slic3r::GUI::SavePresetDialog dialog.
//BBS: add project embedded preset relate logic
void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_project)
void Tab::save_preset(std::string name /*= ""*/, bool detach, bool save_to_project, bool from_input, std::string input_name )
{
// since buttons(and choices too) don't get focus on Mac, we set focus manually
// to the treectrl so that the EVT_* events are fired for the input field having
// focus currently.is there anything better than this ?
//! m_tabctrl->OnSetFocus();
if (from_input) {
SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : "");
dlg.Show(false);
dlg.input_name_from_other(input_name);
wxCommandEvent evt(wxEVT_TEXT, GetId());
dlg.GetEventHandler()->ProcessEvent(evt);
dlg.confirm_from_other();
name = input_name;
}
if (name.empty()) {
SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : "");

View file

@ -333,7 +333,7 @@ public:
void compare_preset();
//BBS: add project embedded preset relate logic
void save_preset(std::string name = std::string(), bool detach = false, bool save_to_project = false);
void save_preset(std::string name = std::string(), bool detach = false, bool save_to_project = false, bool from_input = false, std::string input_name = "");
//void save_preset(std::string name = std::string(), bool detach = false);
void delete_preset();

View file

@ -228,6 +228,7 @@ wxPanel *MachineInfoPanel::create_caption_panel(wxWindow *parent)
m_upgrade_status_img = new wxStaticBitmap(caption_panel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(5), FromDIP(5)));
m_upgrade_status_img->SetBitmap(upgrade_gray_icon);
m_upgrade_status_img->Hide();
m_caption_sizer->Add(m_upgrade_status_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
m_caption_text = new wxStaticText(caption_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize);

View file

@ -649,6 +649,34 @@ int GuideFrame::SaveProfile()
return 0;
}
static std::set<std::string> get_new_added_presets(const std::map<std::string, std::string>& old_data, const std::map<std::string, std::string>& new_data)
{
auto get_aliases = [](const std::map<std::string, std::string>& data) {
std::set<std::string> old_aliases;
for (auto item : data) {
const std::string& name = item.first;
size_t pos = name.find("@");
old_aliases.emplace(pos == std::string::npos ? name : name.substr(0, pos-1));
}
return old_aliases;
};
std::set<std::string> old_aliases = get_aliases(old_data);
std::set<std::string> new_aliases = get_aliases(new_data);
std::set<std::string> diff;
std::set_difference(new_aliases.begin(), new_aliases.end(), old_aliases.begin(), old_aliases.end(), std::inserter(diff, diff.begin()));
return diff;
}
static std::string get_first_added_preset(const std::map<std::string, std::string>& old_data, const std::map<std::string, std::string>& new_data)
{
std::set<std::string> diff = get_new_added_presets(old_data, new_data);
if (diff.empty())
return std::string();
return *diff.begin();
}
bool GuideFrame::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater, bool& apply_keeped_changes)
{
const auto enabled_vendors = m_appconfig_new.vendors();
@ -714,13 +742,67 @@ bool GuideFrame::apply_config(AppConfig *app_config, PresetBundle *preset_bundle
BOOST_LOG_TRIVIAL(info) << "No bundles need to be removed";
}
std::string preferred_model;
std::string preferred_variant;
PrinterTechnology preferred_pt = ptFFF;
auto get_preferred_printer_model = [preset_bundle, enabled_vendors, old_enabled_vendors, preferred_pt](const std::string& bundle_name, std::string& variant) {
const auto config = enabled_vendors.find(bundle_name);
if (config == enabled_vendors.end())
return std::string();
const std::map<std::string, std::set<std::string>>& model_maps = config->second;
//for (const auto& vendor_profile : preset_bundle->vendors) {
for (const auto model_it: model_maps) {
if (model_it.second.size() > 0) {
variant = *model_it.second.begin();
const auto config_old = old_enabled_vendors.find(bundle_name);
if (config_old == old_enabled_vendors.end())
return model_it.first;
const auto model_it_old = config_old->second.find(model_it.first);
if (model_it_old == config_old->second.end())
return model_it.first;
else if (model_it_old->second != model_it.second) {
for (const auto& var : model_it.second)
if (model_it_old->second.find(var) == model_it_old->second.end()) {
variant = var;
return model_it.first;
}
}
}
}
//}
if (!variant.empty())
variant.clear();
return std::string();
};
// Prusa printers are considered first, then 3rd party.
if (preferred_model = get_preferred_printer_model(PresetBundle::BBL_BUNDLE, preferred_variant);
preferred_model.empty()) {
for (const auto& bundle : enabled_vendors) {
if (bundle.first == PresetBundle::BBL_BUNDLE) { continue; }
if (preferred_model = get_preferred_printer_model(bundle.first, preferred_variant);
!preferred_model.empty())
break;
}
}
std::string first_added_filament;
auto get_first_added_material_preset = [this, app_config](const std::string& section_name, std::string& first_added_preset) {
if (m_appconfig_new.has_section(section_name)) {
// get first of new added preset names
const std::map<std::string, std::string>& old_presets = app_config->has_section(section_name) ? app_config->get_section(section_name) : std::map<std::string, std::string>();
first_added_preset = get_first_added_preset(old_presets, m_appconfig_new.get_section(section_name));
}
};
get_first_added_material_preset(AppConfig::SECTION_FILAMENTS, first_added_filament);
//update the app_config
app_config->set_section(AppConfig::SECTION_FILAMENTS, enabled_filaments);
app_config->set_vendors(m_appconfig_new);
if (check_unsaved_preset_changes)
preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem,
{PresetBundle::BBL_DEFAULT_PRINTER_MODEL, PresetBundle::BBL_DEFAULT_PRINTER_VARIANT, PresetBundle::BBL_DEFAULT_FILAMENT, std::string()});
{preferred_model, preferred_variant, first_added_filament, std::string()});
// Update the selections from the compatibilty.
preset_bundle->export_selections(*app_config);
@ -902,6 +984,7 @@ int GuideFrame::LoadProfile()
//} while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
//load BBL bundle from user data path
string targetPath = bbl_bundle_path.make_preferred().string();
boost::filesystem::path myPath(targetPath);
boost::filesystem::directory_iterator endIter;
@ -914,11 +997,30 @@ int GuideFrame::LoadProfile()
//cout << iter->path().string() << endl;
wxString strVendor = from_u8(iter->path().string()).BeforeLast('.');
strVendor = strVendor.AfterLast( '\\');
strVendor = strVendor.AfterLast('\/');
strVendor = strVendor.AfterLast('\/');
LoadProfileFamily(w2s(strVendor), iter->path().string());
if (w2s(strVendor) == PresetBundle::BBL_BUNDLE)
LoadProfileFamily(w2s(strVendor), iter->path().string());
}
}
//string others_targetPath = rsrc_vendor_dir.string();
boost::filesystem::directory_iterator others_endIter;
for (boost::filesystem::directory_iterator iter(rsrc_vendor_dir); iter != others_endIter; iter++) {
if (boost::filesystem::is_directory(*iter)) {
//cout << "is dir" << endl;
//cout << iter->path().string() << endl;
} else {
//cout << "is a file" << endl;
//cout << iter->path().string() << endl;
wxString strVendor = from_u8(iter->path().string()).BeforeLast('.');
strVendor = strVendor.AfterLast( '\\');
strVendor = strVendor.AfterLast('\/');
if (w2s(strVendor) != PresetBundle::BBL_BUNDLE)
LoadProfileFamily(w2s(strVendor), iter->path().string());
}
}
//LoadProfileFamily(PresetBundle::BBL_BUNDLE, bbl_bundle_path.string());
@ -1309,15 +1411,15 @@ int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath
json pPrinters = pm["compatible_printers"];
int nPrinter = pPrinters.size();
std::string ModelList = "";
for (int i = 0; i < nPrinter; i++)
{
for (int i = 0; i < nPrinter; i++)
{
std::string sP = pPrinters.at(i);
if (m_ProfileJson["machine"].contains(sP))
if (m_ProfileJson["machine"].contains(sP))
{
std::string mModel = m_ProfileJson["machine"][sP]["model"];
std::string mNozzle = m_ProfileJson["machine"][sP]["nozzle"];
std::string NewModel = mModel + "++" + mNozzle;
ModelList = (boost::format("%1%[%2%]") % ModelList % NewModel).str();
}
}

View file

@ -31,6 +31,8 @@ wxDEFINE_EVENT(EVT_AMS_ON_SELECTED, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_ON_FILAMENT_EDIT, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_CLIBRATION_AGAIN, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_CLIBRATION_CANCEL, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_GUIDE_WIKI, wxCommandEvent);
wxDEFINE_EVENT(EVT_AMS_RETRY, wxCommandEvent);
inline int hex_digit_to_int(const char c)
{
@ -1467,14 +1469,26 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
m_simplebook_right->AddPage(m_filament_unload_step, wxEmptyString, false);
wxBoxSizer *m_sizer_right_bottom = new wxBoxSizer(wxHORIZONTAL);
m_sizer_right_bottom->Add(0, 0, 1, wxEXPAND, FromDIP(5));
m_button_ams_setting = new Button(m_amswin, _L("AMS Settings"));
m_button_ams_setting->SetBackgroundColor(btn_bg_white);
m_button_ams_setting->SetBorderColor(btn_bd_white);
m_button_ams_setting->SetFont(Label::Body_13);
//m_button_ams_setting->Hide();
m_sizer_right_bottom->Add(m_button_ams_setting, 0, wxTOP, FromDIP(20));
m_sizer_right->Add(m_sizer_right_bottom, 0, wxEXPAND, FromDIP(5));
m_button_ams_setting = new Button(m_amswin, "", "ams_setting_normal", wxBORDER_NONE, FromDIP(24));
m_button_ams_setting->SetPaddingSize(wxSize(0, 0));
m_button_ams_setting->SetBackgroundColor(m_amswin->GetBackgroundColour());
m_button_guide = new Button(m_amswin, _L("Guide"));
m_button_guide->SetFont(Label::Body_13);
m_button_guide->SetCornerRadius(FromDIP(12));
m_button_guide->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_guide->SetBackgroundColor(btn_bg_white);
m_button_retry = new Button(m_amswin, _L("Retry"));
m_button_retry->SetFont(Label::Body_13);
m_button_retry->SetCornerRadius(FromDIP(12));
m_button_retry->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_retry->SetBackgroundColor(btn_bg_white);
m_sizer_right_bottom->Add(m_button_ams_setting, 0);
m_sizer_right_bottom->Add(m_button_guide, 0, wxLEFT, FromDIP(10));
m_sizer_right_bottom->Add(m_button_retry, 0, wxLEFT, FromDIP(10));
m_sizer_right->Add(m_sizer_right_bottom, 0, wxEXPAND | wxTOP, FromDIP(20));
m_sizer_bottom->Add(m_sizer_right, 0, wxEXPAND, FromDIP(5));
m_sizer_body->Add(m_simplebook_amsitems, 0, wxEXPAND, 0);
@ -1485,7 +1499,6 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
m_amswin->SetSizer(m_sizer_body);
m_amswin->Layout();
m_amswin->Fit();
//Thaw();
SetSize(m_amswin->GetSize());
@ -1566,6 +1579,25 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons
m_button_extruder_feed->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AMSControl::on_filament_load), NULL, this);
m_button_extruder_back->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AMSControl::on_filament_unload), NULL, this);
m_button_ams_setting->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AMSControl::on_ams_setting_click), NULL, this);
m_button_ams_setting->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent& e) {
m_button_ams_setting->SetIcon("ams_setting_hover");
e.Skip();
});
m_button_ams_setting->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
m_button_ams_setting->SetIcon("ams_setting_press");
e.Skip();
});
m_button_ams_setting->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent&e) {
m_button_ams_setting->SetIcon("ams_setting_normal");
e.Skip();
});
m_button_guide->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
post_event(wxCommandEvent(EVT_AMS_GUIDE_WIKI));
});
m_button_retry->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
post_event(wxCommandEvent(EVT_AMS_RETRY));
});
CreateAms();
SetSelection(0);
@ -1578,8 +1610,6 @@ void AMSControl::init_scaled_buttons()
m_button_extruder_feed->SetCornerRadius(FromDIP(12));
m_button_extruder_back->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_extruder_back->SetCornerRadius(FromDIP(12));
m_button_ams_setting->SetMinSize(wxSize(-1, FromDIP(33)));
m_button_ams_setting->SetCornerRadius(FromDIP(12));
}
std::string AMSControl::GetCurentAms() { return m_current_ams; }
@ -1709,7 +1739,9 @@ void AMSControl::msw_rescale()
m_extruder->msw_rescale();
m_button_extruder_back->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_extruder_feed->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_ams_setting->SetMinSize(wxSize(-1, FromDIP(33)));
m_button_ams_setting->SetMinSize(wxSize(FromDIP(25), FromDIP(24)));
m_button_guide->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_retry->SetMinSize(wxSize(-1, FromDIP(24)));
for (auto i = 0; i < m_ams_cans_list.GetCount(); i++) {
AmsCansWindow *cans = m_ams_cans_list[i];

View file

@ -461,7 +461,9 @@ protected:
Button *m_button_extruder_feed = {nullptr};
Button *m_button_extruder_back = {nullptr};
Button *m_button_ams_setting = {nullptr};
Button* m_button_ams_setting = {nullptr};
Button *m_button_guide = {nullptr};
Button *m_button_retry = {nullptr};
wxHyperlinkCtrl *m_hyperlink = {nullptr};
@ -518,6 +520,8 @@ wxDECLARE_EVENT(EVT_AMS_ON_SELECTED, wxCommandEvent);
wxDECLARE_EVENT(EVT_AMS_ON_FILAMENT_EDIT, wxCommandEvent);
wxDECLARE_EVENT(EVT_AMS_CLIBRATION_AGAIN, wxCommandEvent);
wxDECLARE_EVENT(EVT_AMS_CLIBRATION_CANCEL, wxCommandEvent);
wxDECLARE_EVENT(EVT_AMS_GUIDE_WIKI, wxCommandEvent);
wxDECLARE_EVENT(EVT_AMS_RETRY, wxCommandEvent);
}} // namespace Slic3r::GUI

View file

@ -7,6 +7,7 @@ BEGIN_EVENT_TABLE(Button, StaticBox)
EVT_LEFT_DOWN(Button::mouseDown)
EVT_LEFT_UP(Button::mouseReleased)
EVT_MOUSE_CAPTURE_LOST(Button::mouseCaptureLost)
EVT_KEY_DOWN(Button::keyDownUp)
EVT_KEY_UP(Button::keyDownUp)
@ -23,7 +24,6 @@ END_EVENT_TABLE()
Button::Button()
: paddingSize(10, 8)
, text_color(*wxBLACK)
{
background_color = StateColor(
std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
@ -31,6 +31,9 @@ Button::Button()
std::make_pair(0x00AE42, (int) StateColor::Checked),
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal));
text_color = StateColor(
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Disabled),
std::make_pair(*wxBLACK, (int) StateColor::Normal));
}
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, int iconSize)
@ -242,12 +245,19 @@ void Button::mouseReleased(wxMouseEvent& event)
event.Skip();
if (pressedDown) {
pressedDown = false;
ReleaseMouse();
if (HasCapture())
ReleaseMouse();
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
sendButtonEvent();
}
}
void Button::mouseCaptureLost(wxMouseCaptureLostEvent &event)
{
wxMouseEvent evt;
mouseReleased(evt);
}
void Button::keyDownUp(wxKeyEvent &event)
{
if (event.GetKeyCode() == WXK_SPACE || event.GetKeyCode() == WXK_RETURN) {

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