mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 19:31:22 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c71ac0870 |
+4
-50
@@ -2116,12 +2116,7 @@ int CLI::run(int argc, char **argv)
|
|||||||
|
|
||||||
// One resolver for the whole run, so presets from the same vendor tree share its load.
|
// One resolver for the whole run, so presets from the same vendor tree share its load.
|
||||||
std::unique_ptr<PresetBundle> system_preset_resolver;
|
std::unique_ptr<PresetBundle> system_preset_resolver;
|
||||||
auto ensure_system_preset_resolver = [&system_preset_resolver]() -> PresetBundle & {
|
auto resolve_preset = [&ensure_cli_preset_bundle, &system_preset_resolver](const std::string &file, DynamicPrintConfig &config,
|
||||||
if (!system_preset_resolver)
|
|
||||||
system_preset_resolver = std::make_unique<PresetBundle>();
|
|
||||||
return *system_preset_resolver;
|
|
||||||
};
|
|
||||||
auto resolve_preset = [&ensure_cli_preset_bundle, &ensure_system_preset_resolver](const std::string &file, DynamicPrintConfig &config,
|
|
||||||
std::string &config_type, const std::string &config_from,
|
std::string &config_type, const std::string &config_from,
|
||||||
bool probe_type, std::string &error) {
|
bool probe_type, std::string &error) {
|
||||||
const auto *inherits = config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS);
|
const auto *inherits = config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS);
|
||||||
@@ -2131,7 +2126,9 @@ int CLI::run(int argc, char **argv)
|
|||||||
PresetBundle *bundle = nullptr;
|
PresetBundle *bundle = nullptr;
|
||||||
bool allow_source_manifest = false;
|
bool allow_source_manifest = false;
|
||||||
if (config_from == "system") {
|
if (config_from == "system") {
|
||||||
bundle = &ensure_system_preset_resolver();
|
if (!system_preset_resolver)
|
||||||
|
system_preset_resolver = std::make_unique<PresetBundle>();
|
||||||
|
bundle = system_preset_resolver.get();
|
||||||
allow_source_manifest = true;
|
allow_source_manifest = true;
|
||||||
} else {
|
} else {
|
||||||
bundle = ensure_cli_preset_bundle(error);
|
bundle = ensure_cli_preset_bundle(error);
|
||||||
@@ -3123,49 +3120,6 @@ int CLI::run(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A project saved before a printer or process option existed has no value for it. The GUI takes such
|
|
||||||
// keys from the project's system preset (load_external_preset refreshes every key the project did not
|
|
||||||
// override), so fill them from there too instead of leaving them to the option default.
|
|
||||||
// The extruder variant keys describe the project's variant layout and are kept as they are, so an
|
|
||||||
// older project is not left with a variant list from one layout and ids from another.
|
|
||||||
auto fill_missing_project_keys = [this, &ensure_system_preset_resolver](const std::string &system_name, Preset::Type type) {
|
|
||||||
if (system_name.empty())
|
|
||||||
return;
|
|
||||||
static const std::set<std::string> skip_keys = {
|
|
||||||
"inherits", "compatible_printers", "compatible_prints", "compatible_printers_condition", "compatible_prints_condition",
|
|
||||||
"print_settings_id", "filament_settings_id", "printer_settings_id",
|
|
||||||
"print_host", "print_host_webui", "printhost_apikey", "printhost_cafile", "printhost_user", "printhost_password", "printhost_port",
|
|
||||||
"printer_extruder_id", "printer_extruder_variant", "print_extruder_id", "print_extruder_variant", "extruder_variant_list"};
|
|
||||||
const std::vector<std::string> &options = type == Preset::TYPE_PRINTER ? Preset::printer_options() : Preset::print_options();
|
|
||||||
// Keys the legacy handler drops on load can never be in a project, so they do not count as missing.
|
|
||||||
auto dropped_on_load = [](std::string key) {
|
|
||||||
std::string value;
|
|
||||||
PrintConfigDef::handle_legacy(key, value);
|
|
||||||
return key.empty();
|
|
||||||
};
|
|
||||||
std::vector<std::string> missing;
|
|
||||||
for (const std::string &key : options)
|
|
||||||
if (m_print_config.option(key) == nullptr && skip_keys.count(key) == 0 && !dropped_on_load(key))
|
|
||||||
missing.push_back(key);
|
|
||||||
if (missing.empty())
|
|
||||||
return;
|
|
||||||
DynamicPrintConfig system_config;
|
|
||||||
std::string error;
|
|
||||||
if (!ensure_system_preset_resolver().resolve_system_preset(system_config, type, system_name, config_substitution_rule, error)) {
|
|
||||||
BOOST_LOG_TRIVIAL(warning) << boost::format("CLI: system preset '%1%' not resolved (%2%); keys missing from the project keep their defaults") % system_name % error;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const std::string &key : missing)
|
|
||||||
if (const ConfigOption *opt = system_config.option(key)) {
|
|
||||||
m_print_config.set_key_value(key, opt->clone());
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("CLI: %1% missing from the project, taken from '%2%': %3%") % key % system_name % opt->serialize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (new_printer_name.empty())
|
|
||||||
fill_missing_project_keys(current_printer_system_name, Preset::TYPE_PRINTER);
|
|
||||||
if (new_process_name.empty())
|
|
||||||
fill_missing_project_keys(current_process_system_name, Preset::TYPE_PRINT);
|
|
||||||
|
|
||||||
std::vector<std::string>& different_settings = m_print_config.option<ConfigOptionStrings>("different_settings_to_system", true)->values;
|
std::vector<std::string>& different_settings = m_print_config.option<ConfigOptionStrings>("different_settings_to_system", true)->values;
|
||||||
std::vector<std::string>& inherits_group = m_print_config.option<ConfigOptionStrings>("inherits_group", true)->values;
|
std::vector<std::string>& inherits_group = m_print_config.option<ConfigOptionStrings>("inherits_group", true)->values;
|
||||||
inherits_group.resize(filament_count + 2, std::string());
|
inherits_group.resize(filament_count + 2, std::string());
|
||||||
|
|||||||
@@ -1692,9 +1692,9 @@ void Layer::make_ironing()
|
|||||||
ironing_params.just_infill = false;
|
ironing_params.just_infill = false;
|
||||||
// ORCA: Get filament-specific overrides if configured, otherwise use process values
|
// ORCA: Get filament-specific overrides if configured, otherwise use process values
|
||||||
size_t extruder_idx = ironing_params.extruder - 1;
|
size_t extruder_idx = ironing_params.extruder - 1;
|
||||||
ironing_params.line_spacing = (!config.filament_ironing_spacing.is_nil(extruder_idx)
|
ironing_params.line_spacing = std::max(IRONING_SPACING_MIN, !config.filament_ironing_spacing.is_nil(extruder_idx)
|
||||||
? config.filament_ironing_spacing.get_at(extruder_idx)
|
? config.filament_ironing_spacing.get_at(extruder_idx)
|
||||||
: config.ironing_spacing);
|
: config.ironing_spacing.value);
|
||||||
ironing_params.inset = (!config.filament_ironing_inset.is_nil(extruder_idx)
|
ironing_params.inset = (!config.filament_ironing_inset.is_nil(extruder_idx)
|
||||||
? config.filament_ironing_inset.get_at(extruder_idx)
|
? config.filament_ironing_inset.get_at(extruder_idx)
|
||||||
: config.ironing_inset);
|
: config.ironing_inset);
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ void FillConcentric::_fill_surface_single(
|
|||||||
|
|
||||||
coord_t min_spacing = scale_(this->spacing) * params.multiline;
|
coord_t min_spacing = scale_(this->spacing) * params.multiline;
|
||||||
coord_t distance = coord_t(min_spacing / params.density);
|
coord_t distance = coord_t(min_spacing / params.density);
|
||||||
|
// A non-positive step never shrinks the region, so the inset loop below would not end.
|
||||||
|
if (min_spacing <= 0 || distance <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance);
|
distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance);
|
||||||
@@ -108,6 +111,8 @@ void FillConcentric::_fill_surface_single(const FillParams& params,
|
|||||||
// no rotation is supported for this infill pattern
|
// no rotation is supported for this infill pattern
|
||||||
Point bbox_size = expolygon.contour.bounding_box().size();
|
Point bbox_size = expolygon.contour.bounding_box().size();
|
||||||
coord_t min_spacing = scaled<coord_t>(this->spacing);
|
coord_t min_spacing = scaled<coord_t>(this->spacing);
|
||||||
|
if (min_spacing <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / min_spacing + 1;
|
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / min_spacing + 1;
|
||||||
|
|||||||
@@ -575,20 +575,18 @@ bool PresetBundle::resolve_preset_config(DynamicPrintConfig &config, Preset::Typ
|
|||||||
const PresetBundle *PresetBundle::load_source_vendor(const boost::filesystem::path &root_dir,
|
const PresetBundle *PresetBundle::load_source_vendor(const boost::filesystem::path &root_dir,
|
||||||
const std::string &vendor_id,
|
const std::string &vendor_id,
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||||
std::string &error, bool allow_cache)
|
std::string &error)
|
||||||
{
|
{
|
||||||
auto key = std::make_tuple(root_dir.string(), vendor_id, compatibility_rule, allow_cache);
|
auto key = std::make_tuple(root_dir.string(), vendor_id, compatibility_rule);
|
||||||
if (auto it = m_source_vendor_bundles.find(key); it != m_source_vendor_bundles.end())
|
if (auto it = m_source_vendor_bundles.find(key); it != m_source_vendor_bundles.end())
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
|
|
||||||
// The library loads with no base of its own, so the tree a vendor inherits from
|
// The library loads with no base of its own, so the tree a vendor inherits from
|
||||||
// is the same one that resolves the library's own presets.
|
// is the same one that resolves the library's own presets.
|
||||||
const std::string library_file = std::string(ORCA_FILAMENT_LIBRARY);
|
|
||||||
const PresetBundle *library = nullptr;
|
const PresetBundle *library = nullptr;
|
||||||
if (vendor_id != ORCA_FILAMENT_LIBRARY &&
|
if (vendor_id != ORCA_FILAMENT_LIBRARY &&
|
||||||
(boost::filesystem::is_regular_file(root_dir / (library_file + ".json")) ||
|
boost::filesystem::is_regular_file(root_dir / (std::string(ORCA_FILAMENT_LIBRARY) + ".json"))) {
|
||||||
(allow_cache && boost::filesystem::is_regular_file(root_dir / (library_file + ".opc"))))) {
|
library = load_source_vendor(root_dir, ORCA_FILAMENT_LIBRARY, compatibility_rule, error);
|
||||||
library = load_source_vendor(root_dir, ORCA_FILAMENT_LIBRARY, compatibility_rule, error, allow_cache);
|
|
||||||
if (library == nullptr) {
|
if (library == nullptr) {
|
||||||
error = "OrcaFilamentLibrary contains invalid presets";
|
error = "OrcaFilamentLibrary contains invalid presets";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -597,7 +595,7 @@ const PresetBundle *PresetBundle::load_source_vendor(const boost::filesystem::pa
|
|||||||
|
|
||||||
auto bundle = std::make_unique<PresetBundle>();
|
auto bundle = std::make_unique<PresetBundle>();
|
||||||
bundle->m_preserve_vendor_source_paths = true;
|
bundle->m_preserve_vendor_source_paths = true;
|
||||||
bundle->load_vendor_configs_from_json(root_dir.string(), vendor_id, LoadSystem, compatibility_rule, library, allow_cache);
|
bundle->load_vendor_configs_from_json(root_dir.string(), vendor_id, LoadSystem, compatibility_rule, library, false);
|
||||||
if (bundle->error_count() != 0) {
|
if (bundle->error_count() != 0) {
|
||||||
error = "Vendor bundle contains invalid presets";
|
error = "Vendor bundle contains invalid presets";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -640,43 +638,6 @@ bool PresetBundle::resolve_preset_config_type(DynamicPrintConfig &config, Preset
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PresetBundle::resolve_system_preset(DynamicPrintConfig &config, Preset::Type type, const std::string &name,
|
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule, std::string &error)
|
|
||||||
{
|
|
||||||
const std::string vendor_id = find_preset_vendor(name, type);
|
|
||||||
if (vendor_id.empty()) {
|
|
||||||
error = "No vendor lists the preset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Release builds ship a vendor as its preset cache alone, without the profile JSONs.
|
|
||||||
auto installed = [&vendor_id](const fs::path &root) {
|
|
||||||
return fs::is_regular_file(root / (vendor_id + ".json")) || fs::is_regular_file(root / (vendor_id + ".opc"));
|
|
||||||
};
|
|
||||||
fs::path root_dir = fs::path(data_dir()) / PRESET_SYSTEM_DIR;
|
|
||||||
if (!installed(root_dir))
|
|
||||||
root_dir = fs::path(resources_dir()) / PRESET_PROFILES_DIR;
|
|
||||||
const bool cache_only = !fs::is_regular_file(root_dir / (vendor_id + ".json"));
|
|
||||||
|
|
||||||
try {
|
|
||||||
const PresetBundle *vendor = load_source_vendor(root_dir, vendor_id, compatibility_rule, error, cache_only);
|
|
||||||
if (vendor == nullptr)
|
|
||||||
return false;
|
|
||||||
const PresetCollection &collection = type == Preset::TYPE_PRINTER ? vendor->printers :
|
|
||||||
type == Preset::TYPE_PRINT ? vendor->prints : vendor->filaments;
|
|
||||||
const Preset *preset = collection.find_preset(name, false);
|
|
||||||
if (preset == nullptr) {
|
|
||||||
error = "Preset was not found in its vendor bundle";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
config = preset->config;
|
|
||||||
} catch (const std::exception &ex) {
|
|
||||||
error = ex.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
error.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresetBundle::PresetBundle(const PresetBundle &rhs)
|
PresetBundle::PresetBundle(const PresetBundle &rhs)
|
||||||
{
|
{
|
||||||
*this = rhs;
|
*this = rhs;
|
||||||
|
|||||||
@@ -273,10 +273,6 @@ public:
|
|||||||
const std::string &source_file,
|
const std::string &source_file,
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||||
std::string &error, bool allow_source_manifest = true);
|
std::string &error, bool allow_source_manifest = true);
|
||||||
// Resolve a system preset by name. The vendor tree is read from data_dir()/system when installed
|
|
||||||
// there, as the GUI reads it, and from the bundled profiles otherwise.
|
|
||||||
bool resolve_system_preset(DynamicPrintConfig &config, Preset::Type type, const std::string &name,
|
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule, std::string &error);
|
|
||||||
|
|
||||||
// Load selections (current print, current filaments, current printer) from config.ini
|
// Load selections (current print, current filaments, current printer) from config.ini
|
||||||
// This is done just once on application start up.
|
// This is done just once on application start up.
|
||||||
@@ -667,14 +663,13 @@ private:
|
|||||||
// Vendor trees loaded by resolve_preset_config's manifest path, so every preset
|
// Vendor trees loaded by resolve_preset_config's manifest path, so every preset
|
||||||
// resolved through this bundle shares one load per source root and vendor. The
|
// resolved through this bundle shares one load per source root and vendor. The
|
||||||
// filament library is one such tree, shared by every vendor under its root.
|
// filament library is one such tree, shared by every vendor under its root.
|
||||||
// A tree read from its preset cache is kept apart: its presets carry no source file.
|
std::map<std::tuple<std::string, std::string, ForwardCompatibilitySubstitutionRule>, std::unique_ptr<PresetBundle>>
|
||||||
std::map<std::tuple<std::string, std::string, ForwardCompatibilitySubstitutionRule, bool>, std::unique_ptr<PresetBundle>>
|
|
||||||
m_source_vendor_bundles;
|
m_source_vendor_bundles;
|
||||||
|
|
||||||
const PresetBundle *load_source_vendor(const boost::filesystem::path &root_dir,
|
const PresetBundle *load_source_vendor(const boost::filesystem::path &root_dir,
|
||||||
const std::string &vendor_id,
|
const std::string &vendor_id,
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||||
std::string &error, bool allow_cache = false);
|
std::string &error);
|
||||||
|
|
||||||
// Orca: validation only - flag any printer with two or more compatible
|
// Orca: validation only - flag any printer with two or more compatible
|
||||||
// filament presets sharing one filament_id (ambiguous AMS subtype match).
|
// filament presets sharing one filament_id (ambiguous AMS subtype match).
|
||||||
|
|||||||
@@ -178,6 +178,10 @@ enum class IroningType {
|
|||||||
Count,
|
Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Smallest usable ironing line spacing. Anything tighter yields an unprintable number of lines,
|
||||||
|
// and zero stops the fillers from making progress.
|
||||||
|
constexpr double IRONING_SPACING_MIN = 0.05;
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
enum class WallInfillOrder {
|
enum class WallInfillOrder {
|
||||||
InnerOuterInfill,
|
InnerOuterInfill,
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ struct SupportParameters {
|
|||||||
|
|
||||||
this->ironing = object_config.support_ironing;
|
this->ironing = object_config.support_ironing;
|
||||||
this->ironing_flow = support_material_interface_flow.with_height(support_material_interface_flow.height() * 0.01 * object_config.support_ironing_flow.value);
|
this->ironing_flow = support_material_interface_flow.with_height(support_material_interface_flow.height() * 0.01 * object_config.support_ironing_flow.value);
|
||||||
this->ironing_spacing = object_config.support_ironing_spacing;
|
this->ironing_spacing = std::max(IRONING_SPACING_MIN, object_config.support_ironing_spacing.value);
|
||||||
this->ironing_pattern = object_config.support_ironing_pattern;
|
this->ironing_pattern = object_config.support_ironing_pattern;
|
||||||
|
|
||||||
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ static const char* Segments_Vertex_Shader =
|
|||||||
// ORCA: 0 during the shadow caster pass - the bias below shifts eye_position but not
|
// ORCA: 0 during the shadow caster pass - the bias below shifts eye_position but not
|
||||||
// world_position, so the caster would write a depth the receiver never looks up.
|
// world_position, so the caster would write a depth the receiver never looks up.
|
||||||
"uniform float bias_scale;\n"
|
"uniform float bias_scale;\n"
|
||||||
// draw the instances last to first, top layers before the ones they hide, so that early depth
|
|
||||||
// rejection discards most of the hidden fragments; set when the camera looks down on the print
|
|
||||||
"uniform int reverse_order;\n"
|
|
||||||
"uniform int instance_count;\n"
|
|
||||||
"in int vertex_id;\n"
|
"in int vertex_id;\n"
|
||||||
"out vec3 color;\n"
|
"out vec3 color;\n"
|
||||||
"// ORCA: realistic view - the light the shadow map is able to block, kept apart from the\n"
|
"// ORCA: realistic view - the light the shadow map is able to block, kept apart from the\n"
|
||||||
@@ -63,8 +59,7 @@ static const char* Segments_Vertex_Shader =
|
|||||||
" return top_diffuse + front_diffuse + top_specular;\n"
|
" return top_diffuse + front_diffuse + top_specular;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" int instance = (reverse_order != 0) ? instance_count - 1 - gl_InstanceID : gl_InstanceID;\n"
|
" int id_a = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n"
|
||||||
" int id_a = int(texelFetch(segment_index_tex, instance).r);\n"
|
|
||||||
" int id_b = id_a + 1;\n"
|
" int id_b = id_a + 1;\n"
|
||||||
" vec3 pos_a = texelFetch(position_tex, id_a).xyz;\n"
|
" vec3 pos_a = texelFetch(position_tex, id_a).xyz;\n"
|
||||||
" vec3 pos_b = texelFetch(position_tex, id_b).xyz;\n"
|
" vec3 pos_b = texelFetch(position_tex, id_b).xyz;\n"
|
||||||
|
|||||||
@@ -763,8 +763,6 @@ void ViewerImpl::init(const std::string& opengl_context_version)
|
|||||||
m_uni_segments_height_width_angle_tex_id = glGetUniformLocation(m_segments_shader_id, "height_width_angle_tex");
|
m_uni_segments_height_width_angle_tex_id = glGetUniformLocation(m_segments_shader_id, "height_width_angle_tex");
|
||||||
m_uni_segments_colors_tex_id = glGetUniformLocation(m_segments_shader_id, "color_tex");
|
m_uni_segments_colors_tex_id = glGetUniformLocation(m_segments_shader_id, "color_tex");
|
||||||
m_uni_segments_segment_index_tex_id = glGetUniformLocation(m_segments_shader_id, "segment_index_tex");
|
m_uni_segments_segment_index_tex_id = glGetUniformLocation(m_segments_shader_id, "segment_index_tex");
|
||||||
m_uni_segments_reverse_order_id = glGetUniformLocation(m_segments_shader_id, "reverse_order");
|
|
||||||
m_uni_segments_instance_count_id = glGetUniformLocation(m_segments_shader_id, "instance_count");
|
|
||||||
// ORCA: realistic view
|
// ORCA: realistic view
|
||||||
m_uni_segments_shadow_map_id = glGetUniformLocation(m_segments_shader_id, "shadow_map");
|
m_uni_segments_shadow_map_id = glGetUniformLocation(m_segments_shader_id, "shadow_map");
|
||||||
m_uni_segments_shadow_light_vp_id = glGetUniformLocation(m_segments_shader_id, "shadow_light_vp");
|
m_uni_segments_shadow_light_vp_id = glGetUniformLocation(m_segments_shader_id, "shadow_light_vp");
|
||||||
@@ -2092,15 +2090,6 @@ void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projec
|
|||||||
glsafe(glUniformMatrix4fv(m_uni_segments_view_matrix_id, 1, GL_FALSE, view_matrix.data()));
|
glsafe(glUniformMatrix4fv(m_uni_segments_view_matrix_id, 1, GL_FALSE, view_matrix.data()));
|
||||||
glsafe(glUniformMatrix4fv(m_uni_segments_projection_matrix_id, 1, GL_FALSE, projection_matrix.data()));
|
glsafe(glUniformMatrix4fv(m_uni_segments_projection_matrix_id, 1, GL_FALSE, projection_matrix.data()));
|
||||||
glsafe(glUniform3fv(m_uni_segments_camera_position_id, 1, camera_position.data()));
|
glsafe(glUniform3fv(m_uni_segments_camera_position_id, 1, camera_position.data()));
|
||||||
// The segments come in print order, bottom layer first. Seen from above, that is back to front,
|
|
||||||
// and every hidden fragment is shaded before the one that covers it. Drawing them last to first
|
|
||||||
// lets the depth test reject the hidden ones instead. The camera looks down when the world's
|
|
||||||
// up axis points towards it, which is the view matrix's (2, 2) entry being positive.
|
|
||||||
const bool top_down = !m_rendering_shadow_casters && view_matrix[10] > 0.0f;
|
|
||||||
glsafe(glUniform1i(m_uni_segments_reverse_order_id, top_down ? 1 : 0));
|
|
||||||
#ifndef ENABLE_OPENGL_ES
|
|
||||||
glsafe(glUniform1i(m_uni_segments_instance_count_id, static_cast<int>(m_enabled_segments_count)));
|
|
||||||
#endif // ENABLE_OPENGL_ES
|
|
||||||
// ORCA: realistic view. The depth pass writes the map it would otherwise read, so it shades
|
// ORCA: realistic view. The depth pass writes the map it would otherwise read, so it shades
|
||||||
// with the lookup off.
|
// with the lookup off.
|
||||||
glsafe(glUniform1i(m_uni_segments_shadow_map_id, m_shadow_map_texture_unit));
|
glsafe(glUniform1i(m_uni_segments_shadow_map_id, m_shadow_map_texture_unit));
|
||||||
|
|||||||
@@ -362,8 +362,6 @@ private:
|
|||||||
int m_uni_segments_height_width_angle_tex_id{ -1 };
|
int m_uni_segments_height_width_angle_tex_id{ -1 };
|
||||||
int m_uni_segments_colors_tex_id{ -1 };
|
int m_uni_segments_colors_tex_id{ -1 };
|
||||||
int m_uni_segments_segment_index_tex_id{ -1 };
|
int m_uni_segments_segment_index_tex_id{ -1 };
|
||||||
int m_uni_segments_reverse_order_id{ -1 };
|
|
||||||
int m_uni_segments_instance_count_id{ -1 };
|
|
||||||
int m_uni_segments_shadow_map_id{ -1 };
|
int m_uni_segments_shadow_map_id{ -1 };
|
||||||
int m_uni_segments_shadow_light_vp_id{ -1 };
|
int m_uni_segments_shadow_light_vp_id{ -1 };
|
||||||
int m_uni_segments_shadow_intensity_id{ -1 };
|
int m_uni_segments_shadow_intensity_id{ -1 };
|
||||||
|
|||||||
@@ -210,6 +210,30 @@ void ConfigManipulation::check_filament_max_volumetric_speed(DynamicPrintConfig
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigManipulation::check_filament_ironing_spacing(DynamicPrintConfig *config)
|
||||||
|
{
|
||||||
|
const auto *opt = config->option<ConfigOptionFloatsNullable>("filament_ironing_spacing");
|
||||||
|
if (opt == nullptr)
|
||||||
|
return;
|
||||||
|
std::vector<double> values = opt->values;
|
||||||
|
bool reset = false;
|
||||||
|
for (size_t i = 0; i < values.size(); ++i)
|
||||||
|
if (!opt->is_nil(i) && values[i] < IRONING_SPACING_MIN) {
|
||||||
|
values[i] = 0.1;
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
if (!reset)
|
||||||
|
return;
|
||||||
|
const wxString msg_text = _(L("Ironing spacing too small\nIt has been reset to 0.1"));
|
||||||
|
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
||||||
|
DynamicPrintConfig new_conf = *config;
|
||||||
|
is_msg_dlg_already_exist = true;
|
||||||
|
dialog.ShowModal();
|
||||||
|
new_conf.set_key_value("filament_ironing_spacing", new ConfigOptionFloatsNullable(values));
|
||||||
|
apply(config, &new_conf);
|
||||||
|
is_msg_dlg_already_exist = false;
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigManipulation::check_chamber_temperature(DynamicPrintConfig* config)
|
void ConfigManipulation::check_chamber_temperature(DynamicPrintConfig* config)
|
||||||
{
|
{
|
||||||
bool support_chamber_temp_control=GUI::wxGetApp().preset_bundle->printers.get_selected_preset().config.opt_bool("support_chamber_temp_control");
|
bool support_chamber_temp_control=GUI::wxGetApp().preset_bundle->printers.get_selected_preset().config.opt_bool("support_chamber_temp_control");
|
||||||
@@ -332,7 +356,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
//BBS: ironing_spacing shouldn't be too small or equal to zero
|
//BBS: ironing_spacing shouldn't be too small or equal to zero
|
||||||
if (config->opt_float("ironing_spacing") < 0.05)
|
if (config->opt_float("ironing_spacing") < IRONING_SPACING_MIN)
|
||||||
{
|
{
|
||||||
const wxString msg_text = _(L("Ironing spacing too small\nIt has been reset to 0.1"));
|
const wxString msg_text = _(L("Ironing spacing too small\nIt has been reset to 0.1"));
|
||||||
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
||||||
@@ -343,7 +367,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||||||
apply(config, &new_conf);
|
apply(config, &new_conf);
|
||||||
is_msg_dlg_already_exist = false;
|
is_msg_dlg_already_exist = false;
|
||||||
}
|
}
|
||||||
if (config->opt_float("support_ironing_spacing") < 0.05)
|
if (config->opt_float("support_ironing_spacing") < IRONING_SPACING_MIN)
|
||||||
{
|
{
|
||||||
const wxString msg_text = _(L("Ironing spacing too small\nIt has been reset to 0.1"));
|
const wxString msg_text = _(L("Ironing spacing too small\nIt has been reset to 0.1"));
|
||||||
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public:
|
|||||||
void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config);
|
void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config);
|
||||||
void check_adaptive_pressure_advance_model(DynamicPrintConfig* config);
|
void check_adaptive_pressure_advance_model(DynamicPrintConfig* config);
|
||||||
void check_filament_max_volumetric_speed(DynamicPrintConfig *config);
|
void check_filament_max_volumetric_speed(DynamicPrintConfig *config);
|
||||||
|
void check_filament_ironing_spacing(DynamicPrintConfig *config);
|
||||||
void check_chamber_temperature(DynamicPrintConfig* config);
|
void check_chamber_temperature(DynamicPrintConfig* config);
|
||||||
void check_chamber_minimal_temperature(DynamicPrintConfig* config);
|
void check_chamber_minimal_temperature(DynamicPrintConfig* config);
|
||||||
bool check_layer_height(DynamicPrintConfig* config);
|
bool check_layer_height(DynamicPrintConfig* config);
|
||||||
|
|||||||
@@ -4905,6 +4905,7 @@ void TabFilament::update()
|
|||||||
return; // ys_FIXME
|
return; // ys_FIXME
|
||||||
|
|
||||||
m_config_manipulation.check_filament_max_volumetric_speed(m_config);
|
m_config_manipulation.check_filament_max_volumetric_speed(m_config);
|
||||||
|
m_config_manipulation.check_filament_ironing_spacing(m_config);
|
||||||
|
|
||||||
m_update_cnt++;
|
m_update_cnt++;
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,3 @@ set_tests_properties(cli_strict_mode PROPERTIES
|
|||||||
LABELS "CLI;RequiresApp"
|
LABELS "CLI;RequiresApp"
|
||||||
SKIP_RETURN_CODE 77
|
SKIP_RETURN_CODE 77
|
||||||
TIMEOUT 900)
|
TIMEOUT 900)
|
||||||
|
|
||||||
add_test(NAME cli_project_missing_keys
|
|
||||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cli_project_missing_keys.sh $<TARGET_FILE:OrcaSlicer> ${ORCA_CLI_TEST_PYTHON}
|
|
||||||
${CMAKE_SOURCE_DIR}/resources/profiles/BBL)
|
|
||||||
set_tests_properties(cli_project_missing_keys PROPERTIES
|
|
||||||
LABELS "CLI;RequiresApp"
|
|
||||||
SKIP_RETURN_CODE 77
|
|
||||||
TIMEOUT 900)
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# End-to-end check that the CLI fills settings missing from a project from the project's system presets.
|
|
||||||
#
|
|
||||||
# A project saved before an option existed has no value for it. The GUI takes such keys from the
|
|
||||||
# project's system printer and process presets, not from the option defaults, and the CLI must slice
|
|
||||||
# the project with the same values. A project is exported from the shipped Bambu Lab P1S presets, one
|
|
||||||
# printer key and one process key are removed from it, one kept key is changed, and it is sliced again.
|
|
||||||
#
|
|
||||||
# usage: test_cli_project_missing_keys.sh <orca-slicer binary> <python3> <resources/profiles/BBL>
|
|
||||||
set -u
|
|
||||||
|
|
||||||
BIN="${1:-}"
|
|
||||||
PY="${2:-python3}"
|
|
||||||
PROFILES="${3:-}"
|
|
||||||
# 77 is the test's SKIP_RETURN_CODE.
|
|
||||||
[ -x "$BIN" ] || { echo "SKIP: orca-slicer binary not found: $BIN"; exit 77; }
|
|
||||||
[ -d "$PROFILES" ] || { echo "FAIL: profiles directory not found: $PROFILES"; exit 1; }
|
|
||||||
|
|
||||||
WORK="$(mktemp -d "${TMPDIR:-/tmp}/orca-cli-missing-keys.XXXXXX")"
|
|
||||||
trap 'rm -rf "$WORK"' EXIT
|
|
||||||
|
|
||||||
"$PY" - "$WORK/cube.stl" <<'EOF'
|
|
||||||
import sys
|
|
||||||
|
|
||||||
v = [(x, y, z) for z in (0, 10) for y in (0, 10) for x in (0, 10)]
|
|
||||||
with open(sys.argv[1], "w") as f:
|
|
||||||
f.write("solid cube\n")
|
|
||||||
for a, b, c, d in ((0, 2, 3, 1), (4, 5, 7, 6), (0, 1, 5, 4), (2, 6, 7, 3), (0, 4, 6, 2), (1, 3, 7, 5)):
|
|
||||||
for tri in ((v[a], v[b], v[c]), (v[a], v[c], v[d])):
|
|
||||||
f.write("facet normal 0 0 0\nouter loop\n")
|
|
||||||
for p in tri:
|
|
||||||
f.write("vertex %g %g %g\n" % p)
|
|
||||||
f.write("endloop\nendfacet\n")
|
|
||||||
f.write("endsolid cube\n")
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# slice <tag> <input> [option...]: slice into $WORK/<tag>/out.3mf with a fresh data directory.
|
|
||||||
slice() {
|
|
||||||
local out="$WORK/$1" input="$2"; shift 2
|
|
||||||
mkdir -p "$out"
|
|
||||||
timeout 300 "$BIN" --datadir "$out/datadir" "$@" --slice 0 --outputdir "$out" --export-3mf out.3mf "$input" \
|
|
||||||
> "$out/log" 2>&1 || { echo "FAIL: $1: orca-slicer exited $?"; tail -n 40 "$out/log"; exit 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
slice base "$WORK/cube.stl" \
|
|
||||||
--load-settings "$PROFILES/machine/Bambu Lab P1S 0.4 nozzle.json;$PROFILES/process/0.20mm Standard @BBL X1C.json" \
|
|
||||||
--load-filaments "$PROFILES/filament/Bambu PLA Basic @BBL P1S 0.4 nozzle.json"
|
|
||||||
|
|
||||||
# The removed keys, with their option defaults from PrintConfig.cpp, and a kept key with a new value.
|
|
||||||
"$PY" - "$WORK/base/out.3mf" "$WORK/old.3mf" <<'EOF' || exit $?
|
|
||||||
import json, sys, zipfile
|
|
||||||
|
|
||||||
src, dst = sys.argv[1], sys.argv[2]
|
|
||||||
missing = {"extruder_clearance_dist_to_rod": "40", "sparse_infill_density": "20%"}
|
|
||||||
with zipfile.ZipFile(src) as zin, zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zout:
|
|
||||||
for item in zin.infolist():
|
|
||||||
data = zin.read(item.filename)
|
|
||||||
if item.filename == "Metadata/project_settings.config":
|
|
||||||
config = json.loads(data)
|
|
||||||
for key, default in missing.items():
|
|
||||||
if config[key] == default:
|
|
||||||
print("SKIP: %s is %s in the system preset, the option default, so the test cannot tell them apart" % (key, default))
|
|
||||||
sys.exit(77)
|
|
||||||
expected = {key: config.pop(key) for key in missing}
|
|
||||||
expected["wall_loops"] = str(int(config["wall_loops"]) + 1)
|
|
||||||
config["wall_loops"] = expected["wall_loops"]
|
|
||||||
data = json.dumps(config, indent=4)
|
|
||||||
zout.writestr(item, data)
|
|
||||||
with open(dst + ".expected.json", "w") as f:
|
|
||||||
json.dump(expected, f)
|
|
||||||
EOF
|
|
||||||
|
|
||||||
slice project "$WORK/old.3mf"
|
|
||||||
|
|
||||||
"$PY" - "$WORK/project/out.3mf" "$WORK/old.3mf.expected.json" <<'EOF'
|
|
||||||
import json, sys, zipfile
|
|
||||||
|
|
||||||
with zipfile.ZipFile(sys.argv[1]) as z:
|
|
||||||
config = json.loads(z.read("Metadata/project_settings.config"))
|
|
||||||
with open(sys.argv[2]) as f:
|
|
||||||
expected = json.load(f)
|
|
||||||
errors = ["%s is %r, want %r" % (key, config.get(key), want) for key, want in expected.items() if config.get(key) != want]
|
|
||||||
for e in errors:
|
|
||||||
print("FAIL: " + e)
|
|
||||||
sys.exit(1 if errors else 0)
|
|
||||||
EOF
|
|
||||||
status=$?
|
|
||||||
[ "$status" -eq 0 ] || { tail -n 40 "$WORK/project/log"; exit 1; }
|
|
||||||
echo "PASS"
|
|
||||||
@@ -747,6 +747,61 @@ TEST_CASE("A region with ironing turned off is never ironed", "[Fill]")
|
|||||||
REQUIRE(Layer::choose_ironing_extruder(cfg, spiral_mode, /*is_topmost_layer=*/true) == -1);
|
REQUIRE(Layer::choose_ironing_extruder(cfg, spiral_mode, /*is_topmost_layer=*/true) == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ironing path count and total length in mm, over the whole object.
|
||||||
|
static std::pair<size_t, double> ironing_extent(const Print &print)
|
||||||
|
{
|
||||||
|
size_t paths = 0;
|
||||||
|
double length = 0.;
|
||||||
|
for (const Layer *layer : print.objects().front()->layers())
|
||||||
|
for (const LayerRegion *region : layer->regions())
|
||||||
|
for (const ExtrusionEntity *entity : region->fills.flatten().entities)
|
||||||
|
if (ironing_role(entity->role())) {
|
||||||
|
++paths;
|
||||||
|
length += unscale<double>(entity->length());
|
||||||
|
}
|
||||||
|
return {paths, length};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Ironing spacing below the minimum irons at the minimum spacing", "[Fill]")
|
||||||
|
{
|
||||||
|
const std::string pattern = GENERATE("rectilinear", "concentric");
|
||||||
|
const bool via_filament = GENERATE(false, true);
|
||||||
|
const double spacing = GENERATE(0., 0.001);
|
||||||
|
CAPTURE(pattern, via_filament, spacing);
|
||||||
|
|
||||||
|
auto ironing_for = [&pattern, via_filament](double spacing) {
|
||||||
|
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||||
|
config.set_deserialize_strict({{"ironing_type", "top"},
|
||||||
|
{"ironing_pattern", pattern},
|
||||||
|
{"layer_height", 0.2}});
|
||||||
|
// The filament override replaces the process spacing, which stays at a usable value.
|
||||||
|
if (via_filament)
|
||||||
|
config.set_deserialize_strict({{"ironing_spacing", 0.1}, {"filament_ironing_spacing", spacing}});
|
||||||
|
else
|
||||||
|
config.set_deserialize_strict({{"ironing_spacing", spacing}});
|
||||||
|
Print print;
|
||||||
|
Slic3r::Test::init_and_process_print({Slic3r::Test::cube(20)}, print, config);
|
||||||
|
return ironing_extent(print);
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::pair<size_t, double> clamped = ironing_for(spacing);
|
||||||
|
const std::pair<size_t, double> minimum = ironing_for(IRONING_SPACING_MIN);
|
||||||
|
REQUIRE(minimum.first > 0);
|
||||||
|
CHECK(clamped.first == minimum.first);
|
||||||
|
CHECK_THAT(clamped.second, Catch::Matchers::WithinRel(minimum.second, 1e-9));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Concentric fill at zero spacing returns without paths", "[Fill]")
|
||||||
|
{
|
||||||
|
std::unique_ptr<Fill> filler(Fill::new_from_type(ipConcentric));
|
||||||
|
filler->spacing = 0.;
|
||||||
|
filler->bounding_box = BoundingBox(Point(0, 0), Point::new_scale(10, 10));
|
||||||
|
FillParams params;
|
||||||
|
params.density = 1.f;
|
||||||
|
Surface surface(stTop, ExPolygon({Point(0, 0), Point::new_scale(10, 0), Point::new_scale(10, 10), Point::new_scale(0, 10)}));
|
||||||
|
CHECK(filler->fill_surface(&surface, params).empty());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Solid infill direction offsets every layer when no template is set", "[Fill]")
|
TEST_CASE("Solid infill direction offsets every layer when no template is set", "[Fill]")
|
||||||
{
|
{
|
||||||
auto angles_for = [](int direction) {
|
auto angles_for = [](int direction) {
|
||||||
|
|||||||
@@ -5405,35 +5405,6 @@ struct ScopedDataDir
|
|||||||
~ScopedDataDir() { set_data_dir(previous); }
|
~ScopedDataDir() { set_data_dir(previous); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// resources_dir() is process-wide too; system preset lookups scan its profiles directory.
|
|
||||||
struct ScopedResourcesDir
|
|
||||||
{
|
|
||||||
std::string previous = resources_dir();
|
|
||||||
explicit ScopedResourcesDir(const fs::path &dir) { set_resources_dir(dir.string()); }
|
|
||||||
~ScopedResourcesDir() { set_resources_dir(previous); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// An "Acme" vendor under root whose "Acme Printer" inherits extruder_clearance_dist_to_rod from an
|
|
||||||
// abstract base, with the printer in a nested sub_path so the name cannot be derived from the file.
|
|
||||||
void write_acme_printer_vendor(const fs::path &root, double dist_to_rod)
|
|
||||||
{
|
|
||||||
const fs::path machine_dir = root / "Acme" / "machine";
|
|
||||||
fs::create_directories(machine_dir / "nested");
|
|
||||||
std::ofstream((root / "Acme.json").string())
|
|
||||||
<< R"({"version":"1.0.0","name":"Acme",)"
|
|
||||||
<< R"("machine_model_list":[{"name":"Acme One","sub_path":"machine/model.json"}],"machine_list":[)"
|
|
||||||
<< R"({"name":"fdm_acme_common","sub_path":"machine/base.json"},)"
|
|
||||||
<< R"({"name":"Acme Printer","sub_path":"machine/nested/printer.json"}]})";
|
|
||||||
std::ofstream((machine_dir / "model.json").string())
|
|
||||||
<< R"({"type":"machine_model","name":"Acme One","nozzle_diameter":"0.4"})";
|
|
||||||
std::ofstream((machine_dir / "base.json").string())
|
|
||||||
<< R"({"type":"machine","name":"fdm_acme_common","from":"system","instantiation":"false",)"
|
|
||||||
<< R"("extruder_clearance_dist_to_rod":")" << dist_to_rod << R"("})";
|
|
||||||
std::ofstream((machine_dir / "nested" / "printer.json").string())
|
|
||||||
<< R"({"type":"machine","name":"Acme Printer","from":"system","instantiation":"true","inherits":"fdm_acme_common",)"
|
|
||||||
<< R"("printer_model":"Acme One","printer_variant":"0.4"})";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string read_file(const fs::path &file)
|
std::string read_file(const fs::path &file)
|
||||||
{
|
{
|
||||||
std::ifstream in(file.string(), std::ios::binary);
|
std::ifstream in(file.string(), std::ios::binary);
|
||||||
@@ -5511,75 +5482,3 @@ TEST_CASE("Config import confines zip entries, preset names and bundle ids to th
|
|||||||
CHECK_FALSE(any_filename_contains(temp_dir.path(), "bundle-escape"));
|
CHECK_FALSE(any_filename_contains(temp_dir.path(), "bundle-escape"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("A system preset resolves by name from the bundled profiles", "[Preset][Bundle]")
|
|
||||||
{
|
|
||||||
ScopedTemporaryDir temp_dir;
|
|
||||||
ScopedDataDir data(temp_dir.path() / "data");
|
|
||||||
ScopedResourcesDir resources(temp_dir.path() / "resources");
|
|
||||||
write_acme_printer_vendor(temp_dir.path() / "resources" / "profiles", 33.);
|
|
||||||
|
|
||||||
PresetBundle bundle;
|
|
||||||
DynamicPrintConfig config;
|
|
||||||
std::string error;
|
|
||||||
REQUIRE(bundle.resolve_system_preset(config, Preset::TYPE_PRINTER, "Acme Printer",
|
|
||||||
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
|
||||||
CHECK(error.empty());
|
|
||||||
CHECK_THAT(config.opt_float("extruder_clearance_dist_to_rod"), Catch::Matchers::WithinAbs(33., 1e-6));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("A system preset resolves from the data directory copy of its vendor", "[Preset][Bundle]")
|
|
||||||
{
|
|
||||||
ScopedTemporaryDir temp_dir;
|
|
||||||
ScopedDataDir data(temp_dir.path() / "data");
|
|
||||||
ScopedResourcesDir resources(temp_dir.path() / "resources");
|
|
||||||
write_acme_printer_vendor(temp_dir.path() / "resources" / "profiles", 33.);
|
|
||||||
write_acme_printer_vendor(temp_dir.path() / "data" / PRESET_SYSTEM_DIR, 35.);
|
|
||||||
|
|
||||||
PresetBundle bundle;
|
|
||||||
DynamicPrintConfig config;
|
|
||||||
std::string error;
|
|
||||||
REQUIRE(bundle.resolve_system_preset(config, Preset::TYPE_PRINTER, "Acme Printer",
|
|
||||||
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
|
||||||
CHECK_THAT(config.opt_float("extruder_clearance_dist_to_rod"), Catch::Matchers::WithinAbs(35., 1e-6));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("A system preset resolves from a vendor shipped as its preset cache alone", "[Preset][Bundle]")
|
|
||||||
{
|
|
||||||
ScopedTemporaryDir temp_dir;
|
|
||||||
ScopedDataDir data(temp_dir.path() / "data");
|
|
||||||
ScopedResourcesDir resources(temp_dir.path() / "resources");
|
|
||||||
const fs::path profiles = temp_dir.path() / "resources" / "profiles";
|
|
||||||
write_acme_printer_vendor(profiles, 33.);
|
|
||||||
|
|
||||||
PresetBundle writer;
|
|
||||||
writer.set_generate_vendor_caches(true);
|
|
||||||
writer.load_vendor_configs_from_json(profiles.string(), "Acme", PresetBundle::LoadSystem,
|
|
||||||
ForwardCompatibilitySubstitutionRule::EnableSilent);
|
|
||||||
REQUIRE(fs::exists(profiles / "Acme.opc"));
|
|
||||||
// Release builds ship the cache and drop the profile JSONs, manifest included.
|
|
||||||
fs::remove(profiles / "Acme.json");
|
|
||||||
fs::remove_all(profiles / "Acme");
|
|
||||||
|
|
||||||
PresetBundle bundle;
|
|
||||||
DynamicPrintConfig config;
|
|
||||||
std::string error;
|
|
||||||
REQUIRE(bundle.resolve_system_preset(config, Preset::TYPE_PRINTER, "Acme Printer",
|
|
||||||
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
|
||||||
CHECK_THAT(config.opt_float("extruder_clearance_dist_to_rod"), Catch::Matchers::WithinAbs(33., 1e-6));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("A system preset no vendor lists is not resolved", "[Preset][Bundle]")
|
|
||||||
{
|
|
||||||
ScopedTemporaryDir temp_dir;
|
|
||||||
ScopedDataDir data(temp_dir.path() / "data");
|
|
||||||
ScopedResourcesDir resources(temp_dir.path() / "resources");
|
|
||||||
write_acme_printer_vendor(temp_dir.path() / "resources" / "profiles", 33.);
|
|
||||||
|
|
||||||
PresetBundle bundle;
|
|
||||||
DynamicPrintConfig config;
|
|
||||||
std::string error;
|
|
||||||
CHECK_FALSE(bundle.resolve_system_preset(config, Preset::TYPE_PRINTER, "Unknown Printer",
|
|
||||||
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
|
||||||
CHECK_FALSE(error.empty());
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user