mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-08 09:46:55 +00:00
fix more issues
This commit is contained in:
@@ -392,7 +392,7 @@ int main(int argc, char* argv[])
|
||||
("generate_presets,g", po::value<bool>()->default_value(false), "Generate user presets for mock test")
|
||||
("slice,s", po::bool_switch()->default_value(false), "Slice a two-colour cube through every printer to expand all custom g-code (catches placeholder/flow errors that static checks miss). Off unless this flag is present.")
|
||||
("outdir,o", po::value<std::string>()->default_value(""), "With -s, also save each printer's g-code to this folder (as <vendor>__<printer>.gcode) for manual inspection. Optional.")
|
||||
("check_filament_subtypes,f", po::bool_switch()->default_value(false), "Also flag printers with duplicate (ambiguous) filament subtypes. Off unless this flag is present.")
|
||||
("check_filament_subtypes,f", po::bool_switch()->default_value(true), "Also flag printers with duplicate (ambiguous) filament subtypes. Off unless this flag is present.")
|
||||
("log_level,l", po::value<int>()->default_value(2), "Log level. Optional, default is 2 (warning). Higher values produce more detailed logs.");
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -16,6 +18,12 @@ namespace {
|
||||
|
||||
constexpr const char* CrealityPrintAgent_VERSION = "0.1.0";
|
||||
|
||||
std::string to_lower(std::string s)
|
||||
{
|
||||
for (auto& c : s) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
return s;
|
||||
}
|
||||
|
||||
bool has_visible_base_preset(const PresetCollection& filaments, const std::string& filament_id)
|
||||
{
|
||||
for (const auto& p : filaments.get_presets()) {
|
||||
@@ -27,19 +35,47 @@ bool has_visible_base_preset(const PresetCollection& filaments, const std::strin
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lower-case words of a preset name with the "@scope" suffix dropped:
|
||||
// "Generic PLA Matte @Creality K2-all" -> {"generic", "pla", "matte"}.
|
||||
std::vector<std::string> name_words(const std::string& name)
|
||||
{
|
||||
std::vector<std::string> words;
|
||||
std::string word;
|
||||
for (char c : name.substr(0, name.find('@'))) {
|
||||
if (std::isalnum(static_cast<unsigned char>(c))) {
|
||||
word += static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
} else if (!word.empty()) {
|
||||
words.push_back(word);
|
||||
word.clear();
|
||||
}
|
||||
}
|
||||
if (!word.empty())
|
||||
words.push_back(word);
|
||||
return words;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Score visible compatible filament presets against the CFS spool metadata and
|
||||
// return the best-matching filament_id. Scoring:
|
||||
// +20 preset name contains brand_name as a substring
|
||||
// (e.g. "Hyper PLA" in "Hyper PLA @Creality K2 0.4 nozzle")
|
||||
// +10 preset name contains the vendor substring (e.g. "Creality")
|
||||
// Tiebreak: prefer the SYSTEM (shipped) preset over user copies. Brand-
|
||||
// specific system presets carry their own filament_id; user copies of
|
||||
// generic presets inherit a generic filament_id from their parent, so
|
||||
// preferring the user copy can collapse a brand-specific match back to
|
||||
// "Generic PLA" via the inherited id. Plus: this code targets upstream
|
||||
// OrcaSlicer where shipping the user's local tuning would be wrong.
|
||||
// +10 the preset belongs to the spool's vendor - by its owning VendorProfile OR by
|
||||
// its name. The profile test is what finds the vendor's own generics, which are
|
||||
// named "Generic <material> @<scope>" and do not repeat the vendor; the name test
|
||||
// still finds a third party filament shipped inside that vendor's bundle, which
|
||||
// carries the bundle owner's profile but names its real brand.
|
||||
// -5 per word of the preset name the spool never mentioned ("generic" excepted -
|
||||
// it marks the unbranded base product rather than a qualifier), so the least
|
||||
// specific preset that still explains the spool wins. Without it a spool
|
||||
// reporting only "PLA" scores "Generic PLA High Speed" and "Generic PLA Matte"
|
||||
// exactly as high as "Generic PLA"; those are three products with three
|
||||
// filament_ids, so whichever sorted first won and the printer got the wrong
|
||||
// one. Applied after the score gate, so it only reorders genuine matches.
|
||||
// Tiebreak: prefer the SYSTEM (shipped) preset over user copies, then by name so the
|
||||
// winner never depends on how std::sort leaves equal elements. User copies of generic
|
||||
// presets inherit a generic filament_id from their parent, so preferring the user copy
|
||||
// can collapse a brand-specific match back to "Generic PLA" via the inherited id.
|
||||
// Requires the preset's declared filament_type to equal the spool's base type
|
||||
// (PLA/PETG/ABS/...) so we never auto-pick a PETG preset for a PLA spool.
|
||||
// Falls back to filaments.filament_id_by_type(base_type) when nothing scores.
|
||||
@@ -48,15 +84,17 @@ std::string CrealityPrintAgent::match_filament_preset(const PresetCollection& fi
|
||||
const std::string& brand_name,
|
||||
const std::string& base_type)
|
||||
{
|
||||
auto to_lower = [](std::string s) {
|
||||
for (auto& c : s) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
return s;
|
||||
};
|
||||
|
||||
const std::string vendor_lower = to_lower(vendor);
|
||||
const std::string brand_lower = to_lower(brand_name);
|
||||
const std::string type_lower = to_lower(base_type);
|
||||
|
||||
// Everything the spool told us about itself, as words. A word in a preset's name
|
||||
// that is not in here is a qualifier the spool never claimed.
|
||||
std::set<std::string> spool_words{"generic"};
|
||||
for (const std::string& src : {brand_lower, vendor_lower, type_lower})
|
||||
for (auto& w : name_words(src))
|
||||
spool_words.insert(std::move(w));
|
||||
|
||||
struct Match {
|
||||
const Preset* preset;
|
||||
int score;
|
||||
@@ -83,11 +121,20 @@ std::string CrealityPrintAgent::match_filament_preset(const PresetCollection& fi
|
||||
int score = 0;
|
||||
if (!brand_lower.empty() && name_lower.find(brand_lower) != std::string::npos)
|
||||
score += 20;
|
||||
if (!vendor_lower.empty() && name_lower.find(vendor_lower) != std::string::npos)
|
||||
// Profile OR name - neither alone covers both the vendor's own generics and the
|
||||
// third party filaments shipped inside its bundle. See the header comment.
|
||||
if (!vendor_lower.empty()
|
||||
&& ((p.vendor != nullptr && to_lower(p.vendor->name) == vendor_lower)
|
||||
|| name_lower.find(vendor_lower) != std::string::npos))
|
||||
score += 10;
|
||||
|
||||
if (score > 0)
|
||||
matches.push_back({&p, score, !p.is_system && !p.is_default});
|
||||
if (score == 0) continue;
|
||||
|
||||
for (const auto& w : name_words(p.name))
|
||||
if (spool_words.count(w) == 0)
|
||||
score -= 5;
|
||||
|
||||
matches.push_back({&p, score, !p.is_system && !p.is_default});
|
||||
}
|
||||
|
||||
if (matches.empty()) {
|
||||
@@ -105,7 +152,7 @@ std::string CrealityPrintAgent::match_filament_preset(const PresetCollection& fi
|
||||
[](const Match& a, const Match& b) {
|
||||
if (a.score != b.score) return a.score > b.score;
|
||||
if (a.is_user != b.is_user) return !a.is_user; // prefer system over user
|
||||
return false;
|
||||
return a.preset->name < b.preset->name; // keep the winner deterministic
|
||||
});
|
||||
|
||||
BOOST_LOG_TRIVIAL(info)
|
||||
|
||||
Reference in New Issue
Block a user