2022-07-15 15:37:19 +00:00
# include <algorithm>
2025-02-25 07:26:10 +00:00
# include <wx/sizer.h>
2023-06-16 09:31:11 +00:00
# include "libslic3r/FlushVolCalc.hpp"
2022-07-15 15:37:19 +00:00
# include "WipeTowerDialog.hpp"
# include "GUI.hpp"
# include "I18N.hpp"
# include "GUI_App.hpp"
2023-12-14 11:50:40 +00:00
# include "libslic3r/Config.hpp"
2022-07-15 15:37:19 +00:00
2023-12-14 11:50:40 +00:00
using namespace Slic3r ;
2022-10-25 10:47:58 +00:00
using namespace Slic3r : : GUI ;
2022-12-05 01:14:52 +00:00
static const float g_min_flush_multiplier = 0.f ;
static const float g_max_flush_multiplier = 3.f ;
2022-07-15 15:37:19 +00:00
2025-02-25 07:26:10 +00:00
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 ) ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
return vec ;
2023-05-25 03:53:44 +00:00
}
2023-08-18 06:06:19 +00:00
2025-02-25 07:26:10 +00:00
wxString WipingDialog : : BuildTableObjStr ( )
2023-05-25 03:53:44 +00:00
{
2025-02-25 07:26:10 +00:00
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 ) ) ;
2023-05-25 03:53:44 +00:00
}
2025-02-25 07:26:10 +00:00
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 ) ;
2022-07-15 15:37:19 +00:00
}
2023-08-18 06:06:19 +00:00
2025-02-25 07:26:10 +00:00
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 ) ;
2023-01-17 10:06:45 +00:00
}
2022-11-04 03:28:05 +00:00
2025-02-25 07:26:10 +00:00
auto obj_str = obj . dump ( ) ;
return obj_str ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
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 ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
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 )
2022-07-15 15:37:19 +00:00
{
2025-02-25 07:26:10 +00:00
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 appied_size = scroll_size + extra_size ;
m_webview = wxWebView : : New ( this , wxID_ANY ,
wxEmptyString ,
wxDefaultPosition ,
appied_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 " ;
2022-07-15 15:37:19 +00:00
}
2022-10-25 10:47:58 +00:00
2025-02-25 07:26:10 +00:00
main_sizer - > SetSizeHints ( this ) ;
main_sizer - > Fit ( this ) ;
CenterOnParent ( ) ;
2022-07-15 15:37:19 +00:00
2025-02-25 07:26:10 +00:00
//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 ) ;
} ) ;
2024-05-06 10:15:30 +00:00
}
2025-02-25 07:26:10 +00:00
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 ) ;
} ) ;
2024-06-17 12:34:18 +00:00
}
2025-02-25 07:26:10 +00:00
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 > > ( ) ) ;
2023-01-17 10:06:45 +00:00
}
2025-02-25 07:26:10 +00:00
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 ( ) ;
2023-01-17 10:06:45 +00:00
}
2025-02-25 07:26:10 +00:00
else if ( j [ " msg " ] . get < std : : string > ( ) = = " quit " ) {
this - > Close ( ) ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
}
catch ( . . . ) {
2022-07-15 15:37:19 +00:00
2025-02-25 07:26:10 +00:00
}
} ) ;
2022-07-15 15:37:19 +00:00
}
2022-07-22 09:46:10 +00:00
2025-02-25 07:26:10 +00:00
int WipingDialog : : CalcFlushingVolume ( const wxColour & from , const wxColour & to , int min_flush_volume )
2022-12-05 01:14:52 +00:00
{
2025-02-25 07:26:10 +00:00
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 ( ) ) ;
2022-07-22 09:46:10 +00:00
}
2025-02-25 07:26:10 +00:00
WipingDialog : : VolumeMatrix WipingDialog : : CalcFlushingVolumes ( int extruder_id )
2022-07-22 09:46:10 +00:00
{
2025-02-25 07:26:10 +00:00
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 ;
2023-12-14 11:50:40 +00:00
std : : vector < std : : vector < wxColour > > multi_colors ;
2025-02-25 07:26:10 +00:00
std : : vector < wxColour > filament_colors ;
for ( auto color_str : filament_color_strs )
filament_colors . emplace_back ( color_str ) ;
2023-12-14 11:50:40 +00:00
// Support for multi-color filament
2025-02-25 07:26:10 +00:00
for ( int i = 0 ; i < filament_colors . size ( ) ; + + i ) {
2023-12-14 11:50:40 +00:00
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 ;
}
}
2025-02-25 07:26:10 +00:00
single_filament . push_back ( wxColour ( filament_colors [ i ] ) ) ;
2023-12-14 11:50:40 +00:00
multi_colors . push_back ( single_filament ) ;
}
2025-02-25 07:26:10 +00:00
VolumeMatrix matrix ;
2023-12-14 11:50:40 +00:00
for ( int from_idx = 0 ; from_idx < multi_colors . size ( ) ; + + from_idx ) {
2022-07-22 09:46:10 +00:00
bool is_from_support = is_support_filament ( from_idx ) ;
2025-02-25 07:26:10 +00:00
matrix . emplace_back ( ) ;
2023-12-14 11:50:40 +00:00
for ( int to_idx = 0 ; to_idx < multi_colors . size ( ) ; + + to_idx ) {
2022-07-22 09:46:10 +00:00
if ( from_idx = = to_idx ) {
2025-02-25 07:26:10 +00:00
matrix . back ( ) . emplace_back ( 0 ) ;
continue ;
2022-07-22 09:46:10 +00:00
}
2025-02-25 07:26:10 +00:00
bool is_to_support = is_support_filament ( to_idx ) ;
2022-07-22 09:46:10 +00:00
2025-02-25 07:26:10 +00:00
int flushing_volume = 0 ;
if ( is_to_support ) {
flushing_volume = Slic3r : : g_flush_volume_to_support ;
2023-04-10 02:13:49 +00:00
}
else {
2025-02-25 07:26:10 +00:00
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 ) ;
}
}
2024-06-17 12:34:18 +00:00
2025-02-25 07:26:10 +00:00
if ( is_from_support ) {
flushing_volume = std : : max ( Slic3r : : g_min_flush_volume_from_support , flushing_volume ) ;
}
2024-06-17 12:34:18 +00:00
}
2025-02-25 07:26:10 +00:00
matrix . back ( ) . emplace_back ( flushing_volume ) ;
2024-06-17 12:34:18 +00:00
}
}
2025-02-25 07:26:10 +00:00
return matrix ;
2024-06-17 12:34:18 +00:00
}
2025-02-25 07:26:10 +00:00
void WipingDialog : : StoreFlushData ( int extruder_num , const std : : vector < std : : vector < double > > & flush_volume_vecs , const std : : vector < double > & flush_multipliers )
2024-06-17 12:34:18 +00:00
{
2025-02-25 07:26:10 +00:00
m_flush_multipliers = flush_multipliers ;
m_raw_matrixs = flush_volume_vecs ;
2024-06-17 12:34:18 +00:00
}
2022-07-15 15:37:19 +00:00
2025-02-25 07:26:10 +00:00
std : : vector < double > WipingDialog : : GetFlattenMatrix ( ) const
{
std : : vector < double > ret ;
for ( auto & matrix : m_raw_matrixs ) {
ret . insert ( ret . end ( ) , matrix . begin ( ) , matrix . end ( ) ) ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
return ret ;
2022-07-15 15:37:19 +00:00
}
2025-02-25 07:26:10 +00:00
std : : vector < double > WipingDialog : : GetMultipliers ( ) const
{
return m_flush_multipliers ;
}