mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-12 03:27:55 +00:00
Merge branch 'main' into feature/protobuf_config_and_dynamic_ui
This commit is contained in:
@@ -138,7 +138,8 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object
|
|||||||
{
|
{
|
||||||
double max_layer_height = std::numeric_limits<double>::max();
|
double max_layer_height = std::numeric_limits<double>::max();
|
||||||
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
||||||
double mlh = config.max_layer_height.values[i];
|
// max_layer_height may be shorter than the extruder count; get_at() clamps.
|
||||||
|
double mlh = config.max_layer_height.get_at(i);
|
||||||
if (mlh == 0.)
|
if (mlh == 0.)
|
||||||
mlh = 0.75 * config.nozzle_diameter.values[i];
|
mlh = 0.75 * config.nozzle_diameter.values[i];
|
||||||
max_layer_height = std::min(max_layer_height, mlh);
|
max_layer_height = std::min(max_layer_height, mlh);
|
||||||
|
|||||||
@@ -946,7 +946,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
|||||||
toggle_line("wipe_tower_extra_rib_length", have_rib_wall);
|
toggle_line("wipe_tower_extra_rib_length", have_rib_wall);
|
||||||
toggle_line("wipe_tower_rib_width", have_rib_wall);
|
toggle_line("wipe_tower_rib_width", have_rib_wall);
|
||||||
toggle_line("wipe_tower_fillet_wall", have_rib_wall);
|
toggle_line("wipe_tower_fillet_wall", have_rib_wall);
|
||||||
toggle_field("prime_tower_width", have_prime_tower && (supports_wipe_tower_2 || have_rib_wall));
|
toggle_field("prime_tower_width", have_prime_tower && !have_rib_wall);
|
||||||
|
|
||||||
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && supports_wipe_tower_2);
|
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && supports_wipe_tower_2);
|
||||||
|
|
||||||
|
|||||||
@@ -6965,6 +6965,10 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
|||||||
// finishFn tears down the progress dialog (and clears the re-entrancy guard), so it
|
// finishFn tears down the progress dialog (and clears the re-entrancy guard), so it
|
||||||
// must run on every exit path — otherwise an early bail-out would leak the modal
|
// must run on every exit path — otherwise an early bail-out would leak the modal
|
||||||
// dialog and leave the guard stuck, blocking all later manual syncs.
|
// dialog and leave the guard stuck, blocking all later manual syncs.
|
||||||
|
// Guard the whole thread body: an uncaught exception here (e.g. a transient
|
||||||
|
// boost::filesystem error while scanning the preset folder) would otherwise
|
||||||
|
// propagate out of the thread and terminate the entire application.
|
||||||
|
try {
|
||||||
if (!m_agent) { finishFn(false); return; }
|
if (!m_agent) { finishFn(false); return; }
|
||||||
|
|
||||||
// One-time scan for orphaned .info files left over from offline deletions; queues HTTP DELETEs.
|
// One-time scan for orphaned .info files left over from offline deletions; queues HTTP DELETEs.
|
||||||
@@ -7206,6 +7210,11 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
|||||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by exception: " << e.what();
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by unknown exception";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8526,8 +8535,13 @@ void GUI_App::scan_orphaned_info_files()
|
|||||||
if (!fs::exists(type_dir))
|
if (!fs::exists(type_dir))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Iterate through all .info files
|
// Iterate through all .info files. Use the error_code-based iterator so a transient
|
||||||
for (auto& entry : boost::filesystem::directory_iterator(type_dir)) {
|
// directory-read failure (e.g. macOS readdir returning ENOTSUP) is logged and skipped
|
||||||
|
// instead of throwing an uncaught exception that would terminate the app from the
|
||||||
|
// background sync thread this runs on.
|
||||||
|
boost::system::error_code ec;
|
||||||
|
for (boost::filesystem::directory_iterator it(type_dir, ec), end; !ec && it != end; it.increment(ec)) {
|
||||||
|
const auto& entry = *it;
|
||||||
if (entry.path().extension() != ".info")
|
if (entry.path().extension() != ".info")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -8546,6 +8560,8 @@ void GUI_App::scan_orphaned_info_files()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ec)
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "scan_orphaned_info_files: failed to scan " << type_dir.string() << ": " << ec.message();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,3 +85,22 @@ TEST_CASE("Per-object wall filament override is honored", "[MultiFilament]")
|
|||||||
CHECK(tools_for_role(gcode, "perimeter") == std::set<int>{ 0, 1 });
|
CHECK(tools_for_role(gcode, "perimeter") == std::set<int>{ 0, 1 });
|
||||||
CHECK(tools_for_role(gcode, "infill") == std::set<int>{ 0 }); // infill not overridden: stays on F1
|
CHECK(tools_for_role(gcode, "infill") == std::set<int>{ 0 }); // infill not overridden: stays on F1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// max_layer_height can be shorter than the extruder count (normalization sizes it to the
|
||||||
|
// filament count under single_extruder_multi_material). calc_max_layer_height() in ToolOrdering
|
||||||
|
// indexed it per-nozzle and read past the end. Shortened directly here to isolate that read;
|
||||||
|
// the other per-extruder keys stay extruder-length so slicing reaches the code under test.
|
||||||
|
TEST_CASE("Multi-extruder slice stays in bounds with a short max_layer_height", "[MultiFilament]")
|
||||||
|
{
|
||||||
|
DynamicPrintConfig config = multifilament_config(2);
|
||||||
|
config.set_deserialize_strict({
|
||||||
|
{ "nozzle_diameter", "0.4,0.4" },
|
||||||
|
{ "printer_extruder_id", "1,2" },
|
||||||
|
{ "printer_extruder_variant", "Direct Drive Standard,Direct Drive Standard" },
|
||||||
|
{ "extruder_printable_height", "0,0" },
|
||||||
|
{ "max_layer_height", "0.3" }, // deliberately one entry short
|
||||||
|
});
|
||||||
|
Print print;
|
||||||
|
init_and_process_print({ cube(20) }, print, config);
|
||||||
|
REQUIRE_FALSE(print.objects().front()->layers().empty());
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user