mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-20 01:12:09 +00:00
Merge branch 'main' into pr/Noisyfox/13712
This commit is contained in:
@@ -65,6 +65,7 @@
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/Utils/CrealityPrint.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/ObjColorUtils.hpp"
|
||||
// For stl export
|
||||
@@ -549,6 +550,7 @@ struct Sidebar::priv
|
||||
wxStaticLine * m_staticline1;
|
||||
StaticBox* m_panel_filament_title;
|
||||
wxStaticText* m_staticText_filament_settings;
|
||||
wxStaticText* m_staticText_filament_count;
|
||||
ScalableButton * m_bpButton_add_filament;
|
||||
ScalableButton * m_bpButton_del_filament;
|
||||
ScalableButton * m_bpButton_ams_filament;
|
||||
@@ -684,6 +686,16 @@ void Sidebar::priv::layout_printer(bool isBBL, bool isDual)
|
||||
panel_nozzle_dia->Show(false);
|
||||
extruder_single_sizer->Show(false);
|
||||
}
|
||||
|
||||
// ORCA ensure printer section is visible after changing printer from printer selection dialog
|
||||
// this will inform user on printer change when printer section is collapsed
|
||||
if (m_panel_printer_content){
|
||||
bool isShown = m_panel_printer_content->IsShown();
|
||||
if(!isShown && m_text_printer_settings){
|
||||
m_text_printer_settings->SetLabel(_L("Printer")); // ensure title returns to default state
|
||||
m_panel_printer_content->Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::priv::flush_printer_sync(bool restart)
|
||||
@@ -911,54 +923,6 @@ struct DynamicFilamentList : DynamicList
|
||||
}
|
||||
};
|
||||
|
||||
struct DynamicFilamentList1Based : DynamicFilamentList
|
||||
{
|
||||
void apply_on(Choice *c) override
|
||||
{
|
||||
if (items.empty())
|
||||
update(true);
|
||||
auto cb = dynamic_cast<ComboBox *>(c->window);
|
||||
auto n = cb->GetSelection();
|
||||
cb->Clear();
|
||||
for (auto i : items) {
|
||||
cb->Append(i.first, *i.second);
|
||||
}
|
||||
if (n < cb->GetCount())
|
||||
cb->SetSelection(n);
|
||||
}
|
||||
wxString get_value(int index) override
|
||||
{
|
||||
wxString str;
|
||||
str << index+1;
|
||||
return str;
|
||||
}
|
||||
int index_of(wxString value) override
|
||||
{
|
||||
long n = 0;
|
||||
if(!value.ToLong(&n))
|
||||
return -1;
|
||||
--n;
|
||||
return (n >= 0 && n <= items.size()) ? int(n) : -1;
|
||||
}
|
||||
void update(bool force = false)
|
||||
{
|
||||
items.clear();
|
||||
if (!force && m_choices.empty())
|
||||
return;
|
||||
auto icons = get_extruder_color_icons(true);
|
||||
auto presets = wxGetApp().preset_bundle->filament_presets;
|
||||
for (int i = 0; i < presets.size(); ++i) {
|
||||
wxString str;
|
||||
std::string type;
|
||||
wxGetApp().preset_bundle->filaments.find_preset(presets[i])->get_filament_type(type);
|
||||
str << type;
|
||||
items.push_back({str, i < icons.size() ? icons[i] : nullptr});
|
||||
}
|
||||
DynamicList::update();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Check if the machine supports Junction Deviation (Marlin firmware with machine_max_junction_deviation > 0)
|
||||
static bool has_junction_deviation(const DynamicPrintConfig* printer_config)
|
||||
{
|
||||
@@ -975,7 +939,6 @@ static bool has_junction_deviation(const DynamicPrintConfig* printer_config)
|
||||
}
|
||||
|
||||
static DynamicFilamentList dynamic_filament_list;
|
||||
static DynamicFilamentList1Based dynamic_filament_list_1_based;
|
||||
|
||||
class AMSCountPopupWindow : public PopupWindow
|
||||
{
|
||||
@@ -1688,9 +1651,12 @@ Sidebar::Sidebar(Plater *parent)
|
||||
{
|
||||
Choice::register_dynamic_list("support_filament", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("support_interface_filament", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("wall_filament", &dynamic_filament_list_1_based);
|
||||
Choice::register_dynamic_list("sparse_infill_filament", &dynamic_filament_list_1_based);
|
||||
Choice::register_dynamic_list("solid_infill_filament", &dynamic_filament_list_1_based);
|
||||
Choice::register_dynamic_list("outer_wall_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("inner_wall_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("sparse_infill_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("internal_solid_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("top_surface_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("bottom_surface_filament_id", &dynamic_filament_list);
|
||||
Choice::register_dynamic_list("wipe_tower_filament", &dynamic_filament_list);
|
||||
|
||||
p->scrolled = new wxPanel(this);
|
||||
@@ -1736,7 +1702,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->m_panel_printer_title->SetBackgroundColor2(0xF1F1F1);
|
||||
|
||||
p->m_printer_icon = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "printer");
|
||||
p->m_text_printer_settings = new Label(p->m_panel_printer_title, _L("Printer"), LB_PROPAGATE_MOUSE_EVENT);
|
||||
p->m_text_printer_settings = new Label(p->m_panel_printer_title, _L("Printer"), LB_PROPAGATE_MOUSE_EVENT | wxST_ELLIPSIZE_END);
|
||||
|
||||
p->m_printer_icon->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||
//auto wizard_t = new ConfigWizard(wxGetApp().mainframe);
|
||||
@@ -1769,8 +1735,8 @@ Sidebar::Sidebar(Plater *parent)
|
||||
wxBoxSizer* h_sizer_title = new wxBoxSizer(wxHORIZONTAL);
|
||||
h_sizer_title->Add(p->m_printer_icon, 0, wxALIGN_CENTRE | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
|
||||
h_sizer_title->AddSpacer(FromDIP(SidebarProps::ElementSpacing()));
|
||||
h_sizer_title->Add(p->m_text_printer_settings, 0, wxALIGN_CENTER);
|
||||
h_sizer_title->AddStretchSpacer();
|
||||
h_sizer_title->Add(p->m_text_printer_settings, 1, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing()));
|
||||
//h_sizer_title->AddStretchSpacer();
|
||||
h_sizer_title->Add(p->m_printer_connect , 0, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing())); // used larger margin to prevent accidental clicks
|
||||
h_sizer_title->Add(p->m_printer_bbl_sync, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing())); // used larger margin to prevent accidental clicks
|
||||
h_sizer_title->Add(p->m_printer_setting, 0, wxALIGN_CENTER);
|
||||
@@ -1789,7 +1755,13 @@ Sidebar::Sidebar(Plater *parent)
|
||||
// add printer title
|
||||
scrolled_sizer->Add(p->m_panel_printer_title, 0, wxEXPAND | wxALL, 0);
|
||||
p->m_panel_printer_title->Bind(wxEVT_LEFT_UP, [this] (auto & e) {
|
||||
p->m_panel_printer_content->Show(!p->m_panel_printer_content->IsShown());
|
||||
if (!p || !p->combo_printer || !p->m_text_printer_settings || !p->m_panel_printer_content || !m_scrolled_sizer)
|
||||
return;
|
||||
// ORCA Show printer name on title when its folded to inform user without expanding it again
|
||||
bool isShown = p->m_panel_printer_content->IsShown();
|
||||
wxString title = _L("Printer") + wxString(!isShown ? "" : (" | " + p->combo_printer->GetValue()));
|
||||
p->m_text_printer_settings->SetLabel(title);
|
||||
p->m_panel_printer_content->Show(!isShown);
|
||||
m_scrolled_sizer->Layout();
|
||||
});
|
||||
|
||||
@@ -1833,19 +1805,23 @@ Sidebar::Sidebar(Plater *parent)
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
// hover state data for printer panel
|
||||
auto printer_preset_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
|
||||
|
||||
p->btn_edit_printer = new ScalableButton(p->panel_printer_preset, wxID_ANY, "edit");
|
||||
p->btn_edit_printer->SetToolTip(_L("Click to edit preset"));
|
||||
p->btn_edit_printer->Hide(); // hide for first launch
|
||||
p->btn_edit_printer->Bind(wxEVT_BUTTON, [this, panel_color](wxCommandEvent){
|
||||
p->btn_edit_printer->Bind(wxEVT_BUTTON, [this, panel_color, printer_preset_hovered](wxCommandEvent){
|
||||
p->editing_filament = -1;
|
||||
if (p->combo_printer->switch_to_tab())
|
||||
p->editing_filament = 0;
|
||||
// ORCA: FIX crash on wxGTK, directly modifying UI (self->Hide() / parent->Layout()) inside a button event can crash because callbacks are not re-entrant, leaving widgets in an inconsistent state
|
||||
wxGetApp().CallAfter([this, panel_color]() {
|
||||
wxGetApp().CallAfter([this, panel_color, printer_preset_hovered]() {
|
||||
// ORCA clicking edit button not triggers wxEVT_KILL_FOCUS wxEVT_LEAVE_WINDOW make changes manually to prevent stucked colors when opening printer settings
|
||||
if (!p || !p->panel_printer_preset || !p->btn_edit_printer)
|
||||
return;
|
||||
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
|
||||
printer_preset_hovered->clear();
|
||||
p->btn_edit_printer->Hide();
|
||||
p->panel_printer_preset->Layout();
|
||||
});
|
||||
@@ -1884,30 +1860,33 @@ Sidebar::Sidebar(Plater *parent)
|
||||
*/
|
||||
// ORCA use Show/Hide to gain text area instead using blank icon. also manages hover effect for border
|
||||
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_preset, p->btn_edit_printer, p->image_printer, p->combo_printer}) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, panel_color](wxMouseEvent &e) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
|
||||
printer_preset_hovered->insert(w);
|
||||
if(!p->combo_printer->HasFocus())
|
||||
p->panel_printer_preset->SetBorderColor(panel_color.bd_hover);
|
||||
if(!p->btn_edit_printer->IsShown()){
|
||||
p->btn_edit_printer->Show();
|
||||
p->panel_printer_preset->Layout();
|
||||
}
|
||||
e.Skip();
|
||||
});
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
|
||||
// Use event-relative coords instead of wxGetMousePosition() which
|
||||
// returns (0,0) on Wayland for global screen coordinates.
|
||||
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
|
||||
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
|
||||
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
|
||||
if (!next_w || !p->panel_printer_preset->IsDescendant(next_w)){
|
||||
if(!p->combo_printer->HasFocus())
|
||||
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
|
||||
p->btn_edit_printer->Hide();
|
||||
p->panel_printer_preset->Layout();
|
||||
}
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
|
||||
printer_preset_hovered->erase(w);
|
||||
if (printer_preset_hovered->empty() && !p->combo_printer->HasFocus())
|
||||
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
|
||||
e.Skip();
|
||||
});
|
||||
}
|
||||
// Perform show/hide in wxEVT_IDLE after enter/leave events have settled.
|
||||
// This prevents the extraneous enter/leave events generated by the
|
||||
// layout change itself from causing a feedback loop.
|
||||
Bind(wxEVT_IDLE, [this, printer_preset_hovered](wxIdleEvent &e) {
|
||||
auto hovered = !printer_preset_hovered->empty();
|
||||
if (p->btn_edit_printer->IsShown() != hovered) {
|
||||
if (hovered) {
|
||||
p->btn_edit_printer->Show();
|
||||
} else {
|
||||
p->btn_edit_printer->Hide();
|
||||
}
|
||||
p->panel_printer_preset->Layout();
|
||||
}
|
||||
});
|
||||
|
||||
// ORCA unified Nozzle diameter selection
|
||||
p->panel_nozzle_dia = new StaticBox(p->m_panel_printer_content);
|
||||
@@ -1953,19 +1932,17 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
|
||||
|
||||
// highlight border on hover
|
||||
auto nozzle_dia_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
|
||||
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_nozzle_dia, p->label_nozzle_title, p->label_nozzle_type, p->combo_nozzle_dia}) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, panel_color](wxMouseEvent &e) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
|
||||
nozzle_dia_hovered->insert(w);
|
||||
if(!p->combo_nozzle_dia->HasFocus())
|
||||
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_hover);
|
||||
e.Skip();
|
||||
});
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
|
||||
// Use event-relative coords instead of wxGetMousePosition() which
|
||||
// returns (0,0) on Wayland for global screen coordinates.
|
||||
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
|
||||
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
|
||||
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
|
||||
if (!p->combo_nozzle_dia->HasFocus() && (!next_w || !p->panel_nozzle_dia->IsDescendant(next_w)))
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
|
||||
nozzle_dia_hovered->erase(w);
|
||||
if (nozzle_dia_hovered->empty() && !p->combo_nozzle_dia->HasFocus())
|
||||
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
|
||||
e.Skip();
|
||||
});
|
||||
@@ -2025,21 +2002,19 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->combo_printer_bed->Bind(wxEVT_KILL_FOCUS, [this, bed_focus_bg](auto& e) {bed_focus_bg(false); e.Skip();});
|
||||
|
||||
// highlight border on hover
|
||||
auto printer_bed_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
|
||||
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_bed, p->image_printer_bed, p->combo_printer_bed}) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
|
||||
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
|
||||
printer_bed_hovered->insert(w);
|
||||
if(!p->combo_printer_bed->HasFocus())
|
||||
p->panel_printer_bed->SetBorderColor(panel_color.bd_hover);
|
||||
if(w == p->image_printer_bed && !p->combo_printer_bed->is_drop_down()) // dont trigger while combo open
|
||||
on_enter_image_printer_bed(e);
|
||||
e.Skip();
|
||||
});
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
|
||||
// Use event-relative coords instead of wxGetMousePosition() which
|
||||
// returns (0,0) on Wayland for global screen coordinates.
|
||||
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
|
||||
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
|
||||
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
|
||||
if (!p->combo_printer_bed->HasFocus() && (!next_w || !p->panel_printer_bed->IsDescendant(next_w)))
|
||||
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
|
||||
printer_bed_hovered->erase(w);
|
||||
if (printer_bed_hovered->empty() && !p->combo_printer_bed->HasFocus())
|
||||
p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
|
||||
if(w == p->image_printer_bed)
|
||||
on_leave_image_printer_bed(e);
|
||||
@@ -2140,6 +2115,8 @@ Sidebar::Sidebar(Plater *parent)
|
||||
return;
|
||||
p->m_panel_filament_content->Show(!p->m_panel_filament_content->IsShown());
|
||||
m_scrolled_sizer->Layout();
|
||||
|
||||
CallAfter([this]{update_filaments_counter(true);}); // call after all UI processing done
|
||||
});
|
||||
|
||||
wxBoxSizer* bSizer39;
|
||||
@@ -2147,11 +2124,13 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->m_filament_icon = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "filament");
|
||||
p->m_staticText_filament_settings = new Label(p->m_panel_filament_title, _L("Project Filaments"), LB_PROPAGATE_MOUSE_EVENT);
|
||||
bSizer39->Add(p->m_filament_icon, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
|
||||
bSizer39->AddSpacer(FromDIP(SidebarProps::ElementSpacing()));
|
||||
bSizer39->Add( p->m_staticText_filament_settings, 0, wxALIGN_CENTER );
|
||||
bSizer39->Add(FromDIP(10), 0, 0, 0, 0);
|
||||
bSizer39->Add(p->m_staticText_filament_settings, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()));
|
||||
bSizer39->SetMinSize(-1, FromDIP(30));
|
||||
|
||||
p->m_staticText_filament_count = new Label(p->m_panel_filament_title, "(0)", LB_PROPAGATE_MOUSE_EVENT);
|
||||
bSizer39->Add(p->m_staticText_filament_count, 0, wxALIGN_CENTER );
|
||||
bSizer39->Add(FromDIP(10), 0, 0, 0, 0);
|
||||
|
||||
p->m_panel_filament_title->SetSizer( bSizer39 );
|
||||
p->m_panel_filament_title->Layout();
|
||||
auto spliter_1 = new ::StaticLine(p->scrolled);
|
||||
@@ -2186,6 +2165,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
add_btn->SetToolTip(_L("Add one filament"));
|
||||
add_btn->Bind(wxEVT_BUTTON, [this, scrolled_sizer](wxCommandEvent& e){
|
||||
add_filament();
|
||||
update_filaments_counter();
|
||||
});
|
||||
p->m_bpButton_add_filament = add_btn;
|
||||
|
||||
@@ -2195,6 +2175,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
del_btn->SetToolTip(_L("Remove last filament"));
|
||||
del_btn->Bind(wxEVT_BUTTON, [this, scrolled_sizer](wxCommandEvent &e) {
|
||||
delete_filament();
|
||||
update_filaments_counter();
|
||||
});
|
||||
p->m_bpButton_del_filament = del_btn;
|
||||
|
||||
@@ -2534,7 +2515,11 @@ void Sidebar::update_all_preset_comboboxes()
|
||||
else
|
||||
p->m_bpButton_ams_filament->Hide();
|
||||
|
||||
auto print_btn_type = MainFrame::PrintSelectType::eExportGcode;
|
||||
// Orca: with "Support 3MF as gcode" (use_3mf) the local export is a .gcode.3mf bundle, so when no
|
||||
// printer host/IP is configured the default action is "Export plate sliced file" (mirrors the
|
||||
// print dropdown) instead of "Export G-code file".
|
||||
auto print_btn_type = cfg.opt_bool("use_3mf") ? MainFrame::PrintSelectType::eExportSlicedFile
|
||||
: MainFrame::PrintSelectType::eExportGcode;
|
||||
wxString url = from_u8(PrintHost::get_print_host_webui(&cfg));
|
||||
wxString apikey;
|
||||
if(url.empty())
|
||||
@@ -2961,6 +2946,26 @@ void Sidebar::update_filaments_area_height()
|
||||
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
|
||||
min_size.y = p->m_panel_filament_content->GetMaxHeight();
|
||||
p->m_panel_filament_content->SetMinSize({-1, min_size.y});
|
||||
|
||||
update_filaments_counter();
|
||||
}
|
||||
|
||||
void Sidebar::update_filaments_counter(bool force_layout)
|
||||
// ORCA
|
||||
{
|
||||
int current_count = p->combos_filament.size();
|
||||
int preferred_count = std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count"));
|
||||
bool isShown = p->m_panel_filament_content->IsShown();
|
||||
auto counter = p->m_staticText_filament_count;
|
||||
|
||||
counter->SetLabel("(" + std::to_string(current_count) + ")"); // update counter on every change
|
||||
if(current_count > preferred_count || !isShown)
|
||||
counter->Show();
|
||||
else if (isShown) // hide when list is visible and short enough
|
||||
counter->Hide();
|
||||
|
||||
if(force_layout)
|
||||
m_scrolled_sizer->Layout();
|
||||
}
|
||||
|
||||
void Sidebar::msw_rescale()
|
||||
@@ -3268,6 +3273,13 @@ void Sidebar::add_filament() {
|
||||
if (p->combos_filament.size() >= MAXIMUM_EXTRUDER_NUMBER) return;
|
||||
wxColour new_col = Plater::get_next_color_for_filament();
|
||||
add_custom_filament(new_col);
|
||||
|
||||
auto filament_list = p->m_panel_filament_content;
|
||||
if(!filament_list->IsShown()){
|
||||
filament_list->Show(); // ORCA show list if its folded
|
||||
m_scrolled_sizer->Layout();
|
||||
}
|
||||
filament_list->Scroll(-1, INT_MAX); // ORCA scroll to end of list on changes to inform user about filament count
|
||||
}
|
||||
|
||||
void Sidebar::delete_filament(size_t filament_id, int replace_filament_id) {
|
||||
@@ -3300,6 +3312,14 @@ void Sidebar::delete_filament(size_t filament_id, int replace_filament_id) {
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
|
||||
wxGetApp().plater()->update();
|
||||
|
||||
auto filament_list = p->m_panel_filament_content;
|
||||
if(!filament_list->IsShown()){
|
||||
filament_list->Show(); // ORCA show list if its folded
|
||||
m_scrolled_sizer->Layout();
|
||||
}
|
||||
|
||||
filament_list->Scroll(-1, INT_MAX); // ORCA scroll to end of list on changes to inform user about filament count
|
||||
}
|
||||
|
||||
void Sidebar::change_filament(size_t from_id, size_t to_id)
|
||||
@@ -3800,6 +3820,7 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish pop_finsish_sync_ams_dialog";
|
||||
}
|
||||
|
||||
|
||||
bool Sidebar::should_show_SEMM_buttons()
|
||||
{
|
||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||
@@ -3840,7 +3861,6 @@ void Sidebar::show_SEMM_buttons()
|
||||
void Sidebar::update_dynamic_filament_list()
|
||||
{
|
||||
dynamic_filament_list.update();
|
||||
dynamic_filament_list_1_based.update();
|
||||
}
|
||||
|
||||
PlaterPresetComboBox* Sidebar::printer_combox()
|
||||
@@ -4686,6 +4706,7 @@ struct Plater::priv
|
||||
}
|
||||
|
||||
void process_validation_warning(StringObjectException const &warning) const;
|
||||
void process_validation_warnings(const std::vector<StringObjectException> &warnings) const;
|
||||
|
||||
bool background_processing_enabled() const {
|
||||
#ifdef SUPPORT_BACKGROUND_PROCESSING
|
||||
@@ -4994,7 +5015,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
"extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
|
||||
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
|
||||
"layer_height", "initial_layer_print_height", "min_layer_height", "max_layer_height",
|
||||
"wall_loops", "wall_filament", "sparse_infill_density", "sparse_infill_filament", "top_shell_layers",
|
||||
"wall_loops", "outer_wall_filament_id", "inner_wall_filament_id", "sparse_infill_density", "sparse_infill_filament_id", "top_shell_layers",
|
||||
"enable_support", "support_filament", "support_interface_filament",
|
||||
"support_top_z_distance", "support_bottom_z_distance", "raft_layers",
|
||||
"wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extra_flow", "wipe_tower_max_purge_speed",
|
||||
@@ -5469,7 +5490,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
std::string last_backup = last;
|
||||
std::string originfile;
|
||||
if (Slic3r::has_restore_data(last_backup, originfile)) {
|
||||
auto result = MessageDialog(this->q, _L("Previous unsaved project detected, do you want to restore it?"), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Restore"), wxYES_NO | wxYES_DEFAULT | wxCENTRE).ShowModal();
|
||||
auto result = MessageDialog(this->q, _L("Previously unsaved items have been detected. Do you want to restore them\?"), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Restore"), wxYES_NO | wxYES_DEFAULT | wxCENTRE).ShowModal();
|
||||
if (result == wxID_YES) {
|
||||
this->q->load_project(from_path(last_backup), from_path(originfile));
|
||||
Slic3r::backup_soon();
|
||||
@@ -5669,9 +5690,9 @@ wxColour Plater::get_next_color_for_filament()
|
||||
wxString Plater::get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning)
|
||||
{
|
||||
if (warning.msg == BED_TEMP_TOO_HIGH_THAN_FILAMENT) {
|
||||
return _L("The current hot bed temperature is relatively high. The nozzle may be clogged when printing this filament in a closed enclosure. Please open the front door and/or remove the upper glass.");
|
||||
return _L("The current heatbed temperature is relatively high. The nozzle may clog when printing this filament in a closed environment. Please open the front door and/or remove the upper glass.");
|
||||
} else if (warning.msg == NOZZLE_HRC_CHECKER) {
|
||||
return _L("The nozzle hardness required by the filament is higher than the default nozzle hardness of the printer. Please replace the hardened nozzle or filament, otherwise, the nozzle will be attrited or damaged.");
|
||||
return _L("The nozzle hardness required by the filament is higher than the default nozzle hardness of the printer. Please replace the hardened nozzle or filament, otherwise, the nozzle will be worn down or damaged.");
|
||||
} else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) {
|
||||
return _L("Enabling traditional timelapse photography may cause surface imperfections. It is recommended to change to smooth mode.");
|
||||
} else if (warning.msg == NOT_GENERATE_TIMELAPSE) {
|
||||
@@ -6152,7 +6173,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
file_version.to_string_sf(), std::string(SLIC3R_APP_FULL_NAME), app_version.to_string_sf());
|
||||
text += "\n";
|
||||
wxString context = text;
|
||||
wxString append = _L("You'd better upgrade your software.\n");
|
||||
wxString append = _L("You should update your software.\n");
|
||||
context += "\n\n";
|
||||
context += append;
|
||||
log_and_show_3mf_info(context, newer_3mf_title);
|
||||
@@ -6221,7 +6242,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
file_version.to_string(), slic3r_version.to_string());
|
||||
text += "\n";
|
||||
wxString context = text;
|
||||
wxString append = _L("You'd better upgrade your software.\n");
|
||||
wxString append = _L("You should update your software.\n");
|
||||
context += "\n\n";
|
||||
context += append;
|
||||
log_and_show_3mf_info(context, bambu_project_title);
|
||||
@@ -6276,6 +6297,10 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
}
|
||||
|
||||
// ORCA: legacy feature-filament default migration (1 -> 0) is now handled
|
||||
// uniformly in PrintConfigDef::handle_legacy() via the old->new key rename
|
||||
// (wall_filament -> wall_filament_id, etc.), which also covers saved presets.
|
||||
|
||||
// plate data
|
||||
if (plate_data.size() > 0) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", import 3mf UPDATE_GCODE_RESULT \n");
|
||||
@@ -6344,12 +6369,12 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("%1%: %2%")%it->first %it->second;
|
||||
//
|
||||
NotificationManager *notify_manager = q->get_notification_manager();
|
||||
std::string error_message = L("Invalid values found in the 3MF:");
|
||||
std::string error_message = _u8L("Invalid values found in the 3MF:");
|
||||
error_message += "\n";
|
||||
for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
|
||||
error_message += "-" + it->first + ": " + it->second + "\n";
|
||||
error_message += "\n";
|
||||
error_message += L("Please correct them in the param tabs");
|
||||
error_message += _u8L("Please correct them in the Param tabs");
|
||||
notify_manager->bbl_show_3mf_warn_notification(error_message);
|
||||
}
|
||||
}
|
||||
@@ -6610,7 +6635,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
|
||||
if (!boost::iends_with(path.string(), ".obj")) { return; }
|
||||
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
ObjColorDialog color_dlg(nullptr, in_out, extruder_colours);
|
||||
ObjColorDialog color_dlg(nullptr, in_out, extruder_colours, Sidebar::should_show_SEMM_buttons());
|
||||
if (color_dlg.ShowModal() != wxID_OK) {
|
||||
in_out.filament_ids.clear();
|
||||
}
|
||||
@@ -6637,7 +6662,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
if (!isUtf8StepFile) {
|
||||
const auto no_warn = wxGetApp().app_config->get_bool("step_not_utf8_no_warn");
|
||||
if (!no_warn) {
|
||||
MessageDialog dlg(nullptr, _L("Name of components inside STEP file is not UTF8 format!") + "\n\n" + _L("The name may show garbage characters!"),
|
||||
MessageDialog dlg(nullptr, _L("Component name(s) inside step file not in UTF8 format!") + "\n\n" + _L("Because of unsupported text encoding, garbage characters may appear!"),
|
||||
wxString(SLIC3R_APP_FULL_NAME " - ") + _L("Attention!"), wxOK | wxICON_INFORMATION);
|
||||
dlg.show_dsa_button(_L("Remember my choice."));
|
||||
dlg.ShowModal();
|
||||
@@ -6750,7 +6775,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
else if (model.looks_like_saved_in_meters()) {
|
||||
// BBS do not handle look like in meters
|
||||
MessageDialog dlg(q,
|
||||
format_wxstr(_L("The object from file %s is too small, and maybe in meters or inches.\n Do you want to scale to millimeters?"),
|
||||
format_wxstr(_L("The object from file %s is too small, and may be in meters or inches.\n Do you want to scale to millimeters\?"),
|
||||
from_path(filename)),
|
||||
_L("Object too small"), wxICON_QUESTION | wxYES_NO);
|
||||
int answer = dlg.ShowModal();
|
||||
@@ -6758,7 +6783,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
} else if (model.looks_like_imperial_units()) {
|
||||
// BBS do not handle look like in meters
|
||||
MessageDialog dlg(q,
|
||||
format_wxstr(_L("The object from file %s is too small, and maybe in meters or inches.\n Do you want to scale to millimeters?"),
|
||||
format_wxstr(_L("The object from file %s is too small, and may be in meters or inches.\n Do you want to scale to millimeters\?"),
|
||||
from_path(filename)),
|
||||
_L("Object too small"), wxICON_QUESTION | wxYES_NO);
|
||||
int answer = dlg.ShowModal();
|
||||
@@ -6789,10 +6814,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
|
||||
if (!is_project_file && model.looks_like_multipart_object()) {
|
||||
MessageDialog msg_dlg(q, _L(
|
||||
"This file contains several objects positioned at multiple heights.\n"
|
||||
"Instead of considering them as multiple objects, should \n"
|
||||
"the file be loaded as a single object having multiple parts?") + "\n",
|
||||
MessageDialog msg_dlg(q, _L("This file contains several objects positioned at multiple heights.\nInstead of considering them as multiple objects, should \nthe file be loaded as a single object with multiple parts\?") + "\n",
|
||||
_L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (msg_dlg.ShowModal() == wxID_YES) {
|
||||
model.convert_multipart_object(filaments_cnt);
|
||||
@@ -6890,7 +6912,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
int single_object_answer = false;
|
||||
if (ask_multi) {
|
||||
RichMessageDialog dlg(q, _L("Load these files as a single object with multiple parts?\n"),
|
||||
_L("Object with multiple parts was detected"), wxICON_QUESTION | wxYES_NO);
|
||||
_L("An object with multiple parts was detected"), wxICON_QUESTION | wxYES_NO);
|
||||
|
||||
dlg.ShowCheckBox(_L("Auto-Drop"), true);
|
||||
single_object_answer = dlg.ShowModal();
|
||||
@@ -6931,12 +6953,12 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
double preset_nozzle_diameter = 0.4;
|
||||
const ConfigOption *opt = printer_preset.config.option("nozzle_diameter");
|
||||
if (opt) preset_nozzle_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
|
||||
float machine_nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||
|
||||
std::string machine_type = obj->printer_type;
|
||||
if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) machine_type = "C12";
|
||||
|
||||
if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || !is_approx((float) preset_nozzle_diameter, machine_nozzle_diameter)) {
|
||||
bool nozzle_mismatch = !obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(0, (float) preset_nozzle_diameter);
|
||||
if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || nozzle_mismatch) {
|
||||
Preset *machine_preset = get_printer_preset(obj);
|
||||
if (machine_preset != nullptr) {
|
||||
std::string printer_model = machine_preset->config.option<ConfigOptionString>("printer_model")->value;
|
||||
@@ -7351,7 +7373,7 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
||||
case FT_3MF:
|
||||
{
|
||||
output_file.replace_extension("3mf");
|
||||
dlg_title = _L("Save file as:");
|
||||
dlg_title = _L("Save file as");
|
||||
break;
|
||||
}
|
||||
case FT_OBJ:
|
||||
@@ -7383,7 +7405,7 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
||||
boost::system::error_code ec;
|
||||
if (boost::filesystem::exists(into_u8(out_path), ec)) {
|
||||
auto result = MessageBox(q->GetHandle(),
|
||||
wxString::Format(_L("The file %s already exists\nDo you want to replace it?"), out_path),
|
||||
wxString::Format(_L("The file %s already exists.\nDo you want to replace it\?"), out_path),
|
||||
_L("Confirm Save As"),
|
||||
MB_YESNO | MB_ICONWARNING);
|
||||
if (result != IDYES)
|
||||
@@ -7517,9 +7539,7 @@ bool Plater::priv::delete_object_from_model(size_t obj_idx, bool refresh_immedia
|
||||
ModelObject *obj = model.objects[obj_idx];
|
||||
if (obj->is_cut()) {
|
||||
InfoDialog dialog(q, _L("Delete object which is a part of cut object"),
|
||||
_L("You try to delete an object which is a part of a cut object.\n"
|
||||
"This action will break a cut correspondence.\n"
|
||||
"After that model consistency can't be guaranteed."),
|
||||
_L("You are trying to delete an object which is a part of a cut object.\nThis action will break a cut correspondence.\nAfter that, model consistency can\'t be guaranteed."),
|
||||
false, wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING);
|
||||
dialog.SetButtonLabel(wxID_YES, _L("Delete"));
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
@@ -7741,7 +7761,7 @@ void Plater::priv::split_object(int obj_idx, bool auto_drop /* = true */)
|
||||
};
|
||||
bool split_auto_drop = auto_drop;
|
||||
if (current_model_object->instances[0]->auto_drop && is_atleast_one_floating()) {
|
||||
MessageDialog dlg(q, _L("Disable Auto-Drop to preserve z positioning?\n"),
|
||||
MessageDialog dlg(q, _L("Disable Auto-Drop to preserve Z positioning?\n"),
|
||||
_L("Object with floating parts was detected"), wxICON_QUESTION | wxYES_NO);
|
||||
|
||||
if (dlg.ShowModal() == wxID_YES)
|
||||
@@ -8006,6 +8026,15 @@ void Plater::priv::process_validation_warning(StringObjectException const &warni
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::priv::process_validation_warnings(const std::vector<StringObjectException> &warnings) const
|
||||
{
|
||||
// ValidateWarning stacks by text (m_multiple_types), so clear the stale set before re-adding.
|
||||
notification_manager->close_notification_of_type(NotificationType::ValidateWarning);
|
||||
for (const StringObjectException &warning : warnings)
|
||||
if (!warning.string.empty())
|
||||
process_validation_warning(warning);
|
||||
}
|
||||
|
||||
|
||||
// Update background processing thread from the current config and Model.
|
||||
// Returns a bitmask of UpdateBackgroundProcessReturnState.
|
||||
@@ -8086,14 +8115,14 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
|
||||
|
||||
//BBS: add is_warning logic
|
||||
StringObjectException warning;
|
||||
std::vector<StringObjectException> warnings;
|
||||
//BBS: refine seq-print logic
|
||||
Polygons polygons;
|
||||
std::vector<std::pair<Polygon, float>> height_polygons;
|
||||
StringObjectException err = background_process.validate(&warning, &polygons, &height_polygons);
|
||||
StringObjectException err = background_process.validate(&warnings, &polygons, &height_polygons);
|
||||
// update string by type
|
||||
q->post_process_string_object_exception(err);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warning=%2%")%err.string%warning.string;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warnings=%2%")%err.string%warnings.size();
|
||||
|
||||
if (err.string.empty()) {
|
||||
this->partplate_list.get_curr_plate()->update_apply_result_invalid(false);
|
||||
@@ -8104,9 +8133,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
if (invalidated != Print::APPLY_STATUS_UNCHANGED && background_processing_enabled())
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_RESTART;
|
||||
|
||||
// Pass a warning from validation and either show a notification,
|
||||
// or hide the old one.
|
||||
process_validation_warning(warning);
|
||||
process_validation_warnings(warnings);
|
||||
if (printer_technology == ptFFF) {
|
||||
view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
view3D->get_canvas3d()->set_as_dirty();
|
||||
@@ -8119,7 +8146,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
// Show error as notification.
|
||||
notification_manager->push_validate_error_notification(err);
|
||||
//also update the warnings
|
||||
process_validation_warning(warning);
|
||||
process_validation_warnings(warnings);
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
if (printer_technology == ptFFF) {
|
||||
const Print* print = background_process.fff_print();
|
||||
@@ -8436,7 +8463,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
|
||||
}
|
||||
|
||||
if (new_model.objects.size() > 1 || new_model.objects.front()->volumes.size() > 1) {
|
||||
MessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
MessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
@@ -8528,7 +8555,7 @@ void Plater::priv::replace_with_stl()
|
||||
|
||||
fs::path out_path = dialog.GetPath().ToUTF8().data();
|
||||
if (out_path.empty()) {
|
||||
MessageDialog dlg(q, _L("File for the replace wasn't selected"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
MessageDialog dlg(q, _L("File for the replacement wasn\'t selected"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
@@ -8612,7 +8639,7 @@ void Plater::priv::replace_all_with_stl()
|
||||
|
||||
fs::path out_path = dialog.GetPath().ToUTF8().data();
|
||||
if (out_path.empty()) {
|
||||
MessageDialog dlg(q, _L("Directory for the replace wasn't selected"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
MessageDialog dlg(q, _L("Directory for the replace wasn't selected"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||
dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
@@ -8870,7 +8897,7 @@ void Plater::priv::reload_from_disk()
|
||||
auto obj_color_fun = [this, &path](ObjDialogInOut &in_out) {
|
||||
if (!boost::iends_with(path, ".obj")) { return; }
|
||||
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
ObjColorDialog color_dlg(nullptr, in_out, extruder_colours);
|
||||
ObjColorDialog color_dlg(nullptr, in_out, extruder_colours, Sidebar::should_show_SEMM_buttons());
|
||||
if (color_dlg.ShowModal() != wxID_OK) {
|
||||
in_out.filament_ids.clear();
|
||||
}
|
||||
@@ -9647,7 +9674,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
|
||||
const auto& extruders = obj->GetExtderSystem()->GetExtruders();
|
||||
for (const DevExtder &extruder : extruders) {
|
||||
if (!is_approx(extruder.GetNozzleDiameter(), float(preset_nozzle_diameter))) {
|
||||
if (!obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(extruder.GetExtId(), float(preset_nozzle_diameter))) {
|
||||
same_nozzle_diameter = false;
|
||||
}
|
||||
}
|
||||
@@ -9665,6 +9692,12 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
wxGetApp().get_tab(preset_type)->select_preset(preset_name);
|
||||
}
|
||||
|
||||
// ORCA: Always refresh the selected filament combo so its color swatch (clr_picker)
|
||||
// matches the chosen preset. update_ams_color() (in OnSelect) updates the project
|
||||
// filament color when the preset defines one; this repaints the swatch to match.
|
||||
if (preset_type == Preset::TYPE_FILAMENT)
|
||||
combo->update();
|
||||
|
||||
// update plater with new config
|
||||
q->on_config_change(wxGetApp().preset_bundle->full_config());
|
||||
if (preset_type == Preset::TYPE_PRINTER) {
|
||||
@@ -10284,7 +10317,7 @@ void Plater::priv::on_action_print_plate(SimpleEvent&)
|
||||
m_select_machine_dlg->prepare(partplate_list.get_curr_plate_index());
|
||||
m_select_machine_dlg->ShowModal();
|
||||
} else {
|
||||
q->send_gcode_legacy(PLATE_CURRENT_IDX, nullptr, true);
|
||||
q->send_gcode_legacy(PLATE_CURRENT_IDX, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10385,7 +10418,7 @@ void Plater::priv::on_action_print_all(SimpleEvent&)
|
||||
m_select_machine_dlg->prepare(PLATE_ALL_IDX);
|
||||
m_select_machine_dlg->ShowModal();
|
||||
} else {
|
||||
q->send_gcode_legacy(PLATE_ALL_IDX, nullptr, true);
|
||||
q->send_gcode_legacy(PLATE_ALL_IDX, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12075,8 +12108,8 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
|
||||
auto check = [this,&transfer_preset_changes](bool yes_or_no) {
|
||||
m_new_project_and_check_state = true;
|
||||
wxString header = _L("Some presets are modified.") + "\n" +
|
||||
(yes_or_no ? _L("You can keep the modified presets to the new project or discard them") :
|
||||
_L("You can keep the modified presets to the new project, discard or save changes as new presets."));
|
||||
(yes_or_no ? _L("You can keep the modified presets for the new project or discard them") :
|
||||
_L("You can keep the modified presets for the new project, discard, or save changes as new presets."));
|
||||
int act_buttons = ActionButtons::KEEP | ActionButtons::REMEMBER_CHOISE;
|
||||
if (!yes_or_no)
|
||||
act_buttons |= ActionButtons::SAVE;
|
||||
@@ -12296,7 +12329,7 @@ int Plater::save_project(bool saveAs)
|
||||
save_strategy = save_strategy | SaveStrategy::FullPathSources;
|
||||
}
|
||||
if (export_3mf(into_path(filename), save_strategy) < 0) {
|
||||
MessageDialog(this, _L("Failed to save the project.\nPlease check whether the folder exists online or if other programs open the project file."),
|
||||
MessageDialog(this, _L("Failed to save the project.\nPlease check whether the folder exists online or if other programs have the project file open."),
|
||||
_L("Save project"), wxOK | wxICON_WARNING).ShowModal();
|
||||
return wxID_CANCEL;
|
||||
}
|
||||
@@ -12411,7 +12444,7 @@ void Plater::import_model_id(wxString download_info)
|
||||
|
||||
//check file suffix
|
||||
if (!extension.Contains(".3mf")) {
|
||||
msg = _L("Download failed, unknown file format.");
|
||||
msg = _L("Download failed; unknown file format.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12486,7 +12519,7 @@ void Plater::import_model_id(wxString download_info)
|
||||
}
|
||||
|
||||
if (size_limit) {
|
||||
msg = _L("Download failed, File size exception.");
|
||||
msg = _L("Download failed; File size exception.");
|
||||
}
|
||||
else {
|
||||
msg = wxString::Format(_L("Project downloaded %d%%"), percent);
|
||||
@@ -13397,8 +13430,6 @@ void Plater::calib_VFA(const Calib_Params& params)
|
||||
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
|
||||
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
|
||||
printer_config->set_key_value("input_shaping_emit", new ConfigOptionBool{true});
|
||||
printer_config->set_key_value("input_shaping_type", new ConfigOptionEnum<InputShaperType>(InputShaperType::Disable));
|
||||
filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 });
|
||||
set_config_values<bool, ConfigOptionBoolsNullable>(print_config, "enable_overhang_speed", false);
|
||||
print_config->set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
|
||||
@@ -13744,8 +13775,8 @@ void Plater::load_gcode(const wxString& filename)
|
||||
p->preview->get_canvas3d()->zoom_to_plate(0);
|
||||
|
||||
if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) {
|
||||
MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid G-code."),
|
||||
wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error occurs while loading G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
|
||||
MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("Does not contain valid G-code."),
|
||||
wxString(GCODEVIEWER_APP_NAME) + " - " + _L("An Error has occurred while loading the G-code file."), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
|
||||
set_project_filename(DEFAULT_PROJECT_NAME);
|
||||
} else {
|
||||
set_project_filename(filename);
|
||||
@@ -14215,7 +14246,7 @@ bool Plater::load_files(const wxArrayString& filenames)
|
||||
else if (normal_paths.empty()){
|
||||
//only gcode files
|
||||
if (gcode_paths.size() > 1) {
|
||||
show_info(this, _L("Only one G-code file can be opened at the same time."), _L("G-code loading"));
|
||||
show_info(this, _L("Only one G-code file can be opened at a time."), _L("G-code loading"));
|
||||
return false;
|
||||
}
|
||||
load_gcode(from_path(gcode_paths.front()));
|
||||
@@ -14223,7 +14254,7 @@ bool Plater::load_files(const wxArrayString& filenames)
|
||||
}
|
||||
|
||||
if (!gcode_paths.empty()) {
|
||||
show_info(this, _L("G-code files cannot be loaded with models together!"), _L("G-code loading"));
|
||||
show_info(this, _L("G-code files and models cannot be loaded together!"), _L("G-code loading"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -14275,7 +14306,7 @@ bool Plater::load_files(const wxArrayString& filenames)
|
||||
if (this->m_only_gcode || this->m_exported_file) {
|
||||
if ((loadfiles_type == LoadFilesType::SingleOther)
|
||||
|| (loadfiles_type == LoadFilesType::MultipleOther)) {
|
||||
show_info(this, _L("Cannot add models when in preview mode!"), _L("Add Models"));
|
||||
show_info(this, _L("Unable to add models in preview mode"), _L("Add Models"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -14595,7 +14626,7 @@ void Plater::reset(bool apply_presets_change) { p->reset(apply_presets_change);
|
||||
void Plater::reset_with_confirm()
|
||||
{
|
||||
if (p->model.objects.empty() || MessageDialog(static_cast<wxWindow *>(this), _L("All objects will be removed, continue?"),
|
||||
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE)
|
||||
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Delete All"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE)
|
||||
.ShowModal() == wxID_YES) {
|
||||
reset();
|
||||
// BBS: jump to plater panel
|
||||
@@ -14612,7 +14643,7 @@ int GUI::Plater::close_with_confirm(std::function<bool(bool)> second_check)
|
||||
return wxID_NO;
|
||||
}
|
||||
|
||||
MessageDialog dlg(static_cast<wxWindow*>(this), _L("The current project has unsaved changes, save it before continue?"),
|
||||
MessageDialog dlg(static_cast<wxWindow*>(this), _L("The current project has unsaved changes. Would you like to save before continuing\?"),
|
||||
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Save"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE);
|
||||
dlg.show_dsa_button(_L("Remember my choice."));
|
||||
auto choise = wxGetApp().app_config->get("save_project_choise");
|
||||
@@ -16142,7 +16173,7 @@ void Plater::reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &
|
||||
// and let the background processing start.
|
||||
this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART);
|
||||
}
|
||||
void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool use_3mf)
|
||||
void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
|
||||
{
|
||||
// if physical_printer is selected, send gcode for this printer
|
||||
// DynamicPrintConfig* physical_printer_config = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config();
|
||||
@@ -16154,6 +16185,10 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
|
||||
if (upload_job.empty())
|
||||
return;
|
||||
|
||||
// Orca: the use_3mf printer option makes us send a .gcode.3mf to the printer
|
||||
const auto* use_3mf_opt = physical_printer_config->option<ConfigOptionBool>("use_3mf");
|
||||
const bool use_3mf = use_3mf_opt != nullptr && use_3mf_opt->value;
|
||||
|
||||
upload_job.upload_data.use_3mf = use_3mf;
|
||||
|
||||
// Obtain default output path
|
||||
@@ -16176,7 +16211,8 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
|
||||
}
|
||||
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
||||
if (use_3mf) {
|
||||
default_output_file.replace_extension("3mf");
|
||||
// Orca: a gcode-in-3mf bundle is named ".gcode.3mf" (matching "Export plate sliced file")
|
||||
default_output_file.replace_extension(".gcode.3mf");
|
||||
}
|
||||
|
||||
// Repetier specific: Query the server for the list of file groups.
|
||||
@@ -16201,15 +16237,96 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
|
||||
|
||||
{
|
||||
auto preset_bundle = wxGetApp().preset_bundle;
|
||||
const auto opt = physical_printer_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
|
||||
const auto host_type = opt != nullptr ? opt->value : htElegooLink;
|
||||
auto config = get_app_config();
|
||||
|
||||
const auto host_type_opt = physical_printer_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
|
||||
const auto host_type = host_type_opt != nullptr ? host_type_opt->value : htElegooLink;
|
||||
const auto* ff_serial_opt = physical_printer_config->option<ConfigOptionString>("flashforge_serial_number");
|
||||
const auto* ff_code_opt = physical_printer_config->option<ConfigOptionString>("printhost_apikey");
|
||||
const bool flashforge_local_api = host_type == htFlashforge && ff_serial_opt != nullptr && !ff_serial_opt->value.empty() &&
|
||||
ff_code_opt != nullptr && !ff_code_opt->value.empty();
|
||||
|
||||
std::unique_ptr<PrintHostSendDialog> pDlg;
|
||||
if (host_type == htElegooLink) {
|
||||
pDlg = std::make_unique<ElegooPrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
|
||||
storage_paths, storage_names,
|
||||
config->get_bool("open_device_tab_post_upload"));
|
||||
} else if (host_type == htCrealityPrint) {
|
||||
pDlg = std::make_unique<CrealityPrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
|
||||
storage_paths, storage_names,
|
||||
config->get_bool("open_device_tab_post_upload"),
|
||||
upload_job.printhost.get());
|
||||
} else if (flashforge_local_api) {
|
||||
auto* flashforge_host = dynamic_cast<Flashforge*>(upload_job.printhost.get());
|
||||
if (flashforge_host == nullptr) {
|
||||
show_error(this, _L("Flashforge host is not available."), false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<FlashforgeMaterialSlot> slots;
|
||||
bool supports_material_station = false;
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
wxString msg;
|
||||
if (!flashforge_host->fetch_material_slots(slots, &supports_material_station, msg)) {
|
||||
show_error(this, msg.empty() ? _L("Unable to log in to the Flashforge printer.") : msg, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FilamentInfo> project_filaments;
|
||||
PlateDataPtrs plate_data_list;
|
||||
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config();
|
||||
const auto* filament_color = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_colour"));
|
||||
const auto* filament_id_opt = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_ids"));
|
||||
const int resolved_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
|
||||
auto enrich_project_filaments = [&](std::vector<FilamentInfo>& filaments) {
|
||||
for (auto& filament : filaments) {
|
||||
if (filament.id < 0)
|
||||
continue;
|
||||
|
||||
std::string display_filament_type;
|
||||
try {
|
||||
filament.type = cfg.get_filament_type(display_filament_type, filament.id);
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
if (filament.type.empty())
|
||||
filament.type = display_filament_type;
|
||||
if (filament.type.empty())
|
||||
filament.type = "Unknown";
|
||||
|
||||
filament.filament_id = filament_id_opt ? filament_id_opt->get_at(static_cast<size_t>(filament.id)) : "";
|
||||
filament.color = filament_color ? filament_color->get_at(static_cast<size_t>(filament.id)) : "#FFFFFF";
|
||||
if (filament.color.empty())
|
||||
filament.color = "#FFFFFF";
|
||||
}
|
||||
};
|
||||
|
||||
p->partplate_list.store_to_3mf_structure(plate_data_list, true, plate_idx);
|
||||
PlateData* selected_plate_data = (resolved_plate_idx >= 0 && resolved_plate_idx < static_cast<int>(plate_data_list.size())) ? plate_data_list[resolved_plate_idx] : nullptr;
|
||||
if (selected_plate_data == nullptr && !plate_data_list.empty())
|
||||
selected_plate_data = plate_data_list.front();
|
||||
|
||||
if (selected_plate_data != nullptr)
|
||||
project_filaments = selected_plate_data->slice_filaments_info;
|
||||
|
||||
if (project_filaments.empty()) {
|
||||
if (PartPlate* plate = get_partplate_list().get_plate(resolved_plate_idx); plate != nullptr)
|
||||
project_filaments = plate->get_slice_filaments_info();
|
||||
}
|
||||
|
||||
if (!project_filaments.empty())
|
||||
enrich_project_filaments(project_filaments);
|
||||
release_PlateData_list(plate_data_list);
|
||||
|
||||
pDlg = std::make_unique<FlashforgePrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
|
||||
storage_paths, storage_names,
|
||||
config->get_bool("open_device_tab_post_upload"),
|
||||
flashforge_host,
|
||||
supports_material_station,
|
||||
std::move(slots),
|
||||
project_filaments);
|
||||
} else {
|
||||
pDlg = std::make_unique<PrintHostSendDialog>(default_output_file, upload_job.printhost->get_post_upload_actions(), groups,
|
||||
storage_paths, storage_names, config->get_bool("open_device_tab_post_upload"));
|
||||
@@ -16239,7 +16356,8 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
|
||||
|
||||
if (use_3mf) {
|
||||
// Process gcode
|
||||
const int result = send_gcode(plate_idx, nullptr);
|
||||
const int export_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
|
||||
const int result = send_gcode(export_plate_idx, nullptr);
|
||||
|
||||
if (result < 0) {
|
||||
wxString msg = _L("Abnormal print file data. Please slice again");
|
||||
@@ -16587,7 +16705,7 @@ void Plater::config_change_notification(const DynamicPrintConfig &config, const
|
||||
if (seq_print && view3d_canvas && view3d_canvas->is_initialized() && view3d_canvas->is_rendering_enabled()) {
|
||||
NotificationManager* notify_manager = get_notification_manager();
|
||||
if (seq_print->value == PrintSequence::ByObject) {
|
||||
std::string info_text = _u8L("Print By Object: \nSuggest to use auto-arrange to avoid collisions when printing.");
|
||||
std::string info_text = _u8L("Print By Object: \nWe suggest using auto-arrange to avoid collisions when printing.");
|
||||
notify_manager->bbl_show_seqprintinfo_notification(info_text);
|
||||
}
|
||||
else
|
||||
@@ -16685,8 +16803,10 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
||||
update_scheduled = true;
|
||||
}
|
||||
// Orca: update when *_filament changed
|
||||
else if (opt_key == "support_interface_filament" || opt_key == "support_filament" || opt_key == "wall_filament" ||
|
||||
opt_key == "sparse_infill_filament" || opt_key == "solid_infill_filament") {
|
||||
else if (opt_key == "support_interface_filament" || opt_key == "support_filament" ||
|
||||
opt_key == "outer_wall_filament_id" || opt_key == "inner_wall_filament_id" ||
|
||||
opt_key == "sparse_infill_filament_id" || opt_key == "internal_solid_filament_id" ||
|
||||
opt_key == "top_surface_filament_id" || opt_key == "bottom_surface_filament_id") {
|
||||
update_scheduled = true;
|
||||
}
|
||||
}
|
||||
@@ -17649,14 +17769,14 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
|
||||
if (p->printer_technology == ptFFF) {
|
||||
//std::string plater_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
|
||||
// "Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");;
|
||||
StringObjectException warning;
|
||||
std::vector<StringObjectException> warnings;
|
||||
Polygons polygons;
|
||||
std::vector<std::pair<Polygon, float>> height_polygons;
|
||||
p->background_process.fff_print()->set_check_multi_filaments_compatibility(wxGetApp().app_config->get("enable_high_low_temp_mixed_printing") == "false");
|
||||
StringObjectException err = p->background_process.validate(&warning, &polygons, &height_polygons);
|
||||
StringObjectException err = p->background_process.validate(&warnings, &polygons, &height_polygons);
|
||||
// update string by type
|
||||
post_process_string_object_exception(err);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warning=%2%, model_fits %3%")%err.string%warning.string %model_fits;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warnings=%2%, model_fits %3%")%err.string%warnings.size() %model_fits;
|
||||
|
||||
if (err.string.empty()) {
|
||||
p->partplate_list.get_curr_plate()->update_apply_result_invalid(false);
|
||||
@@ -17664,9 +17784,7 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
|
||||
p->notification_manager->close_notification_of_type(NotificationType::ValidateError);
|
||||
p->notification_manager->bbl_close_3mf_warn_notification();
|
||||
|
||||
// Pass a warning from validation and either show a notification,
|
||||
// or hide the old one.
|
||||
p->process_validation_warning(warning);
|
||||
p->process_validation_warnings(warnings);
|
||||
p->view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||
p->view3D->get_canvas3d()->set_as_dirty();
|
||||
p->view3D->get_canvas3d()->request_extra_frame();
|
||||
@@ -17676,7 +17794,7 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
|
||||
p->partplate_list.get_curr_plate()->update_apply_result_invalid(true);
|
||||
// Show error as notification.
|
||||
p->notification_manager->push_validate_error_notification(err);
|
||||
p->process_validation_warning(warning);
|
||||
p->process_validation_warnings(warnings);
|
||||
//model_fits = false;
|
||||
validate_error = true;
|
||||
p->view3D->get_canvas3d()->set_sequential_print_clearance_visible(true);
|
||||
@@ -18257,8 +18375,7 @@ void Plater::post_process_string_object_exception(StringObjectException &err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
err.string = format(_L("Plate %d: %s is not suggested to be used to print filament %s (%s). "
|
||||
"If you still want to do this print job, please set this filament's bed temperature to non-zero."),
|
||||
err.string = format(_L("Plate %d: %s is not suggested for use printing filament %s (%s). If you still want to do this print job, please set this filament\'s bed temperature to a number that is not zero."),
|
||||
err.params[0], err.params[1], err.params[2], filament_name);
|
||||
err.string += "\n";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user