mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-19 06:53:02 +00:00
Merge branch 'main' into weilun/speed_dial
This commit is contained in:
+102
-2
@@ -100,6 +100,10 @@ using namespace nlohmann;
|
||||
|
||||
#ifdef SLIC3R_GUI
|
||||
#include "slic3r/GUI/GUI_Init.hpp"
|
||||
// BBLPrinterAgent::from_orca_filament_id(); the map and its lookups live in libslic3r_gui,
|
||||
// which only a SLIC3R_GUI build links (see target_link_libraries(OrcaSlicer libslic3r_gui)
|
||||
// in CMakeLists).
|
||||
#include "slic3r/Utils/BBLPrinterAgent.hpp"
|
||||
#endif /* SLIC3R_GUI */
|
||||
|
||||
using namespace Slic3r;
|
||||
@@ -1970,7 +1974,79 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
auto load_config_file = [](const std::string& file, DynamicPrintConfig& config, std::string& config_type,
|
||||
std::unique_ptr<PresetBundle> cli_preset_bundle;
|
||||
auto ensure_cli_preset_bundle = [&cli_preset_bundle, config_substitution_rule](std::string &error) -> PresetBundle * {
|
||||
if (cli_preset_bundle)
|
||||
return cli_preset_bundle.get();
|
||||
try {
|
||||
AppConfig app_config;
|
||||
const std::string app_config_error = app_config.load_if_exists();
|
||||
if (!app_config_error.empty()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Ignoring invalid app config during CLI preset resolution: " << app_config_error;
|
||||
app_config.reset();
|
||||
}
|
||||
|
||||
auto bundle = std::make_unique<PresetBundle>();
|
||||
std::string load_error;
|
||||
bundle->load_presets(app_config, config_substitution_rule,
|
||||
PresetBundle::PresetPreferences(), &load_error, true);
|
||||
if (!load_error.empty()) {
|
||||
error = "Failed to load presets for inheritance resolution: " + load_error;
|
||||
return nullptr;
|
||||
}
|
||||
cli_preset_bundle = std::move(bundle);
|
||||
return cli_preset_bundle.get();
|
||||
} catch (const std::exception &ex) {
|
||||
error = ex.what();
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
auto resolve_preset = [&ensure_cli_preset_bundle, config_substitution_rule](const std::string &file, DynamicPrintConfig &config,
|
||||
std::string &config_type, const std::string &config_from,
|
||||
bool probe_type, std::string &error) {
|
||||
const auto *inherits = config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS);
|
||||
if (!probe_type && (inherits == nullptr || inherits->value.empty()))
|
||||
return true;
|
||||
|
||||
std::unique_ptr<PresetBundle> source_bundle;
|
||||
PresetBundle *bundle = nullptr;
|
||||
bool allow_source_manifest = false;
|
||||
if (config_from == "system") {
|
||||
source_bundle = std::make_unique<PresetBundle>();
|
||||
bundle = source_bundle.get();
|
||||
allow_source_manifest = true;
|
||||
} else {
|
||||
bundle = ensure_cli_preset_bundle(error);
|
||||
if (bundle == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (probe_type) {
|
||||
Preset::Type preset_type;
|
||||
if (!bundle->resolve_preset_config_type(config, preset_type, file, config_substitution_rule,
|
||||
error, allow_source_manifest))
|
||||
return false;
|
||||
config_type = Preset::get_type_string(preset_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
Preset::Type preset_type;
|
||||
if (config_type == "process")
|
||||
preset_type = Preset::TYPE_PRINT;
|
||||
else if (config_type == "filament")
|
||||
preset_type = Preset::TYPE_FILAMENT;
|
||||
else if (config_type == "machine")
|
||||
preset_type = Preset::TYPE_PRINTER;
|
||||
else {
|
||||
error = "Unsupported preset type: " + config_type;
|
||||
return false;
|
||||
}
|
||||
return bundle->resolve_preset_config(config, preset_type, file, config_substitution_rule,
|
||||
error, allow_source_manifest);
|
||||
};
|
||||
|
||||
auto load_config_file = [config_substitution_rule, &resolve_preset](const std::string& file, DynamicPrintConfig& config, std::string& config_type,
|
||||
std::string& config_name, std::string& filament_id, std::string& config_from) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
boost::nowide::cerr << __FUNCTION__<< ": can not find setting file: " << file << std::endl;
|
||||
@@ -1999,9 +2075,15 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
|
||||
auto type_iter = key_values.find(BBL_JSON_KEY_TYPE);
|
||||
if (type_iter != key_values.end()) {
|
||||
const bool probe_type = type_iter == key_values.end();
|
||||
if (!probe_type)
|
||||
config_type = type_iter->second;
|
||||
|
||||
if (!resolve_preset(file, config, config_type, config_from, probe_type, reason)) {
|
||||
boost::nowide::cerr << __FUNCTION__ << boost::format(": can not resolve preset %1%: %2%") % file % reason << std::endl;
|
||||
return CLI_CONFIG_FILE_ERROR;
|
||||
}
|
||||
|
||||
if (config_type == "machine") {
|
||||
//config.set("printer_settings_id", config_name, true);
|
||||
//printer_inherits = config.option<ConfigOptionString>("inherits", true)->value;
|
||||
@@ -6539,6 +6621,20 @@ int CLI::run(int argc, char **argv)
|
||||
std::string nozzle_diameter_str;
|
||||
if (nozzle_diameter_option)
|
||||
nozzle_diameter_str = nozzle_diameter_option->serialize();
|
||||
#ifdef SLIC3R_GUI
|
||||
// A Bambu printer reads slice_info.config and knows only its own catalog ids. The GUI
|
||||
// gates the same translation on PresetBundle::is_bbl_vendor(); the CLI has no
|
||||
// PresetBundle, so reuse the printer_model prefix that already decides
|
||||
// Print::is_BBL_printer() for this same run.
|
||||
auto* printer_model_option = dynamic_cast<const ConfigOptionString*>(m_print_config.option("printer_model"));
|
||||
const bool is_bbl_printer = printer_model_option && printer_model_option->value.compare(0, 9, "Bambu Lab") == 0;
|
||||
// No wxApp on the CLI path, so there is no live agent to ask; the translator is stateless
|
||||
// over a lazily loaded map, so one instance serves every plate and filament below.
|
||||
// ORCA TODO: this assumes Bambu's is the only agent with a catalog of its own. Once another
|
||||
// agent carries one, resolve the agent from the selected printer the way
|
||||
// GUI_App::resolve_printer_agent_id does, rather than hard-coding BBLPrinterAgent here.
|
||||
const BBLPrinterAgent bbl_agent;
|
||||
#endif /* SLIC3R_GUI */
|
||||
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
PlateData *plate_data = plate_data_list[i];
|
||||
@@ -6556,6 +6652,10 @@ int CLI::run(int argc, char **argv)
|
||||
it->type = m_print_config.get_filament_type(display_filament_type, it->id);
|
||||
it->color = (filament_color && !filament_color->values.empty()) ? filament_color->get_at(it->id) : "#FFFFFF";
|
||||
it->filament_id = (filament_id && !filament_id->values.empty()) ? filament_id->get_at(it->id) : "";
|
||||
#ifdef SLIC3R_GUI
|
||||
if (is_bbl_printer)
|
||||
it->filament_id = bbl_agent.from_orca_filament_id(it->filament_id);
|
||||
#endif /* SLIC3R_GUI */
|
||||
}
|
||||
|
||||
if (!plate_data->plate_thumbnail.is_valid()) {
|
||||
|
||||
@@ -175,6 +175,17 @@ void select_printer_default_presets(PresetBundle &bundle)
|
||||
if (const auto *def_fil = printer_preset.config.option<ConfigOptionStrings>("default_filament_profile");
|
||||
def_fil != nullptr && !def_fil->values.empty())
|
||||
bundle.filaments.select_preset_by_name(def_fil->values.front(), /*force=*/true);
|
||||
// Re-seed the per-slot filament list from that selection, or the sweep's result depends on the
|
||||
// printer sliced before it. Once there are 2+ slots, full_config() builds the filament config from
|
||||
// filament_presets and ignores the selected preset (PresetBundle::full_fff_config), while
|
||||
// update_compatible() only replaces a slot that has gone *incompatible* - and when it does, it ranks
|
||||
// the outgoing preset's alias, then its filament type, above the printer's own default. The sweep
|
||||
// grows every printer to 2 slots and update_multi_material_filament_presets() never shrinks them, so
|
||||
// a material picked up on the first printer rides the whole run. With all vendors loaded the first
|
||||
// printer inherits a TPU (the load-time pick is whichever filament sorts first), the type match
|
||||
// re-resolves it to "Generic TPU @System", and its alias then pins every later printer to that
|
||||
// vendor's own "Generic TPU @..." - which the BBL dual-nozzle profiles rightly refuse to group.
|
||||
bundle.filament_presets.assign(1, bundle.filaments.get_selected_preset_name());
|
||||
}
|
||||
|
||||
// The vendor/printer currently being sliced, stamped onto every engine log record by the sink below so
|
||||
@@ -381,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
|
||||
|
||||
|
||||
@@ -1823,4 +1823,9 @@ bool AppConfig::exists()
|
||||
return boost::filesystem::exists(config_path());
|
||||
}
|
||||
|
||||
std::string AppConfig::load_if_exists()
|
||||
{
|
||||
return boost::filesystem::exists(loading_path()) ? load() : std::string();
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
@@ -113,8 +113,10 @@ public:
|
||||
void set_defaults();
|
||||
|
||||
// Load the slic3r.ini from a user profile directory (or a datadir, if configured).
|
||||
// return error string or empty strinf
|
||||
// Return an error string, or an empty string on success.
|
||||
std::string load();
|
||||
// Treat a missing config as default state; otherwise load it normally.
|
||||
std::string load_if_exists();
|
||||
// Store the slic3r.ini into a user profile directory (or a datadir, if configured).
|
||||
void save();
|
||||
|
||||
|
||||
@@ -342,7 +342,7 @@ void fuzzy_polyline(Points& poly, bool closed, coordf_t slice_z, const FuzzySkin
|
||||
}
|
||||
|
||||
// Thanks Cura developers for this function.
|
||||
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg, bool closed)
|
||||
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, coordf_t layer_height, const FuzzySkinConfig& cfg, bool closed)
|
||||
{
|
||||
|
||||
if (cfg.noise_type == NoiseType::Ripple) {
|
||||
@@ -356,7 +356,9 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice
|
||||
|
||||
const double min_dist_between_points = cfg.point_distance * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value
|
||||
const double range_random_point_dist = cfg.point_distance / 2.;
|
||||
const double min_extrusion_width = 0.01; // workaround for many print options. Need overwrite formula with the layer height parameter. The width must more than >>> layer_height * (1 - 0.25 * PI) * 1.05 <<< (last num is the coeff of overlay error case)
|
||||
// ExtrusionJunction::w is a scaled coord_t, so this floor must be scaled too.
|
||||
// Flow::rounded_rectangle_extrusion_spacing() requires width > height * (1 - 0.25 * PI); keep 5% above it.
|
||||
const double min_extrusion_width = scaled<double>(layer_height * (1. - 0.25 * M_PI) * 1.05);
|
||||
double dist_left_over = random_value() * (min_dist_between_points / 2.); // the distance to be traversed on the line before making the first new point
|
||||
|
||||
auto* p0 = &ext_lines.front();
|
||||
@@ -685,12 +687,13 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
|
||||
void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerator& perimeter_generator, const bool is_contour, const bool closed)
|
||||
{
|
||||
const auto slice_z = perimeter_generator.slice_z;
|
||||
const auto layer_height = perimeter_generator.layer_height;
|
||||
const auto& regions = perimeter_generator.regions_by_fuzzify;
|
||||
if (regions.size() == 1) { // optimization
|
||||
const auto& config = regions.begin()->first;
|
||||
const bool fuzzify = should_fuzzify(config, perimeter_generator.layer_id, extrusion->inset_idx, is_contour);
|
||||
if (fuzzify)
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, config, closed);
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, perimeter_generator.layer_height, config, closed);
|
||||
} else {
|
||||
// Merge regions that produce identical fuzzy effects (differ only in type).
|
||||
// When the style (e.g. External) and a painted region (All) both fuzzify this loop
|
||||
@@ -701,7 +704,7 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
|
||||
// Fast path: single merged region — apply directly without splitting
|
||||
if (merged_regions.size() == 1 && merged_regions.front().expolygons.empty()) {
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, *merged_regions.front().config, closed);
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, perimeter_generator.layer_height, *merged_regions.front().config, closed);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -761,7 +764,7 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
// Fuzzy splitted extrusion
|
||||
if (std::all_of(splitted.begin(), splitted.end(), [](const Algorithm::SplitLineJunction& j) { return j.clipped; })) {
|
||||
// The entire polygon is fuzzified
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, *r.config, closed);
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, perimeter_generator.layer_height, *r.config, closed);
|
||||
continue;
|
||||
} else {
|
||||
const auto current_ext = extrusion->junctions;
|
||||
@@ -769,12 +772,12 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
segment.reserve(current_ext.size());
|
||||
extrusion->junctions.clear();
|
||||
|
||||
const auto fuzzy_current_segment = [&segment, &extrusion, &r, slice_z]() {
|
||||
const auto fuzzy_current_segment = [&segment, &extrusion, &r, slice_z, layer_height]() {
|
||||
// Orca: non fuzzy points to isolate fuzzy region
|
||||
const auto front = segment.front();
|
||||
const auto back = segment.back();
|
||||
|
||||
fuzzy_extrusion_line(segment, slice_z, *r.config, false);
|
||||
fuzzy_extrusion_line(segment, slice_z, layer_height, *r.config, false);
|
||||
// Orca: only add non fuzzy point if it's not in the extrusion closing point.
|
||||
if (!extrusion->junctions.empty() && extrusion->junctions.front().p != front.p) {
|
||||
extrusion->junctions.push_back(front);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Slic3r::Feature::FuzzySkin {
|
||||
|
||||
void fuzzy_polyline(Points& poly, bool closed, coordf_t slice_z, const FuzzySkinConfig& cfg);
|
||||
|
||||
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg, bool closed = true);
|
||||
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, coordf_t layer_height, const FuzzySkinConfig& cfg, bool closed = true);
|
||||
|
||||
void group_region_by_fuzzify(PerimeterGenerator& g);
|
||||
|
||||
|
||||
@@ -2467,9 +2467,11 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
||||
#endif // INFILL_DEBUG_OUTPUT
|
||||
|
||||
const std::vector<SupportArcCost> arches = evaluate_support_arches(infill_ordered, graph, spacing, params);
|
||||
static const double cost_low = line_spacing * 1.3;
|
||||
static const double cost_high = line_spacing * 2.;
|
||||
static const double cost_veryhigh = line_spacing * 3.;
|
||||
// Must not be static: line_spacing varies per call (base vs interface fills differ),
|
||||
// and a static here would fix these to whichever call ran first, order depending on thread count.
|
||||
const double cost_low = line_spacing * 1.3;
|
||||
const double cost_high = line_spacing * 2.;
|
||||
const double cost_veryhigh = line_spacing * 3.;
|
||||
|
||||
{
|
||||
std::vector<const SupportArcCost*> selected;
|
||||
|
||||
@@ -40,8 +40,8 @@ static float DeltaHS_BBS(float h1, float s1, float v1, float h2, float s2, float
|
||||
return std::min(1.2f, dxy);
|
||||
}
|
||||
|
||||
FlushVolCalculator::FlushVolCalculator(int min, int max, int flush_dataset, float multiplier)
|
||||
:m_min_flush_vol(min), m_max_flush_vol(max), m_multiplier(multiplier), m_flush_dataset(flush_dataset)
|
||||
FlushVolCalculator::FlushVolCalculator(int min, int max, int flush_dataset)
|
||||
:m_min_flush_vol(min), m_max_flush_vol(max), m_flush_dataset(flush_dataset)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ extern const int g_max_flush_volume;
|
||||
class FlushVolCalculator
|
||||
{
|
||||
public:
|
||||
FlushVolCalculator(int min, int max, int flush_dataset, float multiplier = 1.0f);
|
||||
FlushVolCalculator(int min, int max, int flush_dataset);
|
||||
~FlushVolCalculator()
|
||||
{
|
||||
}
|
||||
@@ -32,7 +32,6 @@ public:
|
||||
private:
|
||||
int m_min_flush_vol;
|
||||
int m_max_flush_vol;
|
||||
float m_multiplier;
|
||||
int m_flush_dataset;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ class FanMover
|
||||
private:
|
||||
const std::regex regex_fan_speed;
|
||||
const float nb_seconds_delay;
|
||||
const bool with_D_option;
|
||||
// Set from fan_speedup_time at the call site, but nothing here reads it.
|
||||
[[maybe_unused]] const bool with_D_option;
|
||||
const bool relative_e;
|
||||
const bool only_overhangs;
|
||||
const float kickstart;
|
||||
|
||||
+13
-11
@@ -545,7 +545,7 @@ std::string generate_preset_setting_id(const std::string& vendor, const std::str
|
||||
return "";
|
||||
|
||||
// Dedicated namespace for preset setting_ids, distinct from the cloud per-user
|
||||
// namespace (OrcaCloudServiceAgent). Keep in sync with scripts/assign_vendor_setting_ids.py;
|
||||
// namespace (OrcaCloudServiceAgent). Keep in sync with scripts/orca_id_tool.py;
|
||||
// never change this constant.
|
||||
static const boost::uuids::uuid vendor_namespace =
|
||||
boost::uuids::string_generator()("c1f4d9e2-7a3b-5c8d-9e0f-1a2b3c4d5e6f");
|
||||
@@ -1653,7 +1653,7 @@ std::string PresetCollection::canonical_preset_name(const std::string &name, con
|
||||
void PresetCollection::load_presets(
|
||||
const std::string &dir_path, const std::string &subdir,
|
||||
PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule substitution_rule,
|
||||
std::function<void(Preset&)> preset_loaded_fn, const PresetOrigin &load_origin)
|
||||
std::function<void(Preset&)> preset_loaded_fn, const PresetOrigin &load_origin, bool read_only)
|
||||
{
|
||||
// Don't use boost::filesystem::canonical() on Windows, it is broken in regard to reparse points,
|
||||
// see https://github.com/prusa3d/PrusaSlicer/issues/732
|
||||
@@ -1662,7 +1662,7 @@ void PresetCollection::load_presets(
|
||||
|
||||
// Load custom roots first
|
||||
if (fs::exists(dir / "base")) {
|
||||
load_presets(dir.string(), "base", substitutions, substitution_rule, nullptr, resolved_origin);
|
||||
load_presets(dir.string(), "base", substitutions, substitution_rule, nullptr, resolved_origin, read_only);
|
||||
}
|
||||
|
||||
//BBS: add config related logs
|
||||
@@ -1670,7 +1670,8 @@ void PresetCollection::load_presets(
|
||||
//BBS do not parse folder if not exists
|
||||
m_dir_path = dir.string();
|
||||
if (!fs::exists(dir)) {
|
||||
fs::create_directory(dir);
|
||||
if (!read_only)
|
||||
fs::create_directory(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1720,10 +1721,10 @@ void PresetCollection::load_presets(
|
||||
substitutions.push_back({ preset.name, m_type, PresetConfigSubstitutions::Source::UserFile, preset.file, std::move(config_substitutions) });
|
||||
if (!reason.empty()) {
|
||||
fs::path file_path(preset.file);
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
file_path.replace_extension(".info");
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("parse config %1% failed")%preset.file;
|
||||
++m_errors;
|
||||
@@ -1794,7 +1795,8 @@ void PresetCollection::load_presets(
|
||||
size_t at_pos = name.find('@');
|
||||
if (at_pos != std::string::npos && at_pos + 1 < name.length()) {
|
||||
compatible_printers->values.push_back(name.substr(at_pos + 1));
|
||||
preset.save(nullptr);
|
||||
if (!read_only)
|
||||
preset.save(nullptr);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " added compatible_printers for preset: " << name;
|
||||
}
|
||||
}
|
||||
@@ -1812,10 +1814,10 @@ void PresetCollection::load_presets(
|
||||
++m_errors;
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("The user-config cannot be loaded: %1%. Reason: %2%")%preset.file %err.what();
|
||||
fs::path file_path(preset.file);
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
file_path.replace_extension(".info");
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
//throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what());
|
||||
} catch (const std::runtime_error &err) {
|
||||
@@ -1823,10 +1825,10 @@ void PresetCollection::load_presets(
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading the user-config file: %1%. Reason: %2%")%preset.file %err.what();
|
||||
//throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what());
|
||||
fs::path file_path(preset.file);
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
file_path.replace_extension(".info");
|
||||
if (fs::exists(file_path))
|
||||
if (!read_only && fs::exists(file_path))
|
||||
fs::remove(file_path);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,8 +93,8 @@ class PresetBundle;
|
||||
|
||||
// Deterministic preset setting_id: uuid5(vendor/type/name) -> 16 base62 chars.
|
||||
// Pure function of a system preset's identity, so the value can be assigned by
|
||||
// scripts/assign_vendor_setting_ids.py and recomputed here when a profile ships
|
||||
// without it. MUST stay byte-identical to scripts/assign_vendor_setting_ids.py.
|
||||
// scripts/orca_id_tool.py and recomputed here when a profile ships without it.
|
||||
// MUST stay byte-identical to scripts/orca_id_tool.py.
|
||||
// This is NOT the per-user cloud-sync setting_id
|
||||
// (OrcaCloudServiceAgent::generate_uuid_for_setting_id) - do not conflate them.
|
||||
std::string generate_preset_setting_id(const std::string& vendor,
|
||||
@@ -558,7 +558,7 @@ public:
|
||||
void add_default_preset(const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &preset_name);
|
||||
|
||||
// Load ini files of the particular type from the provided directory path.
|
||||
void load_presets(const std::string &dir_path, const std::string &subdir, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, std::function<void(Preset&)> preset_loaded_fn = nullptr, const PresetOrigin &load_origin = PresetOrigin());
|
||||
void load_presets(const std::string &dir_path, const std::string &subdir, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, std::function<void(Preset&)> preset_loaded_fn = nullptr, const PresetOrigin &load_origin = PresetOrigin(), bool read_only = false);
|
||||
|
||||
//BBS: update user presets directory
|
||||
void update_user_presets_directory(const std::string& dir_path, const std::string& type);
|
||||
|
||||
+285
-32
@@ -453,6 +453,158 @@ PresetBundle::PresetBundle()
|
||||
this->project_config.apply_only(FullPrintConfig::defaults(), s_project_options);
|
||||
}
|
||||
|
||||
bool PresetBundle::resolve_preset_config(DynamicPrintConfig &config, Preset::Type type,
|
||||
const std::string &source_file,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||
std::string &error, bool allow_source_manifest)
|
||||
{
|
||||
if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::EnableSilent;
|
||||
else if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem)
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
|
||||
auto collection_for_type = [](PresetBundle &bundle, Preset::Type preset_type) -> PresetCollection * {
|
||||
switch (preset_type) {
|
||||
case Preset::TYPE_PRINT: return &bundle.prints;
|
||||
case Preset::TYPE_FILAMENT: return &bundle.filaments;
|
||||
case Preset::TYPE_PRINTER: return &bundle.printers;
|
||||
default: return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
PresetCollection *collection = collection_for_type(*this, type);
|
||||
if (collection == nullptr) {
|
||||
error = "Unsupported preset type";
|
||||
return false;
|
||||
}
|
||||
|
||||
const boost::filesystem::path source_path = boost::filesystem::absolute(source_file).lexically_normal();
|
||||
auto find_loaded = [&](PresetBundle &bundle) -> const Preset * {
|
||||
PresetCollection *loaded_collection = collection_for_type(bundle, type);
|
||||
const Preset *resolved = nullptr;
|
||||
for (const Preset &preset : loaded_collection->get_presets()) {
|
||||
if (preset.file.empty())
|
||||
continue;
|
||||
|
||||
boost::system::error_code ec;
|
||||
const bool same_file = boost::filesystem::equivalent(source_path, boost::filesystem::path(preset.file), ec);
|
||||
if (ec || !same_file)
|
||||
continue;
|
||||
if (resolved != nullptr) {
|
||||
error = "Preset identity is ambiguous";
|
||||
return nullptr;
|
||||
}
|
||||
resolved = &preset;
|
||||
}
|
||||
return resolved;
|
||||
};
|
||||
|
||||
if (const Preset *resolved = find_loaded(*this)) {
|
||||
config = resolved->config;
|
||||
error.clear();
|
||||
return true;
|
||||
}
|
||||
if (error == "Preset identity is ambiguous")
|
||||
return false;
|
||||
if (!allow_source_manifest) {
|
||||
error = "Preset was not found in the loaded bundle";
|
||||
return false;
|
||||
}
|
||||
|
||||
// A manifest-backed source file can be resolved without requiring the vendor
|
||||
// to have been copied into data_dir()/system. Find the nearest ancestor whose
|
||||
// sibling manifest names it, then let the canonical vendor loader flatten the
|
||||
// complete tree (including nested sub_path entries and library inheritance).
|
||||
for (boost::filesystem::path vendor_dir = source_path.parent_path(); !vendor_dir.empty(); vendor_dir = vendor_dir.parent_path()) {
|
||||
const std::string vendor_id = vendor_dir.filename().string();
|
||||
if (vendor_id.empty())
|
||||
continue;
|
||||
const boost::filesystem::path root_dir = vendor_dir.parent_path();
|
||||
const boost::filesystem::path manifest = root_dir / (vendor_id + ".json");
|
||||
if (!boost::filesystem::is_regular_file(manifest))
|
||||
continue;
|
||||
const boost::filesystem::path manifest_relative = source_path.lexically_relative(vendor_dir);
|
||||
if (manifest_relative.empty() || *manifest_relative.begin() == "..")
|
||||
continue;
|
||||
|
||||
try {
|
||||
PresetBundle library_bundle;
|
||||
const PresetBundle *base_bundle = nullptr;
|
||||
if (vendor_id != ORCA_FILAMENT_LIBRARY &&
|
||||
boost::filesystem::is_regular_file(root_dir / (std::string(ORCA_FILAMENT_LIBRARY) + ".json"))) {
|
||||
library_bundle.m_preserve_vendor_source_paths = true;
|
||||
library_bundle.load_vendor_configs_from_json(root_dir.string(), ORCA_FILAMENT_LIBRARY, LoadSystem,
|
||||
compatibility_rule, nullptr, false);
|
||||
if (library_bundle.error_count() != 0) {
|
||||
error = "OrcaFilamentLibrary contains invalid presets";
|
||||
return false;
|
||||
}
|
||||
base_bundle = &library_bundle;
|
||||
}
|
||||
|
||||
PresetBundle source_bundle;
|
||||
source_bundle.m_preserve_vendor_source_paths = true;
|
||||
source_bundle.load_vendor_configs_from_json(root_dir.string(), vendor_id, LoadSystem,
|
||||
compatibility_rule, base_bundle, false);
|
||||
if (source_bundle.error_count() != 0) {
|
||||
error = "Vendor bundle contains invalid presets";
|
||||
return false;
|
||||
}
|
||||
|
||||
const Preset *resolved = find_loaded(source_bundle);
|
||||
if (resolved == nullptr) {
|
||||
if (error.empty())
|
||||
error = "Source file is not an instantiated preset in its vendor manifest";
|
||||
return false;
|
||||
}
|
||||
config = resolved->config;
|
||||
error.clear();
|
||||
return true;
|
||||
} catch (const std::exception &ex) {
|
||||
error = ex.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
error = "Preset was not found in the loaded bundle";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PresetBundle::resolve_preset_config_type(DynamicPrintConfig &config, Preset::Type &type,
|
||||
const std::string &source_file,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||
std::string &error, bool allow_source_manifest)
|
||||
{
|
||||
std::optional<std::pair<Preset::Type, DynamicPrintConfig>> resolved;
|
||||
for (Preset::Type candidate_type : types_list(ptFFF)) {
|
||||
DynamicPrintConfig candidate_config(config);
|
||||
std::string candidate_error;
|
||||
if (!resolve_preset_config(candidate_config, candidate_type, source_file, compatibility_rule,
|
||||
candidate_error, allow_source_manifest)) {
|
||||
if (candidate_error == "Preset identity is ambiguous") {
|
||||
error = std::move(candidate_error);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (resolved) {
|
||||
error = "Preset type is ambiguous";
|
||||
return false;
|
||||
}
|
||||
resolved.emplace(candidate_type, std::move(candidate_config));
|
||||
}
|
||||
|
||||
if (!resolved) {
|
||||
error = "Preset type could not be resolved";
|
||||
return false;
|
||||
}
|
||||
|
||||
type = resolved->first;
|
||||
config = std::move(resolved->second);
|
||||
error.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
PresetBundle::PresetBundle(const PresetBundle &rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
@@ -574,7 +726,8 @@ void PresetBundle::copy_files(const std::string& from)
|
||||
}
|
||||
|
||||
PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule substitution_rule,
|
||||
const PresetPreferences& preferred_selection/* = PresetPreferences()*/)
|
||||
const PresetPreferences& preferred_selection/* = PresetPreferences()*/,
|
||||
std::string *errors, bool read_only)
|
||||
{
|
||||
// First load the vendor specific system presets.
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
@@ -585,16 +738,20 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward
|
||||
const auto startup_t0 = std::chrono::steady_clock::now();
|
||||
|
||||
//BBS: change system config to json
|
||||
std::tie(substitutions, errors_cummulative) = this->load_system_presets_from_json(substitution_rule);
|
||||
std::tie(substitutions, errors_cummulative) = this->load_system_presets_from_json(substitution_rule, !read_only);
|
||||
if (errors != nullptr)
|
||||
*errors = errors_cummulative;
|
||||
|
||||
// BBS load preset from user's folder, load system default if
|
||||
// BBS: change directories by design
|
||||
std::string dir_user_presets = config.get("preset_folder");
|
||||
if (dir_user_presets.empty()) {
|
||||
load_user_presets(DEFAULT_USER_FOLDER_NAME, substitution_rule);
|
||||
load_user_presets(DEFAULT_USER_FOLDER_NAME, substitution_rule, read_only);
|
||||
} else {
|
||||
load_user_presets(dir_user_presets, substitution_rule);
|
||||
load_user_presets(dir_user_presets, substitution_rule, read_only);
|
||||
}
|
||||
if (errors != nullptr && errors->empty() && m_errors != 0)
|
||||
*errors = "Preset loading reported " + std::to_string(m_errors) + " error(s)";
|
||||
|
||||
// Rewrite renamed compatible_printers / compatible_prints references before selection. Skipped
|
||||
// in validation mode so the profile validator (has_errors -> check_preset_references) sees the
|
||||
@@ -1010,18 +1167,26 @@ std::string PresetBundle::get_hotend_model_for_printer_model(std::string model_n
|
||||
return out;
|
||||
}
|
||||
|
||||
PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule substitution_rule)
|
||||
PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule substitution_rule, bool read_only)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " entry and user is: " << user;
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
|
||||
fs::path user_folder(data_dir() + "/" + PRESET_USER_DIR);
|
||||
if (!fs::exists(user_folder)) fs::create_directory(user_folder);
|
||||
if (!fs::exists(user_folder)) {
|
||||
if (read_only)
|
||||
return substitutions;
|
||||
fs::create_directory(user_folder);
|
||||
}
|
||||
|
||||
std::string dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/" + user;
|
||||
fs::path folder(user_folder / user);
|
||||
if (!fs::exists(folder)) fs::create_directory(folder);
|
||||
if (!fs::exists(folder)) {
|
||||
if (read_only)
|
||||
return substitutions;
|
||||
fs::create_directory(folder);
|
||||
}
|
||||
|
||||
bundles.WriteLock();
|
||||
bundles.m_bundles.clear();
|
||||
@@ -1049,13 +1214,13 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
|
||||
this->prints.load_presets(bundle_dir, PRESET_PRINT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.print_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id), read_only);
|
||||
this->filaments.load_presets(bundle_dir, PRESET_FILAMENT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.filament_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id), read_only);
|
||||
this->printers.load_presets(bundle_dir, PRESET_PRINTER_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.printer_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::LocalBundle, metadata.id), read_only);
|
||||
metadata.bundle_type = BundleType::Local;
|
||||
metadata.path = metadata_file.string();
|
||||
|
||||
@@ -1085,13 +1250,13 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
|
||||
this->prints.load_presets(bundle_dir, PRESET_PRINT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.print_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id), read_only);
|
||||
this->filaments.load_presets(bundle_dir, PRESET_FILAMENT_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.filament_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id), read_only);
|
||||
this->printers.load_presets(bundle_dir, PRESET_PRINTER_NAME, substitutions, substitution_rule, [&](Preset& preset) {
|
||||
metadata.printer_presets.push_back(preset.name);
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id));
|
||||
}, PresetOrigin(PresetOrigin::Kind::SubscribedBundle, metadata.id), read_only);
|
||||
|
||||
metadata.bundle_type = BundleType::Subscribed;
|
||||
metadata.path = metadata_file.string();
|
||||
@@ -1110,17 +1275,20 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
|
||||
const auto json_t0 = std::chrono::steady_clock::now();
|
||||
try {
|
||||
std::string sel = prints.get_selected_preset().name;
|
||||
this->prints.load_presets(dir_user_presets, PRESET_PRINT_NAME, substitutions, substitution_rule);
|
||||
this->prints.load_presets(dir_user_presets, PRESET_PRINT_NAME, substitutions, substitution_rule,
|
||||
nullptr, PresetOrigin(), read_only);
|
||||
prints.select_preset_by_name(sel, false);
|
||||
} catch (const std::runtime_error& err) { errors_cummulative += err.what(); }
|
||||
try {
|
||||
std::string sel = filaments.get_selected_preset().name;
|
||||
this->filaments.load_presets(dir_user_presets, PRESET_FILAMENT_NAME, substitutions, substitution_rule);
|
||||
this->filaments.load_presets(dir_user_presets, PRESET_FILAMENT_NAME, substitutions, substitution_rule,
|
||||
nullptr, PresetOrigin(), read_only);
|
||||
filaments.select_preset_by_name(sel, false);
|
||||
} catch (const std::runtime_error& err) { errors_cummulative += err.what(); }
|
||||
try {
|
||||
std::string sel = printers.get_selected_preset().name;
|
||||
this->printers.load_presets(dir_user_presets, PRESET_PRINTER_NAME, substitutions, substitution_rule);
|
||||
this->printers.load_presets(dir_user_presets, PRESET_PRINTER_NAME, substitutions, substitution_rule,
|
||||
nullptr, PresetOrigin(), read_only);
|
||||
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);
|
||||
@@ -2266,7 +2434,8 @@ void PresetBundle::clear_printer_hold_aliases()
|
||||
}
|
||||
|
||||
//BBS: add json related logic, load system presets from json
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule, bool allow_cache)
|
||||
{
|
||||
//BBS: add config related logs
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%")%compatibility_rule;
|
||||
@@ -2288,7 +2457,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
||||
// 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
|
||||
// is complete enough to be worth caching.
|
||||
m_generate_vendor_caches = m_generate_vendor_caches || ! validation_mode;
|
||||
m_generate_vendor_caches = allow_cache && (m_generate_vendor_caches || !validation_mode);
|
||||
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
@@ -2318,7 +2487,8 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
||||
// state into this load.
|
||||
this->clear_printer_hold_aliases();
|
||||
this->m_errors = 0;
|
||||
append(substitutions, this->load_vendor_configs_from_json(dir.string(), orca_lib_vendor, PresetBundle::LoadSystem, compatibility_rule).first);
|
||||
append(substitutions, this->load_vendor_configs_from_json(
|
||||
dir.string(), orca_lib_vendor, PresetBundle::LoadSystem, compatibility_rule, nullptr, allow_cache).first);
|
||||
first = false;
|
||||
} catch (const std::runtime_error &err) {
|
||||
if (validation_mode)
|
||||
@@ -2343,7 +2513,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
||||
bundle->set_generate_vendor_caches(m_generate_vendor_caches);
|
||||
try {
|
||||
auto result = bundle->load_vendor_configs_from_json(
|
||||
dir.string(), other_vendors[i], PresetBundle::LoadSystem, compatibility_rule, this);
|
||||
dir.string(), other_vendors[i], PresetBundle::LoadSystem, compatibility_rule, this, allow_cache);
|
||||
parallel_substitutions[i] = std::move(result.first);
|
||||
parallel_bundles[i] = std::move(bundle);
|
||||
} catch (const std::runtime_error &err) {
|
||||
@@ -3383,6 +3553,24 @@ std::vector<size_t> PresetBundle::physical_filament_config_indices() const
|
||||
}
|
||||
|
||||
|
||||
// Orca: the AMS lookups below resolve a tray's filament_id to the FIRST compatible base
|
||||
// preset. When several presets match the same id for the selected printer the pick is
|
||||
// arbitrary (a profile bug - see the validator's check_duplicate_filament_subtypes), so
|
||||
// scan past a successful match and warn about the runners-up. Behavior is unchanged.
|
||||
static void warn_ambiguous_filament_id_match(const PresetCollection &filaments, PresetCollection::ConstIterator match, const std::string &filament_id)
|
||||
{
|
||||
if (match == filaments.end())
|
||||
return;
|
||||
std::string others;
|
||||
for (auto it = std::next(match); it != filaments.end(); ++it)
|
||||
if (it->is_compatible && filaments.get_preset_base(*it) == &*it && it->filament_id == filament_id)
|
||||
others += (others.empty() ? "\"" : ", \"") + it->name + "\"";
|
||||
if (!others.empty())
|
||||
BOOST_LOG_TRIVIAL(warning) << "Ambiguous AMS filament match: filament_id \"" << filament_id
|
||||
<< "\" matches multiple presets compatible with the selected printer; picked \"" << match->name
|
||||
<< "\", also matches " << others;
|
||||
}
|
||||
|
||||
void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info)
|
||||
{
|
||||
combox_info.clear();
|
||||
@@ -3405,6 +3593,7 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info)
|
||||
}
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(),
|
||||
[this, &filament_id](auto &f) { return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
if (iter == filaments.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
|
||||
auto filament_type = ams.opt_string("filament_type", 0u);
|
||||
@@ -3507,6 +3696,7 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(), [this, &filament_id, &has_type, filament_type](auto &f) {
|
||||
has_type |= f.config.opt_string("filament_type", 0u) == filament_type;
|
||||
return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
if (iter == filaments.end()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
|
||||
if (!filament_type.empty()) {
|
||||
@@ -4019,6 +4209,9 @@ std::vector<std::vector<DynamicPrintConfig>> PresetBundle::get_extruder_filament
|
||||
return filament_infos;
|
||||
}
|
||||
|
||||
// ORCA TODO: currently, this function assumes the printer name follows the pattern of "<printer_model> <nozzle_diameter>", e.g.
|
||||
// printer_type: "Bambu Lab X2D", nozzle_diameter_str: "0.4 nozzle" => printer_name: "Bambu Lab X2D 0.4 nozzle". If the printer name does
|
||||
// not follow this pattern, the function may not work correctly.
|
||||
std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only)
|
||||
{
|
||||
std::set<std::string> printer_names;
|
||||
@@ -4049,6 +4242,40 @@ std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle
|
||||
return printer_names;
|
||||
}
|
||||
|
||||
std::vector<Preset *> PresetBundle::get_filament_presets_for_machine(const std::string &printer_type,
|
||||
const std::string &nozzle_diameter_str,
|
||||
bool include_user_presets)
|
||||
{
|
||||
// Printer model plus nozzle diameter is expected to resolve to a single system printer preset;
|
||||
// get_printer_names_by_printer_type_and_nozzle asserts as much in debug builds.
|
||||
const std::set<std::string> printer_names = get_printer_names_by_printer_type_and_nozzle(printer_type, nozzle_diameter_str);
|
||||
const Preset *printer = printer_names.empty() ? nullptr : printers.find_preset(*printer_names.begin());
|
||||
if (printer == nullptr)
|
||||
return {};
|
||||
|
||||
// Preset::is_visible is deliberately not consulted: it tracks what the Configuration Wizard
|
||||
// installed, while the caller identifies a physically connected machine the user may never
|
||||
// have installed - gating on it would empty the list for exactly those machines.
|
||||
const PresetWithVendorProfile active_printer = printers.get_preset_with_vendor_profile(*printer);
|
||||
// Loop invariant - the two argument is_compatible_with_printer() would rebuild it per preset.
|
||||
DynamicPrintConfig printer_config;
|
||||
printer_config.set_key_value("printer_preset", new ConfigOptionString(printer->name));
|
||||
if (const ConfigOption *opt = printer->config.option("nozzle_diameter"))
|
||||
printer_config.set_key_value("num_extruders", new ConfigOptionInt((int) static_cast<const ConfigOptionFloats *>(opt)->values.size()));
|
||||
|
||||
std::vector<Preset *> compatible;
|
||||
for (Preset &preset : filaments) {
|
||||
/* The situation where the preset is not offered is as follows:
|
||||
1. Not a root preset
|
||||
2. Not a system preset and the printer firmware does not support user presets */
|
||||
if (filaments.get_preset_base(preset) != &preset || (!preset.is_system && !include_user_presets))
|
||||
continue;
|
||||
if (is_compatible_with_printer(filaments.get_preset_with_vendor_profile(preset), active_printer, &printer_config))
|
||||
compatible.push_back(&preset);
|
||||
}
|
||||
return compatible;
|
||||
}
|
||||
|
||||
bool PresetBundle::check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray(
|
||||
const std::string &printer_type, std::string& nozzle_diameter_str, std::string &setting_id, std::string &tag_uid, std::string &nozzle_temp_min, std::string &nozzle_temp_max, std::string& preset_setting_id)
|
||||
{
|
||||
@@ -4057,7 +4284,11 @@ bool PresetBundle::check_filament_temp_equation_by_printer_type_and_nozzle_for_m
|
||||
std::map<std::string, std::vector<Preset const *>> filament_list = filaments.get_filament_presets();
|
||||
std::set<std::string> printer_names = get_printer_names_by_printer_type_and_nozzle(printer_type, nozzle_diameter_str);
|
||||
|
||||
for (const Preset *preset : filament_list.find(setting_id)->second) {
|
||||
auto filament_iter = filament_list.find(setting_id);
|
||||
if (filament_iter == filament_list.end())
|
||||
return is_equation;
|
||||
|
||||
for (const Preset *preset : filament_iter->second) {
|
||||
if (tag_uid == "0" || (tag_uid.size() == 16 && tag_uid.substr(12, 2) == "01")) continue;
|
||||
if (preset && !preset->is_user()) continue;
|
||||
ConfigOption * printer_opt = const_cast<Preset *>(preset)->config.option("compatible_printers");
|
||||
@@ -5219,9 +5450,11 @@ std::string PresetBundle::load_vendor_preset(
|
||||
return reason;
|
||||
}
|
||||
|
||||
auto file_path = (boost::filesystem::path(data_dir()) /PRESET_SYSTEM_DIR/ vendor_name / entry.sub_path).make_preferred();
|
||||
if(validation_mode)
|
||||
auto file_path = (boost::filesystem::path(data_dir()) / PRESET_SYSTEM_DIR / vendor_name / entry.sub_path).make_preferred();
|
||||
if (validation_mode)
|
||||
file_path = (boost::filesystem::path(data_dir()) / vendor_name / entry.sub_path).make_preferred();
|
||||
if (m_preserve_vendor_source_paths)
|
||||
file_path = (boost::filesystem::path(path) / vendor_name / entry.sub_path).make_preferred();
|
||||
|
||||
// Load the preset into the list of presets, save it to disk.
|
||||
Preset &loaded = presets_collection->load_preset(file_path.string(), preset_name, std::move(config), false);
|
||||
@@ -5232,8 +5465,8 @@ std::string PresetBundle::load_vendor_preset(
|
||||
loaded.description = entry.description;
|
||||
loaded.setting_id = entry.setting_id;
|
||||
// Derive the preset setting_id on the fly when a profile ships without one,
|
||||
// matching scripts/assign_vendor_setting_ids.py. Only instantiated presets
|
||||
// carry an id; non-instantiated base profiles return earlier above. This never
|
||||
// matching scripts/orca_id_tool.py. Only instantiated presets carry an id;
|
||||
// non-instantiated base profiles return earlier above. This never
|
||||
// touches the per-user cloud-sync setting_id written into user .info files.
|
||||
if (loaded.setting_id.empty() && entry.instantiation == "true")
|
||||
loaded.setting_id = generate_preset_setting_id(
|
||||
@@ -5287,7 +5520,8 @@ std::string PresetBundle::load_vendor_preset(
|
||||
|
||||
//BBS: Load a config bundle file from json
|
||||
std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_from_json(
|
||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle)
|
||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle, bool allow_cache)
|
||||
{
|
||||
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
||||
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
||||
@@ -5305,7 +5539,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
||||
// Orca: only a whole-vendor load has a cache — the vendor-only and filament-only
|
||||
// scans want a slice of one. Validation reads the JSONs whatever is cached.
|
||||
const boost::filesystem::path dir_path(dir);
|
||||
const bool cacheable = flags.has(LoadConfigBundleAttribute::LoadSystem) && ! flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
|
||||
const bool cacheable = allow_cache && flags.has(LoadConfigBundleAttribute::LoadSystem) && ! flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
|
||||
if (cacheable && ! validation_mode && this->load_vendor_cache(dir_path, vendor_name, base_bundle)) {
|
||||
size_t presets_loaded = 0;
|
||||
for (const PresetCollection* coll : std::initializer_list<const PresetCollection*>{
|
||||
@@ -6170,7 +6404,11 @@ bool PresetBundle::check_duplicate_filament_subtypes() const
|
||||
// inherited from its @base at load time), grouped by vendor so we only test a
|
||||
// printer against its own vendor's filaments. A vendor's compatible_printers
|
||||
// only names that vendor's printers, so same-vendor scoping is correctness
|
||||
// preserving and avoids an O(all printers x all filaments) sweep.
|
||||
// preserving and avoids an O(all printers x all filaments) sweep. The one
|
||||
// exception is the Orca Filament Library: its presets have empty
|
||||
// compatible_printers (= compatible with every printer, minus the alias-shadowing
|
||||
// exclusions that is_compatible_with_printer checks via m_excluded_from), so they
|
||||
// are tested against every vendor's printers as well.
|
||||
std::map<std::string, std::vector<const Preset *>> filaments_by_vendor;
|
||||
for (const auto &preset : filaments) {
|
||||
if (!preset.is_system || preset.filament_id.empty() || preset.vendor == nullptr)
|
||||
@@ -6178,20 +6416,29 @@ bool PresetBundle::check_duplicate_filament_subtypes() const
|
||||
filaments_by_vendor[preset.vendor->name].push_back(&preset);
|
||||
}
|
||||
|
||||
const std::vector<const Preset *> no_filaments;
|
||||
const auto library_it = filaments_by_vendor.find(ORCA_FILAMENT_LIBRARY);
|
||||
const std::vector<const Preset *> &library_filaments = library_it == filaments_by_vendor.end() ? no_filaments : library_it->second;
|
||||
|
||||
bool found_duplicates = false;
|
||||
for (const auto &printer : printers) {
|
||||
if (!printer.is_system || printer.vendor == nullptr)
|
||||
continue;
|
||||
auto vendor_it = filaments_by_vendor.find(printer.vendor->name);
|
||||
if (vendor_it == filaments_by_vendor.end())
|
||||
const std::vector<const Preset *> &vendor_filaments = vendor_it == filaments_by_vendor.end() ? no_filaments : vendor_it->second;
|
||||
if (vendor_filaments.empty() && library_filaments.empty())
|
||||
continue;
|
||||
|
||||
const PresetWithVendorProfile active_printer = printers.get_preset_with_vendor_profile(printer);
|
||||
// std::map keeps the reported errors in a deterministic (sorted) order.
|
||||
std::map<std::string, std::vector<const Preset *>> by_filament_id;
|
||||
for (const Preset *fil : vendor_it->second)
|
||||
for (const Preset *fil : vendor_filaments)
|
||||
if (is_compatible_with_printer(filaments.get_preset_with_vendor_profile(*fil), active_printer))
|
||||
by_filament_id[fil->filament_id].push_back(fil);
|
||||
if (&vendor_filaments != &library_filaments)
|
||||
for (const Preset *fil : library_filaments)
|
||||
if (is_compatible_with_printer(filaments.get_preset_with_vendor_profile(*fil), active_printer))
|
||||
by_filament_id[fil->filament_id].push_back(fil);
|
||||
|
||||
for (const auto &entry : by_filament_id) {
|
||||
if (entry.second.size() < 2)
|
||||
@@ -6199,9 +6446,15 @@ bool PresetBundle::check_duplicate_filament_subtypes() const
|
||||
found_duplicates = true;
|
||||
// List each conflicting preset with a clickable file:// URI on its own
|
||||
// line, so the profile author can jump straight to the files to fix.
|
||||
// A preset from another bundle (the Orca Filament Library) is tagged with
|
||||
// its vendor so the source bundle is obvious.
|
||||
std::string presets;
|
||||
for (const Preset *p : entry.second)
|
||||
presets += "\n - " + p->name + "\n " + preset_file_uri(p->file);
|
||||
for (const Preset *p : entry.second) {
|
||||
presets += "\n - " + p->name;
|
||||
if (p->vendor != nullptr && p->vendor->name != printer.vendor->name)
|
||||
presets += " [" + p->vendor->name + "]";
|
||||
presets += "\n " + preset_file_uri(p->file);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(error)
|
||||
<< "Ambiguous AMS filament match: " << entry.second.size()
|
||||
<< " filament presets share filament_id \"" << entry.first
|
||||
|
||||
@@ -230,7 +230,22 @@ public:
|
||||
// Load selections (current print, current filaments, current printer) from config.ini
|
||||
// select preferred presets, if any exist
|
||||
PresetsConfigSubstitutions load_presets(AppConfig &config, ForwardCompatibilitySubstitutionRule rule,
|
||||
const PresetPreferences& preferred_selection = PresetPreferences());
|
||||
const PresetPreferences& preferred_selection = PresetPreferences(),
|
||||
std::string *errors = nullptr, bool read_only = false);
|
||||
|
||||
// Resolve an explicitly named source file through a canonical flattened
|
||||
// preset. Exact loaded-file identity is preferred; otherwise a manifest-
|
||||
// backed vendor tree is loaded from that source root without using caches.
|
||||
bool resolve_preset_config(DynamicPrintConfig &config, Preset::Type type,
|
||||
const std::string &source_file,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||
std::string &error, bool allow_source_manifest = true);
|
||||
// Resolve a source file whose JSON omits `type`. Succeeds only when exactly
|
||||
// one FFF preset collection owns the file and returns that collection's type.
|
||||
bool resolve_preset_config_type(DynamicPrintConfig &config, Preset::Type &type,
|
||||
const std::string &source_file,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule,
|
||||
std::string &error, bool allow_source_manifest = true);
|
||||
|
||||
// Load selections (current print, current filaments, current printer) from config.ini
|
||||
// This is done just once on application start up.
|
||||
@@ -238,7 +253,7 @@ public:
|
||||
void load_selections(AppConfig &config, const PresetPreferences& preferred_selection = PresetPreferences());
|
||||
|
||||
// BBS Load user presets
|
||||
PresetsConfigSubstitutions load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule rule);
|
||||
PresetsConfigSubstitutions load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule rule, bool read_only = false);
|
||||
PresetsConfigSubstitutions load_user_presets(AppConfig &config, std::map<std::string, std::map<std::string, std::string>>& my_presets, ForwardCompatibilitySubstitutionRule rule);
|
||||
// Orca: Import subscribed bundle presets (load and save to disk in one operation), handles one bundle at a time
|
||||
PresetsConfigSubstitutions update_subscribed_presets(AppConfig& config,
|
||||
@@ -350,6 +365,13 @@ public:
|
||||
std::vector<std::vector<DynamicPrintConfig>> get_extruder_filament_info() const;
|
||||
|
||||
std::set<std::string> get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only = true);
|
||||
// Orca: the root filament presets a connected machine can use, resolved with the rule the rest
|
||||
// of the app applies (is_compatible_with_printer): an empty compatible_printers means every
|
||||
// printer, minus the alias shadowing exclusions the Orca Filament Library records in
|
||||
// Preset::m_excluded_from.
|
||||
std::vector<Preset *> get_filament_presets_for_machine(const std::string &printer_type,
|
||||
const std::string &nozzle_diameter_str,
|
||||
bool include_user_presets);
|
||||
bool check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray(const std::string &printer_type,
|
||||
std::string & nozzle_diameter_str,
|
||||
std::string & setting_id,
|
||||
@@ -474,10 +496,13 @@ public:
|
||||
//Orca: load config bundle from json, pass the base bundle to support cross vendor inheritance
|
||||
// Orca: `dir` is where the vendor is looked for — its own directory, whether or
|
||||
// not the profile JSONs are still there. A whole-vendor load comes from the
|
||||
// vendor's preset cache whenever one covers the profile on disk, and is parsed
|
||||
// from the JSONs in `dir` only when none does. Nothing here reads resources.
|
||||
// vendor's preset cache whenever one covers the profile on disk and allow_cache
|
||||
// is true, and is parsed from the JSONs in `dir` otherwise. Nothing here reads
|
||||
// resources implicitly.
|
||||
std::pair<PresetsConfigSubstitutions, size_t> load_vendor_configs_from_json(
|
||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle = nullptr);
|
||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags,
|
||||
ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle = nullptr,
|
||||
bool allow_cache = true);
|
||||
|
||||
// Export a config bundle file containing all the presets and the names of the active presets.
|
||||
//void export_configbundle(const std::string &path, bool export_system_settings = false, bool export_physical_printers = false);
|
||||
@@ -599,6 +624,7 @@ private:
|
||||
|
||||
// Whether to (re)write a per-vendor cache after a JSON parse.
|
||||
bool m_generate_vendor_caches { false };
|
||||
bool m_preserve_vendor_source_paths { false };
|
||||
|
||||
// Orca: validation only - flag any printer with two or more compatible
|
||||
// filament presets sharing one filament_id (ambiguous AMS subtype match).
|
||||
@@ -606,7 +632,7 @@ private:
|
||||
|
||||
//std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
//BBS: add json related logic
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule, bool allow_cache = true);
|
||||
// Update the multicolor information for filaments.
|
||||
void update_filament_multi_color();
|
||||
// Update renamed_from and alias maps of system profiles.
|
||||
|
||||
@@ -333,8 +333,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
||||
m_print_config (&object->print()->config()),
|
||||
m_object_config (&object->config()),
|
||||
m_slicing_params (slicing_params),
|
||||
m_support_params (*object),
|
||||
m_object (object)
|
||||
m_support_params (*object)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ private:
|
||||
*/
|
||||
|
||||
// Following objects are not owned by SupportMaterial class.
|
||||
const PrintObject *m_object;
|
||||
const PrintConfig *m_print_config;
|
||||
const PrintObjectConfig *m_object_config;
|
||||
// Pre-calculated parameters shared between the object slicer and the support generator,
|
||||
|
||||
@@ -432,7 +432,6 @@ private:
|
||||
size_t m_highest_overhang_layer = 0;
|
||||
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;
|
||||
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
||||
float DO_NOT_MOVER_UNDER_MM = 0.0;
|
||||
coordf_t base_radius = 0.0;
|
||||
const coordf_t MAX_BRANCH_RADIUS = 10.0;
|
||||
const coordf_t MIN_BRANCH_RADIUS = 0.4;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
@@ -607,6 +608,17 @@ static inline std::vector<IntersectionLines> slice_make_lines(
|
||||
}
|
||||
}
|
||||
);
|
||||
// Facet processing above is parallel, so per-layer line order depends on thread scheduling,
|
||||
// and make_loops() derives island order and loop start vertices from it. Sort canonically;
|
||||
// edge_type and flags only break ties, std::sort being unstable.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, lines.size()),
|
||||
[&lines](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++ i)
|
||||
std::sort(lines[i].begin(), lines[i].end(), [](const IntersectionLine &l, const IntersectionLine &r) {
|
||||
return std::make_tuple(l.edge_a_id, l.edge_b_id, l.a_id, l.b_id, l.a.x(), l.a.y(), l.b.x(), l.b.y(), l.edge_type, l.flags) <
|
||||
std::make_tuple(r.edge_a_id, r.edge_b_id, r.a_id, r.b_id, r.a.x(), r.a.y(), r.b.x(), r.b.y(), r.edge_type, r.flags);
|
||||
});
|
||||
});
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
@@ -1511,6 +1511,10 @@ void AMSDryCtrWin::update_filament_guide_info(DevAms* dev_ams)
|
||||
m_temperature_input->GetValue().ToLong(&input_temp);
|
||||
bool can_start = true;
|
||||
|
||||
// "GFA00" is Bambu's PLA id; GetFilamentDryingPreset is keyed by our OF ids.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string pla_filament_id = agent ? agent->to_orca_filament_id("GFA00") : std::string("GFA00");
|
||||
|
||||
int slot_count = 0, empty_count = 0;
|
||||
for (auto& tray_pair : dev_ams->GetTrays()) {
|
||||
if (!tray_pair.second) {
|
||||
@@ -1526,13 +1530,15 @@ void AMSDryCtrWin::update_filament_guide_info(DevAms* dev_ams)
|
||||
wxString filament_type = tray_pair.second->get_display_filament_type();
|
||||
DevFilamentDryingPreset preset;
|
||||
if (filament_type.IsEmpty()) {
|
||||
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
|
||||
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset(pla_filament_id);
|
||||
if (!fallback_preset) continue; // no PLA preset (e.g. the id map is missing): skip, don't throw
|
||||
preset = fallback_preset.value();
|
||||
filament_type = "?";
|
||||
} else if (preset_opt.has_value()) {
|
||||
preset = preset_opt.value();
|
||||
} else {
|
||||
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
|
||||
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset(pla_filament_id);
|
||||
if (!fallback_preset) continue;
|
||||
preset = fallback_preset.value();
|
||||
}
|
||||
std::string icon_path = "dev_ams_dry_ctr_enable";
|
||||
@@ -1594,39 +1600,21 @@ int AMSDryCtrWin::update_filament_list(DevAms* dev_ams, MachineObject* obj)
|
||||
}
|
||||
stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str);
|
||||
|
||||
for (auto filament_it = filaments.begin(); filament_it != filaments.end(); ++filament_it) {
|
||||
Preset& preset = *filament_it;
|
||||
// Filter by system preset: root preset and (system preset or user preset is supported)
|
||||
if (filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) {
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string filament_alias = filaments.get_preset_alias(*filament_it, true);
|
||||
if (filament_alias.empty())
|
||||
continue;
|
||||
auto opt_info = preset_bundle->get_filament_by_filament_id(filament_it->filament_id);
|
||||
if (!opt_info.has_value())
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigOption * printer_opt = filament_it->config.option("compatible_printers");
|
||||
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
|
||||
if (!printer_strs) continue;
|
||||
|
||||
for (auto printer_str : printer_strs->values) {
|
||||
if (printer_names.find(printer_str) != printer_names.end()) {
|
||||
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filament_id_set.insert(filament_it->filament_id);
|
||||
auto filament_alias = filaments.get_preset_alias(*filament_it, true);
|
||||
if (!filament_alias.empty()) {
|
||||
auto opt_info = preset_bundle->get_filament_by_filament_id(filament_it->filament_id);
|
||||
if (opt_info.has_value()) {
|
||||
auto real_info = opt_info.value();
|
||||
real_info.filament_name = filament_alias;
|
||||
m_tray_ids.push_back(std::move(real_info));
|
||||
m_trays_combo->Append(wxString::FromUTF8(filament_alias));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opt_info->filament_name = filament_alias;
|
||||
m_tray_ids.push_back(std::move(*opt_info));
|
||||
m_trays_combo->Append(wxString::FromUTF8(filament_alias));
|
||||
}
|
||||
|
||||
if (m_tray_ids.empty()) {
|
||||
@@ -1701,9 +1689,10 @@ int AMSDryCtrWin::update_filament_list(DevAms* dev_ams, MachineObject* obj)
|
||||
|
||||
// Select recommended drying temperature and default filament
|
||||
float min_dry_temp = std::numeric_limits<float>::max();
|
||||
std::string default_filament_id = "GFA00";
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
std::string default_filament_id = agent ? agent->to_orca_filament_id("GFA00") : std::string("GFA00"); // compared against m_tray_ids[i].filament_id (our OF ids) below
|
||||
bool has_ready = false;
|
||||
const auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
|
||||
const auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset(default_filament_id);
|
||||
for (const auto& tray_pair : dev_ams->GetTrays()) {
|
||||
if (!tray_pair.second || !tray_pair.second->is_tray_info_ready()) continue;
|
||||
has_ready = true;
|
||||
|
||||
@@ -97,12 +97,6 @@ private:
|
||||
wxSimplebook* m_main_simplebook{nullptr};
|
||||
wxPanel* m_original_page{nullptr};
|
||||
|
||||
wxWindow* m_amswin{nullptr};
|
||||
wxBoxSizer* m_sizer_ams_items{nullptr};
|
||||
wxScrolledWindow* m_panel_prv_left {nullptr};
|
||||
wxScrolledWindow* m_panel_prv_right{nullptr};
|
||||
wxBoxSizer* m_sizer_prv_left{nullptr};
|
||||
wxBoxSizer* m_sizer_prv_right{nullptr};
|
||||
|
||||
// left panel related members
|
||||
ScalableBitmap m_humidity_image;
|
||||
|
||||
@@ -681,6 +681,19 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
}
|
||||
|
||||
|
||||
// Orca: log the tray payload this dialog hands the printer, so the filament_id resolved from the
|
||||
// dropdown selection can be checked against the tray_info_idx the AMS actually receives. A
|
||||
// BBL-tagged (RFID) tray is read-only here, so nothing is published for it.
|
||||
BOOST_LOG_TRIVIAL(info) << "ams_materials_setting: " << (m_is_third ? "sending" : "NOT sending (BBL RFID tray, read-only)")
|
||||
<< ", ams_id = " << ams_id << ", slot_id = " << slot_id
|
||||
<< ", selected = " << m_comboBox_filament->GetValue().ToStdString()
|
||||
<< ", tray_info_idx (filament_id) = " << ams_filament_id
|
||||
<< ", setting_id = " << ams_setting_id
|
||||
<< ", tray_type = " << m_filament_type
|
||||
<< ", tray_color = " << col_buf
|
||||
<< ", nozzle_temp_min = " << nozzle_temp_min_int
|
||||
<< ", nozzle_temp_max = " << nozzle_temp_max_int;
|
||||
|
||||
// set filament
|
||||
if (m_is_third) {
|
||||
obj->command_ams_filament_settings(ams_id, slot_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
|
||||
@@ -802,7 +815,10 @@ void AMSMaterialsSetting::set_color(wxColour color)
|
||||
fila_color.m_colors.insert(color);
|
||||
fila_color.EndSet(m_clr_picker->ctype);
|
||||
auto clr_query = GUI::wxGetApp().get_filament_color_code_query();
|
||||
m_clr_name->SetLabelText(clr_query->GetFilaColorName(ams_filament_id, fila_color));
|
||||
// ams_filament_id is our OF id; GetFilaColorName looks up filaments_color_codes.json,
|
||||
// downloaded from Bambu and keyed by the printer's own ids, so translate for this lookup only.
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
m_clr_name->SetLabelText(clr_query->GetFilaColorName(agent ? agent->from_orca_filament_id(ams_filament_id) : ams_filament_id, fila_color));
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::set_empty_color(wxColour color)
|
||||
@@ -823,7 +839,10 @@ void AMSMaterialsSetting::set_colors(std::vector<wxColour> colors)
|
||||
for (const auto& clr : colors) { fila_color.m_colors.insert(clr); }
|
||||
fila_color.EndSet(m_clr_picker->ctype);
|
||||
auto clr_query = GUI::wxGetApp().get_filament_color_code_query();
|
||||
m_clr_name->SetLabelText(clr_query->GetFilaColorName(ams_filament_id, fila_color));
|
||||
// ams_filament_id is our OF id; GetFilaColorName looks up filaments_color_codes.json,
|
||||
// downloaded from Bambu and keyed by the printer's own ids, so translate for this lookup only.
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
m_clr_name->SetLabelText(clr_query->GetFilaColorName(agent ? agent->from_orca_filament_id(ams_filament_id) : ams_filament_id, fila_color));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +951,6 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
m_input_k_val->GetTextCtrl()->SetValue(k);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(n);
|
||||
|
||||
int idx = 0;
|
||||
wxArrayString filament_items;
|
||||
wxString bambu_filament_name;
|
||||
wxString hint_filament_name; // the hint type to be selected
|
||||
@@ -940,6 +958,9 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
std::unordered_map<wxString, wxString> query_filament_types; //
|
||||
|
||||
std::set<std::string> filament_id_set;
|
||||
// The alias keyed map has to start empty: it is a member, so a stale alias left by an earlier
|
||||
// popup (a different printer, a different nozzle) would resolve to that printer's filament_id.
|
||||
map_filament_items.clear();
|
||||
PresetBundle * preset_bundle = wxGetApp().preset_bundle;
|
||||
std::ostringstream stream;
|
||||
// Defensive: this dialog is opened only from StatusPanel (BBL-only) today, so the fallback fires
|
||||
@@ -952,83 +973,48 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
}
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str);
|
||||
|
||||
if (preset_bundle) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
|
||||
//filter by system preset
|
||||
Preset& preset = *filament_it;
|
||||
/*The situation where the user preset is not displayed is as follows:
|
||||
1. Not a root preset
|
||||
2. Not system preset and the printer firmware does not support user preset */
|
||||
if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) {
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string alias = preset_bundle->filaments.get_preset_alias(*filament_it, true);
|
||||
if (alias.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigOption * printer_opt = filament_it->config.option("compatible_printers");
|
||||
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
|
||||
for (auto printer_str : printer_strs->values) {
|
||||
if (printer_names.find(printer_str) != printer_names.end()) {
|
||||
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
|
||||
continue;
|
||||
} else {
|
||||
filament_id_set.insert(filament_it->filament_id);
|
||||
// name matched
|
||||
if (filament_it->is_system) {
|
||||
filament_items.push_back(filament_it->alias);
|
||||
_collect_filament_info(filament_it->alias, preset, query_filament_vendors, query_filament_types);
|
||||
filament_items.push_back(alias);
|
||||
_collect_filament_info(alias, *filament_it, query_filament_vendors, query_filament_types);
|
||||
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[filament_it->alias] = filament_infos;
|
||||
} else {
|
||||
char target = '@';
|
||||
size_t pos = filament_it->name.find(target);
|
||||
if (pos != std::string::npos) {
|
||||
std::string user_preset_alias = filament_it->name.substr(0, pos - 1);
|
||||
wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8);
|
||||
user_preset_alias = wx_user_preset_alias.ToStdString();
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[alias] = filament_infos;
|
||||
|
||||
filament_items.push_back(user_preset_alias);
|
||||
_collect_filament_info(user_preset_alias, preset, query_filament_vendors, query_filament_types);
|
||||
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[user_preset_alias] = filament_infos;
|
||||
}
|
||||
}
|
||||
|
||||
if (filament_it->filament_id == ams_filament_id) {
|
||||
hint_filament_name = from_u8(filament_it->alias);
|
||||
bambu_filament_name = from_u8(filament_it->alias);
|
||||
if (filament_it->filament_id == ams_filament_id) {
|
||||
hint_filament_name = from_u8(alias);
|
||||
bambu_filament_name = from_u8(alias);
|
||||
|
||||
|
||||
// update if nozzle_temperature_range is found
|
||||
ConfigOption *opt_min = filament_it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts *opt_min_ints = dynamic_cast<ConfigOptionInts *>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
}
|
||||
ConfigOption *opt_max = filament_it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts *opt_max_ints = dynamic_cast<ConfigOptionInts *>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
// update if nozzle_temperature_range is found
|
||||
ConfigOption *opt_min = filament_it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts *opt_min_ints = dynamic_cast<ConfigOptionInts *>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
}
|
||||
ConfigOption *opt_max = filament_it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts *opt_max_ints = dynamic_cast<ConfigOptionInts *>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1251,56 +1237,47 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
}
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(DevPrinterConfigUtil::get_printer_display_name(obj->printer_type),
|
||||
nozzle_diameter_str);
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
if (!m_comboBox_filament->GetValue().IsEmpty()) {
|
||||
auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()];
|
||||
std::string filament_id = filament_item.filament_id;
|
||||
if (it->filament_id.compare(filament_id) == 0) {
|
||||
ConfigOption * printer_opt = it->config.option("compatible_printers");
|
||||
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
|
||||
bool has_compatible_printer = false;
|
||||
for (auto printer_str : printer_strs->values) {
|
||||
if (printer_names.find(printer_str) != printer_names.end()) {
|
||||
has_compatible_printer = true;
|
||||
break;
|
||||
}
|
||||
// Resolve the selection against the same list Popup() built the dropdown from, so the two
|
||||
// halves of the dialog cannot disagree about which filaments this machine can use.
|
||||
const std::string selected = m_comboBox_filament->GetValue().ToStdString();
|
||||
if (!selected.empty()) {
|
||||
const std::string filament_id = map_filament_items[selected].filament_id;
|
||||
for (Preset *it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (it->filament_id != filament_id)
|
||||
continue;
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
if (!it->is_system && !has_compatible_printer) continue;
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
bool found_filament_type = false;
|
||||
if (opt_type) {
|
||||
ConfigOptionStrings* opt_type_strs = dynamic_cast<ConfigOptionStrings*>(opt_type);
|
||||
if (opt_type_strs) {
|
||||
found_filament_type = true;
|
||||
//m_filament_type = opt_type_strs->get_at(0);
|
||||
std::string display_filament_type;
|
||||
m_filament_type = it->config.get_filament_type(display_filament_type);
|
||||
}
|
||||
}
|
||||
if (!found_filament_type)
|
||||
m_filament_type = "";
|
||||
|
||||
break;
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
bool found_filament_type = false;
|
||||
if (opt_type) {
|
||||
ConfigOptionStrings* opt_type_strs = dynamic_cast<ConfigOptionStrings*>(opt_type);
|
||||
if (opt_type_strs) {
|
||||
found_filament_type = true;
|
||||
//m_filament_type = opt_type_strs->get_at(0);
|
||||
std::string display_filament_type;
|
||||
m_filament_type = it->config.get_filament_type(display_filament_type);
|
||||
}
|
||||
}
|
||||
if (!found_filament_type)
|
||||
m_filament_type = "";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +457,6 @@ private:
|
||||
ScalableBitmap close_img;
|
||||
|
||||
wxStaticBitmap* curr_humidity_img;
|
||||
wxStaticBitmap* m_img;
|
||||
|
||||
Label* m_staticText;;
|
||||
Label* m_staticText_note;
|
||||
|
||||
@@ -93,7 +93,6 @@ private:
|
||||
CenteredTitle* m_title_ctrl { nullptr };
|
||||
wxString m_titleText;
|
||||
|
||||
wxAuiToolBarItem* m_model_store_item;
|
||||
|
||||
//wxAuiToolBarItem *m_publish_item;
|
||||
wxAuiToolBarItem* m_undo_item;
|
||||
|
||||
@@ -65,18 +65,10 @@ private:
|
||||
wxPanel* request_bind_panel;
|
||||
wxPanel* binding_panel;
|
||||
|
||||
wxScrolledWindow* m_sw_bind_failed_info;
|
||||
Label* m_bind_failed_info;
|
||||
Label* m_st_txt_error_code{ nullptr };
|
||||
Label* m_st_txt_error_desc{ nullptr };
|
||||
Label* m_st_txt_extra_info{ nullptr };
|
||||
HyperLink* m_link_network_state{ nullptr };
|
||||
wxString m_result_info;
|
||||
wxString m_result_extra;
|
||||
wxString m_ping_code_wiki;
|
||||
bool m_show_error_info_state = true;
|
||||
|
||||
int m_result_code;
|
||||
std::shared_ptr<BBLStatusBarBind> m_status_bar;
|
||||
|
||||
public:
|
||||
@@ -110,7 +102,6 @@ private:
|
||||
wxBitmap m_bitmap_show_error_close;
|
||||
wxBitmap m_bitmap_show_error_open;
|
||||
wxScrolledWindow* m_sw_bind_failed_info;
|
||||
Label* m_bind_failed_info;
|
||||
Label* m_st_txt_error_code{ nullptr };
|
||||
Label* m_st_txt_error_desc{ nullptr };
|
||||
Label* m_st_txt_extra_info{ nullptr };
|
||||
|
||||
@@ -702,7 +702,6 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject
|
||||
|
||||
wxArrayString filament_items;
|
||||
std::set<std::string> filament_id_set;
|
||||
std::set<std::string> printer_names;
|
||||
std::ostringstream stream;
|
||||
// If the machine didn't report a nozzle diameter (0.0 = unknown), fall back to the currently
|
||||
// selected printer preset so the filament list isn't empty.
|
||||
@@ -714,67 +713,21 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
|
||||
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) {
|
||||
// filter by system preset
|
||||
if (!printer_it->is_system)
|
||||
continue;
|
||||
// get printer_model
|
||||
ConfigOption * printer_model_opt = printer_it->config.option("printer_model");
|
||||
ConfigOptionString *printer_model_str = dynamic_cast<ConfigOptionString *>(printer_model_opt);
|
||||
if (!printer_model_str)
|
||||
continue;
|
||||
|
||||
// use printer_model as printer type
|
||||
if (printer_model_str->value != DevPrinterConfigUtil::get_printer_display_name(obj->printer_type))
|
||||
continue;
|
||||
|
||||
if (printer_it->name.find(nozzle_diameter_str) != std::string::npos)
|
||||
printer_names.insert(printer_it->name);
|
||||
}
|
||||
|
||||
if (preset_bundle) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
|
||||
// filter by system preset
|
||||
Preset &preset = *filament_it;
|
||||
/*The situation where the user preset is not displayed is as follows:
|
||||
1. Not a root preset
|
||||
2. Not system preset and the printer firmware does not support user preset */
|
||||
if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && ! obj->is_support_user_preset)) { continue; }
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string alias = preset_bundle->filaments.get_preset_alias(*filament_it, true);
|
||||
if (alias.empty())
|
||||
continue;
|
||||
|
||||
ConfigOption * printer_opt = filament_it->config.option("compatible_printers");
|
||||
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
|
||||
for (auto printer_str : printer_strs->values) {
|
||||
if (printer_names.find(printer_str) != printer_names.end()) {
|
||||
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
|
||||
continue;
|
||||
} else {
|
||||
filament_id_set.insert(filament_it->filament_id);
|
||||
// name matched
|
||||
if (filament_it->is_system) {
|
||||
filament_items.push_back(filament_it->alias);
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[filament_it->alias] = filament_infos;
|
||||
} else {
|
||||
char target = '@';
|
||||
size_t pos = filament_it->name.find(target);
|
||||
if (pos != std::string::npos) {
|
||||
std::string user_preset_alias = filament_it->name.substr(0, pos - 1);
|
||||
wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8);
|
||||
user_preset_alias = wx_user_preset_alias.ToStdString();
|
||||
|
||||
filament_items.push_back(user_preset_alias);
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[user_preset_alias] = filament_infos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
filament_items.push_back(alias);
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[alias] = filament_infos;
|
||||
}
|
||||
}
|
||||
return filament_items;
|
||||
|
||||
@@ -70,11 +70,7 @@ public:
|
||||
|
||||
private:
|
||||
int m_my_devices_count{ 0 };
|
||||
int m_other_devices_count{ 0 };
|
||||
bool m_dismiss{ false };
|
||||
wxWindow* m_placeholder_panel { nullptr };
|
||||
wxWindow* m_panel_body{ nullptr };
|
||||
wxBoxSizer* m_sizer_body{ nullptr };
|
||||
wxBoxSizer* m_sizer_my_devices{ nullptr };
|
||||
wxScrolledWindow* m_scrolledWindow{ nullptr };
|
||||
wxTimer* m_refresh_timer{ nullptr };
|
||||
|
||||
@@ -72,8 +72,10 @@ private:
|
||||
SwitchButton* m_switch_recording;
|
||||
wxStaticText* m_text_vcamera;
|
||||
SwitchButton* m_switch_vcamera;
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
wxStaticText* m_text_liveview_retry;
|
||||
SwitchButton* m_switch_liveview_retry;
|
||||
#endif //BBL_RELEASE_TO_PUBLIC
|
||||
wxStaticText* m_custom_camera_hint;
|
||||
TextInput* m_custom_camera_input;
|
||||
Button* m_custom_camera_input_confirm;
|
||||
|
||||
@@ -62,10 +62,16 @@ std::string decompose_basic_type_from_source(size_t source_config_idx,
|
||||
auto& project_config = wxGetApp().preset_bundle->project_config;
|
||||
if (auto* filament_id_opt = project_config.option<ConfigOptionStrings>("filament_id")) {
|
||||
if (source_config_idx < filament_id_opt->values.size()) {
|
||||
const std::string& filament_id = filament_id_opt->values[source_config_idx];
|
||||
if (filament_id == kDecomposePetgFilamentId)
|
||||
// Dead in practice: "filament_id" is not in PresetBundle's s_project_options, so this
|
||||
// option() lookup (create=false) always returns null and the block never runs. Kept as
|
||||
// found, with the translation the values would need: they would be our OF ids, and the
|
||||
// two constants are the printer's own ids.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string& orca_filament_id = filament_id_opt->values[source_config_idx];
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(orca_filament_id) : orca_filament_id;
|
||||
if (printer_filament_id == kDecomposePetgFilamentId)
|
||||
return kDecomposePetgBasicType;
|
||||
if (filament_id == kDecomposePlaFilamentId)
|
||||
if (printer_filament_id == kDecomposePlaFilamentId)
|
||||
return kDecomposePlaBasicType;
|
||||
}
|
||||
}
|
||||
@@ -82,9 +88,14 @@ std::string decompose_basic_type_from_source(size_t source_config_idx,
|
||||
|
||||
std::string decompose_basic_filament_id(const std::string& basic_type)
|
||||
{
|
||||
if (basic_type == kDecomposePetgBasicType)
|
||||
return kDecomposePetgFilamentId;
|
||||
return kDecomposePlaFilamentId;
|
||||
// The result becomes DecomposeOfficialComponent::filament_id, which the rest of this file
|
||||
// reads as one of our OF ids (translating back before it compares against the printer's
|
||||
// ids), so translate on the way out; kDecompose*FilamentId itself stays the printer-side
|
||||
// literal. The only place that would carry it further, project_config's "filament_id", is
|
||||
// dead code: that key is not in PresetBundle's s_project_options.
|
||||
const std::string printer_filament_id = basic_type == kDecomposePetgBasicType ? kDecomposePetgFilamentId : kDecomposePlaFilamentId;
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
return agent ? agent->to_orca_filament_id(printer_filament_id) : printer_filament_id;
|
||||
}
|
||||
|
||||
void set_created_standard_component_metadata(size_t config_idx, const DecomposeOfficialComponent& component)
|
||||
@@ -98,8 +109,11 @@ void set_created_standard_component_metadata(size_t config_idx, const DecomposeO
|
||||
}
|
||||
}
|
||||
|
||||
const std::string type = component.filament_id == kDecomposePetgFilamentId ? kDecomposePetgShortType :
|
||||
component.filament_id == kDecomposePlaFilamentId ? kDecomposePlaShortType : "";
|
||||
// component.filament_id is our OF id; the two constants are the printer's own ids.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(component.filament_id) : component.filament_id;
|
||||
const std::string type = printer_filament_id == kDecomposePetgFilamentId ? kDecomposePetgShortType :
|
||||
printer_filament_id == kDecomposePlaFilamentId ? kDecomposePlaShortType : "";
|
||||
if (!type.empty()) {
|
||||
if (auto* type_opt = project_config.option<ConfigOptionStrings>("filament_type")) {
|
||||
while (type_opt->values.size() <= config_idx)
|
||||
@@ -151,7 +165,12 @@ DecomposeOfficialComponent lookup_decompose_official_component(
|
||||
continue;
|
||||
if (item.contains("fila_color") && item["fila_color"].is_array() && !item["fila_color"].empty())
|
||||
result.color_hex = decompose_normalize_color_hex(item["fila_color"][0].get<std::string>());
|
||||
result.filament_id = item.value("fila_id", result.filament_id);
|
||||
// fila_id from this shipped, Bambu-keyed color table is a printer-side id; translate it so
|
||||
// result.filament_id stays an OF id like the rest of this struct (the fallback default,
|
||||
// result.filament_id, is already OF and passes through unchanged).
|
||||
const std::string fila_id = item.value("fila_id", result.filament_id);
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
result.filament_id = agent ? agent->to_orca_filament_id(fila_id) : fila_id;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -211,8 +230,11 @@ int find_existing_decompose_component(
|
||||
auto* type_opt = project_config.option<ConfigOptionStrings>("filament_type");
|
||||
const PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
|
||||
const size_t num_physical = physical_colors.size();
|
||||
const std::string expected_basic_type = component.filament_id == kDecomposePetgFilamentId ? kDecomposePetgBasicType :
|
||||
component.filament_id == kDecomposePlaFilamentId ? kDecomposePlaBasicType : "";
|
||||
// component.filament_id is our OF id; the two constants are the printer's own ids.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(component.filament_id) : component.filament_id;
|
||||
const std::string expected_basic_type = printer_filament_id == kDecomposePetgFilamentId ? kDecomposePetgBasicType :
|
||||
printer_filament_id == kDecomposePlaFilamentId ? kDecomposePlaBasicType : "";
|
||||
const std::string expected_short_type = expected_basic_type == kDecomposePetgBasicType ? kDecomposePetgShortType :
|
||||
expected_basic_type == kDecomposePlaBasicType ? kDecomposePlaShortType : "";
|
||||
const std::string expected_preset_part = expected_basic_type.empty() ? "" : std::string(kDecomposeBambuPresetPrefix) + expected_basic_type;
|
||||
|
||||
@@ -74,7 +74,6 @@ private:
|
||||
std::unordered_set<std::string> m_system_filament_types_set;
|
||||
std::set<std::string> m_visible_printers;
|
||||
CreateType m_create_type;
|
||||
Button * m_button_cancel = nullptr;
|
||||
ComboBox * m_filament_vendor_combobox = nullptr;
|
||||
::CheckBox * m_can_not_find_vendor_checkbox = nullptr;
|
||||
ComboBox * m_filament_type_combobox = nullptr;
|
||||
|
||||
@@ -245,7 +245,6 @@ DailyTipsPanel::DailyTipsPanel(bool can_expand, DailyTipsLayout layout)
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_can_expand(can_expand),
|
||||
m_layout(layout),
|
||||
m_uid(DailyTipsPanel::uid++),
|
||||
m_dailytips_renderer(std::make_unique<DailyTipsDataRenderer>(layout))
|
||||
{
|
||||
|
||||
@@ -51,7 +51,6 @@ private:
|
||||
int m_uid;
|
||||
bool m_first_enter{ false };
|
||||
bool m_is_dark{ false };
|
||||
DailyTipsLayout m_layout{ DailyTipsLayout::Vertical };
|
||||
float m_fade_opacity{ 1.0f };
|
||||
};
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
void ParseCalibrationConfig(const json& print_json); //cali
|
||||
|
||||
private:
|
||||
MachineObject* m_obj;
|
||||
[[maybe_unused]] MachineObject* m_obj;
|
||||
|
||||
/*configure vals*/
|
||||
// chamber
|
||||
|
||||
@@ -31,7 +31,7 @@ protected:
|
||||
DevExtensionTool(MachineObject* obj);
|
||||
|
||||
private:
|
||||
MachineObject* m_owner = nullptr;
|
||||
[[maybe_unused]] MachineObject* m_owner = nullptr;
|
||||
|
||||
enum MountState
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
void SetAutoRefillEnabled(bool enable) { m_enable_auto_refill = enable; }
|
||||
|
||||
private:
|
||||
DevFilaSystem* m_owner = nullptr;
|
||||
[[maybe_unused]] DevFilaSystem* m_owner = nullptr;
|
||||
|
||||
std::optional<bool> m_enable_detect_on_insert = false;
|
||||
bool m_enable_detect_on_powerup = false;
|
||||
|
||||
@@ -241,8 +241,11 @@ void check_filaments(const DevFilaBlacklist::CheckFilamentInfo& check_info, DevF
|
||||
std::set<std::string> white_fila_ids = filament_item.contains("white_fila_ids") ? filament_item["white_fila_ids"].get<std::set<std::string>>() : std::set<std::string>();
|
||||
if (!white_fila_ids.empty() && !check_info.fila_id.empty())
|
||||
{
|
||||
auto it = std::find_if(white_fila_ids.begin(), white_fila_ids.end(), [&check_info](const std::string& white_fila_id) {
|
||||
return white_fila_id == check_info.fila_id;
|
||||
// check_info.fila_id is our OF id; white_fila_ids in filaments_blacklist.json holds the printer's own.
|
||||
auto* agent = Slic3r::GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(check_info.fila_id) : check_info.fila_id;
|
||||
auto it = std::find_if(white_fila_ids.begin(), white_fila_ids.end(), [&printer_filament_id](const std::string& white_fila_id) {
|
||||
return white_fila_id == printer_filament_id;
|
||||
});
|
||||
if (it != white_fila_ids.end()) { continue; }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// TODO: remove this include
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
#include "DevUtil.h"
|
||||
#include "DevUtilBackend.h"
|
||||
@@ -95,7 +96,12 @@ std::string DevAmsTray::get_filament_type()
|
||||
if (m_fila_type == "Sup.ABS") { return "ABS-S"; }
|
||||
if (m_fila_type == "Support W") { return "PLA-S"; }
|
||||
if (m_fila_type == "Support G") { return "PA-S"; }
|
||||
if (m_fila_type == "Support") { if (setting_id == "GFS00") { m_fila_type = "PLA-S"; } else if (setting_id == "GFS01") { m_fila_type = "PA-S"; } else { return "PLA-S"; } }
|
||||
// setting_id is our OF id; GFS00/GFS01 are the printer's own support-filament ids.
|
||||
if (m_fila_type == "Support") {
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(setting_id) : setting_id;
|
||||
if (printer_filament_id == "GFS00") { m_fila_type = "PLA-S"; } else if (printer_filament_id == "GFS01") { m_fila_type = "PA-S"; } else { return "PLA-S"; }
|
||||
}
|
||||
|
||||
return m_fila_type;
|
||||
}
|
||||
@@ -654,11 +660,14 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
||||
curr_tray->setting_id = (*tray_it)["tray_info_idx"].get<std::string>();
|
||||
//std::string type = (*tray_it)["tray_type"].get<std::string>();
|
||||
std::string type = MachineObject::setting_id_to_type(curr_tray->setting_id, (*tray_it)["tray_type"].get<std::string>());
|
||||
if (curr_tray->setting_id == "GFS00")
|
||||
// curr_tray->setting_id is our OF id; GFS00/GFS01 are the printer's own support-filament ids.
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(curr_tray->setting_id) : curr_tray->setting_id;
|
||||
if (printer_filament_id == "GFS00")
|
||||
{
|
||||
curr_tray->m_fila_type = "PLA-S";
|
||||
}
|
||||
else if (curr_tray->setting_id == "GFS01")
|
||||
else if (printer_filament_id == "GFS01")
|
||||
{
|
||||
curr_tray->m_fila_type = "PA-S";
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
std::string id;
|
||||
std::string tag_uid; // tag_uid
|
||||
std::string setting_id; // tray_info_idx
|
||||
std::string setting_id; // tray_info_idx, map to the filament_id
|
||||
std::string filament_setting_id; // setting_id
|
||||
std::string m_fila_type;
|
||||
std::string sub_brands;
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
const std::vector<DevHMSItem>& GetHMSItems() const { return m_hms_list; };
|
||||
|
||||
private:
|
||||
MachineObject* m_object = nullptr;
|
||||
[[maybe_unused]] MachineObject* m_object = nullptr;
|
||||
|
||||
// all hms for this machine
|
||||
std::vector<DevHMSItem> m_hms_list;
|
||||
|
||||
@@ -34,7 +34,7 @@ private:
|
||||
//std::string m_connect_type;
|
||||
//std::string m_bind_state;
|
||||
|
||||
MachineObject* m_owner = nullptr;
|
||||
[[maybe_unused]] MachineObject* m_owner = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void ParseStatus(const nlohmann::json& print_jj);
|
||||
|
||||
private:
|
||||
MachineObject *m_owner = nullptr;
|
||||
[[maybe_unused]] MachineObject *m_owner = nullptr;
|
||||
std::optional<DevJobState> m_job_state; // could be nullopt for some old firmware
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
bool is_timelapse_storage_low(const std::string& storage) const;
|
||||
|
||||
private:
|
||||
MachineObject *m_owner;
|
||||
[[maybe_unused]] MachineObject *m_owner;
|
||||
SdcardState m_sdcard_state { NO_SDCARD };
|
||||
// timelapse storage space info (from device push cam data)
|
||||
int tl_internal_free_kb{-1};
|
||||
|
||||
@@ -110,7 +110,9 @@ bool Slic3r::is_stringing_prone_filament(const std::string& filament_id, float n
|
||||
if (filament_id.empty()) return false;
|
||||
const auto* set = pick_stringing_set(nozzle_diameter);
|
||||
if (!set) return false;
|
||||
return set->count(filament_id) > 0;
|
||||
// filament_id is one of our content-addressed OF ids; the table above is keyed by the printer's own.
|
||||
auto* agent = Slic3r::GUI::wxGetApp().getAgent();
|
||||
return set->count(agent ? agent->from_orca_filament_id(filament_id) : filament_id) > 0;
|
||||
}
|
||||
|
||||
wxString Slic3r::get_stage_string(int stage)
|
||||
@@ -5048,10 +5050,13 @@ DevAmsTray MachineObject::parse_vt_tray(json vtray)
|
||||
vt_tray.setting_id = vtray["tray_info_idx"].get<std::string>();
|
||||
//std::string type = vtray["tray_type"].get<std::string>();
|
||||
std::string type = setting_id_to_type(vt_tray.setting_id, vtray["tray_type"].get<std::string>());
|
||||
if (vt_tray.setting_id == "GFS00") {
|
||||
// vt_tray.setting_id is our OF id (translated on the way in); the two support ids below are the printer's own.
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(vt_tray.setting_id) : vt_tray.setting_id;
|
||||
if (printer_filament_id == "GFS00") {
|
||||
vt_tray.m_fila_type = "PLA-S";
|
||||
}
|
||||
else if (vt_tray.setting_id == "GFS01") {
|
||||
else if (printer_filament_id == "GFS01") {
|
||||
vt_tray.m_fila_type = "PA-S";
|
||||
}
|
||||
else {
|
||||
@@ -5592,7 +5597,10 @@ void MachineObject::update_filament_list()
|
||||
|
||||
for (auto it = filament_list.begin(); it != filament_list.end(); it++) {
|
||||
if (m_filament_list.find(it->first) != m_filament_list.end()) {
|
||||
assert(it->first.size() == 8 && it->first[0] == 'P');
|
||||
// User roots may legitimately carry adopted system-shaped ids (GF*/OF*/P-hex
|
||||
// system), so a non-'P' id here is expected, not an invariant violation.
|
||||
if (it->first.size() != 8 || it->first[0] != 'P')
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": user-root filament_id is not user-shaped: " << it->first;
|
||||
|
||||
if (it->second.first != m_filament_list[it->first].first) {
|
||||
BOOST_LOG_TRIVIAL(info) << "old min temp is not equal to new min temp and filament id: " << it->first;
|
||||
@@ -5654,6 +5662,17 @@ void MachineObject::update_printer_preset_name()
|
||||
void MachineObject::check_ams_filament_valid()
|
||||
{
|
||||
PresetBundle * preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle;
|
||||
// A tray id carried by ANY system filament preset is not a dangling user-preset id
|
||||
// (ten shipped P-hex system ids pass the 'P' shape gates below), so the destructive
|
||||
// tray-wipe / temp-rewrite handling must never fire for it.
|
||||
auto is_system_filament_id = [preset_bundle](const std::string &id) {
|
||||
if (!preset_bundle)
|
||||
return false;
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++)
|
||||
if (it->is_system && it->filament_id == id)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
auto printer_model = DevPrinterConfigUtil::get_printer_display_name(this->printer_type);
|
||||
std::map<std::string, std::set<std::string>> need_checked_filament_id;
|
||||
for (auto &ams_pair : m_fila_system->GetAmsList()) {
|
||||
@@ -5675,6 +5694,8 @@ void MachineObject::check_ams_filament_valid()
|
||||
auto &checked_filament = data.checked_filament;
|
||||
for (const auto &[slot_id, curr_tray] : ams->GetTrays()) {
|
||||
|
||||
if (curr_tray->setting_id.size() == 8 && curr_tray->setting_id[0] == 'P' && is_system_filament_id(curr_tray->setting_id))
|
||||
continue;
|
||||
if (curr_tray->setting_id.size() == 8 && curr_tray->setting_id[0] == 'P' && filament_list.find(curr_tray->setting_id) == filament_list.end()) {
|
||||
if (checked_filament.find(curr_tray->setting_id) != checked_filament.end()) {
|
||||
need_checked_filament_id[nozzle_diameter_str].insert(curr_tray->setting_id);
|
||||
@@ -5735,6 +5756,8 @@ void MachineObject::check_ams_filament_valid()
|
||||
auto &data = m_nozzle_filament_data[nozzle_diameter_str];
|
||||
auto &checked_filament = data.checked_filament;
|
||||
auto &filament_list = data.filament_list;
|
||||
if (vt_tray.setting_id.size() == 8 && vt_tray.setting_id[0] == 'P' && is_system_filament_id(vt_tray.setting_id))
|
||||
continue;
|
||||
if (vt_tray.setting_id.size() == 8 && vt_tray.setting_id[0] == 'P' && filament_list.find(vt_tray.setting_id) == filament_list.end()) {
|
||||
if (checked_filament.find(vt_tray.setting_id) != checked_filament.end()) {
|
||||
need_checked_filament_id[nozzle_diameter_str].insert(vt_tray.setting_id);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "GUI_App.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include <algorithm>
|
||||
#include "I18N.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <wx/dcgraph.h>
|
||||
@@ -599,8 +600,10 @@ void ExtrusionCalibration::update_combobox_filaments()
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle && obj) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
std::string printer_type = obj->printer_type;
|
||||
std::set<std::string> printer_preset_list;
|
||||
double nozzle_value = 0.4;
|
||||
m_comboBox_nozzle_dia->GetValue().ToDouble(&nozzle_value);
|
||||
|
||||
std::vector<PresetWithVendorProfile> printer_profiles;
|
||||
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) {
|
||||
// only use system printer preset
|
||||
if (!printer_it->is_system) continue;
|
||||
@@ -610,49 +613,42 @@ void ExtrusionCalibration::update_combobox_filaments()
|
||||
ConfigOptionFloats* printer_nozzle_vals = nullptr;
|
||||
if (printer_nozzle_opt)
|
||||
printer_nozzle_vals = dynamic_cast<ConfigOptionFloats*>(printer_nozzle_opt);
|
||||
double nozzle_value = 0.4;
|
||||
wxString nozzle_value_str = m_comboBox_nozzle_dia->GetValue();
|
||||
try {
|
||||
nozzle_value_str.ToDouble(&nozzle_value);
|
||||
} catch(...) {
|
||||
;
|
||||
}
|
||||
if (!model_id.empty() && model_id.compare(obj->printer_type) == 0
|
||||
&& printer_nozzle_vals
|
||||
&& abs(printer_nozzle_vals->get_at(0) - nozzle_value) < 1e-3) {
|
||||
printer_preset_list.insert(printer_it->name);
|
||||
printer_profiles.push_back(preset_bundle->printers.get_preset_with_vendor_profile(*printer_it));
|
||||
BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: printer_model = " << model_id;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "extrusion_cali: printer_model = " << model_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike the AMS dialogs this one offers every matching preset by full name rather than one
|
||||
// root preset per alias, so it filters the collection itself instead of calling
|
||||
// PresetBundle::get_filament_presets_for_machine().
|
||||
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
|
||||
ConfigOption* printer_opt = filament_it->config.option("compatible_printers");
|
||||
ConfigOptionStrings* printer_strs = dynamic_cast<ConfigOptionStrings*>(printer_opt);
|
||||
for (auto printer_str : printer_strs->values) {
|
||||
if (printer_preset_list.find(printer_str) != printer_preset_list.end()) {
|
||||
user_filaments.push_back(&(*filament_it));
|
||||
const PresetWithVendorProfile filament = preset_bundle->filaments.get_preset_with_vendor_profile(*filament_it);
|
||||
if (std::none_of(printer_profiles.begin(), printer_profiles.end(),
|
||||
[&filament](const PresetWithVendorProfile &printer) { return is_compatible_with_printer(filament, printer); }))
|
||||
continue;
|
||||
|
||||
// set default filament id
|
||||
filament_index++;
|
||||
if (filament_it->is_system
|
||||
&& !ams_filament_id.empty()
|
||||
&& filament_it->filament_id == ams_filament_id
|
||||
) {
|
||||
curr_selection = filament_index;
|
||||
}
|
||||
user_filaments.push_back(&(*filament_it));
|
||||
|
||||
if (filament_it->name == obj->extrusion_cali_filament_name && !obj->extrusion_cali_filament_name.empty())
|
||||
{
|
||||
curr_selection = filament_index;
|
||||
}
|
||||
|
||||
wxString filament_name = wxString::FromUTF8(filament_it->name);
|
||||
filament_items.Add(filament_name);
|
||||
break;
|
||||
}
|
||||
// set default filament id
|
||||
filament_index++;
|
||||
if (filament_it->is_system
|
||||
&& !ams_filament_id.empty()
|
||||
&& filament_it->filament_id == ams_filament_id
|
||||
) {
|
||||
curr_selection = filament_index;
|
||||
}
|
||||
|
||||
if (filament_it->name == obj->extrusion_cali_filament_name && !obj->extrusion_cali_filament_name.empty())
|
||||
{
|
||||
curr_selection = filament_index;
|
||||
}
|
||||
|
||||
filament_items.Add(wxString::FromUTF8(filament_it->name));
|
||||
}
|
||||
m_comboBox_filament->Set(filament_items);
|
||||
m_comboBox_filament->SetSelection(curr_selection);
|
||||
|
||||
@@ -4162,7 +4162,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
// https://github.com/OrcaSlicer/OrcaSlicer/pull/14999#issuecomment-5151344759
|
||||
// We solve this by correcting the state of the event from the actual mouse state querying with `wxGetMouseState()`
|
||||
// so it works like on other platforms.
|
||||
{
|
||||
// Only fill in state the event does not carry, to preserve wx's synthetic right button for Ctrl+left.
|
||||
if (!evt.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
||||
const auto state = wxGetMouseState();
|
||||
evt.SetLeftDown(state.LeftIsDown());
|
||||
evt.SetMiddleDown(state.MiddleIsDown());
|
||||
|
||||
@@ -591,16 +591,11 @@ private:
|
||||
wxColour m_hover_colour;
|
||||
wxBoxSizer* m_top_sizer{nullptr};
|
||||
wxBoxSizer* m_page_sizer{nullptr};
|
||||
wxBoxSizer* m_page_top_sizer{nullptr};
|
||||
wxTextCtrl* m_search_line{ nullptr };
|
||||
ObjectGrid* m_object_grid{nullptr};
|
||||
ObjectGridTable* m_object_grid_table{nullptr};
|
||||
wxStaticText* m_page_text{nullptr};
|
||||
ScalableButton* m_global_reset{nullptr};
|
||||
wxScrolledWindow* m_side_window{nullptr};
|
||||
ObjectTableSettings* m_object_settings{ nullptr };
|
||||
Model* m_model{nullptr};
|
||||
ModelConfig* m_config {nullptr};
|
||||
Plater* m_plater{nullptr};
|
||||
|
||||
int m_cur_row { -1 };
|
||||
@@ -625,8 +620,6 @@ class ObjectTableDialog : public GUI::DPIDialog
|
||||
const int POPUP_HEIGHT = FromDIP(1024);
|
||||
|
||||
//wxPanel* m_panel{ nullptr };
|
||||
wxBoxSizer* m_top_sizer{ nullptr };
|
||||
wxStaticText* m_static_title{ nullptr };
|
||||
//wxTimer* m_refresh_timer;
|
||||
ObjectTablePanel* m_obj_panel{ nullptr };
|
||||
Model* m_model{ nullptr };
|
||||
|
||||
@@ -94,7 +94,6 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
GLModel m_reference_radius;
|
||||
GLModel m_angle_arc;
|
||||
|
||||
Vec3d m_old_center;
|
||||
Vec3d m_cut_normal;
|
||||
|
||||
struct InvalidConnectorsStatistics
|
||||
|
||||
@@ -25,7 +25,6 @@ class HMSNotifyItem : public wxPanel
|
||||
wxStaticBitmap *m_bitmap_notify;
|
||||
wxStaticBitmap *m_bitmap_arrow;
|
||||
wxStaticText * m_hms_content;
|
||||
wxHtmlWindow * m_html;
|
||||
wxPanel * m_staticline;
|
||||
|
||||
wxBitmap m_img_notify_lv1;
|
||||
|
||||
@@ -216,7 +216,6 @@ private:
|
||||
long m_extra_style;
|
||||
float m_label_koef{1.0};
|
||||
|
||||
float m_zero_layer_height = 0.0f;
|
||||
std::vector<double> m_values;
|
||||
TickCodeInfo m_ticks;
|
||||
std::vector<double> m_layers_times;
|
||||
|
||||
@@ -20,7 +20,6 @@ class BindJob : public Job
|
||||
std::string m_sec_link;
|
||||
std::string m_ssdp_version;
|
||||
bool m_job_finished{ false };
|
||||
int m_print_job_completed_id = 0;
|
||||
bool m_improved{false};
|
||||
|
||||
public:
|
||||
|
||||
@@ -27,7 +27,6 @@ class UpgradeNetworkJob : public Job
|
||||
wxWindow * m_event_handle{nullptr};
|
||||
std::function<void()> m_success_fun{nullptr};
|
||||
bool m_job_finished{ false };
|
||||
int m_print_job_completed_id = 0;
|
||||
|
||||
InstallProgressFn pro_fn { nullptr };
|
||||
|
||||
|
||||
@@ -4516,10 +4516,9 @@ std::string MainFrame::get_dir_name(const wxString &full_name) const
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SettingsDialog::SettingsDialog(MainFrame* mainframe)
|
||||
:DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "settings_dialog"),
|
||||
:DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "settings_dialog")
|
||||
//: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize,
|
||||
// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
|
||||
m_main_frame(mainframe)
|
||||
{
|
||||
if (wxGetApp().is_gcode_viewer())
|
||||
return;
|
||||
|
||||
@@ -94,7 +94,6 @@ class SettingsDialog : public DPIDialog//DPIDialog
|
||||
{
|
||||
//wxNotebook* m_tabpanel { nullptr };
|
||||
Notebook* m_tabpanel{ nullptr };
|
||||
MainFrame* m_main_frame { nullptr };
|
||||
wxMenuBar* m_menubar{ nullptr };
|
||||
public:
|
||||
SettingsDialog(MainFrame* mainframe);
|
||||
|
||||
@@ -126,7 +126,6 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
||||
const std::vector<std::string>& physical_types)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Add Mixed Filament"), wxDefaultPosition,
|
||||
wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
, m_edit_mode(false)
|
||||
, m_physical_colors(physical_colors)
|
||||
, m_physical_names(physical_names)
|
||||
, m_physical_types(physical_types)
|
||||
@@ -157,7 +156,6 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
||||
: DPIDialog(parent, wxID_ANY, _L("Edit Mixed Filament"), wxDefaultPosition,
|
||||
wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
, m_result(existing)
|
||||
, m_edit_mode(true)
|
||||
, m_physical_colors(physical_colors)
|
||||
, m_physical_names(physical_names)
|
||||
, m_physical_types(physical_types)
|
||||
|
||||
@@ -115,7 +115,6 @@ private:
|
||||
wxColour comp_colour(size_t i) const;
|
||||
|
||||
MixedFilamentResult m_result;
|
||||
bool m_edit_mode{false};
|
||||
std::vector<std::string> m_physical_colors;
|
||||
std::vector<std::string> m_physical_names;
|
||||
std::vector<std::string> m_physical_types;
|
||||
|
||||
@@ -78,7 +78,6 @@ private:
|
||||
Tabbook* m_tabpanel{ nullptr };
|
||||
wxSizer* m_main_sizer{ nullptr };
|
||||
|
||||
AddMachinePanel* m_status_add_machine_panel;
|
||||
StatusPanel* m_status_info_panel;
|
||||
MediaFilePanel* m_media_file_panel;
|
||||
UpgradePanel* m_upgrade_panel;
|
||||
@@ -86,8 +85,6 @@ private:
|
||||
|
||||
/* side tools */
|
||||
SideTools* m_side_tools{nullptr};
|
||||
wxStaticBitmap* m_bitmap_arrow;
|
||||
wxStaticBitmap* m_bitmap_wifi_signal;
|
||||
SelectMachinePopup m_select_machine;
|
||||
|
||||
/* images */
|
||||
|
||||
@@ -177,7 +177,6 @@ public:
|
||||
// Generic rich message dialog, used intead of wxRichMessageDialog
|
||||
class RichMessageDialog : public MsgDialog
|
||||
{
|
||||
wxCheckBox* m_checkBox{ nullptr };
|
||||
wxString m_checkBoxText;
|
||||
bool m_checkBoxValue{ false };
|
||||
|
||||
@@ -416,7 +415,6 @@ private:
|
||||
wxString m_new_keys;
|
||||
Button * m_update_btn = nullptr;
|
||||
Button * m_later_btn = nullptr;
|
||||
wxStaticText *m_msg_text = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ private:
|
||||
wxBoxSizer* m_main_sizer{nullptr};
|
||||
wxBoxSizer* m_sizer_machine_list{nullptr};
|
||||
wxScrolledWindow* m_machine_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
@@ -99,8 +98,6 @@ private:
|
||||
int m_total_count{ 0 };
|
||||
int m_count_page_item{ 10 };
|
||||
|
||||
bool prev{ false };
|
||||
bool next{ false };
|
||||
Button* btn_last_page{ nullptr };
|
||||
Button* btn_next_page{ nullptr };
|
||||
wxStaticText* st_page_number{ nullptr };
|
||||
|
||||
@@ -81,7 +81,6 @@ private:
|
||||
AppConfig* app_config;
|
||||
Label* m_label{ nullptr };
|
||||
wxScrolledWindow* scroll_macine_list{ nullptr };
|
||||
wxBoxSizer* m_sizer_body{ nullptr };
|
||||
wxBoxSizer* sizer_machine_list{ nullptr };
|
||||
std::map<std::string, DevicePickItem*> m_device_items;
|
||||
int m_selected_count{0};
|
||||
|
||||
@@ -99,7 +99,6 @@ private:
|
||||
wxBoxSizer* page_sizer{ nullptr };
|
||||
wxBoxSizer* m_sizer_task_list{ nullptr };
|
||||
wxScrolledWindow* m_task_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
@@ -113,7 +112,6 @@ private:
|
||||
Button* m_action{ nullptr };
|
||||
|
||||
// ctrl button for all
|
||||
int m_sel_number{0};
|
||||
wxPanel* m_ctrl_btn_panel{ nullptr };
|
||||
wxBoxSizer* m_btn_sizer{ nullptr };
|
||||
Button* btn_stop_all{ nullptr };
|
||||
@@ -160,15 +158,12 @@ private:
|
||||
wxBoxSizer* m_sizer_task_list{ nullptr };
|
||||
wxBoxSizer* m_main_sizer{ nullptr };
|
||||
wxScrolledWindow* m_task_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// Flipping pages
|
||||
int m_current_page{ 0 };
|
||||
int m_total_page{0};
|
||||
int m_total_count{ 0 };
|
||||
int m_count_page_item{ 10 };
|
||||
bool prev{ false };
|
||||
bool next{ false };
|
||||
Button* btn_last_page{ nullptr };
|
||||
Button* btn_next_page{ nullptr };
|
||||
wxStaticText* st_page_number{ nullptr };
|
||||
@@ -191,7 +186,6 @@ private:
|
||||
Button* m_action{ nullptr };
|
||||
|
||||
// ctrl button for all
|
||||
int m_sel_number;
|
||||
wxPanel* m_ctrl_btn_panel{ nullptr };
|
||||
wxBoxSizer* m_btn_sizer{ nullptr };
|
||||
Button* btn_pause_all{ nullptr };
|
||||
|
||||
@@ -86,8 +86,6 @@ ObjColorDialog::ObjColorDialog(wxWindow *parent, Slic3r::ObjDialogInOut &in_out,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE /* | wxRESIZE_BORDER*/)
|
||||
, m_filament_ids(in_out.filament_ids)
|
||||
, m_first_extruder_id(in_out.first_extruder_id)
|
||||
{
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
@@ -94,7 +94,6 @@ private:
|
||||
std::vector<int> m_cluster_map_filaments;//show middle
|
||||
int m_max_filament_index = 0;
|
||||
std::vector<wxColour> m_cluster_colours;//from_algo and show left
|
||||
bool m_can_add_filament{true};
|
||||
bool m_deal_thumbnail_flag{false};
|
||||
std::vector<wxColour> m_new_add_colors;
|
||||
std::vector<wxColour> m_new_add_final_colors;
|
||||
@@ -123,8 +122,6 @@ private:
|
||||
wxBoxSizer * m_main_sizer = nullptr;
|
||||
wxBoxSizer * m_buttons_sizer = nullptr;
|
||||
std::unordered_map<int, Button *> m_button_list;
|
||||
std::vector<unsigned char>& m_filament_ids;
|
||||
unsigned char & m_first_extruder_id;
|
||||
};
|
||||
|
||||
#endif // _WIPE_TOWER_DIALOG_H_
|
||||
@@ -8820,6 +8820,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
if (wipe_tower_y_opt)
|
||||
file_wipe_tower_y = *wipe_tower_y_opt;
|
||||
|
||||
if (auto* agent = wxGetApp().getAgent()) {
|
||||
if (auto* ids = config.opt<ConfigOptionStrings>("filament_ids"))
|
||||
for (std::string& id : ids->values)
|
||||
id = agent->to_orca_filament_id(id);
|
||||
}
|
||||
preset_bundle->load_config_model(filename.string(), std::move(config), file_version);
|
||||
|
||||
ConfigOption* bed_type_opt = preset_bundle->project_config.option("curr_bed_type");
|
||||
@@ -18667,6 +18672,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
nozzle_diameter_str = nozzle_diameter_option->serialize();
|
||||
|
||||
std::string printer_model_id = preset_bundle.printers.get_edited_preset().get_printer_type(&preset_bundle);
|
||||
// The printer reads slice_info.config and knows only its own catalog ids.
|
||||
auto* id_agent = preset_bundle.is_bbl_vendor() ? wxGetApp().getAgent() : nullptr;
|
||||
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
PlateData *plate_data = plate_data_list[i];
|
||||
@@ -18676,6 +18683,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
std::string display_filament_type;
|
||||
it->type = cfg.get_filament_type(display_filament_type, it->id);
|
||||
it->filament_id = filament_id_opt ? filament_id_opt->get_at(it->id) : "";
|
||||
if (id_agent)
|
||||
it->filament_id = id_agent->from_orca_filament_id(it->filament_id);
|
||||
it->color = filament_color ? filament_color->get_at(it->id) : "#FFFFFF";
|
||||
// save filament info used in curr plate
|
||||
int index = p->partplate_list.get_curr_plate_index();
|
||||
|
||||
@@ -16,7 +16,6 @@ PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
const std::vector<Slic3r::PluginDescriptor>& plugins)
|
||||
: wxDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
, m_plugins(plugins)
|
||||
, m_capability_mode(false)
|
||||
{
|
||||
build_ui(plugin_type_label);
|
||||
CentreOnParent();
|
||||
@@ -27,7 +26,6 @@ PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
std::vector<CapabilityEntry> capabilities)
|
||||
: wxDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
, m_capabilities(std::move(capabilities))
|
||||
, m_capability_mode(true)
|
||||
{
|
||||
build_capability_ui(plugin_type_label);
|
||||
CentreOnParent();
|
||||
|
||||
@@ -50,7 +50,6 @@ private:
|
||||
wxStaticText* m_description { nullptr };
|
||||
std::vector<Slic3r::PluginDescriptor> m_plugins;
|
||||
std::vector<CapabilityEntry> m_capabilities;
|
||||
bool m_capability_mode { false };
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -347,7 +347,7 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(wxString title, wxS
|
||||
wxLanguage supported_languages[]{
|
||||
wxLANGUAGE_ENGLISH,
|
||||
wxLANGUAGE_CHINESE_SIMPLIFIED,
|
||||
wxLANGUAGE_CHINESE,
|
||||
wxLANGUAGE_CHINESE_TRADITIONAL,
|
||||
wxLANGUAGE_GERMAN,
|
||||
wxLANGUAGE_CZECH,
|
||||
wxLANGUAGE_FRENCH,
|
||||
@@ -407,7 +407,7 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(wxString title, wxS
|
||||
if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_CHINESE_SIMPLIFIED)) {
|
||||
language_name = wxString::FromUTF8("\xe4\xb8\xad\xe6\x96\x87\x28\xe7\xae\x80\xe4\xbd\x93\x29");
|
||||
}
|
||||
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_CHINESE)) {
|
||||
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_CHINESE_TRADITIONAL)) {
|
||||
language_name = wxString::FromUTF8("\xe4\xb8\xad\xe6\x96\x87\x28\xe7\xb9\x81\xe9\xab\x94\x29");
|
||||
}
|
||||
else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_SPANISH)) {
|
||||
|
||||
@@ -873,10 +873,15 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset
|
||||
auto fila_type = Preset::remove_suffix_modified(GetValue().ToUTF8().data());
|
||||
bool is_official = boost::algorithm::starts_with(fila_type, "Bambu");
|
||||
if (is_official) {
|
||||
// Get filament_id from filament_presets
|
||||
// Get filament_id from filament_presets. FilamentPickerDialog looks up
|
||||
// filaments_color_codes.json, which is downloaded from Bambu and keyed by the
|
||||
// printer's own ids, so translate our OF id (the "GFA00" fallback is already one).
|
||||
const std::string& preset_name = m_preset_bundle->filament_presets[m_filament_idx];
|
||||
const Preset* selected_preset = m_collection->find_preset(preset_name);
|
||||
wxString fila_id = selected_preset ? wxString::FromUTF8(selected_preset->filament_id) : "GFA00";
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
wxString fila_id = "GFA00";
|
||||
if (selected_preset)
|
||||
fila_id = wxString::FromUTF8(agent ? agent->from_orca_filament_id(selected_preset->filament_id) : selected_preset->filament_id);
|
||||
FilamentColor fila_color = get_cur_color_info();
|
||||
|
||||
// Show filament picker dialog
|
||||
|
||||
@@ -114,7 +114,7 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
|
||||
if (parent->m_mode == comDevelop) {
|
||||
// A new user copy of a system preset inherits from the selected system preset.
|
||||
const std::string parent_name = sel_preset.is_system ? sel_preset.name : sel_preset.inherits();
|
||||
const bool can_detach = !parent_name.empty();
|
||||
const bool has_parent = !parent_name.empty();
|
||||
|
||||
wxBoxSizer *detach_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
@@ -123,8 +123,9 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
|
||||
auto detach_checkbox = new ::CheckBox(parent);
|
||||
detach_checkbox->SetToolTip(detach_tooltip);
|
||||
|
||||
auto detach_label = new wxStaticText(parent, wxID_ANY, _L("Detach from parent"));
|
||||
auto detach_label = new wxStaticText(parent, wxID_ANY, has_parent ? _L("Detach from parent") : _L("Save without parent"));
|
||||
detach_label->SetFont(::Label::Body_14);
|
||||
detach_label->SetForegroundColour(wxColour("#363636"));
|
||||
detach_label->SetToolTip(detach_tooltip);
|
||||
|
||||
detach_sizer->Add(detach_checkbox, 0, wxALIGN_LEFT | wxLEFT, BORDER_W);
|
||||
@@ -132,39 +133,31 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
|
||||
sizer->Add(detach_sizer, 0, wxEXPAND | wxTOP, BORDER_W);
|
||||
sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
const wxString parent_text = can_detach ? from_u8(parent_name) : _L("Unique preset");
|
||||
const wxString parent_text = has_parent ? from_u8(parent_name) : _L("Unique preset");
|
||||
auto parent_label = new wxStaticText(parent, wxID_ANY, parent_text);
|
||||
parent_label->SetFont(::Label::Body_12);
|
||||
parent_label->SetForegroundColour(wxColour("#6B6B6B"));
|
||||
parent_label->SetToolTip(can_detach ? _L("Parent preset") : _L("This preset does not inherit from another preset."));
|
||||
parent_label->SetToolTip(has_parent ? _L("Parent preset") : _L("This preset does not inherit from another preset."));
|
||||
sizer->Add(parent_label, 0, wxEXPAND | wxLEFT, BORDER_W + FromDIP(24));
|
||||
|
||||
sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
if (!can_detach) {
|
||||
detach_checkbox->Disable();
|
||||
detach_label->SetForegroundColour(wxColour("#6B6B6B"));
|
||||
}
|
||||
else {
|
||||
// Set initial state (unchecked by default)
|
||||
detach_checkbox->SetValue(m_detach);
|
||||
// Bind the checkbox event to update the detach state for this item
|
||||
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent& event) {
|
||||
m_detach = detach_checkbox->GetValue();
|
||||
event.Skip(); // Let CheckBox update its bitmap for the new state.
|
||||
});
|
||||
// Set initial state (unchecked by default)
|
||||
detach_checkbox->SetValue(m_detach);
|
||||
// Bind the checkbox event to update the detach state for this item
|
||||
detach_checkbox->Bind(wxEVT_TOGGLEBUTTON, [this, detach_checkbox](wxCommandEvent& event) {
|
||||
m_detach = detach_checkbox->GetValue();
|
||||
event.Skip(); // Let CheckBox update its bitmap for the new state.
|
||||
});
|
||||
|
||||
detach_label->SetForegroundColour(wxColour("#363636"));
|
||||
|
||||
auto on_toggle = [detach_checkbox]() {
|
||||
detach_checkbox->SetValue(!detach_checkbox->GetValue());
|
||||
wxCommandEvent ev(wxEVT_TOGGLEBUTTON, detach_checkbox->GetId());
|
||||
ev.SetEventObject(detach_checkbox);
|
||||
detach_checkbox->GetEventHandler()->ProcessEvent(ev);
|
||||
};
|
||||
detach_label->Bind(wxEVT_LEFT_DOWN, [on_toggle](wxMouseEvent& e) {if(!e.LeftDClick()) on_toggle();});
|
||||
detach_label->Bind(wxEVT_LEFT_DCLICK, [on_toggle](wxMouseEvent& e) {on_toggle();});
|
||||
}
|
||||
auto on_toggle = [detach_checkbox]() {
|
||||
detach_checkbox->SetValue(!detach_checkbox->GetValue());
|
||||
wxCommandEvent ev(wxEVT_TOGGLEBUTTON, detach_checkbox->GetId());
|
||||
ev.SetEventObject(detach_checkbox);
|
||||
detach_checkbox->GetEventHandler()->ProcessEvent(ev);
|
||||
};
|
||||
detach_label->Bind(wxEVT_LEFT_DOWN, [on_toggle](wxMouseEvent& e) {if(!e.LeftDClick()) on_toggle();});
|
||||
detach_label->Bind(wxEVT_LEFT_DCLICK, [on_toggle](wxMouseEvent& e) {on_toggle();});
|
||||
}
|
||||
|
||||
m_radio_group->Bind(wxEVT_COMMAND_RADIOBOX_SELECTED, [this](wxCommandEvent &e) {
|
||||
|
||||
@@ -3845,8 +3845,12 @@ int SelectMachineDialog::update_print_required_data(Slic3r::DynamicPrintConfig c
|
||||
m_required_data_config = config;
|
||||
m_required_data_model = model;
|
||||
//m_required_data_plate_data_list = plate_data_list;
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
for (auto i = 0; i < plate_data_list.size(); i++) {
|
||||
if (!plate_data_list[i]->gcode_file.empty()) {
|
||||
if (agent)
|
||||
for (auto& info : plate_data_list[i]->slice_filaments_info)
|
||||
info.filament_id = agent->to_orca_filament_id(info.filament_id);
|
||||
m_required_data_plate_data_list.push_back(plate_data_list[i]);
|
||||
}
|
||||
}
|
||||
@@ -5051,8 +5055,11 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
|
||||
const auto& warning_tpu_filaments =
|
||||
DevPrinterConfigUtil::get_value_from_config<std::vector<std::string>>(obj_->printer_type, "auto_on_cali_warning_tpu_filaments");
|
||||
if (!warning_tpu_filaments.empty()) {
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
for (const auto& fila : m_ams_mapping_result) {
|
||||
if (std::find(warning_tpu_filaments.begin(), warning_tpu_filaments.end(), fila.filament_id) != warning_tpu_filaments.end()) {
|
||||
// fila.filament_id is our OF id; the printer config list holds the printer's own.
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(fila.filament_id) : fila.filament_id;
|
||||
if (std::find(warning_tpu_filaments.begin(), warning_tpu_filaments.end(), printer_filament_id) != warning_tpu_filaments.end()) {
|
||||
show_status(PrintDialogStatus::PrintStatusTPUUnsuggestCali,
|
||||
{ _L("If 'Dynamic Flow Calibration' is set to Auto/On, the system will use the manual calibration value or the default value and skip the flow calibration process. You can perform a manual flow calibration for TPU filament on the 'Calibration' page.") });
|
||||
break;
|
||||
@@ -5208,9 +5215,12 @@ bool SelectMachineDialog::can_support_pa_auto_cali()
|
||||
|
||||
std::vector<std::string> unsupport_auto_cali_filaments = DevPrinterConfigUtil::get_unsupport_auto_cali_filaments(obj->printer_type);
|
||||
if (!unsupport_auto_cali_filaments.empty()) {
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
auto iter = std::find_if(m_filaments.begin(), m_filaments.end(),
|
||||
[&unsupport_auto_cali_filaments](const FilamentInfo &item) {
|
||||
auto iter = std::find(unsupport_auto_cali_filaments.begin(), unsupport_auto_cali_filaments.end(), item.filament_id);
|
||||
[&unsupport_auto_cali_filaments, agent](const FilamentInfo &item) {
|
||||
// item.filament_id is our OF id; the printer config list holds the printer's own.
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(item.filament_id) : item.filament_id;
|
||||
auto iter = std::find(unsupport_auto_cali_filaments.begin(), unsupport_auto_cali_filaments.end(), printer_filament_id);
|
||||
return iter != unsupport_auto_cali_filaments.end();
|
||||
});
|
||||
|
||||
|
||||
@@ -662,7 +662,6 @@ private:
|
||||
ScalableButton* m_button_question { nullptr };
|
||||
|
||||
wxStaticBitmap* m_bed_image{ nullptr };
|
||||
Label* m_text_bed_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -181,13 +181,11 @@ private:
|
||||
PinCodePanel* m_panel_direct_connection{nullptr};
|
||||
wxWindow* m_placeholder_panel{nullptr};
|
||||
HyperLink* m_hyperlink{nullptr}; // ORCA
|
||||
wxBoxSizer * m_sizer_body{nullptr};
|
||||
wxBoxSizer * m_sizer_my_devices{nullptr};
|
||||
wxBoxSizer * m_sizer_other_devices{nullptr};
|
||||
wxBoxSizer * m_sizer_search_bar{nullptr};
|
||||
wxSearchCtrl* m_search_bar{nullptr};
|
||||
wxScrolledWindow * m_scrolledWindow{nullptr};
|
||||
wxWindow * m_panel_body{nullptr};
|
||||
wxTimer * m_refresh_timer{nullptr};
|
||||
std::vector<MachinePanel*> m_user_list_machine_panel;
|
||||
std::vector<MachinePanel*> m_other_list_machine_panel;
|
||||
|
||||
@@ -55,7 +55,6 @@ private:
|
||||
void init_timer();
|
||||
|
||||
int m_print_plate_idx;
|
||||
int m_current_filament_id;
|
||||
int m_print_error_code = 0;
|
||||
int timeout_count = 0;
|
||||
int m_connect_try_times = 0;
|
||||
@@ -77,7 +76,6 @@ private:
|
||||
TextInput* m_rename_input{ nullptr };
|
||||
wxSimplebook* m_rename_switch_panel{ nullptr };
|
||||
Plater* m_plater{ nullptr };
|
||||
wxStaticBitmap* m_staticbitmap{ nullptr };
|
||||
ThumbnailPanel* m_thumbnailPanel{ nullptr };
|
||||
ComboBox* m_comboBox_printer{ nullptr };
|
||||
Button* m_rename_button{ nullptr };
|
||||
@@ -97,8 +95,6 @@ private:
|
||||
wxPanel * m_connecting_panel{nullptr};
|
||||
wxSimplebook* m_simplebook{ nullptr };
|
||||
wxStaticText* m_statictext_finish{ nullptr };
|
||||
wxStaticText* m_stext_sending{ nullptr };
|
||||
wxStaticText* m_staticText_bed_title{ nullptr };
|
||||
wxStaticText* m_statictext_printer_msg{ nullptr };
|
||||
wxStaticText * m_connecting_printer_msg{nullptr};
|
||||
wxStaticText* m_stext_printer_title{ nullptr };
|
||||
@@ -115,7 +111,6 @@ private:
|
||||
wxBoxSizer* sizer_thumbnail;
|
||||
wxBoxSizer* m_sizer_scrollable_region;
|
||||
wxBoxSizer* m_sizer_main;
|
||||
wxStaticText* m_file_name;
|
||||
PrintDialogStatus m_print_status{ PrintStatusInit };
|
||||
AnimaIcon * m_animaicon{nullptr};
|
||||
|
||||
@@ -134,8 +129,6 @@ private:
|
||||
std::vector<RadioBox *> m_storage_radioBox;
|
||||
std::string m_selected_storage;
|
||||
bool m_if_has_sdcard;
|
||||
bool m_waiting_support{ false };
|
||||
bool m_waiting_enable{ false };
|
||||
std::vector<std::string> m_ability_list;
|
||||
|
||||
public:
|
||||
|
||||
@@ -28,7 +28,6 @@ public:
|
||||
|
||||
private:
|
||||
wxScrolledWindow *m_panel;
|
||||
BBLSliceInfo *m_info { nullptr };
|
||||
|
||||
void OnMouse(wxMouseEvent &event);
|
||||
void OnSize(wxSizeEvent &event);
|
||||
|
||||
@@ -631,7 +631,6 @@ void SyncAmsInfoDialog::updata_ui_when_priner_not_same() {
|
||||
SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Synchronize AMS Filament Information"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
, m_input_info(info)
|
||||
, m_export_3mf_cancel(false)
|
||||
, m_mapping_popup(AmsMapingPopup(this,true))
|
||||
, m_mapping_tip_popup(AmsMapingTipPopup(this))
|
||||
, m_mapping_tutorial_popup(AmsTutorialPopup(this))
|
||||
|
||||
@@ -21,15 +21,11 @@ class SyncAmsInfoDialog : public DPIDialog
|
||||
bool m_only_exist_ext_spool_flag{false};
|
||||
int m_current_filament_id{0};
|
||||
int m_print_plate_idx{0};
|
||||
int m_print_plate_total{0};
|
||||
int m_timeout_count{0};
|
||||
int m_print_error_code{0};
|
||||
bool m_is_in_sending_mode{false};
|
||||
bool m_ams_mapping_res{false};
|
||||
bool m_ams_mapping_valid{false};
|
||||
bool m_export_3mf_cancel{false};
|
||||
bool m_is_canceled{false};
|
||||
bool m_is_rename_mode{false};
|
||||
bool m_check_flag{false};
|
||||
PrintPageMode m_print_page_mode{PrintPageMode::PrintPageModePrepare};
|
||||
std::string m_print_error_msg;
|
||||
|
||||
@@ -630,7 +630,6 @@ private:
|
||||
std::vector<PageShp> m_pages_fff;
|
||||
std::vector<PageShp> m_pages_sla;
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
public:
|
||||
ScalableButton* m_reset_to_filament_color = nullptr;
|
||||
|
||||
|
||||
@@ -519,7 +519,6 @@ public:
|
||||
, m_entries(entries)
|
||||
, m_colors_rgba(colors_rgba)
|
||||
, m_names(names)
|
||||
, m_existing_count(existing_count)
|
||||
, m_dialog_anchor(dialog_anchor)
|
||||
, m_on_select(std::move(on_select))
|
||||
, m_on_add_filament(std::move(on_add_filament))
|
||||
@@ -877,7 +876,6 @@ private:
|
||||
std::vector<TextureFilamentEntry> m_entries;
|
||||
std::vector<std::array<float, 4>> m_colors_rgba;
|
||||
std::vector<std::string> m_names;
|
||||
size_t m_existing_count = 0;
|
||||
wxWindow* m_dialog_anchor = nullptr;
|
||||
std::function<void(int)> m_on_select;
|
||||
std::function<void(wxColour)> m_on_add_filament;
|
||||
|
||||
@@ -33,7 +33,6 @@ public:
|
||||
|
||||
void on_hyperlink(wxHyperlinkEvent& evt);
|
||||
private:
|
||||
wxCheckBox *cbox;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -108,13 +108,16 @@ public:
|
||||
private:
|
||||
|
||||
wxWebView* m_browser;
|
||||
wxButton * m_button_stop;
|
||||
wxTextCtrl *m_url;
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
// Created only by the internal-build toolbar in the constructor.
|
||||
wxBoxSizer *bSizer_toolbar;
|
||||
wxButton * m_button_back;
|
||||
wxButton * m_button_forward;
|
||||
wxButton * m_button_stop;
|
||||
wxButton * m_button_reload;
|
||||
wxTextCtrl *m_url;
|
||||
wxButton * m_button_tools;
|
||||
#endif //BBL_RELEASE_TO_PUBLIC
|
||||
|
||||
wxMenu* m_tools_menu;
|
||||
wxMenuItem* m_tools_handle_navigation;
|
||||
@@ -143,7 +146,6 @@ private:
|
||||
wxMenuItem* m_dev_tools;
|
||||
|
||||
wxInfoBar *m_info;
|
||||
wxStaticText* m_info_text;
|
||||
|
||||
long m_zoomFactor;
|
||||
|
||||
|
||||
@@ -641,17 +641,11 @@ private:
|
||||
AMSRoadShowMode m_road_mode = {AMSRoadShowMode::AMS_ROAD_MODE_FOUR};
|
||||
AMSPassRoadSTEP m_load_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
||||
|
||||
bool m_selected = {false};
|
||||
int m_passroad_width = {6};
|
||||
double m_radius = {4};
|
||||
wxColour m_road_def_color;
|
||||
wxColour m_road_color;
|
||||
|
||||
std::vector<ScalableBitmap> ams_humidity_img;
|
||||
|
||||
int m_humidity = {0};
|
||||
bool m_show_humidity = {false};
|
||||
bool m_vams_loading{false};
|
||||
AMSModel m_ams_model;
|
||||
};
|
||||
|
||||
@@ -690,14 +684,10 @@ private:
|
||||
|
||||
int m_left_road_length = {-1};
|
||||
int m_right_road_length = {-1};
|
||||
int m_passroad_width = {6};
|
||||
double m_radius = {4};
|
||||
AMSPassRoadSTEP m_pass_road_left_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
||||
AMSPassRoadSTEP m_pass_road_right_step = {AMSPassRoadSTEP::AMS_ROAD_STEP_NONE};
|
||||
|
||||
std::map<int, wxColour> m_road_color;
|
||||
bool m_vams_loading{false};
|
||||
AMSModel m_ams_model;
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
|
||||
@@ -212,7 +212,6 @@ private:
|
||||
wxGridSizer* m_sizer_fanControl { nullptr };
|
||||
|
||||
wxBoxSizer *m_mode_sizer{ nullptr };
|
||||
wxBoxSizer *m_bottom_sizer{ nullptr };
|
||||
|
||||
// mode switch buttons
|
||||
std::unordered_map<int, SendModeSwitchButton*> m_mode_switch_btns; //<mode_id, SendModeSwitchButton>
|
||||
|
||||
@@ -89,8 +89,6 @@ private:
|
||||
|
||||
bool m_right_on{ true };
|
||||
wxStaticBitmap* badget;
|
||||
Label* left;
|
||||
Label* right;
|
||||
Label* left_diameter_desp;
|
||||
Label* right_diameter_desp;
|
||||
Label* left_flow_desp;
|
||||
|
||||
@@ -1,11 +1,121 @@
|
||||
#include "BBLPrinterAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
#include "NetworkAgentFactory.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
// Bambu's own catalog ids for every filament this app ships, Bambu's own included, since Orca
|
||||
// content-addresses those too. Keyed both ways so each of the four translation entry points
|
||||
// below is a single lookup. Loaded once per process, on first use. A missing or malformed file
|
||||
// logs once and leaves both maps empty, so every translation degrades to identity. Same shape
|
||||
// as DevFilaBlacklist::load_filaments_blacklist_config.
|
||||
struct BambuFilamentIdMap { std::unordered_map<std::string, std::string> to_bambu, to_orca; };
|
||||
|
||||
const BambuFilamentIdMap& bambu_filament_id_map()
|
||||
{
|
||||
static const BambuFilamentIdMap map = [] {
|
||||
BambuFilamentIdMap m;
|
||||
const std::string path = resources_dir() + "/printers/bambu_filament_ids.json";
|
||||
try {
|
||||
boost::nowide::ifstream file(path);
|
||||
if (!file.is_open()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bambu filament id map not found, ids pass through untranslated: " << path;
|
||||
return m;
|
||||
}
|
||||
json doc;
|
||||
file >> doc;
|
||||
for (const auto& [orca_filament_id, row] : doc.at("filaments").items()) {
|
||||
const std::string bambu_id = row.at("bambu_id").get<std::string>();
|
||||
m.to_bambu.emplace(orca_filament_id, bambu_id);
|
||||
m.to_orca.emplace(bambu_id, orca_filament_id);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Bambu filament id map unreadable, ids pass through untranslated: " << e.what();
|
||||
m = {};
|
||||
}
|
||||
return m;
|
||||
}();
|
||||
return map;
|
||||
}
|
||||
|
||||
// Rewrites every string under "tray_info_idx", "filament_id" or "filamentId", at any depth, in place.
|
||||
void rewrite_filament_ids(json& j, const std::unordered_map<std::string, std::string>& map)
|
||||
{
|
||||
if (j.is_object()) {
|
||||
for (auto& [key, value] : j.items()) {
|
||||
if (value.is_string() && (key == "tray_info_idx" || key == "filament_id" || key == "filamentId")) {
|
||||
auto it = map.find(value.get_ref<const std::string&>());
|
||||
if (it != map.end())
|
||||
value = it->second;
|
||||
} else
|
||||
rewrite_filament_ids(value, map);
|
||||
}
|
||||
} else if (j.is_array())
|
||||
for (auto& element : j)
|
||||
rewrite_filament_ids(element, map);
|
||||
}
|
||||
|
||||
// Text that does not parse as JSON, or that mentions none of the id keys, comes back byte-identical.
|
||||
std::string rewrite_filament_ids(std::string text, const std::unordered_map<std::string, std::string>& map)
|
||||
{
|
||||
if (map.empty() || (text.find("tray_info_idx") == std::string::npos && text.find("filament_id") == std::string::npos &&
|
||||
text.find("filamentId") == std::string::npos))
|
||||
return text; // nothing to map, skip the parse (moved, not copied)
|
||||
try {
|
||||
json j = json::parse(text);
|
||||
rewrite_filament_ids(j, map);
|
||||
return j.dump();
|
||||
} catch (const std::exception&) {
|
||||
return text; // not JSON: forward as received
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps an inbound message callback so every Bambu id it delivers arrives already translated.
|
||||
// A null fn is a deregistration (see GUI_App.cpp's shutdown phase 1 and NetworkAgent::apply_printer_callbacks
|
||||
// clearing callbacks with {}), and must stay null rather than become a live wrapper around an empty target.
|
||||
OnMessageFn to_orca_messages(OnMessageFn fn)
|
||||
{
|
||||
if (!fn)
|
||||
return fn;
|
||||
return [fn = std::move(fn)](std::string dev_id, std::string msg) { fn(std::move(dev_id), BBLPrinterAgent::to_orca_payload(std::move(msg))); };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string BBLPrinterAgent::to_orca_filament_id(const std::string& printer_filament_id) const
|
||||
{
|
||||
const auto& map = bambu_filament_id_map().to_orca;
|
||||
auto it = map.find(printer_filament_id);
|
||||
return it != map.end() ? it->second : printer_filament_id;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::from_orca_filament_id(const std::string& orca_filament_id) const
|
||||
{
|
||||
const auto& map = bambu_filament_id_map().to_bambu;
|
||||
auto it = map.find(orca_filament_id);
|
||||
return it != map.end() ? it->second : orca_filament_id;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::to_orca_payload(std::string json_text)
|
||||
{
|
||||
return rewrite_filament_ids(std::move(json_text), bambu_filament_id_map().to_orca);
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::from_orca_payload(std::string json_text)
|
||||
{
|
||||
return rewrite_filament_ids(std::move(json_text), bambu_filament_id_map().to_bambu);
|
||||
}
|
||||
|
||||
BBLPrinterAgent::BBLPrinterAgent() = default;
|
||||
|
||||
BBLPrinterAgent::~BBLPrinterAgent() = default;
|
||||
@@ -22,6 +132,7 @@ void BBLPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
|
||||
|
||||
int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
json_str = from_orca_payload(std::move(json_str));
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message();
|
||||
@@ -67,6 +178,7 @@ int BBLPrinterAgent::disconnect_printer()
|
||||
|
||||
int BBLPrinterAgent::send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
json_str = from_orca_payload(std::move(json_str));
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message_to_printer();
|
||||
@@ -321,6 +433,7 @@ int dispatch_start(CurrentFn func, PrintParams& params, const CallbackFns&... ca
|
||||
auto agent = plugin.get_agent();
|
||||
if (!func || !agent)
|
||||
return -1;
|
||||
params.ams_mapping_info = BBLPrinterAgent::from_orca_payload(std::move(params.ams_mapping_info));
|
||||
switch (plugin.network_abi()) {
|
||||
case NetworkAbi::Legacy:
|
||||
return reinterpret_cast<LegacyFn>(func)(agent, BBLNetworkPlugin::as_legacy(params), callbacks...);
|
||||
@@ -408,7 +521,7 @@ int BBLPrinterAgent::set_on_message_fn(OnMessageFn fn)
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
return func(agent, to_orca_messages(std::move(fn)));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -441,7 +554,7 @@ int BBLPrinterAgent::set_on_local_message_fn(OnMessageFn fn)
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_local_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
return func(agent, to_orca_messages(std::move(fn)));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,20 @@ public:
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
FilamentSyncMode get_filament_sync_mode() const override;
|
||||
|
||||
// Bambu's own catalog ids. Orca content-addresses every system filament, Bambu's included;
|
||||
// the printer, the AMS and Bambu's cloud know only Bambu's ids, so this agent translates at
|
||||
// the boundary through resources/printers/bambu_filament_ids.json (generated by
|
||||
// scripts/update_bambu_filament_ids.py). An id without a map row is returned as it is.
|
||||
std::string to_orca_filament_id(const std::string& printer_filament_id) const override;
|
||||
std::string from_orca_filament_id(const std::string& orca_filament_id) const override;
|
||||
|
||||
// Rewrite every string under "tray_info_idx", "filament_id" or "filamentId", at any depth,
|
||||
// in a JSON document (an MQTT payload or PrintParams::ams_mapping_info). Text that does not
|
||||
// parse, or contains none of the keys, is returned unchanged.
|
||||
// Taken by value: most outbound traffic carries no filament id and is moved straight back out.
|
||||
static std::string to_orca_payload(std::string json_text);
|
||||
static std::string from_orca_payload(std::string json_text);
|
||||
|
||||
private:
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
};
|
||||
|
||||
@@ -62,22 +62,29 @@ std::vector<std::string> not_support_auto_pa_cali_filaments = {
|
||||
|
||||
void get_default_k_n_value(const std::string &filament_id, float &k, float &n)
|
||||
{
|
||||
if (filament_id.compare("GFU01") == 0) {
|
||||
// filament_id is our OF id; the literals below are the printer's own. An id the agent has
|
||||
// no mapping for (e.g. a caller still on the old id) passes through unchanged.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(filament_id) : filament_id;
|
||||
if (printer_filament_id.compare("GFU01") == 0) {
|
||||
/* TPU 95A */
|
||||
k = 0.25;
|
||||
n = 1.0;
|
||||
} else if (filament_id.compare("GFU03") == 0) {
|
||||
} else if (printer_filament_id.compare("GFU03") == 0) {
|
||||
/* TPU 90A */
|
||||
k = 0.35;
|
||||
n = 1.0;
|
||||
} else if (filament_id.compare("GFU04") == 0) {
|
||||
} else if (printer_filament_id.compare("GFU04") == 0) {
|
||||
/* TPU 85A */
|
||||
k = 0.65;
|
||||
n = 1.0;
|
||||
} else if (filament_id.compare("GFG00") == 0 || filament_id.compare("GFG01") == 0 || filament_id.compare("GFG60") == 0 || filament_id.compare("GFL06") == 0 ||
|
||||
filament_id.compare("GFL55") == 0 || filament_id.compare("GFG99") == 0 || filament_id.compare("GFG98") == 0 || filament_id.compare("GFG97") == 0 ||
|
||||
filament_id.compare("GFG50") == 0 || filament_id.compare("GFU02") == 0 || filament_id.compare("GFU98") == 0 || filament_id.compare("GFS00") == 0 ||
|
||||
filament_id.compare("GFS02") == 0) {
|
||||
} else if (printer_filament_id.compare("GFG00") == 0 || printer_filament_id.compare("GFG01") == 0 ||
|
||||
printer_filament_id.compare("GFG60") == 0 || printer_filament_id.compare("GFL06") == 0 ||
|
||||
printer_filament_id.compare("GFL55") == 0 || printer_filament_id.compare("GFG99") == 0 ||
|
||||
printer_filament_id.compare("GFG98") == 0 || printer_filament_id.compare("GFG97") == 0 ||
|
||||
printer_filament_id.compare("GFG50") == 0 || printer_filament_id.compare("GFU02") == 0 ||
|
||||
printer_filament_id.compare("GFU98") == 0 || printer_filament_id.compare("GFS00") == 0 ||
|
||||
printer_filament_id.compare("GFS02") == 0) {
|
||||
/* 0.04 filaments */
|
||||
k = 0.04;
|
||||
n = 1.0;
|
||||
@@ -1393,7 +1400,10 @@ void CalibUtils::calib_retraction(const CalibInfo &calib_info, wxString &error_m
|
||||
|
||||
bool CalibUtils::is_support_auto_pa_cali(std::string filament_id)
|
||||
{
|
||||
auto iter = std::find(not_support_auto_pa_cali_filaments.begin(), not_support_auto_pa_cali_filaments.end(), filament_id);
|
||||
// filament_id is our OF id; not_support_auto_pa_cali_filaments holds the printer's own ids.
|
||||
auto* agent = wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(filament_id) : filament_id;
|
||||
auto iter = std::find(not_support_auto_pa_cali_filaments.begin(), not_support_auto_pa_cali_filaments.end(), printer_filament_id);
|
||||
if (iter != not_support_auto_pa_cali_filaments.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -290,6 +290,16 @@ public:
|
||||
* Populates the MachineObject's DevFilaSystem with fetched filament data.
|
||||
*/
|
||||
virtual bool fetch_filament_info(std::string dev_id) { return false; }
|
||||
|
||||
/**
|
||||
* Translate one filament id across the printer boundary.
|
||||
*
|
||||
* Orca content-addresses every system filament; a printer, its AMS and its vendor cloud
|
||||
* know only that vendor's own catalog ids. An agent whose printers already speak Orca's
|
||||
* ids leaves them alone, and so does an id with no mapping.
|
||||
*/
|
||||
virtual std::string to_orca_filament_id(const std::string& printer_filament_id) const { return printer_filament_id; }
|
||||
virtual std::string from_orca_filament_id(const std::string& orca_filament_id) const { return orca_filament_id; }
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
@@ -619,51 +620,70 @@ std::string MoonrakerPrinterAgent::map_filament_type_to_generic_id(const std::st
|
||||
{
|
||||
const std::string upper = trim_and_upper(filament_type);
|
||||
|
||||
// Map to OrcaFilamentLibrary preset IDs (compatible with all printers)
|
||||
// Source: resources/profiles/OrcaFilamentLibrary/filament/
|
||||
// Normalize reported material names (trimmed, uppercased) to an OrcaFilamentLibrary
|
||||
// generic family. The family's filament_id is resolved from the loaded system presets
|
||||
// below rather than hardcoded, so profile id re-mints never require touching this table.
|
||||
// scripts/test_moonraker_lane_data.py parses this initializer; keep the {"A", "B"} format.
|
||||
static const std::map<std::string, std::string> type_to_ofl_family = {
|
||||
// PLA variants
|
||||
{"PLA", "PLA"},
|
||||
{"PLA-CF", "PLA-CF"},
|
||||
{"PLA SILK", "PLA Silk"},
|
||||
{"PLA-SILK", "PLA Silk"},
|
||||
{"PLA HIGH SPEED", "PLA High Speed"},
|
||||
{"PLA-HS", "PLA High Speed"},
|
||||
{"PLA HS", "PLA High Speed"},
|
||||
|
||||
// PLA variants
|
||||
if (upper == "PLA") return "OGFL99";
|
||||
if (upper == "PLA-CF") return "OGFL98";
|
||||
if (upper == "PLA SILK" || upper == "PLA-SILK") return "OGFL96";
|
||||
if (upper == "PLA HIGH SPEED" || upper == "PLA-HS" || upper == "PLA HS") return "OGFL95";
|
||||
// ABS/ASA variants
|
||||
{"ABS", "ABS"},
|
||||
{"ASA", "ASA"},
|
||||
|
||||
// ABS/ASA variants
|
||||
if (upper == "ABS") return "OGFB99";
|
||||
if (upper == "ASA") return "OGFB98";
|
||||
// PETG/PET variants
|
||||
{"PETG", "PETG"},
|
||||
{"PET", "PETG"},
|
||||
{"PCTG", "PCTG"},
|
||||
|
||||
// PETG/PET variants
|
||||
if (upper == "PETG" || upper == "PET") return "OGFG99";
|
||||
if (upper == "PCTG") return "OGFG97";
|
||||
// PA/Nylon variants
|
||||
{"PA", "PA"},
|
||||
{"NYLON", "PA"},
|
||||
{"PA-CF", "PA-CF"},
|
||||
{"PPA", "PPA-CF"},
|
||||
{"PPA-CF", "PPA-CF"},
|
||||
{"PPA-GF", "PPA-GF"},
|
||||
|
||||
// PA/Nylon variants
|
||||
if (upper == "PA" || upper == "NYLON") return "OGFN99";
|
||||
if (upper == "PA-CF") return "OGFN98";
|
||||
if (upper == "PPA" || upper == "PPA-CF") return "OGFN97";
|
||||
if (upper == "PPA-GF") return "OGFN96";
|
||||
// PC variants
|
||||
{"PC", "PC"},
|
||||
|
||||
// PC variants
|
||||
if (upper == "PC") return "OGFC99";
|
||||
// PP/PE variants
|
||||
{"PE", "PE"},
|
||||
{"PP", "PP"},
|
||||
|
||||
// PP/PE variants
|
||||
if (upper == "PE") return "OGFP99";
|
||||
if (upper == "PP") return "OGFP97";
|
||||
// Support materials
|
||||
{"PVA", "PVA"},
|
||||
{"HIPS", "HIPS"},
|
||||
{"BVOH", "BVOH"},
|
||||
|
||||
// Support materials
|
||||
if (upper == "PVA") return "OGFS99";
|
||||
if (upper == "HIPS") return "OGFS98";
|
||||
if (upper == "BVOH") return "OGFS97";
|
||||
// TPU variants
|
||||
{"TPU", "TPU"},
|
||||
|
||||
// TPU variants
|
||||
if (upper == "TPU") return "OGFU99";
|
||||
// Other materials
|
||||
{"EVA", "EVA"},
|
||||
{"PHA", "PHA"},
|
||||
{"COPE", "CoPE"},
|
||||
{"SBS", "SBS"},
|
||||
};
|
||||
|
||||
// Other materials
|
||||
if (upper == "EVA") return "OGFR99";
|
||||
if (upper == "PHA") return "OGFR98";
|
||||
if (upper == "COPE") return "OGFLC99";
|
||||
if (upper == "SBS") return "OFLSBS99";
|
||||
auto it = type_to_ofl_family.find(upper);
|
||||
if (it == type_to_ofl_family.end())
|
||||
return UNKNOWN_FILAMENT_ID;
|
||||
|
||||
// Unknown material
|
||||
if (auto* bundle = GUI::wxGetApp().preset_bundle) {
|
||||
const Preset* preset = bundle->filaments.find_preset("Generic " + it->second + " @System");
|
||||
if (preset != nullptr && preset->is_system && !preset->filament_id.empty())
|
||||
return preset->filament_id;
|
||||
}
|
||||
|
||||
// Unknown material, or no loaded preset data to resolve against
|
||||
return UNKNOWN_FILAMENT_ID;
|
||||
}
|
||||
|
||||
|
||||
@@ -929,6 +929,20 @@ bool NetworkAgent::fetch_filament_info(std::string dev_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string NetworkAgent::to_orca_filament_id(const std::string& printer_filament_id) const
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->to_orca_filament_id(printer_filament_id);
|
||||
return printer_filament_id;
|
||||
}
|
||||
|
||||
std::string NetworkAgent::from_orca_filament_id(const std::string& orca_filament_id) const
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->from_orca_filament_id(orca_filament_id);
|
||||
return orca_filament_id;
|
||||
}
|
||||
|
||||
int NetworkAgent::request_bind_ticket(std::string* ticket)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
|
||||
@@ -165,6 +165,8 @@ public:
|
||||
int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
FilamentSyncMode get_filament_sync_mode() const;
|
||||
bool fetch_filament_info(std::string dev_id);
|
||||
std::string to_orca_filament_id(const std::string& printer_filament_id) const;
|
||||
std::string from_orca_filament_id(const std::string& orca_filament_id) const;
|
||||
int request_bind_ticket(std::string* ticket);
|
||||
int get_hms_snapshot(std::string dev_id, std::string file_name, std::function<void(std::string, int)> callback);
|
||||
|
||||
|
||||
@@ -859,9 +859,11 @@ std::string OrcaCloudServiceAgent::build_login_cmd()
|
||||
display_name = "unknown name";
|
||||
}
|
||||
json cmd;
|
||||
cmd["command"] = "orca_userlogin";
|
||||
cmd["data"]["name"] = display_name;
|
||||
cmd["data"]["avatar"] = get_user_avatar();
|
||||
cmd["command"] = "orca_userlogin";
|
||||
cmd["data"]["name"] = display_name;
|
||||
cmd["data"]["avatar"] = get_user_avatar();
|
||||
// The unique handle, shown under the display name in the homepage account menu.
|
||||
cmd["data"]["account"] = get_user_name();
|
||||
return cmd.dump();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user