diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 3f242337b6..6f9c71a12d 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -306,8 +306,10 @@ jobs: shell: pwsh run: | $tool = Get-ChildItem -Recurse -Path build -Filter "generate_system_cache.exe" | Select-Object -First 1 + if (-not $tool) { Write-Error "generate_system_cache.exe not found in build tree"; exit 1 } $profiles = Get-ChildItem -Recurse -Path build -Directory -Filter profiles | Where-Object { $_.FullName -match 'resources' } | Select-Object -First 1 + if (-not $profiles) { Write-Error "profiles directory not found in build tree"; exit 1 } & $tool.FullName --path $profiles.FullName --log_level 2 - name: Create installer Win @@ -423,12 +425,13 @@ jobs: shell: bash run: | tool=$(find build -name generate_system_cache -type f | head -1) + if [ -z "$tool" ]; then echo "ERROR: generate_system_cache not found in build tree" >&2; exit 1; fi "$tool" --path build/package/resources/profiles --log_level 2 - # Re-pack the AppImage so the cache is included + # Re-pack the AppImage so the per-vendor caches are included appimage=$(find build -maxdepth 1 -name "OrcaSlicer_Linux_AppImage*.AppImage" | head -1) chmod +x "$appimage" "$appimage" --appimage-extract - cp build/package/resources/profiles/system_presets_cache.cache squashfs-root/resources/profiles/ + cp build/package/resources/profiles/*.cache squashfs-root/resources/profiles/ appimagetool=$(find build -name "appimagetool.AppImage" | head -1) ARCH=$(uname -m) "$appimagetool" --appimage-extract-and-run squashfs-root "$appimage" rm -rf squashfs-root diff --git a/src/dev-utils/CMakeLists.txt b/src/dev-utils/CMakeLists.txt index ccaf24a96d..5312221a42 100644 --- a/src/dev-utils/CMakeLists.txt +++ b/src/dev-utils/CMakeLists.txt @@ -23,7 +23,7 @@ endif() if (ORCA_TOOLS) set(_DEV_DEFS -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x602 -DBOOST_SYSTEM_USE_UTF8) - # generate_system_cache: pre-generates resources/profiles/system_presets_cache.cache for CI bundling. + # generate_system_cache: pre-generates per-vendor resources/profiles/.cache files for CI bundling. add_executable(generate_system_cache generate_system_cache.cpp) target_link_libraries(generate_system_cache libslic3r boost_headeronly) target_compile_definitions(generate_system_cache PRIVATE ${_DEV_DEFS}) diff --git a/src/dev-utils/generate_system_cache.cpp b/src/dev-utils/generate_system_cache.cpp index a46a761c20..6685f40037 100644 --- a/src/dev-utils/generate_system_cache.cpp +++ b/src/dev-utils/generate_system_cache.cpp @@ -1,5 +1,5 @@ #include "libslic3r/PresetBundle.hpp" -#include "libslic3r/PresetBundleCache.hpp" +#include "libslic3r/Preset.hpp" #include "libslic3r/Utils.hpp" #include @@ -70,17 +70,59 @@ int main(int argc, char* argv[]) return 1; } - const std::string cache_path = - (fs::path(profiles_path) / "system_presets_cache.cache").make_preferred().string(); + // Collect all vendor names from JSON files in the profiles directory. + std::vector vendor_names; + for (const auto& e : fs::directory_iterator(profiles_path)) { + if (e.path().extension() == ".json") + vendor_names.push_back(e.path().stem().string()); + } - PresetBundleCache::SystemPresetsCache cache; - cache.capture(*preset_bundle, profiles_path); - cache.save(cache_path); + // Sort: PresetBundle::ORCA_FILAMENT_LIBRARY first, rest alphabetical. + std::sort(vendor_names.begin(), vendor_names.end(), + [](const std::string& a, const std::string& b) { + if (a == PresetBundle::ORCA_FILAMENT_LIBRARY) return true; + if (b == PresetBundle::ORCA_FILAMENT_LIBRARY) return false; + return a < b; + }); - std::cout << "Cache written: " << cache_path << "\n" - << " Vendor profiles: " << cache.vendor_profiles.size() << "\n" - << " Print presets: " << cache.print_presets.size() << "\n" - << " Filament presets: " << cache.filament_presets.size() << "\n" - << " Printer presets: " << cache.printer_presets.size() << "\n"; - return 0; + size_t total_print = 0, total_filament = 0, total_printer = 0; + int saved = 0, failed = 0; + + for (const auto& vendor_name : vendor_names) { + const std::string json_path = (fs::path(profiles_path) / (vendor_name + ".json")).string(); + const Semver ver = get_version_from_json(json_path); + const std::string ver_str = ver.valid() ? ver.to_string() : ""; + + const bool is_orca_lib = (vendor_name == PresetBundle::ORCA_FILAMENT_LIBRARY); + Slic3r::VendorCache vc; + vc.capture(*preset_bundle, vendor_name, ver_str, is_orca_lib); + + const std::string cache_path = + (fs::path(profiles_path) / (vendor_name + ".cache")).make_preferred().string(); + vc.save(cache_path); + + // Verify the file was written and can be reloaded. + Slic3r::VendorCache verify; + if (!verify.load(cache_path) || !verify.is_valid(ver_str)) { + std::cerr << "WARNING: verification failed for " << cache_path << "\n"; + ++failed; + } else { + std::cout << " [ok] " << vendor_name << ".cache" + << " (" << vc.print_presets.size() << " print, " + << vc.filament_presets.size() << " filament, " + << vc.printer_presets.size() << " printer)\n"; + total_print += vc.print_presets.size(); + total_filament += vc.filament_presets.size(); + total_printer += vc.printer_presets.size(); + ++saved; + } + } + + std::cout << "\nDone: " << saved << " cache(s) written"; + if (failed) std::cout << ", " << failed << " FAILED"; + std::cout << "\n" + << " Total print presets: " << total_print << "\n" + << " Total filament presets: " << total_filament << "\n" + << " Total printer presets: " << total_printer << "\n"; + return failed ? 1 : 0; } diff --git a/src/dev-utils/inspect_system_cache.cpp b/src/dev-utils/inspect_system_cache.cpp index d8d548bf50..97c1ae1856 100644 --- a/src/dev-utils/inspect_system_cache.cpp +++ b/src/dev-utils/inspect_system_cache.cpp @@ -1,22 +1,106 @@ -#include "libslic3r/PresetBundleCache.hpp" +#include "libslic3r/PresetBundle.hpp" +#include #include #include #include using namespace Slic3r; +namespace fs = boost::filesystem; namespace po = boost::program_options; static void print_bar(char c, int n) { std::cout << std::string(n, c) << "\n"; } +static void inspect_one(const std::string& path, const po::variables_map& vm) +{ + Slic3r::VendorCache vc; + if (!vc.load(path)) { + std::cerr << "Failed to load cache: " << path << "\n" + << " (wrong format version, truncated file, CRC mismatch, or not a .cache file)\n"; + return; + } + + bool show_all = !vm.count("vendors") && !vm.count("models") && + !vm.count("presets") && !vm.count("filaments") && + !vm.count("printers") && !vm.count("process"); + + // ---- Summary ---- + print_bar('=', 60); + std::cout << "Cache file : " << path << "\n"; + std::cout << "Vendor : " << vc.profile.id << " v" << vc.profile.config_version << "\n"; + std::cout << "JSON version: " << (vc.vendor_json_version.empty() ? "(none)" : vc.vendor_json_version) << "\n"; + std::cout << "Cache ver : " << vc.cache_version << "\n"; + std::cout << "Config opts : " << vc.config_options_count << "\n"; + print_bar('-', 60); + std::cout << "Models : " << vc.profile.models.size() << "\n"; + std::cout << "Printers : " << vc.printer_presets.size() << "\n"; + std::cout << "Filaments : " << vc.filament_presets.size() << "\n"; + std::cout << "Print proc : " << vc.print_presets.size() << "\n"; + std::cout << "SLA print : " << vc.sla_print_presets.size() << "\n"; + std::cout << "SLA material: " << vc.sla_material_presets.size() << "\n"; + std::cout << "config_maps : " << vc.config_maps.size() << "\n"; + std::cout << "filament_id_maps: " << vc.filament_id_maps.size() << "\n"; + print_bar('=', 60); + + // ---- Models ---- + if (show_all || vm.count("vendors") || vm.count("models")) { + std::cout << "\nVENDOR PROFILE [" << vc.profile.id << "]\n"; + print_bar('-', 60); + std::cout << " Name: " << vc.profile.name << "\n"; + std::cout << " Config version: " << vc.profile.config_version << "\n"; + if (vm.count("models") || show_all) { + for (const auto& m : vc.profile.models) { + std::cout << " " << std::left << std::setw(40) << m.name + << " variants:" << m.variants.size() << "\n"; + } + } + } + + // ---- Printer presets ---- + if (vm.count("presets") || vm.count("printers")) { + std::cout << "\nPRINTER PRESETS (" << vc.printer_presets.size() << ")\n"; + print_bar('-', 60); + for (const auto& cp : vc.printer_presets) { + const auto* pm = cp.config.option("printer_model"); + const auto* pv = cp.config.option("printer_variant"); + std::cout << " " << std::left << std::setw(50) << cp.name + << " model=" << (pm ? pm->value : "?") + << " nozzle=" << (pv ? pv->value : "?") + << (cp.is_visible ? "" : " [hidden]") << "\n"; + } + } + + // ---- Filament presets ---- + if (vm.count("presets") || vm.count("filaments")) { + std::cout << "\nFILAMENT PRESETS (" << vc.filament_presets.size() << ")\n"; + print_bar('-', 60); + for (const auto& cp : vc.filament_presets) { + const auto* fv = cp.config.option("filament_vendor"); + const auto* ft = cp.config.option("filament_type"); + std::cout << " " << std::left << std::setw(50) << cp.name + << " vendor=" << (fv && !fv->values.empty() ? fv->values[0] : "?") + << " type=" << (ft && !ft->values.empty() ? ft->values[0] : "?") + << (cp.is_visible ? "" : " [hidden]") << "\n"; + } + } + + // ---- Print process presets ---- + if (vm.count("presets") || vm.count("process")) { + std::cout << "\nPRINT PROCESS PRESETS (" << vc.print_presets.size() << ")\n"; + print_bar('-', 60); + for (const auto& cp : vc.print_presets) + std::cout << " " << cp.name << (cp.is_visible ? "" : " [hidden]") << "\n"; + } +} + int main(int argc, char* argv[]) { po::options_description desc("OrcaSlicer Cache Inspector\nUsage"); desc.add_options() ("help,h", "Show help") - ("path,p", po::value(), "Path to .cache file (required)") - ("vendors,V", "List all vendor IDs and versions") - ("models,m", "List all printer models per vendor") + ("path,p", po::value(), "Path to a .cache file or a directory of .cache files (required)") + ("vendors,V", "Show vendor profile summary") + ("models,m", "List all printer models") ("presets,P", "List all preset names") ("filaments,f", "List filament presets") ("printers,r", "List printer presets") @@ -33,93 +117,17 @@ int main(int argc, char* argv[]) const std::string path = vm["path"].as(); - PresetBundleCache::SystemPresetsCache cache; - if (!cache.load(path)) { - std::cerr << "Failed to load cache: " << path << "\n" - << " (wrong format version, truncated file, or not a .cache file)\n"; - return 1; - } - - // ---- Summary ---- - print_bar('=', 60); - std::cout << "Cache file : " << path << "\n"; - std::cout << "Format ver : " << cache.format_version << "\n"; - std::cout << "Config opts: " << cache.config_options_count << "\n"; - print_bar('-', 60); - std::cout << "Vendors : " << cache.vendor_versions.size() << "\n"; - std::cout << "Models : "; - size_t total_models = 0; - for (const auto& vp : cache.vendor_profiles) total_models += vp.models.size(); - std::cout << total_models << "\n"; - std::cout << "Printers : " << cache.printer_presets.size() << "\n"; - std::cout << "Filaments : " << cache.filament_presets.size() << "\n"; - std::cout << "Print proc : " << cache.print_presets.size() << "\n"; - std::cout << "config_maps: " << cache.config_maps.size() << "\n"; - std::cout << "filament_id_maps: " << cache.filament_id_maps.size() << "\n"; - print_bar('=', 60); - - bool show_all = !vm.count("vendors") && !vm.count("models") && - !vm.count("presets") && !vm.count("filaments") && - !vm.count("printers") && !vm.count("process"); - - // ---- Vendor versions ---- - if (show_all || vm.count("vendors")) { - std::cout << "\nVENDOR VERSIONS (" << cache.vendor_versions.size() << ")\n"; - print_bar('-', 60); - for (const auto& [id, ver] : cache.vendor_versions) - std::cout << " " << std::left << std::setw(30) << id << " " << ver << "\n"; - } - - // ---- Models per vendor ---- - if (show_all || vm.count("models")) { - std::cout << "\nVENDOR PROFILES & MODELS\n"; - print_bar('-', 60); - for (const auto& vp : cache.vendor_profiles) { - std::cout << " [" << vp.id << "] v" << vp.config_version - << " (" << vp.models.size() << " models)\n"; - if (vm.count("models")) { - for (const auto& m : vp.models) { - std::cout << " " << std::left << std::setw(40) << m.name - << " variants:" << m.variants.size() << "\n"; - } - } - } - } - - // ---- Printer presets ---- - if (vm.count("presets") || vm.count("printers")) { - std::cout << "\nPRINTER PRESETS (" << cache.printer_presets.size() << ")\n"; - print_bar('-', 60); - for (const auto& cp : cache.printer_presets) { - const auto* pm = cp.config.option("printer_model"); - const auto* pv = cp.config.option("printer_variant"); - std::cout << " " << std::left << std::setw(50) << cp.name - << " model=" << (pm ? pm->value : "?") - << " nozzle=" << (pv ? pv->value : "?") - << (cp.is_visible ? "" : " [hidden]") << "\n"; - } - } - - // ---- Filament presets ---- - if (vm.count("presets") || vm.count("filaments")) { - std::cout << "\nFILAMENT PRESETS (" << cache.filament_presets.size() << ")\n"; - print_bar('-', 60); - for (const auto& cp : cache.filament_presets) { - const auto* fv = cp.config.option("filament_vendor"); - const auto* ft = cp.config.option("filament_type"); - std::cout << " " << std::left << std::setw(50) << cp.name - << " vendor=" << (fv ? fv->value : "?") - << " type=" << (ft && !ft->values.empty() ? ft->values[0] : "?") - << (cp.is_visible ? "" : " [hidden]") << "\n"; - } - } - - // ---- Print process presets ---- - if (vm.count("presets") || vm.count("process")) { - std::cout << "\nPRINT PROCESS PRESETS (" << cache.print_presets.size() << ")\n"; - print_bar('-', 60); - for (const auto& cp : cache.print_presets) - std::cout << " " << cp.name << (cp.is_visible ? "" : " [hidden]") << "\n"; + if (fs::is_directory(path)) { + // Inspect all .cache files in the directory. + std::vector files; + for (const auto& e : fs::directory_iterator(path)) + if (e.path().extension() == ".cache") + files.push_back(e.path()); + std::sort(files.begin(), files.end()); + for (const auto& f : files) + inspect_one(f.string(), vm); + } else { + inspect_one(path, vm); } return 0; diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 80aa365bec..9b67d7ab50 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -344,8 +344,6 @@ set(lisbslic3r_sources Polyline.hpp PresetBundle.cpp PresetBundle.hpp - PresetBundleCache.cpp - PresetBundleCache.hpp Preset.cpp Preset.hpp PrincipalComponents2D.cpp