Merge branch 'main' into belt/baseChanges

This commit is contained in:
Joseph Robertson
2026-06-18 09:41:14 -05:00
committed by GitHub
210 changed files with 80490 additions and 187481 deletions
+79 -82
View File
@@ -244,7 +244,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"bed_temperature_formula",
"filament_notes",
"process_notes",
"printer_notes"
"printer_notes",
"use_3mf"
};
static std::unordered_set<std::string> steps_ignore;
@@ -700,13 +701,13 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
//juedge the exclude area
if (!intersection(exclude_polys, convex_hull_no_offset).empty()) {
if (single_object_exception.string.empty()) {
single_object_exception.string = (boost::format(L("%1% is too close to exclusion area, there may be collisions when printing.")) %instance.model_instance->get_object()->name).str();
single_object_exception.string = (boost::format(L("%1% is too close to exclusion area. There may be collisions when printing.")) %instance.model_instance->get_object()->name).str();
// single_object_exception.object = instance.model_instance->get_object();
//ORCA: Pass ModelInstance instead of ModelObject
single_object_exception.object = instance.model_instance;
}
else {
single_object_exception.string += "\n"+(boost::format(L("%1% is too close to exclusion area, there may be collisions when printing.")) %instance.model_instance->get_object()->name).str();
single_object_exception.string += "\n"+(boost::format(L("%1% is too close to exclusion area. There may be collisions when printing.")) %instance.model_instance->get_object()->name).str();
single_object_exception.object = nullptr;
}
//if (polygons) {
@@ -1069,7 +1070,7 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
/*if (warning) {
warning->string += L("Prime Tower is too close to exclusion area, there may be collisions when printing.\n");
}*/
return {L("Prime Tower") + L(" is too close to exclusion area, and collisions will be caused.\n")};
return {L("Prime Tower") + L(" is too close to an exclusion area, and collisions will be caused.\n")};
}
if (print_config.enable_wrapping_detection.value && !intersection({wrapping_poly}, convex_hulls_temp).empty()) {
return {L("Prime Tower") + L(" is too close to clumping detection area, and collisions will be caused.\n")};
@@ -1286,9 +1287,22 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
}
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
//BBS: refine seq-print validation logic.....FIXME:StringObjectException *warning can only contain one warning, but there might be many warnings, need a vector<StringObjectException>
StringObjectException Print::validate(StringObjectException *warning, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
//BBS: refine seq-print validation logic
StringObjectException Print::validate(std::vector<StringObjectException> *warnings, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
{
auto add_warning = [warnings](StringObjectException w) {
w.is_warning = true;
if (warnings != nullptr)
warnings->push_back(std::move(w));
};
auto warn = [&](std::string msg, std::string opt_key = "", const ObjectBase* object = nullptr) {
StringObjectException w;
w.string = std::move(msg);
w.opt_key = std::move(opt_key);
w.object = object;
add_warning(std::move(w));
};
std::vector<unsigned int> extruders = this->extruders();
unsigned int nozzles = m_config.nozzle_diameter.size();
@@ -1313,9 +1327,8 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (!ret.string.empty())
{
ret.type = STRING_EXCEPT_FILAMENTS_DIFFERENT_TEMP;
if (ret.is_warning && warning != nullptr) {
*warning = ret;
//return {};
if (ret.is_warning) {
add_warning(ret);
}else
return ret;
}
@@ -1341,32 +1354,26 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
else {
//BBS
auto ret = layered_print_cleareance_valid(*this, warning);
StringObjectException layer_warning;
auto ret = layered_print_cleareance_valid(*this, &layer_warning);
if (!ret.string.empty()) {
ret.type = STRING_EXCEPT_OBJECT_COLLISION_IN_LAYER_PRINT;
return ret;
}
if (!layer_warning.string.empty())
add_warning(layer_warning);
}
if (m_config.enable_prime_tower) {
for (const PrintObject* object : m_objects) {
if (object->config().precise_z_height.value && warning != nullptr) {
StringObjectException warningtemp;
warningtemp.string = L("Enabling both precise Z height and the prime tower may cause slicing errors.");
warningtemp.opt_key = "precise_z_height";
warningtemp.is_warning = true;
*warning = warningtemp;
if (object->config().precise_z_height.value) {
warn(L("Enabling both precise Z height and the prime tower may cause slicing errors."), "precise_z_height");
break;
}
}
} else {
if (m_config.enable_wrapping_detection && warning!=nullptr) {
StringObjectException warningtemp;
warningtemp.string = L("A prime tower is required for clumping detection; otherwise, there may be flaws on the model.");
warningtemp.opt_key = "enable_prime_tower";
warningtemp.is_warning = true;
*warning = warningtemp;
}
if (m_config.enable_wrapping_detection)
warn(L("A prime tower is required for clumping detection; otherwise, there may be flaws on the model."), "enable_prime_tower");
}
if (m_config.spiral_mode) {
@@ -1383,7 +1390,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (std::any_of(all_regions.begin() + 1, all_regions.end(), [ra = all_regions.front()](const auto rb) {
return !Layer::is_perimeter_compatible(ra, rb);
})) {
return {L("The spiral vase mode does not work when an object contains more than one materials."), nullptr, "spiral_mode"};
return {L("Spiral (vase) mode does not work when an object contains more than one material."), nullptr, "spiral_mode"};
}
}
}
@@ -1484,8 +1491,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam
|| std::abs((filament_diam - first_filament_diam) / first_filament_diam) > 0.1) {
// return { L("Different nozzle diameters and different filament diameters may not work well when prime tower is enabled. It's very experimental, please proceed with caucious.") };
warning->string = L("Different nozzle diameters and different filament diameters may not work well when the prime tower is enabled. It's very experimental, so please proceed with caution.");
warning->opt_key = "nozzle_diameter";
warn(L("Different nozzle diameters and different filament diameters may not work well when the prime tower is enabled. It's very experimental, so please proceed with caution."), "nozzle_diameter");
break;
}
}
@@ -1502,14 +1508,14 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return { L("The prime tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.")};
if ((m_config.print_sequence == PrintSequence::ByObject) && extruders.size() > 1)
return { L("The prime tower is not supported in \"By object\" print."), nullptr, "enable_prime_tower" };
return { L("A prime tower is not supported in \u201cBy object\u201d print."), nullptr, "enable_prime_tower" };
// BBS: When prime tower is on, object layer and support layer must be aligned. So support gap should be multiple of object layer height.
for (size_t i = 0; i < m_objects.size(); i++) {
const PrintObject* object = m_objects[i];
const SlicingParameters& slicing_params = object->slicing_parameters();
if (object->config().adaptive_layer_height) {
return { L("The prime tower is not supported when adaptive layer height is on. It requires that all objects have the same layer height."), object, "adaptive_layer_height" };
return { L("A prime tower is not supported when adaptive layer height is on. It requires that all objects have the same layer height."), object, "adaptive_layer_height" };
}
if (!object->config().enable_support)
@@ -1517,7 +1523,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
double gap_layers = slicing_params.gap_object_support / slicing_params.layer_height;
if (gap_layers - (int)gap_layers > EPSILON) {
return {L("The prime tower requires \"support gap\" to be multiple of layer height."), object};
return {L("A prime tower requires any \u201csupport gap\u201d to be a multiple of layer height."), object};
}
}
#endif
@@ -1530,9 +1536,9 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
const SlicingParameters &slicing_params = object->slicing_parameters();
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
return {L("The prime tower requires that all objects have the same layer heights."), object, "initial_layer_print_height"};
return {L("A prime tower requires that all objects have the same layer height."), object, "initial_layer_print_height"};
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
return {L("The prime tower requires that all objects are printed over the same number of raft layers."), object, "raft_layers"};
return {L("A prime tower requires that all objects are printed over the same number of raft layers."), object, "raft_layers"};
// BBS: support gap can be multiple of object layer height, remove _L()
#if 0
if (slicing_params0.gap_object_support != slicing_params.gap_object_support ||
@@ -1540,7 +1546,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return {L("The prime tower is only supported for multiple objects if they are printed with the same support_top_z_distance."), object};
#endif
if (!equal_layering(slicing_params, slicing_params0))
return { L("The prime tower requires that all objects are sliced with the same layer heights."), object };
return { L("A prime tower requires that all objects are sliced with the same layer height."), object };
if (has_custom_layering) {
auto &lh = layer_height_profile(i);
auto &lh_tallest = layer_height_profile(tallest_object_idx);
@@ -1606,10 +1612,10 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (extrusion_width_min == 0) {
// Default "auto-generated" extrusion width is always valid.
} else if (extrusion_width_min <= layer_height) {
err_msg = L("Too small line width");
err_msg = L("Line width too small");
return false;
} else if (extrusion_width_max > max_nozzle_diameter * MAX_LINE_WIDTH_MULTIPLIER) {
err_msg = L("Too large line width");
err_msg = L("Line width too large");
return false;
}
return true;
@@ -1631,7 +1637,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
// BBS
#if 0
if (this->has_wipe_tower() && object->config().independent_support_layer_height) {
return {L("The prime tower requires that support has the same layer height with object."), object, "support_filament"};
return {L("A prime tower requires that support has the same layer height as the object."), object, "support_filament"};
}
#endif
@@ -1642,22 +1648,15 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
// Orca: use organic as default
object->config().support_style == smsDefault) {
if (warning) {
// Orca: check the support wall count and the base pattern
if (object->config().tree_support_wall_count > 1 &&
object->config().support_base_pattern != SupportMaterialPattern::smpNone &&
object->config().support_base_pattern != SupportMaterialPattern::smpDefault) {
warning->string = L("For Organic supports, two walls are supported only with the Hollow/Default base pattern.");
warning->opt_key = "support_base_pattern";
}
// Orca: check the support wall count and the base pattern
if (object->config().tree_support_wall_count > 1 &&
object->config().support_base_pattern != SupportMaterialPattern::smpNone &&
object->config().support_base_pattern != SupportMaterialPattern::smpDefault)
warn(L("For Organic supports, two walls are supported only with the Hollow/Default base pattern."), "support_base_pattern");
// Orca: check if the Lightning base pattern selected
if (object->config().support_base_pattern == SupportMaterialPattern::smpLightning) {
warning->string = L(
"The Lightning base pattern is not supported by this support type; Rectilinear will be used instead.");
warning->opt_key = "support_base_pattern";
}
}
// Orca: check if the Lightning base pattern selected
if (object->config().support_base_pattern == SupportMaterialPattern::smpLightning)
warn(L("The Lightning base pattern is not supported by this support type; Rectilinear will be used instead."), "support_base_pattern");
float extrusion_width = std::min(
support_material_flow(object).width(),
@@ -1669,28 +1668,23 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (object->config().tree_support_branch_diameter_organic < object->config().tree_support_tip_diameter)
return { L("Organic support branch diameter must not be smaller than support tree tip diameter."), object, "tree_support_branch_diameter_organic" };
}
} else if (object->config().support_base_pattern == SupportMaterialPattern::smpLightning && warning) {
} else if (object->config().support_base_pattern == SupportMaterialPattern::smpLightning) {
// Orca: check if the Lightning base pattern selected
warning->string = L("The Lightning base pattern is not supported by this support type; Rectilinear will be used instead.");
warning->opt_key = "support_base_pattern";
} else if (object->config().support_base_pattern == SupportMaterialPattern::smpNone && warning) {
warn(L("The Lightning base pattern is not supported by this support type; Rectilinear will be used instead."), "support_base_pattern");
} else if (object->config().support_base_pattern == SupportMaterialPattern::smpNone) {
// Orca: check if the Hollow base pattern selected
warning->string = L("The Hollow base pattern is not supported by this support type; Rectilinear will be used instead.");
warning->opt_key = "support_base_pattern";
warn(L("The Hollow base pattern is not supported by this support type; Rectilinear will be used instead."), "support_base_pattern");
}
}
// Do we have custom support data that would not be used?
// Notify the user in that case.
if (! object->has_support() && warning) {
if (! object->has_support()) {
for (const ModelVolume* mv : object->model_object()->volumes) {
bool has_enforcers = mv->is_support_enforcer() ||
(mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER));
if (has_enforcers) {
StringObjectException warningtemp;
warningtemp.string = L("Support enforcers are used but support is not enabled. Please enable support.");
warningtemp.object = object;
*warning = warningtemp;
warn(L("Support enforcers are used but support is not enabled. Please enable support."), "", object);
break;
}
}
@@ -1744,7 +1738,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return { err_msg, object, "bridge_line_width" };
}
if (!allow_thin_bridge_width && bridge_width <= layer_height) {
err_msg = L("Too small line width");
err_msg = L("Line width too small");
return { err_msg, object, "bridge_line_width" };
}
}
@@ -1842,7 +1836,11 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
// check if print speed/accel/jerk is higher than the maximum speed of the printer
if (warning) {
if (warnings) {
// The motion-ability checks are mutually exclusive (gated on warning_key), so collect the
// single one that fires into a local and push it once - separate from the precise-wall and
// shrinkage warnings below.
StringObjectException motion_warning;
try {
auto check_motion_ability_object_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
std::string warning_key;
@@ -1873,7 +1871,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
if (!ignore_jerk_validation) {
if (m_default_object_config.default_jerk == 1 || m_default_object_config.outer_wall_jerk == 1 ||
m_default_object_config.inner_wall_jerk == 1) {
warning->string = L("Setting the jerk speed too low could lead to artifacts on curved surfaces");
motion_warning.string = L("Setting the jerk speed too low could lead to artifacts on curved surfaces");
if (m_default_object_config.outer_wall_jerk == 1)
warning_key = "outer_wall_jerk";
else if (m_default_object_config.inner_wall_jerk == 1)
@@ -1881,7 +1879,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
else
warning_key = "default_jerk";
warning->opt_key = warning_key;
motion_warning.opt_key = warning_key;
}
if (warning_key.empty() && m_default_object_config.default_jerk > 0) {
@@ -1891,20 +1889,20 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
warning_key.clear();
warning_key = check_motion_ability_object_setting(jerk_to_check, max_jerk);
if (!warning_key.empty()) {
warning->string = L(
motion_warning.string = L(
"The jerk setting exceeds the printer's maximum jerk (machine_max_jerk_x/machine_max_jerk_y).\n"
"Orca will automatically cap the jerk speed to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the maximum jerk setting in your printer's configuration to get higher speeds.");
warning->opt_key = warning_key;
motion_warning.opt_key = warning_key;
}
}
}
// check junction deviation
else if (m_default_object_config.default_junction_deviation.value > max_junction_deviation) {
warning->string = L( "Junction deviation setting exceeds the printer's maximum value (machine_max_junction_deviation).\n"
motion_warning.string = L( "Junction deviation setting exceeds the printer's maximum value (machine_max_junction_deviation).\n"
"Orca will automatically cap the junction deviation to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the machine_max_junction_deviation value in your printer's configuration to get higher limits.");
warning->opt_key = "default_junction_deviation";
motion_warning.opt_key = "default_junction_deviation";
}
// check acceleration
@@ -1939,12 +1937,12 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_accel);
if (!warning_key.empty()) {
warning->string = L("The acceleration setting exceeds the printer's maximum acceleration "
motion_warning.string = L("The acceleration setting exceeds the printer's maximum acceleration "
"(machine_max_acceleration_extruding).\nOrca will "
"automatically cap the acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_extruding value in your printer's configuration to get higher speeds.");
warning->opt_key = warning_key;
motion_warning.opt_key = warning_key;
}
if (support_travel_acc) {
const auto max_travel = m_config.machine_max_acceleration_travel.values[0];
@@ -1954,13 +1952,13 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_travel);
if (!warning_key.empty()) {
warning->string = L(
motion_warning.string = L(
"The travel acceleration setting exceeds the printer's maximum travel acceleration "
"(machine_max_acceleration_travel).\nOrca will "
"automatically cap the travel acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_travel value in your printer's configuration to get higher speeds.");
warning->opt_key = warning_key;
motion_warning.opt_key = warning_key;
}
}
}
@@ -1986,19 +1984,17 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
// }
// check wall sequence and precise outer wall
if (m_default_region_config.precise_outer_wall && m_default_region_config.wall_sequence != WallSequence::InnerOuter) {
warning->string = L("The precise wall option will be ignored for outer-inner or inner-outer-inner wall sequences.");
warning->opt_key = "precise_outer_wall";
}
if (m_default_region_config.precise_outer_wall && m_default_region_config.wall_sequence != WallSequence::InnerOuter)
warn(L("The precise wall option will be ignored for outer-inner or inner-outer-inner wall sequences."), "precise_outer_wall");
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(warning) << "Orca: validate motion ability failed: " << e.what() << std::endl;
}
if (!motion_warning.string.empty())
add_warning(motion_warning);
}
if (!this->has_same_shrinkage_compensations()){
warning->string = L("Filament shrinkage will not be used because filament shrinkage for the used filaments does not match.");
warning->opt_key = "";
}
if (!this->has_same_shrinkage_compensations())
warn(L("Filament shrinkage will not be used because filament shrinkage for the used filaments does not match."));
return {};
}
@@ -2711,7 +2707,8 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
gcode->do_export(this, path.c_str(), result, thumbnail_cb);
gcode->export_layer_filaments(result);
//BBS
result->conflict_result = m_conflict_result;
if (result != nullptr)
result->conflict_result = m_conflict_result;
return path.c_str();
}