Merge remote-tracking branch 'upstream/main' into feedback

This commit is contained in:
Clifford Garwood committed 2026-05-01 01:30:40 -04:00
commit b452a8a28f
1033 files changed
+24477 -1712

No files matched your search

+149 -43
View File
@@ -5110,7 +5110,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->q->set_prepare_state(Job::PREPARE_STATE_MENU);
this->q->orient(); });
//BBS
view3D_canvas->Bind(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL, [this](SimpleEvent&) {this->q->select_curr_plate_all(); });
view3D_canvas->Bind(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL, [this](SimpleEvent&) {this->q->select_curr_plate_all(); });
view3D_canvas->Bind(EVT_GLCANVAS_PRINTABLE, [this](SimpleEvent& evt) { this->sidebar->obj_list()->toggle_printable_state(); });
view3D_canvas->Bind(EVT_GLCANVAS_SELECT_ALL, [this](SimpleEvent&) { this->q->select_all(); });
view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
@@ -5995,11 +5996,24 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
// BBS: version check
Semver app_version = *(Semver::parse(SoftFever_VERSION));
const wxString load_3mf_title = _L("Load 3MF");
const wxString newer_3mf_title = _L("Newer 3MF version");
const wxString bambu_project_title = _L("BambuStudio Project");
const wxString msg_unsupported_geometry = _L("The 3MF is not supported by OrcaSlicer, loading geometry data only.");
const wxString msg_old_orca_geometry = _L("The 3MF file was generated by an old OrcaSlicer version, loading geometry data only.");
const wxString msg_older_geometry = _L("The 3MF file was generated by an older version, loading geometry data only.");
const wxString msg_bambu_geometry = _L("The 3MF file was generated by BambuStudio, loading geometry data only.");
auto log_and_show_3mf_info = [&](const wxString& text, const wxString& title) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
<< " "
<< boost::format("3MF import message [%1%]: %2% | file: %3%") % into_u8(title) % into_u8(text) % path.string();
show_info(q, text, title);
};
if (en_3mf_file_type == En3mfType::From_Prusa) {
// do not reset the model config
load_config = false;
if(load_type != LoadType::LoadGeometry)
show_info(q, _L("The 3MF is not supported by OrcaSlicer, loading geometry data only."), _L("Load 3MF"));
if (load_type != LoadType::LoadGeometry)
log_and_show_3mf_info(msg_unsupported_geometry, load_3mf_title);
}
else if (en_3mf_file_type == En3mfType::From_Orca) {
// OrcaSlicer file (has OrcaSlicer tag) - compare file_version with SoftFever_VERSION
@@ -6035,7 +6049,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
wxString append = _L("You'd better upgrade your software.\n");
context += "\n\n";
context += append;
show_info(q, context, _L("Newer 3MF version"));
log_and_show_3mf_info(context, newer_3mf_title);
}
else {
//if the minor version is not matched
@@ -6043,13 +6057,13 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
wxString text = wxString::Format(_L("The 3MF file version %s is newer than %s's version %s, we suggest to upgrade your software."),
file_version.to_string_sf(), std::string(SLIC3R_APP_FULL_NAME), app_version.to_string_sf());
text += "\n";
show_info(q, text, _L("Newer 3MF version"));
log_and_show_3mf_info(text, newer_3mf_title);
}
}
}
else if (load_config && config_loaded.empty()) {
load_config = false;
show_info(q, _L("The 3MF file was generated by an old OrcaSlicer version, loading geometry data only."), _L("Load 3MF"));
log_and_show_3mf_info(msg_old_orca_geometry, load_3mf_title);
}
}
else if (en_3mf_file_type == En3mfType::From_BBS) {
@@ -6084,7 +6098,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
else if (load_config && config_loaded.empty()) {
load_config = false;
show_info(q, _L("The 3MF file was generated by an older version, loading geometry data only."), _L("Load 3MF"));
log_and_show_3mf_info(msg_older_geometry, load_3mf_title);
}
} else {
// BambuStudio project (version > 2.3.2 without OrcaSlicer tag)
@@ -6092,7 +6106,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
Semver slic3r_version = *(Semver::parse(SLIC3R_VERSION));
if (load_config && config_loaded.empty()) {
load_config = false;
show_info(q, _L("The 3MF file was generated by BambuStudio, loading geometry data only."), _L("Load 3MF"));
log_and_show_3mf_info(msg_bambu_geometry, load_3mf_title);
}
else if (load_config && (file_version > slic3r_version)) {
// BambuStudio file version is newer than our compatible SLIC3R_VERSION
@@ -6104,23 +6118,32 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
wxString append = _L("You'd better upgrade your software.\n");
context += "\n\n";
context += append;
show_info(q, context, _L("BambuStudio Project"));
log_and_show_3mf_info(context, bambu_project_title);
} else {
wxString text = wxString::Format(_L("The 3MF was created by BambuStudio (version %s), which is newer than the compatible version %s. Some settings may not be fully compatible."),
file_version.to_string(), slic3r_version.to_string());
text += "\n";
show_info(q, text, _L("BambuStudio Project"));
log_and_show_3mf_info(text, bambu_project_title);
}
} else if (load_config) {
// BambuStudio version is older or same as our SLIC3R_VERSION
wxString text = _L("The 3MF was created by BambuStudio. Some settings may differ from OrcaSlicer.");
show_info(q, text, _L("BambuStudio Project"));
log_and_show_3mf_info(text, bambu_project_title);
}
}
}
else if (en_3mf_file_type == En3mfType::From_Other) {
// Generic CAD/other 3MF without slicer metadata: import geometry silently.
if (load_config && config_loaded.empty()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
<< " "
<< boost::format("3MF has no slicer metadata/project config, importing geometry only: %1%") % path.string();
load_config = false;
}
}
else if (load_config && config_loaded.empty()) {
load_config = false;
show_info(q, _L("The 3MF file was generated by an old OrcaSlicer version, loading geometry data only."), _L("Load 3MF"));
log_and_show_3mf_info(msg_old_orca_geometry, load_3mf_title);
}
else if (!load_config) {
// reset config except color
@@ -6210,9 +6233,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
config += std::move(config_loaded);
std::map<std::string, std::string> validity = config.validate();
if (!validity.empty()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("Param values in 3mf error: ");
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("Param values in 3mf error: ");
for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("%1%: %2%")%it->first %it->second;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("%1%: %2%")%it->first %it->second;
//
NotificationManager *notify_manager = q->get_notification_manager();
std::string error_message = L("Invalid values found in the 3MF:");
@@ -6694,7 +6717,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
model_object->center_around_origin(false);
// BBS
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n");
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n");
wxString msg = wxString::Format("Loading file: %s", from_path(real_filename));
model_idx++;
dlg_cont = dlg.Update(progress_percent, msg);
@@ -7777,22 +7800,72 @@ void Plater::priv::process_validation_warning(StringObjectException const &warni
std::string text = warning.string;
auto po = dynamic_cast<PrintObjectBase const *>(warning.object);
auto mo = po ? po->model_object() : dynamic_cast<ModelObject const *>(warning.object);
auto action_fn = (mo || !warning.opt_key.empty()) ? [id = mo ? mo->id() : 0, opt = warning.opt_key](wxEvtHandler *) {
//ORCA: Update process_validation_warning to handle ModelInstance selection and include fallback
auto mi = dynamic_cast<ModelInstance const *>(warning.object);
auto action_fn = (mo || mi || !warning.opt_key.empty()) ? [id = mo ? mo->id() : (mi ? mi->id() : 0),
parent_id = mi ? mi->get_object()->id() : 0,
is_inst = (mi != nullptr),
opt = warning.opt_key](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
if (is_inst) {
bool selected = false;
auto iter = std::find_if(objects.begin(), objects.end(), [parent_id](auto o) { return o->id() == parent_id; });
if (iter != objects.end()) {
ModelObject* obj = *iter;
int inst_idx = -1;
for(size_t i=0; i<obj->instances.size(); ++i) {
if (obj->instances[i]->id() == id) {
inst_idx = i;
break;
}
}
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
if (inst_idx != -1) {
auto* model = wxGetApp().obj_list()->GetModel();
wxDataViewItem item;
wxDataViewItem objItem = model->GetObjectItem(obj);
if (objItem.IsOk()) {
int vm_obj_idx = model->GetIdByItem(objItem);
if (vm_obj_idx != -1) {
item = model->GetItemByInstanceId(vm_obj_idx, inst_idx);
}
}
if (item.IsOk()) {
wxDataViewItemArray sel_items;
sel_items.Add(item);
wxGetApp().obj_list()->select_items(sel_items);
wxGetApp().obj_list()->update_selections_on_canvas();
selected = true;
}
}
if (!selected) {
wxGetApp().obj_list()->select_items({ {obj, nullptr} });
wxGetApp().obj_list()->update_selections_on_canvas();
}
}
} else {
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
wxGetApp().obj_list()->update_selections_on_canvas();
}
}
if (!opt.empty()) {
if (iter != objects.end())
if ((!is_inst && id.id) || (is_inst && parent_id.id))
wxGetApp().params_panel()->switch_to_object();
wxGetApp().sidebar().jump_to_option(opt, Preset::TYPE_PRINT, L"");
}
return false;
} : std::function<bool(wxEvtHandler *)>();
auto hypertext = (mo || !warning.opt_key.empty()) ? _u8L("Jump to") : "";
auto hypertext = (mo || mi || !warning.opt_key.empty()) ? _u8L("Jump to") : "";
if (mo) hypertext += std::string(" [") + mo->name + "]";
if (mi) hypertext += std::string(" [") + mi->get_object()->name + "]";
if (!warning.opt_key.empty()) hypertext += std::string(" (") + warning.opt_key + ")";
// BBS disable support enforcer
@@ -12633,6 +12706,7 @@ void Plater::calib_pa(const Calib_Params& params)
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
print_config->set_key_value("overhang_reverse", new ConfigOptionBool(false));
print_config->set_key_value("precise_z_height", new ConfigOptionBool(false));
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
switch (params.mode) {
case CalibMode::Calib_PA_Line:
@@ -13141,6 +13215,10 @@ void Plater::calib_flowrate(bool is_linear, int pass, InfillPattern pattern) {
void Plater::calib_temp(const Calib_Params& params) {
constexpr double base_temp_tower_nozzle_diameter = 0.4;
constexpr double base_temp_tower_block_height = 10.0;
constexpr int base_temp_tower_temp_step = 5;
const auto calib_temp_name = wxString::Format(L"Nozzle temperature test");
new_project(false, false, calib_temp_name);
wxGetApp().mainframe->select_tab(size_t(MainFrame::tp3DEditor));
@@ -13151,18 +13229,61 @@ void Plater::calib_temp(const Calib_Params& params) {
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
auto start_temp = lround(params.start);
const ConfigOptionFloats* nozzle_diameter_config = printer_config->option<ConfigOptionFloats>("nozzle_diameter");
size_t nozzle_id = static_cast<size_t>(std::max(params.extruder_id, 0));
double nozzle_diameter = base_temp_tower_nozzle_diameter;
if (nozzle_diameter_config && !nozzle_diameter_config->values.empty()) {
nozzle_id = std::min(nozzle_id, nozzle_diameter_config->values.size() - 1);
nozzle_diameter = nozzle_diameter_config->values[nozzle_id];
}
if (nozzle_diameter <= 0.0)
nozzle_diameter = base_temp_tower_nozzle_diameter;
const double nozzle_scale = nozzle_diameter / base_temp_tower_nozzle_diameter;
const double block_height = base_temp_tower_block_height;
// cut upper
auto obj_bb = model().objects[0]->bounding_box_exact();
auto block_count = lround((500 - params.end) / base_temp_tower_temp_step + 1);
if (block_count > 0) {
// subtract EPSILON offset to avoid cutting at the exact location where the flat surface is
auto new_height = block_count * block_height - EPSILON;
if (new_height < obj_bb.size().z()) {
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepLower);
}
}
// cut bottom
obj_bb = model().objects[0]->bounding_box_exact();
block_count = lround((500 - params.start) / base_temp_tower_temp_step);
if (block_count > 0) {
auto new_height = block_count * block_height + EPSILON;
if (new_height < obj_bb.size().z()) {
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepUpper);
}
}
if (std::abs(nozzle_scale - 1.0) > EPSILON)
model().objects[0]->scale(nozzle_scale, nozzle_scale, nozzle_scale);
model().objects[0]->ensure_on_bed();
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
filament_config->set_key_value("nozzle_temperature_initial_layer", new ConfigOptionInts(1,(int)start_temp));
filament_config->set_key_value("nozzle_temperature", new ConfigOptionInts(1,(int)start_temp));
model().objects[0]->config.set_key_value("layer_height", new ConfigOptionFloat(nozzle_diameter/2));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(5.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
model().objects[0]->config.set_key_value("alternate_extra_wall", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("seam_slope_type", new ConfigOptionEnum<SeamScarfType>(SeamScarfType::None));
model().objects[0]->config.set_key_value("overhang_reverse", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("precise_z_height", new ConfigOptionBool(false));
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false));
print_config->set_key_value("initial_layer_print_height", new ConfigOptionFloat(nozzle_diameter/2));
changed_objects({ 0 });
wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty();
@@ -13170,27 +13291,6 @@ void Plater::calib_temp(const Calib_Params& params) {
wxGetApp().get_tab(Preset::TYPE_PRINT)->reload_config();
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->reload_config();
// cut upper
auto obj_bb = model().objects[0]->bounding_box_exact();
auto block_count = lround((500 - params.end) / 5 + 1);
if(block_count > 0){
// subtract EPSILON offset to avoid cutting at the exact location where the flat surface is
auto new_height = block_count * 10.0 - EPSILON;
if (new_height < obj_bb.size().z()) {
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepLower);
}
}
// cut bottom
obj_bb = model().objects[0]->bounding_box_exact();
block_count = lround((500 - params.start) / 5);
if(block_count > 0){
auto new_height = block_count * 10.0 + EPSILON;
if (new_height < obj_bb.size().z()) {
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepUpper);
}
}
p->background_process.fff_print()->set_calib_params(params);
}
@@ -13239,6 +13339,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params)
obj_cfg.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterAndInner));
obj_cfg.set_key_value("brim_width", new ConfigOptionFloat(5.0));
obj_cfg.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
obj_cfg.set_key_value("precise_z_height", new ConfigOptionBool(false));
print_config->set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
print_config->set_key_value("spiral_mode", new ConfigOptionBool(true));
print_config->set_key_value("max_volumetric_extrusion_rate_slope", new ConfigOptionFloat(0));
@@ -13311,6 +13412,7 @@ void Plater::calib_retraction(const Calib_Params& params)
obj->config.set_key_value("seam_position", new ConfigOptionEnum<SeamPosition>(spAligned));
obj->config.set_key_value("wall_sequence", new ConfigOptionEnum<WallSequence>(WallSequence::InnerOuter));
obj->config.set_key_value("overhang_reverse", new ConfigOptionBool(false));
obj->config.set_key_value("precise_z_height", new ConfigOptionBool(false));
changed_objects({ 0 });
@@ -13349,6 +13451,7 @@ void Plater::calib_VFA(const Calib_Params& params)
print_config->set_key_value("detect_thin_wall", new ConfigOptionBool(false));
print_config->set_key_value("spiral_mode", new ConfigOptionBool(true));
print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false));
print_config->set_key_value("precise_z_height", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
@@ -13416,6 +13519,7 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params)
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("precise_z_height", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
@@ -13476,6 +13580,7 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("precise_z_height", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
@@ -13538,6 +13643,7 @@ void Plater::Calib_Cornering(const Calib_Params& params)
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("precise_z_height", new ConfigOptionBool(false));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));