mirror of
https://github.com/Dark98/SliceBeam.git
synced 2026-07-03 00:38:53 +00:00
Updated Config Handling
This commit is contained in:
@@ -258,7 +258,11 @@ public class FilamentConfigFragment extends ProfileListFragment {
|
||||
|
||||
@Override
|
||||
protected void onResetConfig() {
|
||||
currentConfig = new ConfigObject(Santoku.CONFIG.findFilament(Santoku.CONFIG.presets.get("filament")));
|
||||
ConfigObject base = Santoku.CONFIG.findFilament(Santoku.CONFIG.presets.get("filament"));
|
||||
if (base == null && Santoku.CONFIG.filamentConfigs != null && !Santoku.CONFIG.filamentConfigs.isEmpty()) {
|
||||
base = Santoku.CONFIG.filamentConfigs.get(0);
|
||||
}
|
||||
currentConfig = base != null ? new ConfigObject(base) : ConfigObject.createCustomFilamentProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <chrono>
|
||||
#include <math.h>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
@@ -105,6 +106,29 @@ namespace Slic3r {
|
||||
gcode += '\n';
|
||||
}
|
||||
|
||||
static std::string rewrite_simple_curly_placeholders_to_legacy(const std::string &templ)
|
||||
{
|
||||
// Convert {name} or {name[0]} to legacy [name] / [name_0].
|
||||
// Only touches simple, standalone placeholders to avoid breaking control macros.
|
||||
static const std::regex pattern(R"(\{([A-Za-z_][A-Za-z0-9_]*)(?:\[(\d+)\])?\})");
|
||||
std::string out;
|
||||
out.reserve(templ.size());
|
||||
size_t last_pos = 0;
|
||||
for (auto it = std::sregex_iterator(templ.begin(), templ.end(), pattern); it != std::sregex_iterator(); ++it) {
|
||||
const std::smatch &m = *it;
|
||||
out.append(templ, last_pos, m.position() - last_pos);
|
||||
const std::string &name = m[1].str();
|
||||
const std::string &idx = m[2].str();
|
||||
if (! idx.empty())
|
||||
out += "[" + name + "_" + idx + "]";
|
||||
else
|
||||
out += "[" + name + "]";
|
||||
last_pos = m.position() + m.length();
|
||||
}
|
||||
out.append(templ, last_pos, std::string::npos);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Return true if tch_prefix is found in custom_gcode
|
||||
static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder)
|
||||
{
|
||||
@@ -1087,6 +1111,8 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
|
||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||
m_placeholder_parser_integration.parser = print.placeholder_parser();
|
||||
// Ensure all print config options are available for { } placeholder expressions.
|
||||
m_placeholder_parser_integration.parser.apply_config(print.full_print_config());
|
||||
m_placeholder_parser_integration.parser.update_timestamp();
|
||||
m_placeholder_parser_integration.context.rng = std::mt19937(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||
// Enable passing global variables between PlaceholderParser invocations.
|
||||
@@ -1181,6 +1207,29 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
this->placeholder_parser().set("has_wipe_tower", has_wipe_tower);
|
||||
this->placeholder_parser().set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
||||
this->placeholder_parser().set("total_toolchanges", tool_ordering.toolchanges_count());
|
||||
{
|
||||
const DynamicPrintConfig &cfg = print.full_print_config();
|
||||
if (const ConfigOption *opt = cfg.optptr("first_layer_temperature")) {
|
||||
this->placeholder_parser().set("first_layer_temperature", opt->clone());
|
||||
} else {
|
||||
this->placeholder_parser().set("first_layer_temperature", new ConfigOptionInts(print.config().first_layer_temperature.values));
|
||||
}
|
||||
if (const ConfigOption *opt = cfg.optptr("temperature")) {
|
||||
this->placeholder_parser().set("temperature", opt->clone());
|
||||
} else {
|
||||
this->placeholder_parser().set("temperature", new ConfigOptionInts(print.config().temperature.values));
|
||||
}
|
||||
if (const ConfigOption *opt = cfg.optptr("first_layer_bed_temperature")) {
|
||||
this->placeholder_parser().set("first_layer_bed_temperature", opt->clone());
|
||||
} else {
|
||||
this->placeholder_parser().set("first_layer_bed_temperature", new ConfigOptionInts(print.config().first_layer_bed_temperature.values));
|
||||
}
|
||||
if (const ConfigOption *opt = cfg.optptr("chamber_temperature")) {
|
||||
this->placeholder_parser().set("chamber_temperature", opt->clone());
|
||||
} else {
|
||||
this->placeholder_parser().set("chamber_temperature", new ConfigOptionInts(print.config().chamber_temperature.values));
|
||||
}
|
||||
}
|
||||
{
|
||||
const char *bed_type_label = (print.config().elegoolink_bed_type.value == ElegooBedType::PTE) ? "Side A" : "Side B";
|
||||
this->placeholder_parser().set("curr_bed_type", new ConfigOptionString(bed_type_label));
|
||||
@@ -1214,7 +1263,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
this->placeholder_parser().set("print_bed_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
||||
this->placeholder_parser().set("print_bed_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
||||
}
|
||||
if (host_is_klipper) {
|
||||
{
|
||||
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
|
||||
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
|
||||
// It does NOT encompass user extrusions generated by custom G-code,
|
||||
@@ -1224,59 +1273,64 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
pts->values.reserve(print.first_layer_convex_hull().size());
|
||||
for (const Point &pt : print.first_layer_convex_hull().points)
|
||||
pts->values.emplace_back(unscale(pt));
|
||||
BoundingBoxf bbox(pts->values);
|
||||
BoundingBoxf first_layer_bbox(pts->values);
|
||||
this->placeholder_parser().set("first_layer_print_convex_hull", pts.release());
|
||||
this->placeholder_parser().set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
|
||||
this->placeholder_parser().set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
||||
this->placeholder_parser().set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
||||
this->placeholder_parser().set("first_layer_print_min", new ConfigOptionFloats({ first_layer_bbox.min.x(), first_layer_bbox.min.y() }));
|
||||
this->placeholder_parser().set("first_layer_print_max", new ConfigOptionFloats({ first_layer_bbox.max.x(), first_layer_bbox.max.y() }));
|
||||
this->placeholder_parser().set("first_layer_print_size", new ConfigOptionFloats({ first_layer_bbox.size().x(), first_layer_bbox.size().y() }));
|
||||
this->placeholder_parser().set("num_extruders", int(print.config().nozzle_diameter.values.size()));
|
||||
|
||||
BoundingBoxf bed_bbox(print.config().bed_shape.values);
|
||||
BoundingBoxf mesh_bbox = bbox;
|
||||
if (bed_bbox.defined) {
|
||||
const double margin = print.config().adaptive_bed_mesh_margin.value;
|
||||
double min_x = bbox.min.x() - margin;
|
||||
double min_y = bbox.min.y() - margin;
|
||||
double max_x = bbox.max.x() + margin;
|
||||
double max_y = bbox.max.y() + margin;
|
||||
if (host_is_klipper) {
|
||||
BoundingBoxf bed_bbox(print.config().bed_shape.values);
|
||||
BoundingBoxf mesh_bbox = first_layer_bbox;
|
||||
if (bed_bbox.defined) {
|
||||
const double margin = print.config().adaptive_bed_mesh_margin.value;
|
||||
double min_x = first_layer_bbox.min.x() - margin;
|
||||
double min_y = first_layer_bbox.min.y() - margin;
|
||||
double max_x = first_layer_bbox.max.x() + margin;
|
||||
double max_y = first_layer_bbox.max.y() + margin;
|
||||
|
||||
min_x = std::max(min_x, bed_bbox.min.x());
|
||||
min_y = std::max(min_y, bed_bbox.min.y());
|
||||
max_x = std::min(max_x, bed_bbox.max.x());
|
||||
max_y = std::min(max_y, bed_bbox.max.y());
|
||||
min_x = std::max(min_x, bed_bbox.min.x());
|
||||
min_y = std::max(min_y, bed_bbox.min.y());
|
||||
max_x = std::min(max_x, bed_bbox.max.x());
|
||||
max_y = std::min(max_y, bed_bbox.max.y());
|
||||
|
||||
const Vec2d limit_min = print.config().bed_mesh_limit_min.value;
|
||||
const Vec2d limit_max = print.config().bed_mesh_limit_max.value;
|
||||
if (limit_min.x() > -99998 || limit_min.y() > -99998) {
|
||||
min_x = std::max(min_x, limit_min.x());
|
||||
min_y = std::max(min_y, limit_min.y());
|
||||
}
|
||||
if (limit_max.x() > -99998 || limit_max.y() > -99998) {
|
||||
max_x = std::min(max_x, limit_max.x());
|
||||
max_y = std::min(max_y, limit_max.y());
|
||||
const Vec2d limit_min = print.config().bed_mesh_limit_min.value;
|
||||
const Vec2d limit_max = print.config().bed_mesh_limit_max.value;
|
||||
if (limit_min.x() > -99998 || limit_min.y() > -99998) {
|
||||
min_x = std::max(min_x, limit_min.x());
|
||||
min_y = std::max(min_y, limit_min.y());
|
||||
}
|
||||
if (limit_max.x() > -99998 || limit_max.y() > -99998) {
|
||||
max_x = std::min(max_x, limit_max.x());
|
||||
max_y = std::min(max_y, limit_max.y());
|
||||
}
|
||||
|
||||
mesh_bbox.min = Vec2d(min_x, min_y);
|
||||
mesh_bbox.max = Vec2d(max_x, max_y);
|
||||
}
|
||||
|
||||
mesh_bbox.min = Vec2d(min_x, min_y);
|
||||
mesh_bbox.max = Vec2d(max_x, max_y);
|
||||
adaptive_bed_mesh_min = mesh_bbox.min;
|
||||
adaptive_bed_mesh_max = mesh_bbox.max;
|
||||
adaptive_bed_mesh_ready = true;
|
||||
|
||||
this->placeholder_parser().set("adaptive_bed_mesh_min", new ConfigOptionFloats({ mesh_bbox.min.x(), mesh_bbox.min.y() }));
|
||||
this->placeholder_parser().set("adaptive_bed_mesh_max", new ConfigOptionFloats({ mesh_bbox.max.x(), mesh_bbox.max.y() }));
|
||||
|
||||
const Vec2d probe_dist = print.config().bed_mesh_probe_distance.value;
|
||||
const double probe_dist_x = std::max(1.0, probe_dist.x());
|
||||
const double probe_dist_y = std::max(1.0, probe_dist.y());
|
||||
const int probe_count_x = std::max(3, int(std::ceil(mesh_bbox.size().x() / probe_dist_x)) + 1);
|
||||
const int probe_count_y = std::max(3, int(std::ceil(mesh_bbox.size().y() / probe_dist_y)) + 1);
|
||||
adaptive_probe_count_x = probe_count_x;
|
||||
adaptive_probe_count_y = probe_count_y;
|
||||
this->placeholder_parser().set("bed_mesh_probe_count", new ConfigOptionInts({ probe_count_x, probe_count_y }));
|
||||
adaptive_bed_mesh_algo = (probe_count_x < 4 || probe_count_y < 4) ? "lagrange" : "bicubic";
|
||||
this->placeholder_parser().set("bed_mesh_algo", new ConfigOptionString(adaptive_bed_mesh_algo));
|
||||
}
|
||||
}
|
||||
|
||||
adaptive_bed_mesh_min = mesh_bbox.min;
|
||||
adaptive_bed_mesh_max = mesh_bbox.max;
|
||||
adaptive_bed_mesh_ready = true;
|
||||
|
||||
this->placeholder_parser().set("adaptive_bed_mesh_min", new ConfigOptionFloats({ mesh_bbox.min.x(), mesh_bbox.min.y() }));
|
||||
this->placeholder_parser().set("adaptive_bed_mesh_max", new ConfigOptionFloats({ mesh_bbox.max.x(), mesh_bbox.max.y() }));
|
||||
|
||||
const Vec2d probe_dist = print.config().bed_mesh_probe_distance.value;
|
||||
const double probe_dist_x = std::max(1.0, probe_dist.x());
|
||||
const double probe_dist_y = std::max(1.0, probe_dist.y());
|
||||
const int probe_count_x = std::max(3, int(std::ceil(mesh_bbox.size().x() / probe_dist_x)) + 1);
|
||||
const int probe_count_y = std::max(3, int(std::ceil(mesh_bbox.size().y() / probe_dist_y)) + 1);
|
||||
adaptive_probe_count_x = probe_count_x;
|
||||
adaptive_probe_count_y = probe_count_y;
|
||||
this->placeholder_parser().set("bed_mesh_probe_count", new ConfigOptionInts({ probe_count_x, probe_count_y }));
|
||||
adaptive_bed_mesh_algo = (probe_count_x < 4 || probe_count_y < 4) ? "lagrange" : "bicubic";
|
||||
this->placeholder_parser().set("bed_mesh_algo", new ConfigOptionString(adaptive_bed_mesh_algo));
|
||||
{
|
||||
// PlaceholderParser currently substitues non-existent vector values with the zero'th value, which is harmful in the case of "is_extruder_used[]"
|
||||
// as Slicer may lie about availability of such non-existent extruder.
|
||||
// We rather sacrifice 256B of memory before we change the behavior of the PlaceholderParser, which should really only fill in the non-existent
|
||||
@@ -1829,6 +1883,34 @@ std::string GCodeGenerator::placeholder_parser_process(
|
||||
}
|
||||
catch (std::runtime_error &err)
|
||||
{
|
||||
// Retry with legacy placeholders for simple {name} / {name[idx]} patterns.
|
||||
if (std::string(err.what()).find("Not a variable name") != std::string::npos) {
|
||||
const std::string compat_templ = rewrite_simple_curly_placeholders_to_legacy(templ);
|
||||
if (compat_templ != templ) {
|
||||
ppi.update_from_gcodewriter(m_writer, m_print->wipe_tower_data());
|
||||
std::string output = ppi.parser.process(compat_templ, current_extruder_id, config_override, &ppi.output_config, &ppi.context);
|
||||
ppi.validate_output_vector_variables();
|
||||
|
||||
if (const std::vector<double> &pos = ppi.opt_position->values; ppi.position != pos) {
|
||||
m_writer.update_position({ pos[0], pos[1], pos[2] });
|
||||
this->last_position = this->gcode_to_point({ pos[0], pos[1] });
|
||||
}
|
||||
|
||||
for (const Extruder &e : m_writer.extruders()) {
|
||||
unsigned int eid = e.id();
|
||||
assert(eid < ppi.num_extruders);
|
||||
if ( eid < ppi.num_extruders) {
|
||||
if (! m_writer.config.use_relative_e_distances && ! is_approx(ppi.e_position[eid], ppi.opt_e_position->values[eid]))
|
||||
const_cast<Extruder&>(e).set_position(ppi.opt_e_position->values[eid]);
|
||||
if (! is_approx(ppi.e_retracted[eid], ppi.opt_e_retracted->values[eid]) ||
|
||||
! is_approx(ppi.e_restart_extra[eid], ppi.opt_e_restart_extra->values[eid]))
|
||||
const_cast<Extruder&>(e).set_retracted(ppi.opt_e_retracted->values[eid], ppi.opt_e_restart_extra->values[eid]);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
// Collect the names of failed template substitutions for error reporting.
|
||||
auto it = ppi.failed_templates.find(name);
|
||||
if (it == ppi.failed_templates.end())
|
||||
|
||||
@@ -1022,6 +1022,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
|
||||
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
|
||||
m_placeholder_parser.set("physical_printer_preset", new_full_config.option("physical_printer_settings_id")->clone());
|
||||
// Make all config options available to the PlaceholderParser.
|
||||
m_placeholder_parser.apply_config(new_full_config);
|
||||
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
|
||||
// see "Placeholders do not respect filament overrides." GH issue #3649
|
||||
m_placeholder_parser.apply_config(filament_overrides);
|
||||
|
||||
Reference in New Issue
Block a user