NEW: first layer printing sequence

Change-Id: I19e39a27cf972eb859e51a334aeae8f57ee263f8
This commit is contained in:
liz.li 2023-08-07 18:16:08 +08:00 committed by Lane.Wei
parent a75d024485
commit 060b41707e
8 changed files with 404 additions and 2 deletions

View File

@ -0,0 +1,10 @@
<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_13328_29956)">
<path d="M13.8527 8.35312C14.0465 8.15937 14.0465 7.84062 13.8527 7.64687L8.35274 2.14687C8.15899 1.95312 7.84024 1.95312 7.64649 2.14687C7.45274 2.34062 7.45274 2.65937 7.64649 2.85312L12.2934 7.5L0.49961 7.5C0.22461 7.5 -0.000390458 7.725 -0.000390482 8C-0.000390506 8.275 0.22461 8.5 0.499609 8.5L12.2934 8.5L7.64648 13.1469C7.45273 13.3406 7.45273 13.6594 7.64648 13.8531C7.84023 14.0469 8.15898 14.0469 8.35273 13.8531L13.8527 8.35312Z" fill="#A5A5A5"/>
</g>
<defs>
<clipPath id="clip0_13328_29956">
<rect width="14" height="16" fill="white" transform="translate(14 16) rotate(-180)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 754 B

View File

@ -370,6 +370,8 @@ set(SLIC3R_GUI_SOURCES
GUI/ProjectDirtyStateManager.cpp
GUI/DesktopIntegrationDialog.cpp
GUI/DesktopIntegrationDialog.hpp
GUI/DragCanvas.cpp
GUI/DragCanvas.hpp
GUI/PublishDialog.cpp
GUI/PublishDialog.hpp
GUI/RecenterDialog.cpp

View File

@ -0,0 +1,250 @@
#include "DragCanvas.hpp"
#include "wxExtensions.hpp"
#include "GUI_App.hpp"
namespace Slic3r { namespace GUI {
#define CANVAS_WIDTH FromDIP(240)
#define SHAPE_SIZE FromDIP(20)
#define SHAPE_GAP (2 * SHAPE_SIZE)
#define LINE_HEIGHT (SHAPE_SIZE + FromDIP(5))
static const wxColour CANVAS_BORDER_COLOR = wxColour(0xCECECE);
DragCanvas::DragCanvas(wxWindow* parent, const std::vector<std::string>& colors, const std::vector<int>& order)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
, m_drag_mode(DragMode::NONE)
, m_max_shape_pos(wxPoint(0, 0))
{
SetBackgroundColour(*wxWHITE);
m_arrow_bmp = create_scaled_bitmap("plate_settings_arrow", this, 16);
set_shape_list(colors, order);
Bind(wxEVT_PAINT, &DragCanvas::on_paint, this);
Bind(wxEVT_ERASE_BACKGROUND, &DragCanvas::on_erase, this);
Bind(wxEVT_LEFT_DOWN, &DragCanvas::on_mouse, this);
Bind(wxEVT_LEFT_UP, &DragCanvas::on_mouse, this);
Bind(wxEVT_MOTION, &DragCanvas::on_mouse, this);
Bind(wxEVT_ENTER_WINDOW, &DragCanvas::on_mouse, this);
Bind(wxEVT_LEAVE_WINDOW, &DragCanvas::on_mouse, this);
}
DragCanvas::~DragCanvas()
{
for (int i = 0; i < m_dragshape_list.size(); i++) {
delete m_dragshape_list[i];
}
m_dragshape_list.clear();
if (m_drag_image)
delete m_drag_image;
}
void DragCanvas::set_shape_list(const std::vector<std::string>& colors, const std::vector<int>& order)
{
m_dragshape_list.clear();
for (int i = 0; i < order.size(); i++) {
wxBitmap* bmp = get_extruder_color_icon(colors[order[i] - 1], std::to_string(order[i]), SHAPE_SIZE, SHAPE_SIZE);
DragShape* shape = new DragShape(*bmp, order[i]);
m_dragshape_list.push_back(shape);
}
// wrapping lines
for (int i = 0; i < order.size(); i++) {
int shape_pos_x = FromDIP(10) + i * SHAPE_GAP;
int shape_pos_y = FromDIP(5);
while (shape_pos_x + SHAPE_SIZE > CANVAS_WIDTH) {
shape_pos_x -= CANVAS_WIDTH;
shape_pos_y += LINE_HEIGHT;
int row = shape_pos_y / LINE_HEIGHT + 1;
if (row > 1) {
if (row % 2 == 0) {
shape_pos_x += (SHAPE_GAP - SHAPE_SIZE);
}
else {
shape_pos_x -= (SHAPE_GAP - SHAPE_SIZE);
shape_pos_x += SHAPE_GAP;
}
}
}
m_max_shape_pos.x = std::max(m_max_shape_pos.x, shape_pos_x);
m_max_shape_pos.y = std::max(m_max_shape_pos.y, shape_pos_y);
m_dragshape_list[i]->SetPosition(wxPoint(shape_pos_x, shape_pos_y));
}
int rows = m_max_shape_pos.y / LINE_HEIGHT + 1;
SetMinSize(wxSize(CANVAS_WIDTH, LINE_HEIGHT * rows + FromDIP(5)));
}
std::vector<int> DragCanvas::get_shape_list_order()
{
std::vector<int> res;
std::vector<DragShape*> ordered_list = get_ordered_shape_list();
res.reserve(ordered_list.size());
for (auto& item : ordered_list) {
res.push_back(item->get_index());
}
return res;
}
std::vector<DragShape*> DragCanvas::get_ordered_shape_list()
{
std::vector<DragShape*> ordered_list = m_dragshape_list;
std::sort(ordered_list.begin(), ordered_list.end(), [](const DragShape* l, const DragShape* r) {
if (l->GetPosition().y < r->GetPosition().y)
return true;
else if (l->GetPosition().y == r->GetPosition().y) {
return l->GetPosition().x < r->GetPosition().x;
}
else {
return false;
}
});
return ordered_list;
}
void DragCanvas::on_paint(wxPaintEvent& event)
{
wxPaintDC dc(this);
for (int i = 0; i < m_dragshape_list.size(); i++) {
m_dragshape_list[i]->paint(dc, m_dragshape_list[i] == m_slot_shape);
auto arrow_pos = m_dragshape_list[i]->GetPosition() - wxSize(SHAPE_GAP - SHAPE_SIZE, 0);
if (arrow_pos.x < 0) {
arrow_pos.x = m_max_shape_pos.x;
arrow_pos.y -= LINE_HEIGHT;
}
arrow_pos += wxSize((SHAPE_GAP - SHAPE_SIZE - m_arrow_bmp.GetWidth() / dc.GetContentScaleFactor()) / 2, (SHAPE_SIZE - m_arrow_bmp.GetHeight() / dc.GetContentScaleFactor()) / 2);
dc.DrawBitmap(m_arrow_bmp, arrow_pos);
}
}
void DragCanvas::on_erase(wxEraseEvent& event)
{
wxSize size = GetSize();
if (event.GetDC())
{
auto& dc = *(event.GetDC());
dc.SetPen(CANVAS_BORDER_COLOR);
dc.SetBrush(*wxWHITE_BRUSH);
dc.DrawRectangle({ 0,0 }, size);
}
else
{
wxClientDC dc(this);
dc.SetPen(CANVAS_BORDER_COLOR);
dc.SetBrush(*wxWHITE_BRUSH);
dc.DrawRectangle({ 0,0 }, size);
}
}
void DragCanvas::on_mouse(wxMouseEvent& event)
{
if (event.LeftDown())
{
DragShape* shape = find_shape(event.GetPosition());
if (shape)
{
m_drag_mode = DragMode::DRAGGING;
m_drag_start_pos = event.GetPosition();
m_dragging_shape = shape;
if (m_drag_image) {
delete m_drag_image;
m_drag_image = nullptr;
}
m_drag_image = new wxDragImage(m_dragging_shape->GetBitmap());
wxPoint offset = m_drag_start_pos - m_dragging_shape->GetPosition();
bool success = m_drag_image->BeginDrag(offset, this);
if (!success)
{
delete m_drag_image;
m_drag_image = nullptr;
m_drag_mode = DragMode::NONE;
}
}
}
else if (event.Dragging() && m_drag_mode == DragMode::DRAGGING)
{
DragShape* shape = find_shape(event.GetPosition());
if (shape) {
if (shape != m_dragging_shape) {
m_slot_shape = shape;
Refresh();
Update();
}
}
else {
if (m_slot_shape) {
m_slot_shape = nullptr;
Refresh();
Update();
}
}
m_drag_image->Move(event.GetPosition());
m_drag_image->Show();
}
else if (event.LeftUp() && m_drag_mode != DragMode::NONE)
{
m_drag_mode = DragMode::NONE;
if (m_drag_image) {
m_drag_image->Hide();
m_drag_image->EndDrag();
// swap position
if (m_slot_shape && m_dragging_shape) {
auto highlighted_pos = m_slot_shape->GetPosition();
m_slot_shape->SetPosition(m_dragging_shape->GetPosition());
m_dragging_shape->SetPosition(highlighted_pos);
m_slot_shape = nullptr;
m_dragging_shape = nullptr;
}
}
Refresh();
Update();
}
}
DragShape* DragCanvas::find_shape(const wxPoint& pt) const
{
for (auto& shape : m_dragshape_list) {
if (shape->hit_test(pt))
return shape;
}
return nullptr;
}
DragShape::DragShape(const wxBitmap& bitmap, int index)
: m_bitmap(bitmap)
, m_pos(wxPoint(0,0))
, m_index(index)
{
}
bool DragShape::hit_test(const wxPoint& pt) const
{
wxRect rect(wxRect(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight()));
return rect.Contains(pt.x, pt.y);
}
void DragShape::paint(wxDC& dc, bool highlight)
{
dc.DrawBitmap(m_bitmap, m_pos);
if (highlight)
{
dc.SetPen(*wxWHITE_PEN);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight());
}
}
}}

View File

@ -0,0 +1,65 @@
#ifndef slic3r_GUI_DragCanvas_hpp_
#define slic3r_GUI_DragCanvas_hpp_
#include "wx/bitmap.h"
#include "wx/dragimag.h"
namespace Slic3r { namespace GUI {
class DragShape : public wxObject
{
public:
DragShape(const wxBitmap& bitmap, int index);
~DragShape() {}
wxPoint GetPosition() const { return m_pos; }
void SetPosition(const wxPoint& pos) { m_pos = pos; }
const wxBitmap& GetBitmap() const { return m_bitmap; }
void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }
int get_index() { return m_index; }
bool hit_test(const wxPoint& pt) const;
void paint(wxDC& dc, bool highlight = false);
protected:
wxPoint m_pos;
wxBitmap m_bitmap;
int m_index;
};
enum class DragMode {
NONE,
DRAGGING,
};
class DragCanvas : public wxPanel
{
public:
DragCanvas(wxWindow* parent, const std::vector<std::string>& colors, const std::vector<int>& order);
~DragCanvas();
void set_shape_list(const std::vector<std::string>& colors, const std::vector<int>& order);
std::vector<int> get_shape_list_order();
std::vector<DragShape*> get_ordered_shape_list();
protected:
void on_paint(wxPaintEvent& event);
void on_erase(wxEraseEvent& event);
void on_mouse(wxMouseEvent& event);
DragShape* find_shape(const wxPoint& pt) const;
private:
std::vector<DragShape*> m_dragshape_list;
DragMode m_drag_mode;
DragShape* m_dragging_shape{ nullptr };
DragShape* m_slot_shape{ nullptr }; // The shape that's being highlighted
wxDragImage* m_drag_image{ nullptr };
wxPoint m_drag_start_pos;
wxBitmap m_arrow_bmp;
wxPoint m_max_shape_pos;
};
}}
#endif

View File

@ -931,13 +931,13 @@ void PartPlate::render_icons(bool bottom, bool only_body, int hover_id)
if (m_partplate_list->render_plate_settings) {
if (hover_id == 5) {
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault)
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault && get_first_layer_print_sequence().empty())
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_hovered_texture, m_plate_settings_vbo_id);
else
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_hovered_texture,
m_plate_settings_vbo_id);
} else {
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault)
if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault && get_first_layer_print_sequence().empty())
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_texture, m_plate_settings_vbo_id);
else
render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_changed_texture, m_plate_settings_vbo_id);

View File

@ -43,6 +43,37 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, wxWindowID id, const
top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT |wxALL, FromDIP(5));
top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5));
m_first_layer_print_seq_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY);
m_first_layer_print_seq_choice->Append(_L("Auto"));
m_first_layer_print_seq_choice->Append(_L("Customize"));
m_first_layer_print_seq_choice->SetSelection(0);
m_first_layer_print_seq_choice->Bind(wxEVT_COMBOBOX, [this](auto& e) {
if (e.GetSelection() == 0) {
m_drag_canvas->Hide();
}
else if (e.GetSelection() == 1) {
m_drag_canvas->Show();
}
Layout();
Fit();
});
wxStaticText* first_layer_txt = new wxStaticText(this, wxID_ANY, _L("First Layer print sequence"));
first_layer_txt->SetFont(Label::Body_14);
top_sizer->Add(first_layer_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
top_sizer->Add(m_first_layer_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5));
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<int> order;
if (order.empty()) {
for (int i = 1; i <= extruder_colours.size(); i++) {
order.push_back(i);
}
}
m_drag_canvas = new DragCanvas(this, extruder_colours, order);
m_drag_canvas->Hide();
top_sizer->Add(0, 0, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
top_sizer->Add(m_drag_canvas, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxALL, FromDIP(30));
auto sizer_button = new wxBoxSizer(wxHORIZONTAL);
@ -119,6 +150,22 @@ void PlateSettingsDialog::sync_print_seq(int print_seq)
}
}
void PlateSettingsDialog::sync_first_layer_print_seq(int selection, const std::vector<int>& seq)
{
if (m_first_layer_print_seq_choice != nullptr) {
if (selection == 1) {
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
m_drag_canvas->set_shape_list(extruder_colours, seq);
}
m_first_layer_print_seq_choice->SetSelection(selection);
wxCommandEvent event(wxEVT_COMBOBOX);
event.SetInt(selection);
event.SetEventObject(m_first_layer_print_seq_choice);
wxPostEvent(m_first_layer_print_seq_choice, event);
}
}
wxString PlateSettingsDialog::to_bed_type_name(BedType bed_type) {
switch (bed_type) {
case btDefault:
@ -149,6 +196,11 @@ void PlateSettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
m_button_cancel->Rescale();
}
std::vector<int> PlateSettingsDialog::get_first_layer_print_seq()
{
return m_drag_canvas->get_shape_list_order();
}
//PlateNameEditDialog
PlateNameEditDialog::PlateNameEditDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style)

View File

@ -6,6 +6,7 @@
#include "Widgets/Button.hpp"
#include "Widgets/RadioBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "DragCanvas.hpp"
namespace Slic3r { namespace GUI {
@ -31,6 +32,7 @@ public:
~PlateSettingsDialog();
void sync_bed_type(BedType type);
void sync_print_seq(int print_seq = 0);
void sync_first_layer_print_seq(int selection, const std::vector<int>& seq = std::vector<int>());
wxString to_bed_type_name(BedType bed_type);
wxString to_print_sequence_name(PrintSequence print_seq);
void on_dpi_changed(const wxRect& suggested_rect) override;
@ -49,7 +51,18 @@ public:
return choice;
};
int get_first_layer_print_seq_choice() {
int choice = 0;
if (m_first_layer_print_seq_choice != nullptr)
choice = m_first_layer_print_seq_choice->GetSelection();
return choice;
};
std::vector<int> get_first_layer_print_seq();
protected:
DragCanvas* m_drag_canvas;
ComboBox* m_first_layer_print_seq_choice { nullptr };
ComboBox* m_print_seq_choice { nullptr };
ComboBox* m_bed_type_choice { nullptr };
Button* m_button_ok;

View File

@ -12115,6 +12115,11 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
else
dlg.sync_print_seq(0);
auto first_layer_print_seq = curr_plate->get_first_layer_print_sequence();
if (first_layer_print_seq.empty())
dlg.sync_first_layer_print_seq(0);
else
dlg.sync_first_layer_print_seq(1, curr_plate->get_first_layer_print_sequence());
dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index, &dlg](wxCommandEvent& e) {
PartPlate *curr_plate = p->partplate_list.get_curr_plate();
@ -12127,6 +12132,11 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select bed type %1% for plate %2% at plate side")%bt_sel %plate_index;
if (dlg.get_first_layer_print_seq_choice() != 0)
curr_plate->set_first_layer_print_sequence(dlg.get_first_layer_print_seq());
else
curr_plate->set_first_layer_print_sequence({});
int ps_sel = dlg.get_print_seq_choice();
if (ps_sel != 0)
curr_plate->set_print_seq(PrintSequence(ps_sel - 1));