298 lines
13 KiB
C++
298 lines
13 KiB
C++
#include <algorithm>
|
|
#include <wx/sizer.h>
|
|
#include "libslic3r/FlushVolCalc.hpp"
|
|
#include "WipeTowerDialog.hpp"
|
|
#include "GUI.hpp"
|
|
#include "I18N.hpp"
|
|
#include "GUI_App.hpp"
|
|
#include "libslic3r/Config.hpp"
|
|
|
|
|
|
using namespace Slic3r;
|
|
using namespace Slic3r::GUI;
|
|
|
|
static const float g_min_flush_multiplier = 0.f;
|
|
static const float g_max_flush_multiplier = 3.f;
|
|
|
|
static std::vector<float> MatrixFlatten(const WipingDialog::VolumeMatrix& matrix) {
|
|
std::vector<float> vec;
|
|
for (auto row_elems : matrix) {
|
|
for (auto elem : row_elems)
|
|
vec.emplace_back(elem);
|
|
}
|
|
return vec;
|
|
}
|
|
|
|
wxString WipingDialog::BuildTableObjStr()
|
|
{
|
|
auto full_config = wxGetApp().preset_bundle->full_config();
|
|
auto filament_colors = full_config.option<ConfigOptionStrings>("filament_colour")->values;
|
|
auto flush_multiplier = full_config.option<ConfigOptionFloats>("flush_multiplier")->values;
|
|
int nozzle_num = full_config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values.size();
|
|
auto raw_matrix_data = full_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values;
|
|
std::vector<std::vector<double>> flush_matrixs;
|
|
for (int idx = 0; idx < nozzle_num; ++idx) {
|
|
flush_matrixs.emplace_back(get_flush_volumes_matrix(raw_matrix_data, idx, nozzle_num));
|
|
}
|
|
flush_multiplier.resize(nozzle_num, 1);
|
|
|
|
m_raw_matrixs = flush_matrixs;
|
|
m_flush_multipliers = flush_multiplier;
|
|
|
|
json obj;
|
|
obj["flush_multiplier"] = flush_multiplier;
|
|
obj["extruder_num"] = nozzle_num;
|
|
obj["filament_colors"] = filament_colors;
|
|
obj["flush_volume_matrixs"] = json::array();
|
|
obj["min_flush_volumes"] = json::array();
|
|
obj["max_flush_volumes"] = json::array();
|
|
obj["min_flush_multiplier"] = g_min_flush_multiplier;
|
|
obj["max_flush_multiplier"] = g_max_flush_multiplier;
|
|
obj["is_dark_mode"] = wxGetApp().dark_mode();
|
|
|
|
for (const auto& vec : flush_matrixs) {
|
|
obj["flush_volume_matrixs"].push_back(vec);
|
|
}
|
|
|
|
for (int idx = 0; idx < nozzle_num; ++idx) {
|
|
obj["min_flush_volumes"].push_back(*min_element(m_extra_flush_volume[idx].begin(), m_extra_flush_volume[idx].end()));
|
|
obj["max_flush_volumes"].push_back(m_max_flush_volume);
|
|
}
|
|
|
|
auto obj_str = obj.dump();
|
|
return obj_str;
|
|
}
|
|
|
|
wxString WipingDialog::BuildTextObjStr()
|
|
{
|
|
wxString auto_flush_tip = _L("Studio would re-calculate your flushing volumes everytime the filaments color changed or filaments changed. You could disable the auto-calculate in Bambu Studio > Preferences");
|
|
wxString volume_desp_panel = _L("Flushing volume (mm³) for each filament pair.");
|
|
wxString volume_range_panel = wxString::Format(_L("Suggestion: Flushing Volume in range [%d, %d]"), 0, 700);
|
|
wxString multiplier_range_panel = wxString::Format(_L("The multiplier should be in range [%.2f, %.2f]."), 0, 3);
|
|
wxString calc_btn_panel = _L("Re-calculate");
|
|
wxString extruder_label_0 = _L("Left extruder");
|
|
wxString extruder_label_1 = _L("Right extruder");
|
|
wxString multiplier_label = _L("Multiplier");
|
|
wxString ok_btn_label = _L("OK");
|
|
wxString cancel_btn_label = _L("Cancel");
|
|
|
|
wxString text_obj = "{";
|
|
text_obj += wxString::Format("\"volume_desp_panel\":\"%s\",", volume_desp_panel);
|
|
text_obj += wxString::Format("\"volume_range_panel\":\"%s\",", volume_range_panel);
|
|
text_obj += wxString::Format("\"multiplier_range_panel\":\"%s\",", multiplier_range_panel);
|
|
text_obj += wxString::Format("\"calc_btn_panel\":\"%s\",", calc_btn_panel);
|
|
text_obj += wxString::Format("\"extruder_label_0\":\"%s\",", extruder_label_0);
|
|
text_obj += wxString::Format("\"extruder_label_1\":\"%s\",", extruder_label_1);
|
|
text_obj += wxString::Format("\"multiplier_label\":\"%s\",", multiplier_label);
|
|
text_obj += wxString::Format("\"ok_btn_label\":\"%s\",", ok_btn_label);
|
|
text_obj += wxString::Format("\"cancel_btn_label\":\"%s\",", cancel_btn_label);
|
|
text_obj += wxString::Format("\"auto_flush_tip\":\"%s\"", auto_flush_tip);
|
|
text_obj += "}";
|
|
return text_obj;
|
|
}
|
|
|
|
WipingDialog::WipingDialog(wxWindow* parent, const std::vector<std::vector<int>>& extra_flush_volume,const int max_flush_volume) :
|
|
wxDialog(parent, wxID_ANY, _(L("Flushing volumes for filament change")),
|
|
wxDefaultPosition, wxDefaultSize,
|
|
wxDEFAULT_DIALOG_STYLE ),
|
|
m_extra_flush_volume(extra_flush_volume),
|
|
m_max_flush_volume(max_flush_volume)
|
|
{
|
|
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % Slic3r::resources_dir()).str();
|
|
SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
|
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
|
this->SetSizer(main_sizer);
|
|
|
|
auto filament_count= wxGetApp().preset_bundle->project_config.option<ConfigOptionStrings>("filament_colour")->values.size();
|
|
wxSize extra_size = { FromDIP(100),FromDIP(235) };
|
|
if (filament_count <= 2)
|
|
extra_size.y += FromDIP(16) * 3 + FromDIP(32);
|
|
else if (filament_count == 3)
|
|
extra_size.y += FromDIP(16) * 3;
|
|
else if (4 <= filament_count && filament_count <= 8)
|
|
extra_size.y += FromDIP(16) * 2;
|
|
else
|
|
extra_size.y += FromDIP(16);
|
|
|
|
wxSize max_scroll_size = { FromDIP(1000),FromDIP(500) };
|
|
wxSize estimate_size = { (int)(filament_count + 1) * FromDIP(60),(int)(filament_count + 1) * FromDIP(30)+FromDIP(2)};
|
|
wxSize scroll_size ={ std::min(max_scroll_size.x,estimate_size.x),std::min(max_scroll_size.y,estimate_size.y) };
|
|
wxSize applied_size = scroll_size + extra_size;
|
|
|
|
wxSize scaled_screen_size = wxGetDisplaySize();
|
|
double scale_factor = wxDisplay().GetScaleFactor();
|
|
scaled_screen_size = { (int)(scaled_screen_size.x / scale_factor),(int)(scaled_screen_size.y / scale_factor) };
|
|
|
|
applied_size = { std::min(applied_size.x,scaled_screen_size.x),std::min(applied_size.y,scaled_screen_size.y) };
|
|
m_webview = wxWebView::New(this, wxID_ANY,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
applied_size,
|
|
wxWebViewBackendDefault,
|
|
wxNO_BORDER);
|
|
|
|
m_webview->AddScriptMessageHandler("wipingDialog");
|
|
main_sizer->Add(m_webview, 1);
|
|
|
|
fs::path filepath = fs::path(resources_dir()) / "web/flush/WipingDialog.html";
|
|
wxString filepath_str = wxString::FromUTF8(filepath.string());
|
|
wxFileName fn(filepath_str);
|
|
if(fn.FileExists()) {
|
|
wxString url = "file:///" + fn.GetFullPath();
|
|
m_webview->LoadURL(url);
|
|
} else {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< "WipingDialog.html not exist";
|
|
}
|
|
|
|
main_sizer->SetSizeHints(this);
|
|
main_sizer->Fit(this);
|
|
CenterOnParent();
|
|
|
|
//m_webview->Bind(wxEVT_WEBVIEW_NAVIGATED, [this](auto& evt) {
|
|
// auto table_obj_str = BuildTableObjStr();
|
|
// auto text_obj_str = BuildTextObjStr();
|
|
// CallAfter([table_obj_str, text_obj_str, this] {
|
|
// wxString script = wxString::Format("buildTable(%s);buildText(%s)", table_obj_str, text_obj_str);
|
|
// m_webview->RunScript(script);
|
|
// });
|
|
// });
|
|
|
|
m_webview->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, [this](wxWebViewEvent& evt) {
|
|
std::string message = evt.GetString().ToStdString();
|
|
try {
|
|
json j = json::parse(message);
|
|
if (j["msg"].get<std::string>() == "init") {
|
|
auto table_obj_str = BuildTableObjStr();
|
|
auto text_obj_str = BuildTextObjStr();
|
|
CallAfter([table_obj_str, text_obj_str, this] {
|
|
wxString script = wxString::Format("buildTable(%s);buildText(%s)", table_obj_str, text_obj_str);
|
|
m_webview->RunScript(script);
|
|
});
|
|
}
|
|
else if (j["msg"].get<std::string>() == "updateMatrix") {
|
|
int extruder_id = j["extruder_id"].get<int>();
|
|
auto new_matrix = CalcFlushingVolumes(extruder_id);
|
|
json obj;
|
|
obj["flush_volume_matrix"] = MatrixFlatten(new_matrix);
|
|
obj["extruder_id"] = extruder_id;
|
|
CallAfter([obj, this] {
|
|
std::string flush_volume_matrix_str = obj["flush_volume_matrix"].dump();
|
|
std::string extruder_id_str = std::to_string(obj["extruder_id"].get<int>());
|
|
wxString script = wxString::Format("updateTable(%s,%s)", flush_volume_matrix_str, extruder_id_str);
|
|
m_webview->RunScript(script);
|
|
});
|
|
}
|
|
else if (j["msg"].get<std::string>() == "storeData") {
|
|
int extruder_num = j["number_of_extruders"].get<int>();
|
|
std::vector<std::vector<double>> store_matrixs;
|
|
for (auto iter = j["raw_matrix"].begin(); iter != j["raw_matrix"].end(); ++iter) {
|
|
store_matrixs.emplace_back((*iter).get<std::vector<double>>());
|
|
}
|
|
std::vector<double>store_multipliers = j["flush_multiplier"].get<std::vector<double>>();
|
|
this->StoreFlushData(extruder_num, store_matrixs, store_multipliers);
|
|
m_submit_flag = true;
|
|
this->Close();
|
|
}
|
|
else if (j["msg"].get<std::string>() == "quit") {
|
|
this->Close();
|
|
}
|
|
}
|
|
catch (...) {
|
|
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
int WipingDialog::CalcFlushingVolume(const wxColour& from, const wxColour& to, int min_flush_volume)
|
|
{
|
|
Slic3r::FlushVolCalculator calculator(min_flush_volume, Slic3r::g_max_flush_volume);
|
|
return calculator.calc_flush_vol(from.Alpha(), from.Red(), from.Green(), from.Blue(), to.Alpha(), to.Red(), to.Green(), to.Blue());
|
|
}
|
|
|
|
WipingDialog::VolumeMatrix WipingDialog::CalcFlushingVolumes(int extruder_id)
|
|
{
|
|
auto& preset_bundle = wxGetApp().preset_bundle;
|
|
auto full_config = preset_bundle->full_config();
|
|
auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment;
|
|
|
|
std::vector<std::string> filament_color_strs = full_config.option<ConfigOptionStrings>("filament_colour")->values;
|
|
std::vector<std::vector<wxColour>> multi_colors;
|
|
std::vector<wxColour> filament_colors;
|
|
for (auto color_str : filament_color_strs)
|
|
filament_colors.emplace_back(color_str);
|
|
|
|
// Support for multi-color filament
|
|
for (int i = 0; i < filament_colors.size(); ++i) {
|
|
std::vector<wxColour> single_filament;
|
|
if (i < ams_multi_color_filament.size()) {
|
|
if (!ams_multi_color_filament[i].empty()) {
|
|
std::vector<std::string> colors = ams_multi_color_filament[i];
|
|
for (int j = 0; j < colors.size(); ++j) {
|
|
single_filament.push_back(wxColour(colors[j]));
|
|
}
|
|
multi_colors.push_back(single_filament);
|
|
continue;
|
|
}
|
|
}
|
|
single_filament.push_back(wxColour(filament_colors[i]));
|
|
multi_colors.push_back(single_filament);
|
|
}
|
|
|
|
VolumeMatrix matrix;
|
|
|
|
for (int from_idx = 0; from_idx < multi_colors.size(); ++from_idx) {
|
|
bool is_from_support = is_support_filament(from_idx);
|
|
matrix.emplace_back();
|
|
for (int to_idx = 0; to_idx < multi_colors.size(); ++to_idx) {
|
|
if (from_idx == to_idx) {
|
|
matrix.back().emplace_back(0);
|
|
continue;
|
|
}
|
|
|
|
bool is_to_support = is_support_filament(to_idx);
|
|
|
|
int flushing_volume = 0;
|
|
if (is_to_support) {
|
|
flushing_volume = Slic3r::g_flush_volume_to_support;
|
|
}
|
|
else {
|
|
for (int i = 0; i < multi_colors[from_idx].size(); ++i) {
|
|
const wxColour& from = multi_colors[from_idx][i];
|
|
for (int j = 0; j < multi_colors[to_idx].size(); ++j) {
|
|
const wxColour& to = multi_colors[to_idx][j];
|
|
int volume = CalcFlushingVolume(from, to, m_extra_flush_volume[extruder_id][from_idx]);
|
|
flushing_volume = std::max(flushing_volume, volume);
|
|
}
|
|
}
|
|
|
|
if (is_from_support) {
|
|
flushing_volume = std::max(Slic3r::g_min_flush_volume_from_support, flushing_volume);
|
|
}
|
|
}
|
|
matrix.back().emplace_back(flushing_volume);
|
|
}
|
|
}
|
|
return matrix;
|
|
}
|
|
|
|
void WipingDialog::StoreFlushData(int extruder_num, const std::vector<std::vector<double>>& flush_volume_vecs, const std::vector<double>&flush_multipliers)
|
|
{
|
|
m_flush_multipliers = flush_multipliers;
|
|
m_raw_matrixs = flush_volume_vecs;
|
|
}
|
|
|
|
std::vector<double> WipingDialog::GetFlattenMatrix()const
|
|
{
|
|
std::vector<double> ret;
|
|
for (auto& matrix : m_raw_matrixs) {
|
|
ret.insert(ret.end(), matrix.begin(), matrix.end());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
std::vector<double> WipingDialog::GetMultipliers()const
|
|
{
|
|
return m_flush_multipliers;
|
|
} |