mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-15 08:23:00 +00:00
Removing user\bundle serialization and keeping it only for system presets
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
#include "Exception.hpp"
|
||||
#include "Preset.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PresetBundleCache.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -709,8 +708,6 @@ void Preset::save(DynamicPrintConfig* parent_config)
|
||||
this->save_info(idx_file.string());
|
||||
}
|
||||
|
||||
// Update the per-file binary cache so the next startup skips JSON parsing.
|
||||
PresetBundleCache::write_file_cache(*this);
|
||||
}
|
||||
|
||||
void Preset::reload(Preset const &parent)
|
||||
|
||||
@@ -959,16 +959,6 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
|
||||
const auto user_load_t0 = std::chrono::steady_clock::now();
|
||||
|
||||
// Helper: collect canonical names of presets in a collection that belong to a bundle.
|
||||
auto collect_bundle_preset_names = [](const PresetCollection& coll,
|
||||
const std::string& bundle_id,
|
||||
std::vector<std::string>& out) {
|
||||
for (const Preset& p : coll()) {
|
||||
if (p.bundle_id == bundle_id)
|
||||
out.push_back(p.name);
|
||||
}
|
||||
};
|
||||
|
||||
// Load bundle metadata from _local directory first
|
||||
fs::path local_dir(folder / PRESET_LOCAL_DIR);
|
||||
if (fs::exists(local_dir)) {
|
||||
@@ -987,34 +977,15 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
metadata.filament_presets.clear();
|
||||
metadata.printer_presets.clear();
|
||||
|
||||
const PresetOrigin origin(PresetOrigin::Kind::LocalBundle, metadata.id);
|
||||
|
||||
// Pre-load from per-file caches; load_presets will skip these.
|
||||
PresetBundleCache::preload_file_caches(prints, (fs::path(bundle_dir) / PRESET_PRINT_NAME).string(), origin);
|
||||
PresetBundleCache::preload_file_caches(filaments, (fs::path(bundle_dir) / PRESET_FILAMENT_NAME).string(), origin);
|
||||
PresetBundleCache::preload_file_caches(printers, (fs::path(bundle_dir) / PRESET_PRINTER_NAME).string(), origin);
|
||||
|
||||
// Record names of preloaded presets in metadata.
|
||||
collect_bundle_preset_names(prints, metadata.id, metadata.print_presets);
|
||||
collect_bundle_preset_names(filaments, metadata.id, metadata.filament_presets);
|
||||
collect_bundle_preset_names(printers, metadata.id, metadata.printer_presets);
|
||||
|
||||
// Load any presets not covered by the cache (callback adds to metadata).
|
||||
this->prints.load_presets(bundle_dir, PRESET_PRINT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.print_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
this->filaments.load_presets(bundle_dir, PRESET_FILAMENT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.filament_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
this->printers.load_presets(bundle_dir, PRESET_PRINTER_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.printer_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
|
||||
// Persist any newly-loaded presets back to per-file caches.
|
||||
PresetBundleCache::update_file_caches(prints, (fs::path(bundle_dir) / PRESET_PRINT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(filaments, (fs::path(bundle_dir) / PRESET_FILAMENT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(printers, (fs::path(bundle_dir) / PRESET_PRINTER_NAME).string());
|
||||
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
metadata.bundle_type = BundleType::Local;
|
||||
metadata.path = metadata_file.string();
|
||||
|
||||
@@ -1042,33 +1013,15 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
metadata.printer_presets.clear();
|
||||
metadata.is_subscribed = true;
|
||||
|
||||
const PresetOrigin origin(PresetOrigin::Kind::SubscribedBundle, metadata.id);
|
||||
|
||||
// Pre-load from per-file caches; load_presets will skip these.
|
||||
PresetBundleCache::preload_file_caches(prints, (fs::path(bundle_dir) / PRESET_PRINT_NAME).string(), origin);
|
||||
PresetBundleCache::preload_file_caches(filaments, (fs::path(bundle_dir) / PRESET_FILAMENT_NAME).string(), origin);
|
||||
PresetBundleCache::preload_file_caches(printers, (fs::path(bundle_dir) / PRESET_PRINTER_NAME).string(), origin);
|
||||
|
||||
// Record names of preloaded presets in metadata.
|
||||
collect_bundle_preset_names(prints, metadata.id, metadata.print_presets);
|
||||
collect_bundle_preset_names(filaments, metadata.id, metadata.filament_presets);
|
||||
collect_bundle_preset_names(printers, metadata.id, metadata.printer_presets);
|
||||
|
||||
// Load any presets not covered by the cache (callback adds to metadata).
|
||||
this->prints.load_presets(bundle_dir, PRESET_PRINT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.print_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
this->filaments.load_presets(bundle_dir, PRESET_FILAMENT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.filament_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
this->printers.load_presets(bundle_dir, PRESET_PRINTER_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.printer_presets.push_back(preset.name);
|
||||
}, origin);
|
||||
|
||||
// Persist any newly-loaded presets back to per-file caches.
|
||||
PresetBundleCache::update_file_caches(prints, (fs::path(bundle_dir) / PRESET_PRINT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(filaments, (fs::path(bundle_dir) / PRESET_FILAMENT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(printers, (fs::path(bundle_dir) / PRESET_PRINTER_NAME).string());
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
|
||||
metadata.bundle_type = BundleType::Subscribed;
|
||||
metadata.path = metadata_file.string();
|
||||
@@ -1083,46 +1036,28 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
// BBS do not load sla_print
|
||||
// BBS: change directories by design
|
||||
|
||||
// Regular user presets (process/filament/machine) — per-file cache approach.
|
||||
{
|
||||
const PresetOrigin user_origin; // Kind::Auto → resolved to User by detect_origin_from_path
|
||||
|
||||
// Pre-load from per-file .cache siblings; load_presets will skip pre-loaded names.
|
||||
int cached_prints = PresetBundleCache::preload_file_caches(prints, (fs::path(dir_user_presets) / PRESET_PRINT_NAME).string(), user_origin);
|
||||
int cached_filaments = PresetBundleCache::preload_file_caches(filaments, (fs::path(dir_user_presets) / PRESET_FILAMENT_NAME).string(), user_origin);
|
||||
int cached_printers = PresetBundleCache::preload_file_caches(printers, (fs::path(dir_user_presets) / PRESET_PRINTER_NAME).string(), user_origin);
|
||||
BOOST_LOG_TRIVIAL(info) << "PresetBundle: user presets from cache: "
|
||||
<< cached_prints << " process, "
|
||||
<< cached_filaments << " filament, "
|
||||
<< cached_printers << " machine";
|
||||
|
||||
const auto json_t0 = std::chrono::steady_clock::now();
|
||||
try {
|
||||
std::string print_selected_preset_name = prints.get_selected_preset().name;
|
||||
std::string sel = prints.get_selected_preset().name;
|
||||
this->prints.load_presets(dir_user_presets, PRESET_PRINT_NAME, substitutions, substitution_rule);
|
||||
prints.select_preset_by_name(print_selected_preset_name, false);
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
prints.select_preset_by_name(sel, false);
|
||||
} catch (const std::runtime_error& err) { errors_cummulative += err.what(); }
|
||||
try {
|
||||
std::string filament_selected_preset_name = filaments.get_selected_preset().name;
|
||||
std::string sel = filaments.get_selected_preset().name;
|
||||
this->filaments.load_presets(dir_user_presets, PRESET_FILAMENT_NAME, substitutions, substitution_rule);
|
||||
filaments.select_preset_by_name(filament_selected_preset_name, false);
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
filaments.select_preset_by_name(sel, false);
|
||||
} catch (const std::runtime_error& err) { errors_cummulative += err.what(); }
|
||||
try {
|
||||
std::string printer_selected_preset_name = printers.get_selected_preset().name;
|
||||
std::string sel = printers.get_selected_preset().name;
|
||||
this->printers.load_presets(dir_user_presets, PRESET_PRINTER_NAME, substitutions, substitution_rule);
|
||||
printers.select_preset_by_name(printer_selected_preset_name, false);
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
printers.select_preset_by_name(sel, false);
|
||||
} catch (const std::runtime_error& err) { errors_cummulative += err.what(); }
|
||||
if (!errors_cummulative.empty()) throw Slic3r::RuntimeError(errors_cummulative);
|
||||
|
||||
// Persist any newly-loaded presets back to per-file caches.
|
||||
PresetBundleCache::update_file_caches(prints, (fs::path(dir_user_presets) / PRESET_PRINT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(filaments, (fs::path(dir_user_presets) / PRESET_FILAMENT_NAME).string());
|
||||
PresetBundleCache::update_file_caches(printers, (fs::path(dir_user_presets) / PRESET_PRINTER_NAME).string());
|
||||
const auto json_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - json_t0).count();
|
||||
BOOST_LOG_TRIVIAL(info) << "PresetBundle: user presets loaded from JSON in " << json_ms << " ms";
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
#include "PresetBundleCache.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/crc.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
#include <tbb/blocked_range.h>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include <cereal/archives/binary.hpp>
|
||||
#include <cereal/types/map.hpp>
|
||||
#include <cereal/types/polymorphic.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
|
||||
#include "Preset.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "Semver.hpp"
|
||||
@@ -29,7 +23,6 @@ namespace PresetBundleCache {
|
||||
// -------------------------------------------------------------------------
|
||||
// Binary cache file format: raw 20-byte header followed by cereal blob.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static constexpr uint32_t CACHE_MAGIC = 0x4F52435A; // "ORCZ"
|
||||
static constexpr uint32_t CACHE_FILE_VERSION = 1;
|
||||
|
||||
@@ -52,10 +45,8 @@ static void save_blob(const std::string& path, const T& obj)
|
||||
ar(obj);
|
||||
}
|
||||
const std::string blob = oss.str();
|
||||
|
||||
boost::crc_32_type crc;
|
||||
crc.process_bytes(blob.data(), blob.size());
|
||||
|
||||
try {
|
||||
boost::filesystem::create_directories(boost::filesystem::path(path).parent_path());
|
||||
boost::nowide::ofstream ofs(path, std::ios::binary | std::ios::trunc);
|
||||
@@ -82,7 +73,6 @@ static bool load_blob(const std::string& path, T& obj)
|
||||
boost::nowide::ifstream ifs(path, std::ios::binary);
|
||||
if (!ifs.is_open())
|
||||
return false;
|
||||
|
||||
CacheFileHeader hdr;
|
||||
if (!ifs.read(reinterpret_cast<char*>(&hdr), sizeof(hdr)))
|
||||
return false;
|
||||
@@ -90,18 +80,15 @@ static bool load_blob(const std::string& path, T& obj)
|
||||
return false;
|
||||
if (hdr.data_size == 0 || hdr.data_size > 512u * 1024u * 1024u)
|
||||
return false;
|
||||
|
||||
std::string blob(hdr.data_size, '\0');
|
||||
if (!ifs.read(&blob[0], static_cast<std::streamsize>(hdr.data_size)))
|
||||
return false;
|
||||
|
||||
boost::crc_32_type crc;
|
||||
crc.process_bytes(blob.data(), blob.size());
|
||||
if (crc.checksum() != hdr.crc32) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "PresetBundleCache: CRC32 mismatch: " << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::istringstream iss(blob, std::ios::in | std::ios::binary);
|
||||
cereal::BinaryInputArchive ar(iss);
|
||||
ar(obj);
|
||||
@@ -115,7 +102,6 @@ static bool load_blob(const std::string& path, T& obj)
|
||||
// -------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static std::string vendor_root_json(const std::string& system_dir, const std::string& vendor_id)
|
||||
{
|
||||
return (boost::filesystem::path(system_dir) / (vendor_id + ".json")).make_preferred().string();
|
||||
@@ -124,7 +110,6 @@ static std::string vendor_root_json(const std::string& system_dir, const std::st
|
||||
// -------------------------------------------------------------------------
|
||||
// SystemPresetsCache
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
std::string SystemPresetsCache::cache_path()
|
||||
{
|
||||
return (boost::filesystem::path(data_dir()) / PRESET_SYSTEM_DIR / "system_presets_cache.cache")
|
||||
@@ -137,7 +122,6 @@ bool SystemPresetsCache::is_valid(const std::string& system_dir) const
|
||||
return false;
|
||||
if (config_options_count != print_config_def.options.size())
|
||||
return false;
|
||||
|
||||
std::map<std::string, std::string> current;
|
||||
try {
|
||||
for (const auto& entry : boost::filesystem::directory_iterator(system_dir)) {
|
||||
@@ -153,7 +137,6 @@ bool SystemPresetsCache::is_valid(const std::string& system_dir) const
|
||||
BOOST_LOG_TRIVIAL(warning) << "PresetBundleCache: directory scan failed: " << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current.size() != vendor_versions.size())
|
||||
return false;
|
||||
for (const auto& [name, ver] : current) {
|
||||
@@ -180,12 +163,11 @@ void SystemPresetsCache::capture(const PresetBundle& bundle, const std::string&
|
||||
|
||||
for (const auto& [id, vp] : bundle.vendors) {
|
||||
CachedVendorProfile cvp;
|
||||
cvp.id = vp.id;
|
||||
cvp.name = vp.name;
|
||||
cvp.config_version = vp.config_version.valid() ? vp.config_version.to_string() : "";
|
||||
cvp.id = vp.id;
|
||||
cvp.name = vp.name;
|
||||
cvp.config_version = vp.config_version.valid() ? vp.config_version.to_string() : "";
|
||||
cvp.config_update_url = vp.config_update_url;
|
||||
cvp.changelog_url = vp.changelog_url;
|
||||
|
||||
cvp.changelog_url = vp.changelog_url;
|
||||
for (const auto& model : vp.models) {
|
||||
CachedPrinterModel cm;
|
||||
cm.id = model.id;
|
||||
@@ -195,26 +177,23 @@ void SystemPresetsCache::capture(const PresetBundle& bundle, const std::string&
|
||||
cm.technology = static_cast<int>(model.technology);
|
||||
for (const auto& v : model.variants)
|
||||
cm.variants.push_back({v.name});
|
||||
cm.default_materials = model.default_materials;
|
||||
cm.not_support_bed_types = model.not_support_bed_types;
|
||||
cm.bed_model = model.bed_model;
|
||||
cm.bed_texture = model.bed_texture;
|
||||
cm.image_bed_type = model.image_bed_type;
|
||||
cm.bottom_texture_end_name = model.bottom_texture_end_name;
|
||||
cm.default_materials = model.default_materials;
|
||||
cm.not_support_bed_types = model.not_support_bed_types;
|
||||
cm.bed_model = model.bed_model;
|
||||
cm.bed_texture = model.bed_texture;
|
||||
cm.image_bed_type = model.image_bed_type;
|
||||
cm.bottom_texture_end_name = model.bottom_texture_end_name;
|
||||
cm.use_double_extruder_default_texture = model.use_double_extruder_default_texture;
|
||||
cm.bottom_texture_rect = model.bottom_texture_rect;
|
||||
cm.middle_texture_rect = model.middle_texture_rect;
|
||||
cm.hotend_model = model.hotend_model;
|
||||
cm.bottom_texture_rect = model.bottom_texture_rect;
|
||||
cm.middle_texture_rect = model.middle_texture_rect;
|
||||
cm.hotend_model = model.hotend_model;
|
||||
cvp.models.push_back(std::move(cm));
|
||||
}
|
||||
|
||||
for (const auto& f : vp.default_filaments)
|
||||
cvp.default_filaments.push_back(f);
|
||||
for (const auto& m : vp.default_sla_materials)
|
||||
cvp.default_sla_materials.push_back(m);
|
||||
|
||||
vendor_profiles.push_back(std::move(cvp));
|
||||
|
||||
Semver ver = get_version_from_json(vendor_root_json(system_dir, id));
|
||||
vendor_versions[id] = ver.valid() ? ver.to_string() : "";
|
||||
}
|
||||
@@ -224,24 +203,23 @@ void SystemPresetsCache::capture(const PresetBundle& bundle, const std::string&
|
||||
if (!p.is_system)
|
||||
continue;
|
||||
CachedPreset cp;
|
||||
cp.type = static_cast<int>(p.type);
|
||||
cp.name = p.name;
|
||||
cp.alias = p.alias;
|
||||
cp.file = p.file;
|
||||
cp.version = p.version.valid() ? p.version.to_string() : "";
|
||||
cp.vendor_id = (p.vendor != nullptr) ? p.vendor->id : "";
|
||||
cp.filament_id = p.filament_id;
|
||||
cp.setting_id = p.setting_id;
|
||||
cp.description = p.description;
|
||||
cp.renamed_from = p.renamed_from;
|
||||
cp.is_system = p.is_system;
|
||||
cp.is_visible = p.is_visible;
|
||||
cp.type = static_cast<int>(p.type);
|
||||
cp.name = p.name;
|
||||
cp.alias = p.alias;
|
||||
cp.file = p.file;
|
||||
cp.version = p.version.valid() ? p.version.to_string() : "";
|
||||
cp.vendor_id = (p.vendor != nullptr) ? p.vendor->id : "";
|
||||
cp.filament_id = p.filament_id;
|
||||
cp.setting_id = p.setting_id;
|
||||
cp.description = p.description;
|
||||
cp.renamed_from = p.renamed_from;
|
||||
cp.is_system = p.is_system;
|
||||
cp.is_visible = p.is_visible;
|
||||
cp.m_from_orca_filament_lib = p.m_from_orca_filament_lib;
|
||||
cp.config = p.config;
|
||||
cp.config = p.config;
|
||||
out.push_back(std::move(cp));
|
||||
}
|
||||
};
|
||||
|
||||
capture_col(bundle.prints, print_presets);
|
||||
capture_col(bundle.filaments, filament_presets);
|
||||
capture_col(bundle.printers, printer_presets);
|
||||
@@ -252,7 +230,6 @@ void SystemPresetsCache::capture(const PresetBundle& bundle, const std::string&
|
||||
void SystemPresetsCache::apply(PresetBundle& bundle) const
|
||||
{
|
||||
bundle.reset(false);
|
||||
|
||||
for (const auto& cvp : vendor_profiles) {
|
||||
VendorProfile vp(cvp.id);
|
||||
vp.name = cvp.name;
|
||||
@@ -262,7 +239,6 @@ void SystemPresetsCache::apply(PresetBundle& bundle) const
|
||||
auto v = Semver::parse(cvp.config_version);
|
||||
if (v) vp.config_version = *v;
|
||||
}
|
||||
|
||||
for (const auto& cm : cvp.models) {
|
||||
VendorProfile::PrinterModel model;
|
||||
model.id = cm.id;
|
||||
@@ -272,24 +248,22 @@ void SystemPresetsCache::apply(PresetBundle& bundle) const
|
||||
model.technology = static_cast<PrinterTechnology>(cm.technology);
|
||||
for (const auto& v : cm.variants)
|
||||
model.variants.emplace_back(v.name);
|
||||
model.default_materials = cm.default_materials;
|
||||
model.not_support_bed_types = cm.not_support_bed_types;
|
||||
model.bed_model = cm.bed_model;
|
||||
model.bed_texture = cm.bed_texture;
|
||||
model.image_bed_type = cm.image_bed_type;
|
||||
model.bottom_texture_end_name = cm.bottom_texture_end_name;
|
||||
model.default_materials = cm.default_materials;
|
||||
model.not_support_bed_types = cm.not_support_bed_types;
|
||||
model.bed_model = cm.bed_model;
|
||||
model.bed_texture = cm.bed_texture;
|
||||
model.image_bed_type = cm.image_bed_type;
|
||||
model.bottom_texture_end_name = cm.bottom_texture_end_name;
|
||||
model.use_double_extruder_default_texture = cm.use_double_extruder_default_texture;
|
||||
model.bottom_texture_rect = cm.bottom_texture_rect;
|
||||
model.middle_texture_rect = cm.middle_texture_rect;
|
||||
model.hotend_model = cm.hotend_model;
|
||||
model.bottom_texture_rect = cm.bottom_texture_rect;
|
||||
model.middle_texture_rect = cm.middle_texture_rect;
|
||||
model.hotend_model = cm.hotend_model;
|
||||
vp.models.push_back(std::move(model));
|
||||
}
|
||||
|
||||
for (const auto& f : cvp.default_filaments)
|
||||
vp.default_filaments.insert(f);
|
||||
for (const auto& m : cvp.default_sla_materials)
|
||||
vp.default_sla_materials.insert(m);
|
||||
|
||||
bundle.vendors.emplace(cvp.id, std::move(vp));
|
||||
}
|
||||
|
||||
@@ -304,26 +278,23 @@ void SystemPresetsCache::apply(PresetBundle& bundle) const
|
||||
}
|
||||
DynamicPrintConfig config = cp.config;
|
||||
Preset& p = coll.load_preset(cp.file, cp.name, std::move(config), /*select=*/false, version);
|
||||
p.is_system = true;
|
||||
p.is_visible = cp.is_visible;
|
||||
p.alias = cp.alias;
|
||||
p.renamed_from = cp.renamed_from;
|
||||
p.filament_id = cp.filament_id;
|
||||
p.setting_id = cp.setting_id;
|
||||
p.description = cp.description;
|
||||
p.is_system = true;
|
||||
p.is_visible = cp.is_visible;
|
||||
p.alias = cp.alias;
|
||||
p.renamed_from = cp.renamed_from;
|
||||
p.filament_id = cp.filament_id;
|
||||
p.setting_id = cp.setting_id;
|
||||
p.description = cp.description;
|
||||
p.m_from_orca_filament_lib = cp.m_from_orca_filament_lib;
|
||||
|
||||
if (!cp.vendor_id.empty()) {
|
||||
auto it = bundle.vendors.find(cp.vendor_id);
|
||||
if (it != bundle.vendors.end())
|
||||
p.vendor = &it->second;
|
||||
}
|
||||
|
||||
if (is_filaments)
|
||||
coll.set_printer_hold_alias(p.alias, p);
|
||||
}
|
||||
};
|
||||
|
||||
apply_col(print_presets, bundle.prints, false);
|
||||
apply_col(filament_presets, bundle.filaments, true);
|
||||
apply_col(printer_presets, bundle.printers, false);
|
||||
@@ -345,251 +316,5 @@ void SystemPresetsCache::save(const std::string& path) const
|
||||
save_blob(path, *this);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// PresetFileCache
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
std::string PresetFileCache::cache_path_for(const std::string& json_path)
|
||||
{
|
||||
boost::filesystem::path p(json_path);
|
||||
p.replace_extension(".cache");
|
||||
return p.string();
|
||||
}
|
||||
|
||||
bool PresetFileCache::is_valid(const std::string& json_path) const
|
||||
{
|
||||
if (format_version != FORMAT_VERSION)
|
||||
return false;
|
||||
if (config_options_count != print_config_def.options.size())
|
||||
return false;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
const fs::path json(json_path);
|
||||
if (!fs::exists(json))
|
||||
return false;
|
||||
|
||||
int64_t cur_json_mtime = 0;
|
||||
try {
|
||||
cur_json_mtime = static_cast<int64_t>(fs::last_write_time(json));
|
||||
} catch (...) { return false; }
|
||||
if (json_mtime != cur_json_mtime)
|
||||
return false;
|
||||
|
||||
fs::path info = json;
|
||||
info.replace_extension(".info");
|
||||
int64_t cur_info_mtime = 0;
|
||||
if (fs::exists(info)) {
|
||||
try {
|
||||
cur_info_mtime = static_cast<int64_t>(fs::last_write_time(info));
|
||||
} catch (...) { return false; }
|
||||
}
|
||||
return info_mtime == cur_info_mtime;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// preload_file_caches / update_file_caches
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int preload_file_caches(PresetCollection& coll, const std::string& dir_path,
|
||||
const PresetOrigin& origin)
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
const fs::path dir(dir_path);
|
||||
if (!fs::exists(dir))
|
||||
return 0;
|
||||
|
||||
// Step 1: collect .json paths (fast, sequential).
|
||||
std::vector<std::string> json_paths;
|
||||
try {
|
||||
for (const auto& entry : fs::directory_iterator(dir)) {
|
||||
if (fs::is_regular_file(entry.path()) &&
|
||||
entry.path().extension().string() == ".json")
|
||||
json_paths.push_back(entry.path().string());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "PresetBundleCache: dir scan failed ("
|
||||
<< dir_path << "): " << e.what();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Step 2: load + deserialize each .cache file in parallel.
|
||||
// Each slot is independent - no shared state touched here.
|
||||
struct LoadResult {
|
||||
std::string json_path;
|
||||
std::string canonical_name;
|
||||
PresetFileCache pfc;
|
||||
bool valid = false;
|
||||
};
|
||||
std::vector<LoadResult> results(json_paths.size());
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, json_paths.size()),
|
||||
[&](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||
const std::string& json_path = json_paths[i];
|
||||
const std::string cache_path = PresetFileCache::cache_path_for(json_path);
|
||||
|
||||
PresetFileCache pfc;
|
||||
if (!load_blob(cache_path, pfc) || !pfc.is_valid(json_path))
|
||||
continue;
|
||||
|
||||
const std::string stem = fs::path(json_path).stem().string();
|
||||
results[i].json_path = json_path;
|
||||
results[i].canonical_name = get_preset_canonical_name(stem, origin);
|
||||
results[i].pfc = std::move(pfc);
|
||||
results[i].valid = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Step 3: sequential merge into the collection (load_preset uses a lock).
|
||||
const bool is_filaments = (coll.type() == Preset::TYPE_FILAMENT);
|
||||
int loaded = 0;
|
||||
for (auto& r : results) {
|
||||
if (!r.valid)
|
||||
continue;
|
||||
|
||||
Semver version;
|
||||
if (!r.pfc.preset.version.empty()) {
|
||||
auto v = Semver::parse(r.pfc.preset.version);
|
||||
if (v) version = *v;
|
||||
}
|
||||
|
||||
DynamicPrintConfig config = r.pfc.preset.config;
|
||||
Preset& p = coll.load_preset(r.json_path, r.canonical_name,
|
||||
std::move(config), /*select=*/false, version);
|
||||
p.is_system = false;
|
||||
p.is_visible = r.pfc.preset.is_visible;
|
||||
p.alias = r.pfc.preset.alias;
|
||||
p.filament_id = r.pfc.preset.filament_id;
|
||||
p.setting_id = r.pfc.preset.setting_id;
|
||||
p.description = r.pfc.preset.description;
|
||||
p.base_id = r.pfc.preset.base_id;
|
||||
p.user_id = r.pfc.preset.user_id;
|
||||
p.sync_info = r.pfc.preset.sync_info;
|
||||
p.updated_time = r.pfc.preset.updated_time;
|
||||
p.renamed_from = r.pfc.preset.renamed_from;
|
||||
p.bundle_id = origin.bundle_id;
|
||||
|
||||
if (is_filaments)
|
||||
coll.set_printer_hold_alias(p.alias, p);
|
||||
|
||||
++loaded;
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void update_file_caches(const PresetCollection& coll, const std::string& dir_path)
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
const std::string norm_dir = fs::path(dir_path).make_preferred().string();
|
||||
|
||||
// Step 1: collect candidate presets (sequential, fast).
|
||||
std::vector<const Preset*> candidates;
|
||||
for (const Preset& p : coll()) {
|
||||
if (p.is_system || p.is_default || p.file.empty())
|
||||
continue;
|
||||
const std::string norm_file = fs::path(p.file).make_preferred().string();
|
||||
if (norm_file.rfind(norm_dir, 0) != 0)
|
||||
continue;
|
||||
candidates.push_back(&p);
|
||||
}
|
||||
|
||||
// Step 2: check + write each .cache file in parallel.
|
||||
// Each write targets an independent file path - no shared state.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, candidates.size()),
|
||||
[&](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||
const Preset& p = *candidates[i];
|
||||
const std::string cache_path = PresetFileCache::cache_path_for(p.file);
|
||||
|
||||
PresetFileCache existing;
|
||||
if (load_blob(cache_path, existing) && existing.is_valid(p.file))
|
||||
continue;
|
||||
|
||||
PresetFileCache pfc;
|
||||
pfc.format_version = PresetFileCache::FORMAT_VERSION;
|
||||
pfc.config_options_count = print_config_def.options.size();
|
||||
|
||||
try {
|
||||
pfc.json_mtime = static_cast<int64_t>(
|
||||
fs::last_write_time(fs::path(p.file)));
|
||||
} catch (...) {}
|
||||
|
||||
fs::path info_path = fs::path(p.file);
|
||||
info_path.replace_extension(".info");
|
||||
if (fs::exists(info_path)) {
|
||||
try {
|
||||
pfc.info_mtime = static_cast<int64_t>(
|
||||
fs::last_write_time(info_path));
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
CachedPreset& cp = pfc.preset;
|
||||
cp.type = static_cast<int>(p.type);
|
||||
cp.name = p.name;
|
||||
cp.alias = p.alias;
|
||||
cp.file = p.file;
|
||||
cp.version = p.version.valid() ? p.version.to_string() : "";
|
||||
cp.filament_id = p.filament_id;
|
||||
cp.setting_id = p.setting_id;
|
||||
cp.description = p.description;
|
||||
cp.base_id = p.base_id;
|
||||
cp.user_id = p.user_id;
|
||||
cp.sync_info = p.sync_info;
|
||||
cp.updated_time = p.updated_time;
|
||||
cp.renamed_from = p.renamed_from;
|
||||
cp.is_system = false;
|
||||
cp.is_visible = p.is_visible;
|
||||
cp.config = p.config;
|
||||
|
||||
save_blob(cache_path, pfc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void write_file_cache(const Preset& preset)
|
||||
{
|
||||
if (preset.is_system || preset.is_default || preset.is_project_embedded || preset.file.empty())
|
||||
return;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
const std::string cache_path = PresetFileCache::cache_path_for(preset.file);
|
||||
|
||||
PresetFileCache pfc;
|
||||
pfc.format_version = PresetFileCache::FORMAT_VERSION;
|
||||
pfc.config_options_count = print_config_def.options.size();
|
||||
|
||||
try {
|
||||
pfc.json_mtime = static_cast<int64_t>(fs::last_write_time(fs::path(preset.file)));
|
||||
} catch (...) {}
|
||||
|
||||
fs::path info_path = fs::path(preset.file);
|
||||
info_path.replace_extension(".info");
|
||||
if (fs::exists(info_path)) {
|
||||
try {
|
||||
pfc.info_mtime = static_cast<int64_t>(fs::last_write_time(info_path));
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
CachedPreset& cp = pfc.preset;
|
||||
cp.type = static_cast<int>(preset.type);
|
||||
cp.name = preset.name;
|
||||
cp.alias = preset.alias;
|
||||
cp.file = preset.file;
|
||||
cp.version = preset.version.valid() ? preset.version.to_string() : "";
|
||||
cp.filament_id = preset.filament_id;
|
||||
cp.setting_id = preset.setting_id;
|
||||
cp.description = preset.description;
|
||||
cp.base_id = preset.base_id;
|
||||
cp.user_id = preset.user_id;
|
||||
cp.sync_info = preset.sync_info;
|
||||
cp.updated_time = preset.updated_time;
|
||||
cp.renamed_from = preset.renamed_from;
|
||||
cp.is_system = false;
|
||||
cp.is_visible = preset.is_visible;
|
||||
cp.config = preset.config;
|
||||
|
||||
save_blob(cache_path, pfc);
|
||||
}
|
||||
|
||||
} // namespace PresetBundleCache
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
|
||||
#include "Preset.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -30,7 +29,7 @@ struct CachedPrinterVariant {
|
||||
|
||||
struct CachedPrinterModel {
|
||||
std::string id, name, model_id, family;
|
||||
int technology = 0; // PrinterTechnology enum
|
||||
int technology = 0;
|
||||
std::vector<CachedPrinterVariant> variants;
|
||||
std::vector<std::string> default_materials;
|
||||
std::vector<std::string> not_support_bed_types;
|
||||
@@ -62,12 +61,12 @@ struct CachedVendorProfile {
|
||||
}
|
||||
};
|
||||
|
||||
// ---- Per-preset cache entry (shared by system and per-file caches) ----
|
||||
// ---- Per-preset cache entry ----
|
||||
|
||||
struct CachedPreset {
|
||||
int type = 0; // Preset::Type
|
||||
int type = 0;
|
||||
std::string name, alias, file, version;
|
||||
std::string vendor_id; // reconstruct Preset::vendor pointer (system only)
|
||||
std::string vendor_id;
|
||||
std::string filament_id, setting_id, description;
|
||||
std::string base_id, user_id, sync_info;
|
||||
long long updated_time = 0;
|
||||
@@ -87,7 +86,9 @@ struct CachedPreset {
|
||||
};
|
||||
|
||||
// ---- System preset cache ----
|
||||
// Stored next to vendor JSONs: <data_dir>/system/system_presets_cache.bin
|
||||
// Single blob at <data_dir>/system/system_presets_cache.cache
|
||||
// Covers all vendor profiles and system presets.
|
||||
// Invalidated when any vendor version string changes or config option count changes.
|
||||
|
||||
struct SystemPresetsCache {
|
||||
static constexpr uint32_t FORMAT_VERSION = 2;
|
||||
@@ -125,46 +126,5 @@ struct SystemPresetsCache {
|
||||
void save(const std::string& path) const;
|
||||
};
|
||||
|
||||
// ---- Per-file preset cache ----
|
||||
// Each <name>.json gets a sibling <name>.cache file.
|
||||
// Invalidated when json or info mtime changes, or when the app binary changes.
|
||||
|
||||
struct PresetFileCache {
|
||||
static constexpr uint32_t FORMAT_VERSION = 1;
|
||||
|
||||
uint32_t format_version = FORMAT_VERSION;
|
||||
size_t config_options_count = 0;
|
||||
int64_t json_mtime = 0; // last_write_time of .json file
|
||||
int64_t info_mtime = 0; // last_write_time of .info file (0 = doesn't exist)
|
||||
CachedPreset preset;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar)
|
||||
{
|
||||
ar(format_version, config_options_count, json_mtime, info_mtime, preset);
|
||||
}
|
||||
|
||||
// Returns the path of the .cache file sibling to json_path.
|
||||
static std::string cache_path_for(const std::string& json_path);
|
||||
|
||||
// Returns true when the stored mtimes still match the current filesystem state.
|
||||
bool is_valid(const std::string& json_path) const;
|
||||
};
|
||||
|
||||
// Pre-load cached presets from all valid .cache files found in dir_path.
|
||||
// Presets are inserted into coll via load_preset() so that a subsequent
|
||||
// load_presets() call will skip them. Returns the count of presets loaded.
|
||||
int preload_file_caches(PresetCollection& coll, const std::string& dir_path,
|
||||
const PresetOrigin& origin);
|
||||
|
||||
// Write (or overwrite) .cache files for presets in coll whose json .file is
|
||||
// inside dir_path and whose existing .cache (if any) is stale or missing.
|
||||
void update_file_caches(const PresetCollection& coll, const std::string& dir_path);
|
||||
|
||||
// Write (or overwrite) the .cache file for a single preset immediately after
|
||||
// its .json has been written to disk. Safe to call from Preset::save().
|
||||
// Does nothing for system, default, or project-embedded presets.
|
||||
void write_file_cache(const Preset& preset);
|
||||
|
||||
} // namespace PresetBundleCache
|
||||
} // namespace Slic3r
|
||||
} // namespace Slic3r
|
||||
Reference in New Issue
Block a user