Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_wipe_moves

This commit is contained in:
enricoturri1966 2020-11-23 10:11:04 +01:00
commit f68cf49f3d
29 changed files with 5731 additions and 4062 deletions

View file

@ -1,11 +1,6 @@
#include "libslic3r/libslic3r.h"
#if ENABLE_GCODE_VIEWER
#include "DoubleSlider.hpp"
#include "libslic3r/GCode.hpp"
#else
#include "wxExtensions.hpp"
#include "libslic3r/GCode/PreviewData.hpp"
#endif // ENABLE_GCODE_VIEWER
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "Plater.hpp"
@ -137,14 +132,13 @@ Control::Control( wxWindow *parent,
m_line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN };
m_segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN };
const wxFont& font = GetFont();
m_font = is_osx ? font.Smaller().Smaller() : font.Smaller();
m_font = GetFont();
this->SetMinSize(get_min_size());
}
void Control::msw_rescale()
{
const wxFont& font = GUI::wxGetApp().normal_font();
m_font = is_osx ? font.Smaller().Smaller() : font.Smaller();
m_font = GUI::wxGetApp().normal_font();
m_bmp_thumb_higher.msw_rescale();
m_bmp_thumb_lower .msw_rescale();
@ -182,8 +176,7 @@ int Control::GetActiveValue() const
wxSize Control::get_min_size() const
{
const int min_side = GUI::wxGetApp().em_unit() * ( is_horizontal() ? (is_osx ? 8 : 6) : 10 );
const int min_side = GUI::wxGetApp().em_unit() * ( is_horizontal() ? 5 : 11 );
return wxSize(min_side, min_side);
}
@ -713,7 +706,7 @@ void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, LabelType l
text_pos = wxPoint(xx, pos.y - m_thumb_size.x / 2 - text_height - 1);
}
else
text_pos = wxPoint(pos.x - text_width - 1 - m_thumb_size.x, pos.y - 0.5 * text_height + 1);
text_pos = wxPoint(std::max(2, pos.x - text_width - 1 - m_thumb_size.x), pos.y - 0.5 * text_height + 1);
}
if (label_type == ltEstimatedTime)

View file

@ -2743,7 +2743,9 @@ void GCodeViewer::render_legend() const
}
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_extruder_ids) {
imgui.text(_u8L("Filament") + " " + std::to_string(i + 1) + ":");
std::string txt = _u8L("Filament");
txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1);
imgui.text(txt);
ImGui::SameLine(offset);
imgui.text(m_settings_ids.filament[i]);
}

View file

@ -1091,7 +1091,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent);
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
GLCanvas3D::ArrangeSettings load_arrange_settings()
static GLCanvas3D::ArrangeSettings load_arrange_settings()
{
GLCanvas3D::ArrangeSettings settings;
@ -2392,7 +2392,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
return;
}
if (keyCode == WXK_ESCAPE && (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item()))
if (keyCode == WXK_ESCAPE && (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item() || _deactivate_arrange_menu()))
return;
if (m_gizmos.on_char(evt))
@ -3083,7 +3083,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) {
if (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item())
if (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item() || _deactivate_arrange_menu())
return;
// If user pressed left or right button we first check whether this happened
@ -3868,11 +3868,12 @@ bool GLCanvas3D::_render_search_list(float pos_x) const
return action_taken;
}
void GLCanvas3D:: _render_arrange_popup()
bool GLCanvas3D::_render_arrange_menu(float pos_x)
{
ImGuiWrapper *imgui = wxGetApp().imgui();
float x = 0.5f * (float)get_canvas_size().get_width();
auto canvas_w = float(get_canvas_size().get_width());
const float x = pos_x * float(wxGetApp().plater()->get_camera().get_zoom()) + 0.5f * canvas_w;
imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
imgui->begin(_(L("Arrange options")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
@ -3880,17 +3881,39 @@ void GLCanvas3D:: _render_arrange_popup()
auto &appcfg = wxGetApp().app_config;
bool settings_changed = false;
if (imgui->slider_float(_(L("Gap size")), &settings.distance, 0.f, 100.f)) {
m_arrange_settings.distance = settings.distance;
appcfg->set("arrange", "min_object_distance", std::to_string(settings.distance));
settings_changed = true;
}
if (imgui->checkbox(_(L("Enable rotations")), settings.enable_rotation)) {
m_arrange_settings.enable_rotation = settings.enable_rotation;
appcfg->set("arrange", "enable_rotation", "1");
settings_changed = true;
}
ImGui::Separator();
if (imgui->button(_(L("Reset")))) {
m_arrange_settings = ArrangeSettings{};
settings_changed = true;
}
if (settings_changed) {
appcfg->set("arrange", "min_object_distance", std::to_string(m_arrange_settings.distance));
appcfg->set("arrange", "enable_rotation", m_arrange_settings.enable_rotation? "1" : "0");
}
ImGui::SameLine();
if (imgui->button(_(L("Arrange")))) {
wxGetApp().plater()->arrange();
}
imgui->end();
return settings_changed;
}
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0
@ -4305,7 +4328,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.name = "arrange";
item.icon_filename = "arrange.svg";
item.tooltip = _utf8(L("Arrange")) + " [A]\n" + _utf8(L("Arrange selection")) + " [Shift+A]";
item.tooltip = _utf8(L("Arrange")) + " [A]\n" + _utf8(L("Arrange selection")) + " [Shift+A]\n" + _utf8(L("Click right mouse button to show arrangement options"));
item.sprite_id = 3;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
@ -4313,7 +4336,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.right.render_callback = [this](float left, float right, float, float) {
if (m_canvas != nullptr)
{
_render_arrange_popup();
_render_arrange_menu(0.5f * (left + right));
}
};
if (!m_main_toolbar.add_item(item))
@ -6246,6 +6269,16 @@ bool GLCanvas3D::is_search_pressed() const
return m_main_toolbar.is_item_pressed("search");
}
bool GLCanvas3D::_deactivate_arrange_menu()
{
if (m_main_toolbar.is_item_pressed("arrange")) {
m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("arrange"), *this);
return true;
}
return false;
}
bool GLCanvas3D::_deactivate_search_toolbar_item()
{
if (is_search_pressed())

View file

@ -728,7 +728,7 @@ private:
void _render_selection_sidebar_hints() const;
bool _render_undo_redo_stack(const bool is_undo, float pos_x) const;
bool _render_search_list(float pos_x) const;
void _render_arrange_popup();
bool _render_arrange_menu(float pos_x);
void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const;
// render thumbnail using an off-screen framebuffer
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const;
@ -780,6 +780,7 @@ private:
bool _deactivate_search_toolbar_item();
bool _activate_search_toolbar_item();
bool _deactivate_collapse_toolbar_items();
bool _deactivate_arrange_menu();
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }

View file

@ -283,7 +283,7 @@ bool Preview::init(wxWindow* parent, Model* model)
wxBoxSizer* right_sizer = new wxBoxSizer(wxVERTICAL);
right_sizer->Add(m_layers_slider_sizer, 1, wxEXPAND, 0);
m_moves_slider = new DoubleSlider::Control(m_bottom_toolbar_panel, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxSize(-1, 3 * GetTextExtent("m").y), wxSL_HORIZONTAL);
m_moves_slider = new DoubleSlider::Control(m_bottom_toolbar_panel, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView);
wxBoxSizer* bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL);
@ -692,7 +692,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times);
else
m_layers_slider->SetLayersTimes(m_gcode_result->time_statistics.modes[0].layers_times);
m_layers_slider->SetLayersTimes(m_gcode_result->time_statistics.modes.front().layers_times);
m_layers_slider_sizer->Show((size_t)0);
Layout();

View file

@ -259,16 +259,15 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance)
std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
#else
std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]), ec).string());
if(ec.value() > 0) { // canonical was not able to find execitable (can happen with appimage on some systems)
ec.clear();
// Compose path with boost canonical of folder and filename
hashed_path = std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]).parent_path(), ec).string() + "/" + boost::filesystem::system_complete(argv[0]).filename().string());
if(ec.value() > 0) {
// Still not valid, process without canonical
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
}
if (ec.value() > 0) { // canonical was not able to find the executable (can happen with appimage on some systems. Does it fail on Fuse file systems?)
ec.clear();
// Compose path with boost canonical of folder and filename
hashed_path = std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]).parent_path(), ec).string() + "/" + boost::filesystem::system_complete(argv[0]).filename().string());
if (ec.value() > 0) {
// Still not valid, process without canonical
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
}
}
#endif // win32
std::string lock_name = std::to_string(hashed_path);

View file

@ -8,6 +8,7 @@
#include <boost/algorithm/string/split.hpp>
#include "libslic3r/Utils.hpp"
#include "I18N.hpp"
#include "format.hpp"
namespace Slic3r { namespace GUI {
@ -174,7 +175,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
label += ":";
wxCoord label_w, label_h;
#ifdef __WXMSW__
// when we use 2 monitors with different DPIs, GetTextExtent() return value for the primary display
// so, use dc.GetMultiLineTextExtent on Windows
wxPaintDC dc(this);
dc.SetFont(m_font);
dc.GetMultiLineTextExtent(label, &label_w, &label_h);
#else
GetTextExtent(label, &label_w, &label_h, 0, 0, &m_font);
#endif //__WXMSW__
h_pos += label_w + 1 + m_h_gap;
}
h_pos += (opt.opt.gui_type == "legend" ? 1 : 3) * blinking_button_width;
@ -231,10 +240,14 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
wxString language = wxGetApp().app_config->get("translation_language");
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
for (CtrlLine& line : ctrl_lines) {
line.is_focused = is_point_in_rect(pos, line.rect_label);
if (line.is_focused) {
tooltip = get_url(line.og_line.label_path);
if (!suppress_hyperlinks && !line.og_line.label_path.empty())
tooltip = get_url(line.og_line.label_path) +"\n\n";
tooltip += line.og_line.label_tooltip;
break;
}
@ -464,6 +477,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
{
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
if (draw_just_act_buttons) {
if (field)
draw_act_bmps(dc, wxPoint(0, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink());
@ -481,7 +495,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
bool is_url_string = false;
if (ctrl->opt_group->label_width != 0 && !label.IsEmpty()) {
const wxColour* text_clr = (option_set.size() == 1 && field ? field->label_color() : og_line.full_Label_color);
is_url_string = !og_line.label_path.IsEmpty();
is_url_string = !suppress_hyperlinks && !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label + ":", text_clr, ctrl->opt_group->label_width * ctrl->m_em_unit, is_url_string);
}
@ -521,7 +535,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
if (is_url_string)
is_url_string = false;
else if(opt == option_set.front())
is_url_string = !og_line.label_path.IsEmpty();
is_url_string = !suppress_hyperlinks && !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit, is_url_string);
}
@ -598,7 +612,7 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr
dc.GetMultiLineTextExtent(out_text, &text_width, &text_height);
pos.y = pos.y + lround((height - text_height) / 2);
if (width > 0 && is_url)
if (width > 0)
rect_label = wxRect(pos, wxSize(text_width, text_height));
wxColour old_clr = dc.GetTextForeground();
@ -660,7 +674,19 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBi
bool OG_CustomCtrl::CtrlLine::launch_browser() const
{
return is_focused && !og_line.label_path.IsEmpty() && wxLaunchDefaultBrowser(get_url(og_line.label_path));
if (get_app_config()->get("suppress_hyperlinks").empty()) {
wxString preferences_item = _L("Suppress to open hyperlink in browser");
wxString msg =
_L("PrusaSlicer will remember your action.") + "\n" +
_L("You will not be asked about it again on label hovering.") + "\n\n" +
format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto changes your choise."), preferences_item) + "\n\n" +
_L("Should we suppress to use hyperlinks in PrusaSlicer?");
wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxYES | wxNO | wxICON_INFORMATION);
get_app_config()->set("suppress_hyperlinks", dialog.ShowModal() == wxID_YES ? "1" : "0");
}
return get_app_config()->get("suppress_hyperlinks") == "0" && is_focused && !og_line.label_path.IsEmpty() && wxLaunchDefaultBrowser(get_url(og_line.label_path));
}

View file

@ -1156,7 +1156,43 @@ void Sidebar::update_sliced_info_sizer()
new_label = imperial_units ? _L("Used Filament (in³)") : _L("Used Filament (mm³)");
info_text = wxString::Format("%.2f", imperial_units ? ps.total_extruded_volume * koef : ps.total_extruded_volume);
p->sliced_info->SetTextAndShow(siFilament_mm3, info_text, new_label);
p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight));
if (ps.total_weight == 0.0)
p->sliced_info->SetTextAndShow(siFilament_g, "N/A");
else {
new_label = _L("Used Filament (g)");
info_text = wxString::Format("%.2f", ps.total_weight);
const std::vector<std::string>& filament_presets = wxGetApp().preset_bundle->filament_presets;
const PresetCollection& filaments = wxGetApp().preset_bundle->filaments;
if (ps.filament_stats.size() > 1)
new_label += ":";
for (auto filament : ps.filament_stats) {
const Preset* filament_preset = filaments.find_preset(filament_presets[filament.first], false);
if (filament_preset) {
double filament_weight;
if (ps.filament_stats.size() == 1)
filament_weight = ps.total_weight;
else {
double filament_density = filament_preset->config.opt_float("filament_density", 0);
filament_weight = filament.second * filament_density * 2.4052f * 0.001; // assumes 1.75mm filament diameter;
new_label += "\n - " + format_wxstr(_L("Filament at extruder %1%"), filament.first + 1);
info_text += wxString::Format("\n%.2f", filament_weight);
}
double spool_weight = filament_preset->config.opt_float("filament_spool_weight", 0);
if (spool_weight != 0.0) {
new_label += "\n " + _L("(weight with spool)");
info_text += wxString::Format(" (%.2f)\n", filament_weight + spool_weight);
}
}
}
p->sliced_info->SetTextAndShow(siFilament_g, info_text, new_label);
}
new_label = _L("Cost");
if (is_wipe_tower)

View file

@ -235,6 +235,14 @@ void PreferencesDialog::build()
option = Option(def, "seq_top_layer_only");
m_optgroup_gui->append_single_option_line(option);
def.label = L("Suppress to open hyperlink in browser");
def.type = coBool;
def.tooltip = L("If enabled, the descriptions of configuration parameters in settings tabs woldn't work as hyperlinks. "
"If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks.");
def.set_default_value(new ConfigOptionBool{ app_config->get("suppress_hyperlinks") == "1" });
option = Option(def, "suppress_hyperlinks");
m_optgroup_gui->append_single_option_line(option);
m_optgroup_gui->activate();
if (is_editor) {

View file

@ -1785,6 +1785,19 @@ void TabFilament::build()
optgroup->append_single_option_line("extrusion_multiplier");
optgroup->append_single_option_line("filament_density");
optgroup->append_single_option_line("filament_cost");
optgroup->append_single_option_line("filament_spool_weight");
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value)
{
update_dirty();
if (opt_key == "filament_spool_weight") {
// Change of this option influences for an update of "Sliced Info"
wxGetApp().sidebar().update_sliced_info_sizer();
wxGetApp().sidebar().Layout();
}
else
on_value_change(opt_key, value);
};
// optgroup = page->new_optgroup(_(L("Temperature")) + wxString(" °C", wxConvUTF8));
optgroup = page->new_optgroup(L("Temperature"));