This commit is contained in:
bubnikv 2019-04-30 12:01:44 +02:00
commit 6b72c16985
32 changed files with 1295 additions and 1093 deletions

File diff suppressed because it is too large Load diff

View file

@ -213,7 +213,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("clip_multipart_objects", coBool);
def->label = L("Clip multi-part objects");
def->tooltip = L("When printing multi-material objects, this settings will make slic3r "
def->tooltip = L("When printing multi-material objects, this settings will make Slic3r "
"to clip the overlapping object parts one by the other "
"(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).");
def->mode = comExpert;
@ -2266,7 +2266,7 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Printer scaling correction");
def->min = 0;
def->mode = comExpert;
def->default_value = new ConfigOptionFloats( { 1., 1., 1. } );
def->default_value = new ConfigOptionFloats( { 1., 1. } );
def = this->add("absolute_correction", coFloat);
def->label = L("Printer absolute correction");
@ -2323,7 +2323,7 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Correction for expansion");
def->min = 0;
def->mode = comExpert;
def->default_value = new ConfigOptionFloats( { 1. , 1., 1. } );
def->default_value = new ConfigOptionFloats( { 1. , 1. } );
def = this->add("material_notes", coString);
def->label = L("SLA print material notes");

View file

@ -248,20 +248,21 @@ RawBytes Raster::save(Raster::Compression comp)
{
assert(m_impl);
std::uint8_t *ptr = nullptr; size_t s = 0;
std::vector<std::uint8_t> data; size_t s = 0;
switch(comp) {
case Compression::PNG: {
void *rawdata = tdefl_write_image_to_png_file_in_memory(
m_impl->buffer().data(),
int(resolution().width_px),
int(resolution().height_px), 1, &s);
if(rawdata == nullptr) break;
ptr = static_cast<std::uint8_t*>(rawdata);
auto ptr = static_cast<std::uint8_t*>(rawdata);
data.reserve(s); std::copy(ptr, ptr + s, std::back_inserter(data));
MZ_FREE(rawdata);
break;
}
case Compression::RAW: {
@ -270,21 +271,19 @@ RawBytes Raster::save(Raster::Compression comp)
std::to_string(m_impl->resolution().height_px) + " " + "255 ";
auto sz = m_impl->buffer().size()*sizeof(Impl::TBuffer::value_type);
s = sz + header.size();
ptr = static_cast<std::uint8_t*>(MZ_MALLOC(s));
data.reserve(s);
auto buff = reinterpret_cast<std::uint8_t*>(m_impl->buffer().data());
std::copy(buff, buff+sz, ptr + header.size());
std::copy(header.begin(), header.end(), std::back_inserter(data));
std::copy(buff, buff+sz, std::back_inserter(data));
break;
}
}
return {ptr, s};
}
void RawBytes::MinzDeleter::operator()(uint8_t *rawptr)
{
MZ_FREE(rawptr);
return {std::move(data)};
}
}

View file

@ -15,18 +15,12 @@ class ExPolygon;
// Raw byte buffer paired with its size. Suitable for compressed PNG data.
class RawBytes {
class MinzDeleter {
public:
void operator()(std::uint8_t *rawptr);
};
std::vector<std::uint8_t> m_buffer;
public:
RawBytes() = default;
RawBytes(std::uint8_t *rawptr, size_t s): m_buffer(rawptr, rawptr + s) { MinzDeleter()(rawptr); }
RawBytes(std::vector<std::uint8_t>&& data): m_buffer(std::move(data)) {}
size_t size() const { return m_buffer.size(); }
const uint8_t * data() { return m_buffer.data(); }

View file

@ -846,6 +846,16 @@ public:
if(!meshcache_valid) merged_mesh();
return model_height;
}
// Intended to be called after the generation is fully complete
void clear_support_data() {
merged_mesh(); // in case the mesh is not generated, it should be...
m_heads.clear();
m_pillars.clear();
m_junctions.clear();
m_bridges.clear();
m_compact_bridges.clear();
}
};
@ -2285,6 +2295,7 @@ SLASupportTree::SLASupportTree(const std::vector<SupportPoint> &points,
{
m_impl->ground_level = emesh.ground_level() - cfg.object_elevation_mm;
generate(points, emesh, cfg, ctl);
m_impl->clear_support_data();
}
SLASupportTree::SLASupportTree(const SLASupportTree &c):

View file

@ -436,6 +436,12 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
if (new_objects)
update_apply_status(false);
}
if(m_objects.empty()) {
m_printer.release();
m_printer_input.clear();
m_print_statistics.clear();
}
#ifdef _DEBUG
check_model_ids_equal(m_model, model);
@ -668,8 +674,8 @@ void SLAPrint::process()
// Slicing the model object. This method is oversimplified and needs to
// be compared with the fff slicing algorithm for verification
auto slice_model = [this, ilhs, ilh](SLAPrintObject& po) {
TriangleMesh mesh = po.transformed_mesh();
auto slice_model = [this, ilhs, ilh, ilhd](SLAPrintObject& po) {
const TriangleMesh& mesh = po.transformed_mesh();
// We need to prepare the slice index...
@ -685,13 +691,15 @@ void SLAPrint::process()
auto maxZs = coord_t(maxZ / SCALING_FACTOR);
po.m_slice_index.clear();
po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1);
po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh);
for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) {
po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh);
}
size_t cap = size_t(1 + (maxZs - minZs - ilhs) / lhs);
po.m_slice_index.reserve(cap);
po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilhd / 2.0, ilh);
for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs)
po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lhd / 2.0, lh);
// Just get the first record that is form the model:
auto slindex_it =
po.closest_slice_record(po.m_slice_index, float(bb3d.min(Z)));
@ -704,11 +712,8 @@ void SLAPrint::process()
po.m_model_height_levels.clear();
po.m_model_height_levels.reserve(po.m_slice_index.size());
for(auto it = slindex_it; it != po.m_slice_index.end(); ++it)
{
po.m_model_height_levels.emplace_back(it->slice_level());
}
mesh.require_shared_vertices(); // TriangleMeshSlicer needs this
TriangleMeshSlicer slicer(&mesh);
po.m_model_slices.clear();
@ -1169,8 +1174,9 @@ void SLAPrint::process()
for(const SliceRecord& record : layer.slices()) {
const SLAPrintObject *po = record.print_obj();
const ExPolygons &rawmodelslices = record.get_slice(soModel);
const ExPolygons &modelslices = clpr_back_offs != 0 ? offset_ex(rawmodelslices, clpr_back_offs) : rawmodelslices;
// const ExPolygons &rawmodelslices = record.get_slice(soModel);
// const ExPolygons &modelslices = clpr_back_offs != 0 ? offset_ex(rawmodelslices, clpr_back_offs) : rawmodelslices;
const ExPolygons &modelslices = record.get_slice(soModel);
bool is_lefth = record.print_obj()->is_left_handed();
if (!modelslices.empty()) {
@ -1178,8 +1184,9 @@ void SLAPrint::process()
for(ClipperPolygon& p_tmp : v) model_polygons.emplace_back(std::move(p_tmp));
}
const ExPolygons &rawsupportslices = record.get_slice(soSupport);
const ExPolygons &supportslices = clpr_back_offs != 0 ? offset_ex(rawsupportslices, clpr_back_offs) : rawsupportslices;
// const ExPolygons &rawsupportslices = record.get_slice(soSupport);
// const ExPolygons &supportslices = clpr_back_offs != 0 ? offset_ex(rawsupportslices, clpr_back_offs) : rawsupportslices;
const ExPolygons &supportslices = record.get_slice(soSupport);
if (!supportslices.empty()) {
ClipperPolygons v = get_all_polygons(supportslices, po->instances(), is_lefth);
@ -1534,7 +1541,7 @@ SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
Inherited(print, model_object),
m_stepmask(slaposCount, true),
m_transformed_rmesh( [this](TriangleMesh& obj){
obj = m_model_object->raw_mesh(); obj.transform(m_trafo);
obj = m_model_object->raw_mesh(); obj.transform(m_trafo); obj.require_shared_vertices();
})
{
}
@ -1657,16 +1664,16 @@ Vec3d SLAPrint::relative_correction() const
{
Vec3d corr(1., 1., 1.);
if(printer_config().relative_correction.values.size() == 2) {
if(printer_config().relative_correction.values.size() >= 2) {
corr(X) = printer_config().relative_correction.values[0];
corr(Y) = printer_config().relative_correction.values[0];
corr(Z) = printer_config().relative_correction.values[1];
}
corr(Z) = printer_config().relative_correction.values.back();
}
if(material_config().material_correction.values.size() == 2) {
if(material_config().material_correction.values.size() >= 2) {
corr(X) *= material_config().material_correction.values[0];
corr(Y) *= material_config().material_correction.values[0];
corr(Z) *= material_config().material_correction.values[1];
corr(Z) *= material_config().material_correction.values.back();
}
return corr;

View file

@ -149,7 +149,10 @@ set(SLIC3R_GUI_SOURCES
)
if (APPLE)
list(APPEND SLIC3R_GUI_SOURCES Utils/RetinaHelperImpl.mm)
list(APPEND SLIC3R_GUI_SOURCES
Utils/RetinaHelperImpl.mm
Utils/MacDarkMode.mm
)
endif ()
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})

View file

@ -8,6 +8,7 @@
#include "GUI_App.hpp"
#include "PresetBundle.hpp"
#include "Gizmos/GLGizmoBase.hpp"
#include <GL/glew.h>
@ -232,7 +233,7 @@ void Bed3D::Axes::render() const
glsafe(::glEnable(GL_LIGHTING));
// x axis
glsafe(::glColor3f(1.0f, 0.0f, 0.0f));
glsafe(::glColor3fv(AXES_COLOR[0]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
@ -240,7 +241,7 @@ void Bed3D::Axes::render() const
glsafe(::glPopMatrix());
// y axis
glsafe(::glColor3f(0.0f, 1.0f, 0.0f));
glsafe(::glColor3fv(AXES_COLOR[1]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
@ -248,7 +249,7 @@ void Bed3D::Axes::render() const
glsafe(::glPopMatrix());
// z axis
glsafe(::glColor3f(0.0f, 0.0f, 1.0f));
glsafe(::glColor3fv(AXES_COLOR[2]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
render_axis(length(2));

View file

@ -67,7 +67,7 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve
}
if (! compatible) {
text += "<p align=\"right\">" + _(L("Incompatible with this Slic3r")) + "</p>";
text += "<p align=\"right\">" + wxString::Format(_(L("Incompatible with this %s")), SLIC3R_APP_NAME) + "</p>";
}
else if (! snapshot_active)
text += "<p align=\"right\"><a href=\"" + snapshot.id + "\">" + _(L("Activate")) + "</a></p>";

View file

@ -649,12 +649,6 @@ void PageTemperatures::apply_custom_config(DynamicPrintConfig &config)
ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent)
: wxPanel(parent)
/* #ys_FIXME_delete_after_testing by VK
, bg(GUI::from_u8(Slic3r::var("Slic3r_192px_transparent.png")), wxBITMAP_TYPE_PNG)
, bullet_black(GUI::from_u8(Slic3r::var("bullet_black.png")), wxBITMAP_TYPE_PNG)
, bullet_blue(GUI::from_u8(Slic3r::var("bullet_blue.png")), wxBITMAP_TYPE_PNG)
, bullet_white(GUI::from_u8(Slic3r::var("bullet_white.png")), wxBITMAP_TYPE_PNG)
*/
, bg(ScalableBitmap(parent, "Slic3r_192px_transparent.png", 192))
, bullet_black(ScalableBitmap(parent, "bullet_black.png"))
, bullet_blue(ScalableBitmap(parent, "bullet_blue.png"))
@ -675,9 +669,6 @@ ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent)
// In some cases it didn't work at all. And so wxStaticBitmap is used here instead,
// because it has all the platform quirks figured out.
auto *sizer = new wxBoxSizer(wxVERTICAL);
/* #ys_FIXME_delete_after_testing by VK
auto *logo = new wxStaticBitmap(this, wxID_ANY, bg);
*/
logo = new wxStaticBitmap(this, wxID_ANY, bg.bmp());
sizer->AddStretchSpacer();
sizer->Add(logo);
@ -786,10 +777,6 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
wxPaintDC dc(this);
/* #ys_FIXME_delete_after_testing by VK
const auto bullet_w = bullet_black.GetSize().GetWidth();
const auto bullet_h = bullet_black.GetSize().GetHeight();
*/
const auto bullet_w = bullet_black.bmp().GetSize().GetWidth();
const auto bullet_h = bullet_black.bmp().GetSize().GetHeight();
const int yoff_icon = bullet_h < em_h ? (em_h - bullet_h) / 2 : 0;
@ -804,12 +791,6 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
unsigned x = em_w/2 + item.indent * em_w;
if (i == item_active || item_hover >= 0 && i == (size_t)item_hover) {
/*#ys_FIXME_delete_after_testing by VK
dc.DrawBitmap(bullet_blue, x, y + yoff_icon, false);
}
else if (i < item_active) { dc.DrawBitmap(bullet_black, x, y + yoff_icon, false); }
else if (i > item_active) { dc.DrawBitmap(bullet_white, x, y + yoff_icon, false); }
*/
dc.DrawBitmap(bullet_blue.bmp(), x, y + yoff_icon, false);
}
else if (i < item_active) { dc.DrawBitmap(bullet_black.bmp(), x, y + yoff_icon, false); }
@ -848,6 +829,10 @@ void ConfigWizardIndex::on_mouse_move(wxMouseEvent &evt)
void ConfigWizardIndex::msw_rescale()
{
const wxSize size = GetTextExtent("m");
em_w = size.x;
em_h = size.y;
bg.msw_rescale();
SetMinSize(bg.bmp().GetSize());
logo->SetBitmap(bg.bmp());
@ -897,6 +882,29 @@ void ConfigWizard::priv::load_pages(bool custom_setup)
q->Layout();
}
void ConfigWizard::priv::init_dialog_size()
{
// Clamp the Wizard size based on screen dimensions
const auto idx = wxDisplay::GetFromWindow(q);
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
const auto disp_rect = display.GetClientArea();
wxRect window_rect(
disp_rect.x + disp_rect.width / 20,
disp_rect.y + disp_rect.height / 20,
9*disp_rect.width / 10,
9*disp_rect.height / 10);
const int width_hint = index->GetSize().GetWidth() + page_fff->get_width() + 30 * em(); // XXX: magic constant, I found no better solution
if (width_hint < window_rect.width) {
window_rect.x += (window_rect.width - width_hint) / 2;
window_rect.width = width_hint;
}
q->SetSize(window_rect);
}
bool ConfigWizard::priv::check_first_variant() const
{
return run_reason == RR_DATA_EMPTY || run_reason == RR_DATA_LEGACY;
@ -982,10 +990,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
size_t size_sum = 0;
for (const auto &model : vendor->second) { size_sum += model.second.size(); }
if (size_sum == 0) { continue; }
// This vendor needs to be installed
install_bundles.emplace_back(vendor_rsrc.second);
if (size_sum > 0) {
// This vendor needs to be installed
install_bundles.emplace_back(vendor_rsrc.second);
}
}
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
@ -1011,9 +1020,26 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
app_config->set_vendors(appconfig_vendors);
app_config->set("version_check", page_update->version_check ? "1" : "0");
app_config->set("preset_update", page_update->preset_update ? "1" : "0");
app_config->reset_selections();
preset_bundle->load_presets(*app_config);
std::string preferred_model;
// Figure out the default pre-selected printer based on the seletions in the picker.
// The default is the first selected printer model (one with at least 1 variant selected).
// The default is only applied by load_presets() if the user doesn't have a (visible) printer
// selected already.
const auto vendor_prusa = vendors.find("PrusaResearch");
const auto config_prusa = enabled_vendors.find("PrusaResearch");
if (vendor_prusa != vendors.end() && config_prusa != enabled_vendors.end()) {
for (const auto &model : vendor_prusa->second.models) {
const auto model_it = config_prusa->second.find(model.id);
if (model_it != config_prusa->second.end() && model_it->second.size() > 0) {
preferred_model = model.id;
break;
}
}
}
preset_bundle->load_presets(*app_config, preferred_model);
if (page_custom->custom_wanted()) {
page_firmware->apply_custom_config(*custom_config);
@ -1107,25 +1133,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason)
p->hscroll->SetScrollRate(30, 30);
on_window_geometry(this, [this]() {
// Clamp the Wizard size based on screen dimensions
const auto idx = wxDisplay::GetFromWindow(this);
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
const auto disp_rect = display.GetClientArea();
wxRect window_rect(
disp_rect.x + disp_rect.width / 20,
disp_rect.y + disp_rect.height / 20,
9*disp_rect.width / 10,
9*disp_rect.height / 10);
const int width_hint = p->index->GetSize().GetWidth() + p->page_fff->get_width() + 30 * p->em(); // XXX: magic constant, I found no better solution
if (width_hint < window_rect.width) {
window_rect.x += (window_rect.width - width_hint) / 2;
window_rect.width = width_hint;
}
SetSize(window_rect);
p->init_dialog_size();
});
p->btn_prev->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { this->p->index->go_prev(); });
@ -1194,7 +1202,7 @@ void ConfigWizard::on_dpi_changed(const wxRect &suggested_rect)
for (auto printer_picker: p->page_fff->printer_pickers)
msw_buttons_rescale(this, em, printer_picker->get_button_indexes());
// FIXME VK SetSize(???)
p->init_dialog_size();
Refresh();
}

View file

@ -292,6 +292,7 @@ struct ConfigWizard::priv
priv(ConfigWizard *q) : q(q) {}
void load_pages(bool custom_setup);
void init_dialog_size();
bool check_first_variant() const;
void load_vendors();

View file

@ -100,6 +100,7 @@ wxString Field::get_tooltip_text(const wxString& default_string)
{
wxString tooltip_text("");
wxString tooltip = _(m_opt.tooltip);
edit_tooltip(tooltip);
if (tooltip.length() > 0)
tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " +
(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + default_string +
@ -504,6 +505,11 @@ void SpinCtrl::BUILD() {
else tmp_value = -9999;
#ifdef __WXOSX__
propagate_value();
// Forcibly set the input value for SpinControl, since the value
// inserted from the clipboard is not updated under OSX
if (tmp_value > -9999)
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value);
#endif
}), temp->GetId());

View file

@ -794,10 +794,15 @@ bool GLCanvas3D::WarningTexture::_generate(const std::string& msg_utf8, const GL
wxString msg = GUI::from_u8(msg_utf8);
wxMemoryDC memDC;
#ifdef __WXMSW__
// set scaled application normal font as default font
wxFont font = wxGetApp().normal_font();
#else
// select default font
const float scale = canvas.get_canvas_size().get_scale_factor();
// wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale);
wxFont font = wxGetApp().normal_font();//! #ys_FIXME_experiment
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale);
#endif
font.MakeLarger();
font.MakeBold();
@ -899,7 +904,7 @@ void GLCanvas3D::WarningTexture::render(const GLCanvas3D& canvas) const
}
}
void GLCanvas3D::WarningTexture::rescale(const GLCanvas3D& canvas)
void GLCanvas3D::WarningTexture::msw_rescale(const GLCanvas3D& canvas)
{
if (m_msg_text.empty())
return;
@ -976,14 +981,16 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
const int scaled_square_contour = Px_Square_Contour * scale;
const int scaled_border = Px_Border * scale;
// select default font
// wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl);
wxFont font = wxGetApp().normal_font();//! #ys_FIXME_experiment
#ifdef __WXMSW__
// set scaled application normal font as default font
wxFont font = wxGetApp().normal_font();
// Disabling ClearType works, but the font returned is very different (much thicker) from the default.
// msw_disable_cleartype(font);
bool cleartype = is_font_cleartype(font);
#else
// select default font
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl);
bool cleartype = false;
#endif /* __WXMSW__ */
@ -3190,7 +3197,7 @@ double GLCanvas3D::get_size_proportional_to_max_bed_size(double factor) const
void GLCanvas3D::msw_rescale()
{
m_warning_texture.rescale(*this);
m_warning_texture.msw_rescale(*this);
}
bool GLCanvas3D::_is_shown_on_screen() const
@ -4994,6 +5001,10 @@ bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, con
// creates a new volume for each tool
for (Tool& tool : tools)
{
// tool.value could be invalid (as it was with https://github.com/prusa3d/Slic3r/issues/2179), we better check
if (tool.value >= tool_colors.size())
continue;
GLVolume* volume = new GLVolume(tool_colors.data() + tool.value * 4);
if (volume == nullptr)
return false;
@ -5008,7 +5019,7 @@ bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, con
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id));
if (tool != tools.end())
if (tool != tools.end() && tool->volume != nullptr)
{
tool->volume->print_zs.push_back(unscale<double>(polyline.polyline.bounding_box().min(2)));
tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.quad_indices.size());

View file

@ -354,7 +354,7 @@ private:
void render(const GLCanvas3D& canvas) const;
// function used to get an information for rescaling of the warning
void rescale(const GLCanvas3D& canvas);
void msw_rescale(const GLCanvas3D& canvas);
private:
static const unsigned char Background_Color[3];

View file

@ -125,9 +125,6 @@ void config_wizard(int reason)
if (! wxGetApp().check_unsaved_changes())
return;
// save selected preset before config wizard running
const auto printer_preset_name = wxGetApp().preset_bundle->printers.get_edited_preset().name;
try {
ConfigWizard wizard(nullptr, static_cast<ConfigWizard::RunReason>(reason));
wizard.run(wxGetApp().preset_bundle, wxGetApp().preset_updater);
@ -136,10 +133,8 @@ void config_wizard(int reason)
show_error(nullptr, e.what());
}
// select old(before config wizard running) preset
wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printer_preset_name);
// If old preset if invisible now, then first visible preset will be selected
// So, let control the case if multi-part object is on the scene and first visible preset is SLA
wxGetApp().load_current_presets();
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA &&
wxGetApp().obj_list()->has_multi_part_objects())
{

View file

@ -34,6 +34,7 @@
#include "../Utils/PresetUpdater.hpp"
#include "../Utils/PrintHost.hpp"
#include "../Utils/MacDarkMode.hpp"
#include "ConfigWizard.hpp"
#include "slic3r/Config/Snapshot.hpp"
#include "ConfigSnapshotDialog.hpp"
@ -284,10 +285,24 @@ unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
));
}
bool GUI_App::dark_mode()
{
const unsigned luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
return luma < 128;
}
bool GUI_App::dark_mode_menus()
{
#if __APPLE__
return mac_dark_mode();
#else
return dark_mode();
#endif
}
void GUI_App::init_label_colours()
{
auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
if (luma >= 128) {
if (dark_mode()) {
m_color_label_modified = wxColour(252, 77, 1);
m_color_label_sys = wxColour(26, 132, 57);
}
@ -451,7 +466,7 @@ void GUI_App::update_ui_from_settings()
mainframe->update_ui_from_settings();
}
void GUI_App::persist_window_geometry(wxTopLevelWindow *window)
void GUI_App::persist_window_geometry(wxTopLevelWindow *window, bool default_maximized)
{
const std::string name = into_u8(window->GetName());
@ -460,7 +475,7 @@ void GUI_App::persist_window_geometry(wxTopLevelWindow *window)
event.Skip();
});
window_pos_restore(window, name);
window_pos_restore(window, name, default_maximized);
on_window_geometry(window, [=]() {
window_pos_sanitize(window);
@ -663,7 +678,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comAdvanced); }, config_id_base + ConfigMenuModeAdvanced);
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comExpert); }, config_id_base + ConfigMenuModeExpert);
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode")));
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), wxString::Format(_(L("%s View Mode")), SLIC3R_APP_NAME));
local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language")));
local_menu->AppendSeparator();
@ -868,15 +883,21 @@ void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
app_config->save();
}
void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &name)
void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized)
{
if (name.empty()) { return; }
const auto config_key = (boost::format("window_%1%") % name).str();
if (! app_config->has(config_key)) { return; }
if (! app_config->has(config_key)) {
window->Maximize(default_maximized);
return;
}
auto metrics = WindowMetrics::deserialize(app_config->get(config_key));
if (! metrics) { return; }
if (! metrics) {
window->Maximize(default_maximized);
return;
}
window->SetSize(metrics->get_rect());
window->Maximize(metrics->get_maximized());

View file

@ -94,7 +94,9 @@ public:
GUI_App();
unsigned get_colour_approx_luma(const wxColour &colour);
static unsigned get_colour_approx_luma(const wxColour &colour);
static bool dark_mode();
static bool dark_mode_menus();
void init_label_colours();
void update_label_colours_from_appconfig();
void init_fonts();
@ -122,7 +124,7 @@ public:
const std::string& err);
// void notify(/*message*/);
void persist_window_geometry(wxTopLevelWindow *window);
void persist_window_geometry(wxTopLevelWindow *window, bool default_maximized = false);
void update_ui_from_settings();
bool select_language(wxArrayString & names, wxArrayLong & identifiers);
@ -174,7 +176,7 @@ public:
private:
bool on_init_inner();
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false);
void window_pos_sanitize(wxTopLevelWindow* window);
};
DECLARE_APP(GUI_App)

View file

@ -23,7 +23,7 @@ namespace GUI {
static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f };
static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f };
static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f };
static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
static const float AXES_COLOR[3][3] = { { 0.75f, 0.0f, 0.0f }, { 0.0f, 0.75f, 0.0f }, { 0.0f, 0.0f, 0.75f } };

View file

@ -129,7 +129,7 @@ DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAU
event.Skip();
});
wxGetApp().persist_window_geometry(this);
wxGetApp().persist_window_geometry(this, true);
update_ui_from_settings(); // FIXME (?)
}
@ -276,12 +276,26 @@ void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
for (auto tab : wxGetApp().tabs_list)
tab->msw_rescale();
// Workarounds for correct Window rendering after rescale
/* Even if Window is maximized during moving,
* first of all we should imitate Window resizing. So:
* 1. cancel maximization, if it was set
* 2. imitate resizing
* 3. set maximization, if it was set
*/
const bool is_maximized = this->IsMaximized();
if (is_maximized)
this->Maximize(false);
/* To correct window rendering (especially redraw of a status bar)
* we should imitate window resizing.
*/
const wxSize& sz = this->GetSize();
this->SetSize(sz.x + 1, sz.y + 1);
this->SetSize(sz);
this->Maximize(is_maximized);
}
void MainFrame::init_menubar()
@ -360,7 +374,7 @@ void MainFrame::init_menubar()
append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")),
[this](wxCommandEvent&) { repair_stl(); }, "wrench");
fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")),
append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), wxString::Format(_(L("Quit %s")), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { Close(false); });
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
@ -497,9 +511,11 @@ void MainFrame::init_menubar()
//# wxTheApp->check_version(1);
//# });
//# $versioncheck->Enable(wxTheApp->have_version_check);
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Website")), _(L("Open the Slic3r website in your browser")),
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_(L("%s &Website")), SLIC3R_APP_NAME),
wxString::Format(_(L("Open the %s website in your browser")), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://slic3r.org/"); });
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Manual")), _(L("Open the Slic3r manual in your browser")),
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_(L("%s &Manual")), SLIC3R_APP_NAME),
wxString::Format(_(L("Open the %s manual in your browser")), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); });
helpMenu->AppendSeparator();
append_menu_item(helpMenu, wxID_ANY, _(L("System &Info")), _(L("Show system information")),

View file

@ -70,7 +70,8 @@ MsgDialog::~MsgDialog() {}
// ErrorDialog
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
: MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")),
: MsgDialog(parent, wxString::Format(_(L("%s error")), SLIC3R_APP_NAME),
wxString::Format(_(L("%s has encountered an error")), SLIC3R_APP_NAME),
wxID_NONE)
, msg(msg)
{

View file

@ -307,7 +307,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
}
Line OptionsGroup::create_single_option_line(const Option& option) const {
Line retval{ _(option.opt.label), _(option.opt.tooltip) };
// Line retval{ _(option.opt.label), _(option.opt.tooltip) };
wxString tooltip = _(option.opt.tooltip);
edit_tooltip(tooltip);
Line retval{ _(option.opt.label), tooltip };
Option tmp(option);
tmp.opt.label = std::string("");
retval.append_option(tmp);

View file

@ -127,7 +127,7 @@ void PreferencesDialog::accept()
{
if (m_values.find("no_defaults") != m_values.end() ||
m_values.find("use_legacy_opengl") != m_values.end()) {
warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective.")));
warning_catcher(this, wxString::Format(_(L("You need to restart %s to make the changes effective.")), SLIC3R_APP_NAME));
}
auto app_config = get_app_config();

View file

@ -1330,4 +1330,15 @@ const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConf
return this->default_preset((opt_printer_technology == nullptr || opt_printer_technology->value == ptFFF) ? 0 : 1);
}
const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model_id) const
{
if (model_id.empty()) { return nullptr; }
const auto it = std::find_if(cbegin(), cend(), [&](const Preset &preset) {
return preset.config.opt_string("printer_model") == model_id;
});
return it != cend() ? &*it : nullptr;
}
} // namespace Slic3r

View file

@ -312,7 +312,7 @@ public:
const Preset& get_edited_preset() const { return m_edited_preset; }
// used to update preset_choice from Tab
const std::deque<Preset>& get_presets() { return m_presets; }
const std::deque<Preset>& get_presets() const { return m_presets; }
int get_idx_selected() { return m_idx_selected; }
static const std::string& get_suffix_modified();
@ -503,6 +503,8 @@ public:
PrinterPresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name = "- default -") :
PresetCollection(type, keys, defaults, default_name) {}
const Preset& default_preset_for(const DynamicPrintConfig &config) const override;
const Preset* find_by_model_id(const std::string &model_id) const;
};
} // namespace Slic3r

View file

@ -191,7 +191,7 @@ void PresetBundle::setup_directories()
}
}
void PresetBundle::load_presets(const AppConfig &config)
void PresetBundle::load_presets(const AppConfig &config, const std::string &preferred_model_id)
{
// First load the vendor specific system presets.
std::string errors_cummulative = this->load_system_presets();
@ -234,7 +234,7 @@ void PresetBundle::load_presets(const AppConfig &config)
if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative);
this->load_selections(config);
this->load_selections(config, preferred_model_id);
}
// Load system presets into this PresetBundle.
@ -324,7 +324,7 @@ void PresetBundle::load_installed_printers(const AppConfig &config)
// Load selections (current print, current filaments, current printer) from config.ini
// This is done on application start up or after updates are applied.
void PresetBundle::load_selections(const AppConfig &config)
void PresetBundle::load_selections(const AppConfig &config, const std::string &preferred_model_id)
{
// Update visibility of presets based on application vendor / model / variant configuration.
this->load_installed_printers(config);
@ -336,11 +336,21 @@ void PresetBundle::load_selections(const AppConfig &config)
std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", "sla_material"));
std::string initial_printer_profile_name = remove_ini_suffix(config.get("presets", "printer"));
// Activate print / filament / printer profiles from the config.
// If the printer profile enumerated by the config are not visible, select an alternate preset.
// Activate print / filament / printer profiles from either the config,
// or from the preferred_model_id suggestion passed in by ConfigWizard.
// If the printer profile enumerated by the config are not visible, select an alternate preset.
// Do not select alternate profiles for the print / filament profiles as those presets
// will be selected by the following call of this->update_compatible(true).
printers.select_preset_by_name(initial_printer_profile_name, true);
const Preset *initial_printer = printers.find_preset(initial_printer_profile_name);
const Preset *preferred_printer = printers.find_by_model_id(preferred_model_id);
if (preferred_printer != nullptr && (initial_printer == nullptr || !initial_printer->is_visible)) {
printers.select_preset_by_name(preferred_printer->name, true);
} else {
printers.select_preset_by_name(initial_printer_profile_name, true);
}
PrinterTechnology printer_technology = printers.get_selected_preset().printer_technology();
if (printer_technology == ptFFF) {
prints.select_preset_by_name_strict(initial_print_profile_name);

View file

@ -31,7 +31,7 @@ public:
// Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets.
// Load selections (current print, current filaments, current printer) from config.ini
// This is done just once on application start up.
void load_presets(const AppConfig &config);
void load_presets(const AppConfig &config, const std::string &preferred_model_id = "");
// Export selections (current print, current filaments, current printer) into config.ini
void export_selections(AppConfig &config);
@ -143,7 +143,7 @@ private:
// Load selections (current print, current filaments, current printer) from config.ini
// This is done just once on application start up.
void load_selections(const AppConfig &config);
void load_selections(const AppConfig &config, const std::string &preferred_model_id = "");
// Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path.
// and the external config is just referenced, not stored into user profile directory.

View file

@ -1770,9 +1770,9 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
line.widget = [this, ca_file_hint] (wxWindow* parent) {
auto txt = new wxStaticText(parent, wxID_ANY, wxString::Format("%s\n\n\t%s",
_(L("HTTPS CA File:\n\
\tOn this system, Slic3r uses HTTPS certificates from the system Certificate Store or Keychain.\n\
\tTo use a custom CA file, please import your CA file into Certificate Store / Keychain.")),
wxString::Format(_(L("HTTPS CA File:\n\
\tOn this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.\n\
\tTo use a custom CA file, please import your CA file into Certificate Store / Keychain.")), SLIC3R_APP_NAME),
ca_file_hint));
txt->SetFont(Slic3r::GUI::wxGetApp().normal_font());
auto sizer = new wxBoxSizer(wxHORIZONTAL);

View file

@ -109,7 +109,8 @@ MsgUpdateConfig::~MsgUpdateConfig() {}
// MsgDataIncompatible
MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, wxString> &incompats) :
MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxID_NONE)
MsgDialog(nullptr, wxString::Format(_(L("%s incompatibility")), SLIC3R_APP_NAME),
wxString::Format(_(L("%s configuration is incompatible")), SLIC3R_APP_NAME), wxID_NONE)
{
logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192));
@ -117,9 +118,9 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, w
"This version of %s is not compatible with currently installed configuration bundles.\n"
"This probably happened as a result of running an older %s after using a newer one.\n\n"
"You may either exit Slic3r and try again with a newer version, or you may re-run the initial configuration. "
"Doing so will create a backup snapshot of the existing configuration before installing files compatible with this Slic3r.\n"
)), SLIC3R_APP_NAME, SLIC3R_APP_NAME));
"You may either exit %s and try again with a newer version, or you may re-run the initial configuration. "
"Doing so will create a backup snapshot of the existing configuration before installing files compatible with this %s.\n"
)), SLIC3R_APP_NAME, SLIC3R_APP_NAME, SLIC3R_APP_NAME, SLIC3R_APP_NAME));
text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
content_sizer->Add(text);
@ -144,7 +145,7 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, w
content_sizer->Add(versions);
content_sizer->AddSpacer(2*VERT_SPACING);
auto *btn_exit = new wxButton(this, wxID_EXIT, _(L("Exit Slic3r")));
auto *btn_exit = new wxButton(this, wxID_EXIT, wxString::Format(_(L("Exit %s")), SLIC3R_APP_NAME));
btn_sizer->Add(btn_exit);
btn_sizer->AddSpacer(HORIZ_SPACING);
auto *btn_reconf = new wxButton(this, wxID_REPLACE, _(L("Re-configure")));
@ -187,7 +188,7 @@ MsgDataLegacy::MsgDataLegacy() :
auto *text2 = new wxStaticText(this, wxID_ANY, _(L("For more information please visit our wiki page:")));
static const wxString url("https://github.com/prusa3d/Slic3r/wiki/Slic3r-PE-1.40-configuration-update");
// The wiki page name is intentionally not localized:
auto *link = new wxHyperlinkCtrl(this, wxID_ANY, "Slic3r PE 1.40 configuration update", CONFIG_UPDATE_WIKI_URL);
auto *link = new wxHyperlinkCtrl(this, wxID_ANY, wxString::Format("%s 1.40 configuration update", SLIC3R_APP_NAME), CONFIG_UPDATE_WIKI_URL);
content_sizer->Add(text2);
content_sizer->Add(link);
content_sizer->AddSpacer(VERT_SPACING);

View file

@ -267,6 +267,13 @@ void wxDataViewTreeCtrlComboPopup::OnDataViewTreeCtrlSelection(wxCommandEvent& e
cmb->SetText(selected);
}
// edit tooltip : change Slic3r to SLIC3R_APP_KEY
// Temporary workaround for localization
void edit_tooltip(wxString& tooltip)
{
tooltip.Replace("Slic3r", SLIC3R_APP_KEY, true);
}
/* Function for rescale of buttons in Dialog under MSW if dpi is changed.
* btn_ids - vector of buttons identifiers
*/
@ -2344,8 +2351,9 @@ void ModeButton::SetState(const bool state)
void ModeButton::focus_button(const bool focus)
{
wxFont font = GetFont();
const wxFont& new_font = focus ? font.Bold() : font.GetBaseFont();
const wxFont& new_font = focus ?
Slic3r::GUI::wxGetApp().bold_font() :
Slic3r::GUI::wxGetApp().normal_font();
SetFont(new_font);

View file

@ -32,6 +32,7 @@ wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string,
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
class wxDialog;
void edit_tooltip(wxString& tooltip);
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids);
int em_unit(wxWindow* win);

View file

@ -0,0 +1,15 @@
#ifndef slic3r_MacDarkMode_hpp_
#define slic3r_MacDarkMode_hpp_
namespace Slic3r {
namespace GUI {
#if __APPLE__
extern bool mac_dark_mode();
#endif
} // namespace GUI
} // namespace Slic3r
#endif // MacDarkMode_h

View file

@ -0,0 +1,22 @@
#import "MacDarkMode.hpp"
#import <Foundation/Foundation.h>
@implementation MacDarkMode
namespace Slic3r {
namespace GUI {
bool mac_dark_mode()
{
NSString *style = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
return style && [style isEqualToString:@"Dark"];
}
}
}
@end