From 7880c20330065d7a3a8623a3be29aecf81e2412c Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 9 Dec 2021 11:43:49 +0100 Subject: [PATCH 1/4] wider SLA material type in conf wizard --- src/slic3r/GUI/ConfigWizard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 5794812015..04d95952a5 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -627,7 +627,7 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin list_printer->SetMinSize(wxSize(23*em, list_h)); - list_type->SetMinSize(wxSize(8*em, list_h)); + list_type->SetMinSize(wxSize(13*em, list_h)); list_vendor->SetMinSize(wxSize(13*em, list_h)); list_profile->SetMinSize(wxSize(23*em, list_h)); From 27883caa08983f7c963cad8f185e3e45fc1432eb Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 9 Dec 2021 14:16:17 +0100 Subject: [PATCH 2/4] Follow-up https://github.com/prusa3d/PrusaSlicer/commit/b3074ad2cce49ab9ca929faf42ad5721f1b76849 Change random values of the S and V in HSV colors. To avoid generation of the extremely light or dark colors we use now generated values from the range [0.65; 0.1] --- src/slic3r/GUI/DoubleSlider.cpp | 22 +- src/slic3r/GUI/DoubleSlider.hpp | 2 + src/slic3r/GUI/DoubleSlider_Utils.hpp | 310 ++++++++++++++------------ 3 files changed, 176 insertions(+), 158 deletions(-) diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 5b0cf430c9..3d914d5b66 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -1,6 +1,5 @@ #include "libslic3r/libslic3r.h" #include "DoubleSlider.hpp" -#include "DoubleSlider_Utils.hpp" #include "libslic3r/GCode.hpp" #include "GUI.hpp" #include "GUI_App.hpp" @@ -27,7 +26,6 @@ #include #include #include -#include #include "Field.hpp" #include "format.hpp" #include "NotificationManager.hpp" @@ -2562,7 +2560,7 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) { #if 1 if (ticks.empty()) - return get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color((*m_colors)[0]); auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick); if (before_tick_it == ticks.end()) @@ -2571,24 +2569,24 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (--before_tick_it; before_tick_it->type == ColorChange) break; if (before_tick_it->type == ColorChange) - return get_opposite_color(before_tick_it->color); - return get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color((*m_colors)[0]); } if (before_tick_it == ticks.begin()) { const std::string& frst_color = (*m_colors)[0]; if (before_tick_it->type == ColorChange) - return get_opposite_color(frst_color, before_tick_it->color); + return color_generator.get_opposite_color(frst_color, before_tick_it->color); auto next_tick_it = before_tick_it; while (next_tick_it != ticks.end()) if (++next_tick_it; next_tick_it->type == ColorChange) break; if (next_tick_it->type == ColorChange) - return get_opposite_color(frst_color, next_tick_it->color); + return color_generator.get_opposite_color(frst_color, next_tick_it->color); - return get_opposite_color(frst_color); + return color_generator.get_opposite_color(frst_color); } std::string frst_color = ""; @@ -2609,13 +2607,13 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (before_tick_it->type == ColorChange) { if (frst_color.empty()) - return get_opposite_color(before_tick_it->color); - return get_opposite_color(before_tick_it->color, frst_color); + return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color(before_tick_it->color, frst_color); } if (frst_color.empty()) - return get_opposite_color((*m_colors)[0]); - return get_opposite_color((*m_colors)[0], frst_color); + return color_generator.get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color((*m_colors)[0], frst_color); #else const std::vector& colors = ColorPrintColors::get(); if (ticks.empty()) diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index e0f713d879..23275cf2ad 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -3,6 +3,7 @@ #include "libslic3r/CustomGCode.hpp" #include "wxExtensions.hpp" +#include "DoubleSlider_Utils.hpp" #include #include @@ -118,6 +119,7 @@ class TickCodeInfo // int m_default_color_idx = 0; std::vector* m_colors {nullptr}; + ColorGenerator color_generator; std::string get_color_for_tick(TickCode tick, Type type, const int extruder); diff --git a/src/slic3r/GUI/DoubleSlider_Utils.hpp b/src/slic3r/GUI/DoubleSlider_Utils.hpp index 704eb5a878..b5955f2fc4 100644 --- a/src/slic3r/GUI/DoubleSlider_Utils.hpp +++ b/src/slic3r/GUI/DoubleSlider_Utils.hpp @@ -1,173 +1,191 @@ #include +#include + #include "wx/colour.h" -// next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both - -typedef struct { - double r; // a fraction between 0 and 1 - double g; // a fraction between 0 and 1 - double b; // a fraction between 0 and 1 -} rgb; - -typedef struct { - double h; // angle in degrees - double s; // a fraction between 0 and 1 - double v; // a fraction between 0 and 1 -} hsv; - -static hsv rgb2hsv(rgb in); -static rgb hsv2rgb(hsv in); - -hsv rgb2hsv(rgb in) +class ColorGenerator { - hsv out; - double min, max, delta; + // Some of next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both + typedef struct { + double r; // a fraction between 0 and 1 + double g; // a fraction between 0 and 1 + double b; // a fraction between 0 and 1 + } rgb; - min = in.r < in.g ? in.r : in.g; - min = min < in.b ? min : in.b; + typedef struct { + double h; // angle in degrees + double s; // a fraction between 0 and 1 + double v; // a fraction between 0 and 1 + } hsv; - max = in.r > in.g ? in.r : in.g; - max = max > in.b ? max : in.b; + //static hsv rgb2hsv(rgb in); + //static rgb hsv2rgb(hsv in); - out.v = max; // v - delta = max - min; - if (delta < 0.00001) + hsv rgb2hsv(rgb in) { - out.s = 0; - out.h = 0; // undefined, maybe nan? + hsv out; + double min, max, delta; + + min = in.r < in.g ? in.r : in.g; + min = min < in.b ? min : in.b; + + max = in.r > in.g ? in.r : in.g; + max = max > in.b ? max : in.b; + + out.v = max; // v + delta = max - min; + if (delta < 0.00001) + { + out.s = 0; + out.h = 0; // undefined, maybe nan? + return out; + } + if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash + out.s = (delta / max); // s + } + else { + // if max is 0, then r = g = b = 0 + // s = 0, h is undefined + out.s = 0.0; + out.h = NAN; // its now undefined + return out; + } + if (in.r >= max) // > is bogus, just keeps compilor happy + out.h = (in.g - in.b) / delta; // between yellow & magenta + else + if (in.g >= max) + out.h = 2.0 + (in.b - in.r) / delta; // between cyan & yellow + else + out.h = 4.0 + (in.r - in.g) / delta; // between magenta & cyan + + out.h *= 60.0; // degrees + + if (out.h < 0.0) + out.h += 360.0; + return out; } - if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash - out.s = (delta / max); // s - } else { - // if max is 0, then r = g = b = 0 - // s = 0, h is undefined - out.s = 0.0; - out.h = NAN; // its now undefined + + hsv rgb2hsv(const std::string& str_clr_in) + { + wxColour clr(str_clr_in); + rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 }; + return rgb2hsv(in); + } + + + rgb hsv2rgb(hsv in) + { + double hh, p, q, t, ff; + long i; + rgb out; + + if (in.s <= 0.0) { // < is bogus, just shuts up warnings + out.r = in.v; + out.g = in.v; + out.b = in.v; + return out; + } + hh = in.h; + if (hh >= 360.0) hh -= 360.0;//hh = 0.0; + hh /= 60.0; + i = (long)hh; + ff = hh - i; + p = in.v * (1.0 - in.s); + q = in.v * (1.0 - (in.s * ff)); + t = in.v * (1.0 - (in.s * (1.0 - ff))); + + switch (i) { + case 0: + out.r = in.v; + out.g = t; + out.b = p; + break; + case 1: + out.r = q; + out.g = in.v; + out.b = p; + break; + case 2: + out.r = p; + out.g = in.v; + out.b = t; + break; + + case 3: + out.r = p; + out.g = q; + out.b = in.v; + break; + case 4: + out.r = t; + out.g = p; + out.b = in.v; + break; + case 5: + default: + out.r = in.v; + out.g = p; + out.b = q; + break; + } return out; } - if( in.r >= max ) // > is bogus, just keeps compilor happy - out.h = ( in.g - in.b ) / delta; // between yellow & magenta - else - if( in.g >= max ) - out.h = 2.0 + ( in.b - in.r ) / delta; // between cyan & yellow - else - out.h = 4.0 + ( in.r - in.g ) / delta; // between magenta & cyan - out.h *= 60.0; // degrees + std::random_device rd; - if( out.h < 0.0 ) - out.h += 360.0; +public: - return out; -} + ColorGenerator() {} + ~ColorGenerator() {} -hsv rgb2hsv(const std::string& str_clr_in) -{ - wxColour clr(str_clr_in); - rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 }; - return rgb2hsv(in); -} + double rand_val() + { + std::mt19937 rand_generator(rd()); - -rgb hsv2rgb(hsv in) -{ - double hh, p, q, t, ff; - long i; - rgb out; - - if(in.s <= 0.0) { // < is bogus, just shuts up warnings - out.r = in.v; - out.g = in.v; - out.b = in.v; - return out; + // this value will be used for Saturation and Value + // to avoid extremely light/dark colors, take this value from range [0.65; 1.0] + std::uniform_real_distribution distrib(0.65, 1.0); + return distrib(rand_generator); } - hh = in.h; - if (hh >= 360.0) hh -= 360.0;//hh = 0.0; - hh /= 60.0; - i = (long)hh; - ff = hh - i; - p = in.v * (1.0 - in.s); - q = in.v * (1.0 - (in.s * ff)); - t = in.v * (1.0 - (in.s * (1.0 - ff))); - switch(i) { - case 0: - out.r = in.v; - out.g = t; - out.b = p; - break; - case 1: - out.r = q; - out.g = in.v; - out.b = p; - break; - case 2: - out.r = p; - out.g = in.v; - out.b = t; - break; - case 3: - out.r = p; - out.g = q; - out.b = in.v; - break; - case 4: - out.r = t; - out.g = p; - out.b = in.v; - break; - case 5: - default: - out.r = in.v; - out.g = p; - out.b = q; - break; + std::string get_opposite_color(const std::string& color) + { + std::string opp_color = ""; + + hsv hsv_clr = rgb2hsv(color); + hsv_clr.h += 65; // 65 instead 60 to avoid circle values + hsv_clr.s = rand_val(); + hsv_clr.v = rand_val(); + + rgb rgb_opp_color = hsv2rgb(hsv_clr); + + wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); + opp_color = clr_str.ToStdString(); + + return opp_color; } - return out; -} -double rand_val() -{ - return 0.1 * (10 - rand() % 8); -} + std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd) + { + std::string opp_color = ""; -std::string get_opposite_color(const std::string& color) -{ - std::string opp_color = ""; + hsv hsv_frst = rgb2hsv(color_frst); + hsv hsv_scnd = rgb2hsv(color_scnd); - hsv hsv_clr = rgb2hsv(color); - hsv_clr.h += 65; // 65 instead 60 to avoid circle values - hsv_clr.s = rand_val(); - hsv_clr.v = rand_val(); + double delta_h = fabs(hsv_frst.h - hsv_scnd.h); + double start_h = delta_h > 180 ? std::min(hsv_scnd.h, hsv_frst.h) : std::max(hsv_scnd.h, hsv_frst.h); + start_h += 5; // to avoid circle change of colors for 120 deg + if (delta_h < 180) + delta_h = 360 - delta_h; - rgb rgb_opp_color = hsv2rgb(hsv_clr); + hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() }; + rgb rgb_opp_color = hsv2rgb(hsv_opp); - wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); - opp_color = clr_str.ToStdString(); + wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); + opp_color = clr_str.ToStdString(); - return opp_color; -} - -std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd) -{ - std::string opp_color = ""; - - hsv hsv_frst = rgb2hsv(color_frst); - hsv hsv_scnd = rgb2hsv(color_scnd); - - double delta_h = fabs(hsv_frst.h - hsv_scnd.h); - double start_h = delta_h > 180 ? std::min(hsv_scnd.h, hsv_frst.h) : std::max(hsv_scnd.h, hsv_frst.h); - start_h += 5; // to avoid circle change of colors for 120 deg - if (delta_h < 180) - delta_h = 360 - delta_h; - - hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() }; - rgb rgb_opp_color = hsv2rgb(hsv_opp); - - wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); - opp_color = clr_str.ToStdString(); - - return opp_color; -} \ No newline at end of file + return opp_color; + } +}; \ No newline at end of file From f1429f026c04af53749cec547929cc1cb97de83b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 9 Dec 2021 16:00:12 +0100 Subject: [PATCH 3/4] RichMessageDialog on non-MSW platforms: Set escape ID to wxID_CANCEL + Fixed behavior of the "Open hyperlink" dialog when "cross"(close window button) is clicked. --- src/slic3r/GUI/MsgDialog.hpp | 4 +++- src/slic3r/GUI/OptionsGroup.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index 9fde187a6a..ea424c176f 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -293,7 +293,9 @@ public: const wxString& message, const wxString& caption = wxEmptyString, long style = wxOK) - : wxRichMessageDialog(parent, message, caption, style) {} + : wxRichMessageDialog(parent, message, caption, style) { + this->SetEscapeId(wxID_CANCEL); + } ~RichMessageDialog() {} }; #endif diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 6039dcbcb9..64fc4b8c89 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -984,6 +984,8 @@ bool OptionsGroup::launch_browser(const std::string& path_end) RichMessageDialog dialog(parent, _L("Open hyperlink in default browser?"), _L("PrusaSlicer: Open hyperlink"), wxYES_NO); dialog.ShowCheckBox(_L("Remember my choice")); int answer = dialog.ShowModal(); + if (answer == wxID_CANCEL) + return false; if (dialog.IsCheckBoxChecked()) { wxString preferences_item = _L("Suppress to open hyperlink in browser"); From ea796aaa68a2948058d02711cc25a0a0fcfcee30 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 9 Dec 2021 18:45:45 +0100 Subject: [PATCH 4/4] Changed message about copying another configuration folder. Added headline to RitchTextDialog. --- src/slic3r/GUI/GUI_App.cpp | 32 +++++++++++++++----------------- src/slic3r/GUI/MsgDialog.cpp | 6 ++++-- src/slic3r/GUI/MsgDialog.hpp | 4 +++- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index bda7394ed6..0c40000e50 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -949,25 +949,23 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup) BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path; // ask about using older data folder RichMessageDialog msg(nullptr, backup ? - wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." - "\nIts version is %s." - "\nLast version you used in current configuration folder is %s." - "\nPlease note that PrusaSlicer uses different folders to save configuration of alpha, beta and full release versions." - "\nWould you like to copy found configuration to your current configuration folder?" - - "\n\nIf you select yes, PrusaSlicer will copy all profiles and other files from found folder to the current one. Overwriting any existing file with matching name." - "\nIf you select no, you will continue with current configuration.") - , m_older_data_dir_path, last_semver.to_string(), current_version.to_string()) - : wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." - "\nIts version is %s." + wxString::Format(_L( + "Current configuration folder: %s" + "\n\n%s found another configuration for version %s." + "\nIt is found at %s." + "\n\nDo you wish to copy and use the configuration file for version %s (overwriting any file with the same name)? A backup of your current configuration will be created." + "\nIf you select no, you will continue with the configuration file for version %s (may not be fully compatible).") + , current_version.to_string(), SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string(), current_version.to_string()) + : wxString::Format(_L( + "%s found another configuration for version %s." + "\nIt is found at %s." "\nThere is no configuration file in current configuration folder." - "\nPlease note that PrusaSlicer uses different folders to save configuration of alpha, beta and full release versions." - "\nWould you like to copy found configuration to your current configuration folder?" - - "\n\nIf you select yes, PrusaSlicer will copy all profiles and other files from found folder to the current one." + "\n\nDo you wish to copy and use the configuration file for version %s?" "\nIf you select no, you will start with clean installation with configuration wizard.") - , m_older_data_dir_path, last_semver.to_string()) - , _L("PrusaSlicer"), /*wxICON_QUESTION | */wxYES_NO); + , SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string()) + , _L("PrusaSlicer") + , wxYES_NO + , wxString::Format(_L("Load configuration from version %s?"), last_semver.to_string())); if (msg.ShowModal() == wxID_YES) { std::string snapshot_id; if (backup) { diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 56e9905774..9343bb741b 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -215,8 +215,10 @@ MessageDialog::MessageDialog(wxWindow* parent, RichMessageDialog::RichMessageDialog(wxWindow* parent, const wxString& message, const wxString& caption/* = wxEmptyString*/, - long style/* = wxOK*/) - : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, style) + long style/* = wxOK*/, + const wxString& headline/* = wxEmptyString*/ + ) + : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, headline, style) { add_msg_content(this, content_sizer, message); diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index ea424c176f..50651312ea 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -133,7 +133,9 @@ public: RichMessageDialog( wxWindow *parent, const wxString& message, const wxString& caption = wxEmptyString, - long style = wxOK); + long style = wxOK, + const wxString& headline = wxEmptyString + ); RichMessageDialog(RichMessageDialog&&) = delete; RichMessageDialog(const RichMessageDialog&) = delete; RichMessageDialog &operator=(RichMessageDialog&&) = delete;