Resync the DeviceCore state models

This commit is contained in:
SoftFever
2026-07-17 00:49:04 +08:00
parent 550ab5d438
commit 4bca7b3008
23 changed files with 529 additions and 200 deletions

View File

@@ -8,17 +8,30 @@ using namespace nlohmann;
namespace Slic3r
{
bool DevConfig::SupportChamberTempDisplay() const
{
if (!m_support_chamber_temp_display.has_value()) {
return m_has_chamber;
}
return m_support_chamber_temp_display.value();
}
void DevConfig::ParseConfig(const json& print_json)
{
ParseChamberConfig(print_json);
ParsePrintOptionsConfig(print_json);
ParseCalibrationConfig(print_json);
}
void DevConfig::ParseChamberConfig(const json& print_json)
{
DevJsonValParser::ParseVal(print_json, "support_chamber", m_has_chamber);
if (print_json.contains("support_chamber_temp_display")) {
m_support_chamber_temp_display = DevJsonValParser::GetVal<bool>(print_json, "support_chamber_temp_display");
}
DevJsonValParser::ParseVal(print_json, "support_chamber_temp_edit", m_support_chamber_edit);
if (m_support_chamber_edit)
{

View File

@@ -3,8 +3,9 @@
#include "slic3r/Utils/json_diff.hpp"
#include <wx/string.h>
#include <limits>
#include <limits>
#include <optional>
namespace Slic3r
{
@@ -22,6 +23,7 @@ public:
public:
// chamber
bool HasChamber() const { return m_has_chamber; }
bool SupportChamberTempDisplay() const;
bool SupportChamberEdit() const { return m_support_chamber_edit; }
int GetChamberTempEditMin() const { return m_chamber_temp_edit_min; }
int GetChamberTempEditMax() const { return m_chamber_temp_edit_max; }
@@ -57,6 +59,7 @@ private:
/*configure vals*/
// chamber
bool m_has_chamber = false; // whether the machine has a chamber
std::optional<bool> m_support_chamber_temp_display;
bool m_support_chamber_edit = false;
int m_chamber_temp_edit_min = 0;
int m_chamber_temp_edit_max = 60;

View File

@@ -1,16 +1,41 @@
#include "DevConfigUtil.h"
#include <algorithm>
#include <cctype>
#include <wx/dir.h>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include "../I18N.hpp"
using namespace nlohmann;
namespace Slic3r
{
// Translation markers for xgettext extraction.
// These strings are configured in printers/*.json (tool_head_display_names)
// and passed to _L() at runtime. xgettext cannot scan dynamic strings,
// so we mark them here with L() for extraction into .pot file.
// This block is never executed at runtime.
static void _toolhead_translation_markers()
{
// Dynamic toolhead display names from JSON config — xgettext cannot scan these
L("Main Extruder"); L("Main extruder"); L("main extruder");
L("Auxiliary Extruder"); L("Auxiliary extruder"); L("auxiliary extruder");
L("Left Extruder"); L("Left extruder"); L("left extruder");
L("Right Extruder"); L("Right extruder"); L("right extruder");
L("Main Nozzle"); L("Main nozzle"); L("main nozzle");
L("Auxiliary Nozzle"); L("Auxiliary nozzle"); L("auxiliary nozzle");
L("Left Nozzle"); L("Left nozzle"); L("left nozzle");
L("Right Nozzle"); L("Right nozzle"); L("right nozzle");
L("Main Hotend"); L("Main hotend"); L("main hotend");
L("Auxiliary Hotend"); L("Auxiliary hotend"); L("auxiliary hotend");
L("Left Hotend"); L("Left hotend"); L("left hotend");
L("Right Hotend"); L("Right hotend"); L("right hotend");
// standalone position words (short_name=true runtime results)
L("main"); L("auxiliary");
L("Main"); L("Auxiliary");
L("left"); L("right");
L("Left"); L("Right");
}
std::string DevPrinterConfigUtil::m_resource_file_path = "";
@@ -36,8 +61,6 @@ std::map<std::string, std::string> DevPrinterConfigUtil::get_all_model_id_with_n
for (wxString file : m_files)
{
if (!file.Lower().ends_with(".json")) continue;
std::string config_file = m_resource_file_path + "/printers/" + file.ToStdString();
boost::nowide::ifstream json_file(config_file.c_str());
@@ -91,7 +114,7 @@ std::string DevPrinterConfigUtil::get_filament_load_img(const std::string &type_
{
if (has_nozzle_rack)
{
const auto &rack_vec = get_value_from_config<std::vector<std::string>>(type_str, "filament_load_image_nozzle_rack");
const auto &rack_vec = get_value_from_config<std::vector<std::string>>(type_str, "filament_load_image_nozzle_rack") ;
if (!rack_vec.empty())
{
if (ext_id >= 0 && static_cast<size_t>(ext_id) < rack_vec.size())
@@ -111,7 +134,6 @@ std::string DevPrinterConfigUtil::get_filament_load_img(const std::string &type_
std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, const std::string& key)
{
std::vector<std::string> filaments;
std::string config_file = m_resource_file_path + "/printers/" + type_str + ".json";
boost::nowide::ifstream json_file(config_file.c_str());
try
@@ -134,6 +156,25 @@ std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, cons
return std::string();
}
std::vector<std::string> DevPrinterConfigUtil::get_fan_text_params(const std::string& type_str, const std::string& key)
{
std::string config_file = m_resource_file_path + "/printers/" + type_str + ".json";
boost::nowide::ifstream json_file(config_file.c_str());
try {
json jj;
if (json_file.is_open()) {
json_file >> jj;
if (jj.contains("00.00.00.00")) {
json const& printer = jj["00.00.00.00"];
if (printer.contains("fan") && printer["fan"].contains(key)) {
return printer["fan"][key].get<std::vector<std::string>>();
}
}
}
} catch (...) {}
return std::vector<std::string>();
}
std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, int airduct_mode, int airduct_func, int submode)
{
std::vector<std::string> filaments;
@@ -181,6 +222,36 @@ std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, int
return std::string();
}
std::string DevPrinterConfigUtil::get_fan_mode_text(const std::string& type_str, int airduct_mode, const std::string& key)
{
std::vector<std::string> filaments;
std::string config_file = m_resource_file_path + "/printers/" + type_str + ".json";
boost::nowide::ifstream json_file(config_file.c_str());
try {
json jj;
if (json_file.is_open()) {
json_file >> jj;
if (jj.contains("00.00.00.00")) {
json const& printer = jj["00.00.00.00"];
if (!printer.contains("fan")) {
return std::string();
}
json const& fan_item = printer["fan"];
const auto& airduct_mode_str = std::to_string(airduct_mode);
if (!fan_item.contains(airduct_mode_str)) {
return std::string();
}
if (fan_item[airduct_mode_str].contains(key)) {
return fan_item[airduct_mode_str][key].get<std::string>();
}
}
}
} catch (...) {}
return std::string();
}
std::map<std::string, std::vector<std::string>> DevPrinterConfigUtil::get_all_subseries(std::string type_str)
{
std::map<std::string, std::vector<std::string>> subseries;
@@ -284,36 +355,45 @@ std::string DevPrinterConfigUtil::get_toolhead_display_name(
{ ToolHeadComponent::Hotend, "hotend" }
};
const int case_index = static_cast<int>(name_case);
const std::string role_key = std::to_string(ext_id);
int case_index = static_cast<int>(name_case); // 0, 1, 2
// Try to read from printer config json
auto names_json = get_value_from_config<json>(type_str, "tool_head_display_names");
std::string role_key = std::to_string(ext_id); // "0" or "1"
const std::string& comp_key = comp_keys.at(component);
std::string result;
auto names_json = get_value_from_config<json>(type_str, "tool_head_display_names");
if (!names_json.is_null() && names_json.contains(role_key) && names_json[role_key].contains(comp_key)) {
if (!names_json.is_null()
&& names_json.contains(role_key)
&& names_json[role_key].contains(comp_key))
{
auto& arr = names_json[role_key][comp_key];
if (arr.is_array() && case_index < static_cast<int>(arr.size()))
if (arr.is_array() && case_index < static_cast<int>(arr.size())) {
result = arr[case_index].get<std::string>();
}
}
// Fallback: all dual-extruder printers should have tool_head_display_names configured.
// This is a safety net only — return a generic name.
if (result.empty()) {
const std::string side = ext_id == DEPUTY_EXTRUDER_ID ? "Left" : "Right";
const std::string component_name = component == ToolHeadComponent::Extruder ? "Extruder" :
component == ToolHeadComponent::Hotend ? "Hotend" : "Nozzle";
result = side + " " + component_name;
if (name_case == ToolHeadNameCase::SentenceCase && result.size() > side.size() + 1)
result[side.size() + 1] = static_cast<char>(std::tolower(static_cast<unsigned char>(result[side.size() + 1])));
else if (name_case == ToolHeadNameCase::LowerCase)
std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
static const std::map<ToolHeadComponent, std::string> fallback_names = {
{ ToolHeadComponent::Extruder, "Extruder" },
{ ToolHeadComponent::Nozzle, "Nozzle" },
{ ToolHeadComponent::Hotend, "Hotend" }
};
result = fallback_names.at(component);
}
// short_name: return only the role prefix (e.g. "Main" from "Main Nozzle")
if (short_name) {
auto sp = result.find(' ');
if (sp != std::string::npos)
if (sp != std::string::npos) {
result = result.substr(0, sp);
}
}
return result;
}
};
};

View File

@@ -11,6 +11,8 @@
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <cctype>
#include <boost/log/trivial.hpp>
#include <boost/nowide/fstream.hpp>
@@ -23,6 +25,20 @@
namespace Slic3r
{
/// Toolhead component type (extruder / nozzle / hotend)
enum class ToolHeadComponent {
Extruder,
Nozzle,
Hotend
};
/// Name case style for toolhead display names
enum class ToolHeadNameCase {
TitleCase = 0, // [0] "Main Extruder" — panel titles, section headers
SentenceCase = 1, // [1] "Main extruder" — static box labels
LowerCase = 2 // [2] "main extruder" — inline text, sentence concatenation
};
class dePrinterConfigFactory
{
public:
@@ -30,17 +46,6 @@ public:
~dePrinterConfigFactory() = default;
};
enum class ToolHeadComponent {
Extruder,
Nozzle,
Hotend
};
enum class ToolHeadNameCase {
TitleCase = 0,
SentenceCase = 1,
LowerCase = 2
};
class DevPrinterConfigUtil
{
@@ -74,14 +79,19 @@ public:
static std::string get_printer_use_ams_type(std::string type_str) { return get_value_from_config<std::string>(type_str, "use_ams_type"); }
static std::string get_printer_ams_img(const std::string& type_str) { return get_value_from_config<std::string>(type_str, "printer_use_ams_image"); }
static std::string get_printer_ext_img(const std::string& type_str, int pos);//printer_ext_image
static bool support_ams_fila_change_abort(std::string type_str) { return get_value_from_config<bool>(type_str, "print", "support_ams_filament_change_abort"); }
static std::string get_filament_load_img(const std::string &type_str, int ext_id, bool has_nozzle_rack = false);
/*fan*/
static std::string get_fan_text(const std::string& type_str, const std::string& key);
static std::string get_fan_text(const std::string& type_str, const std::string& key);
static std::vector<std::string> get_fan_text_params(const std::string& type_str, const std::string& key);
static std::string get_fan_text(const std::string& type_str, int airduct_mode, int airduct_func, int submode);
static std::string get_fan_mode_text(const std::string& type_str, int airduct_mode, const std::string& key);
/*extruder*/
static bool get_printer_can_set_nozzle(std::string type_str) { return get_value_from_config<bool>(type_str, "enable_set_nozzle_info"); }// can set nozzle from studio
/*toolhead display names (extruder / nozzle / hotend)*/
static std::string get_toolhead_display_name(
const std::string& type_str,
int ext_id,
@@ -90,10 +100,15 @@ public:
bool short_name = false);
/*print job*/
static bool support_print_check_firmware_for_tpu_left(std::string type_str){ return get_value_from_config<bool>(type_str, "print", "support_print_check_firmware_for_tpu_left"); }
static bool support_user_first_setup_tpu_check(std::string type_str){ return get_value_from_config<bool>(type_str, "print", "support_user_first_setup_tpu_check"); }
static std::string support_user_first_setup_tpu_check_url(std::string type_str){ return get_value_from_config<std::string>(type_str, "print", "support_user_first_setup_tpu_check_url"); }
static bool support_ams_ext_mix_print(std::string type_str) { return get_value_from_config<bool>(type_str, "print", "support_ams_ext_mix_print"); }
static bool support_print_time_estimate_warning(std::string type_str) { return get_value_from_config<bool>(type_str, "print", "support_print_time_estimate_warning"); }
/*calibration*/
static std::vector<std::string> get_unsupport_auto_cali_filaments(std::string type_str) { return get_value_from_config<std::vector<std::string>>(type_str, "auto_cali_not_support_filaments"); }
static bool support_disable_cali_flow_type(std::string type_str) { return get_value_from_config<bool>(type_str,"support_disable_cali_flow_type"); }
/*detection*/
static bool support_wrapping_detection(const std::string& type_str) { return get_value_from_config<bool>(type_str, "support_wrapping_detection"); }
@@ -103,7 +118,10 @@ public:
/*print check*/
static bool support_print_check_extension_fan_f000_mounted(const std::string& type_str) { return get_value_from_config<bool>(type_str, "print", "support_print_check_extension_fan_f000_mounted"); }
static bool support_print_check_firmware_for_tpu_left(const std::string& type_str) { return get_value_from_config<bool>(type_str, "print", "support_print_check_firmware_for_tpu_left"); }
static std::string air_print_detection_position(const std::string &type_str) { return get_value_from_config<std::string>(type_str, "air_print_detection_position"); }
/*bed*/
static int get_bed_temperature_limit(const std::string &type_str) { return get_value_from_config<int>(type_str, "print", "bed_temperature_limit"); }
public:
template<typename T>
@@ -127,7 +145,7 @@ public:
}
}
}
catch (...) { assert(0 && "get_value_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors
catch (...) { assert(0 && "get_value_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors
return T();
};
@@ -179,7 +197,7 @@ public:
}
}
}
catch (...) { assert(0 && "get_json_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors
catch (...) { assert(0 && "get_json_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors
return nlohmann::json();
}
@@ -188,35 +206,25 @@ private:
};
/*special transform*/
static std::string _parse_printer_type(const std::string& type_str)
static std::string _parse_printer_type(const std::string &type_str)
{
if (type_str.compare("3DPrinter-X1") == 0)
{
return "BL-P002";
}
else if (type_str.compare("3DPrinter-X1-Carbon") == 0)
{
return "BL-P001";
}
else if (type_str.compare("BL-P001") == 0)
{
return type_str;
}
else if (type_str.compare("BL-P002") == 0)
{
return type_str;
}
else
{
std::string result = DevPrinterConfigUtil::get_printer_type(type_str);
if (!result.empty())
{
return result;
}
}
static std::unordered_map<std::string, std::string> s_printer_type_lazy_cache;
if (type_str == "3DPrinter-X1") return "BL-P002";
if (type_str == "3DPrinter-X1-Carbon") return "BL-P001";
if (type_str == "BL-P001" || type_str == "BL-P002") return type_str;
auto cache_it = s_printer_type_lazy_cache.find(type_str);
if (cache_it != s_printer_type_lazy_cache.end()) {
return cache_it->second;
}
std::string result = DevPrinterConfigUtil::get_printer_type(type_str);
if (!result.empty()) {
s_printer_type_lazy_cache[type_str] = result;
return result;
}
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Unsupported printer type: " << type_str;
return type_str;
}
};// namespace Slic3r
};// namespace Slic3r

View File

@@ -10,12 +10,21 @@
#pragma once
#include <string>
#include <utility>
#include <nlohmann/json.hpp>
// Reserved for future usage
#define DEV_RESERVED_FOR_FUTURE(...) /* stripped */
// Previous definitions
namespace Slic3r
{
class MachineObject;
}
enum PrinterArch
{
ARCH_CORE_XY,
ARCH_I3,
ARCH_CORE_XY,// move hotbed
ARCH_I3,//move z
};
enum PrinterSeries
@@ -36,6 +45,7 @@ enum AmsStatusMain
AMS_STATUS_MAIN_RFID_IDENTIFYING = 0x02,
AMS_STATUS_MAIN_ASSIST = 0x03,
AMS_STATUS_MAIN_CALIBRATION = 0x04,
AMS_STATUS_MAIN_COLD_PULL = 0x07,
AMS_STATUS_MAIN_SELF_CHECK = 0x10,
AMS_STATUS_MAIN_DEBUG = 0x20,
AMS_STATUS_MAIN_UNKNOWN = 0xFF,
@@ -51,10 +61,6 @@ enum DevAmsType : int
AMS_LITE_MIXED = 5, // AMS-Lite for N9
};
// Device-numbered filament-change step codes. Newer firmware reports the exact change-step
// sequence through the AMS (ams.cfs), keyed by these codes, instead of the client hardcoding
// steps per model. Distinct from the legacy GUI-side Slic3r::GUI::FilamentStep enum.
// STEP_CHECK_POSITION and STEP_CONFIRM_EXTRUDED share code 0x08 by device design.
enum DevFilamentStep
{
STEP_IDLE = 0x00,
@@ -83,37 +89,35 @@ enum DevFilamentStep
#define VIRTUAL_AMS_MAIN_ID_STR "255"
#define VIRTUAL_AMS_DEPUTY_ID_STR "254"
// Tray index offset for the AMS-Lite-mixed unit (A2L / N9). Its 4 trays occupy
// global tray indices 24..27.
#define AMS_LITE_MIXED_TRAY_INDEX_OFFSET 24
// Tray index offsets for different AMS types
#define AMS_LITE_MIXED_TRAY_INDEX_OFFSET 24 // Offset for AMS_LITE_MIXED tray index (24)
#define INVALID_AMS_TEMPERATURE std::numeric_limits<float>::min()
// (ams_id, slot_id) pair.
using DevAmsSlotId = std::pair<int, int>;
/* Extruder*/
#define MAIN_EXTRUDER_ID 0
#define DEPUTY_EXTRUDER_ID 1
#define UNIQUE_EXTRUDER_ID MAIN_EXTRUDER_ID
#define INVALID_EXTRUDER_ID -1
/* Logical extruder ids (multi-nozzle). */
// see PartPlate::get_physical_extruder_by_logical_extruder
#define LOGIC_UNIQUE_EXTRUDER_ID 0
#define LOGIC_L_EXTRUDER_ID 0
#define LOGIC_R_EXTRUDER_ID 1
// <ams_id, slot_id>
using DevAmsSlotId = std::pair<int, int>;
/* Nozzle*/
enum NozzleFlowType
enum NozzleFlowType : int
{
NONE_FLOWTYPE,
S_FLOW,
H_FLOW,
U_FLOW, // TPU 1.75 High Flow (device-reported; maps to nvtTPUHighFlow)
U_FLOW, // TPU 1.75 High Flow
E_FLOW, // E3D High Flow
};
// Discrete nozzle diameters reported by the device.
/* 0.2mm 0.4mm 0.6mm 0.8mm */
enum NozzleDiameterType : int
{
NONE_DIAMETER_TYPE,
@@ -135,7 +139,7 @@ enum DevPrintingSpeedLevel
};
/*Upgrade*/
enum class DevFirmwareUpgradingState : int
enum class DevFirmwareUpgradeState : int
{
DC = -1,
UpgradingUnavaliable = 0,
@@ -144,6 +148,10 @@ enum class DevFirmwareUpgradingState : int
UpgradingFinished = 3
};
// Orca: transitional shim (removed in resync cluster 8) — DeviceManager/UpgradePanel still use the
// pre-resync name; alias keeps them compiling until they are resynced to the reference name.
using DevFirmwareUpgradingState = DevFirmwareUpgradeState;
class devPrinterUtil
{
public:
@@ -157,9 +165,6 @@ public:
namespace GUI
{
// Print source. Defined here (rather than in SelectMachine.hpp) so the shared device-mapping
// GUI headers — AmsMappingPopup, wgtDeviceNozzleSelect — can name it without pulling in
// SelectMachine.hpp, which would create an include cycle.
enum PrintFromType
{
FROM_NORMAL,
@@ -169,8 +174,6 @@ enum PrintFromType
};// namespace Slic3r
// A nozzle requirement of the sliced plate (or an installed nozzle's identity), compared in the
// pre-print slicing-vs-installed nozzle checks.
struct NozzleDef
{
float nozzle_diameter;
@@ -190,4 +193,7 @@ template<> struct std::hash<NozzleDef>
size_t h2 = std::hash<int>{}(v.nozzle_flow_type);
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
};
};
};
// key(extruder_id) -> { key1(nozzle type info), val1( number of the nozzle type)}
using ExtruderNozzleInfos = std::unordered_map<int, std::unordered_map<NozzleDef, int>>;

View File

@@ -61,6 +61,14 @@ static std::string _get_string_from_fantype(int type)
int Slic3r::DevFan::command_control_fan(int fan_type, int val)
{
std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int) fan_type % (val)).str();
try {
json j;
j["ctrl_type"] = _get_string_from_fantype(fan_type);
j["value"] = val;
NetworkAgent *agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_event("printer_control", j.dump());
} catch (...) {}
return m_owner->publish_gcode(gcode);
}
@@ -166,8 +174,6 @@ void Slic3r::DevFan::ParseV3_0(const json &device)
m_air_duct_data.modes.clear();
m_air_duct_data.parts.clear();
m_air_duct_data.curren_mode = device["airduct"]["modeCur"].get<int>();
const json &airduct = device["airduct"];
if (airduct.contains("modeCur")) { m_air_duct_data.curren_mode = airduct["modeCur"].get<int>(); }
if (airduct.contains("subMode")) { m_air_duct_data.m_sub_mode = airduct["subMode"].get<int>(); }
@@ -193,7 +199,7 @@ void Slic3r::DevFan::ParseV3_0(const json &device)
}
}
if (AIR_DUCT(mode.id) == AIR_DUCT::AIR_DUCT_EXHAUST) { continue; } /*STUDIO-12796*/
if (AIR_DUCT(mode.id) == AIR_DUCT::AIR_DUCT_EXHAUST) { continue; }
m_air_duct_data.modes[mode.id] = mode;
}
}

View File

@@ -11,8 +11,6 @@ class MachineObject;
enum AirDuctType { AIR_FAN_TYPE, AIR_DOOR_TYPE };
typedef std::function<void(const json &)> CommandCallBack;
enum AIR_FUN : int {
FAN_HEAT_BREAK_0_IDX = 0,
FAN_COOLING_0_AIRDOOR = 1,
@@ -91,6 +89,13 @@ public:
bool IsSupportCoolingFilter() const { return m_support_cooling_filter; }
bool IsCoolingFilerOn() const { return m_sub_mode == 1; }
bool IsExaustFanExit() const
{
for (auto &p : parts) {
if (p.id == int(AIR_FUN::FAN_CHAMBER_0_IDX)) return true;
}
return false;
}
};
class DevFan

View File

@@ -1,5 +1,6 @@
#pragma once
#include <optional>
#include <unordered_map> // Orca: for m_firmwares (kept unordered for not-yet-resynced AMSSetting.cpp)
#include <nlohmann/json.hpp>
#include "DevCtrl.h"
@@ -75,7 +76,7 @@ public:
DevAmsSystemIdx GetCurrentFirmwareIdxSel() const { return m_current_firmware_sel.m_firmare_idx; };
DevAmsSystemIdx GetCurrentFirmwareIdxRun() const { return m_current_firmware_run.m_firmare_idx; };
std::unordered_map<int, DevAmsSystemFirmware> GetSuppotedFirmwares() const { return m_firmwares;};
std::unordered_map<int, DevAmsSystemFirmware> GetSuppotedFirmwares() const { return m_firmwares;}; // Orca: unordered (AMSSetting.cpp, cluster 8)
bool IsSwitching() const { return m_status == "SWITCHING";};
bool IsIdle() const { return m_status == "IDLE";};
@@ -94,7 +95,7 @@ private:
DevAmsSystemFirmware m_current_firmware_run;
DevAmsSystemFirmware m_current_firmware_sel;
std::unordered_map<int, DevAmsSystemFirmware> m_firmwares;
std::unordered_map<int, DevAmsSystemFirmware> m_firmwares; // Orca: unordered (AMSSetting.cpp, cluster 8)
DevCtrlInfo m_ctrl_switching;
};

View File

@@ -9,19 +9,6 @@ namespace Slic3r {
DevFilaSwitch::DevFilaSwitch(MachineObject *owner) { m_owner = owner; }
bool DevFilaSwitch::IsReady() const
{
if (!m_is_installed) { return false; }
const auto& ams_list = m_owner->GetFilaSystem()->GetAmsList();
for (const auto& ams_item : ams_list) {
if (ams_item.second->GetBindedExtruderSet().empty()) { return false; }
if (!ams_item.second->GetSwitcherPos().has_value()) { return false; }
}
return true;
}
void DevFilaSwitch::Reset()
{
m_is_installed = false;
@@ -34,6 +21,24 @@ void DevFilaSwitch::Reset()
m_cali_status = CaliStatus::CALI_IDLE;
}
bool DevFilaSwitch::IsReady() const
{
if (!m_is_installed) {
BOOST_LOG_TRIVIAL(debug) << "[FilaSwitch] IsReady: not installed";
return false;
}
const auto& ams_list = m_owner->GetFilaSystem()->GetAmsList();
for (const auto& ams_item : ams_list) {
if (ams_item.second->GetBindedExtruderSet().size() == 0) { return false; }
if (!ams_item.second->GetSwitcherPos().has_value()) {
return false;
}
}
return true;
}
std::optional<DevAmsTray> DevFilaSwitch::GetInA_Slot() const
{
auto ams_id_opt = GetInA_SlotId();
@@ -128,4 +133,4 @@ void DevFilaSwitch::ParseFilaSwitchInfo(const nlohmann::json &print_jj)
}
}
}; // namespace Slic3r
}; // namespace Slic3r

View File

@@ -1,7 +1,6 @@
#pragma once
#include "DevDefs.h"
#include <optional>
#include <nlohmann/json.hpp>
namespace Slic3r
{
@@ -10,16 +9,11 @@ class MachineObject;
class DevExtder;
class DevAmsTray;
// Filament Track Switch (H2-family hardware).
// The filament blacklist consumes IsInstalled() for the `has_filament_switch`
// rule (e.g. PLA Silk). m_is_installed defaults to false and is only raised when
// the device reports the switch over MQTT (aux bit 29), so the rule stays inert on
// every printer that does not report an installed switch.
class DevFilaSwitch
{
public:
enum class CaliStatus : int
{
{
CALI_IDLE = 0,
CALI_STEPING = 1,
};
@@ -48,10 +42,6 @@ public:
public:
bool IsInstalled() const { return m_is_installed; };
// Ready once installed and every AMS has resolved both its extruder binding and its
// switcher track position from the device. The send dialog and sidebar sync UX only
// treat the switch as usable when this is true.
bool IsReady() const;
std::optional<bool> IsInA_HasFilament() const { return m_in_a_has_filament; };
@@ -88,4 +78,4 @@ private:
CaliStatus m_cali_status = CaliStatus::CALI_IDLE;
};
};
};

View File

@@ -270,10 +270,10 @@ private:
AmsType m_ams_type = AmsType::AMS;
std::string m_ams_id;
int m_ext_id;//extruder id
// Orca: keeps the legacy single m_ext_id for existing consumers and carries the
// switch-aware binding alongside it (BambuStudio stores only the set). Without a Filament
// Track Switch the set is {m_ext_id}; with one installed the device binds both extruders and
// records which input track (A/B) feeds this AMS.
// Orca: pull-mode / multi-vendor agent model — keeps the legacy single m_ext_id for existing
// consumers and carries the switch-aware binding alongside it. Without a Filament Track Switch
// the set is {m_ext_id}; with one installed the device binds both extruders and records which
// input track (A/B) feeds this AMS.
std::set<int> m_binded_extruder_set;
std::optional<DevFilaSwitch::SwitchPos> m_binded_switcher_pos;
bool m_exist = false;

View File

@@ -28,8 +28,8 @@ int DevFilaSystem::CtrlAmsStartDryingHour(int ams_id,
jj_command["print"]["command"] = "ams_filament_drying";
jj_command["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
jj_command["print"]["ams_id"] = ams_id;
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::OnTime);
jj_command["print"]["filament"] = filament_type;
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::OnTime); // Orca: cast scoped enum for json
jj_command["print"]["filament"] = filament_type; // Orca: fix comma-operator typo
jj_command["print"]["temp"] = tag_temp;
jj_command["print"]["duration"] = tag_duration_hour;
jj_command["print"]["humidity"] = 0;
@@ -45,8 +45,8 @@ int DevFilaSystem::CtrlAmsStopDrying(int ams_id) const
jj_command["print"]["command"] = "ams_filament_drying";
jj_command["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
jj_command["print"]["ams_id"] = ams_id;
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::Off);
jj_command["print"]["filament"] = "";
jj_command["print"]["mode"] = static_cast<int>(DevAms::DryCtrlMode::Off); // Orca: cast scoped enum for json
jj_command["print"]["filament"] = ""; // Orca: fix comma-operator typo
jj_command["print"]["temp"] = 0;
jj_command["print"]["duration"] = 0;
jj_command["print"]["humidity"] = 0;

View File

@@ -1,4 +1,7 @@
#pragma once
#include "DevFirmware.h"
#include "slic3r/Utils/json_diff.hpp"
#include <nlohmann/json.hpp>
#include <wx/string.h>
#include "slic3r/Utils/json_diff.hpp"
@@ -8,6 +11,7 @@ namespace Slic3r {
//Previous definitions
class MachineObject;
// Orca: firmware-type enum consumed by DeviceManager/UpgradePanel; no reference-side equivalent yet
enum PrinterFirmwareType
{
FIRMWARE_TYPE_ENGINEER = 0,
@@ -15,7 +19,6 @@ enum PrinterFirmwareType
FIRMEARE_TYPE_UKNOWN,
};
class FirmwareInfo
{
public:
@@ -40,12 +43,18 @@ public:
public:
bool isValid() const { return !sn.empty(); }
/*type check*/
bool isAirPump() const { return product_name.Contains("Air Pump"); }
bool isLaszer() const { return product_name.Contains("Laser"); }
bool isCuttingModule() const { return product_name.Contains("Cutting Module"); }
bool isExtinguishSystem() const { return product_name.Contains("Extinguishing System"); }
bool isWTM() const { return name.find("wtm") != std::string::npos; } // nozzle (rack hotend) module firmware
bool isFilaTrackSwitch() const { return product_name.Contains("Filament Track"); }
bool isRotary() const { return product_name.Contains("Rotary"); }// Rotary Attachment
bool isExtinguishSystem() const { return product_name.Contains("Extinguishing System"); }// Auto Fire Extinguishing System
bool isWTM() const { return name.find("wtm") != string::npos; } // nozzle
bool isExhaustFan() const { return product_name.Contains("Exhaust Fan"); }
bool isHmshub() const { return product_name.find("Filament Buffer") != string::npos; }
bool isFilaTrackSwitch() const { return product_name.find("Filament Track") != string::npos; }
};

View File

@@ -29,6 +29,7 @@ bool DevHMSItem::parse_hms_info(unsigned attr, unsigned code)
std::string DevHMSItem::get_long_error_code() const
{
char buf[64];
// Orca: HMS long-error-code format excludes the reserved byte and keys the Orca HMS wiki lookups
::sprintf(buf, "%02X%02X%02X00000%1X%04X",
this->m_module_id,
this->m_module_num,

View File

@@ -8,6 +8,10 @@ namespace Slic3r {
class MachineObject;
/* some static info of machine*/ /*TODO*/
// Orca: kept as a stub — connection_type/is_lan_mode_printer/is_cloud_mode_printer live inline on
// MachineObject (DeviceManager.hpp). Adopting the reference's full DevInfo would duplicate those
// definitions and require an m_dev_info member MachineObject does not have; that consolidation is
// deferred to the DeviceManager resync (cluster 2).
class DevInfo
{
public:

View File

@@ -16,10 +16,6 @@
#include "slic3r/GUI/GUI_App.hpp"
#include <algorithm>
#include <unordered_set>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <nlohmann/json.hpp>
using namespace nlohmann;
@@ -33,30 +29,6 @@ void MachineObject::clear_auto_nozzle_mapping()
}
}
static std::string s_get_diameter_str(float diameter)
{
return (boost::format("%.2f") % diameter).str();
}
static std::string s_get_diameter_str(const std::string& diameter)
{
try {
float dia = boost::lexical_cast<float>(diameter);
return s_get_diameter_str(dia);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed to boost::lexical_cast: " << diameter;
return diameter;
}
try {
float dia = std::stof(diameter);
return s_get_diameter_str(dia);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " std::stof: " << diameter;
return diameter;
}
}
// get auto nozzle mapping through AP
// warnings:
@@ -268,7 +240,7 @@ int DevNozzleMappingCtrl::CtrlGetAutoNozzleMappingV1(Slic3r::GUI::Plater* plater
void DevNozzleMappingCtrl::ParseAutoNozzleMapping(const json& print_jj)
{
if (print_jj.contains("command") && print_jj["command"].get<std::string>() == "get_auto_nozzle_mapping") {
if (print_jj.contains("command") && print_jj["command"].get<string>() == "get_auto_nozzle_mapping") {
if (print_jj.contains("sequence_id") && print_jj["sequence_id"] == m_sequence_id) {
Clear();
DevJsonValParser::ParseVal(print_jj, "result", m_result);
@@ -482,4 +454,4 @@ float DevNozzleMappingCtrl::GetFlushWeight(Slic3r::MachineObject* obj) const
return total_flush_volume * 1.26 * 0.001;
}
} // namespace Slic3r
} // namespace Slic3r

View File

@@ -18,7 +18,7 @@ namespace GUI
class Plater;
}
struct FilamentInfo; // libslic3r/ProjectTask.hpp
struct FilamentInfo; // Orca: libslic3r/ProjectTask.hpp — forward-decl for CtrlGetAutoNozzleMappingV0 signature
class MachineObject;
class DevNozzleMappingCtrl

View File

@@ -19,17 +19,17 @@ DevStorage::SdcardState Slic3r::DevStorage::set_sdcard_state(int state)
{
if (system)
{
if (print_json.contains("sdcard")) {
if (print_json["sdcard"].get<bool>())
system->m_sdcard_state = DevStorage::SdcardState::HAS_SDCARD_NORMAL;
else
system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD;
} else {
system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD;
}
// parse timelapse storage space from cam push data
try {
if (print_json.contains("sdcard")) {
if (print_json["sdcard"].get<bool>())
system->m_sdcard_state = DevStorage::SdcardState::HAS_SDCARD_NORMAL;
else
system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD;
} else {
system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD;
}
// parse timelapse storage space from cam push data
if (print_json.contains("device") && print_json["device"].is_object()) {
const auto& device_json = print_json["device"];
if (device_json.contains("cam") && device_json["cam"].is_object()) {
@@ -45,17 +45,16 @@ DevStorage::SdcardState Slic3r::DevStorage::set_sdcard_state(int state)
}
}
} catch (...) {}
}
}
}
bool DevStorage::is_timelapse_storage_low(const std::string& storage) const
{
const int THRESHOLD_KB = 20480; // 20MB
const int THRESHOLD_KB = 20480; // Orca: 20MB (20480 KB; corrected mislabeled comment)
if (storage == "internal")
return tl_internal_free_kb >= 0 && tl_internal_free_kb < THRESHOLD_KB;
else
return tl_external_free_kb >= 0 && tl_external_free_kb < THRESHOLD_KB;
}
} // namespace Slic3r

View File

@@ -26,7 +26,7 @@ public:
SdcardState get_sdcard_state() const { return m_sdcard_state; };
SdcardState set_sdcard_state(int state);
static void ParseV1_0(const json &print_json, DevStorage *system);
static void ParseV1_0(const json &print_json, DevStorage *system);
bool is_timelapse_storage_low(const std::string& storage) const;
@@ -34,10 +34,13 @@ private:
MachineObject *m_owner;
SdcardState m_sdcard_state { NO_SDCARD };
// timelapse storage space info (from device push cam data)
int tl_internal_free_kb { -1 };
int tl_internal_total_kb { -1 };
int tl_external_free_kb { -1 };
int tl_external_total_kb { -1 };
int tl_internal_free_kb{-1};
int tl_internal_total_kb{-1};
int tl_external_free_kb{-1};
int tl_external_total_kb{-1};
};
} // namespace Slic3r

View File

@@ -24,6 +24,79 @@ int DevUtil::get_flag_bits(std::string str, int start, int count)
return 0;
}
uint32_t DevUtil::get_flag_bits_no_border(std::string str, int start_idx, int count)
{
if (start_idx < 0 || count <= 0) return 0;
try {
// --- 1) trim ---
auto ltrim = [](std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); };
auto rtrim = [](std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); };
ltrim(str);
rtrim(str);
// --- 2) remove 0x/0X prefix ---
if (str.size() >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { str.erase(0, 2); }
// --- 3) keep only hex digits ---
std::string hex;
hex.reserve(str.size());
for (char c : str) {
if (std::isxdigit(static_cast<unsigned char>(c))) hex.push_back(c);
}
if (hex.empty()) return 0;
// --- 4) use size_t for all index/bit math ---
const size_t total_bits = hex.size() * 4ULL;
const size_t ustart = static_cast<size_t>(start_idx);
if (ustart >= total_bits) return 0;
const int int_bits = std::numeric_limits<uint32_t>::digits; // typically 32
const size_t need_bits = static_cast<size_t>(std::min(count, int_bits));
// [first_bit, last_bit]
const size_t first_bit = ustart;
const size_t last_bit = std::min(ustart + need_bits, total_bits) - 1ULL;
if (last_bit < first_bit) return 0;
const size_t right_index = hex.size() - 1ULL;
const size_t first_nibble = first_bit / 4ULL;
const size_t last_nibble = last_bit / 4ULL;
const size_t start_idx = right_index - last_nibble;
const size_t end_idx = right_index - first_nibble;
if (end_idx < start_idx) return 0;
const size_t sub_len = end_idx - start_idx + 1ULL;
if (end_idx >= hex.size()) return 0;
const std::string sub_hex = hex.substr(start_idx, sub_len);
unsigned long long chunk = std::stoull(sub_hex, nullptr, 16);
const unsigned nibble_offset = static_cast<unsigned>(first_bit % 4ULL);
const unsigned long long shifted = (nibble_offset == 0U) ? chunk : (chunk >> nibble_offset);
uint32_t mask;
if (need_bits >= static_cast<size_t>(std::numeric_limits<uint32_t>::digits)) {
mask = std::numeric_limits<uint32_t>::max();
} else {
mask = static_cast<uint32_t>((1ULL << need_bits) - 1ULL);
}
const uint32_t val = static_cast<uint32_t>(shifted & mask);
return val;
} catch (const std::invalid_argument &) {
return 0;
} catch (const std::out_of_range &) {
return 0;
} catch (...) {
return 0;
}
}
int DevUtil::get_flag_bits(int num, int start, int count, int base)
{

View File

@@ -12,8 +12,15 @@
#include <stdexcept>
#include <boost/log/trivial.hpp>
#include <boost/lexical_cast.hpp>
#include "nlohmann/json.hpp"
/* Sequence Id*/
#define STUDIO_START_SEQ_ID 20000
#define STUDIO_END_SEQ_ID 30000
#define CLOUD_SEQ_ID 0
namespace Slic3r
{
@@ -27,14 +34,18 @@ public:
public:
static int get_flag_bits(std::string str, int start, int count = 1);
static int get_flag_bits(int num, int start, int count = 1, int base = 10);
static uint32_t get_flag_bits_no_border(std::string str, int start_idx, int count = 1);
// Extract the hex digit at position `pos` (0 = least-significant).
// eg. get_hex_bits(16, 1, 10) = 1
static int get_hex_bits(int num, int pos, int input_num_base = 10) { return get_flag_bits(num, pos * 4, 4, input_num_base); }
static int get_hex_bits(int num, int pos, int input_num_base = 10) { return get_flag_bits(num, pos * 4, 4, input_num_base);};
static float string_to_float(const std::string& str_value);
static std::string convertToIp(long long ip);
// sequence id check
static bool is_studio_cmd(int seq) { return seq >= STUDIO_START_SEQ_ID && seq < STUDIO_END_SEQ_ID;};
static bool is_cloud_cmd(int seq) { return seq == CLOUD_SEQ_ID;};
};
@@ -108,4 +119,94 @@ struct NumericStrCompare
}
};
enum class DirtyMode{
COUNTER,
TIMER
};
template<typename T>
class DevDirtyHandler{
public:
DevDirtyHandler(T init_value, int setting_threshold, DirtyMode mode): m_value(init_value), m_setting_threshold(setting_threshold), m_mode(mode)
{
m_threshold = setting_threshold;
}
~DevDirtyHandler(){};
T GetValue() const { return m_value; };
void SetOptimisticValue(const T& data)
{
m_value = data;
m_start_time = time(nullptr);
m_threshold = m_setting_threshold;
}
void UpdateValue(const T& data)
{
if (m_mode == DirtyMode::COUNTER)
{
if (m_threshold > 0)
m_threshold--;
else
m_value = data;
}
else if (m_mode == DirtyMode::TIMER)
{
if (time(nullptr) - m_start_time > m_threshold)
m_value = data;
}
}
private:
T m_value;
DirtyMode m_mode;
int m_setting_threshold{0};
int m_start_time{0};
int m_threshold{0};
};
static std::string s_get_diameter_str(float diameter)
{
return (boost::format("%.2f") % diameter).str();
}
static std::string s_get_diameter_str(const std::string& diameter)
{
try {
float dia = boost::lexical_cast<float>(diameter);
return s_get_diameter_str(dia);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed to boost::lexical_cast: " << diameter;
return diameter;
}
try {
float dia = std::stof(diameter);
return s_get_diameter_str(dia);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " std::stof: " << diameter;
return diameter;
}
}
static float s_get_diameter(const std::string& diameter)
{
try {
return boost::lexical_cast<float>(diameter);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed to boost::lexical_cast: " << diameter;
}
try {
return std::stof(diameter);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " std::stof: " << diameter;
}
return 0.0;
}
}; // namespace Slic3r

View File

@@ -2,15 +2,28 @@
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
#include "slic3r/GUI/PartPlate.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include <boost/log/trivial.hpp>
#include <boost/lexical_cast.hpp>
#include <wx/string.h>
namespace Slic3r
{
std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> DevUtilBackend::GetNozzleGroupResult(Slic3r::GUI::Plater* plater)
Slic3r::MultiNozzleUtils::NozzleInfo DevUtilBackend::GetNozzleInfo(const DevNozzle& dev_nozzle)
{
MultiNozzleUtils::NozzleInfo info;
info.diameter = dev_nozzle.GetNozzleDiameterStr().ToStdString();
info.volume_type = DevNozzle::ToNozzleVolumeType(dev_nozzle.GetNozzleFlowType());
info.extruder_id = dev_nozzle.GetLogicExtruderId();
return info;
}
std::shared_ptr<Slic3r::MultiNozzleUtils::NozzleGroupResultBase> DevUtilBackend::GetNozzleGroupResult(Slic3r::GUI::Plater *plater)
{
if (plater && plater->background_process().get_current_gcode_result()) {
return plater->background_process().get_current_gcode_result()->nozzle_group_result;
@@ -19,6 +32,29 @@ std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> DevUtilBackend::GetNozz
return nullptr;
}
std::unordered_map<NozzleDef, int> DevUtilBackend::CollectNozzleInfo(MultiNozzleUtils::NozzleGroupResultBase *nozzle_group_res, int logic_ext_id)
{
std::unordered_map<NozzleDef, int> need_nozzle_map;
if (!nozzle_group_res) {
return need_nozzle_map;
}
const std::vector<Slic3r::MultiNozzleUtils::NozzleInfo>& nozzle_vec = nozzle_group_res->get_used_nozzles_in_extruder(logic_ext_id);
for (auto slicing_nozzle : nozzle_vec) {
try {
NozzleDef data;
data.nozzle_diameter = boost::lexical_cast<float>(slicing_nozzle.diameter);
data.nozzle_flow_type = DevNozzle::ToNozzleFlowType(slicing_nozzle.volume_type);
need_nozzle_map[data]++;
} catch (const std::exception& e) {
assert(0);
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "exception: " << e.what();
}
}
return need_nozzle_map;
}
static std::unordered_map<std::string, DevAmsType> s_ams_type_map = {
{"0", DevAmsType::N3F},
{"1", DevAmsType::N3S},
@@ -41,6 +77,7 @@ std::optional<Slic3r::DevFilamentDryingPreset> DevUtilBackend::GetFilamentDrying
std::vector<std::string> types = config.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations")->values;
for (auto type : types) {
if (s_ams_type_map.count(type) == 0) {
// assert(0);
continue;
}
info.ams_limitations.insert(s_ams_type_map[type]);
@@ -62,10 +99,10 @@ std::optional<Slic3r::DevFilamentDryingPreset> DevUtilBackend::GetFilamentDrying
}
if (config.has("filament_dev_drying_softening_temperature")) {
info.filament_dev_drying_softening_temperature = config.option<ConfigOptionFloats>("filament_dev_drying_softening_temperature")->get_at(0);
info.filament_dev_drying_softening_temperature = config.option<ConfigOptionFloats>("filament_dev_drying_softening_temperature")->get_at(0);
}
if (config.has("filament_dev_ams_drying_heat_distortion_temperature")) {
if (config.has("filament_dev_ams_drying_heat_distortion_temperature")){
info.filament_dev_ams_drying_heat_distortion_temperature = config.option<ConfigOptionFloats>("filament_dev_ams_drying_heat_distortion_temperature")->get_at(0);
}
@@ -83,4 +120,4 @@ std::optional<Slic3r::DevFilamentDryingPreset> DevUtilBackend::GetFilamentDrying
return std::nullopt;
}
}; // namespace Slic3r
};// namespace Slic3r

View File

@@ -1,19 +1,32 @@
/**
* @file DevUtilBackend.h
* @brief Provides common static utility methods for backend (preset/slicing).
*
* This class offers a collection of static helper functions such as string manipulation,
* file operations, and other frequently used utilities.
*/
#pragma once
#include "DevDefs.h"
#include "DevNozzleSystem.h"
#include "DevFilaSystem.h"
#include "libslic3r/MultiNozzleUtils.hpp"
#include <optional>
#include <string>
#include <unordered_map>
// Forward declarations
namespace Slic3r
{
class MachineObject;
namespace GUI
{
class Plater;
}
}; // namespace Slic3r::GUI
namespace Slic3r
{
namespace GUI { class Plater; }
class DevUtilBackend
{
@@ -21,14 +34,14 @@ public:
DevUtilBackend() = delete;
public:
static MultiNozzleUtils::NozzleInfo GetNozzleInfo(const DevNozzle& dev_nozzle);
// for rack: the slicer's per-filament -> logical-nozzle grouping for the current plate, read off
// the post-slice GCodeProcessorResult (plater->background_process().get_current_gcode_result()).
// Returns nullptr when there is no plater / no current result.
static std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> GetNozzleGroupResult(Slic3r::GUI::Plater* plater);
// for rack
static std::shared_ptr<MultiNozzleUtils::NozzleGroupResultBase> GetNozzleGroupResult(Slic3r::GUI::Plater *plater);
static std::unordered_map<NozzleDef, int> CollectNozzleInfo(MultiNozzleUtils::NozzleGroupResultBase *nozzle_group_res, int logic_ext_id);
// for filament preset
static std::optional<DevFilamentDryingPreset> GetFilamentDryingPreset(const std::string& fila_id);
};
}; // namespace Slic3r
}; // namespace Slic3r