mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-16 07:22:10 +00:00
Merge branch 'main' into feature/protobuf_config_and_dynamic_ui
This commit is contained in:
@@ -964,10 +964,6 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Orca: this g92e0 regex is used copied from PrusaSlicer
|
||||
// Matches "G92 E0" with various forms of writing the zero and with an optional comment.
|
||||
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
|
||||
|
||||
// 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
|
||||
@@ -1254,12 +1250,12 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
auto validate_extrusion_width = [min_nozzle_diameter, max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
|
||||
double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
|
||||
double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
|
||||
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");
|
||||
return false;
|
||||
} else if (extrusion_width_max > max_nozzle_diameter * MAX_LINE_WIDTH_MULTIPLIER) {
|
||||
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");
|
||||
return false;
|
||||
} else if (extrusion_width_max > max_nozzle_diameter * MAX_LINE_WIDTH_MULTIPLIER) {
|
||||
err_msg = L("Too large line width");
|
||||
return false;
|
||||
}
|
||||
@@ -1381,30 +1377,83 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
for (const PrintRegion ®ion : object->all_regions())
|
||||
if (!validate_extrusion_width(region.config(), opt_key, layer_height, err_msg))
|
||||
return {err_msg, object, opt_key};
|
||||
|
||||
const bool allow_thin_bridge_width = object->config().thick_bridges && object->config().thick_internal_bridges;
|
||||
for (const PrintRegion ®ion : object->all_regions()) {
|
||||
const auto &bridge_width_opt = region.config().bridge_line_width;
|
||||
for (FlowRole bridge_role : { frPerimeter, frInfill, frSolidInfill, frTopSolidInfill }) {
|
||||
const double nozzle_diameter = m_config.nozzle_diameter.get_at(region.extruder(bridge_role) - 1);
|
||||
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
|
||||
if (bridge_width <= 0.)
|
||||
continue;
|
||||
if (bridge_width > nozzle_diameter) {
|
||||
err_msg = L("Bridge line width must not exceed nozzle diameter");
|
||||
return { err_msg, object, "bridge_line_width" };
|
||||
}
|
||||
if (!allow_thin_bridge_width && bridge_width <= layer_height) {
|
||||
err_msg = L("Too small line width");
|
||||
return { err_msg, object, "bridge_line_width" };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Orca: G92 E0 is not supported when using absolute extruder addressing
|
||||
// This check is copied from PrusaSlicer, the original author is Vojtech Bubnik
|
||||
if(!is_BBL_printer()) {
|
||||
bool before_layer_gcode_resets_extruder =
|
||||
boost::regex_search(m_config.before_layer_change_gcode.value, regex_g92e0);
|
||||
bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_change_gcode.value, regex_g92e0);
|
||||
if (m_config.use_relative_e_distances) {
|
||||
// See GH issues #6336 #5073
|
||||
if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
|
||||
!before_layer_gcode_resets_extruder && !layer_gcode_resets_extruder)
|
||||
return {L("Relative extruder addressing requires resetting the extruder position at each layer to "
|
||||
"prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."),
|
||||
nullptr, "before_layer_change_gcode"};
|
||||
} else if (before_layer_gcode_resets_extruder)
|
||||
return {L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder "
|
||||
// This check is modified from PrusaSlicer, the original author is Vojtech Bubnik
|
||||
// Orca: case‑sensitive match for exactly "G92 E0" (uppercase G and E only)
|
||||
// because gcode is case sensitive and G92 e0 satisfies the regex but causes a slicing error
|
||||
// https://github.com/OrcaSlicer/OrcaSlicer/issues/13927
|
||||
|
||||
// Matches any case of "G92 E0" (original pattern)
|
||||
static const boost::regex regex_g92e0 {
|
||||
"^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$"
|
||||
};
|
||||
// Matches only the exact uppercase "G92 E0"
|
||||
static const boost::regex regex_g92e0_correct {
|
||||
"^[ \\t]*G92[ \\t]*E(0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$"
|
||||
};
|
||||
|
||||
const bool before_has_g92_any = boost::regex_search(
|
||||
m_config.before_layer_change_gcode.value, regex_g92e0);
|
||||
const bool layer_has_g92_any = boost::regex_search(
|
||||
m_config.layer_change_gcode.value, regex_g92e0);
|
||||
|
||||
if (m_config.use_relative_e_distances) {
|
||||
// Relative mode: "G92 E0" is required to reset extruder position.
|
||||
const bool before_has_g92_exact = boost::regex_search(
|
||||
m_config.before_layer_change_gcode.value, regex_g92e0_correct);
|
||||
const bool layer_has_g92_exact = boost::regex_search(
|
||||
m_config.layer_change_gcode.value, regex_g92e0_correct);
|
||||
|
||||
// Wrong case found?
|
||||
if (before_has_g92_any && !before_has_g92_exact)
|
||||
return {L("\"G92 E0\" was found in before_layer_change_gcode, but the G or E are not uppercase. "
|
||||
"Please change them to the exact uppercase \"G92 E0\"."),
|
||||
nullptr, "before_layer_change_gcode"};
|
||||
if (layer_has_g92_any && !layer_has_g92_exact)
|
||||
return {L("\"G92 E0\" was found in layer_change_gcode, but the G or E are not uppercase. "
|
||||
"Please change them to the exact uppercase \"G92 E0\"."),
|
||||
nullptr, "layer_change_gcode"};
|
||||
|
||||
// Only Marlin flavours need the reset; BBL printers do not.
|
||||
if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
|
||||
!is_BBL_printer() &&
|
||||
!before_has_g92_exact && !layer_has_g92_exact)
|
||||
return {L("Relative extruder addressing requires resetting the extruder position at each layer to "
|
||||
"prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."),
|
||||
nullptr, "before_layer_change_gcode"};
|
||||
} else {
|
||||
// Absolute mode: any occurrence of "G92 E0" is incompatible.
|
||||
if (before_has_g92_any)
|
||||
return {L("\"G92 E0\" was found in before_layer_change_gcode, which is incompatible with absolute extruder "
|
||||
"addressing."),
|
||||
nullptr, "before_layer_change_gcode"};
|
||||
else if (layer_gcode_resets_extruder)
|
||||
return {L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."),
|
||||
if (layer_has_g92_any)
|
||||
return {L("\"G92 E0\" was found in layer_change_gcode, which is incompatible with absolute extruder "
|
||||
"addressing."),
|
||||
nullptr, "layer_change_gcode"};
|
||||
}
|
||||
}
|
||||
|
||||
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
|
||||
assert(bed_type_def != nullptr);
|
||||
@@ -3209,6 +3258,24 @@ std::string Print::output_filename(const std::string &filename_base) const
|
||||
config.set_key_value("plate_number", new ConfigOptionString(get_plate_number_formatted()));
|
||||
config.set_key_value("model_name", new ConfigOptionString(get_model_name()));
|
||||
|
||||
// the same type of filament contains multiple names, support exporting according to the filament name
|
||||
auto full_print_config = this->full_print_config();
|
||||
const ConfigOptionStrings* filament_settings_id = full_print_config.option<ConfigOptionStrings>("filament_settings_id");
|
||||
std::string filament_name = "";
|
||||
auto extruders = this->extruders(true);
|
||||
if(!extruders.empty()) {
|
||||
// first extruder is the default extruder
|
||||
int extruder_id = extruders.front();
|
||||
if(filament_settings_id->values.size() > extruder_id) {
|
||||
filament_name = filament_settings_id->values[extruder_id];
|
||||
}
|
||||
}
|
||||
size_t end_pos = filament_name.find_first_of("@");
|
||||
if (end_pos != std::string::npos) {
|
||||
filament_name = filament_name.substr(0, end_pos);
|
||||
}
|
||||
config.set_key_value("filament_name", new ConfigOptionString(filament_name));
|
||||
|
||||
return this->PrintBase::output_filename(m_config.filename_format.value, ".gcode", filename_base, &config);
|
||||
}
|
||||
|
||||
@@ -3301,9 +3368,12 @@ DynamicConfig PrintStatistics::config() const
|
||||
config.set_key_value("total_cost", new ConfigOptionFloat(this->total_cost));
|
||||
config.set_key_value("total_toolchanges", new ConfigOptionInt(this->total_toolchanges));
|
||||
config.set_key_value("total_weight", new ConfigOptionFloat(this->total_weight));
|
||||
config.set_key_value("extruded_weight_total", new ConfigOptionFloat(this->total_weight));
|
||||
config.set_key_value("extruded_volume_total", new ConfigOptionFloat(this->total_extruded_volume));
|
||||
config.set_key_value("total_wipe_tower_cost", new ConfigOptionFloat(this->total_wipe_tower_cost));
|
||||
config.set_key_value("total_wipe_tower_filament", new ConfigOptionFloat(this->total_wipe_tower_filament));
|
||||
config.set_key_value("initial_tool", new ConfigOptionInt(static_cast<int>(this->initial_tool)));
|
||||
config.set_key_value("initial_extruder", new ConfigOptionInt(static_cast<int>(this->initial_tool)));
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -3312,8 +3382,8 @@ DynamicConfig PrintStatistics::placeholders()
|
||||
DynamicConfig config;
|
||||
for (const std::string key : {
|
||||
"print_time", "normal_print_time", "silent_print_time",
|
||||
"used_filament", "extruded_volume", "total_cost", "total_weight",
|
||||
"initial_tool", "total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"})
|
||||
"used_filament", "extruded_volume", "extruded_volume_total", "total_cost", "total_weight", "extruded_weight_total",
|
||||
"initial_tool", "initial_extruder", "total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"})
|
||||
config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}"));
|
||||
return config;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user