mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 21:39:02 +08:00
Merge branch 'master' into fs_svg_SPE-1517
This commit is contained in:
commit
c6dbd0a6cd
@ -720,6 +720,7 @@ namespace DoExport {
|
||||
const FullPrintConfig &config,
|
||||
const std::vector<Extruder> &extruders,
|
||||
unsigned int initial_extruder_id,
|
||||
int total_toolchanges,
|
||||
PrintStatistics &print_statistics,
|
||||
bool export_binary_data,
|
||||
bgcode::binarize::BinaryData &binary_data)
|
||||
@ -727,7 +728,7 @@ namespace DoExport {
|
||||
std::string filament_stats_string_out;
|
||||
|
||||
print_statistics.clear();
|
||||
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
|
||||
print_statistics.total_toolchanges = total_toolchanges;
|
||||
print_statistics.initial_extruder_id = initial_extruder_id;
|
||||
std::vector<std::string> filament_types;
|
||||
if (! extruders.empty()) {
|
||||
@ -1161,7 +1162,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
||||
this->placeholder_parser().set("has_wipe_tower", has_wipe_tower);
|
||||
this->placeholder_parser().set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
||||
this->placeholder_parser().set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
|
||||
this->placeholder_parser().set("total_toolchanges", tool_ordering.toolchanges_count());
|
||||
{
|
||||
BoundingBoxf bbox(print.config().bed_shape.values);
|
||||
assert(bbox.defined);
|
||||
@ -1389,6 +1390,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
this->config(),
|
||||
m_writer.extruders(),
|
||||
initial_extruder_id,
|
||||
tool_ordering.toolchanges_count(),
|
||||
// Modifies
|
||||
print.m_print_statistics,
|
||||
export_to_binary_gcode,
|
||||
|
@ -109,7 +109,7 @@ std::string LabelObjects::all_objects_header() const
|
||||
|
||||
out += "\n";
|
||||
for (const auto& [print_instance, label] : label_data_sorted) {
|
||||
if (m_flavor == gcfKlipper) {
|
||||
if (m_label_objects_style == LabelObjectsStyle::Firmware && m_flavor == gcfKlipper) {
|
||||
char buffer[64];
|
||||
out += "EXCLUDE_OBJECT_DEFINE NAME=" + label.name;
|
||||
Polygon outline = instance_outline(print_instance);
|
||||
|
@ -479,6 +479,9 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||
|
||||
bool ToolOrdering::insert_wipe_tower_extruder()
|
||||
{
|
||||
if (!m_print_config_ptr->wipe_tower)
|
||||
return false;
|
||||
|
||||
// In case that wipe_tower_extruder is set to non-zero, we must make sure that the extruder will be in the list.
|
||||
bool changed = false;
|
||||
if (m_print_config_ptr->wipe_tower_extruder != 0) {
|
||||
@ -836,4 +839,20 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print, const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ToolOrdering::toolchanges_count() const
|
||||
{
|
||||
std::vector<unsigned int> tools_in_order;
|
||||
for (const LayerTools& lt : m_layer_tools)
|
||||
tools_in_order.insert(tools_in_order.end(), lt.extruders.begin(), lt.extruders.end());
|
||||
assert(std::find(tools_in_order.begin(), tools_in_order.end(), (unsigned int)(-1)) == tools_in_order.end());
|
||||
for (size_t i=1; i<tools_in_order.size(); ++i)
|
||||
if (tools_in_order[i] == tools_in_order[i-1])
|
||||
tools_in_order[i-1] = (unsigned int)(-1);
|
||||
tools_in_order.erase(std::remove(tools_in_order.begin(), tools_in_order.end(), (unsigned int)(-1)), tools_in_order.end());
|
||||
if (tools_in_order.size() > 1 && tools_in_order.back() == tools_in_order[tools_in_order.size()-2])
|
||||
tools_in_order.pop_back();
|
||||
return std::max(0, int(tools_in_order.size())-1); // 5 tools = 4 toolchanges
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -165,6 +165,7 @@ public:
|
||||
bool empty() const { return m_layer_tools.empty(); }
|
||||
std::vector<LayerTools>& layer_tools() { return m_layer_tools; }
|
||||
bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().wipe_tower_partitions > 0; }
|
||||
int toolchanges_count() const;
|
||||
|
||||
private:
|
||||
void initialize_layers(std::vector<coordf_t> &zs);
|
||||
|
@ -793,12 +793,13 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool)
|
||||
.set_initial_tool(m_current_tool)
|
||||
.set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f))
|
||||
.append(";--------------------\n"
|
||||
"; CP TOOLCHANGE START\n")
|
||||
.comment_with_value(" toolchange #", m_num_tool_changes + 1); // the number is zero-based
|
||||
"; CP TOOLCHANGE START\n");
|
||||
|
||||
if (tool != (unsigned)(-1))
|
||||
if (tool != (unsigned)(-1)) {
|
||||
writer.comment_with_value(" toolchange #", m_num_tool_changes + 1); // the number is zero-based
|
||||
writer.append(std::string("; material : " + (m_current_tool < m_filpar.size() ? m_filpar[m_current_tool].material : "(NONE)") + " -> " + m_filpar[tool].material + "\n").c_str())
|
||||
.append(";--------------------\n");
|
||||
}
|
||||
|
||||
writer.speed_override_backup();
|
||||
writer.speed_override(100);
|
||||
|
@ -474,7 +474,9 @@ struct WipeTowerData
|
||||
used_filament.clear();
|
||||
number_of_toolchanges = -1;
|
||||
depth = 0.f;
|
||||
z_and_depth_pairs.clear();
|
||||
brim_width = 0.f;
|
||||
height = 0.f;
|
||||
width = 0.f;
|
||||
first_layer_height = 0.f;
|
||||
cone_angle = 0.f;
|
||||
|
@ -1163,7 +1163,7 @@ void Sidebar::update_reslice_btn_tooltip() const
|
||||
|
||||
void Sidebar::msw_rescale()
|
||||
{
|
||||
SetMinSize(wxSize(40 * wxGetApp().em_unit(), -1));
|
||||
SetMinSize(wxSize(42 * wxGetApp().em_unit(), -1));
|
||||
|
||||
for (PlaterPresetComboBox* combo : std::vector<PlaterPresetComboBox*> { p->combo_print,
|
||||
p->combo_sla_print,
|
||||
@ -1502,8 +1502,7 @@ void Sidebar::update_sliced_info_sizer()
|
||||
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
||||
}
|
||||
|
||||
// if there is a wipe tower, insert number of toolchanges info into the array:
|
||||
p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", ps.total_toolchanges) : "N/A");
|
||||
p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, ps.total_toolchanges > 0 ? wxString::Format("%.d", ps.total_toolchanges) : "N/A");
|
||||
|
||||
// Hide non-FFF sliced info parameters
|
||||
p->sliced_info->SetTextAndShow(siMateril_unit, "N/A");
|
||||
|
@ -74,15 +74,19 @@ PreferencesDialog::PreferencesDialog(wxWindow* parent) :
|
||||
build();
|
||||
|
||||
wxSize sz = GetSize();
|
||||
sz.x += em_unit();
|
||||
bool is_scrollbar_shown = false;
|
||||
|
||||
const size_t pages_cnt = tabs->GetPageCount();
|
||||
for (size_t tab_id = 0; tab_id < pages_cnt; tab_id++) {
|
||||
wxSizer* tab_sizer = tabs->GetPage(tab_id)->GetSizer();
|
||||
wxScrolledWindow* scrolled = static_cast<wxScrolledWindow*>(tab_sizer->GetItem(size_t(0))->GetWindow());
|
||||
scrolled->SetScrollRate(0, 5);
|
||||
|
||||
is_scrollbar_shown |= scrolled->GetScrollLines(wxVERTICAL) > 0;
|
||||
}
|
||||
|
||||
if (is_scrollbar_shown)
|
||||
sz.x += 2*em_unit();
|
||||
SetSize(sz);
|
||||
|
||||
m_highlighter.set_timer_owner(this, 0);
|
||||
|
@ -61,7 +61,10 @@ ComboBox::ComboBox(wxWindow * parent,
|
||||
for (int i = 0; i < n; ++i) Append(choices[i]);
|
||||
}
|
||||
|
||||
int ComboBox::GetSelection() const { return drop.GetSelection(); }
|
||||
int ComboBox::GetSelection() const
|
||||
{
|
||||
return drop.GetSelection();
|
||||
}
|
||||
|
||||
void ComboBox::SetSelection(int n)
|
||||
{
|
||||
@ -233,6 +236,11 @@ wxBitmap ComboBox::GetItemBitmap(unsigned int n)
|
||||
return icons[n].GetBitmapFor(m_parent);
|
||||
}
|
||||
|
||||
void ComboBox::OnKeyDown(wxKeyEvent &event)
|
||||
{
|
||||
keyDown(event);
|
||||
}
|
||||
|
||||
int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
unsigned int pos,
|
||||
void ** clientData,
|
||||
@ -290,10 +298,15 @@ void ComboBox::keyDown(wxKeyEvent& event)
|
||||
{
|
||||
int key_code = event.GetKeyCode();
|
||||
switch (key_code) {
|
||||
#ifndef __WXOSX__
|
||||
case WXK_RETURN:
|
||||
if (drop_down) {
|
||||
drop.DismissAndNotify();
|
||||
|
||||
wxCommandEvent e(wxEVT_COMBOBOX);
|
||||
e.SetEventObject(this);
|
||||
e.SetId(GetId());
|
||||
e.SetInt(GetSelection());
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
} else if (drop.HasDismissLongTime()) {
|
||||
drop.autoPosition();
|
||||
drop_down = true;
|
||||
@ -302,32 +315,53 @@ void ComboBox::keyDown(wxKeyEvent& event)
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case WXK_UP:
|
||||
case WXK_DOWN:
|
||||
case WXK_LEFT:
|
||||
case WXK_RIGHT:
|
||||
if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) {
|
||||
case WXK_UP: {
|
||||
if (GetSelection() > 0)
|
||||
SetSelection(GetSelection() - 1);
|
||||
} else if ((event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_RIGHT) && GetSelection() + 1 < int(texts.size())) {
|
||||
break;
|
||||
}
|
||||
case WXK_DOWN: {
|
||||
if (GetSelection() + 1 < int(texts.size()))
|
||||
SetSelection(GetSelection() + 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case WXK_LEFT: {
|
||||
if (HasFlag(wxCB_READONLY)) {
|
||||
if(GetSelection() > 0)
|
||||
SetSelection(GetSelection() - 1);
|
||||
break;
|
||||
}
|
||||
{
|
||||
wxCommandEvent e(wxEVT_COMBOBOX);
|
||||
e.SetEventObject(this);
|
||||
e.SetId(GetId());
|
||||
e.SetInt(GetSelection());
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
const auto pos = GetTextCtrl()->GetInsertionPoint();
|
||||
if(pos > 0)
|
||||
GetTextCtrl()->SetInsertionPoint(pos - 1);
|
||||
break;
|
||||
}
|
||||
case WXK_RIGHT: {
|
||||
if (HasFlag(wxCB_READONLY)) {
|
||||
if (GetSelection() + 1 < int(texts.size()))
|
||||
SetSelection(GetSelection() + 1);
|
||||
break;
|
||||
}
|
||||
const size_t pos = size_t(GetTextCtrl()->GetInsertionPoint());
|
||||
if (pos < GetLabel().Length())
|
||||
GetTextCtrl()->SetInsertionPoint(pos + 1);
|
||||
break;
|
||||
}
|
||||
case WXK_TAB:
|
||||
HandleAsNavigationKey(event);
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
if (drop.IsShown() && HasFlag(wxCB_READONLY)) {
|
||||
for (size_t n = 0; n < texts.size(); n++) {
|
||||
if (texts[n].StartsWith(wxString(static_cast<char>(key_code)))) {
|
||||
SetSelection(int(n));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
event.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
|
||||
wxBitmap GetItemBitmap(unsigned int n);
|
||||
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
||||
protected:
|
||||
virtual int DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
unsigned int pos,
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "DropDown.hpp"
|
||||
#include "ComboBox.hpp"
|
||||
#include "../GUI_App.hpp"
|
||||
#include "../OptionsGroup.hpp"
|
||||
|
||||
@ -60,10 +61,60 @@ DropDown::DropDown(wxWindow * parent,
|
||||
Create(parent, style);
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
static gint gtk_popup_key_press (GtkWidget *widget, GdkEvent *gdk_event, wxPopupWindow* win )
|
||||
{
|
||||
// Ignore events sent out before we connected to the signal
|
||||
if (win->m_time >= ((GdkEventKey*)gdk_event)->time)
|
||||
return FALSE;
|
||||
|
||||
GtkWidget *child = gtk_get_event_widget (gdk_event);
|
||||
|
||||
/* We don't ask for button press events on the grab widget, so
|
||||
* if an event is reported directly to the grab widget, it must
|
||||
* be on a window outside the application (and thus we remove
|
||||
* the popup window). Otherwise, we check if the widget is a child
|
||||
* of the grab widget, and only remove the popup window if it
|
||||
* is not. */
|
||||
if (child != widget) {
|
||||
while (child) {
|
||||
if (child == widget)
|
||||
return FALSE;
|
||||
child = gtk_widget_get_parent(child);
|
||||
}
|
||||
}
|
||||
|
||||
gchar* keyval = gdk_keyval_name(((GdkEventKey*)gdk_event)->keyval);
|
||||
const long keyCode = strcmp(keyval, "Up") == 0 ? WXK_UP :
|
||||
strcmp(keyval, "Down") == 0 ? WXK_DOWN :
|
||||
strcmp(keyval, "Left") == 0 ? WXK_LEFT :
|
||||
strcmp(keyval, "Right") == 0 ? WXK_RIGHT :
|
||||
strcmp(keyval, "Return") == 0 ? WXK_RETURN : WXK_NONE;
|
||||
|
||||
if (keyCode != WXK_NONE) {
|
||||
wxKeyEvent event( wxEVT_KEY_DOWN, win->GetId());
|
||||
event.m_keyCode = keyCode;
|
||||
event.SetEventObject( win );
|
||||
(void)win->HandleWindowEvent( event );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DropDown::Create(wxWindow * parent,
|
||||
long style)
|
||||
{
|
||||
wxPopupTransientWindow::Create(parent);
|
||||
#ifdef __WXGTK__
|
||||
g_signal_connect (m_widget, "key_press_event", G_CALLBACK (gtk_popup_key_press), this);
|
||||
|
||||
Bind(wxEVT_KEY_DOWN, [parent](wxKeyEvent &e) {
|
||||
if (ComboBox* cb = dynamic_cast<ComboBox*>(parent))
|
||||
cb->OnKeyDown(e);
|
||||
});
|
||||
#endif
|
||||
|
||||
if (!wxOSX) SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
|
||||
state_handler.update_binds();
|
||||
@ -95,6 +146,8 @@ void DropDown::SetSelection(int n)
|
||||
n = -1;
|
||||
if (selection == n) return;
|
||||
selection = n;
|
||||
if (IsShown())
|
||||
autoPosition();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
@ -212,7 +265,11 @@ void DropDown::SetTransparentBG(wxDC& dc, wxWindow* win)
|
||||
}
|
||||
|
||||
constexpr int slider_width = 12;
|
||||
#ifdef __WXOSX__
|
||||
constexpr int slider_step = 1;
|
||||
#else
|
||||
constexpr int slider_step = 5;
|
||||
#endif
|
||||
constexpr int items_padding = 2;
|
||||
|
||||
/*
|
||||
@ -423,14 +480,14 @@ void DropDown::autoPosition()
|
||||
if (use_content_width && texts.size() <= 15) size.x += 6;
|
||||
size.y = drect.GetBottom() - GetPosition().y - 10;
|
||||
wxWindow::SetSize(size);
|
||||
if (selection >= 0) {
|
||||
if (offset.y + rowSize.y * (selection + 1) > size.y)
|
||||
offset.y = size.y - rowSize.y * (selection + 1);
|
||||
else if (offset.y + rowSize.y * selection < 0)
|
||||
offset.y = -rowSize.y * selection;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selection >= 0) {
|
||||
if (offset.y + rowSize.y * (selection + 1) > size.y)
|
||||
offset.y = size.y - rowSize.y * (selection + 3);
|
||||
else if (offset.y + rowSize.y * selection < 0)
|
||||
offset.y = -rowSize.y * selection;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDown::mouseDown(wxMouseEvent& event)
|
||||
@ -461,6 +518,10 @@ void DropDown::mouseReleased(wxMouseEvent& event)
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
if (hover_item >= 0) { // not moved
|
||||
#ifdef __WXOSX__
|
||||
// To avoid cases, when some dialog appears after item selection, but DropDown is still shown
|
||||
Hide();
|
||||
#endif
|
||||
sendDropDownEvent();
|
||||
DismissAndNotify();
|
||||
}
|
||||
@ -507,6 +568,8 @@ void DropDown::mouseMove(wxMouseEvent &event)
|
||||
|
||||
void DropDown::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
if (event.GetWheelRotation() == 0)
|
||||
return;
|
||||
auto delta = event.GetWheelRotation() > 0 ? rowSize.y : -rowSize.y;
|
||||
wxPoint pt2 = offset + wxPoint{0, slider_step * delta};
|
||||
int text_size = int(texts.size());
|
||||
|
Loading…
x
Reference in New Issue
Block a user