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_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));

View file

@ -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 <cmath>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <random>
#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<std::string>& colors = ColorPrintColors::get();
if (ticks.empty())

View file

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

View file

@ -1,173 +1,191 @@
#include <stdio.h>
#include <random>
#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<double> 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<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;
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<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;
}
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;
// 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) {

View file

@ -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);

View file

@ -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;
@ -293,7 +295,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

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);
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");