mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-11 01:41:03 +00:00
Sync upstream main
124 upstream commits including CrealityPrint integration (added include in Plater.cpp alongside the existing IMEXHelpers include), profile fixes and version bumps (#14084, #14085, Polymaker), CI artifact publishing, test refactors (arachne walls test added; test_3mf/test_config/ test_gcodewriter content moved/removed upstream — IMEX test file preserved as it is feedback-only), translations.
This commit is contained in:
+106
-62
@@ -3286,18 +3286,24 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
if (is_bbl_printers) {
|
||||
this->_print_first_layer_extruder_temperatures(file, print, machine_start_gcode, initial_extruder_id, true);
|
||||
}
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest during_print_exhaust_fan_speed
|
||||
bool activate_air_filtration_during_print = false;
|
||||
int during_print_exhaust_fan_speed = 0;
|
||||
for (const auto &extruder : m_writer.extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_during_print.get_at(extruder.id())) {
|
||||
activate_air_filtration_during_print = true;
|
||||
during_print_exhaust_fan_speed = std::max(during_print_exhaust_fan_speed,
|
||||
m_config.during_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
|
||||
// Orca: when air filtration is supported, check if it needs to be activated during printing and set the exhaust fan speed accordingly
|
||||
if (m_config.support_air_filtration.value) {
|
||||
bool activate_air_filtration_during_print = false;
|
||||
int during_print_exhaust_fan_speed = 0;
|
||||
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest during_print_exhaust_fan_speed
|
||||
for (const auto &extruder : m_writer.extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_during_print.get_at(extruder.id())) {
|
||||
activate_air_filtration_during_print = true;
|
||||
during_print_exhaust_fan_speed = std::max(during_print_exhaust_fan_speed,
|
||||
m_config.during_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
}
|
||||
}
|
||||
|
||||
if (activate_air_filtration_during_print)
|
||||
file.write(m_writer.set_exhaust_fan(during_print_exhaust_fan_speed));
|
||||
}
|
||||
if (activate_air_filtration_during_print)
|
||||
file.write(m_writer.set_exhaust_fan(during_print_exhaust_fan_speed, true));
|
||||
|
||||
print.throw_if_canceled();
|
||||
|
||||
@@ -3619,16 +3625,23 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
if (activate_chamber_temp_control && max_chamber_temp > 0)
|
||||
file.write(m_writer.set_chamber_temperature(0, false)); //close chamber_temperature
|
||||
|
||||
bool activate_air_filtration_on_completion = false;
|
||||
int complete_print_exhaust_fan_speed = 0;
|
||||
for (const auto& extruder : m_writer.extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_on_completion.get_at(extruder.id())) {
|
||||
activate_air_filtration_on_completion = true;
|
||||
complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
// Orca: when air filtration is supported, check if it needs to be activated after print completion and set the exhaust fan speed accordingly
|
||||
if (m_config.support_air_filtration.value) {
|
||||
bool activate_air_filtration_on_completion = false;
|
||||
int complete_print_exhaust_fan_speed = 0;
|
||||
|
||||
// Orca: when activate_air_filtration is set on any extruder, find and set the highest complete_print_exhaust_fan_speed
|
||||
for (const auto& extruder : m_writer.extruders()) {
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_on_completion.get_at(extruder.id())) {
|
||||
activate_air_filtration_on_completion = true;
|
||||
complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
}
|
||||
}
|
||||
|
||||
if (activate_air_filtration_on_completion)
|
||||
file.write(m_writer.set_exhaust_fan(complete_print_exhaust_fan_speed));
|
||||
}
|
||||
if (activate_air_filtration_on_completion)
|
||||
file.write(m_writer.set_exhaust_fan(complete_print_exhaust_fan_speed, true));
|
||||
|
||||
// adds tags for time estimators
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str());
|
||||
file.write_format("; EXECUTABLE_BLOCK_END\n\n");
|
||||
@@ -4928,6 +4941,7 @@ LayerResult GCode::process_layer(
|
||||
|
||||
// Group extrusions by an extruder, then by an object, an island and a region.
|
||||
std::map<unsigned int, std::vector<ObjectByExtruder>> by_extruder;
|
||||
std::vector<std::unique_ptr<ExtrusionEntityCollection>> split_perimeter_storage;
|
||||
bool is_anything_overridden = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden();
|
||||
for (const LayerToPrint &layer_to_print : layers) {
|
||||
if (layer_to_print.support_layer != nullptr) {
|
||||
@@ -5083,55 +5097,83 @@ LayerResult GCode::process_layer(
|
||||
if (extrusions->entities.empty()) // This shouldn't happen but first_point() would fail.
|
||||
continue;
|
||||
|
||||
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
|
||||
int correct_extruder_id = layer_tools.extruder(*extrusions, region);
|
||||
auto process_extrusions = [&](const ExtrusionEntityCollection *current_extrusions,
|
||||
const ExtrusionEntityCollection *overrides_key,
|
||||
bool use_overrides) {
|
||||
// This extrusion is part of certain Region, which tells us which extruder should be used for it.
|
||||
int correct_extruder_id = layer_tools.extruder(*current_extrusions, region);
|
||||
|
||||
// Let's recover vector of extruder overrides:
|
||||
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
|
||||
if (! layer_tools.has_extruder(correct_extruder_id)) {
|
||||
// this entity is not overridden, but its extruder is not in layer_tools - we'll print it
|
||||
// by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
|
||||
correct_extruder_id = layer_tools.extruders.back();
|
||||
}
|
||||
printing_extruders.clear();
|
||||
if (is_anything_overridden) {
|
||||
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(extrusions, layer_to_print.original_object, correct_extruder_id, layer_to_print.object()->instances().size());
|
||||
if (entity_overrides == nullptr) {
|
||||
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
|
||||
if (! layer_tools.has_extruder(correct_extruder_id)) {
|
||||
// this entity is not overridden, but its extruder is not in layer_tools - we'll print it
|
||||
// by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
|
||||
correct_extruder_id = layer_tools.extruders.back();
|
||||
}
|
||||
printing_extruders.clear();
|
||||
if (is_anything_overridden && use_overrides) {
|
||||
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(overrides_key, layer_to_print.original_object, correct_extruder_id, layer_to_print.object()->instances().size());
|
||||
if (entity_overrides == nullptr) {
|
||||
printing_extruders.emplace_back(correct_extruder_id);
|
||||
} else {
|
||||
printing_extruders.reserve(entity_overrides->size());
|
||||
for (int extruder : *entity_overrides)
|
||||
printing_extruders.emplace_back(extruder >= 0 ?
|
||||
// at least one copy is overridden to use this extruder
|
||||
extruder :
|
||||
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
||||
static_cast<unsigned int>(- extruder - 1));
|
||||
Slic3r::sort_remove_duplicates(printing_extruders);
|
||||
}
|
||||
} else {
|
||||
printing_extruders.emplace_back(correct_extruder_id);
|
||||
} else {
|
||||
printing_extruders.reserve(entity_overrides->size());
|
||||
for (int extruder : *entity_overrides)
|
||||
printing_extruders.emplace_back(extruder >= 0 ?
|
||||
// at least one copy is overridden to use this extruder
|
||||
extruder :
|
||||
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
||||
static_cast<unsigned int>(- extruder - 1));
|
||||
Slic3r::sort_remove_duplicates(printing_extruders);
|
||||
}
|
||||
} else
|
||||
printing_extruders.emplace_back(correct_extruder_id);
|
||||
|
||||
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
|
||||
for (unsigned int extruder : printing_extruders)
|
||||
{
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||
by_extruder,
|
||||
extruder,
|
||||
&layer_to_print - layers.data(),
|
||||
layers.size(), n_slices+1);
|
||||
for (size_t i = 0; i <= n_slices; ++ i) {
|
||||
bool last = i == n_slices;
|
||||
size_t island_idx = last ? n_slices : slices_test_order[i];
|
||||
if (// extrusions->first_point does not fit inside any slice
|
||||
last ||
|
||||
// extrusions->first_point fits inside ith slice
|
||||
point_inside_surface(island_idx, extrusions->first_point())) {
|
||||
if (islands[island_idx].by_region.empty())
|
||||
islands[island_idx].by_region.assign(print.num_print_regions(), ObjectByExtruder::Island::Region());
|
||||
islands[island_idx].by_region[region.print_region_id()].append(entity_type, extrusions, entity_overrides);
|
||||
break;
|
||||
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it.
|
||||
for (unsigned int extruder : printing_extruders) {
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||
by_extruder,
|
||||
extruder,
|
||||
&layer_to_print - layers.data(),
|
||||
layers.size(), n_slices + 1);
|
||||
for (size_t i = 0; i <= n_slices; ++i) {
|
||||
bool last = i == n_slices;
|
||||
size_t island_idx = last ? n_slices : slices_test_order[i];
|
||||
if (last || point_inside_surface(island_idx, current_extrusions->first_point())) {
|
||||
if (islands[island_idx].by_region.empty())
|
||||
islands[island_idx].by_region.assign(print.num_print_regions(), ObjectByExtruder::Island::Region());
|
||||
islands[island_idx].by_region[region.print_region_id()].append(entity_type, current_extrusions, entity_overrides);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool split_mixed_perimeters =
|
||||
entity_type == ObjectByExtruder::Island::Region::PERIMETERS &&
|
||||
region.config().outer_wall_filament_id.value != region.config().inner_wall_filament_id.value &&
|
||||
extrusions->role() == erMixed;
|
||||
|
||||
if (split_mixed_perimeters) {
|
||||
auto outer_perimeters = std::make_unique<ExtrusionEntityCollection>();
|
||||
auto inner_perimeters = std::make_unique<ExtrusionEntityCollection>();
|
||||
for (const ExtrusionEntity *entity : extrusions->entities) {
|
||||
const ExtrusionRole role = entity->role();
|
||||
if (role == erExternalPerimeter || role == erOverhangPerimeter)
|
||||
outer_perimeters->append(*entity);
|
||||
else if (role == erPerimeter)
|
||||
inner_perimeters->append(*entity);
|
||||
}
|
||||
|
||||
if (!outer_perimeters->entities.empty()) {
|
||||
split_perimeter_storage.emplace_back(std::move(outer_perimeters));
|
||||
process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
|
||||
}
|
||||
if (!inner_perimeters->entities.empty()) {
|
||||
split_perimeter_storage.emplace_back(std::move(inner_perimeters));
|
||||
process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
|
||||
}
|
||||
} else {
|
||||
process_extrusions(extrusions, extrusions, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6327,7 +6369,9 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
||||
if (extrusions.empty())
|
||||
return gcode;
|
||||
|
||||
chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point());
|
||||
//ORCA: Respect no_sort to preserve support base outline->fill order.
|
||||
if (!support_fills.no_sort)
|
||||
chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point());
|
||||
|
||||
const double support_speed = m_config.support_speed.value;
|
||||
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
||||
|
||||
Reference in New Issue
Block a user