This commit is contained in:
enricoturri1966 2021-12-10 08:21:56 +01:00
commit d561d3579a
8 changed files with 204 additions and 180 deletions

View File

@ -627,7 +627,7 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
list_printer->SetMinSize(wxSize(23*em, list_h)); 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_vendor->SetMinSize(wxSize(13*em, list_h));
list_profile->SetMinSize(wxSize(23*em, list_h)); list_profile->SetMinSize(wxSize(23*em, list_h));

View File

@ -1,6 +1,5 @@
#include "libslic3r/libslic3r.h" #include "libslic3r/libslic3r.h"
#include "DoubleSlider.hpp" #include "DoubleSlider.hpp"
#include "DoubleSlider_Utils.hpp"
#include "libslic3r/GCode.hpp" #include "libslic3r/GCode.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
@ -27,7 +26,6 @@
#include <cmath> #include <cmath>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <random>
#include "Field.hpp" #include "Field.hpp"
#include "format.hpp" #include "format.hpp"
#include "NotificationManager.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 (mode == SingleExtruder && type == ColorChange && m_use_default_colors) {
#if 1 #if 1
if (ticks.empty()) 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); auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick);
if (before_tick_it == ticks.end()) 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) if (--before_tick_it; before_tick_it->type == ColorChange)
break; break;
if (before_tick_it->type == ColorChange) if (before_tick_it->type == ColorChange)
return get_opposite_color(before_tick_it->color); return color_generator.get_opposite_color(before_tick_it->color);
return get_opposite_color((*m_colors)[0]); return color_generator.get_opposite_color((*m_colors)[0]);
} }
if (before_tick_it == ticks.begin()) if (before_tick_it == ticks.begin())
{ {
const std::string& frst_color = (*m_colors)[0]; const std::string& frst_color = (*m_colors)[0];
if (before_tick_it->type == ColorChange) 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; auto next_tick_it = before_tick_it;
while (next_tick_it != ticks.end()) while (next_tick_it != ticks.end())
if (++next_tick_it; next_tick_it->type == ColorChange) if (++next_tick_it; next_tick_it->type == ColorChange)
break; break;
if (next_tick_it->type == ColorChange) 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 = ""; 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 (before_tick_it->type == ColorChange) {
if (frst_color.empty()) if (frst_color.empty())
return get_opposite_color(before_tick_it->color); return color_generator.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, frst_color);
} }
if (frst_color.empty()) if (frst_color.empty())
return get_opposite_color((*m_colors)[0]); return color_generator.get_opposite_color((*m_colors)[0]);
return get_opposite_color((*m_colors)[0], frst_color); return color_generator.get_opposite_color((*m_colors)[0], frst_color);
#else #else
const std::vector<std::string>& colors = ColorPrintColors::get(); const std::vector<std::string>& colors = ColorPrintColors::get();
if (ticks.empty()) if (ticks.empty())

View File

@ -3,6 +3,7 @@
#include "libslic3r/CustomGCode.hpp" #include "libslic3r/CustomGCode.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "DoubleSlider_Utils.hpp"
#include <wx/window.h> #include <wx/window.h>
#include <wx/control.h> #include <wx/control.h>
@ -118,6 +119,7 @@ class TickCodeInfo
// int m_default_color_idx = 0; // int m_default_color_idx = 0;
std::vector<std::string>* m_colors {nullptr}; std::vector<std::string>* m_colors {nullptr};
ColorGenerator color_generator;
std::string get_color_for_tick(TickCode tick, Type type, const int extruder); std::string get_color_for_tick(TickCode tick, Type type, const int extruder);

View File

@ -1,173 +1,191 @@
#include <stdio.h> #include <stdio.h>
#include <random>
#include "wx/colour.h" #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 class ColorGenerator
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)
{ {
hsv out; // 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
double min, max, delta; 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; typedef struct {
min = min < in.b ? min : in.b; 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; //static hsv rgb2hsv(rgb in);
max = max > in.b ? max : in.b; //static rgb hsv2rgb(hsv in);
out.v = max; // v hsv rgb2hsv(rgb in)
delta = max - min;
if (delta < 0.00001)
{ {
out.s = 0; hsv out;
out.h = 0; // undefined, maybe nan? 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; return out;
} }
if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
out.s = (delta / max); // s hsv rgb2hsv(const std::string& str_clr_in)
} else { {
// if max is 0, then r = g = b = 0 wxColour clr(str_clr_in);
// s = 0, h is undefined rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 };
out.s = 0.0; return rgb2hsv(in);
out.h = NAN; // its now undefined }
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; 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 ) public:
out.h += 360.0;
return out; ColorGenerator() {}
} ~ColorGenerator() {}
hsv rgb2hsv(const std::string& str_clr_in) double rand_val()
{ {
wxColour clr(str_clr_in); std::mt19937 rand_generator(rd());
rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 };
return rgb2hsv(in);
}
// this value will be used for Saturation and Value
rgb hsv2rgb(hsv in) // to avoid extremely light/dark colors, take this value from range [0.65; 1.0]
{ std::uniform_real_distribution<double> distrib(0.65, 1.0);
double hh, p, q, t, ff; return distrib(rand_generator);
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: std::string get_opposite_color(const std::string& color)
out.r = p; {
out.g = q; std::string opp_color = "";
out.b = in.v;
break; hsv hsv_clr = rgb2hsv(color);
case 4: hsv_clr.h += 65; // 65 instead 60 to avoid circle values
out.r = t; hsv_clr.s = rand_val();
out.g = p; hsv_clr.v = rand_val();
out.b = in.v;
break; rgb rgb_opp_color = hsv2rgb(hsv_clr);
case 5:
default: 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));
out.r = in.v; opp_color = clr_str.ToStdString();
out.g = p;
out.b = q; return opp_color;
break;
} }
return out;
}
double rand_val() std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd)
{ {
return 0.1 * (10 - rand() % 8); std::string opp_color = "";
}
std::string get_opposite_color(const std::string& color) hsv hsv_frst = rgb2hsv(color_frst);
{ hsv hsv_scnd = rgb2hsv(color_scnd);
std::string opp_color = "";
hsv hsv_clr = rgb2hsv(color); double delta_h = fabs(hsv_frst.h - hsv_scnd.h);
hsv_clr.h += 65; // 65 instead 60 to avoid circle values double start_h = delta_h > 180 ? std::min<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(hsv_scnd.h, hsv_frst.h);
hsv_clr.s = rand_val(); start_h += 5; // to avoid circle change of colors for 120 deg
hsv_clr.v = rand_val(); 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)); 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(); opp_color = clr_str.ToStdString();
return opp_color; 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<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(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;
}

View File

@ -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; BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path;
// ask about using older data folder // ask about using older data folder
RichMessageDialog msg(nullptr, backup ? RichMessageDialog msg(nullptr, backup ?
wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." wxString::Format(_L(
"\nIts version is %s." "Current configuration folder: %s"
"\nLast version you used in current configuration folder is %s." "\n\n%s found another configuration for version %s."
"\nPlease note that PrusaSlicer uses different folders to save configuration of alpha, beta and full release versions." "\nIt is found at %s."
"\nWould you like to copy found configuration to your current configuration folder?" "\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).")
"\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." , current_version.to_string(), SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string(), current_version.to_string())
"\nIf you select no, you will continue with current configuration.") : wxString::Format(_L(
, m_older_data_dir_path, last_semver.to_string(), current_version.to_string()) "%s found another configuration for version %s."
: wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." "\nIt is found at %s."
"\nIts version is %s."
"\nThere is no configuration file in current configuration folder." "\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." "\n\nDo you wish to copy and use the configuration file for version %s?"
"\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."
"\nIf you select no, you will start with clean installation with configuration wizard.") "\nIf you select no, you will start with clean installation with configuration wizard.")
, m_older_data_dir_path, last_semver.to_string()) , SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string())
, _L("PrusaSlicer"), /*wxICON_QUESTION | */wxYES_NO); , _L("PrusaSlicer")
, wxYES_NO
, wxString::Format(_L("Load configuration from version %s?"), last_semver.to_string()));
if (msg.ShowModal() == wxID_YES) { if (msg.ShowModal() == wxID_YES) {
std::string snapshot_id; std::string snapshot_id;
if (backup) { if (backup) {

View File

@ -215,8 +215,10 @@ MessageDialog::MessageDialog(wxWindow* parent,
RichMessageDialog::RichMessageDialog(wxWindow* parent, RichMessageDialog::RichMessageDialog(wxWindow* parent,
const wxString& message, const wxString& message,
const wxString& caption/* = wxEmptyString*/, const wxString& caption/* = wxEmptyString*/,
long style/* = wxOK*/) long style/* = wxOK*/,
: MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, style) 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); add_msg_content(this, content_sizer, message);

View File

@ -133,7 +133,9 @@ public:
RichMessageDialog( wxWindow *parent, RichMessageDialog( wxWindow *parent,
const wxString& message, const wxString& message,
const wxString& caption = wxEmptyString, const wxString& caption = wxEmptyString,
long style = wxOK); long style = wxOK,
const wxString& headline = wxEmptyString
);
RichMessageDialog(RichMessageDialog&&) = delete; RichMessageDialog(RichMessageDialog&&) = delete;
RichMessageDialog(const RichMessageDialog&) = delete; RichMessageDialog(const RichMessageDialog&) = delete;
RichMessageDialog &operator=(RichMessageDialog&&) = delete; RichMessageDialog &operator=(RichMessageDialog&&) = delete;
@ -293,7 +295,9 @@ public:
const wxString& message, const wxString& message,
const wxString& caption = wxEmptyString, const wxString& caption = wxEmptyString,
long style = wxOK) long style = wxOK)
: wxRichMessageDialog(parent, message, caption, style) {} : wxRichMessageDialog(parent, message, caption, style) {
this->SetEscapeId(wxID_CANCEL);
}
~RichMessageDialog() {} ~RichMessageDialog() {}
}; };
#endif #endif

View File

@ -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); RichMessageDialog dialog(parent, _L("Open hyperlink in default browser?"), _L("PrusaSlicer: Open hyperlink"), wxYES_NO);
dialog.ShowCheckBox(_L("Remember my choice")); dialog.ShowCheckBox(_L("Remember my choice"));
int answer = dialog.ShowModal(); int answer = dialog.ShowModal();
if (answer == wxID_CANCEL)
return false;
if (dialog.IsCheckBoxChecked()) { if (dialog.IsCheckBoxChecked()) {
wxString preferences_item = _L("Suppress to open hyperlink in browser"); wxString preferences_item = _L("Suppress to open hyperlink in browser");