mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-23 00:42:33 +00:00
Merge branch 'feat/printer-agent-ui' of https://github.com/OrcaSlicer/OrcaSlicer into feat/printer-agent-ui
This commit is contained in:
@@ -31,8 +31,9 @@ namespace AABBTreeLines {
|
||||
inline VectorType closest_point_to_origin(size_t primitive_index, ScalarType& squared_distance) const
|
||||
{
|
||||
Vec<LineType::Dim, typename LineType::Scalar> nearest_point;
|
||||
Vec<LineType::Dim, typename LineType::Scalar> cast_origin = origin.template cast<typename LineType::Scalar>();
|
||||
const LineType& line = lines[primitive_index];
|
||||
squared_distance = line_alg::distance_to_squared(line, origin.template cast<typename LineType::Scalar>(), &nearest_point);
|
||||
squared_distance = line_alg::distance_to_squared(line, cast_origin, &nearest_point);
|
||||
return nearest_point.template cast<ScalarType>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,12 +220,12 @@ double Extruder::retract_restart_extra() const
|
||||
|
||||
double Extruder::retract_length_toolchange() const
|
||||
{
|
||||
return m_config->retract_length_toolchange.get_at(extruder_id());
|
||||
return m_config->retract_length_toolchange.get_at(m_config_index);
|
||||
}
|
||||
|
||||
double Extruder::retract_restart_extra_toolchange() const
|
||||
{
|
||||
return m_config->retract_restart_extra_toolchange.get_at(extruder_id());
|
||||
return m_config->retract_restart_extra_toolchange.get_at(m_config_index);
|
||||
}
|
||||
|
||||
double Extruder::travel_slope() const
|
||||
|
||||
+24
-21
@@ -1137,8 +1137,8 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
|
||||
float old_retract_length = (old_filament_id != -1) ? full_config.retraction_length.get_at(old_fi) : 0;
|
||||
float new_retract_length = full_config.retraction_length.get_at(new_fi);
|
||||
float old_retract_length_toolchange = (old_filament_id != -1) ? full_config.retract_length_toolchange.get_at(old_filament_id) : 0;
|
||||
float new_retract_length_toolchange = full_config.retract_length_toolchange.get_at(new_filament_id);
|
||||
float old_retract_length_toolchange = (old_filament_id != -1) ? full_config.retract_length_toolchange.get_at(old_fi) : 0;
|
||||
float new_retract_length_toolchange = full_config.retract_length_toolchange.get_at(new_fi);
|
||||
int old_filament_temp = (old_filament_id != -1) ? (gcodegen.on_first_layer()? full_config.nozzle_temperature_initial_layer.get_at(old_fi) : full_config.nozzle_temperature.get_at(old_fi)) : 210;
|
||||
int new_filament_temp = gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(new_fi) : full_config.nozzle_temperature.get_at(new_fi);
|
||||
Vec3d nozzle_pos = gcode_writer.get_position();
|
||||
@@ -2884,6 +2884,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled,
|
||||
print.get_layered_nozzle_group_result());
|
||||
const bool is_bbl_printers = print.is_BBL_printer();
|
||||
const bool skip_config_block = print.config().gcode_skip_config_block;
|
||||
const WipeTowerType wipe_tower_type = print.wipe_tower_type();
|
||||
m_calib_config.clear();
|
||||
// resets analyzer's tracking data
|
||||
@@ -3059,7 +3060,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// as configuration key / value pairs to be parsable by older versions of
|
||||
// PrusaSlicer G-code viewer.
|
||||
{
|
||||
if (is_bbl_printers) {
|
||||
if (is_bbl_printers && !skip_config_block) {
|
||||
file.write("; CONFIG_BLOCK_START\n");
|
||||
std::string full_config;
|
||||
append_full_config(print, full_config);
|
||||
@@ -4086,23 +4087,25 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder)
|
||||
.c_str());
|
||||
file.write("\n");
|
||||
file.write("; CONFIG_BLOCK_START\n");
|
||||
std::string full_config;
|
||||
append_full_config(print, full_config);
|
||||
if (!full_config.empty())
|
||||
file.write(full_config);
|
||||
if (!skip_config_block) {
|
||||
file.write("; CONFIG_BLOCK_START\n");
|
||||
std::string full_config;
|
||||
append_full_config(print, full_config);
|
||||
if (!full_config.empty())
|
||||
file.write(full_config);
|
||||
|
||||
// SoftFever: write compatiple info
|
||||
int first_layer_bed_temperature = get_bed_temperature(0, true, print.config().curr_bed_type);
|
||||
file.write_format("; first_layer_bed_temperature = %d\n", first_layer_bed_temperature);
|
||||
file.write_format("; bed_shape = %s\n", print.full_print_config().opt_serialize("printable_area").c_str());
|
||||
file.write_format("; first_layer_temperature = %d\n", print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write_format("; first_layer_height = %.3f\n", print.config().initial_layer_print_height.value);
|
||||
|
||||
//SF TODO
|
||||
// file.write_format("; variable_layer_height = %d\n", print.ad.adaptive_layer_height ? 1 : 0);
|
||||
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
// SoftFever: write compatiple info
|
||||
int first_layer_bed_temperature = get_bed_temperature(0, true, print.config().curr_bed_type);
|
||||
file.write_format("; first_layer_bed_temperature = %d\n", first_layer_bed_temperature);
|
||||
file.write_format("; bed_shape = %s\n", print.full_print_config().opt_serialize("printable_area").c_str());
|
||||
file.write_format("; first_layer_temperature = %d\n", print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write_format("; first_layer_height = %.3f\n", print.config().initial_layer_print_height.value);
|
||||
|
||||
//SF TODO
|
||||
// file.write_format("; variable_layer_height = %d\n", print.ad.adaptive_layer_height ? 1 : 0);
|
||||
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
} // !skip_config_block
|
||||
|
||||
}
|
||||
file.write("\n");
|
||||
@@ -9035,7 +9038,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
// per-layer nozzle grouping; resolve the column instead of indexing by the filament id.
|
||||
size_t new_fi = get_filament_config_index((int)new_filament_id);
|
||||
float new_retract_length = m_config.retraction_length.get_at(new_fi);
|
||||
float new_retract_length_toolchange = m_config.retract_length_toolchange.get_at(new_filament_id);
|
||||
float new_retract_length_toolchange = m_config.retract_length_toolchange.get_at(new_fi);
|
||||
int new_filament_temp = this->on_first_layer() ? m_config.nozzle_temperature_initial_layer.get_at(new_fi) : m_config.nozzle_temperature.get_at(new_fi);
|
||||
// BBS: if print_z == 0 use first layer temperature
|
||||
if (abs(print_z) < EPSILON)
|
||||
@@ -9066,7 +9069,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
// gap-filled carry-forward, so its current-layer column matches the nozzle it occupies.
|
||||
size_t old_fi = get_filament_config_index(old_filament_id);
|
||||
old_retract_length = m_config.retraction_length.get_at(old_fi);
|
||||
old_retract_length_toolchange = m_config.retract_length_toolchange.get_at(old_filament_id);
|
||||
old_retract_length_toolchange = m_config.retract_length_toolchange.get_at(old_fi);
|
||||
old_filament_temp = this->on_first_layer()? m_config.nozzle_temperature_initial_layer.get_at(old_fi) : m_config.nozzle_temperature.get_at(old_fi);
|
||||
|
||||
//During the filament change, the extruder will extrude an extra length of grab_length for the corresponding detection, so the purge can reduce this length.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "I18N.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry/ArcWelder.hpp"
|
||||
#include "Line.hpp"
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
@@ -1018,45 +1019,48 @@ std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, c
|
||||
}
|
||||
|
||||
if (!this->config.enable_arc_fitting) { // Orca: if arc fitting is disabled, approximate the arc with small linear segments
|
||||
std::ostringstream oss;
|
||||
const double z_start = m_pos(2); // starting Z height
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Determine number of segments based on Resolution
|
||||
// --------------------------------------------------------------------
|
||||
const double ref_resolution = 0.01; // reference resolution in mm
|
||||
const double ref_segments = 8.0; // reference number of segments at reference resolution
|
||||
|
||||
// number of linear segments to use for approximating the arc, clamp between 4 and 16
|
||||
const int segments = std::clamp(int(std::round(ref_segments * (ref_resolution / m_resolution))), 4, 16);
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
const double px = m_pos(0) - m_x_offset; // take plate offset into consideration
|
||||
const double py = m_pos(1) - m_y_offset; // take plate offset into consideration
|
||||
const double cx = px + ij_offset(0); // center x
|
||||
const double cy = py + ij_offset(1); // center y
|
||||
const double radius = ij_offset.norm(); // radius
|
||||
|
||||
// Number of linear segments approximating the circle, chosen so that a chord never deviates
|
||||
// from the true arc by more than the slicing resolution. A resolution of 0 means "no
|
||||
// simplification", which has no finite segment count, so it takes the upper bound.
|
||||
constexpr size_t min_segments = 8; // keep a small spiral visibly round
|
||||
constexpr size_t max_segments = 128; // bound the emitted G-code
|
||||
const int segments = int(m_resolution > 0. ?
|
||||
std::clamp(Geometry::ArcWelder::arc_discretization_steps(radius, 2. * M_PI, m_resolution), min_segments, max_segments) :
|
||||
max_segments);
|
||||
|
||||
const double a0 = std::atan2(py - cy, px - cx); // start angle
|
||||
const double delta = 2.0 * M_PI; // CCW full circle
|
||||
|
||||
if (full_gcode_comment)
|
||||
oss << ";" << comment << "\n";
|
||||
auto emit_point = [&output](const Vec3d &point) {
|
||||
GCodeG1Formatter w;
|
||||
w.emit_xyz(point);
|
||||
output += w.string();
|
||||
};
|
||||
|
||||
oss << "G1 F" << (speed * 60.0) << "\n"; // set feedrate
|
||||
output.reserve(size_t(segments) * 40); // ~40 characters per emitted G1 line
|
||||
|
||||
GCodeG1Formatter w; // set feedrate
|
||||
w.emit_f(speed * 60.0);
|
||||
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
|
||||
output += w.string();
|
||||
|
||||
// approximate the arc with small linear segments (without the last point which is added later to ensure exactness)
|
||||
for (int i = 1; i < segments; ++i) {
|
||||
double t = double(i) / segments; // parametric position along arc
|
||||
double a = a0 + delta * t; // CCW arc param
|
||||
double x = cx + radius * std::cos(a); // point on circle
|
||||
double y = cy + radius * std::sin(a); // point on circle
|
||||
double zz = z_start + (z - z_start) * t; // interpolated Z height
|
||||
|
||||
oss << "G1 X" << x << " Y" << y << " Z" << zz << "\n";
|
||||
const double t = double(i) / segments; // parametric position along arc
|
||||
const double a = a0 + 2. * M_PI * t; // CCW arc param, full circle
|
||||
emit_point(Vec3d(cx + radius * std::cos(a), // point on circle
|
||||
cy + radius * std::sin(a),
|
||||
z_start + (z - z_start) * t)); // interpolated Z height
|
||||
}
|
||||
|
||||
oss << "G1 X" << px << " Y" << py << " Z" << z << "\n"; // final point to ensure exactness
|
||||
output = oss.str();
|
||||
emit_point(Vec3d(px, py, z)); // final point to ensure exactness
|
||||
} else { // Orca: if arc fitting is enabled emit a G2/G3 command for the spiral lift
|
||||
output = std::string("G17") + (full_gcode_comment ? " ; XY plane for arc\n" : "\n");
|
||||
|
||||
|
||||
@@ -1977,7 +1977,7 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
||||
ExPolygons unsupported = diff_ex(last, *this->lower_slices, ApplySafetyOffset::Yes);
|
||||
if (!unsupported.empty()) {
|
||||
//remove small overhangs
|
||||
ExPolygons unsupported_filtered = offset2_ex(unsupported, double(-perimeter_spacing), double(perimeter_spacing));
|
||||
ExPolygons unsupported_filtered = opening_ex(unsupported, perimeter_spacing);
|
||||
|
||||
if (!unsupported_filtered.empty()) {
|
||||
//to_draw.insert(to_draw.end(), last.begin(), last.end());
|
||||
@@ -2090,35 +2090,40 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
||||
//TODO: add other polys as holes inside this one (-margin)
|
||||
} else { // if(this->config->counterbore_hole_bridging.value == chbBridges)
|
||||
// Orca: Partial counterbore bridging is mask-based. Preserve the supported
|
||||
// remainder (`last`) and use simplified BridgeDetector coverage to derive the
|
||||
// remainder and use simplified BridgeDetector coverage to derive the
|
||||
// bridgeable counterbore span. The span is grown from supported material,
|
||||
// shrunk back, stripped from `last`, and expanded back. It is then prevented
|
||||
// from intruding deeper into `last` than the explicit anchor overlap.
|
||||
// Finally, add the allowed anchor band from `last` then remove the
|
||||
// shrunk back, stripped from the remaining normal surface, and expanded back.
|
||||
// It is then prevented from intruding deeper into it than the explicit anchor overlap.
|
||||
// Finally, add the allowed anchor band from it then remove the
|
||||
// narrow hole-side wall contact, which must remain unbridgeable.
|
||||
|
||||
last = diff_ex(last, unsupported_filtered, ApplySafetyOffset::Yes);
|
||||
const ExPolygons remaining = diff_ex(last, unsupported_filtered, ApplySafetyOffset::Yes);
|
||||
|
||||
ExPolygons bridgeable_filtered;
|
||||
|
||||
for (ExPolygon& poly : bridgeable) {
|
||||
poly.simplify(perimeter_spacing, &bridgeable_filtered);
|
||||
}
|
||||
bridgeable_filtered = opening_ex(bridgeable_filtered, ext_perimeter_width);
|
||||
|
||||
// Get rid of coarseness of the resulted bridgeable area by using the original supported area as reference.
|
||||
// This is to avoid keeping tiny bridgeable areas that are far from the supported area, or protrude into it.
|
||||
bridgeable_filtered = union_ex(offset_ex(last, perimeter_spacing), bridgeable_filtered);
|
||||
// This is to avoid keeping tiny bridgeable areas that are far from the supported area, or protrude into it.
|
||||
bridgeable_filtered = union_ex(offset_ex(remaining, perimeter_spacing), bridgeable_filtered);
|
||||
bridgeable_filtered = offset_ex(bridgeable_filtered, -perimeter_spacing);
|
||||
bridgeable_filtered = diff_ex(bridgeable_filtered, last, ApplySafetyOffset::Yes);
|
||||
bridgeable_filtered = diff_ex(bridgeable_filtered, remaining, ApplySafetyOffset::Yes);
|
||||
bridgeable_filtered = opening_ex(bridgeable_filtered, perimeter_spacing); // filter noise from the diff_ex
|
||||
bridgeable_filtered = offset_ex(bridgeable_filtered, perimeter_spacing); // restore the size to the original bridgeable area
|
||||
// Safety measure: Keep the bridge mask from intruding deeper into the
|
||||
// supported anchor region (`last`) than the explicit anchor overlap.
|
||||
bridgeable_filtered = diff_ex(bridgeable_filtered, offset_ex(last, -bridge_anchor_offset));
|
||||
// supported anchor region than the explicit anchor overlap.
|
||||
bridgeable_filtered = diff_ex(bridgeable_filtered, offset_ex(remaining, -bridge_anchor_offset));
|
||||
|
||||
ExPolygons bridge_anchor_areas = intersection_ex(last, offset_ex(unsupported_filtered, bridge_anchor_offset));
|
||||
ExPolygons bridge_anchor_areas = intersection_ex(remaining, offset_ex(unsupported_filtered, bridge_anchor_offset));
|
||||
unsupported_filtered = union_ex(bridgeable_filtered, bridge_anchor_areas); // add bridge anchor
|
||||
unsupported_filtered = opening_ex(unsupported_filtered, bridge_anchor_offset); // remove anchor area from hole-side walls, it must remain unbridgeable
|
||||
|
||||
// update 'last' only if we have a valid bridgeable area, otherwise we will lose the original unsupported area
|
||||
if (!unsupported_filtered.empty())
|
||||
last = remaining;
|
||||
// TODO: Fix the case with thin outer walls around the bridge (1~2 walls) where classic wall
|
||||
// might generate two walls in a tiny space or non at all if "Detect thin walls" is not activated
|
||||
}
|
||||
|
||||
@@ -1791,6 +1791,8 @@ namespace client
|
||||
// from UTF8 to UTF16 don't bail out.
|
||||
msg += boost::nowide::narrow(boost::nowide::widen(error_line));
|
||||
msg += '\n';
|
||||
// The error dialog (MsgDialog.cpp) renders this excerpt monospaced. It recognizes a source
|
||||
// line directly above a caret line of spaces and a single '^'.
|
||||
for (size_t i = 0; i < error_pos; ++ i)
|
||||
msg += ' ';
|
||||
msg += "^\n";
|
||||
|
||||
@@ -1351,6 +1351,8 @@ static std::vector<std::string> s_Preset_filament_options {/*"filament_colour",
|
||||
"filament_retraction_length",
|
||||
"filament_retraction_minimum_travel",
|
||||
"filament_retraction_speed",
|
||||
"filament_retract_length_toolchange",
|
||||
"filament_retract_restart_extra_toolchange",
|
||||
"filament_wipe",
|
||||
"filament_z_hop",
|
||||
"filament_z_hop_types",
|
||||
@@ -1404,7 +1406,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "extruder_printable_area", "support_parallel_printheads", "parallel_printheads_count", "parallel_printheads_bed_exclude_areas", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"fan_kickstart", "part_cooling_fan_min_pwm", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"gcode_skip_config_block", "fan_kickstart", "part_cooling_fan_min_pwm", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"single_extruder_multi_material", "manual_filament_change", "file_start_gcode", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type",
|
||||
"printable_height", "extruder_printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
@@ -3784,12 +3786,14 @@ void PresetCollection::update_library_profile_excluded_from()
|
||||
}
|
||||
|
||||
// Check all presets that has the same alias as the filament presets with empty compatible_printers in Orca Filament Library.
|
||||
// A printer specific profile supersedes the generic one, no matter whether it lives in a vendor bundle or in the
|
||||
// library itself.
|
||||
for (const Preset& preset : m_presets) {
|
||||
if (preset.vendor == nullptr || preset.vendor->name == PresetBundle::ORCA_FILAMENT_LIBRARY)
|
||||
if (preset.vendor == nullptr)
|
||||
continue;
|
||||
|
||||
const auto* compatible_printers = dynamic_cast<const ConfigOptionStrings*>(preset.config.option("compatible_printers"));
|
||||
// All profiles in concrete vendor profile shouldn't have empty compatible_printers, but here we check it for safety.
|
||||
// Profiles with empty compatible_printers are the generic ones, they never supersede anything.
|
||||
if (compatible_printers == nullptr || compatible_printers->values.empty())
|
||||
continue;
|
||||
auto itr = excluded_froms.find(preset.alias);
|
||||
|
||||
@@ -72,6 +72,8 @@ const std::vector<std::string> filament_extruder_override_keys = {
|
||||
"filament_deretraction_speed",
|
||||
"filament_retract_restart_extra", //not in filament_options_with_variant, added on 20250816
|
||||
"filament_retraction_minimum_travel",
|
||||
"filament_retract_length_toolchange",
|
||||
"filament_retract_restart_extra_toolchange",
|
||||
// BBS: floats
|
||||
"filament_wipe_distance",
|
||||
// bools
|
||||
@@ -4259,6 +4261,15 @@ void PrintConfigDef::init_fff_params()
|
||||
def->readonly = false;
|
||||
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfMarlinLegacy));
|
||||
|
||||
def = this->add("gcode_skip_config_block", coBool);
|
||||
def->label = L("Skip G-code config block");
|
||||
def->tooltip = L("Do not write the CONFIG_BLOCK (slicer configuration key/value pairs) into the G-code file. "
|
||||
"This can help with printers whose firmware crashes when parsing these comment lines "
|
||||
"(e.g. Anycubic go-klipper). Note: the G-code file will no longer contain slicer settings, "
|
||||
"so importing it back into OrcaSlicer will not restore the configuration.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("pellet_modded_printer", coBool);
|
||||
def->label = L("Pellet Modded Printer");
|
||||
def->tooltip = L("Enable this option if your printer uses pellets instead of filaments.");
|
||||
@@ -4292,7 +4303,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"slow down.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(0));
|
||||
|
||||
|
||||
//BBS
|
||||
def = this->add("infill_combination", coBool);
|
||||
def->label = L("Infill combination");
|
||||
@@ -5725,12 +5736,10 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionFloatsNullable{10});
|
||||
|
||||
def = this->add("retract_length_toolchange", coFloats);
|
||||
def->label = L("Length");
|
||||
//def->full_label = L("Retraction Length (Toolchange)");
|
||||
def->full_label = "Retraction Length (Toolchange)";
|
||||
//def->tooltip = L("When retraction is triggered before changing tool, filament is pulled back "
|
||||
// "by the specified amount (the length is measured on raw filament, before it enters "
|
||||
// "the extruder).");
|
||||
def->label = L("Retraction Length (Toolchange)");
|
||||
def->tooltip = L("When retraction is triggered before changing tool, filament is pulled back "
|
||||
"by the specified amount (the length is measured on raw filament, before it enters "
|
||||
"the extruder).");
|
||||
def->sidetext = L("mm"); // millimeters, CIS languages need translation
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 10. });
|
||||
@@ -5984,7 +5993,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
def = this->add("retract_restart_extra_toolchange", coFloats);
|
||||
def->label = L("Extra length on restart");
|
||||
def->label = L("Extra length on restart (Toolchange)");
|
||||
def->tooltip = L("When the retraction is compensated after changing tool, the extruder will push "
|
||||
"this additional amount of filament.");
|
||||
def->sidetext = L("mm"); // millimeters, CIS languages need translation
|
||||
@@ -8154,10 +8163,12 @@ void PrintConfigDef::init_extruder_option_keys()
|
||||
"long_retractions_when_cut",
|
||||
"retract_after_wipe",
|
||||
"retract_before_wipe",
|
||||
"retract_length_toolchange",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
"retract_lift_enforce",
|
||||
"retract_restart_extra",
|
||||
"retract_restart_extra_toolchange",
|
||||
"retract_when_changing_layer",
|
||||
"retraction_distances_when_cut",
|
||||
"retraction_length",
|
||||
@@ -9245,6 +9256,8 @@ std::set<std::string> filament_options_with_variant = {
|
||||
"filament_retract_lift_below",
|
||||
"filament_retract_lift_enforce",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_length_toolchange",
|
||||
"filament_retract_restart_extra_toolchange",
|
||||
"filament_retraction_speed",
|
||||
"filament_deretraction_speed",
|
||||
"filament_retraction_minimum_travel",
|
||||
|
||||
@@ -1547,7 +1547,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionBool, gcode_add_line_number))
|
||||
((ConfigOptionBool, bbl_bed_temperature_gcode))
|
||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||
|
||||
((ConfigOptionBool, gcode_skip_config_block))
|
||||
((ConfigOptionFloat, time_cost))
|
||||
((ConfigOptionString, layer_change_gcode))
|
||||
((ConfigOptionString, time_lapse_gcode))
|
||||
|
||||
@@ -4756,7 +4756,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
deselect_all();
|
||||
}
|
||||
//BBS Select plate in this 3D canvas.
|
||||
else if (evt.LeftUp() && !m_mouse.dragging && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled())
|
||||
// The left up may come from an ImGui window (e.g. a drag started on the gizmo floating window and released over the bed),
|
||||
// in which case it must not be treated as a click on the plate, otherwise the gizmo would be closed (see deselect_all below).
|
||||
else if (evt.LeftUp() && !m_mouse.ignore_left_up && !m_mouse.dragging && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled())
|
||||
{
|
||||
int hover_idx = m_hover_plate_idxs.front();
|
||||
wxGetApp().plater()->select_plate_by_hover_id(hover_idx);
|
||||
|
||||
@@ -1119,6 +1119,10 @@ public:
|
||||
|
||||
void set_mouse_as_dragging() { m_mouse.dragging = true; }
|
||||
bool is_mouse_dragging() const { return m_mouse.dragging; }
|
||||
// True when the current left up event comes from an ImGui window and was not processed by it
|
||||
// (e.g. a drag that started on a gizmo floating window and was released over the 3D scene).
|
||||
// Such a release is the end of an ImGui interaction, not a click on the scene.
|
||||
bool is_mouse_left_up_ignored() const { return m_mouse.ignore_left_up; }
|
||||
|
||||
double get_size_proportional_to_max_bed_size(double factor) const;
|
||||
|
||||
|
||||
@@ -256,18 +256,18 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
||||
}
|
||||
}
|
||||
|
||||
void show_error(wxWindow* parent, const wxString& message, bool monospaced_font)
|
||||
void show_error(wxWindow* parent, const wxString& message, bool has_code_excerpts)
|
||||
{
|
||||
wxGetApp().CallAfter([=] {
|
||||
ErrorDialog msg(parent, message, monospaced_font);
|
||||
ErrorDialog msg(parent, message, has_code_excerpts);
|
||||
msg.ShowModal();
|
||||
});
|
||||
}
|
||||
|
||||
void show_error(wxWindow* parent, const char* message, bool monospaced_font)
|
||||
void show_error(wxWindow* parent, const char* message, bool has_code_excerpts)
|
||||
{
|
||||
assert(message);
|
||||
show_error(parent, wxString::FromUTF8(message), monospaced_font);
|
||||
show_error(parent, wxString::FromUTF8(message), has_code_excerpts);
|
||||
}
|
||||
|
||||
void show_error_id(int id, const std::string& message)
|
||||
|
||||
@@ -40,11 +40,11 @@ extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_
|
||||
// Change option value in config
|
||||
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0);
|
||||
|
||||
// If monospaced_font is true, the error message is displayed using html <code><pre></pre></code> tags,
|
||||
// so that the code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||
void show_error(wxWindow* parent, const wxString& message, bool monospaced_font = false);
|
||||
void show_error(wxWindow* parent, const char* message, bool monospaced_font = false);
|
||||
inline void show_error(wxWindow* parent, const std::string& message, bool monospaced_font = false) { show_error(parent, message.c_str(), monospaced_font); }
|
||||
// If has_code_excerpts is true, code excerpts (a source line and the caret line below it) render
|
||||
// monospaced so the caret aligns. Used for placeholder-parser errors.
|
||||
void show_error(wxWindow* parent, const wxString& message, bool has_code_excerpts = false);
|
||||
void show_error(wxWindow* parent, const char* message, bool has_code_excerpts = false);
|
||||
inline void show_error(wxWindow* parent, const std::string& message, bool has_code_excerpts = false) { show_error(parent, message.c_str(), has_code_excerpts); }
|
||||
void show_error_id(int id, const std::string& message); // For Perl
|
||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title = wxString());
|
||||
void show_info(wxWindow* parent, const char* message, const char* title = nullptr);
|
||||
|
||||
@@ -113,14 +113,7 @@ public:
|
||||
update_dark_ui(this);
|
||||
#endif
|
||||
|
||||
// Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
|
||||
// So, calculate the m_em_unit value from the font size, as before
|
||||
#if !defined(__WXGTK__)
|
||||
m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor);
|
||||
#else
|
||||
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
|
||||
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
|
||||
#endif // __WXGTK__
|
||||
update_em_unit();
|
||||
|
||||
// recalc_font();
|
||||
|
||||
@@ -235,6 +228,19 @@ private:
|
||||
// m_em_unit = metrics.averageWidth;
|
||||
// }
|
||||
|
||||
// update em_unit value for new window font
|
||||
void update_em_unit()
|
||||
{
|
||||
// Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
|
||||
// So, calculate the m_em_unit value from the font size, as before
|
||||
#if !defined(__WXGTK__)
|
||||
m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor);
|
||||
#else
|
||||
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
|
||||
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
|
||||
#endif // __WXGTK__
|
||||
}
|
||||
|
||||
// check if new scale is differ from previous
|
||||
bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }
|
||||
|
||||
@@ -247,8 +253,7 @@ private:
|
||||
// set normal application font as a current window font
|
||||
m_normal_font = this->GetFont();
|
||||
|
||||
// update em_unit value for new window font
|
||||
m_em_unit = std::max<int>(10, 10.0f * m_scale_factor);
|
||||
update_em_unit();
|
||||
|
||||
// rescale missed controls sizes and images
|
||||
on_dpi_changed(suggested_rect);
|
||||
|
||||
@@ -566,8 +566,11 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
||||
|
||||
void GLGizmoEmboss::on_mouse_change_selection(const wxMouseEvent &mouse_event)
|
||||
{
|
||||
static bool was_dragging = true;
|
||||
if ((mouse_event.LeftUp() || mouse_event.RightUp()) && !was_dragging) {
|
||||
static bool was_dragging = true;
|
||||
// The left up may be the end of a drag that started on the gizmo floating window (e.g. selecting
|
||||
// text in the input field). Such a release is not a click on the scene and must not close the gizmo.
|
||||
// (The flag is only set for left up events, so right up behavior is unchanged.)
|
||||
if ((mouse_event.LeftUp() || mouse_event.RightUp()) && !was_dragging && !m_parent.is_mouse_left_up_ignored()) {
|
||||
// is hovered volume closest hovered?
|
||||
int hovered_idx = m_parent.get_first_hover_volume_idx();
|
||||
if (hovered_idx < 0)
|
||||
|
||||
+106
-18
@@ -9,8 +9,13 @@
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/html/winpars.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
@@ -229,12 +234,82 @@ void MsgDialog::finalize()
|
||||
}
|
||||
|
||||
|
||||
// A placeholder-parser caret line, pointing at the column where parsing failed.
|
||||
static bool is_caret_line(const std::string &line)
|
||||
{
|
||||
return std::count(line.begin(), line.end(), '^') == 1 &&
|
||||
std::all_of(line.begin(), line.end(), [](char c) { return c == ' ' || c == '^'; });
|
||||
}
|
||||
|
||||
// Tag each line as a code excerpt (a caret line or the source line above one) that must stay
|
||||
// monospaced for the '^' to align.
|
||||
static std::vector<std::pair<std::string, bool>> classify_code_lines(const std::string &msg)
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
boost::split(lines, msg, boost::is_any_of("\n"));
|
||||
for (std::string &line : lines)
|
||||
if (!line.empty() && line.back() == '\r')
|
||||
line.pop_back();
|
||||
|
||||
std::vector<std::pair<std::string, bool>> tagged;
|
||||
tagged.reserve(lines.size());
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
bool is_code = is_caret_line(lines[i]) || (i + 1 < lines.size() && is_caret_line(lines[i + 1]));
|
||||
tagged.emplace_back(std::move(lines[i]), is_code);
|
||||
}
|
||||
return tagged;
|
||||
}
|
||||
|
||||
// Keeps whitespace literal so the caret's leading spaces survive.
|
||||
// Used inside <code>, which supplies the fixed face. <pre> does both but adds a blank line above it.
|
||||
class CodeExcerptTagHandler : public wxHtmlWinTagHandler
|
||||
{
|
||||
public:
|
||||
wxString GetSupportedTags() override { return wxT("EXCERPT"); }
|
||||
bool HandleTag(const wxHtmlTag &tag) override
|
||||
{
|
||||
const wxHtmlWinParser::WhitespaceMode ws = m_WParser->GetWhitespaceMode();
|
||||
m_WParser->SetWhitespaceMode(wxHtmlWinParser::Whitespace_Pre);
|
||||
ParseInner(tag);
|
||||
m_WParser->SetWhitespaceMode(ws);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Render the message as HTML, monospacing only the code excerpts.
|
||||
static std::string format_parser_error_html(const std::string &msg)
|
||||
{
|
||||
std::string out;
|
||||
for (const auto &[text, is_code] : classify_code_lines(msg)) {
|
||||
if (!out.empty()) out += "<br>"; // join, not trail; a trailing <br> forces a scrollbar
|
||||
std::string escaped = xml_escape(text);
|
||||
if (is_code)
|
||||
out += "<code><excerpt>" + escaped + "</excerpt></code>";
|
||||
else
|
||||
out += escaped;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Measure each line in the font it will render in, so the dialog fits the longest line without slack.
|
||||
static wxSize measure_mixed_text(wxWindow *parent, const std::string &msg, const wxFont &prose_font, const wxFont &code_font)
|
||||
{
|
||||
wxClientDC dc(parent);
|
||||
int width = 0, height = 0;
|
||||
for (const auto &[text, is_code] : classify_code_lines(msg)) {
|
||||
dc.SetFont(is_code ? code_font : prose_font);
|
||||
width = std::max(width, dc.GetTextExtent(wxString::FromUTF8(text.c_str())).GetWidth());
|
||||
height += dc.GetCharHeight();
|
||||
}
|
||||
return wxSize(width, height);
|
||||
}
|
||||
|
||||
// Text shown as HTML, so that mouse selection and Ctrl-V to copy will work.
|
||||
static void add_msg_content(wxWindow *parent,
|
||||
wxBoxSizer *content_sizer,
|
||||
wxString msg,
|
||||
bool monospaced_font = false,
|
||||
bool is_marked_msg = false,
|
||||
bool has_code_excerpts = false,
|
||||
bool is_marked_msg = false,
|
||||
const wxString &link_text = "",
|
||||
std::function<void(const wxString &)> link_callback = nullptr)
|
||||
{
|
||||
@@ -243,7 +318,7 @@ static void add_msg_content(wxWindow *parent,
|
||||
|
||||
// count lines in the message
|
||||
int msg_lines = 0;
|
||||
if (!monospaced_font) {
|
||||
if (!has_code_excerpts) {
|
||||
int line_len = 55;// count of symbols in one line
|
||||
int start_line = 0;
|
||||
for (auto i = msg.begin(); i != msg.end(); ++i) {
|
||||
@@ -300,13 +375,23 @@ static void add_msg_content(wxWindow *parent,
|
||||
page_size = wxSize(info_width, page_height);
|
||||
}
|
||||
else {
|
||||
wxClientDC dc(parent);
|
||||
dc.SetFont(font); // ORCA without this it calculates bigger size
|
||||
wxSize msg_sz = dc.GetMultiLineTextExtent(msg) + parent->FromDIP(wxSize(10,5)); // added extra spacing to prevent wrapping
|
||||
wxSize msg_sz;
|
||||
if (has_code_excerpts) {
|
||||
msg_sz = measure_mixed_text(parent, msg.ToUTF8().data(), font, monospace);
|
||||
} else {
|
||||
wxClientDC dc(parent);
|
||||
dc.SetFont(font); // ORCA without this it calculates bigger size
|
||||
msg_sz = dc.GetMultiLineTextExtent(msg);
|
||||
}
|
||||
msg_sz += parent->FromDIP(wxSize(10,5)); // added extra spacing to prevent wrapping
|
||||
|
||||
page_size = wxSize(std::min(msg_sz.GetX(), info_width), std::min(msg_sz.GetY(), info_width));
|
||||
int page_height = msg_sz.GetY();
|
||||
// Reserve the horizontal scrollbar's height, or it clips the last line.
|
||||
if (msg_sz.GetX() > info_width)
|
||||
page_height += wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y, parent);
|
||||
page_size = wxSize(std::min(msg_sz.GetX(), info_width), std::min(page_height, info_width));
|
||||
// Extra line breaks in message dialog
|
||||
if (link_text.IsEmpty() && !link_callback && is_marked_msg == false) {//for common text
|
||||
if (link_text.IsEmpty() && !link_callback && is_marked_msg == false && !has_code_excerpts) {//for common text
|
||||
html->Destroy();
|
||||
if (msg_sz.GetX() < info_width) {//No need for line breaks
|
||||
info_width = msg_sz.GetX();
|
||||
@@ -337,12 +422,15 @@ static void add_msg_content(wxWindow *parent,
|
||||
}
|
||||
html->SetMinSize(page_size);
|
||||
|
||||
std::string msg_escaped = xml_escape(msg.ToUTF8().data(), is_marked_msg);
|
||||
boost::replace_all(msg_escaped, "\r\n", "<br>");
|
||||
boost::replace_all(msg_escaped, "\n", "<br>");
|
||||
if (monospaced_font)
|
||||
// Code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||
msg_escaped = std::string("<pre><code>") + msg_escaped + "</code></pre>";
|
||||
std::string msg_escaped;
|
||||
if (has_code_excerpts) {
|
||||
html->GetParser()->AddTagHandler(new CodeExcerptTagHandler());
|
||||
msg_escaped = format_parser_error_html(msg.ToUTF8().data());
|
||||
} else {
|
||||
msg_escaped = xml_escape(msg.ToUTF8().data(), is_marked_msg);
|
||||
boost::replace_all(msg_escaped, "\r\n", "<br>");
|
||||
boost::replace_all(msg_escaped, "\n", "<br>");
|
||||
}
|
||||
|
||||
if (!link_text.IsEmpty() && link_callback) {
|
||||
msg_escaped += "<span><a href=\"#\" style=\"color:rgb(0, 150, 136); text-decoration:underline;\">" + std::string(link_text.ToUTF8().data()) + "</a></span>";
|
||||
@@ -360,15 +448,15 @@ static void add_msg_content(wxWindow *parent,
|
||||
|
||||
// ErrorDialog
|
||||
|
||||
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &temp_msg, bool monospaced_font)
|
||||
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &temp_msg, bool has_code_excerpts)
|
||||
: MsgDialog(parent, wxString::Format(_(L("%s error")), SLIC3R_APP_FULL_NAME),
|
||||
wxString::Format(_(L("%s has encountered an error")), SLIC3R_APP_FULL_NAME), wxOK)
|
||||
, msg(temp_msg)
|
||||
{
|
||||
add_msg_content(this, content_sizer, msg, monospaced_font);
|
||||
add_msg_content(this, content_sizer, msg, has_code_excerpts);
|
||||
|
||||
// Use a small bitmap with monospaced font, as the error text will not be wrapped.
|
||||
logo->SetBitmap(create_scaled_bitmap("OrcaSlicer_192px_grayscale.png", this, monospaced_font ? 48 : /*1*/64));
|
||||
// Use a small bitmap for code excerpts, which cannot wrap and so need the width.
|
||||
logo->SetBitmap(create_scaled_bitmap("OrcaSlicer_192px_grayscale.png", this, has_code_excerpts ? 48 : /*1*/64));
|
||||
|
||||
SetMaxSize(MSG_DLG_MAX_SIZE);
|
||||
|
||||
|
||||
@@ -106,9 +106,9 @@ protected:
|
||||
class ErrorDialog : public MsgDialog
|
||||
{
|
||||
public:
|
||||
// If monospaced_font is true, the error message is displayed using html <code><pre></pre></code> tags,
|
||||
// so that the code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||
ErrorDialog(wxWindow *parent, const wxString &temp_msg, bool courier_font);
|
||||
// If has_code_excerpts is true, code excerpts (a source line and the caret line below it) render
|
||||
// monospaced so the caret aligns. Used for placeholder-parser errors.
|
||||
ErrorDialog(wxWindow *parent, const wxString &temp_msg, bool has_code_excerpts);
|
||||
ErrorDialog(ErrorDialog &&) = delete;
|
||||
ErrorDialog(const ErrorDialog &) = delete;
|
||||
ErrorDialog &operator=(ErrorDialog &&) = delete;
|
||||
|
||||
+18
-8
@@ -3078,7 +3078,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("combine_brims", "others_settings_brim#combine-brims");
|
||||
optgroup->append_single_option_line("brim_ears_max_angle", "others_settings_brim#ear-max-angle");
|
||||
optgroup->append_single_option_line("brim_ears_detection_length", "others_settings_brim#ear-detection-radius");
|
||||
optgroup->append_single_option_line("brim_ears_outer_only");
|
||||
optgroup->append_single_option_line("brim_ears_outer_only", "others_settings_brim#brim-ears-outer-only");
|
||||
|
||||
optgroup = page->new_optgroup(L("Special mode"), L"param_special");
|
||||
optgroup->append_single_option_line("slicing_mode", "others_settings_special_mode#slicing-mode");
|
||||
@@ -4007,13 +4007,12 @@ void TabFilament::add_filament_overrides_page()
|
||||
|
||||
const int extruder_idx = 0; // #ys_FIXME
|
||||
|
||||
ConfigOptionsGroupShp retraction_optgroup = page->new_optgroup(L("Retraction"), L"param_retraction");
|
||||
auto append_retraction_option = [this, retraction_optgroup](const std::string& opt_key, int opt_index)
|
||||
auto append_retraction_option = [this](ConfigOptionsGroupShp optgroup, const std::string& opt_key, int opt_index)
|
||||
{
|
||||
Line line {"",""};
|
||||
line = retraction_optgroup->create_single_option_line(retraction_optgroup->get_option(opt_key, opt_index));
|
||||
line = optgroup->create_single_option_line(optgroup->get_option(opt_key, opt_index));
|
||||
|
||||
line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(retraction_optgroup), opt_key, opt_index](wxWindow* parent) {
|
||||
line.near_label_widget = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup), opt_key, opt_index](wxWindow* parent) {
|
||||
auto check_box = new ::CheckBox(parent); // ORCA modernize checkboxes
|
||||
check_box->Bind(wxEVT_TOGGLEBUTTON, [this, optgroup_wk, opt_key, opt_index](wxCommandEvent& evt) {
|
||||
const bool is_checked = evt.IsChecked();
|
||||
@@ -4040,9 +4039,10 @@ void TabFilament::add_filament_overrides_page()
|
||||
return check_box;
|
||||
};
|
||||
|
||||
retraction_optgroup->append_line(line);
|
||||
optgroup->append_line(line);
|
||||
};
|
||||
|
||||
ConfigOptionsGroupShp retraction_optgroup = page->new_optgroup(L("Retraction"), L"param_retraction");
|
||||
for (const std::string opt_key : { "filament_retraction_length",
|
||||
"filament_z_hop",
|
||||
"filament_z_hop_types",
|
||||
@@ -4066,7 +4066,13 @@ void TabFilament::add_filament_overrides_page()
|
||||
//SoftFever
|
||||
// "filament_seam_gap"
|
||||
})
|
||||
append_retraction_option(opt_key, extruder_idx);
|
||||
append_retraction_option(retraction_optgroup, opt_key, extruder_idx);
|
||||
|
||||
ConfigOptionsGroupShp toolchange_optgroup = page->new_optgroup(L("Retraction when switching material"), L"param_retraction_material_change");
|
||||
for (const std::string opt_key : { "filament_retract_length_toolchange",
|
||||
"filament_retract_restart_extra_toolchange"
|
||||
})
|
||||
append_retraction_option(toolchange_optgroup, opt_key, extruder_idx);
|
||||
|
||||
ConfigOptionsGroupShp ironing_optgroup = page->new_optgroup(L("Ironing"), L"param_ironing");
|
||||
auto append_ironing_option = [this, ironing_optgroup](const std::string& opt_key, int opt_index)
|
||||
@@ -4181,6 +4187,8 @@ void TabFilament::update_filament_overrides_page(const DynamicPrintConfig* print
|
||||
"filament_retraction_speed",
|
||||
"filament_deretraction_speed",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_length_toolchange",
|
||||
"filament_retract_restart_extra_toolchange",
|
||||
"filament_retraction_minimum_travel",
|
||||
"filament_retract_when_changing_layer",
|
||||
"filament_wipe",
|
||||
@@ -4211,7 +4219,8 @@ void TabFilament::update_filament_overrides_page(const DynamicPrintConfig* print
|
||||
is_checked &= !dynamic_cast<ConfigOptionVectorBase*>(m_config->option(opt_key))->is_nil(extruder_idx);
|
||||
m_overrides_options[opt_key]->SetValue(is_checked);
|
||||
|
||||
Field* field = optgroup->get_fieldc(opt_key, 0);
|
||||
// the toolchange overrides live in their own optgroup, so search the whole page
|
||||
Field* field = page->get_field(opt_key, 0);
|
||||
if (field == nullptr) continue;
|
||||
|
||||
if (opt_key == "filament_long_retractions_when_cut") {
|
||||
@@ -5017,6 +5026,7 @@ void TabPrinter::build_fff()
|
||||
|
||||
optgroup->append_single_option_line("printer_structure", "printer_basic_information_advanced#printer-structure");
|
||||
optgroup->append_single_option_line("gcode_flavor", "printer_basic_information_advanced#g-code-flavor");
|
||||
optgroup->append_single_option_line("gcode_skip_config_block", "printer_basic_information_advanced#skip-g-code-config-block");
|
||||
optgroup->append_single_option_line("pellet_modded_printer", "printer_basic_information_advanced#pellet-modded-printer");
|
||||
optgroup->append_single_option_line("bbl_use_printhost", "printer_basic_information_advanced#use-3rd-party-print-host");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user