Merge branch 'main' into feat/plugin-pages

This commit is contained in:
Ian Chua
2026-08-14 12:20:34 +08:00
committed by GitHub
26 changed files with 182 additions and 93 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "Snapmaker", "name": "Snapmaker",
"version": "02.04.00.08", "version": "02.04.00.09",
"force_update": "0", "force_update": "0",
"description": "Snapmaker configurations", "description": "Snapmaker configurations",
"machine_model_list": [ "machine_model_list": [
@@ -186,7 +186,6 @@
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\nTIMELAPSE_TAKE_FRAME\nDEFECT_DETECTION_DETECT", "before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\nTIMELAPSE_TAKE_FRAME\nDEFECT_DETECTION_DETECT",
"machine_pause_gcode": "M600", "machine_pause_gcode": "M600",
"nozzle_volume": "143", "nozzle_volume": "143",
"support_multi_bed_types": "0",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}", "layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}",
"default_print_profile": "0.10 Standard @Snapmaker U1 (0.2 nozzle)" "default_print_profile": "0.10 Standard @Snapmaker U1 (0.2 nozzle)"
} }
@@ -186,7 +186,6 @@
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\nTIMELAPSE_TAKE_FRAME\nDEFECT_DETECTION_DETECT", "before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\nTIMELAPSE_TAKE_FRAME\nDEFECT_DETECTION_DETECT",
"default_print_profile": "0.20 Standard @Snapmaker U1 (0.4 nozzle)", "default_print_profile": "0.20 Standard @Snapmaker U1 (0.4 nozzle)",
"machine_pause_gcode": "M600", "machine_pause_gcode": "M600",
"default_bed_type": "Textured PEI Plate",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}", "layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}",
"nozzle_volume": "143", "nozzle_volume": "143",
"resonance_avoidance": "1", "resonance_avoidance": "1",
@@ -187,6 +187,5 @@
"machine_pause_gcode": "M600", "machine_pause_gcode": "M600",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}", "layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}",
"nozzle_volume": "143", "nozzle_volume": "143",
"support_multi_bed_types": "0",
"default_print_profile": "0.30 Standard @Snapmaker U1 (0.6 nozzle)" "default_print_profile": "0.30 Standard @Snapmaker U1 (0.6 nozzle)"
} }
@@ -187,6 +187,5 @@
"machine_pause_gcode": "M600", "machine_pause_gcode": "M600",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}", "layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} CURRENT_LAYER={layer_num+1}",
"nozzle_volume": "143", "nozzle_volume": "143",
"support_multi_bed_types": "0",
"default_print_profile": "0.40 Standard @Snapmaker U1 (0.8 nozzle)" "default_print_profile": "0.40 Standard @Snapmaker U1 (0.8 nozzle)"
} }
@@ -183,7 +183,8 @@
"scan_first_layer": "0", "scan_first_layer": "0",
"nozzle_type": "undefine", "nozzle_type": "undefine",
"auxiliary_fan": "0", "auxiliary_fan": "0",
"default_bed_type": "Textured PEI Plate", "support_multi_bed_types": "1",
"default_bed_type": "4",
"printable_area": [ "printable_area": [
"0.5x1", "0.5x1",
"270.5x1", "270.5x1",
+2
View File
@@ -2982,6 +2982,8 @@ public:
const double & opt_float(const t_config_option_key &opt_key, unsigned int idx) const; const double & opt_float(const t_config_option_key &opt_key, unsigned int idx) const;
double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloatsNullable>(opt_key)->get_at(idx); } double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloatsNullable>(opt_key)->get_at(idx); }
const double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloatsNullable *>(this->option(opt_key))->get_at(idx); } const double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloatsNullable *>(this->option(opt_key))->get_at(idx); }
FloatOrPercent & opt_float_or_percent_nullable(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloatsOrPercentsNullable>(opt_key)->get_at(idx); }
const FloatOrPercent & opt_float_or_percent_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(this->option(opt_key))->get_at(idx); }
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; } int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; } int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
+1
View File
@@ -6726,6 +6726,7 @@ void GCode::append_full_config(const Print &print, std::string &str)
"farthest_point_timelapse"sv, "farthest_point_timelapse"sv,
"compatible_printers"sv, "compatible_printers"sv,
"compatible_prints"sv, "compatible_prints"sv,
"filament_colour_type"sv,
"print_host"sv, "print_host"sv,
"print_host_webui"sv, "print_host_webui"sv,
"printhost_apikey"sv, "printhost_apikey"sv,
+2 -2
View File
@@ -3243,9 +3243,9 @@ double Model::findMaxSpeed(const ModelObject* object) {
if (objectKey == "outer_wall_speed") if (objectKey == "outer_wall_speed")
externalPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); externalPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "small_perimeter_speed") if (objectKey == "small_perimeter_speed")
smallPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); smallPerimeterSpeedObj = object->config.get().opt_float_or_percent_nullable(objectKey, 0).get_abs_value(externalPerimeterSpeedObj);
if (objectKey == "small_support_perimeter_speed") if (objectKey == "small_support_perimeter_speed")
smallSupportPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); smallSupportPerimeterSpeedObj = object->config.get().opt_float_or_percent_nullable(objectKey, 0).get_abs_value(supportSpeedObj);
} }
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, std::max(smallSupportPerimeterSpeedObj, objMaxSpeed)))))))); objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, std::max(smallSupportPerimeterSpeedObj, objMaxSpeed))))))));
if (objMaxSpeed <= 0) objMaxSpeed = 250.; if (objMaxSpeed <= 0) objMaxSpeed = 250.;
+1 -1
View File
@@ -5378,7 +5378,7 @@ void PresetBundle::update_multi_material_filament_presets(size_t to_delete_filam
f_multiplier.resize(nozzle_nums, 1.f); f_multiplier.resize(nozzle_nums, 1.f);
} }
if ( (num_filaments * num_filaments) != size_t(old_matrix.size() / old_nozzle_nums) ) { if (old_matrix.size() != num_filaments * num_filaments * nozzle_nums) {
// First verify if purging volumes presets for each extruder matches number of extruders // First verify if purging volumes presets for each extruder matches number of extruders
std::vector<double>& filaments = this->project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values; std::vector<double>& filaments = this->project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values;
while (filaments.size() < 2* num_filaments) { while (filaments.size() < 2* num_filaments) {
+5 -3
View File
@@ -559,9 +559,11 @@ static inline bool model_volume_solid_or_modifier(const ModelVolume &mv)
static inline Transform3f trafo_for_bbox(const Transform3d &object_trafo, const Transform3d &volume_trafo) static inline Transform3f trafo_for_bbox(const Transform3d &object_trafo, const Transform3d &volume_trafo)
{ {
Transform3d m = object_trafo * volume_trafo; // Orca: Keep the volume's local XY offset for multipart overlap checks, but remove the object's bed placement.
m.translation().x() = 0.; Transform3d object_trafo_local = object_trafo;
m.translation().y() = 0.; object_trafo_local.translation().x() = 0.;
object_trafo_local.translation().y() = 0.;
Transform3d m = object_trafo_local * volume_trafo;
return m.cast<float>(); return m.cast<float>();
} }
+11 -1
View File
@@ -10426,6 +10426,16 @@ int DynamicPrintConfig::update_values_from_multi_to_multi_2(const std::vector<st
} }
void set_variant_override(ConfigOptionVectorBase &target, const ConfigOptionVectorBase &source,
const std::vector<int> &variant_index, int stride)
{
// A single-value object or region override applies to every nozzle variant.
std::vector<int> indices = variant_index;
if (source.size() == 1 && !source.is_nil(0))
std::fill(indices.begin(), indices.end(), 0);
target.set_to_index(&source, indices, stride);
}
//used for object/region config //used for object/region config
//use the smallest of multiple to single //use the smallest of multiple to single
@@ -11503,7 +11513,7 @@ void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPr
else { else {
ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(opt_src); ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(opt_src);
const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(opt_dest); const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(opt_dest);
opt_vec_src->set_to_index(opt_vec_dest, variant_index, stride); set_variant_override(*opt_vec_src, *opt_vec_dest, variant_index, stride);
} }
} }
} }
+52
View File
@@ -842,6 +842,9 @@ extern std::set<std::string> printer_options_with_variant_1;
extern std::set<std::string> printer_options_with_variant_2; extern std::set<std::string> printer_options_with_variant_2;
extern std::set<std::string> empty_options; extern std::set<std::string> empty_options;
void set_variant_override(ConfigOptionVectorBase &target, const ConfigOptionVectorBase &source,
const std::vector<int> &variant_index, int stride = 1);
extern std::set<std::string> filament_dev_options; extern std::set<std::string> filament_dev_options;
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1); extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
@@ -2394,6 +2397,55 @@ static void set_flush_volumes_matrix(std::vector<T> &out_matrix, const std::vect
} }
} }
template<class T>
static bool has_zero_flush_volume_for_used_filaments(const std::vector<T> &fv_matrix,
const std::vector<T> &flush_multipliers,
const std::vector<int> &used_filaments)
{
if (used_filaments.size() < 2 || flush_multipliers.empty())
return false;
if (fv_matrix.size() % flush_multipliers.size() != 0)
return false;
const size_t matrix_len = fv_matrix.size() / flush_multipliers.size();
const size_t row_len = size_t(std::sqrt(double(matrix_len)));
if (row_len < 2 || row_len * row_len != matrix_len)
return false;
std::vector<int> filtered_filaments;
filtered_filaments.reserve(used_filaments.size());
for (int filament_id : used_filaments) {
if (filament_id <= 0 || filament_id > int(row_len))
continue;
if (std::find(filtered_filaments.begin(), filtered_filaments.end(), filament_id) == filtered_filaments.end())
filtered_filaments.push_back(filament_id);
}
if (filtered_filaments.size() < 2)
return false;
for (T multiplier : flush_multipliers) {
if (multiplier == 0)
return true;
}
for (size_t nozzle_idx = 0; nozzle_idx < flush_multipliers.size(); nozzle_idx++) {
const size_t block_offset = nozzle_idx * matrix_len;
for (int from_id : filtered_filaments) {
for (int to_id : filtered_filaments) {
if (from_id == to_id)
continue;
const size_t matrix_idx = block_offset + size_t(from_id - 1) * row_len + size_t(to_id - 1);
if (matrix_idx < fv_matrix.size() && fv_matrix[matrix_idx] == 0)
return true;
}
}
}
return false;
}
size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id); size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id);
} // namespace Slic3r } // namespace Slic3r
+1 -1
View File
@@ -3812,7 +3812,7 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr
else { else {
ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(my_opt); ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(my_opt);
const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(it->second.get()); const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(it->second.get());
opt_vec_src->set_to_index(opt_vec_dest, variant_index, 1); set_variant_override(*opt_vec_src, *opt_vec_dest, variant_index);
} }
} }
} }
+3 -1
View File
@@ -156,6 +156,8 @@ void ConnectPrinterDialog::on_input_enter(wxCommandEvent& evt)
void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event) void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event)
{ {
wxString code = m_textCtrl_code->GetTextCtrl()->GetValue(); wxString code = m_textCtrl_code->GetTextCtrl()->GetValue();
if (code.empty())
code = "88888888";
for (char c : code) { for (char c : code) {
if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) { if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) {
show_error(this, _L("Invalid input")); show_error(this, _L("Invalid input"));
@@ -163,7 +165,7 @@ void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event)
} }
} }
if (m_obj) { if (m_obj) {
m_obj->set_user_access_code(code.ToStdString()); m_obj->set_access_code(code.ToStdString());
} }
EndModal(wxID_OK); EndModal(wxID_OK);
} }
+14 -5
View File
@@ -15,6 +15,18 @@
using namespace nlohmann; using namespace nlohmann;
namespace {
// Orca: access_code and user_access_code used to be separate AppConfig keys before the two
// fields were merged; fall back to the legacy key so existing users' saved codes aren't lost.
std::string get_access_code_with_legacy_fallback(Slic3r::AppConfig* config, const std::string& dev_id)
{
std::string code = config->get("access_code", dev_id);
if (code.empty())
code = config->get("user_access_code", dev_id);
return code;
}
}
namespace Slic3r namespace Slic3r
{ {
DeviceManager::DeviceManager(NetworkAgent* agent) DeviceManager::DeviceManager(NetworkAgent* agent)
@@ -48,8 +60,7 @@ namespace Slic3r
obj->bind_sec_link = "secure"; obj->bind_sec_link = "secure";
obj->m_is_online = true; obj->m_is_online = true;
obj->last_alive = Slic3r::Utils::get_current_time_utc(); obj->last_alive = Slic3r::Utils::get_current_time_utc();
obj->set_access_code(config->get("access_code", m.dev_id), false); obj->set_access_code(get_access_code_with_legacy_fallback(config, m.dev_id), false);
obj->set_user_access_code(config->get("user_access_code", m.dev_id), false);
if (obj->has_access_right()) { if (obj->has_access_right()) {
localMachineList.insert(std::make_pair(m.dev_id, obj)); localMachineList.insert(std::make_pair(m.dev_id, obj));
} else { } else {
@@ -339,8 +350,7 @@ namespace Slic3r
//load access code //load access code
AppConfig* config = Slic3r::GUI::wxGetApp().app_config; AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
if (config) { if (config) {
obj->set_access_code(Slic3r::GUI::wxGetApp().app_config->get("access_code", dev_id), false); obj->set_access_code(get_access_code_with_legacy_fallback(config, dev_id), false);
obj->set_user_access_code(Slic3r::GUI::wxGetApp().app_config->get("user_access_code", dev_id), false);
} }
localMachineList.insert(std::make_pair(dev_id, obj)); localMachineList.insert(std::make_pair(dev_id, obj));
@@ -382,7 +392,6 @@ namespace Slic3r
obj->m_is_online = true; obj->m_is_online = true;
obj->last_alive = Slic3r::Utils::get_current_time_utc(); obj->last_alive = Slic3r::Utils::get_current_time_utc();
obj->set_access_code(access_code, false); obj->set_access_code(access_code, false);
obj->set_user_access_code(access_code, false);
update_local_machine(*obj); update_local_machine(*obj);
+1 -35
View File
@@ -449,9 +449,7 @@ bool MachineObject::HasRecentLanMessage()
std::string MachineObject::get_access_code() const std::string MachineObject::get_access_code() const
{ {
if (get_user_access_code().empty()) return access_code;
return access_code;
return get_user_access_code();
} }
void MachineObject::set_access_code(std::string code, bool only_refresh) void MachineObject::set_access_code(std::string code, bool only_refresh)
@@ -470,37 +468,6 @@ void MachineObject::set_access_code(std::string code, bool only_refresh)
} }
} }
void MachineObject::erase_user_access_code()
{
this->user_access_code = "";
AppConfig* config = GUI::wxGetApp().app_config;
if (config) {
GUI::wxGetApp().app_config->erase("user_access_code", get_dev_id());
//GUI::wxGetApp().app_config->save();
}
}
void MachineObject::set_user_access_code(std::string code, bool only_refresh)
{
this->user_access_code = code;
if (only_refresh && !code.empty()) {
AppConfig* config = GUI::wxGetApp().app_config;
if (config && !code.empty()) {
GUI::wxGetApp().app_config->set_str("user_access_code", get_dev_id(), code);
DeviceManager::update_local_machine(*this);
}
}
}
std::string MachineObject::get_user_access_code() const
{
AppConfig* config = GUI::wxGetApp().app_config;
if (config) {
return GUI::wxGetApp().app_config->get("user_access_code", get_dev_id());
}
return "";
}
std::string MachineObject::get_show_printer_type() const std::string MachineObject::get_show_printer_type() const
{ {
std::string printer_type = this->printer_type; std::string printer_type = this->printer_type;
@@ -2907,7 +2874,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
std::string access_code = j_pre["system"]["access_code"].get<std::string>(); std::string access_code = j_pre["system"]["access_code"].get<std::string>();
if (!access_code.empty()) { if (!access_code.empty()) {
set_access_code(access_code); set_access_code(access_code);
set_user_access_code(access_code);
} }
} }
} }
-6
View File
@@ -113,7 +113,6 @@ private:
std::string dev_name; std::string dev_name;
std::string dev_ip; std::string dev_ip;
std::string access_code; std::string access_code;
std::string user_access_code;
// type, time stamp, delay // type, time stamp, delay
std::vector<std::tuple<std::string, uint64_t, uint64_t>> message_delay; std::vector<std::tuple<std::string, uint64_t, uint64_t>> message_delay;
@@ -228,11 +227,6 @@ public:
std::string get_access_code() const; std::string get_access_code() const;
void set_access_code(std::string code, bool only_refresh = true); void set_access_code(std::string code, bool only_refresh = true);
/*user access code*/
void set_user_access_code(std::string code, bool only_refresh = true);
void erase_user_access_code();
std::string get_user_access_code() const;
//PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN; //PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN;
std::string printer_type; /* model_id */ std::string printer_type; /* model_id */
std::string get_show_printer_type() const; std::string get_show_printer_type() const;
+7 -18
View File
@@ -10602,9 +10602,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
wxString region = L"en"; wxString region = L"en";
if (language.find("zh") == 0) if (language.find("zh") == 0)
region = L"zh"; region = L"zh";
// Use the generic dual-nozzle PLA+PETG guide rather than the H2D-specific page // Although this link looks like it's only for the H2D, its guidance is generic.
// so the link is relevant for all dual-extrusion printers, not just Bambu H2D. (#12073) wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.bambulab.com/%s/filament-acc/filament/h2d-pla-and-petg-mutual-support", region));
wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.bambulab.com/%s/filament-acc/filament/pla-and-petg-dual-extrusion", region));
return false; return false;
}); });
} }
@@ -10738,24 +10737,14 @@ bool GLCanvas3D::is_flushing_matrix_error() {
if (!Sidebar::should_show_SEMM_buttons()) if (!Sidebar::should_show_SEMM_buttons())
return false; return false;
std::vector<int> plate_extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders(true);
if (plate_extruders.size() < 2)
return false;
const auto &project_config = wxGetApp().preset_bundle->project_config; const auto &project_config = wxGetApp().preset_bundle->project_config;
const std::vector<double> &config_matrix = (project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values; const std::vector<double> &config_matrix = (project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values;
const std::vector<double> &config_multiplier = (project_config.option<ConfigOptionFloats>("flush_multiplier"))->values; const std::vector<double> &config_multiplier = (project_config.option<ConfigOptionFloats>("flush_multiplier"))->values;
return has_zero_flush_volume_for_used_filaments(config_matrix, config_multiplier, plate_extruders);
for (auto multiplier : config_multiplier) {
if (multiplier == 0) return true;
}
int matrix_len = config_matrix.size() / config_multiplier.size();
int row_len = std::sqrt(matrix_len);
for (int i = 0; i < config_matrix.size(); i++)
{
int relative_id = i % matrix_len;
int row_id = relative_id / row_len;
int col_id = relative_id % row_len;
if (row_id != col_id && config_matrix[i] == 0) return true;
}
return false;
} }
bool GLCanvas3D::_is_any_volume_outside() const bool GLCanvas3D::_is_any_volume_outside() const
+1 -3
View File
@@ -2166,7 +2166,6 @@ void GUI_App::init_networking_callbacks()
obj->is_tunnel_mqtt = tunnel; obj->is_tunnel_mqtt = tunnel;
obj->command_request_push_all(true); obj->command_request_push_all(true);
obj->command_get_version(); obj->command_get_version();
obj->erase_user_access_code();
obj->command_get_access_code(); obj->command_get_access_code();
if (m_agent) if (m_agent)
m_agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer()); m_agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer());
@@ -2216,7 +2215,6 @@ void GUI_App::init_networking_callbacks()
wxString text; wxString text;
if (msg == "5") { if (msg == "5") {
obj->set_access_code(""); obj->set_access_code("");
obj->erase_user_access_code();
text = wxString::Format(_L("Incorrect password")); text = wxString::Format(_L("Incorrect password"));
wxGetApp().show_dialog(text); wxGetApp().show_dialog(text);
} else { } else {
@@ -8300,7 +8298,7 @@ bool GUI_App::show_modal_ip_address_enter_dialog(bool input_sn, wxString title)
wxGetApp().app_config->save(); wxGetApp().app_config->save();
obj->set_dev_ip(ip_address.ToStdString()); obj->set_dev_ip(ip_address.ToStdString());
obj->set_user_access_code(access_code.ToStdString()); obj->set_access_code(access_code.ToStdString());
} }
} }
}); });
+17 -5
View File
@@ -1382,8 +1382,8 @@ void MainFrame::show_device(bool should_use_native) {
const bool use_printer_agents = wxGetApp().app_config->get_bool("use_printer_agents"); const bool use_printer_agents = wxGetApp().app_config->get_bool("use_printer_agents");
// The legacy page is appended when printer agents are enabled. Remove that // The web page is appended when printer agents are enabled. Remove that
// extra page before switching back to the normal native/legacy layout. // extra page before switching back to the normal native/Web layout.
if (!use_printer_agents) { if (!use_printer_agents) {
if ((idx = m_tabpanel->FindPage(m_printer_view)) != wxNOT_FOUND && idx != m_tabpanel->FindPageByName(TAB_ID_MONITOR)) { if ((idx = m_tabpanel->FindPage(m_printer_view)) != wxNOT_FOUND && idx != m_tabpanel->FindPageByName(TAB_ID_MONITOR)) {
m_printer_view->Show(false); m_printer_view->Show(false);
@@ -1449,7 +1449,7 @@ void MainFrame::show_device(bool should_use_native) {
m_printer_view->Show(false); m_printer_view->Show(false);
m_tabpanel->AddPage(m_printer_view, _L("Device (legacy)"), false, Notebook::PAGE_MONITOR); m_tabpanel->AddPage(m_printer_view, _L("Device (legacy)"), false, Notebook::PAGE_MONITOR);
} else { } else {
m_tabpanel->SetPageText(idx, _L("Device (legacy)")); m_tabpanel->SetPageText(idx, _L("Device (Web)"));
} }
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
@@ -4366,14 +4366,26 @@ void MainFrame::load_printer_url(wxString url, wxString apikey)
void MainFrame::load_printer_url() void MainFrame::load_printer_url()
{ {
PresetBundle &preset_bundle = *wxGetApp().preset_bundle; PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
if (preset_bundle.use_bbl_device_tab() || wxGetApp().app_config->get_bool("use_printer_agents")) if (preset_bundle.use_bbl_device_tab() && !wxGetApp().app_config->get_bool("use_printer_agents"))
return; return;
auto cfg = preset_bundle.printers.get_edited_preset().config; auto cfg = preset_bundle.printers.get_edited_preset().config;
if (cfg.opt_string("print_host").empty()) {
if (auto *device_manager = wxGetApp().getDeviceManager()) {
auto *machine = device_manager->get_selected_machine();
if (!machine) {
auto machines = device_manager->get_my_machine_list();
if (machines.size() == 1)
machine = machines.begin()->second;
}
if (machine && !machine->get_dev_ip().empty())
cfg.opt_string("print_host") = machine->get_dev_ip();
}
}
wxString url = from_u8(PrintHost::get_print_host_webui(&cfg)); wxString url = from_u8(PrintHost::get_print_host_webui(&cfg));
wxString apikey; wxString apikey;
const auto host_type = cfg.option<ConfigOptionEnum<PrintHostType>>("host_type")->value; const auto host_type = cfg.option<ConfigOptionEnum<PrintHostType>>("host_type")->value;
if (cfg.has("printhost_apikey") && (host_type == htPrusaLink || host_type == htPrusaConnect)) if (cfg.has("printhost_apikey") && host_type != htSimplyPrint)
apikey = cfg.opt_string("printhost_apikey"); apikey = cfg.opt_string("printhost_apikey");
if (!url.empty()) { if (!url.empty()) {
load_printer_url(url, apikey); load_printer_url(url, apikey);
+4 -2
View File
@@ -3287,7 +3287,9 @@ void Sidebar::update_all_preset_comboboxes()
: MainFrame::PrintSelectType::eSendGcode; : MainFrame::PrintSelectType::eSendGcode;
} }
if (!use_native_device_tab || use_printer_agents) if (use_printer_agents)
p_mainframe->load_printer_url();
else if (!use_native_device_tab)
p_mainframe->load_printer_url(url, apikey); p_mainframe->load_printer_url(url, apikey);
@@ -11245,7 +11247,7 @@ void Plater::priv::on_tab_selection_changing(wxBookCtrlEvent& e)
} else { } else {
if (new_sel == main_frame->m_tabpanel->FindPageByName(TAB_ID_MONITOR) && wxGetApp().preset_bundle != nullptr) { if (new_sel == main_frame->m_tabpanel->FindPageByName(TAB_ID_MONITOR) && wxGetApp().preset_bundle != nullptr) {
auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config; auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
wxString url = cfg.opt_string("print_host_webui").empty() ? cfg.opt_string("print_host") : cfg.opt_string("print_host_webui"); wxString url = from_u8(PrintHost::get_print_host_webui(&cfg));
if (main_frame->m_printer_view && url.empty()) { if (main_frame->m_printer_view && url.empty()) {
// It's missing_connection page, reload so that we can replay the gif image // It's missing_connection page, reload so that we can replay the gif image
main_frame->m_printer_view->reload(); main_frame->m_printer_view->reload();
+7 -2
View File
@@ -1991,7 +1991,7 @@ void InputIpAddressDialog::workerThreadFunc(std::string str_ip, std::string str_
if (w.expired()) return; if (w.expired()) return;
if (m_obj) { if (m_obj) {
m_obj->set_user_access_code(str_access_code); m_obj->set_access_code(str_access_code);
wxGetApp().getDeviceManager()->set_selected_machine(m_obj->get_dev_id()); wxGetApp().getDeviceManager()->set_selected_machine(m_obj->get_dev_id());
} }
@@ -2055,6 +2055,11 @@ void InputIpAddressDialog::on_text(wxCommandEvent &evt)
{ {
auto str_ip = m_input_ip->GetTextCtrl()->GetValue(); auto str_ip = m_input_ip->GetTextCtrl()->GetValue();
auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue(); auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
if (str_access_code.empty()) {
str_access_code = "88888888";
}
auto str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both); auto str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both);
auto str_sn = m_input_sn->GetTextCtrl()->GetValue().Strip(wxString::both); auto str_sn = m_input_sn->GetTextCtrl()->GetValue().Strip(wxString::both);
bool invalid_access_code = true; bool invalid_access_code = true;
@@ -2062,7 +2067,7 @@ void InputIpAddressDialog::on_text(wxCommandEvent &evt)
for (char c : str_access_code) { for (char c : str_access_code) {
if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) { if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) {
invalid_access_code = false; invalid_access_code = false;
return; break;
} }
} }
-1
View File
@@ -704,7 +704,6 @@ void SelectMachinePopup::update_user_devices()
} }
mobj->set_access_code(""); mobj->set_access_code("");
mobj->erase_user_access_code();
} }
if (GUI::wxGetApp().plater()) if (GUI::wxGetApp().plater())
@@ -1359,7 +1359,6 @@ void MoonrakerPrinterAgent::announce_printhost_device()
if (auto* app_config = GUI::wxGetApp().app_config) { if (auto* app_config = GUI::wxGetApp().app_config) {
const std::string access_code = device_info.api_key.empty() ? "88888888" : device_info.api_key; const std::string access_code = device_info.api_key.empty() ? "88888888" : device_info.api_key;
app_config->set_str("access_code", device_info.dev_id, access_code); app_config->set_str("access_code", device_info.dev_id, access_code);
app_config->set_str("user_access_code", device_info.dev_id, access_code);
} }
nlohmann::json payload; nlohmann::json payload;
+50
View File
@@ -235,6 +235,56 @@ SCENARIO("Config ini load/save interface", "[Config]") {
} }
} }
TEST_CASE("Flush-volume warning predicate respects used filament transitions", "[Config][Regression]")
{
const std::vector<double> multipliers = {1.0};
SECTION("Single used filament does not trigger warning with zero transition entries")
{
const std::vector<double> matrix = {
0.0, 0.0,
0.0, 0.0
};
const std::vector<int> used_filaments = {1};
REQUIRE_FALSE(has_zero_flush_volume_for_used_filaments(matrix, multipliers, used_filaments));
}
SECTION("Two used filaments trigger warning when transition flush entry is zero")
{
const std::vector<double> matrix = {
0.0, 0.0,
0.0, 0.0
};
const std::vector<int> used_filaments = {1, 2};
REQUIRE(has_zero_flush_volume_for_used_filaments(matrix, multipliers, used_filaments));
}
SECTION("Two used filaments do not trigger warning when transitions are non-zero")
{
const std::vector<double> matrix = {
0.0, 280.0,
280.0, 0.0
};
const std::vector<int> used_filaments = {1, 2};
REQUIRE_FALSE(has_zero_flush_volume_for_used_filaments(matrix, multipliers, used_filaments));
}
SECTION("Zero multiplier still triggers warning when multiple filaments are used")
{
const std::vector<double> matrix = {
0.0, 280.0,
280.0, 0.0
};
const std::vector<double> zero_multiplier = {0.0};
const std::vector<int> used_filaments = {1, 2};
REQUIRE(has_zero_flush_volume_for_used_filaments(matrix, zero_multiplier, used_filaments));
}
}
// TODO: https://github.com/SoftFever/OrcaSlicer/issues/11269 - Is this test still relevant? Delete if not. // TODO: https://github.com/SoftFever/OrcaSlicer/issues/11269 - Is this test still relevant? Delete if not.
// It was failing so at least "nozzle_type" and "extruder_printable_area" could not be serialized // It was failing so at least "nozzle_type" and "extruder_printable_area" could not be serialized
// and an exception was thrown, but "nozzle_type" has been around for at least 3 months now. // and an exception was thrown, but "nozzle_type" has been around for at least 3 months now.