Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/slic3r')
-rw-r--r--src/slic3r/GUI/3DScene.cpp14
-rw-r--r--src/slic3r/GUI/DoubleSlider.cpp84
-rw-r--r--src/slic3r/GUI/DoubleSlider.hpp11
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp2
-rw-r--r--src/slic3r/GUI/GUI_App.cpp22
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp15
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.hpp3
-rw-r--r--src/slic3r/GUI/GUI_Preview.cpp30
-rw-r--r--src/slic3r/GUI/GalleryDialog.cpp15
-rw-r--r--src/slic3r/GUI/MainFrame.cpp2
-rw-r--r--src/slic3r/GUI/NotificationManager.cpp4
-rw-r--r--src/slic3r/GUI/NotificationManager.hpp3
-rw-r--r--src/slic3r/GUI/OG_CustomCtrl.cpp77
-rw-r--r--src/slic3r/GUI/OG_CustomCtrl.hpp9
-rw-r--r--src/slic3r/GUI/OptionsGroup.cpp20
-rw-r--r--src/slic3r/GUI/OptionsGroup.hpp11
-rw-r--r--src/slic3r/GUI/Preferences.cpp99
-rw-r--r--src/slic3r/GUI/Preferences.hpp8
-rw-r--r--src/slic3r/GUI/Selection.cpp14
-rw-r--r--src/slic3r/Utils/PresetUpdater.cpp73
-rw-r--r--src/slic3r/Utils/PresetUpdater.hpp4
21 files changed, 432 insertions, 88 deletions
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index dfc10658d..27eb69363 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -464,9 +464,15 @@ std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume)
color[2] = 0.2f;
}
else if (model_volume.is_modifier()) {
+#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
+ color[0] = 1.0f;
+ color[1] = 1.0f;
+ color[2] = 0.2f;
+#else
color[0] = 0.2f;
color[1] = 1.0f;
color[2] = 0.2f;
+#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
}
else if (model_volume.is_support_blocker()) {
color[0] = 1.0f;
@@ -836,7 +842,15 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisable(GL_CULL_FACE));
for (GLVolumeWithIdAndZ& volume : to_render) {
+#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
+ if (type == ERenderType::Transparent)
+ volume.first->force_transparent = true;
+#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
volume.first->set_render_color();
+#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
+ if (type == ERenderType::Transparent)
+ volume.first->force_transparent = false;
+#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
// render sinking contours of non-hovered volumes
if (m_show_sinking_contours)
diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp
index 77679a1ad..d0b29165c 100644
--- a/src/slic3r/GUI/DoubleSlider.cpp
+++ b/src/slic3r/GUI/DoubleSlider.cpp
@@ -38,6 +38,14 @@ using GUI::format_wxstr;
namespace DoubleSlider {
+constexpr double min_delta_area = scale_(scale_(25)); // equal to 25 mm2
+constexpr double miscalculation = scale_(scale_(1)); // equal to 1 mm2
+
+bool equivalent_areas(const double& bottom_area, const double& top_area)
+{
+ return fabs(bottom_area - top_area) <= miscalculation;
+}
+
wxDEFINE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent);
static std::string gcode(Type type)
@@ -2034,6 +2042,32 @@ void Control::show_cog_icon_context_menu()
GUI::wxGetApp().plater()->PopupMenu(&menu);
}
+bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs, std::function<bool(Layer*)> break_condition)
+{
+ double prev_area = area(object->get_layer(frst_layer_id)->lslices);
+
+ bool detected = false;
+ for (size_t i = frst_layer_id+1; i < layers_cnt; i++) {
+ Layer* layer = object->get_layer(i);
+ double cur_area = area(layer->lslices);
+
+ // check for overhangs
+ if (check_overhangs && cur_area > prev_area && !equivalent_areas(prev_area, cur_area))
+ break;
+
+ // Check percent of the area decrease.
+ // This value have to be more than min_delta_area and more then 10%
+ if ((prev_area - cur_area > min_delta_area) && (cur_area / prev_area < 0.9)) {
+ detected = true;
+ if (break_condition(layer))
+ break;
+ }
+
+ prev_area = cur_area;
+ }
+ return detected;
+}
+
void Control::auto_color_change()
{
if (!m_ticks.empty()) {
@@ -2049,45 +2083,33 @@ void Control::auto_color_change()
int extruder = 2;
const Print& print = GUI::wxGetApp().plater()->fff_print();
- double delta_area = scale_(scale_(25)); // equal to 25 mm2
-
for (auto object : print.objects()) {
if (object->layer_count() == 0)
continue;
- double prev_area = area(object->get_layer(0)->lslices);
-
- for (size_t i = 1; i < object->layers().size(); i++) {
- Layer* layer = object->get_layer(i);
- double cur_area = area(layer->lslices);
- if (cur_area > prev_area && prev_area - cur_area > scale_(scale_(1)))
- break;
-
- if (prev_area - cur_area > delta_area) {
- // Check percent of the area decrease.
- // Ignore it, if this value is less than 10%
- if (cur_area / prev_area > 0.9)
- continue;
- int tick = get_tick_from_value(layer->print_z);
- if (tick >= 0 && !m_ticks.has_tick(tick)) {
- if (m_mode == SingleExtruder) {
- m_ticks.set_default_colors(true);
- m_ticks.add_tick(tick, ColorChange, 1, layer->print_z);
- }
- else {
- m_ticks.add_tick(tick, ToolChange, extruder, layer->print_z);
- if (++extruder > extruders_cnt)
+ check_color_change(object, 1, object->layers().size(), false, [this, extruders_cnt](Layer* layer)
+ {
+ int tick = get_tick_from_value(layer->print_z);
+ if (tick >= 0 && !m_ticks.has_tick(tick)) {
+ if (m_mode == SingleExtruder) {
+ m_ticks.set_default_colors(true);
+ m_ticks.add_tick(tick, ColorChange, 1, layer->print_z);
+ }
+ else {
+ int extruder = 2;
+ if (!m_ticks.empty()) {
+ auto it = m_ticks.ticks.end();
+ it--;
+ extruder = it->extruder + 1;
+ if (extruder > extruders_cnt)
extruder = 1;
}
+ m_ticks.add_tick(tick, ToolChange, extruder, layer->print_z);
}
-
- // allow max 3 auto color changes
- if (m_ticks.ticks.size() == 3)
- break;
}
-
- prev_area = cur_area;
- }
+ // allow max 3 auto color changes
+ return m_ticks.ticks.size() > 2;
+ });
}
if (m_ticks.empty())
diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp
index 0f663f663..8f88de472 100644
--- a/src/slic3r/GUI/DoubleSlider.hpp
+++ b/src/slic3r/GUI/DoubleSlider.hpp
@@ -17,6 +17,8 @@ class wxMenu;
namespace Slic3r {
using namespace CustomGCode;
+class PrintObject;
+class Layer;
namespace DoubleSlider {
@@ -25,6 +27,15 @@ namespace DoubleSlider {
*/
constexpr double epsilon() { return 0.0011; }
+// return true when areas are mostly equivalent
+bool equivalent_areas(const double& bottom_area, const double& top_area);
+
+// return true if color change was detected
+bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs,
+ // what to do with detected color change
+ // and return true when detection have to be desturbed
+ std::function<bool(Layer*)> break_condition);
+
// custom message the slider sends to its parent to notify a tick-change:
wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent);
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 9ba72e629..ca31645c1 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1286,12 +1286,14 @@ bool GLCanvas3D::is_reload_delayed() const
void GLCanvas3D::enable_layers_editing(bool enable)
{
m_layers_editing.set_enabled(enable);
+#if !ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
const Selection::IndicesList& idxs = m_selection.get_volume_idxs();
for (unsigned int idx : idxs) {
GLVolume* v = m_volumes.volumes[idx];
if (v->is_modifier)
v->force_transparent = enable;
}
+#endif // !ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
set_as_dirty();
}
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index e2a9df25d..a19858eea 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -865,8 +865,11 @@ bool GUI_App::on_init_inner()
wxInitAllImageHandlers();
#ifdef _MSW_DARK_MODE
- if (app_config->get("dark_color_mode") == "1")
+ if (bool dark_mode = app_config->get("dark_color_mode") == "1") {
NppDarkMode::InitDarkMode();
+ if (dark_mode != NppDarkMode::IsDarkMode())
+ NppDarkMode::SetDarkMode(dark_mode);
+ }
#endif
SplashScreen* scrn = nullptr;
if (app_config->get("show_splash_screen") == "1") {
@@ -915,6 +918,23 @@ bool GUI_App::on_init_inner()
}
}
});
+ Bind(EVT_SLIC3R_ALPHA_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
+ app_config->save();
+ if (this->plater_ != nullptr && app_config->get("notify_testing_release") == "1") {
+ if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
+ this->plater_->get_notification_manager()->push_notification(NotificationType::NewAlphaAvailable);
+ }
+ }
+ });
+ Bind(EVT_SLIC3R_BETA_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
+ app_config->save();
+ if (this->plater_ != nullptr && app_config->get("notify_testing_release") == "1") {
+ if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
+ this->plater_->get_notification_manager()->close_notification_of_type(NotificationType::NewAlphaAvailable);
+ this->plater_->get_notification_manager()->push_notification(NotificationType::NewBetaAvailable);
+ }
+ }
+ });
}
else {
#ifdef __WXMSW__
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index e6e7336f7..83f9d1ec1 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -1405,9 +1405,11 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
item = m_objects_model->GetItemById(obj_idx);
std::vector<ModelVolume*> volumes;
+ // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
+ /*
if (type == ModelVolumeType::MODEL_PART)
load_part(*(*m_objects)[obj_idx], volumes, type, from_galery);
- else
+ else*/
load_modifier(*(*m_objects)[obj_idx], volumes, type, from_galery);
if (volumes.empty())
@@ -1430,8 +1432,8 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
selection_changed();
}
-
-void ObjectList::load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery/* = false*/)
+/*
+void ObjectList::load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery/* = false* /)
{
if (type != ModelVolumeType::MODEL_PART)
return;
@@ -1489,11 +1491,12 @@ void ObjectList::load_part(ModelObject& model_object, std::vector<ModelVolume*>&
}
}
}
-
+*/
void ObjectList::load_modifier(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery)
{
- if (type == ModelVolumeType::MODEL_PART)
- return;
+ // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
+ //if (type == ModelVolumeType::MODEL_PART)
+ // return;
wxWindow* parent = wxGetApp().tab_panel()->GetPage(0);
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index cc619fc45..535bfa7a7 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -249,7 +249,8 @@ public:
bool is_instance_or_object_selected();
void load_subobject(ModelVolumeType type, bool from_galery = false);
- void load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
+ // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
+ //void load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
void load_modifier(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
void load_generic_subobject(const std::string& type_name, const ModelVolumeType type);
void load_shape_object(const std::string &type_name);
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 8a1e9121d..f5168649a 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -13,6 +13,7 @@
#include "DoubleSlider.hpp"
#include "Plater.hpp"
#include "MainFrame.hpp"
+#include "format.hpp"
#include <wx/listbook.h>
#include <wx/notebook.h>
@@ -708,7 +709,6 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
if (m_layers_slider->IsNewPrint())
{
const Print& print = wxGetApp().plater()->fff_print();
- double delta_area = scale_(scale_(25)); // equal to 25 mm2
//bool is_possible_auto_color_change = false;
for (auto object : print.objects()) {
@@ -729,7 +729,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
int i, min_solid_height = int(0.25 * num_layers);
for (i = 1; i <= min_solid_height; ++ i) {
double cur_area = area(object->get_layer(i)->lslices);
- if (cur_area != bottom_area && fabs(cur_area - bottom_area) > scale_(scale_(1))) {
+ if (!DoubleSlider::equivalent_areas(bottom_area, cur_area)) {
// but due to the elephant foot compensation, the first layer may be slightly smaller than the others
if (i == 1 && fabs(cur_area - bottom_area) / bottom_area < 0.1) {
// So, let process this case and use second layer as a bottom
@@ -742,33 +742,23 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
if (i < min_solid_height)
continue;
- // bottom layer have to be a biggest, so control relation between bottom layer and object size
- double prev_area = area(object->get_layer(i)->lslices);
- for ( i++; i < num_layers; i++) {
- double cur_area = area(object->get_layer(i)->lslices);
- if (cur_area > prev_area && prev_area - cur_area > scale_(scale_(1)))
- break;
- prev_area = cur_area;
- }
- if (i < num_layers)
- continue;
-
- double top_area = area(object->get_layer(int(object->layers().size()) - 1)->lslices);
- if( bottom_area - top_area > delta_area) {
- NotificationManager *notif_mngr = wxGetApp().plater()->get_notification_manager();
+ if (DoubleSlider::check_color_change(object, i, num_layers, true, [this, object](Layer*) {
+ NotificationManager* notif_mngr = wxGetApp().plater()->get_notification_manager();
notif_mngr->push_notification(
NotificationType::SignDetected, NotificationManager::NotificationLevel::PrintInfoNotificationLevel,
- _u8L("NOTE:") + "\n" + _u8L("Sliced object looks like the sign") + "\n",
- _u8L("Apply auto color change to print"),
+ _u8L("NOTE:") + "\n" +
+ format(_u8L("Sliced object \"%1%\" looks like a logo or a sign"), object->model_object()->name) + "\n",
+ _u8L("Apply automatic color change"),
[this](wxEvtHandler*) {
m_layers_slider->auto_color_change();
return true;
});
notif_mngr->apply_in_preview();
-
+ return true;
+ }) )
+ // first object with color chnages is found
break;
- }
}
}
diff --git a/src/slic3r/GUI/GalleryDialog.cpp b/src/slic3r/GUI/GalleryDialog.cpp
index 5429e2658..fef131b88 100644
--- a/src/slic3r/GUI/GalleryDialog.cpp
+++ b/src/slic3r/GUI/GalleryDialog.cpp
@@ -66,7 +66,7 @@ bool GalleryDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& f
GalleryDialog::GalleryDialog(wxWindow* parent, bool modify_gallery/* = false*/) :
- DPIDialog(parent, wxID_ANY, _L("Shapes Gallery"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
+ DPIDialog(parent, wxID_ANY, _L("Shape Gallery"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
#ifndef _WIN32
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@@ -75,7 +75,7 @@ GalleryDialog::GalleryDialog(wxWindow* parent, bool modify_gallery/* = false*/)
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Select shape from the gallery") + ":");
- m_list_ctrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(55 * wxGetApp().em_unit(), 35 * wxGetApp().em_unit()),
+ m_list_ctrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(50 * wxGetApp().em_unit(), 35 * wxGetApp().em_unit()),
wxLC_ICON | wxSIMPLE_BORDER);
m_list_ctrl->Bind(wxEVT_LIST_ITEM_SELECTED, &GalleryDialog::select, this);
m_list_ctrl->Bind(wxEVT_LIST_ITEM_DESELECTED, &GalleryDialog::deselect, this);
@@ -152,7 +152,7 @@ void GalleryDialog::on_dpi_changed(const wxRect& suggested_rect)
msw_buttons_rescale(this, em, { ID_BTN_ADD_CUSTOM_SHAPE, ID_BTN_DEL_CUSTOM_SHAPE, ID_BTN_REPLACE_CUSTOM_PNG, wxID_OK, wxID_CLOSE });
- wxSize size = wxSize(55 * em, 35 * em);
+ wxSize size = wxSize(50 * em, 35 * em);
m_list_ctrl->SetMinSize(size);
m_list_ctrl->SetSize(size);
@@ -461,8 +461,11 @@ void GalleryDialog::replace_custom_png(wxEvent& event)
}
try {
+ fs::path png_path = fs::path(get_dir(false) / m_selected_items[0].name);
+ png_path.replace_extension("png");
+
fs::path current = fs::path(into_u8(input_files.Item(0)));
- fs::copy_file(current, get_dir(false) / (m_selected_items[0].name + ".png"), fs::copy_option::overwrite_if_exists);
+ fs::copy_file(current, png_path, fs::copy_option::overwrite_if_exists);
}
catch (fs::filesystem_error const& e) {
std::cerr << e.what() << '\n';
@@ -535,12 +538,12 @@ bool GalleryDialog::load_files(const wxArrayString& input_files)
if (!fs::exists(dest_dir / current.filename()))
fs::copy_file(current, dest_dir / current.filename());
else {
- std::string filename = current.filename().string();
+ std::string filename = current.stem().string();
int file_idx = 0;
for (auto& dir_entry : fs::directory_iterator(dest_dir))
if (is_gallery_file(dir_entry, ".stl") || is_gallery_file(dir_entry, ".obj")) {
- std::string name = dir_entry.path().filename().string();
+ std::string name = dir_entry.path().stem().string();
if (filename == name) {
if (file_idx == 0)
file_idx++;
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 66e22c694..799c4e793 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -1400,7 +1400,7 @@ void MainFrame::init_menubar_as_editor()
}
windowMenu->AppendSeparator();
- append_menu_item(windowMenu, wxID_ANY, _L("Modify Shapes Gallery"), _L("Open the dialog to modify shapes gallery"),
+ append_menu_item(windowMenu, wxID_ANY, _L("Shape Gallery"), _L("Open the dialog to modify shape gallery"),
[this](wxCommandEvent&) {
GalleryDialog dlg(this, true);
if (dlg.ShowModal() == wxID_OK) {
diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp
index ed6f11ddb..b12256cf0 100644
--- a/src/slic3r/GUI/NotificationManager.cpp
+++ b/src/slic3r/GUI/NotificationManager.cpp
@@ -43,6 +43,10 @@ const NotificationManager::NotificationData NotificationManager::basic_notificat
},
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
wxGetApp().open_browser_with_warning_dialog("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
+ {NotificationType::NewAlphaAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New alpha release is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
+ wxGetApp().open_browser_with_warning_dialog("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
+ {NotificationType::NewBetaAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New beta release is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
+ wxGetApp().open_browser_with_warning_dialog("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
{NotificationType::EmptyColorChangeCode, NotificationLevel::PrintInfoNotificationLevel, 10,
_u8L("You have just added a G-code for color change, but its value is empty.\n"
"To export the G-code correctly, check the \"Color Change G-code\" in \"Printer Settings > Custom G-code\"") },
diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp
index ad2e315b7..00065f795 100644
--- a/src/slic3r/GUI/NotificationManager.hpp
+++ b/src/slic3r/GUI/NotificationManager.hpp
@@ -52,6 +52,9 @@ enum class NotificationType
// Notification on the start of PrusaSlicer, when a new PrusaSlicer version is published.
// Contains a hyperlink to open a web browser pointing to the PrusaSlicer download location.
NewAppAvailable,
+ // Like NewAppAvailable but with text and link for alpha / bet release
+ NewAlphaAvailable,
+ NewBetaAvailable,
// Notification on the start of PrusaSlicer, when updates of system profiles are detected.
// Contains a hyperlink to execute installation of the new system profiles.
PresetUpdateAvailable,
diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp
index f01a1e962..9c31f679b 100644
--- a/src/slic3r/GUI/OG_CustomCtrl.cpp
+++ b/src/slic3r/GUI/OG_CustomCtrl.cpp
@@ -72,6 +72,11 @@ void OG_CustomCtrl::init_ctrl_lines()
const std::vector<Line>& og_lines = opt_group->get_lines();
for (const Line& line : og_lines)
{
+ if (line.is_separator()) {
+ ctrl_lines.emplace_back(CtrlLine(0, this, line));
+ continue;
+ }
+
if (line.full_width && (
// description line
line.widget != nullptr ||
@@ -124,6 +129,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
line_height = win_height;
};
+ auto correct_horiz_pos = [this](int& h_pos, Field* field) {
+ if (m_max_win_width > 0 && field->getWindow()) {
+ int win_width = field->getWindow()->GetSize().GetWidth();
+ if (dynamic_cast<CheckBox*>(field))
+ win_width *= 0.5;
+ h_pos += m_max_win_width - win_width;
+ }
+ };
+
for (CtrlLine& ctrl_line : ctrl_lines) {
if (&ctrl_line.og_line == &line)
{
@@ -160,6 +174,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
h_pos += 3 * blinking_button_width;
Field* field = opt_group->get_field(option_set.front().opt_id);
correct_line_height(ctrl_line.height, field->getWindow());
+ correct_horiz_pos(h_pos, field);
break;
}
@@ -189,8 +204,10 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
}
h_pos += (opt.opt.gui_type == ConfigOptionDef::GUIType::legend ? 1 : 3) * blinking_button_width;
- if (field == field_in)
+ if (field == field_in) {
+ correct_horiz_pos(h_pos, field);
break;
+ }
if (opt.opt.gui_type == ConfigOptionDef::GUIType::legend)
h_pos += 2 * blinking_button_width;
@@ -361,6 +378,28 @@ void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line,
}
};
+void OG_CustomCtrl::init_max_win_width()
+{
+ if (opt_group->ctrl_horiz_alignment == wxALIGN_RIGHT && m_max_win_width == 0)
+ for (CtrlLine& line : ctrl_lines) {
+ if (int max_win_width = line.get_max_win_width();
+ m_max_win_width < max_win_width)
+ m_max_win_width = max_win_width;
+ }
+}
+
+void OG_CustomCtrl::set_max_win_width(int max_win_width)
+{
+ if (m_max_win_width == max_win_width)
+ return;
+ m_max_win_width = max_win_width;
+ for (CtrlLine& line : ctrl_lines)
+ line.correct_items_positions();
+
+ GetParent()->Layout();
+}
+
+
void OG_CustomCtrl::msw_rescale()
{
#ifdef __WXOSX__
@@ -374,6 +413,8 @@ void OG_CustomCtrl::msw_rescale()
m_bmp_mode_sz = create_scaled_bitmap("mode_simple", this, wxOSX ? 10 : 12).GetSize();
m_bmp_blinking_sz = create_scaled_bitmap("search_blink", this).GetSize();
+ m_max_win_width = 0;
+
wxCoord v_pos = 0;
for (CtrlLine& line : ctrl_lines) {
line.msw_rescale();
@@ -407,6 +448,21 @@ OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height,
}
}
+int OG_CustomCtrl::CtrlLine::get_max_win_width()
+{
+ int max_win_width = 0;
+ if (!draw_just_act_buttons) {
+ const std::vector<Option>& option_set = og_line.get_options();
+ for (auto opt : option_set) {
+ Field* field = ctrl->opt_group->get_field(opt.opt_id);
+ if (field && field->getWindow())
+ max_win_width = field->getWindow()->GetSize().GetWidth();
+ }
+ }
+
+ return max_win_width;
+}
+
void OG_CustomCtrl::CtrlLine::correct_items_positions()
{
if (draw_just_act_buttons || !is_visible)
@@ -447,6 +503,8 @@ void OG_CustomCtrl::CtrlLine::msw_rescale()
void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode)
{
+ if (og_line.is_separator())
+ return;
const std::vector<Option>& option_set = og_line.get_options();
const ConfigOptionMode& line_mode = option_set.front().opt.mode;
@@ -480,8 +538,25 @@ void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode)
correct_items_positions();
}
+void OG_CustomCtrl::CtrlLine::render_separator(wxDC& dc, wxCoord v_pos)
+{
+ wxPoint begin(ctrl->m_h_gap, v_pos);
+ wxPoint end(ctrl->GetSize().GetWidth() - ctrl->m_h_gap, v_pos);
+
+ wxPen pen, old_pen = pen = dc.GetPen();
+ pen.SetColour(*wxLIGHT_GREY);
+ dc.SetPen(pen);
+ dc.DrawLine(begin, end);
+ dc.SetPen(old_pen);
+}
+
void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
{
+ if (is_separator()) {
+ render_separator(dc, v_pos);
+ return;
+ }
+
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
diff --git a/src/slic3r/GUI/OG_CustomCtrl.hpp b/src/slic3r/GUI/OG_CustomCtrl.hpp
index afbc6c930..117ca6920 100644
--- a/src/slic3r/GUI/OG_CustomCtrl.hpp
+++ b/src/slic3r/GUI/OG_CustomCtrl.hpp
@@ -33,6 +33,8 @@ class OG_CustomCtrl :public wxPanel
wxSize m_bmp_mode_sz;
wxSize m_bmp_blinking_sz;
+ int m_max_win_width{0};
+
struct CtrlLine {
wxCoord height { wxDefaultCoord };
OG_CustomCtrl* ctrl { nullptr };
@@ -50,16 +52,20 @@ class OG_CustomCtrl :public wxPanel
bool draw_mode_bitmap = true);
~CtrlLine() { ctrl = nullptr; }
+ int get_max_win_width();
void correct_items_positions();
void msw_rescale();
void update_visibility(ConfigOptionMode mode);
+ void render_separator(wxDC& dc, wxCoord v_pos);
+
void render(wxDC& dc, wxCoord v_pos);
wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos);
wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url = false);
wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking);
wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id = 0);
bool launch_browser() const;
+ bool is_separator() const { return og_line.is_separator(); }
std::vector<wxRect> rects_undo_icon;
std::vector<wxRect> rects_undo_to_sys_icon;
@@ -86,6 +92,9 @@ public:
bool update_visibility(ConfigOptionMode mode);
void correct_window_position(wxWindow* win, const Line& line, Field* field = nullptr);
void correct_widgets_position(wxSizer* widget, const Line& line, Field* field = nullptr);
+ void init_max_win_width();
+ void set_max_win_width(int max_win_width);
+ int get_max_win_width() { return m_max_win_width; }
void msw_rescale();
void sys_color_changed();
diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp
index b57b7f302..fd9f4b5e8 100644
--- a/src/slic3r/GUI/OptionsGroup.cpp
+++ b/src/slic3r/GUI/OptionsGroup.cpp
@@ -126,6 +126,12 @@ bool OptionsGroup::is_legend_line()
return false;
}
+void OptionsGroup::set_max_win_width(int max_win_width)
+{
+ if (custom_ctrl)
+ custom_ctrl->set_max_win_width(max_win_width);
+}
+
void OptionsGroup::show_field(const t_config_option_key& opt_key, bool show/* = true*/)
{
Field* field = get_field(opt_key);
@@ -185,8 +191,16 @@ void OptionsGroup::append_line(const Line& line)
m_options_mode.push_back(option_set[0].opt.mode);
}
+void OptionsGroup::append_separator()
+{
+ m_lines.emplace_back(Line());
+}
+
void OptionsGroup::activate_line(Line& line)
{
+ if (line.is_separator())
+ return;
+
m_use_custom_ctrl_as_parent = false;
if (line.full_width && (
@@ -396,7 +410,7 @@ void OptionsGroup::activate_line(Line& line)
}
// create all controls for the option group from the m_lines
-bool OptionsGroup::activate(std::function<void()> throw_if_canceled)
+bool OptionsGroup::activate(std::function<void()> throw_if_canceled/* = [](){}*/, int horiz_alignment/* = wxALIGN_LEFT*/)
{
if (sizer)//(!sizer->IsEmpty())
return false;
@@ -436,6 +450,10 @@ bool OptionsGroup::activate(std::function<void()> throw_if_canceled)
throw_if_canceled();
activate_line(line);
}
+
+ ctrl_horiz_alignment = horiz_alignment;
+ if (custom_ctrl)
+ custom_ctrl->init_max_win_width();
} catch (UIBuildCanceled&) {
auto p = sizer;
this->clear();
diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp
index 592f2cd76..597527aef 100644
--- a/src/slic3r/GUI/OptionsGroup.hpp
+++ b/src/slic3r/GUI/OptionsGroup.hpp
@@ -49,6 +49,7 @@ using t_option = std::unique_ptr<Option>; //!
/// Represents option lines
class Line {
+ bool m_is_separator{ false };
public:
wxString label;
wxString label_tooltip;
@@ -71,6 +72,9 @@ public:
}
Line(wxString label, wxString tooltip) :
label(_(label)), label_tooltip(_(tooltip)) {}
+ Line() : m_is_separator(true) {}
+
+ bool is_separator() const { return m_is_separator; }
const std::vector<widget_t>& get_extra_widgets() const {return m_extra_widgets;}
const std::vector<Option>& get_options() const { return m_options; }
@@ -95,6 +99,7 @@ public:
size_t label_width = 20 ;// {200};
wxSizer* sizer {nullptr};
OG_CustomCtrl* custom_ctrl{ nullptr };
+ int ctrl_horiz_alignment{ wxALIGN_LEFT};
column_t extra_column {nullptr};
t_change m_on_change { nullptr };
// To be called when the field loses focus, to assign a new initial value to the field.
@@ -124,12 +129,13 @@ public:
void activate_line(Line& line);
// create all controls for the option group from the m_lines
- bool activate(std::function<void()> throw_if_canceled = [](){});
+ bool activate(std::function<void()> throw_if_canceled = [](){}, int horiz_alignment = wxALIGN_LEFT);
// delete all controls from the option group
void clear(bool destroy_custom_ctrl = false);
Line create_single_option_line(const Option& option, const wxString& path = wxEmptyString) const;
void append_single_option_line(const Option& option, const wxString& path = wxEmptyString) { append_line(create_single_option_line(option, path)); }
+ void append_separator();
// return a non-owning pointer reference
inline Field* get_field(const t_config_option_key& id) const{
@@ -171,6 +177,9 @@ public:
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
const std::vector<Line>& get_lines() { return m_lines; }
bool is_legend_line();
+ // if we have to set the same control alignment for different option groups,
+ // we have to set same max contrtol width to all of them
+ void set_max_win_width(int max_win_width);
protected:
std::map<t_config_option_key, Option> m_options;
diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp
index 9d1236922..ae52b52a9 100644
--- a/src/slic3r/GUI/Preferences.cpp
+++ b/src/slic3r/GUI/Preferences.cpp
@@ -8,8 +8,39 @@
#include <wx/notebook.h>
#include "Notebook.hpp"
#include "ButtonsDescription.hpp"
+#include "OG_CustomCtrl.hpp"
+#include <initializer_list>
namespace Slic3r {
+
+ static t_config_enum_names enum_names_from_keys_map(const t_config_enum_values& enum_keys_map)
+ {
+ t_config_enum_names names;
+ int cnt = 0;
+ for (const auto& kvp : enum_keys_map)
+ cnt = std::max(cnt, kvp.second);
+ cnt += 1;
+ names.assign(cnt, "");
+ for (const auto& kvp : enum_keys_map)
+ names[kvp.second] = kvp.first;
+ return names;
+ }
+
+#define CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(NAME) \
+ static t_config_enum_names s_keys_names_##NAME = enum_names_from_keys_map(s_keys_map_##NAME); \
+ template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values() { return s_keys_map_##NAME; } \
+ template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names() { return s_keys_names_##NAME; }
+
+
+
+ static const t_config_enum_values s_keys_map_NotifyReleaseMode = {
+ {"all", NotifyReleaseAll},
+ {"release", NotifyReleaseOnly},
+ {"none", NotifyReleaseNone},
+ };
+
+ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(NotifyReleaseMode)
+
namespace GUI {
PreferencesDialog::PreferencesDialog(wxWindow* parent, int selected_tab) :
@@ -39,7 +70,7 @@ static std::shared_ptr<ConfigOptionsGroup>create_options_tab(const wxString& tit
static void activate_options_tab(std::shared_ptr<ConfigOptionsGroup> optgroup)
{
- optgroup->activate();
+ optgroup->activate([](){}, wxALIGN_RIGHT);
optgroup->update_visibility(comSimple);
wxBoxSizer* sizer = static_cast<wxBoxSizer*>(static_cast<wxPanel*>(optgroup->parent())->GetSizer());
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
@@ -116,6 +147,8 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "version_check");
m_optgroup_general->append_single_option_line(option);
+ m_optgroup_general->append_separator();
+
// Please keep in sync with ConfigWizard
def.label = L("Export sources full pathnames to 3mf and amf");
def.type = coBool;
@@ -141,6 +174,8 @@ void PreferencesDialog::build(size_t selected_tab)
m_optgroup_general->append_single_option_line(option);
#endif // _WIN32
+ m_optgroup_general->append_separator();
+
// Please keep in sync with ConfigWizard
def.label = L("Update built-in Presets automatically");
def.type = coBool;
@@ -165,6 +200,8 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "show_incompatible_presets");
m_optgroup_general->append_single_option_line(option);
+ m_optgroup_general->append_separator();
+
def.label = L("Show drop project dialog");
def.type = coBool;
def.tooltip = L("When checked, whenever dragging and dropping a project file on the application, shows a dialog asking to select the action to take on the file to load.");
@@ -172,7 +209,6 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "show_drop_project_dialog");
m_optgroup_general->append_single_option_line(option);
-
#if __APPLE__
def.label = L("Allow just a single PrusaSlicer instance");
def.type = coBool;
@@ -186,6 +222,8 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "single_instance");
m_optgroup_general->append_single_option_line(option);
+ m_optgroup_general->append_separator();
+
def.label = L("Ask for unsaved changes when closing application or loading new project");
def.type = coBool;
def.tooltip = L("Always ask for unsaved changes, when: \n"
@@ -230,6 +268,8 @@ void PreferencesDialog::build(size_t selected_tab)
m_optgroup_general->append_single_option_line(option);
#endif
+ m_optgroup_general->append_separator();
+
// Show/Hide splash screen
def.label = L("Show splash screen");
def.type = coBool;
@@ -291,7 +331,15 @@ void PreferencesDialog::build(size_t selected_tab)
m_optgroup_gui->m_on_change = [this, tabs](t_config_option_key opt_key, boost::any value) {
if (opt_key == "suppress_hyperlinks")
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "";
- else
+ else if (opt_key == "notify_release") {
+ int val_int = boost::any_cast<int>(value);
+ for (const auto& item : s_keys_map_NotifyReleaseMode) {
+ if (item.second == val_int) {
+ m_values[opt_key] = item.first;
+ break;
+ }
+ }
+ } else
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
if (opt_key == "use_custom_toolbar_size") {
@@ -300,6 +348,8 @@ void PreferencesDialog::build(size_t selected_tab)
tabs->Layout();
this->layout();
}
+
+
};
def.label = L("Sequential slider applied only to top layer");
@@ -361,7 +411,9 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "tabs_as_menu");
m_optgroup_gui->append_single_option_line(option);
#endif
-
+
+ m_optgroup_gui->append_separator();
+
def.label = L("Show \"Tip of the day\" notification after start");
def.type = coBool;
def.tooltip = L("If enabled, useful hints are displayed at startup.");
@@ -369,15 +421,37 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "show_hints");
m_optgroup_gui->append_single_option_line(option);
+ ConfigOptionDef def_enum;
+ def_enum.label = L("Notify about new releases");
+ def_enum.type = coEnum;
+ def_enum.tooltip = L("You will be notified about new release after startup acordingly: All = Regular release and alpha / beta releases. Release only = regular release.");
+ def_enum.enum_keys_map = &ConfigOptionEnum<NotifyReleaseMode>::get_enum_values();
+ def_enum.enum_values.push_back("all");
+ def_enum.enum_values.push_back("release");
+ def_enum.enum_values.push_back("none");
+ def_enum.enum_labels.push_back(L("All"));
+ def_enum.enum_labels.push_back(L("Release only"));
+ def_enum.enum_labels.push_back(L("None"));
+ def_enum.mode = comSimple;
+ def_enum.set_default_value(new ConfigOptionEnum<NotifyReleaseMode>(static_cast<NotifyReleaseMode>(s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")))));
+ option = Option(def_enum, "notify_release");
+ m_optgroup_gui->append_single_option_line(option);
+
+ m_optgroup_gui->append_separator();
+
def.label = L("Use custom size for toolbar icons");
def.type = coBool;
def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_custom_toolbar_size") == "1" });
option = Option(def, "use_custom_toolbar_size");
m_optgroup_gui->append_single_option_line(option);
+
}
activate_options_tab(m_optgroup_gui);
+ // set Field for notify_release to its value to activate the object
+ boost::any val = s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release"));
+ m_optgroup_gui->get_field("notify_release")->set_value(val, false);
if (is_editor) {
create_icon_size_slider();
@@ -406,6 +480,9 @@ void PreferencesDialog::build(size_t selected_tab)
}
#endif // ENABLE_ENVIRONMENT_MAP
+ // update alignment of the controls for all tabs
+ update_ctrls_alignment();
+
if (selected_tab < tabs->GetPageCount())
tabs->SetSelection(selected_tab);
@@ -425,6 +502,20 @@ void PreferencesDialog::build(size_t selected_tab)
this->CenterOnParent();
}
+void PreferencesDialog::update_ctrls_alignment()
+{
+ int max_ctrl_width{ 0 };
+ std::initializer_list<ConfigOptionsGroup*> og_list = { m_optgroup_general.get(), m_optgroup_camera.get(), m_optgroup_gui.get() };
+ for (auto og : og_list) {
+ if (int max = og->custom_ctrl->get_max_win_width();
+ max_ctrl_width < max)
+ max_ctrl_width = max;
+ }
+ if (max_ctrl_width)
+ for (auto og : og_list)
+ og->custom_ctrl->set_max_win_width(max_ctrl_width);
+}
+
void PreferencesDialog::accept(wxEvent&)
{
// if (m_values.find("no_defaults") != m_values.end()
diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp
index 4e5b58df0..7f708ff9c 100644
--- a/src/slic3r/GUI/Preferences.hpp
+++ b/src/slic3r/GUI/Preferences.hpp
@@ -10,6 +10,13 @@
class wxColourPickerCtrl;
namespace Slic3r {
+
+ enum NotifyReleaseMode {
+ NotifyReleaseAll,
+ NotifyReleaseOnly,
+ NotifyReleaseNone
+ };
+
namespace GUI {
class ConfigOptionsGroup;
@@ -39,6 +46,7 @@ public:
bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; }
bool recreate_GUI() const { return m_recreate_GUI; }
void build(size_t selected_tab = 0);
+ void update_ctrls_alignment();
void accept(wxEvent&);
protected:
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 3ab9b7bdc..6a82ca8d3 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -444,11 +444,25 @@ void Selection::clear()
if (m_list.empty())
return;
+#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
+ // ensure that the volumes get the proper color before next call to render (expecially needed for transparent volumes)
+ for (unsigned int i : m_list) {
+ GLVolume& volume = *(*m_volumes)[i];
+ volume.selected = false;
+ bool transparent = volume.color[3] < 1.0f;
+ if (transparent)
+ volume.force_transparent = true;
+ volume.set_render_color();
+ if (transparent)
+ volume.force_transparent = false;
+ }
+#else
for (unsigned int i : m_list) {
(*m_volumes)[i]->selected = false;
// ensure the volume gets the proper color before next call to render (expecially needed for transparent volumes)
(*m_volumes)[i]->set_render_color();
}
+#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
m_list.clear();
diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp
index 97c6cb2a5..13c631c9c 100644
--- a/src/slic3r/Utils/PresetUpdater.cpp
+++ b/src/slic3r/Utils/PresetUpdater.cpp
@@ -141,7 +141,8 @@ struct Updates
wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
-
+wxDEFINE_EVENT(EVT_SLIC3R_ALPHA_VERSION_ONLINE, wxCommandEvent);
+wxDEFINE_EVENT(EVT_SLIC3R_BETA_VERSION_ONLINE, wxCommandEvent);
struct PresetUpdater::priv
{
@@ -167,6 +168,7 @@ struct PresetUpdater::priv
bool get_file(const std::string &url, const fs::path &target_path) const;
void prune_tmps() const;
void sync_version() const;
+ void parse_version_string(const std::string& body) const;
void sync_config(const VendorMap vendors);
void check_install_indices() const;
@@ -262,23 +264,68 @@ void PresetUpdater::priv::sync_version() const
})
.on_complete([&](std::string body, unsigned /* http_status */) {
boost::trim(body);
- const auto nl_pos = body.find_first_of("\n\r");
- if (nl_pos != std::string::npos) {
- body.resize(nl_pos);
- }
+ parse_version_string(body);
+ })
+ .perform_sync();
+}
- if (! Semver::parse(body)) {
- BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, body);
+// Parses version string obtained in sync_version() and sends events to UI thread.
+// Version string must contain release version on first line. Follows non-mandatory alpha / beta releases on following lines (alpha=2.0.0-alpha1).
+void PresetUpdater::priv::parse_version_string(const std::string& body) const
+{
+ // release version
+ std::string version;
+ const auto first_nl_pos = body.find_first_of("\n\r");
+ if (first_nl_pos != std::string::npos)
+ version = body.substr(0, first_nl_pos);
+ else
+ version = body;
+ if (!Semver::parse(version)) {
+ BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
+ return;
+ }
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
+
+ // alpha / beta version
+ size_t nexn_nl_pos = first_nl_pos;
+ while (nexn_nl_pos != std::string::npos && body.size() > nexn_nl_pos + 1) {
+ const auto last_nl_pos = nexn_nl_pos;
+ nexn_nl_pos = body.find_first_of("\n\r", last_nl_pos + 1);
+ std::string line;
+ if (nexn_nl_pos == std::string::npos)
+ line = body.substr(last_nl_pos + 1);
+ else
+ line = body.substr(last_nl_pos + 1, nexn_nl_pos - last_nl_pos - 1);
+
+ // alpha
+ if (line.substr(0, 6) == "alpha=") {
+ version = line.substr(6);
+ if (!Semver::parse(version)) {
+ BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents for alpha release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
return;
}
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version of alpha release: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_ALPHA_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
- BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, body);
-
- wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
- evt->SetString(GUI::from_u8(body));
+ // beta
+ }
+ else if (line.substr(0, 5) == "beta=") {
+ version = line.substr(5);
+ if (!Semver::parse(version)) {
+ BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents for beta release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
+ return;
+ }
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version of beta release: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_BETA_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
GUI::wxGetApp().QueueEvent(evt);
- })
- .perform_sync();
+ }
+ }
}
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp
index d7eeb5604..b7937c574 100644
--- a/src/slic3r/Utils/PresetUpdater.hpp
+++ b/src/slic3r/Utils/PresetUpdater.hpp
@@ -61,7 +61,7 @@ private:
};
wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
-
-
+wxDECLARE_EVENT(EVT_SLIC3R_ALPHA_VERSION_ONLINE, wxCommandEvent);
+wxDECLARE_EVENT(EVT_SLIC3R_BETA_VERSION_ONLINE, wxCommandEvent);
}
#endif