Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEnrico Turri <enricoturri@seznam.cz>2019-06-24 14:21:14 +0300
committerEnrico Turri <enricoturri@seznam.cz>2019-06-24 14:21:14 +0300
commit53d1ff879c805a8ca53d1fa5deea3c3f162ad259 (patch)
treec1ad11ccf0b99c66b96bb9e156d3ac36440e6cc8 /src
parent7aaba25520ea37d662ced74b465b66c394f34593 (diff)
parent0f35a95d752a06a9b4b17f9bc806b8d44cb25db9 (diff)
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/MTUtils.hpp207
-rw-r--r--src/libslic3r/ModelArrange.cpp31
-rw-r--r--src/slic3r/GUI/wxExtensions.cpp78
-rw-r--r--src/slic3r/GUI/wxExtensions.hpp4
4 files changed, 219 insertions, 101 deletions
diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp
index 0afe3563f..b261a79be 100644
--- a/src/libslic3r/MTUtils.hpp
+++ b/src/libslic3r/MTUtils.hpp
@@ -1,172 +1,218 @@
#ifndef MTUTILS_HPP
#define MTUTILS_HPP
-#include <atomic> // for std::atomic_flag and memory orders
-#include <mutex> // for std::lock_guard
-#include <functional> // for std::function
-#include <utility> // for std::forward
+#include <atomic> // for std::atomic_flag and memory orders
+#include <mutex> // for std::lock_guard
+#include <functional> // for std::function
+#include <utility> // for std::forward
#include <algorithm>
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 T> class CachedObject {
+template<class T> class CachedObject
+{
public:
// Method type which refreshes the object when it has been invalidated
- using Setter = std::function<void(T&)>;
+ using Setter = std::function<void(T &)>;
+
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<void(T&)> m_setter;
-public:
+ // the setter will be called just before the object's const value is
+ // about to be retrieved.
+ std::function<void(T &)> m_setter;
+public:
// Forwarded constructor
- template<class...Args> inline CachedObject(Setter fn, Args&&...args):
- m_obj(std::forward<Args>(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<void()> fn) {
- std::lock_guard<SpinMutex> lck(m_lck); fn(); m_valid = false;
+ template<class... Args>
+ inline CachedObject(Setter fn, Args &&... args)
+ : m_obj(std::forward<Args>(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<void()> fn)
+ {
+ std::lock_guard<SpinMutex> lck(m_lck);
+ fn();
+ m_valid = false;
}
// Get the const object properly updated.
- inline const T& get() {
+ inline const T &get()
+ {
std::lock_guard<SpinMutex> 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 Vector, // The container type, must be random access...
+template<class Vector, // The container type, must be random access...
class Value = typename Vector::value_type // The value type
>
-class IndexBasedIterator {
+class IndexBasedIterator
+{
static const size_t NONE = size_t(-1);
std::reference_wrapper<Vector> 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 It> class Range {
+template<class It> 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<It>(b)), to(std::forward<It>(e)) {}
+ Range(It &&b, It &&e)
+ : from(std::forward<It>(b)), to(std::forward<It>(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<class C> bool all_of(const C &container) {
+template<class C> bool all_of(const C &container)
+{
return std::all_of(container.begin(),
container.end(),
[](const typename C::value_type &v) {
@@ -191,6 +239,15 @@ template<class C> bool all_of(const C &container) {
});
}
+template<class X, class Y> inline X ceil_i(X x, Y y)
+{
+ static_assert(std::is_integral<X>::value &&
+ std::is_integral<Y>::value && sizeof(X) >= sizeof(Y),
+ "");
+
+ return (x % y) ? x / y + 1 : x / y;
}
+} // namespace Slic3r
+
#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 <libnest2d.h>
@@ -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<libnest2d::Coord>(bbb.min(0)),
- static_cast<libnest2d::Coord>(bbb.min(1))
- },
- {
- static_cast<libnest2d::Coord>(bbb.max(0)),
- static_cast<libnest2d::Coord>(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<libnest2d::Coord>(bbb.min(0)),
- static_cast<libnest2d::Coord>(bbb.min(1))
- },
- {
- static_cast<libnest2d::Coord>(bbb.max(0)),
- static_cast<libnest2d::Coord>(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()) {
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;