diff --git a/flatpak/io.github.softfever.OrcaSlicer.yml b/flatpak/io.github.softfever.OrcaSlicer.yml index ae29d671de..4395cc47ca 100755 --- a/flatpak/io.github.softfever.OrcaSlicer.yml +++ b/flatpak/io.github.softfever.OrcaSlicer.yml @@ -298,7 +298,7 @@ modules: - | mkdir -p build CXXFLAGS=-std=gnu++20 cmake . -B build \ - -DSLIC3R_PCH=OFF \ + -DSLIC3R_PCH=ON \ -DSLIC3R_FHS=ON \ -DSLIC3R_GTK=3 \ -DSLIC3R_STATIC=ON \ diff --git a/src/slic3r/GUI/2DBed.cpp b/src/slic3r/GUI/2DBed.cpp index 2921e064cf..a08c47c0ef 100644 --- a/src/slic3r/GUI/2DBed.cpp +++ b/src/slic3r/GUI/2DBed.cpp @@ -1,6 +1,9 @@ #include "2DBed.hpp" #include "GUI_App.hpp" +#include "3DBed.hpp" +#include "PartPlate.hpp" + #include #include "libslic3r/BoundingBox.hpp" @@ -21,6 +24,63 @@ wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), - #endif /*__APPLE__*/ } +int Bed_2D::calculate_grid_step(const BoundingBox& bb) +{ + // Orca: use 500 x 500 bed size as baseline. + int min_edge = (bb.size() / ((coord_t) scale_(1)) ).minCoeff(); // Get short edge + // if the grid is too dense, we increase the step + return min_edge >= 6000 ? 100 // Short edge >= 6000mm Main Grid: 5 x 100 = 500mm + : min_edge >= 1200 ? 50 // Short edge >= 1200mm Main Grid: 5 x 50 = 250mm + : min_edge >= 600 ? 20 // Short edge >= 600mm Main Grid: 5 x 20 = 100mm + : 10; // Short edge < 600mm Main Grid: 5 x 10 = 50mm +} + +std::vector Bed_2D::generate_grid(const ExPolygon& poly, const BoundingBox& bb, const Vec2d& origin, const float& step, const float& scale) +{ + Polylines lines_thin, lines_bold; + int count = 0; + + // ORCA draw grid lines relative to origin + for (coord_t x = origin.x(); x >= bb.min(0); x -= step) { // Negative X axis + (count % 5 ? lines_thin : lines_bold).push_back(Polyline( + Point(x, bb.min(1)), + Point(x, bb.max(1)) + )); + count ++; + } + count = 0; + for (coord_t x = origin.x(); x <= bb.max(0); x += step) { // Positive X axis + (count % 5 ? lines_thin : lines_bold).push_back(Polyline( + Point(x, bb.min(1)), + Point(x, bb.max(1)) + )); + count ++; + } + count = 0; + for (coord_t y = origin.y(); y >= bb.min(1); y -= step) { // Negative Y axis + (count % 5 ? lines_thin : lines_bold).push_back(Polyline( + Point(bb.min(0), y), + Point(bb.max(0), y) + )); + count ++; + } + count = 0; + for (coord_t y = origin.y(); y <= bb.max(1); y += step) { // Positive Y axis + (count % 5 ? lines_thin : lines_bold).push_back(Polyline( + Point(bb.min(0), y), + Point(bb.max(0), y) + )); + count ++; + } + + std::vector grid; + // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped + auto scaled_poly = offset(poly, scale); + grid.push_back(intersection_pl(lines_thin, scaled_poly)); + grid.push_back(intersection_pl(lines_bold, scaled_poly)); + return grid; +} + void Bed_2D::repaint(const std::vector& shape) { wxAutoBufferedPaintDC dc(this); @@ -28,6 +88,7 @@ void Bed_2D::repaint(const std::vector& shape) auto ch = GetSize().GetHeight(); // when canvas is not rendered yet, size is 0, 0 if (cw == 0) return ; + bool is_dark = wxGetApp().dark_mode(); if (m_user_drawn_background) { // On all systems the AutoBufferedPaintDC() achieves double buffering. @@ -35,7 +96,7 @@ void Bed_2D::repaint(const std::vector& shape) // and on Linux / GTK the background is erased to gray color. // Fill DC with the background on Windows & Linux / GTK. wxColour color; - if (wxGetApp().dark_mode()) {// SetBackgroundColour + if (is_dark) {// SetBackgroundColour color = wxColour(45, 45, 49); } else { @@ -58,7 +119,6 @@ void Bed_2D::repaint(const std::vector& shape) auto ccenter = cbb.center(); // get bounding box of bed shape in G - code coordinates - auto bed_polygon = Polygon::new_scale(shape); auto bb = BoundingBoxf(shape); bb.merge(Vec2d(0, 0)); // origin needs to be in the visible area auto bw = bb.size()(0); @@ -75,8 +135,16 @@ void Bed_2D::repaint(const std::vector& shape) m_scale_factor = sfactor; m_shift = Vec2d(shift(0) + cbb.min(0), shift(1) - (cbb.max(1) - ch)); + // ORCA match colors + ColorRGBA bed_rgba = is_dark ? Bed3D::DEFAULT_MODEL_COLOR_DARK : Bed3D::DEFAULT_MODEL_COLOR; + std::string bed_color = encode_color(ColorRGBA(bed_rgba[0] * 0.8f, bed_rgba[1] * 0.8f,bed_rgba[2] * 0.8f, bed_rgba[3])); + ColorRGBA grid_color = is_dark ? PartPlate::LINE_TOP_SEL_DARK_COLOR : PartPlate::LINE_TOP_SEL_COLOR; + std::string lines_bold_color = encode_color(grid_color); + std::string lines_thin_color = encode_color(grid_color * 0.85); + wxColour text_color = wxColour(lines_bold_color); + // draw bed fill - dc.SetBrush(wxBrush(wxColour(255, 255, 255), wxBRUSHSTYLE_SOLID)); + dc.SetBrush(wxBrush(wxColour(bed_color), wxBRUSHSTYLE_SOLID)); wxPointList pt_list; for (auto pt : shape) { @@ -85,36 +153,40 @@ void Bed_2D::repaint(const std::vector& shape) } dc.DrawPolygon(&pt_list, 0, 0); - // draw grid - auto step = 10; // 1cm grid - Polylines polylines; - for (auto x = bb.min(0) - fmod(bb.min(0), step) + step; x < bb.max(0); x += step) { - polylines.push_back(Polyline::new_scale({ Vec2d(x, bb.min(1)), Vec2d(x, bb.max(1)) })); - } - for (auto y = bb.min(1) - fmod(bb.min(1), step) + step; y < bb.max(1); y += step) { - polylines.push_back(Polyline::new_scale({ Vec2d(bb.min(0), y), Vec2d(bb.max(0), y) })); - } - polylines = intersection_pl(polylines, bed_polygon); + ExPolygon bed_poly; + for (const Vec2d& p : shape) + bed_poly.contour.append({p(0), p(1)}); + auto bed_bb = bed_poly.contour.bounding_box(); + int step = calculate_grid_step(bed_bb); + auto grid_lines = generate_grid(bed_poly, bed_bb, m_pos, step, 1.0f); - dc.SetPen(wxPen(wxColour(230, 230, 230), 1, wxPENSTYLE_SOLID)); - for (auto pl : polylines) - { - for (size_t i = 0; i < pl.points.size()-1; i++) { - Point pt1 = to_pixels(unscale(pl.points[i]), ch); - Point pt2 = to_pixels(unscale(pl.points[i + 1]), ch); + // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped + dc.SetPen(wxPen(wxColour(lines_thin_color), 1, wxPENSTYLE_SOLID)); + for (auto pl : grid_lines[0]) { + for (size_t i = 0; i < pl.points.size() - 1; i++) { + Point pt1 = to_pixels(pl.points[i ], ch); + Point pt2 = to_pixels(pl.points[i+1], ch); + dc.DrawLine(pt1(0), pt1(1), pt2(0), pt2(1)); + } + } + dc.SetPen(wxPen(wxColour(lines_bold_color), 1, wxPENSTYLE_SOLID)); + for (auto pl : grid_lines[1]) { + for (size_t i = 0; i < pl.points.size() - 1; i++) { + Point pt1 = to_pixels(pl.points[i ], ch); + Point pt2 = to_pixels(pl.points[i+1], ch); dc.DrawLine(pt1(0), pt1(1), pt2(0), pt2(1)); } } // draw bed contour - dc.SetPen(wxPen(wxColour(0, 0, 0), 1, wxPENSTYLE_SOLID)); - dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT)); + dc.SetPen( wxPen( wxColour(lines_bold_color), 1, wxPENSTYLE_SOLID)); + dc.SetBrush(wxBrush(wxColour(lines_bold_color), wxBRUSHSTYLE_TRANSPARENT)); dc.DrawPolygon(&pt_list, 0, 0); auto origin_px = to_pixels(Vec2d(0, 0), ch); // draw axes - auto axes_len = 50; + auto axes_len = 5 * wxGetApp().em_unit(); // scale axis auto arrow_len = 6; auto arrow_angle = Geometry::deg2rad(45.0); dc.SetPen(wxPen(wxColour(255, 0, 0), 2, wxPENSTYLE_SOLID)); // red @@ -139,13 +211,26 @@ void Bed_2D::repaint(const std::vector& shape) dc.DrawCircle(origin_px(0), origin_px(1), 3); static const auto origin_label = wxString("(0,0)"); - dc.SetTextForeground(wxColour(0, 0, 0)); + dc.SetTextForeground(wxColour("#FFFFFF")); dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); auto extent = dc.GetTextExtent(origin_label); - const auto origin_label_x = origin_px(0) <= cw / 2 ? origin_px(0) + 1 : origin_px(0) - 1 - extent.GetWidth(); - const auto origin_label_y = origin_px(1) <= ch / 2 ? origin_px(1) + 1 : origin_px(1) - 1 - extent.GetHeight(); + const auto origin_label_x = origin_px(0) + 2; // ORCA always draw (0,0) text in axes bounding box + const auto origin_label_y = origin_px(1) - extent.GetHeight() - 2; + dc.SetPen( wxPen( wxColour(wxColour(bed_color)), 1, wxPENSTYLE_SOLID)); + dc.SetBrush(wxBrush(wxColour(wxColour(bed_color)), wxBRUSHSTYLE_SOLID)); + dc.DrawRectangle(wxPoint(origin_label_x, origin_label_y), extent); // ORCA draw a background to origin position text to improve readability when overlaps with grid dc.DrawText(origin_label, origin_label_x, origin_label_y); + // ORCA add grid size value as information for large scale beds + auto grid_label = wxString("1x1 Grid: " + std::to_string(step) + " mm"); + Point draw_bb = to_pixels(Vec2d( + std::min(m_pos(0),bb.min(0)), + std::min(m_pos(1),bb.min(1)) + ),ch); + dc.SetTextForeground(wxColour(StateColor::darkModeColorFor("#262E30"))); + dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + dc.DrawText(grid_label, draw_bb(0), draw_bb(1) + 5); + // draw current position if (m_pos!= Vec2d(0, 0)) { auto pos_px = to_pixels(m_pos, ch); @@ -166,6 +251,12 @@ Point Bed_2D::to_pixels(const Vec2d& point, int height) return Point(p(0) + Border, height - p(1) + Border); } +Point Bed_2D::to_pixels(const Point& point, int height) +{ + auto p = point * m_scale_factor + Point(m_shift); + return Point(p(0) + Border, height - p(1) + Border); +} + void Bed_2D::set_pos(const Vec2d& pos) { m_pos = pos; diff --git a/src/slic3r/GUI/2DBed.hpp b/src/slic3r/GUI/2DBed.hpp index 80926bea72..e6dd1add77 100644 --- a/src/slic3r/GUI/2DBed.hpp +++ b/src/slic3r/GUI/2DBed.hpp @@ -18,11 +18,16 @@ class Bed_2D : public wxPanel Vec2d m_pos = Vec2d::Zero(); Point to_pixels(const Vec2d& point, int height); + Point to_pixels(const Point& point, int height); void set_pos(const Vec2d& pos); public: explicit Bed_2D(wxWindow* parent); + static int calculate_grid_step(const BoundingBox& bb); + + static std::vector generate_grid(const ExPolygon& poly, const BoundingBox& pp_bbox, const Vec2d& origin, const float& step, const float& scale); + void repaint(const std::vector& shape); }; diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 9fddc21262..5686375098 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -28,10 +28,6 @@ #endif static const float GROUND_Z = -0.04f; -static const Slic3r::ColorRGBA DEFAULT_MODEL_COLOR = { 0.3255f, 0.337f, 0.337f, 1.0f }; -static const Slic3r::ColorRGBA DEFAULT_MODEL_COLOR_DARK = { 0.255f, 0.255f, 0.283f, 1.0f }; -static const Slic3r::ColorRGBA DEFAULT_SOLID_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f }; -static const Slic3r::ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 0.6f }; namespace Slic3r { namespace GUI { @@ -185,6 +181,12 @@ const float Bed3D::Axes::DefaultStemLength = 25.0f; const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius; const float Bed3D::Axes::DefaultTipLength = 5.0f; +// ORCA make bed colors accessable for 2D bed +ColorRGBA Bed3D::DEFAULT_MODEL_COLOR = { 0.3255f, 0.337f, 0.337f, 1.0f }; +ColorRGBA Bed3D::DEFAULT_MODEL_COLOR_DARK = { 0.255f, 0.255f, 0.283f, 1.0f }; +ColorRGBA Bed3D::DEFAULT_SOLID_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f }; +ColorRGBA Bed3D::DEFAULT_TRANSPARENT_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 0.6f }; + ColorRGBA Bed3D::AXIS_X_COLOR = ColorRGBA::X(); ColorRGBA Bed3D::AXIS_Y_COLOR = ColorRGBA::Y(); ColorRGBA Bed3D::AXIS_Z_COLOR = ColorRGBA::Z(); diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 1f3d3aab8a..c138e8c8dc 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -47,6 +47,12 @@ bool init_model_from_poly(GLModel &model, const ExPolygon &poly, float z); class Bed3D { public: + // ORCA make bed colors accessable for 2D bed + static ColorRGBA DEFAULT_MODEL_COLOR; + static ColorRGBA DEFAULT_MODEL_COLOR_DARK; + static ColorRGBA DEFAULT_SOLID_GRID_COLOR; + static ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR; + static ColorRGBA AXIS_X_COLOR; static ColorRGBA AXIS_Y_COLOR; static ColorRGBA AXIS_Z_COLOR; diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 67814d66be..e70a888ecf 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -458,13 +458,13 @@ void BedShapePanel::set_shape(const Pointfs& points) { BedShape shape(points); - m_shape_options_book->SetSelection(int(shape.get_page_type())); - shape.apply_optgroup_values(m_optgroups[int(shape.get_page_type())]); - // Copy the polygon to the canvas, make a copy of the array, if custom shape is selected if (shape.is_custom()) m_loaded_shape = points; + m_shape_options_book->SetSelection(int(shape.get_page_type())); + shape.apply_optgroup_values(m_optgroups[int(shape.get_page_type())]); + update_shape(); return; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 2b022d762d..f45ae34c46 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -30,6 +30,7 @@ #include "libslic3r/PresetBundle.hpp" #include "BackgroundSlicingProcess.hpp" #include "Widgets/Label.hpp" +#include "2DBed.hpp" #include "3DBed.hpp" #include "PartPlate.hpp" #include "Camera.hpp" @@ -466,65 +467,22 @@ void PartPlate::calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox m_gridlines.reset(); m_gridlines_bolder.reset(); - Polylines axes_lines, axes_lines_bolder; - int count = 0; - int step = 10; // Uses up to 599mm Main Grid: 10 x 5 = 50mm - // Orca: use 500 x 500 bed size as baseline. - // if the grid is too dense, we increase the step - auto min_edge_scaled = (pp_bbox.size() / ((coord_t) scale_(1))).minCoeff(); - if ( min_edge_scaled >= 6000) // Switch when short edge >= 6000mm Main Grid: 100 x 5 = 500mm - step = 100; - else if (min_edge_scaled >= 1200) // Switch when short edge >= 1200mm Main Grid: 50 x 5 = 250mm - step = 50; - else if (min_edge_scaled >= 600) // Switch when short edge >= 600mm Main Grid: 20 x 5 = 100mm - step = 20; + // calculate and generate grid + int step = Bed_2D::calculate_grid_step(pp_bbox); + Vec2d scaled_origin = Vec2d(scale_(m_origin.x()),scale_(m_origin.x())); + auto grid_lines = Bed_2D::generate_grid(poly, pp_bbox, scaled_origin, scale_(step), SCALED_EPSILON); - // ORCA draw grid lines relative to origin - for (coord_t x = scale_(m_origin.x()); x >= pp_bbox.min(0); x -= scale_(step)) { // Negative X axis - (count % 5 == 0 ? axes_lines_bolder : axes_lines).push_back(Polyline( - Point(x, pp_bbox.min(1)), - Point(x, pp_bbox.max(1)) - )); - count ++; - } - count = 0; - for (coord_t x = scale_(m_origin.x()); x <= pp_bbox.max(0); x += scale_(step)) { // Positive X axis - (count % 5 == 0 ? axes_lines_bolder : axes_lines).push_back(Polyline( - Point(x, pp_bbox.min(1)), - Point(x, pp_bbox.max(1)) - )); - count ++; - } - count = 0; - for (coord_t y = scale_(m_origin.y()); y >= pp_bbox.min(1); y -= scale_(step)) { // Negative Y axis - (count % 5 == 0 ? axes_lines_bolder : axes_lines).push_back(Polyline( - Point(pp_bbox.min(0), y), - Point(pp_bbox.max(0), y) - )); - count ++; - } - count = 0; - for (coord_t y = scale_(m_origin.y()); y <= pp_bbox.max(1); y += scale_(step)) { // Positive Y axis - (count % 5 == 0 ? axes_lines_bolder : axes_lines).push_back(Polyline( - Point(pp_bbox.min(0), y), - Point(pp_bbox.max(0), y) - )); - count ++; - } - count = 0; - - // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped - Lines gridlines = to_lines(intersection_pl(axes_lines, offset(poly, (float)SCALED_EPSILON))); - Lines gridlines_bolder = to_lines(intersection_pl(axes_lines_bolder, offset(poly, (float)SCALED_EPSILON))); + Lines lines_thin = to_lines(grid_lines[0]); + Lines lines_bold = to_lines(grid_lines[1]); // append bed contours Lines contour_lines = to_lines(poly); - std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines)); + std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(lines_thin)); - if (!init_model_from_lines(m_gridlines, gridlines, GROUND_Z_GRIDLINE)) + if (!init_model_from_lines(m_gridlines , lines_thin, GROUND_Z_GRIDLINE)) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; - if (!init_model_from_lines(m_gridlines_bolder, gridlines_bolder, GROUND_Z_GRIDLINE)) + if (!init_model_from_lines(m_gridlines_bolder, lines_bold, GROUND_Z_GRIDLINE)) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n"; }