From 121b6c078b4e5217ca5818b23102a7725e7cf20f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 24 Jun 2019 13:01:52 +0200 Subject: [PATCH 1/3] Print bed not considered as object in arrange anymore. --- src/libslic3r/MTUtils.hpp | 9 +++++++++ src/libslic3r/ModelArrange.cpp | 31 ++++++++++++++----------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 0afe3563f..f6bff2b1f 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -191,6 +191,15 @@ template bool all_of(const C &container) { }); } +template inline X ceil_i(X x, Y y) +{ + static_assert(std::is_integral::value && + std::is_integral::value && sizeof(X) >= sizeof(Y), + ""); + + return (x % y) ? x / y + 1 : x / y; +} + } #endif // MTUTILS_HPP diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index a440c3999..36f7e3971 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -2,6 +2,7 @@ #include "Model.hpp" #include "Geometry.hpp" #include "SVG.hpp" +#include "MTUtils.hpp" #include @@ -820,15 +821,13 @@ bool arrange(Model &model, // The model with the geometries BoundingBox bbb(bed); auto& cfn = stopcondition; + + coord_t md = ceil_i(min_obj_distance, 2) - SCALED_EPSILON; - auto binbb = Box({ - static_cast(bbb.min(0)), - static_cast(bbb.min(1)) - }, - { - static_cast(bbb.max(0)), - static_cast(bbb.max(1)) - }); + auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md, + libnest2d::Coord{bbb.min(1)} - md}, + {libnest2d::Coord{bbb.max(0)} + md, + libnest2d::Coord{bbb.max(1)} + md}); switch(bedhint.type) { case BedShapeType::BOX: { @@ -916,15 +915,13 @@ void find_new_position(const Model &model, BedShapeHint bedhint = bedShape(bed); BoundingBox bbb(bed); - - auto binbb = Box({ - static_cast(bbb.min(0)), - static_cast(bbb.min(1)) - }, - { - static_cast(bbb.max(0)), - static_cast(bbb.max(1)) - }); + + coord_t md = ceil_i(min_obj_distance, 2) - SCALED_EPSILON; + + auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md, + libnest2d::Coord{bbb.min(1)} - md}, + {libnest2d::Coord{bbb.max(0)} + md, + libnest2d::Coord{bbb.max(1)} + md}); for(auto it = shapemap.begin(); it != shapemap.end(); ++it) { if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) { From 75ed542686c66b21f5b2812ec48061055f2ca738 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 24 Jun 2019 13:03:46 +0200 Subject: [PATCH 2/3] Reformatted MTUtils with some refined directives. Only whitespace changes in MTUtils.hpp ! --- .clang-format | 8 +- src/libslic3r/MTUtils.hpp | 200 +++++++++++++++++++++++--------------- 2 files changed, 128 insertions(+), 80 deletions(-) diff --git a/.clang-format b/.clang-format index d5740f689..9cbcf26f2 100644 --- a/.clang-format +++ b/.clang-format @@ -18,7 +18,7 @@ AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes +AlwaysBreakTemplateDeclarations: false BinPackArguments: false BinPackParameters: false BraceWrapping: @@ -37,18 +37,18 @@ BraceWrapping: SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false -BreakBeforeBinaryOperators: All +BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: true +BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 75 CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false +CompactNamespaces: true ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index f6bff2b1f..b261a79be 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -1,172 +1,218 @@ #ifndef MTUTILS_HPP #define MTUTILS_HPP -#include // for std::atomic_flag and memory orders -#include // for std::lock_guard -#include // for std::function -#include // for std::forward +#include // for std::atomic_flag and memory orders +#include // for std::lock_guard +#include // for std::function +#include // for std::forward #include namespace Slic3r { /// Handy little spin mutex for the cached meshes. /// Implements the "Lockable" concept -class SpinMutex { - std::atomic_flag m_flg; +class SpinMutex +{ + std::atomic_flag m_flg; static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire; static const /*constexpr*/ auto MO_REL = std::memory_order_release; + public: inline SpinMutex() { m_flg.clear(MO_REL); } - inline void lock() { while(m_flg.test_and_set(MO_ACQ)); } + inline void lock() { while (m_flg.test_and_set(MO_ACQ)) ; } inline bool try_lock() { return !m_flg.test_and_set(MO_ACQ); } inline void unlock() { m_flg.clear(MO_REL); } }; /// A wrapper class around arbitrary object that needs thread safe caching. -template class CachedObject { +template class CachedObject +{ public: // Method type which refreshes the object when it has been invalidated - using Setter = std::function; + using Setter = std::function; + private: - T m_obj; // the object itself - bool m_valid; // invalidation flag - SpinMutex m_lck; // to make the caching thread safe + T m_obj; // the object itself + bool m_valid; // invalidation flag + SpinMutex m_lck; // to make the caching thread safe + + // the setter will be called just before the object's const value is + // about to be retrieved. + std::function m_setter; - // the setter will be called just before the object's const value is about - // to be retrieved. - std::function m_setter; public: - // Forwarded constructor - template inline CachedObject(Setter fn, Args&&...args): - m_obj(std::forward(args)...), m_valid(false), m_setter(fn) {} + template + inline CachedObject(Setter fn, Args &&... args) + : m_obj(std::forward(args)...), m_valid(false), m_setter(fn) + {} - // invalidate the value of the object. The object will be refreshed at the - // next retrieval (Setter will be called). The data that is used in - // the setter function should be guarded as well during modification so the - // modification has to take place in fn. - inline void invalidate(std::function fn) { - std::lock_guard lck(m_lck); fn(); m_valid = false; + // invalidate the value of the object. The object will be refreshed at + // the next retrieval (Setter will be called). The data that is used in + // the setter function should be guarded as well during modification so + // the modification has to take place in fn. + inline void invalidate(std::function fn) + { + std::lock_guard lck(m_lck); + fn(); + m_valid = false; } // Get the const object properly updated. - inline const T& get() { + inline const T &get() + { std::lock_guard lck(m_lck); - if(!m_valid) { m_setter(m_obj); m_valid = true; } + if (!m_valid) { + m_setter(m_obj); + m_valid = true; + } return m_obj; } }; -/// An std compatible random access iterator which uses indices to the source -/// vector thus resistant to invalidation caused by relocations. It also "knows" -/// its container. No comparison is neccesary to the container "end()" iterator. -/// The template can be instantiated with a different value type than that of -/// the container's but the types must be compatible. E.g. a base class of the -/// contained objects is compatible. +/// An std compatible random access iterator which uses indices to the +/// source vector thus resistant to invalidation caused by relocations. It +/// also "knows" its container. No comparison is neccesary to the container +/// "end()" iterator. The template can be instantiated with a different +/// value type than that of the container's but the types must be +/// compatible. E.g. a base class of the contained objects is compatible. /// /// For a constant iterator, one can instantiate this template with a value /// type preceded with 'const'. -template -class IndexBasedIterator { +class IndexBasedIterator +{ static const size_t NONE = size_t(-1); std::reference_wrapper m_index_ref; - size_t m_idx = NONE; -public: + size_t m_idx = NONE; - using value_type = Value; - using pointer = Value *; - using reference = Value &; - using difference_type = long; +public: + using value_type = Value; + using pointer = Value *; + using reference = Value &; + using difference_type = long; using iterator_category = std::random_access_iterator_tag; - inline explicit - IndexBasedIterator(Vector& index, size_t idx): - m_index_ref(index), m_idx(idx) {} + inline explicit IndexBasedIterator(Vector &index, size_t idx) + : m_index_ref(index), m_idx(idx) + {} // Post increment - inline IndexBasedIterator operator++(int) { - IndexBasedIterator cpy(*this); ++m_idx; return cpy; + inline IndexBasedIterator operator++(int) + { + IndexBasedIterator cpy(*this); + ++m_idx; + return cpy; } - inline IndexBasedIterator operator--(int) { - IndexBasedIterator cpy(*this); --m_idx; return cpy; + inline IndexBasedIterator operator--(int) + { + IndexBasedIterator cpy(*this); + --m_idx; + return cpy; } - inline IndexBasedIterator& operator++() { - ++m_idx; return *this; + inline IndexBasedIterator &operator++() + { + ++m_idx; + return *this; } - inline IndexBasedIterator& operator--() { - --m_idx; return *this; + inline IndexBasedIterator &operator--() + { + --m_idx; + return *this; } - inline IndexBasedIterator& operator+=(difference_type l) { - m_idx += size_t(l); return *this; + inline IndexBasedIterator &operator+=(difference_type l) + { + m_idx += size_t(l); + return *this; } - inline IndexBasedIterator operator+(difference_type l) { - auto cpy = *this; cpy += l; return cpy; + inline IndexBasedIterator operator+(difference_type l) + { + auto cpy = *this; + cpy += l; + return cpy; } - inline IndexBasedIterator& operator-=(difference_type l) { - m_idx -= size_t(l); return *this; + inline IndexBasedIterator &operator-=(difference_type l) + { + m_idx -= size_t(l); + return *this; } - inline IndexBasedIterator operator-(difference_type l) { - auto cpy = *this; cpy -= l; return cpy; + inline IndexBasedIterator operator-(difference_type l) + { + auto cpy = *this; + cpy -= l; + return cpy; } operator difference_type() { return difference_type(m_idx); } /// Tesing the end of the container... this is not possible with std /// iterators. - inline bool is_end() const { return m_idx >= m_index_ref.get().size();} + inline bool is_end() const + { + return m_idx >= m_index_ref.get().size(); + } - inline Value & operator*() const { + inline Value &operator*() const + { assert(m_idx < m_index_ref.get().size()); return m_index_ref.get().operator[](m_idx); } - inline Value * operator->() const { + inline Value *operator->() const + { assert(m_idx < m_index_ref.get().size()); return &m_index_ref.get().operator[](m_idx); } /// If both iterators point past the container, they are equal... - inline bool operator ==(const IndexBasedIterator& other) { + inline bool operator==(const IndexBasedIterator &other) + { size_t e = m_index_ref.get().size(); return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e); } - inline bool operator !=(const IndexBasedIterator& other) { + inline bool operator!=(const IndexBasedIterator &other) + { return !(*this == other); } - inline bool operator <=(const IndexBasedIterator& other) { + inline bool operator<=(const IndexBasedIterator &other) + { return (m_idx < other.m_idx) || (*this == other); } - inline bool operator <(const IndexBasedIterator& other) { + inline bool operator<(const IndexBasedIterator &other) + { return m_idx < other.m_idx && (*this != other); } - inline bool operator >=(const IndexBasedIterator& other) { + inline bool operator>=(const IndexBasedIterator &other) + { return m_idx > other.m_idx || *this == other; } - inline bool operator >(const IndexBasedIterator& other) { + inline bool operator>(const IndexBasedIterator &other) + { return m_idx > other.m_idx && *this != other; } }; /// A very simple range concept implementation with iterator-like objects. -template class Range { +template class Range +{ It from, to; -public: +public: // The class is ready for range based for loops. It begin() const { return from; } It end() const { return to; } @@ -175,15 +221,17 @@ public: using Type = It; Range() = default; - Range(It &&b, It &&e): - from(std::forward(b)), to(std::forward(e)) {} + Range(It &&b, It &&e) + : from(std::forward(b)), to(std::forward(e)) + {} // Some useful container-like methods... inline size_t size() const { return end() - begin(); } - inline bool empty() const { return size() == 0; } + inline bool empty() const { return size() == 0; } }; -template bool all_of(const C &container) { +template bool all_of(const C &container) +{ return std::all_of(container.begin(), container.end(), [](const typename C::value_type &v) { @@ -196,10 +244,10 @@ template inline X ceil_i(X x, Y y) static_assert(std::is_integral::value && std::is_integral::value && sizeof(X) >= sizeof(Y), ""); - + return (x % y) ? x / y + 1 : x / y; } -} +} // namespace Slic3r #endif // MTUTILS_HPP From 14d8621ffe6e7791528fede8d9e101d3b06b56ce Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 24 Jun 2019 13:11:18 +0200 Subject: [PATCH 3/3] Color_print issues : - fixed #1933 - implemented thumb moving to the mouse click position - implemented "discard color changes" button --- src/slic3r/GUI/wxExtensions.cpp | 78 +++++++++++++++++++++++++++++---- src/slic3r/GUI/wxExtensions.hpp | 4 ++ 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 406daccf5..ed496a97e 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1583,6 +1583,9 @@ DoubleSlider::DoubleSlider( wxWindow *parent, m_bmp_one_layer_unlock_off = ScalableBitmap(this, "one_layer_unlock_off.png"); m_lock_icon_dim = m_bmp_one_layer_lock_on.bmp().GetSize().x; + m_bmp_revert = ScalableBitmap(this, "undo"); + m_revert_icon_dim = m_bmp_revert.bmp().GetSize().x; + m_selection = ssUndef; // slider events @@ -1638,6 +1641,9 @@ void DoubleSlider::msw_rescale() m_bmp_one_layer_unlock_off.msw_rescale(); m_lock_icon_dim = m_bmp_one_layer_lock_on.bmp().GetSize().x; + m_bmp_revert.msw_rescale(); + m_revert_icon_dim = m_bmp_revert.bmp().GetSize().x; + SLIDER_MARGIN = 4 + Slic3r::GUI::wxGetApp().em_unit(); SetMinSize(get_min_size()); @@ -1874,8 +1880,11 @@ void DoubleSlider::render() //draw color print ticks draw_ticks(dc); - //draw color print ticks + //draw lock/unlock draw_one_layer_icon(dc); + + //draw revert bitmap (if it's shown) + draw_revert_icon(dc); } void DoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end) @@ -2102,6 +2111,24 @@ void DoubleSlider::draw_one_layer_icon(wxDC& dc) m_rect_one_layer_icon = wxRect(x_draw, y_draw, m_lock_icon_dim, m_lock_icon_dim); } +void DoubleSlider::draw_revert_icon(wxDC& dc) +{ + if (m_ticks.empty()) + return; + + int width, height; + get_size(&width, &height); + + wxCoord x_draw, y_draw; + is_horizontal() ? x_draw = width-2 : x_draw = 0.25*SLIDER_MARGIN; + is_horizontal() ? y_draw = 0.25*SLIDER_MARGIN: y_draw = height-2; + + dc.DrawBitmap(m_bmp_revert.bmp(), x_draw, y_draw); + + //update rect of the lock/unlock icon + m_rect_revert_icon = wxRect(x_draw, y_draw, m_revert_icon_dim, m_revert_icon_dim); +} + void DoubleSlider::update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection) { const wxRect& rect = wxRect(begin_x, begin_y, m_thumb_size.x, m_thumb_size.y); @@ -2118,8 +2145,8 @@ int DoubleSlider::get_value_from_position(const wxCoord x, const wxCoord y) if (is_horizontal()) return int(double(x - SLIDER_MARGIN) / step + 0.5); - else - return int(m_min_value + double(height - SLIDER_MARGIN - y) / step + 0.5); + + return int(m_min_value + double(height - SLIDER_MARGIN - y) / step + 0.5); } void DoubleSlider::detect_selected_slider(const wxPoint& pt) @@ -2169,7 +2196,10 @@ void DoubleSlider::ChangeOneLayerLock() void DoubleSlider::OnLeftDown(wxMouseEvent& event) { + if (HasCapture()) + return; this->CaptureMouse(); + wxClientDC dc(this); wxPoint pos = event.GetLogicalPosition(dc); if (is_point_in_rect(pos, m_rect_tick_action) && m_is_enabled_tick_manipulation) { @@ -2179,6 +2209,7 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event) m_is_left_down = true; if (is_point_in_rect(pos, m_rect_one_layer_icon)) { + // switch on/off one layer mode m_is_one_layer = !m_is_one_layer; if (!m_is_one_layer) { SetLowerValue(m_min_value); @@ -2187,20 +2218,36 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event) m_selection == ssLower ? correct_lower_value() : correct_higher_value(); if (!m_selection) m_selection = ssHigher; } + else if (is_point_in_rect(pos, m_rect_revert_icon)) { + // discard all color changes + SetLowerValue(m_min_value); + SetHigherValue(m_max_value); + + m_selection == ssLower ? correct_lower_value() : correct_higher_value(); + if (!m_selection) m_selection = ssHigher; + + m_ticks.clear(); + wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); + } else detect_selected_slider(pos); - if (!m_selection && m_is_enabled_tick_manipulation) { - const auto tick = is_point_near_tick(pos); - if (tick >= 0) + if (!m_selection) { + const int tick_val = is_point_near_tick(pos); + /* Set current thumb position to the nearest tick (if it is) + * OR to a value corresponding to the mouse click + * */ + const int mouse_val = tick_val >= 0 && m_is_enabled_tick_manipulation ? tick_val : + get_value_from_position(pos.x, pos.y); + if (mouse_val >= 0) { - if (abs(tick - m_lower_value) < abs(tick - m_higher_value)) { - SetLowerValue(tick); + if (abs(mouse_val - m_lower_value) < abs(mouse_val - m_higher_value)) { + SetLowerValue(mouse_val); correct_lower_value(); m_selection = ssLower; } else { - SetHigherValue(tick); + SetHigherValue(mouse_val); correct_higher_value(); m_selection = ssHigher; } @@ -2240,9 +2287,13 @@ void DoubleSlider::OnMotion(wxMouseEvent& event) const wxClientDC dc(this); const wxPoint pos = event.GetLogicalPosition(dc); + m_is_one_layer_icon_focesed = is_point_in_rect(pos, m_rect_one_layer_icon); + bool is_revert_icon_focused = false; + if (!m_is_left_down && !m_is_one_layer) { m_is_action_icon_focesed = is_point_in_rect(pos, m_rect_tick_action); + is_revert_icon_focused = !m_ticks.empty() && is_point_in_rect(pos, m_rect_revert_icon); } else if (m_is_left_down || m_is_right_down) { if (m_selection == ssLower) { @@ -2262,6 +2313,13 @@ void DoubleSlider::OnMotion(wxMouseEvent& event) Update(); event.Skip(); + // Set tooltips with information for each icon + const wxString tooltip = m_is_one_layer_icon_focesed ? _(L("One layer mode")) : + m_is_action_icon_focesed ? _(L("Add/Del color change")) : + is_revert_icon_focused ? _(L("Discard all color changes")) : + wxEmptyString; + this->SetToolTip(tooltip); + if (action) { wxCommandEvent e(wxEVT_SCROLL_CHANGED); @@ -2412,7 +2470,9 @@ void DoubleSlider::OnChar(wxKeyEvent& event) void DoubleSlider::OnRightDown(wxMouseEvent& event) { + if (HasCapture()) return; this->CaptureMouse(); + const wxClientDC dc(this); detect_selected_slider(event.GetLogicalPosition(dc)); if (!m_selection) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index dd035690a..081c0d48f 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -742,6 +742,7 @@ protected: void draw_ticks(wxDC& dc); void draw_colored_band(wxDC& dc); void draw_one_layer_icon(wxDC& dc); + void draw_revert_icon(wxDC& dc); void draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection); void draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, SelectedSlider selection); void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const; @@ -783,6 +784,7 @@ private: ScalableBitmap m_bmp_one_layer_lock_off; ScalableBitmap m_bmp_one_layer_unlock_on; ScalableBitmap m_bmp_one_layer_unlock_off; + ScalableBitmap m_bmp_revert; SelectedSlider m_selection; bool m_is_left_down = false; bool m_is_right_down = false; @@ -796,9 +798,11 @@ private: wxRect m_rect_higher_thumb; wxRect m_rect_tick_action; wxRect m_rect_one_layer_icon; + wxRect m_rect_revert_icon; wxSize m_thumb_size; int m_tick_icon_dim; int m_lock_icon_dim; + int m_revert_icon_dim; long m_style; float m_label_koef = 1.0;