mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-02 13:20:59 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64460d7f85 |
@@ -588,13 +588,15 @@ const PresetBundle *PresetBundle::load_source_vendor(const boost::filesystem::pa
|
|||||||
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. It is only a base, so
|
||||||
|
// it comes from its cache whenever that is all that is installed, even when the
|
||||||
|
// vendor itself is parsed (a vendor updated over the air).
|
||||||
const std::string library_file = std::string(ORCA_FILAMENT_LIBRARY);
|
const std::string library_file = std::string(ORCA_FILAMENT_LIBRARY);
|
||||||
|
const bool library_json = boost::filesystem::is_regular_file(root_dir / (library_file + ".json"));
|
||||||
|
const bool library_cache_only = !library_json && boost::filesystem::is_regular_file(root_dir / (library_file + ".opc"));
|
||||||
const PresetBundle *library = nullptr;
|
const PresetBundle *library = nullptr;
|
||||||
if (vendor_id != ORCA_FILAMENT_LIBRARY &&
|
if (vendor_id != ORCA_FILAMENT_LIBRARY && (library_json || library_cache_only)) {
|
||||||
(boost::filesystem::is_regular_file(root_dir / (library_file + ".json")) ||
|
library = load_source_vendor(root_dir, ORCA_FILAMENT_LIBRARY, compatibility_rule, error, allow_cache || library_cache_only);
|
||||||
(allow_cache && boost::filesystem::is_regular_file(root_dir / (library_file + ".opc"))))) {
|
|
||||||
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;
|
||||||
@@ -2527,7 +2529,7 @@ void PresetBundle::clear_printer_hold_aliases()
|
|||||||
|
|
||||||
//BBS: add json related logic, load system presets from json
|
//BBS: add json related logic, load system presets from json
|
||||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(
|
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(
|
||||||
ForwardCompatibilitySubstitutionRule compatibility_rule, bool allow_cache)
|
ForwardCompatibilitySubstitutionRule compatibility_rule, bool write_caches)
|
||||||
{
|
{
|
||||||
//BBS: add config related logs
|
//BBS: add config related logs
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%")%compatibility_rule;
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%")%compatibility_rule;
|
||||||
@@ -2547,14 +2549,14 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||||||
// The vendors below are loaded whole and against each other — the filament
|
// The vendors below are loaded whole and against each other — the filament
|
||||||
// library first, then every other vendor with it as the base — so each parse
|
// library first, then every other vendor with it as the base — so each parse
|
||||||
// is complete enough to be worth caching.
|
// is complete enough to be worth caching.
|
||||||
m_generate_vendor_caches = allow_cache && (m_generate_vendor_caches || !validation_mode);
|
m_generate_vendor_caches = write_caches && (m_generate_vendor_caches || !validation_mode);
|
||||||
|
|
||||||
// Sorted, so any duplicate-preset warning comes out in the same order on every run.
|
// Sorted, so any duplicate-preset warning comes out in the same order on every run.
|
||||||
std::vector<VendorSource> vendors;
|
std::vector<VendorSource> vendors;
|
||||||
for (const std::string& name : vendor_names_in(dir))
|
for (const std::string& name : vendor_names_in(dir))
|
||||||
if (name == ORCA_FILAMENT_LIBRARY || !(validation_mode && !vendor_to_validate.empty() && name != vendor_to_validate))
|
if (name == ORCA_FILAMENT_LIBRARY || !(validation_mode && !vendor_to_validate.empty() && name != vendor_to_validate))
|
||||||
vendors.push_back({ name, dir });
|
vendors.push_back({ name, dir });
|
||||||
auto result = this->load_vendors(vendors, compatibility_rule, allow_cache);
|
auto result = this->load_vendors(vendors, compatibility_rule, true);
|
||||||
|
|
||||||
this->update_system_maps();
|
this->update_system_maps();
|
||||||
|
|
||||||
|
|||||||
@@ -839,7 +839,9 @@ private:
|
|||||||
|
|
||||||
//std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
//std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||||
//BBS: add json related logic
|
//BBS: add json related logic
|
||||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule, bool allow_cache = true);
|
// Reads each vendor from its preset cache where one covers the profile, as every load does.
|
||||||
|
// write_caches = false keeps a read-only load from writing caches into the data directory.
|
||||||
|
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule, bool write_caches = true);
|
||||||
// Update the multicolor information for filaments.
|
// Update the multicolor information for filaments.
|
||||||
void update_filament_multi_color();
|
void update_filament_multi_color();
|
||||||
// Update renamed_from and alias maps of system profiles.
|
// Update renamed_from and alias maps of system profiles.
|
||||||
|
|||||||
@@ -5788,6 +5788,131 @@ TEST_CASE("A system preset no vendor lists is not resolved", "[Preset][Bundle]")
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// Writes each vendor's preset cache into dir, then deletes its profile JSONs: what a release build installs.
|
||||||
|
void reduce_vendors_to_caches(const fs::path &dir, const std::vector<std::string> &vendor_ids)
|
||||||
|
{
|
||||||
|
const std::string lib(PresetBundle::ORCA_FILAMENT_LIBRARY);
|
||||||
|
PresetBundle library;
|
||||||
|
if (fs::exists(dir / (lib + ".json"))) {
|
||||||
|
library.set_generate_vendor_caches(true);
|
||||||
|
library.load_vendor_configs_from_json(dir.string(), lib, PresetBundle::LoadSystem,
|
||||||
|
ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||||
|
}
|
||||||
|
for (const std::string &vendor_id : vendor_ids) {
|
||||||
|
if (vendor_id == lib)
|
||||||
|
continue;
|
||||||
|
PresetBundle writer;
|
||||||
|
writer.set_generate_vendor_caches(true);
|
||||||
|
writer.load_vendor_configs_from_json(dir.string(), vendor_id, PresetBundle::LoadSystem,
|
||||||
|
ForwardCompatibilitySubstitutionRule::EnableSilent, &library);
|
||||||
|
}
|
||||||
|
for (const std::string &vendor_id : vendor_ids) {
|
||||||
|
REQUIRE(fs::exists(dir / (vendor_id + ".opc")));
|
||||||
|
fs::remove(dir / (vendor_id + ".json"));
|
||||||
|
fs::remove_all(dir / vendor_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The filament library with one abstract base filament, and an "Acme" vendor whose one filament inherits it.
|
||||||
|
void write_library_and_acme_filament(const fs::path &root)
|
||||||
|
{
|
||||||
|
const std::string lib(PresetBundle::ORCA_FILAMENT_LIBRARY);
|
||||||
|
fs::create_directories(root / lib / "filament");
|
||||||
|
std::ofstream((root / (lib + ".json")).string())
|
||||||
|
<< R"({"version":"1.0.0","name":")" << lib << R"(",)"
|
||||||
|
<< R"("filament_list":[{"name":"Generic PLA","sub_path":"filament/generic_pla.json"}]})";
|
||||||
|
std::ofstream((root / lib / "filament" / "generic_pla.json").string())
|
||||||
|
<< R"({"type":"filament","name":"Generic PLA","from":"system","instantiation":"false","filament_id":"GFL99","filament_cost":"27"})";
|
||||||
|
fs::create_directories(root / "Acme" / "filament");
|
||||||
|
std::ofstream((root / "Acme.json").string())
|
||||||
|
<< R"({"version":"1.0.0","name":"Acme","filament_list":[{"name":"Acme PLA","sub_path":"filament/pla.json"}]})";
|
||||||
|
std::ofstream((root / "Acme" / "filament" / "pla.json").string())
|
||||||
|
<< R"({"type":"filament","name":"Acme PLA","from":"system","instantiation":"true","inherits":"Generic PLA"})";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("A read-only load resolves a user preset against vendors installed as their cache alone", "[Preset][Bundle][Regression]")
|
||||||
|
{
|
||||||
|
ScopedTemporaryDir temp_dir;
|
||||||
|
const fs::path data = temp_dir.path() / "data";
|
||||||
|
const fs::path system = data / PRESET_SYSTEM_DIR;
|
||||||
|
ScopedDataDir scoped_data(data);
|
||||||
|
ScopedResourcesDir scoped_resources(temp_dir.path() / "resources");
|
||||||
|
write_acme_printer_vendor(system, 33.);
|
||||||
|
reduce_vendors_to_caches(system, {"Acme"});
|
||||||
|
|
||||||
|
fs::create_directories(data / PRESET_USER_DIR / DEFAULT_USER_FOLDER_NAME / PRESET_PRINTER_NAME);
|
||||||
|
std::ofstream((data / PRESET_USER_DIR / DEFAULT_USER_FOLDER_NAME / PRESET_PRINTER_NAME / "My Acme.json").string())
|
||||||
|
<< R"({"type":"machine","name":"My Acme","from":"User","version":"2.3.0.0","inherits":"Acme Printer","printable_height":"123"})";
|
||||||
|
|
||||||
|
AppConfig app_config;
|
||||||
|
PresetBundle bundle;
|
||||||
|
std::string errors;
|
||||||
|
bundle.load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSilent, PresetBundle::PresetPreferences(),
|
||||||
|
&errors, true);
|
||||||
|
CHECK(errors.empty());
|
||||||
|
const Preset *preset = bundle.printers.find_preset("My Acme");
|
||||||
|
REQUIRE(preset != nullptr);
|
||||||
|
CHECK_THAT(preset->config.opt_float("printable_height"), Catch::Matchers::WithinAbs(123., 1e-6));
|
||||||
|
CHECK_THAT(preset->config.opt_float("extruder_clearance_dist_to_rod"), Catch::Matchers::WithinAbs(33., 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A read-only load writes no preset cache", "[Preset][Bundle][Regression]")
|
||||||
|
{
|
||||||
|
ScopedTemporaryDir temp_dir;
|
||||||
|
const fs::path system = temp_dir.path() / "data" / PRESET_SYSTEM_DIR;
|
||||||
|
ScopedDataDir scoped_data(temp_dir.path() / "data");
|
||||||
|
ScopedResourcesDir scoped_resources(temp_dir.path() / "resources");
|
||||||
|
write_acme_printer_vendor(system, 33.);
|
||||||
|
|
||||||
|
AppConfig app_config;
|
||||||
|
PresetBundle bundle;
|
||||||
|
std::string errors;
|
||||||
|
bundle.load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSilent, PresetBundle::PresetPreferences(),
|
||||||
|
&errors, true);
|
||||||
|
CHECK(errors.empty());
|
||||||
|
CHECK(bundle.printers.find_preset("Acme Printer") != nullptr);
|
||||||
|
CHECK_FALSE(fs::exists(system / "Acme.opc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A vendor updated over the air resolves against the library installed as its cache alone", "[Preset][Bundle][Regression]")
|
||||||
|
{
|
||||||
|
ScopedTemporaryDir temp_dir;
|
||||||
|
const fs::path system = temp_dir.path() / "data" / PRESET_SYSTEM_DIR;
|
||||||
|
ScopedDataDir scoped_data(temp_dir.path() / "data");
|
||||||
|
ScopedResourcesDir scoped_resources(temp_dir.path() / "resources");
|
||||||
|
// System presets are found by name through the bundled profiles.
|
||||||
|
write_library_and_acme_filament(temp_dir.path() / "resources" / PRESET_PROFILES_DIR);
|
||||||
|
// The release install, then an update that brings Acme back as JSONs while the library stays a cache.
|
||||||
|
write_library_and_acme_filament(system);
|
||||||
|
reduce_vendors_to_caches(system, {PresetBundle::ORCA_FILAMENT_LIBRARY, "Acme"});
|
||||||
|
write_library_and_acme_filament(temp_dir.path() / "update");
|
||||||
|
fs::copy_file(temp_dir.path() / "update" / "Acme.json", system / "Acme.json");
|
||||||
|
fs::create_directories(system / "Acme" / "filament");
|
||||||
|
fs::copy_file(temp_dir.path() / "update" / "Acme" / "filament" / "pla.json", system / "Acme" / "filament" / "pla.json");
|
||||||
|
|
||||||
|
SECTION("by name") {
|
||||||
|
PresetBundle bundle;
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
std::string error;
|
||||||
|
REQUIRE(bundle.resolve_system_preset(config, Preset::TYPE_FILAMENT, "Acme PLA",
|
||||||
|
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
||||||
|
CHECK_THAT(config.opt<ConfigOptionFloats>("filament_cost")->values.front(), Catch::Matchers::WithinAbs(27., 1e-6));
|
||||||
|
}
|
||||||
|
SECTION("by its source file") {
|
||||||
|
PresetBundle bundle;
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS, true)->value = "Generic PLA";
|
||||||
|
std::string error;
|
||||||
|
REQUIRE(bundle.resolve_preset_config(config, Preset::TYPE_FILAMENT, (system / "Acme" / "filament" / "pla.json").string(),
|
||||||
|
ForwardCompatibilitySubstitutionRule::EnableSilent, error));
|
||||||
|
CHECK_THAT(config.opt<ConfigOptionFloats>("filament_cost")->values.front(), Catch::Matchers::WithinAbs(27., 1e-6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// A default preset config for type, built the way PresetBundle builds its default presets.
|
// A default preset config for type, built the way PresetBundle builds its default presets.
|
||||||
DynamicPrintConfig external_default_config(Preset::Type type)
|
DynamicPrintConfig external_default_config(Preset::Type type)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user