From 59ad126b48f02e6f4d3e4a6d0f41d93f16e3ac44 Mon Sep 17 00:00:00 2001 From: Ian Bassi Date: Sun, 14 Dec 2025 02:20:14 -0300 Subject: [PATCH] Fix: Replace with STL to Replace with 3D file: Support STEP (#11637) * Replace with STL to Replace with 3D file: Support STEP Enhanced the replace logic to support STEP (.stp, .step) files, including user-configurable mesh settings and dialog, while maintaining backward compatibility with STL and other formats. Updated the menu label and tooltips to 'Replace 3D file' for clarity. * Update 'STL' references to '3D file' in UI and logs Replaces user-facing text and log messages referring to 'STL' with '3D file' for broader file type support and improved clarity in the menu, status messages, and logging. * Merge branch 'main' into remplace-with-stl --- src/slic3r/GUI/GUI_Factories.cpp | 4 ++-- src/slic3r/GUI/Plater.cpp | 39 ++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index a5e09271c6..0148f695aa 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -870,14 +870,14 @@ void MenuFactory::append_menu_item_reload_from_disk(wxMenu* menu) void MenuFactory::append_menu_item_replace_with_stl(wxMenu *menu) { - append_menu_item(menu, wxID_ANY, _L("Replace with STL") + dots, _L("Replace the selected part with new STL"), + append_menu_item(menu, wxID_ANY, _L("Replace 3D file") + dots, _L("Replace the selected part with a new 3D file"), [](wxCommandEvent &) { plater()->replace_with_stl(); }, "", menu, []() { return plater()->can_replace_with_stl(); }, m_parent); } void MenuFactory::append_menu_item_replace_all_with_stl(wxMenu *menu) { - append_menu_item(menu, wxID_ANY, _L("Replace all with STL") + dots, _L("Replace all selected parts with STL from folder"), + append_menu_item(menu, wxID_ANY, _L("Replace all with 3D files") + dots, _L("Replace all selected parts with 3D files from folder"), [](wxCommandEvent &) { plater()->replace_all_with_stl(); }, "", menu, []() { return plater()->can_replace_all_with_stl(); }, m_parent); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 855788f1ff..1d5c6f508a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -7766,7 +7766,38 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const Model new_model; try { - new_model = Model::read_from_file(path, nullptr, nullptr, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel); + const bool is_step = boost::algorithm::iends_with(path, ".stp") || boost::algorithm::iends_with(path, ".step"); + if (is_step) { + auto config = wxGetApp().app_config; + double linear = std::max(0.003, string_to_double_decimal_point(config->get("linear_defletion"))); + double angle = std::max(0.5, string_to_double_decimal_point(config->get("angle_defletion"))); + bool split_compound = config->get_bool("is_split_compound"); + bool is_user_cancel = false; + + auto callback = [&is_user_cancel, linear, angle, split_compound](Slic3r::Step &file, double &linear_value, double &angle_value, bool &is_split) -> int { + if (wxGetApp().app_config->get_bool("enable_step_mesh_setting")) { + StepMeshDialog mesh_dlg(nullptr, file, linear, angle); + if (mesh_dlg.ShowModal() == wxID_OK) { + linear_value = mesh_dlg.get_linear_defletion(); + angle_value = mesh_dlg.get_angle_defletion(); + is_split = mesh_dlg.get_split_compound_value(); + return 1; + } + } else { + linear_value = linear; + angle_value = angle; + is_split = split_compound; + return 1; + } + is_user_cancel = true; + return -1; + }; + + new_model = Model::read_from_step(path, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel, nullptr, nullptr, callback, linear, angle, split_compound); + if (is_user_cancel) return false; + } else { + new_model = Model::read_from_file(path, nullptr, nullptr, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel); + } for (ModelObject* model_object : new_model.objects) { model_object->center_around_origin(); model_object->ensure_on_bed(); @@ -7865,7 +7896,7 @@ void Plater::priv::replace_with_stl() return; } - if (!replace_volume_with_stl(object_idx, volume_idx, out_path, "Replace with STL")) + if (!replace_volume_with_stl(object_idx, volume_idx, out_path, "Replace with 3D file")) return; // update 3D scene @@ -7949,7 +7980,7 @@ void Plater::priv::replace_all_with_stl() return; } - std::string status = _L("Replaced with STLs from directory:\n").ToStdString() + out_path.string() + "\n\n"; + std::string status = _L("Replaced with 3D files from directory:\n").ToStdString() + out_path.string() + "\n\n"; for (unsigned int idx : volume_idxs) { const GLVolume* v = selection.get_volume(idx); @@ -7982,7 +8013,7 @@ void Plater::priv::replace_all_with_stl() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " replacing volume : " << input_path << " with " << new_path; - if (!replace_volume_with_stl(object_idx, volume_idx, new_path, "Replace with STL")) { + if (!replace_volume_with_stl(object_idx, volume_idx, new_path, "Replace with 3D file")) { status += boost::str(boost::format(_L("✖ Skipped %1%: failed to replace.\n").ToStdString()) % volume_name); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " cannot replace volume : failed to replace with " << new_path; continue;