From 19a96336ffad44ad3c38383e0d7c93047c4258ad Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 20 Mar 2019 18:03:11 +0100 Subject: [PATCH 01/29] WIP on slice indexing --- src/libslic3r/SLAPrint.cpp | 300 +++++++++++++++++++++++++------------ src/libslic3r/SLAPrint.hpp | 112 ++++++++++---- 2 files changed, 289 insertions(+), 123 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 83fa61fdd0..62ddba84b7 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -567,6 +567,18 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { return scfg; } +sla::PoolConfig make_pool_config(const SLAPrintObjectConfig& c) { + sla::PoolConfig pcfg; + + pcfg.min_wall_thickness_mm = c.pad_wall_thickness.getFloat(); + pcfg.wall_slope = c.pad_wall_slope.getFloat(); + pcfg.edge_radius_mm = c.pad_edge_radius.getFloat(); + pcfg.max_merge_distance_mm = c.pad_max_merge_distance.getFloat(); + pcfg.min_wall_height_mm = c.pad_wall_height.getFloat(); + + return pcfg; +} + void swapXY(ExPolygon& expoly) { for(auto& p : expoly.contour.points) std::swap(p(X), p(Y)); for(auto& h : expoly.holes) for(auto& p : h.points) std::swap(p(X), p(Y)); @@ -647,18 +659,58 @@ void SLAPrint::process() // Slicing the model object. This method is oversimplified and needs to // be compared with the fff slicing algorithm for verification auto slice_model = [this, ilh](SLAPrintObject& po) { - double lh = po.m_config.layer_height.getFloat(); - TriangleMesh mesh = po.transformed_mesh(); + + // We need to prepare the slice index... + + auto&& bb3d = mesh.bounding_box(); + float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); + float maxZ = float(bb3d.max(Z)); + auto flh = float(po.m_config.layer_height.getFloat()); + + auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + + po.m_slice_index.clear(); + po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); + po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + + for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { + po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + } + + + using SlRec = SLAPrintObject::SliceRecord; + auto slindex_it = std::lower_bound(po.m_slice_index.begin(), + po.m_slice_index.end(), + float(bb3d.min(Z)), // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + if(slindex_it == po.m_slice_index.end()) + throw std::runtime_error(L("Slicing had to be stopped " + "due to an internal error.")); + + po.m_height_levels.clear(); + po.m_height_levels.reserve(po.m_slice_index.size()); + for(auto it = slindex_it; it != po.m_slice_index.end(); ++it) + po.m_height_levels.emplace_back(it->slice_level()); + TriangleMeshSlicer slicer(&mesh); - // The 1D grid heights - std::vector heights = calculate_heights(mesh.bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + po.m_model_slices.clear(); + slicer.slice(po.m_height_levels, + float(po.config().slice_closing_radius.value), + &po.m_model_slices, + [this](){ throw_if_canceled(); }); - auto& layers = po.m_model_slices; layers.clear(); - slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); }); + auto mit = slindex_it; + for(size_t id = 0; + id < po.m_model_slices.size() && mit != po.m_slice_index.end(); + id++) + { + mit->set_model_slice_idx(id); ++mit; + } }; // In this step we check the slices, identify island and cover them with @@ -680,12 +732,8 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - double lh = po.m_config.layer_height.getFloat(); - - std::vector heights = - calculate_heights(po.transformed_mesh().bounding_box(), - float(po.get_elevation()), - ilh, float(lh)); + auto&& bb = po.transformed_mesh().bounding_box(); + std::vector heights = po.get_slice_levels(float(bb.min(Z))); this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -837,79 +885,86 @@ void SLAPrint::process() auto lh = float(po.m_config.layer_height.getFloat()); sd->support_slices = sd->support_tree_ptr->slice(lh, ilh); } + + for(size_t i = 0; + i < sd->support_slices.size() && i < po.m_slice_index.size(); + ++i) + { + po.m_slice_index[i].set_support_slice_idx(i); + } }; // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) auto index_slices = [this, ilhd](SLAPrintObject& po) { - po.m_slice_index.clear(); - auto sih = LevelID(scale_(ilhd)); +// po.m_slice_index.clear(); +// auto sih = LevelID(scale_(ilhd)); - // Establish the slice grid boundaries - auto bb = po.transformed_mesh().bounding_box(); - double modelgnd = bb.min(Z); - double elevation = po.get_elevation(); - double lh = po.m_config.layer_height.getFloat(); - double minZ = modelgnd - elevation; +// // Establish the slice grid boundaries +// auto bb = po.transformed_mesh().bounding_box(); +// double modelgnd = bb.min(Z); +// double elevation = po.get_elevation(); +// double lh = po.m_config.layer_height.getFloat(); +// double minZ = modelgnd - elevation; - // scaled values: - auto sminZ = LevelID(scale_(minZ)); - auto smaxZ = LevelID(scale_(bb.max(Z))); - auto smodelgnd = LevelID(scale_(modelgnd)); - auto slh = LevelID(scale_(lh)); +// // scaled values: +// auto sminZ = LevelID(scale_(minZ)); +// auto smaxZ = LevelID(scale_(bb.max(Z))); +// auto smodelgnd = LevelID(scale_(modelgnd)); +// auto slh = LevelID(scale_(lh)); - // It is important that the next levels match the levels in - // model_slice method. Only difference is that here it works with - // scaled coordinates - po.m_level_ids.clear(); - for(LevelID h = sminZ + sih; h < smaxZ; h += slh) - if(h >= smodelgnd) po.m_level_ids.emplace_back(h); +// // It is important that the next levels match the levels in +// // model_slice method. Only difference is that here it works with +// // scaled coordinates +// po.m_level_ids.clear(); +// for(LevelID h = sminZ + sih; h < smaxZ; h += slh) +// if(h >= smodelgnd) po.m_level_ids.emplace_back(h); - std::vector& oslices = po.m_model_slices; +// std::vector& oslices = po.m_model_slices; - // If everything went well this code should not run at all, but - // let's be robust... - // assert(levelids.size() == oslices.size()); - if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... +// // If everything went well this code should not run at all, but +// // let's be robust... +// // assert(levelids.size() == oslices.size()); +// if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... - BOOST_LOG_TRIVIAL(warning) - << "Height level mismatch at rasterization!\n"; +// BOOST_LOG_TRIVIAL(warning) +// << "Height level mismatch at rasterization!\n"; - LevelID lastlvl = po.m_level_ids.back(); - while(po.m_level_ids.size() < oslices.size()) { - lastlvl += slh; - po.m_level_ids.emplace_back(lastlvl); - } - } +// LevelID lastlvl = po.m_level_ids.back(); +// while(po.m_level_ids.size() < oslices.size()) { +// lastlvl += slh; +// po.m_level_ids.emplace_back(lastlvl); +// } +// } - for(size_t i = 0; i < oslices.size(); ++i) { - LevelID h = po.m_level_ids[i]; +// for(size_t i = 0; i < oslices.size(); ++i) { +// LevelID h = po.m_level_ids[i]; - float fh = float(double(h) * SCALING_FACTOR); +// float fh = float(double(h) * SCALING_FACTOR); - // now for the public slice index: - SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; - // There should be only one slice layer for each print object - assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); - sr.model_slices_idx = i; - } +// // now for the public slice index: +// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; +// // There should be only one slice layer for each print object +// assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); +// sr.model_slices_idx = i; +// } - if(po.m_supportdata) { // deal with the support slices if present - std::vector& sslices = po.m_supportdata->support_slices; - po.m_supportdata->level_ids.clear(); - po.m_supportdata->level_ids.reserve(sslices.size()); +// if(po.m_supportdata) { // deal with the support slices if present +// std::vector& sslices = po.m_supportdata->support_slices; +// po.m_supportdata->level_ids.clear(); +// po.m_supportdata->level_ids.reserve(sslices.size()); - for(int i = 0; i < int(sslices.size()); ++i) { - LevelID h = sminZ + sih + i * slh; - po.m_supportdata->level_ids.emplace_back(h); +// for(int i = 0; i < int(sslices.size()); ++i) { +// LevelID h = sminZ + sih + i * slh; +// po.m_supportdata->level_ids.emplace_back(h); - float fh = float(double(h) * SCALING_FACTOR); +// float fh = float(double(h) * SCALING_FACTOR); - SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; - assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); - sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); - } - } +// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; +// assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); +// sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); +// } +// } // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); @@ -923,31 +978,33 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { - auto& po = *o; - std::vector& oslices = po.m_model_slices; +// auto& po = *o; +// std::vector& oslices = po.m_model_slices; - // We need to adjust the min Z level of the slices to be zero - LevelID smfirst = - po.m_supportdata && !po.m_supportdata->level_ids.empty() ? - po.m_supportdata->level_ids.front() : 0; - LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); - LevelID gndlvl = -(std::min(smfirst, mfirst)); +// // We need to adjust the min Z level of the slices to be zero +// LevelID smfirst = +// po.m_supportdata && !po.m_supportdata->level_ids.empty() ? +// po.m_supportdata->level_ids.front() : 0; +// LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); +// LevelID gndlvl = -(std::min(smfirst, mfirst)); - // now merge this object's support and object slices with the rest - // of the print object slices +// // now merge this object's support and object slices with the rest +// // of the print object slices - for(size_t i = 0; i < oslices.size(); ++i) { - auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; - lyrs.emplace_back(oslices[i], po.m_instances); - } +// for(size_t i = 0; i < oslices.size(); ++i) { +// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; +// lyrs.emplace_back(oslices[i], po.m_instances); +// } - if(!po.m_supportdata) continue; - std::vector& sslices = po.m_supportdata->support_slices; - for(size_t i = 0; i < sslices.size(); ++i) { - LayerRefs& lyrs = - m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; - lyrs.emplace_back(sslices[i], po.m_instances); - } +// if(!po.m_supportdata) continue; +// std::vector& sslices = po.m_supportdata->support_slices; +// for(size_t i = 0; i < sslices.size(); ++i) { +// LayerRefs& lyrs = +// m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; +// lyrs.emplace_back(sslices[i], po.m_instances); +// } + +// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1474,11 +1531,7 @@ double SLAPrintObject::get_elevation() const { // its walls but currently it is half of its thickness. Whatever it // will be in the future, we provide the config to the get_pad_elevation // method and we will have the correct value - sla::PoolConfig pcfg; - pcfg.min_wall_height_mm = m_config.pad_wall_height.getFloat(); - pcfg.min_wall_thickness_mm = m_config.pad_wall_thickness.getFloat(); - pcfg.edge_radius_mm = m_config.pad_edge_radius.getFloat(); - pcfg.max_merge_distance_mm = m_config.pad_max_merge_distance.getFloat(); + sla::PoolConfig pcfg = make_pool_config(m_config); ret += sla::get_pad_elevation(pcfg); } @@ -1509,6 +1562,33 @@ const std::vector& SLAPrintObject::get_support_points() const return m_supportdata->support_points; } +SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const +{ + SliceIterator ret = so == soModel ? get_model_slices().end() : + get_support_slices().end(); + + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + k, + SliceRecord::cmpfn); + + if(it != m_slice_index.end()) { + ret = it->get_slices(*this, so); + } + + return ret; +} + +SliceRange SLAPrintObject::get_slices(SliceOrigin so, + float from_level, + float to_level) const +{ + auto from = LevelID(double(from_level) / SCALING_FACTOR); + auto to = LevelID(double(to_level) / SCALING_FACTOR); + + return SliceRange(get_slices(so, from), get_slices(so, to)); +} + const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1516,12 +1596,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const +const std::vector& +SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); return m_slice_index; } +std::vector SLAPrintObject::get_slice_levels(float from_eq) const +{ + using SlRec = SLAPrintObject::SliceRecord; + auto it = std::lower_bound(m_slice_index.begin(), + m_slice_index.end(), + from_eq, // model start z + [](const SlRec& sr1, const SlRec& sr2){ + return sr1.slice_level() < sr2.slice_level(); + }); + + std::vector heights; heights.reserve(m_slice_index.size()); + for(; it != m_slice_index.end(); ++it) + heights.emplace_back(it->slice_level()); +} + const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); @@ -1639,4 +1735,18 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } +SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, + SliceOrigin so) const +{ + + const std::vector& v = so == soModel? po.get_model_slices() : + po.get_support_slices(); + + Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + + using DiffT = std::vector::const_iterator::difference_type; + + return idx == NONE? v.end() : v.begin() + DiffT(idx); +} + } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index c06e2fc777..4d5f1d0daa 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -35,12 +35,34 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; +template struct Range { + It from, to; + It begin() const { return from; } + It end() const { return to; } + using Type = It; + + Range() = default; + explicit Range(It &&b, It &&e): + from(std::forward(b)), to(std::forward(e)) {} +}; + +enum SliceOrigin { soSlice, soModel }; + +using SliceStore = std::vector; +using SliceIterator = SliceStore::const_iterator; +using SliceRange = Range; + class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. using Inherited = _SLAPrintObjectBase; public: + + // I refuse to grantee copying (Tamas) + SLAPrintObject(const SLAPrintObject&) = delete; + SLAPrintObject& operator=(const SLAPrintObject&) = delete; + const SLAPrintObjectConfig& config() const { return m_config; } const Transform3d& trafo() const { return m_trafo; } @@ -82,6 +104,66 @@ public: // pad is not, then without the pad, otherwise the full value is returned. double get_current_elevation() const; + // This method returns the support points of this SLAPrintObject. + const std::vector& get_support_points() const; + +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class SliceRecord { + public: + using Key = LevelID; + + private: + using Idx = size_t; + static const Idx NONE = Idx(-1); // this will be the max limit of size_t + + LevelID m_print_z = 0; // Top of the layer + float m_slice_z = 0.f; // Exact level of the slice + float m_height = 0.f; // Height of the sliced layer + Idx m_model_slices_idx = NONE; + Idx m_support_slices_idx = NONE; + + public: + + SliceRecord(Key key, float slicez, float height): + m_print_z(key), m_slice_z(slicez), m_height(height) {} + + inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) + { + return sr1.key() < sr2.key(); + } + + inline Key key() const { return m_print_z; } + inline float slice_level() const { return m_slice_z; } + inline float layer_height() const { return m_height; } + + SliceIterator get_slices(const SLAPrintObject& po, + SliceOrigin so) const; + + void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } + void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + }; + + + // Retrieve the slice index which is readable only after slaposIndexSlices + // is done. + const std::vector& get_slice_index() const; + + std::vector get_slice_levels(float from_eq) const; + +public: + + SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + SliceRange get_slices( + SliceOrigin so, + float from_level, + float to_level = std::numeric_limits::infinity()) const; + // These two methods should be callable on the client side (e.g. UI thread) // when the appropriate steps slaposObjectSlice and slaposSliceSupports // are ready. All the print objects are processed before slapsRasterize so @@ -89,33 +171,6 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - // This method returns the support points of this SLAPrintObject. - const std::vector& get_support_points() const; - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. - struct SliceRecord { - using Key = float; - - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t - - Idx model_slices_idx = NONE; - Idx support_slices_idx = NONE; - }; - - using SliceIndex = std::map; - - // Retrieve the slice index which is readable only after slaposIndexSlices - // is done. - const SliceIndex& get_slice_index() const; - - // I refuse to grantee copying (Tamas) - SLAPrintObject(const SLAPrintObject&) = delete; - SLAPrintObject& operator=(const SLAPrintObject&) = delete; - protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -154,11 +209,12 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - SliceIndex m_slice_index; + std::vector m_slice_index; // The height levels corrected and scaled up in integer values. This will // be used at rasterization. std::vector m_level_ids; + std::vector m_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; From 213ff2852a247d2ba8d27d750879bf13d3c08190 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 21 Mar 2019 11:44:39 +0100 Subject: [PATCH 02/29] We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955. So we are applying a workaround here, just on linux. --- src/slic3r/GUI/GUI_Preview.cpp | 22 ++++++++++------------ src/slic3r/GUI/GUI_Preview.hpp | 4 ++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index be3fad9ece..e5e2ce6be9 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -354,23 +354,14 @@ void Preview::load_print(bool keep_z_range) void Preview::reload_print(bool keep_volumes) { -#ifndef __linux__ - if (m_volumes_cleanup_required || !keep_volumes) - { - m_canvas->reset_volumes(); - m_canvas->reset_legend_texture(); - m_loaded = false; - m_volumes_cleanup_required = false; - } -#endif // __linux__ - +#ifdef __linux__ + // We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955. + // So we are applying a workaround here: a delayed release of OpenGL vertex buffers. if (!IsShown()) { m_volumes_cleanup_required = !keep_volumes; return; } - -#ifdef __linux__ if (m_volumes_cleanup_required || !keep_volumes) { m_canvas->reset_volumes(); @@ -378,6 +369,13 @@ void Preview::reload_print(bool keep_volumes) m_loaded = false; m_volumes_cleanup_required = false; } +#else // __linux__ + if (!keep_volumes) + { + m_canvas->reset_volumes(); + m_canvas->reset_legend_texture(); + m_loaded = false; + } #endif // __linux__ load_print(); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 182eaa9528..96c49e54ff 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -84,7 +84,11 @@ class Preview : public wxPanel BackgroundSlicingProcess* m_process; GCodePreviewData* m_gcode_preview_data; +#ifdef __linux__ + // We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955. + // So we are applying a workaround here. bool m_volumes_cleanup_required; +#endif /* __linux__ */ // Calling this function object forces Plater::schedule_background_process. std::function m_schedule_background_process; From f76880cd5e5eed894e6ee0e9fac58ebf4d3e243c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 21 Mar 2019 11:54:25 +0100 Subject: [PATCH 03/29] Fix and optimization of the previous commit. --- src/slic3r/GUI/GUI_Preview.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index e5e2ce6be9..980843e8c5 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -174,7 +174,9 @@ Preview::Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_t , m_loaded(false) , m_enabled(false) , m_schedule_background_process(schedule_background_process_func) +#ifdef __linux__ , m_volumes_cleanup_required(false) +#endif // __linux__ { if (init(parent, bed, camera, view_toolbar)) { @@ -362,21 +364,19 @@ void Preview::reload_print(bool keep_volumes) m_volumes_cleanup_required = !keep_volumes; return; } - if (m_volumes_cleanup_required || !keep_volumes) + if ( +#ifdef __linux__ + m_volumes_cleanup_required || +#endif /* __linux__ */ + !keep_volumes) { m_canvas->reset_volumes(); m_canvas->reset_legend_texture(); m_loaded = false; +#ifdef __linux__ m_volumes_cleanup_required = false; +#endif /* __linux__ */ } -#else // __linux__ - if (!keep_volumes) - { - m_canvas->reset_volumes(); - m_canvas->reset_legend_texture(); - m_loaded = false; - } -#endif // __linux__ load_print(); } From f9e3b935d3a8960d51c89c23d74243ed0577ef08 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 21 Mar 2019 12:09:14 +0100 Subject: [PATCH 04/29] Yet another fix. --- src/slic3r/GUI/GUI_Preview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 980843e8c5..9bb6c97908 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -364,6 +364,7 @@ void Preview::reload_print(bool keep_volumes) m_volumes_cleanup_required = !keep_volumes; return; } +#endif /* __linux __ */ if ( #ifdef __linux__ m_volumes_cleanup_required || From d4dde12d0d031970113706a5dd954907776216ed Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 12:25:33 +0100 Subject: [PATCH 05/29] Slic3r compiles with the new slice index interface. --- src/libslic3r/SLAPrint.cpp | 151 +++++++++++++++++++++++---------- src/libslic3r/SLAPrint.hpp | 32 ++++--- src/slic3r/GUI/GLCanvas3D.cpp | 66 +++++++++----- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 4 files changed, 172 insertions(+), 83 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 62ddba84b7..938f148a30 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -678,14 +678,7 @@ void SLAPrint::process() po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); } - - using SlRec = SLAPrintObject::SliceRecord; - auto slindex_it = std::lower_bound(po.m_slice_index.begin(), - po.m_slice_index.end(), - float(bb3d.min(Z)), // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); + auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); if(slindex_it == po.m_slice_index.end()) throw std::runtime_error(L("Slicing had to be stopped " @@ -715,7 +708,7 @@ void SLAPrint::process() // In this step we check the slices, identify island and cover them with // support points. Then we sprinkle the rest of the mesh. - auto support_points = [this, ilh](SLAPrintObject& po) { + auto support_points = [this](SLAPrintObject& po) { const ModelObject& mo = *po.m_model_object; po.m_supportdata.reset( new SLAPrintObject::SupportData(po.transformed_mesh()) ); @@ -732,8 +725,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - auto&& bb = po.transformed_mesh().bounding_box(); - std::vector heights = po.get_slice_levels(float(bb.min(Z))); + const std::vector& heights = po.m_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -896,7 +888,7 @@ void SLAPrint::process() // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) - auto index_slices = [this, ilhd](SLAPrintObject& po) { + auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) { // po.m_slice_index.clear(); // auto sih = LevelID(scale_(ilhd)); @@ -978,6 +970,19 @@ void SLAPrint::process() m_printer_input.clear(); for(SLAPrintObject * o : m_objects) { + LevelID gndlvl = o->get_slice_index().front().key(); + for(auto& slicerecord : o->get_slice_index()) { + auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; + auto objslit = slicerecord.get_slices(*o, soModel); + auto supslit = slicerecord.get_slices(*o, soSupport); + + if(objslit != o->get_model_slices().end()) + lyrs.emplace_back(*objslit, o->instances()); + + if(supslit != o->get_support_slices().end()) + lyrs.emplace_back(*supslit, o->instances()); + } + // auto& po = *o; // std::vector& oslices = po.m_model_slices; @@ -1003,8 +1008,6 @@ void SLAPrint::process() // m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; // lyrs.emplace_back(sslices[i], po.m_instances); // } - -// for(size_t i = 0; i < o->m_sli) } // collect all the keys @@ -1306,13 +1309,13 @@ void SLAPrint::fill_statistics() // find highest object // Which is a better bet? To compare by max_z or by number of layers in the index? - double max_z = 0.; + float max_z = 0.; size_t max_layers_cnt = 0; size_t highest_obj_idx = 0; for (SLAPrintObject *&po : m_objects) { const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index(); if (! slice_index.empty()) { - double z = (-- slice_index.end())->first; + float z = (-- slice_index.end())->slice_level(); size_t cnt = slice_index.size(); //if (z > max_z) { if (cnt > max_layers_cnt) { @@ -1332,7 +1335,7 @@ void SLAPrint::fill_statistics() int sliced_layer_cnt = 0; for (const auto& layer : highest_obj_slice_index) { - const double l_height = (layer.first == highest_obj_slice_index.begin()->first) ? init_layer_height : layer_height; + const double l_height = (layer.key() == highest_obj_slice_index.begin()->key()) ? init_layer_height : layer_height; // Calculation of the consumed material @@ -1344,18 +1347,19 @@ void SLAPrint::fill_statistics() const SLAPrintObject::SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); - auto key = layer.first; - const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON)); - if (it_key == index.end() || it_key->first > key + EPSILON) + auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); + if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON)) continue; - record = &it_key->second; + record = &(*it); } - if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances())); + auto modelslice_it = record->get_slices(*po, soModel); + if (modelslice_it != po->get_model_slices().end()) + append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE) - append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances())); + auto supportslice_it = record->get_slices(*po, soSupport); + if (supportslice_it != po->get_support_slices().end()) + append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); } model_polygons = union_(model_polygons); @@ -1562,15 +1566,74 @@ const std::vector& SLAPrintObject::get_support_points() const return m_supportdata->support_points; } +SLAPrintObject::SliceIndex::iterator +SLAPrintObject::search_slice_index(float slice_level) +{ + SliceRecord query(0, slice_level, 0); + auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.slice_level() < r2.slice_level(); + }); + + return it; +} + +SLAPrintObject::SliceIndex::const_iterator +SLAPrintObject::search_slice_index(float slice_level) const +{ + SliceRecord query(0, slice_level, 0); + auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.slice_level() < r2.slice_level(); + }); + + return it; +} + +SLAPrintObject::SliceIndex::iterator +SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) +{ + SliceRecord query(key, 0.f, 0.f); + auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.key() < r2.key(); + }); + + // Return valid iterator only if the keys really match + if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + + return it; +} + +SLAPrintObject::SliceIndex::const_iterator +SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const +{ + SliceRecord query(key, 0.f, 0.f); + auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), + query, + [](const SliceRecord& r1, const SliceRecord& r2) + { + return r1.key() < r2.key(); + }); + + // Return valid iterator only if the keys really match + if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + + return it; +} + SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const { SliceIterator ret = so == soModel ? get_model_slices().end() : get_support_slices().end(); - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - k, - SliceRecord::cmpfn); + auto it = search_slice_index(k); if(it != m_slice_index.end()) { ret = it->get_slices(*this, so); @@ -1603,20 +1666,22 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -std::vector SLAPrintObject::get_slice_levels(float from_eq) const -{ - using SlRec = SLAPrintObject::SliceRecord; - auto it = std::lower_bound(m_slice_index.begin(), - m_slice_index.end(), - from_eq, // model start z - [](const SlRec& sr1, const SlRec& sr2){ - return sr1.slice_level() < sr2.slice_level(); - }); +//std::vector SLAPrintObject::get_slice_levels(float from_eq) const +//{ +// using SlRec = SLAPrintObject::SliceRecord; +// auto it = std::lower_bound(m_slice_index.begin(), +// m_slice_index.end(), +// from_eq, // model start z +// [](const SlRec& sr1, const SlRec& sr2){ +// return sr1.slice_level() < sr2.slice_level(); +// }); - std::vector heights; heights.reserve(m_slice_index.size()); - for(; it != m_slice_index.end(); ++it) - heights.emplace_back(it->slice_level()); -} +// std::vector heights; heights.reserve(m_slice_index.size()); +// for(; it != m_slice_index.end(); ++it) +// heights.emplace_back(it->slice_level()); + + +//} const std::vector &SLAPrintObject::get_model_slices() const { @@ -1742,7 +1807,7 @@ SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, const std::vector& v = so == soModel? po.get_model_slices() : po.get_support_slices(); - Idx idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; + size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; using DiffT = std::vector::const_iterator::difference_type; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 4d5f1d0daa..6204628757 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -46,7 +46,7 @@ template struct Range { from(std::forward(b)), to(std::forward(e)) {} }; -enum SliceOrigin { soSlice, soModel }; +enum SliceOrigin { soSupport, soModel }; using SliceStore = std::vector; using SliceIterator = SliceStore::const_iterator; @@ -118,25 +118,19 @@ private: using Key = LevelID; private: - using Idx = size_t; - static const Idx NONE = Idx(-1); // this will be the max limit of size_t + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer - Idx m_model_slices_idx = NONE; - Idx m_support_slices_idx = NONE; public: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} - inline static bool cmpfn(const SliceRecord& sr1, const SliceRecord& sr2) - { - return sr1.key() < sr2.key(); - } - inline Key key() const { return m_print_z; } inline float slice_level() const { return m_slice_z; } inline float layer_height() const { return m_height; } @@ -144,16 +138,22 @@ private: SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - void set_model_slice_idx(Idx id) { m_model_slices_idx = id; } - void set_support_slice_idx(Idx id) { m_support_slices_idx = id; } + + void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } + void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } + }; + using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. - const std::vector& get_slice_index() const; + const SliceIndex& get_slice_index() const; - std::vector get_slice_levels(float from_eq) const; + SliceIndex::iterator search_slice_index(float slice_level); + SliceIndex::const_iterator search_slice_index(float slice_level) const; + SliceIndex::iterator search_slice_index(SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: @@ -171,6 +171,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + inline const std::vector& get_height_levels() const { + return m_height_levels; + } + protected: // to be called from SLAPrint only. friend class SLAPrint; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1c09096a8d..7bd63aa3c9 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4937,32 +4937,52 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { - const std::vector& model_slices = obj->get_model_slices(); - const std::vector& support_slices = obj->get_support_slices(); + // FIXME: is this all right (by Tamas)? + SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); - const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); - SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; }); - SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; }); + // calculate model bottom cap + if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) + bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); - if (it_min_z != index.end()) - { - // calculate model bottom cap - if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) - bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true); - // calculate support bottom cap - if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) - bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true); - } + // calculate support bottom cap + if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) + bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, min_z, true); - if (it_max_z != index.end()) - { - // calculate model top cap - if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) - top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false); - // calculate support top cap - if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) - top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false); - } + // calculate model top cap + if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) + top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + + // calculate support top cap + if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) + top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + +// const std::vector& model_slices = obj->get_model_slices(); +// const std::vector& support_slices = obj->get_support_slices(); + +// const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); +// SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; }); +// SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; }); + +// if (it_min_z != index.end()) +// { +// // calculate model bottom cap +// if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) +// bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true); +// // calculate support bottom cap +// if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) +// bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true); +// } + +// if (it_max_z != index.end()) +// { +// // calculate model top cap +// if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) +// top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false); +// // calculate support top cap +// if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) +// top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false); +// } } if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty()) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index be3fad9ece..f691850b42 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); - for (const SLAPrintObject::SliceIndex::value_type& id : index) + const std::vector& hlvls = obj->get_height_levels(); + for (float h : hlvls) { - zs.insert(shift_z + id.first); + zs.insert(shift_z + double(h)); } } } From 562343cd2a1b932dcc21ac24d7029c37d2a9c1ce Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 21 Mar 2019 14:33:55 +0100 Subject: [PATCH 06/29] Localization fix of the warning texts in the 3D scene. Improved anti-aliasing of the warning texts in the 3D scene and the G-code legend. A ClearType rendering has been suppressed by rendering of the text into a red channel only. --- src/slic3r/GUI/GLCanvas3D.cpp | 146 ++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 35 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1c09096a8d..b086887847 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -34,6 +34,7 @@ #include #include #include +#include // Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx. #include "libslic3r/Print.hpp" @@ -1659,13 +1660,69 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool _generate(text, canvas, red_colored); // GUI::GLTexture::reset() is called at the beginning of generate(...) } -bool GLCanvas3D::WarningTexture::_generate(const std::string& msg, const GLCanvas3D& canvas, const bool red_colored/* = false*/) + +#ifdef __WXMSW__ +static bool is_font_cleartype(const wxFont &font) +{ + // Native font description: on MSW, it is a version number plus the content of LOGFONT, separated by semicolon. + wxString font_desc = font.GetNativeFontInfoDesc(); + // Find the quality field. + wxString sep(";"); + size_t startpos = 0; + for (size_t i = 0; i < 12; ++ i) + startpos = font_desc.find(sep, startpos + 1); + ++ startpos; + size_t endpos = font_desc.find(sep, startpos); + int quality = wxAtoi(font_desc(startpos, endpos - startpos)); + return quality == CLEARTYPE_QUALITY; +} + +// ClearType produces renders, which are difficult to convert into an alpha blended OpenGL texture. +// Therefore it is better to disable it, though Vojtech found out, that the font returned with ClearType +// disabled is signifcantly thicker than the default ClearType font. +// This function modifies the font provided. +static void msw_disable_cleartype(wxFont &font) +{ + // Native font description: on MSW, it is a version number plus the content of LOGFONT, separated by semicolon. + wxString font_desc = font.GetNativeFontInfoDesc(); + // Find the quality field. + wxString sep(";"); + size_t startpos_weight = 0; + for (size_t i = 0; i < 5; ++ i) + startpos_weight = font_desc.find(sep, startpos_weight + 1); + ++ startpos_weight; + size_t endpos_weight = font_desc.find(sep, startpos_weight); + // Parse the weight field. + unsigned int weight = atoi(font_desc(startpos_weight, endpos_weight - startpos_weight)); + size_t startpos = endpos_weight; + for (size_t i = 0; i < 6; ++ i) + startpos = font_desc.find(sep, startpos + 1); + ++ startpos; + size_t endpos = font_desc.find(sep, startpos); + int quality = wxAtoi(font_desc(startpos, endpos - startpos)); + if (quality == CLEARTYPE_QUALITY) { + // Replace the weight with a smaller value to compensate the weight of non ClearType font. + wxString sweight = std::to_string(weight * 2 / 4); + size_t len_weight = endpos_weight - startpos_weight; + wxString squality = std::to_string(ANTIALIASED_QUALITY); + font_desc.replace(startpos_weight, len_weight, sweight); + font_desc.replace(startpos + sweight.size() - len_weight, endpos - startpos, squality); + font.SetNativeFontInfo(font_desc); + wxString font_desc2 = font.GetNativeFontInfoDesc(); + } + wxString font_desc2 = font.GetNativeFontInfoDesc(); +} +#endif /* __WXMSW__ */ + +bool GLCanvas3D::WarningTexture::_generate(const std::string& msg_utf8, const GLCanvas3D& canvas, const bool red_colored/* = false*/) { reset(); - if (msg.empty()) + if (msg_utf8.empty()) return false; + wxString msg = GUI::from_u8(msg_utf8); + wxMemoryDC memDC; // select default font const float scale = canvas.get_canvas_size().get_scale_factor(); @@ -1676,46 +1733,47 @@ bool GLCanvas3D::WarningTexture::_generate(const std::string& msg, const GLCanva // calculates texture size wxCoord w, h; -// memDC.GetTextExtent(msg, &w, &h); memDC.GetMultiLineTextExtent(msg, &w, &h); - int pow_of_two_size = next_highest_power_of_2(std::max(w, h)); - m_original_width = (int)w; m_original_height = (int)h; - m_width = pow_of_two_size; - m_height = pow_of_two_size; + m_width = (int)next_highest_power_of_2((uint32_t)w); + m_height = (int)next_highest_power_of_2((uint32_t)h); // generates bitmap wxBitmap bitmap(m_width, m_height); memDC.SelectObject(bitmap); - memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2]))); + memDC.SetBackground(wxBrush(*wxBLACK)); memDC.Clear(); // draw message - memDC.SetTextForeground(red_colored ? wxColour(255,72,65/*204,204*/) : *wxWHITE); -// memDC.DrawText(msg, 0, 0); - memDC.DrawLabel(msg, wxRect(0,0, m_original_width, m_original_height), wxALIGN_CENTER); + memDC.SetTextForeground(*wxRED); + memDC.DrawLabel(msg, wxRect(0,0, m_original_width, m_original_height), wxALIGN_CENTER); memDC.SelectObject(wxNullBitmap); // Convert the bitmap into a linear data ready to be loaded into the GPU. wxImage image = bitmap.ConvertToImage(); - image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]); // prepare buffer std::vector data(4 * m_width * m_height, 0); + const unsigned char *src = image.GetData(); for (int h = 0; h < m_height; ++h) { - int hh = h * m_width; - unsigned char* px_ptr = data.data() + 4 * hh; + unsigned char* dst = data.data() + 4 * h * m_width; for (int w = 0; w < m_width; ++w) { - *px_ptr++ = image.GetRed(w, h); - *px_ptr++ = image.GetGreen(w, h); - *px_ptr++ = image.GetBlue(w, h); - *px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity; + *dst++ = 255; + if (red_colored) { + *dst++ = 72; // 204 + *dst++ = 65; // 204 + } else { + *dst++ = 255; + *dst++ = 255; + } + *dst++ = (unsigned char)std::min(255, *src); + src += 3; } } @@ -1839,7 +1897,15 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c const int scaled_border = Px_Border * scale; // select default font - const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl); + wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl); +#ifdef __WXMSW__ + // Disabling ClearType works, but the font returned is very different (much thicker) from the default. +// msw_disable_cleartype(font); + bool cleartype = is_font_cleartype(font); +#else + bool cleartype = false; +#endif /* __WXMSW__ */ + memDC.SetFont(font); mask_memDC.SetFont(font); @@ -1863,10 +1929,8 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c if (items_count > 1) m_original_height += (items_count - 1) * scaled_square_contour; - int pow_of_two_size = (int)next_highest_power_of_2(std::max(m_original_width, m_original_height)); - - m_width = pow_of_two_size; - m_height = pow_of_two_size; + m_width = (int)next_highest_power_of_2((uint32_t)m_original_width); + m_height = (int)next_highest_power_of_2((uint32_t)m_original_height); // generates bitmap wxBitmap bitmap(m_width, m_height); @@ -1883,16 +1947,13 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c // draw title memDC.SetTextForeground(*wxWHITE); - mask_memDC.SetTextForeground(*wxWHITE); + mask_memDC.SetTextForeground(*wxRED); int title_x = scaled_border; int title_y = scaled_border; memDC.DrawText(title, title_x, title_y); mask_memDC.DrawText(title, title_x, title_y); - mask_memDC.SetPen(wxPen(*wxWHITE)); - mask_memDC.SetBrush(wxBrush(*wxWHITE)); - // draw icons contours as background int squares_contour_x = scaled_border; int squares_contour_y = scaled_border + title_height + scaled_title_offset; @@ -1907,7 +1968,6 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c memDC.SetPen(pen); memDC.SetBrush(brush); memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height)); - mask_memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height)); // draw items (colored icon + text) int icon_x = squares_contour_x + scaled_square_contour; @@ -1943,7 +2003,6 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square)); // draw text - memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset); mask_memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset); // update y @@ -1959,17 +2018,34 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c // prepare buffer std::vector data(4 * m_width * m_height, 0); - for (int h = 0; h < m_height; ++h) + const unsigned char *src_image = image.GetData(); + const unsigned char *src_mask = mask_image.GetData(); + for (int h = 0; h < m_height; ++h) { int hh = h * m_width; unsigned char* px_ptr = data.data() + 4 * hh; for (int w = 0; w < m_width; ++w) { - unsigned char alpha = (mask_image.GetRed(w, h) + mask_image.GetGreen(w, h) + mask_image.GetBlue(w, h)) / 3; - *px_ptr++ = image.GetRed(w, h); - *px_ptr++ = image.GetGreen(w, h); - *px_ptr++ = image.GetBlue(w, h); - *px_ptr++ = (alpha == 0) ? 128 : 255; + if (w >= squares_contour_x && w < squares_contour_x + squares_contour_width && + h >= squares_contour_y && h < squares_contour_y + squares_contour_height) { + // Color palette, use the color verbatim. + *px_ptr++ = *src_image++; + *px_ptr++ = *src_image++; + *px_ptr++ = *src_image++; + *px_ptr++ = 255; + } else { + // Text or background + unsigned char alpha = *src_mask; + // Compensate the white color for the 50% opacity reduction at the character edges. + //unsigned char color = (unsigned char)floor(alpha * 255.f / (128.f + 0.5f * alpha)); + unsigned char color = alpha; + *px_ptr++ = color; + *px_ptr++ = color; // *src_mask ++; + *px_ptr++ = color; // *src_mask ++; + *px_ptr++ = 128 + (alpha / 2); // (alpha > 0) ? 255 : 128; + src_image += 3; + } + src_mask += 3; } } From 4be6c17fd358d19e8fce0766a85b081f9315afe5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 21 Mar 2019 14:56:20 +0100 Subject: [PATCH 07/29] Limit number of perimeters to 10 thousands, that is 50 meters with 0.2mm nozzle. The number of perimeters has to be limited due to a numerical overflow of fixed point 32bit coordinates in the offsetting algorithm. --- src/libslic3r/PrintConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8c67cc067e..630dbfb5fd 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1375,6 +1375,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("(minimum)"); def->aliases = { "perimeter_offsets" }; def->min = 0; + def->max = 10000; def->default_value = new ConfigOptionInt(3); def = this->add("post_process", coStrings); From 24a5dd4235764cd767e0bdfd7f69ee45f85deba2 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 15:16:33 +0100 Subject: [PATCH 08/29] FIx for broken slice preview --- src/libslic3r/SLAPrint.cpp | 46 ++++++++++++++-------------------- src/libslic3r/SLAPrint.hpp | 12 ++++----- src/slic3r/GUI/GLCanvas3D.cpp | 22 ++++++++-------- src/slic3r/GUI/GUI_Preview.cpp | 6 ++--- 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 938f148a30..e12dc7f233 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -30,7 +30,6 @@ public: std::vector support_points; // all the support points (manual/auto) SupportTreePtr support_tree_ptr; // the supports SlicedSupports support_slices; // sliced supports - std::vector level_ids; inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {} }; @@ -603,25 +602,9 @@ std::string SLAPrint::validate() const return ""; } -std::vector SLAPrint::calculate_heights(const BoundingBoxf3& bb3d, - float elevation, - float initial_layer_height, - float layer_height) const -{ - std::vector heights; - float minZ = float(bb3d.min(Z)) - float(elevation); - float maxZ = float(bb3d.max(Z)); - auto flh = float(layer_height); - auto gnd = float(bb3d.min(Z)); - - for(float h = minZ + initial_layer_height; h < maxZ; h += flh) - if(h >= gnd) heights.emplace_back(h); - - return heights; -} - template -void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) { +void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) +{ BOOST_LOG_TRIVIAL(info) << st << "% " << msg; p.set_status(st, msg, std::forward(args)...); } @@ -684,15 +667,17 @@ void SLAPrint::process() throw std::runtime_error(L("Slicing had to be stopped " "due to an internal error.")); - po.m_height_levels.clear(); - po.m_height_levels.reserve(po.m_slice_index.size()); + po.m_model_height_levels.clear(); + po.m_model_height_levels.reserve(po.m_slice_index.size()); for(auto it = slindex_it; it != po.m_slice_index.end(); ++it) - po.m_height_levels.emplace_back(it->slice_level()); + { + po.m_model_height_levels.emplace_back(it->slice_level()); + } TriangleMeshSlicer slicer(&mesh); po.m_model_slices.clear(); - slicer.slice(po.m_height_levels, + slicer.slice(po.m_model_height_levels, float(po.config().slice_closing_radius.value), &po.m_model_slices, [this](){ throw_if_canceled(); }); @@ -725,7 +710,7 @@ void SLAPrint::process() if (mo.sla_points_status != sla::PointsStatus::UserModified) { // calculate heights of slices (slices are calculated already) - const std::vector& heights = po.m_height_levels; + const std::vector& heights = po.m_model_height_levels; this->throw_if_canceled(); SLAAutoSupports::Config config; @@ -1646,10 +1631,17 @@ SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const { - auto from = LevelID(double(from_level) / SCALING_FACTOR); - auto to = LevelID(double(to_level) / SCALING_FACTOR); + auto it_from = search_slice_index(from_level); + auto it_to = search_slice_index(to_level); - return SliceRange(get_slices(so, from), get_slices(so, to)); + SliceRange ret; + + auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); + + ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); + ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); + + return ret; } const std::vector &SLAPrintObject::get_support_slices() const diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 6204628757..e86080963a 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -171,8 +171,9 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; - inline const std::vector& get_height_levels() const { - return m_height_levels; + inline size_t get_slice_count() const { return m_slice_index.size(); } + inline float get_slice_level(size_t idx) const { + return m_slice_index[idx].slice_level(); } protected: @@ -204,8 +205,10 @@ protected: private: // Object specific configuration, pulled from the configuration layer. SLAPrintObjectConfig m_config; + // Translation in Z + Rotation by Y and Z + Scaling / Mirroring. Transform3d m_trafo = Transform3d::Identity(); + std::vector m_instances; // Individual 2d slice polygons from lower z to higher z levels @@ -215,10 +218,7 @@ private: // the index to the model and the support slice vectors. std::vector m_slice_index; - // The height levels corrected and scaled up in integer values. This will - // be used at rasterization. - std::vector m_level_ids; - std::vector m_height_levels; + std::vector m_model_height_levels; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject m_transformed_rmesh; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7bd63aa3c9..90656c93b7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4938,24 +4938,26 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { // FIXME: is this all right (by Tamas)? - SliceRange model_slices = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange support_slices = obj->get_slices(soSupport, float(min_z), float(max_z)); + SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); + SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); + auto obj_end = obj->get_model_slices().end(); + auto sup_end = obj->get_support_slices().end(); // calculate model bottom cap - if(bottom_obj_triangles.empty() && model_slices.from != obj->get_model_slices().end()) - bottom_obj_triangles = triangulate_expolygons_3d(*model_slices.from, min_z, true); + if(bottom_obj_triangles.empty() && obj_range.from != obj_end) + bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && support_slices.from != obj->get_support_slices().end()) - bottom_sup_triangles = triangulate_expolygons_3d(*support_slices.from, min_z, true); + if(bottom_sup_triangles.empty() && sup_range.from != sup_end) + bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && model_slices.to != obj->get_model_slices().end()) - top_obj_triangles = triangulate_expolygons_3d(*model_slices.to, max_z, true); + if(top_obj_triangles.empty() && obj_range.to != obj_end) + top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && support_slices.to != obj->get_support_slices().end()) - top_sup_triangles = triangulate_expolygons_3d(*support_slices.to, max_z, true); + if(top_sup_triangles.empty() && sup_range.to != sup_end) + top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index f691850b42..4776733420 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -776,10 +776,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - const std::vector& hlvls = obj->get_height_levels(); - for (float h : hlvls) + size_t cnt = obj->get_slice_count(); + for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(h)); + zs.insert(shift_z + double(obj->get_slice_level(i))); } } } From 63a899b239a6ee8717102871aaea0122aab1ed34 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 16:14:26 +0100 Subject: [PATCH 09/29] Using same slicing grid for the supports and the model. --- src/libslic3r/SLA/SLASupportTree.cpp | 12 ++++++++ src/libslic3r/SLA/SLASupportTree.hpp | 2 ++ src/libslic3r/SLAPrint.cpp | 45 +++++++--------------------- src/libslic3r/SLAPrint.hpp | 35 ++++++++++++++++++---- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index df9990822d..34dd80cee0 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -2240,6 +2240,18 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const return ret; } +SlicedSupports SLASupportTree::slice(const std::vector &heights, + float cr) const +{ + TriangleMesh fullmesh = m_impl->merged_mesh(); + fullmesh.merge(get_pad()); + TriangleMeshSlicer slicer(&fullmesh); + SlicedSupports ret; + slicer.slice(heights, cr, &ret, get().ctl().cancelfn); + + return ret; +} + const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate, const PoolConfig& pcfg) const { diff --git a/src/libslic3r/SLA/SLASupportTree.hpp b/src/libslic3r/SLA/SLASupportTree.hpp index 74d7da9cad..66677e4d7a 100644 --- a/src/libslic3r/SLA/SLASupportTree.hpp +++ b/src/libslic3r/SLA/SLASupportTree.hpp @@ -181,6 +181,8 @@ public: /// Get the sliced 2d layers of the support geometry. SlicedSupports slice(float layerh, float init_layerh = -1.0) const; + SlicedSupports slice(const std::vector&, float closing_radius) const; + /// Adding the "pad" (base pool) under the supports const TriangleMesh& add_pad(const SliceLayer& baseplate, const PoolConfig& pcfg) const; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index e12dc7f233..bbf53ef7e8 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -856,11 +856,19 @@ void SLAPrint::process() // Slicing the support geometries similarly to the model slicing procedure. // If the pad had been added previously (see step "base_pool" than it will // be part of the slices) - auto slice_supports = [ilh](SLAPrintObject& po) { + auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; if(sd && sd->support_tree_ptr) { - auto lh = float(po.m_config.layer_height.getFloat()); - sd->support_slices = sd->support_tree_ptr->slice(lh, ilh); + sd->support_slices.clear(); + + std::vector heights; heights.reserve(po.m_slice_index.size()); + + for(auto& rec : po.m_slice_index) { + heights.emplace_back(rec.slice_level()); + } + + sd->support_slices = sd->support_tree_ptr->slice( + heights, float(po.config().slice_closing_radius.value)); } for(size_t i = 0; @@ -1613,20 +1621,6 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const return it; } -SliceIterator SLAPrintObject::get_slices(SliceOrigin so, LevelID k) const -{ - SliceIterator ret = so == soModel ? get_model_slices().end() : - get_support_slices().end(); - - auto it = search_slice_index(k); - - if(it != m_slice_index.end()) { - ret = it->get_slices(*this, so); - } - - return ret; -} - SliceRange SLAPrintObject::get_slices(SliceOrigin so, float from_level, float to_level) const @@ -1658,23 +1652,6 @@ SLAPrintObject::get_slice_index() const return m_slice_index; } -//std::vector SLAPrintObject::get_slice_levels(float from_eq) const -//{ -// using SlRec = SLAPrintObject::SliceRecord; -// auto it = std::lower_bound(m_slice_index.begin(), -// m_slice_index.end(), -// from_eq, // model start z -// [](const SlRec& sr1, const SlRec& sr2){ -// return sr1.slice_level() < sr2.slice_level(); -// }); - -// std::vector heights; heights.reserve(m_slice_index.size()); -// for(; it != m_slice_index.end(); ++it) -// heights.emplace_back(it->slice_level()); - - -//} - const std::vector &SLAPrintObject::get_model_slices() const { // assert(is_step_done(slaposObjectSlice)); diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e86080963a..3e0a0c5e3a 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -122,7 +122,7 @@ private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; - LevelID m_print_z = 0; // Top of the layer + LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer @@ -131,34 +131,54 @@ private: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} + // The key will be the integer height level of the top of the layer. inline Key key() const { return m_print_z; } + + // Returns the exact floating point Z coordinate of the slice inline float slice_level() const { return m_slice_z; } + + // Returns the current layer height inline float layer_height() const { return m_height; } - SliceIterator get_slices(const SLAPrintObject& po, - SliceOrigin so) const; - + // Returns the slices for eighter the model or the supports. The return + // value is an iterator to po.get_model_slices() or po.get_support_slices + // depending on the SliceOrigin parameter. + SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; + // Methods for setting the indixes into the slice vectors. void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } - }; + // Slice index will be a plain vector sorted by the integer height levels using SliceIndex = std::vector; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. const SliceIndex& get_slice_index() const; + // Search slice index for the closest slice to the given level SliceIndex::iterator search_slice_index(float slice_level); SliceIndex::const_iterator search_slice_index(float slice_level) const; + + // Search the slice index for a particular level in integer coordinates. + // If no such layer is present, it will return m_slice_index.end() SliceIndex::iterator search_slice_index(SliceRecord::Key key); SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; public: - SliceIterator get_slices(SliceOrigin so, LevelID k) const; + // ///////////////////////////////////////////////////////////////////////// + // The following methods can be used after the model and the support slicing + // steps have been succesfully finished. + // ///////////////////////////////////////////////////////////////////////// + // Getting slices for either the model or the supports for a particular + // height ID. +// SliceIterator get_slices(SliceOrigin so, LevelID k) const; + + // Getting slices (model or supports) for a Z coordinate range. The returned + // iterators should include the slices for the given boundaries as well. SliceRange get_slices( SliceOrigin so, float from_level, @@ -171,7 +191,10 @@ public: const std::vector& get_model_slices() const; const std::vector& get_support_slices() const; + // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } + + // One can query the Z coordinate of the slice for a given inline float get_slice_level(size_t idx) const { return m_slice_index[idx].slice_level(); } From 5e646562cd2194cb03c80f68b871a6b3f9636d52 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 21 Mar 2019 18:01:41 +0100 Subject: [PATCH 10/29] Fixes for the duplicated layer issues... --- src/libslic3r/SLAPrint.cpp | 51 ++++++++++++++++++++-------------- src/libslic3r/SLAPrint.hpp | 51 ++++++++++++++++++---------------- src/slic3r/GUI/GUI_Preview.cpp | 2 +- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index bbf53ef7e8..58386c0bdb 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -615,12 +615,19 @@ void SLAPrint::process() using namespace sla; using ExPolygon = Slic3r::ExPolygon; + if(m_objects.empty()) return; + // Assumption: at this point the print objects should be populated only with // the model objects we have to process and the instances are also filtered // shortcut to initial layer height double ilhd = m_material_config.initial_layer_height.getFloat(); auto ilh = float(ilhd); + double lhd = m_objects.front()->m_config.layer_height.getFloat(); + float lh = float(lhd); + + LevelID ilhs = ilhd / SCALING_FACTOR; + LevelID lhs = lhd / SCALING_FACTOR; const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -641,24 +648,26 @@ void SLAPrint::process() // Slicing the model object. This method is oversimplified and needs to // be compared with the fff slicing algorithm for verification - auto slice_model = [this, ilh](SLAPrintObject& po) { + auto slice_model = [this, ilhs, lhs, ilh, lh](SLAPrintObject& po) { TriangleMesh mesh = po.transformed_mesh(); // We need to prepare the slice index... auto&& bb3d = mesh.bounding_box(); - float minZ = float(bb3d.min(Z)) - float(po.get_elevation()); - float maxZ = float(bb3d.max(Z)); - auto flh = float(po.m_config.layer_height.getFloat()); + double minZ = bb3d.min(Z) - po.get_elevation(); + double maxZ = bb3d.max(Z); + + LevelID minZs = minZ / SCALING_FACTOR; + LevelID maxZs = maxZ / SCALING_FACTOR; auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; po.m_slice_index.clear(); - po.m_slice_index.reserve(size_t(maxZ - (minZ + ilh) / flh) + 1); - po.m_slice_index.emplace_back(slh(minZ + ilh), minZ + ilh / 2.f, ilh); + po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1); + po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilh / 2.f, ilh); - for(float h = minZ + ilh + flh; h <= maxZ; h += flh) { - po.m_slice_index.emplace_back(slh(h), h - flh / 2.f, flh); + for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) { + po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lh / 2.f, lh); } auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); @@ -1337,7 +1346,7 @@ void SLAPrint::fill_statistics() for (SLAPrintObject * po : m_objects) { - const SLAPrintObject::SliceRecord *record = nullptr; + const SLAPrintObject::_SliceRecord *record = nullptr; { const SLAPrintObject::SliceIndex& index = po->get_slice_index(); auto it = po->search_slice_index(layer.slice_level() - float(EPSILON)); @@ -1562,10 +1571,10 @@ const std::vector& SLAPrintObject::get_support_points() const SLAPrintObject::SliceIndex::iterator SLAPrintObject::search_slice_index(float slice_level) { - SliceRecord query(0, slice_level, 0); + _SliceRecord query(0, slice_level, 0); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1576,10 +1585,10 @@ SLAPrintObject::search_slice_index(float slice_level) SLAPrintObject::SliceIndex::const_iterator SLAPrintObject::search_slice_index(float slice_level) const { - SliceRecord query(0, slice_level, 0); + _SliceRecord query(0, slice_level, 0); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.slice_level() < r2.slice_level(); }); @@ -1588,12 +1597,12 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) { - SliceRecord query(key, 0.f, 0.f); + _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1605,12 +1614,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) } SLAPrintObject::SliceIndex::const_iterator -SLAPrintObject::search_slice_index(SLAPrintObject::SliceRecord::Key key) const +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const { - SliceRecord query(key, 0.f, 0.f); + _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), query, - [](const SliceRecord& r1, const SliceRecord& r2) + [](const _SliceRecord& r1, const _SliceRecord& r2) { return r1.key() < r2.key(); }); @@ -1645,7 +1654,7 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const std::vector& +const std::vector& SLAPrintObject::get_slice_index() const { // assert(is_step_done(slaposIndexSlices)); @@ -1769,7 +1778,7 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::SliceRecord::get_slices(const SLAPrintObject &po, +SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, SliceOrigin so) const { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 3e0a0c5e3a..b33bfdeb08 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -107,30 +107,21 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& get_support_points() const; -private: - - // An index record referencing the slices - // (get_model_slices(), get_support_slices()) where the keys are the height - // levels of the model in scaled-clipper coordinates. The levels correspond - // to the z coordinate of the object coordinate system. class SliceRecord { public: using Key = LevelID; private: - static const size_t NONE = size_t(-1); // this will be the max limit of size_t - size_t m_model_slices_idx = NONE; - size_t m_support_slices_idx = NONE; - LevelID m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer - public: - + protected: SliceRecord(Key key, float slicez, float height): m_print_z(key), m_slice_z(slicez), m_height(height) {} + public: + // The key will be the integer height level of the top of the layer. inline Key key() const { return m_print_z; } @@ -139,8 +130,25 @@ private: // Returns the current layer height inline float layer_height() const { return m_height; } + }; - // Returns the slices for eighter the model or the supports. The return +private: + + // An index record referencing the slices + // (get_model_slices(), get_support_slices()) where the keys are the height + // levels of the model in scaled-clipper coordinates. The levels correspond + // to the z coordinate of the object coordinate system. + class _SliceRecord: public SliceRecord { + private: + static const size_t NONE = size_t(-1); // this will be the max limit of size_t + size_t m_model_slices_idx = NONE; + size_t m_support_slices_idx = NONE; + + public: + _SliceRecord(Key key, float slicez, float height): + SliceRecord(key, slicez, height) {} + + // Returns the slices for either the model or the supports. The return // value is an iterator to po.get_model_slices() or po.get_support_slices // depending on the SliceOrigin parameter. SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; @@ -151,7 +159,7 @@ private: }; // Slice index will be a plain vector sorted by the integer height levels - using SliceIndex = std::vector; + using SliceIndex = std::vector<_SliceRecord>; // Retrieve the slice index which is readable only after slaposIndexSlices // is done. @@ -163,8 +171,8 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(SliceRecord::Key key) const; + SliceIndex::iterator search_slice_index(_SliceRecord::Key key); + SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; public: @@ -173,10 +181,6 @@ public: // steps have been succesfully finished. // ///////////////////////////////////////////////////////////////////////// - // Getting slices for either the model or the supports for a particular - // height ID. -// SliceIterator get_slices(SliceOrigin so, LevelID k) const; - // Getting slices (model or supports) for a Z coordinate range. The returned // iterators should include the slices for the given boundaries as well. SliceRange get_slices( @@ -194,9 +198,8 @@ public: // Returns the total number of slices in the slice grid (model and supports) inline size_t get_slice_count() const { return m_slice_index.size(); } - // One can query the Z coordinate of the slice for a given - inline float get_slice_level(size_t idx) const { - return m_slice_index[idx].slice_level(); + inline const SliceRecord& get_slice_record(size_t idx) const { + return m_slice_index[idx]; } protected: @@ -239,7 +242,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 148b830811..10a4a12c7e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -778,7 +778,7 @@ void Preview::load_print_as_sla() size_t cnt = obj->get_slice_count(); for (size_t i = 0; i < cnt; i++) { - zs.insert(shift_z + double(obj->get_slice_level(i))); + zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); } } } From a5fd9a34e88b22cdde9883516637d1786f86efba Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 09:47:40 +0100 Subject: [PATCH 11/29] Do not consider modifiers when centering an object after 3mf and amf import --- src/libslic3r/Model.cpp | 6 +++++- src/libslic3r/Model.hpp | 4 ++++ src/slic3r/GUI/Plater.cpp | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 68f71c3088..f9db9fea0b 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -997,12 +997,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) return hull; } +#if ENABLE_VOLUMES_CENTERING_FIXES +void ModelObject::center_around_origin(bool include_modifiers) +#else void ModelObject::center_around_origin() +#endif // ENABLE_VOLUMES_CENTERING_FIXES { // calculate the displacements needed to // center this object around the origin #if ENABLE_VOLUMES_CENTERING_FIXES - BoundingBoxf3 bb = full_raw_mesh_bounding_box(); + BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box(); #else BoundingBoxf3 bb; for (ModelVolume *v : this->volumes) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 1260500eec..8a48f8ee96 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -236,7 +236,11 @@ public: // This method is used by the auto arrange function. Polygon convex_hull_2d(const Transform3d &trafo_instance); +#if ENABLE_VOLUMES_CENTERING_FIXES + void center_around_origin(bool include_modifiers = true); +#else void center_around_origin(); +#endif // ENABLE_VOLUMES_CENTERING_FIXES void ensure_on_bed(); void translate_instances(const Vec3d& vector); void translate_instance(size_t instance_idx, const Vec3d& vector); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2acc2cec44..906a5009ae 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1617,7 +1617,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (type_3mf || type_any_amf) { #endif // !ENABLE_VOLUMES_CENTERING_FIXES for (ModelObject* model_object : model.objects) { +#if ENABLE_VOLUMES_CENTERING_FIXES + model_object->center_around_origin(false); +#else model_object->center_around_origin(); +#endif // ENABLE_VOLUMES_CENTERING_FIXES model_object->ensure_on_bed(); } #if !ENABLE_VOLUMES_CENTERING_FIXES From 0848617fd37e16f9404a208192d0dc8f9e18925a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 22 Mar 2019 10:56:51 +0100 Subject: [PATCH 12/29] SLA gizmo fix: adding points to selection by Shift+click should now work again (was broken by 8466c55) --- src/slic3r/GUI/GLCanvas3D.cpp | 8 ++++---- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b086887847..1bcc53efd7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3521,6 +3521,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) _update_gizmos_data(); m_dirty = true; } + else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown())) + { + // the gizmo got the event and took some action, there is no need to do anything more + } else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) { _update_gizmos_data(); @@ -3536,10 +3540,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } - else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown())) - { - // the gizmo got the event and took some action, there is no need to do anything more - } else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::RightDown)) { // event was taken care of by the SlaSupports gizmo diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 619ae3b3fd..c629f21729 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -328,6 +328,10 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous // left down without selection rectangle - place point on the mesh: if (action == SLAGizmoEventType::LeftDown && !m_selection_rectangle_active && !shift_down) { + // If any point is in hover state, this should initiate its move - return control back to GLCanvas: + if (m_hover_id != -1) + return false; + // If there is some selection, don't add new point and deselect everything instead. if (m_selection_empty) { try { From bbb2a6d714d0c89f00847b47b1569b0849dd4f60 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 11:51:10 +0100 Subject: [PATCH 13/29] Fixed non-uniform scale of single volumes selection when made using the sidebar matrix fields --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index f759250b35..6c8fdcab73 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -209,8 +209,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = volume->get_volume_offset(); m_new_rotation = volume->get_volume_rotation(); m_new_scale = volume->get_volume_scaling_factor(); - m_new_size = volume->get_instance_transformation().get_matrix(true, true) * volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size(); - m_new_enabled = true; + m_new_size = volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size(); + m_new_enabled = true; } else if (wxGetApp().obj_list()->multiple_selection()) { From f5516f24c444d26c0c791f4c239eb35ba60f9f37 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 12:11:23 +0100 Subject: [PATCH 14/29] Fix of 1.42 beta crash when deleting printer profile created by configuration assistant #1985 Fixed an issue, where deleting a profile did not correctly update profile dependences, and deleting a profile would not test dirty status of depending profiles, which would be switched thus user changes would be lost. Fixed enabling / disabling the --default FFF-- / --default SLA-- profiles when deleting the last printer profile. Little refactoring (don't compare by strings but by symbolic names). Making a copy of a profile - "Copy" suffix is added to a system profile. --- src/slic3r/GUI/Preset.cpp | 21 ++++++--- src/slic3r/GUI/Preset.hpp | 5 ++- src/slic3r/GUI/Tab.cpp | 94 ++++++++++++++++++++++++--------------- src/slic3r/GUI/Tab.hpp | 3 +- 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 656658b0bf..e63ae32f7f 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -740,6 +740,8 @@ void PresetCollection::save_current_preset(const std::string &new_name) return; // Overwriting an existing preset. preset.config = std::move(m_edited_preset.config); + // The newly saved preset will be activated -> make it visible. + preset.is_visible = true; } else { // Creating a new preset. Preset &preset = *m_presets.insert(it, m_edited_preset); @@ -761,18 +763,20 @@ void PresetCollection::save_current_preset(const std::string &new_name) preset.is_default = false; preset.is_system = false; preset.is_external = false; - } + // The newly saved preset will be activated -> make it visible. + preset.is_visible = true; + } // 2) Activate the saved preset. this->select_preset_by_name(new_name, true); // 2) Store the active preset to disk. this->get_selected_preset().save(); } -void PresetCollection::delete_current_preset() +bool PresetCollection::delete_current_preset() { const Preset &selected = this->get_selected_preset(); - if (selected.is_default) - return; + if (selected.is_default) + return false; if (! selected.is_external && ! selected.is_system) { // Erase the preset file. boost::nowide::remove(selected.file.c_str()); @@ -786,6 +790,7 @@ void PresetCollection::delete_current_preset() if (new_selected_idx == m_presets.size()) for (--new_selected_idx; new_selected_idx > 0 && !m_presets[new_selected_idx].is_visible; --new_selected_idx); this->select_preset(new_selected_idx); + return true; } bool PresetCollection::load_bitmap_default(const std::string &file_name) @@ -843,7 +848,9 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) { if (m_default_suppressed != default_suppressed) { m_default_suppressed = default_suppressed; - m_presets.front().is_visible = ! default_suppressed || (m_presets.size() > m_num_default_presets && m_idx_selected > 0); + bool default_visible = ! default_suppressed || m_idx_selected < m_num_default_presets; + for (size_t i = 0; i < m_num_default_presets; ++ i) + m_presets[i].is_visible = default_visible; } } @@ -1114,7 +1121,9 @@ Preset& PresetCollection::select_preset(size_t idx) idx = first_visible_idx(); m_idx_selected = idx; m_edited_preset = m_presets[idx]; - m_presets.front().is_visible = ! m_default_suppressed || m_idx_selected == 0; + bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets; + for (size_t i = 0; i < m_num_default_presets; ++i) + m_presets[i].is_visible = default_visible; return m_presets[idx]; } diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index 5113137157..c84c37029e 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -115,6 +115,8 @@ public: // Is this preset compatible with the currently active printer? bool is_compatible = true; + bool is_user() const { return ! this->is_default && ! this->is_system; } + // Name of the preset, usually derived form the file name. std::string name; // File name of the preset. This could be a Print / Filament / Printer preset, @@ -269,7 +271,8 @@ public: void save_current_preset(const std::string &new_name); // Delete the current preset, activate the first visible preset. - void delete_current_preset(); + // returns true if the preset was deleted successfully. + bool delete_current_preset(); // Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame. bool load_bitmap_default(const std::string &file_name); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 46a6de6abe..d38e96ca28 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -385,7 +385,7 @@ void Tab::update_changed_ui() if (m_postpone_update_ui) return; - const bool deep_compare = (m_name == "printer" || m_name == "sla_material"); + const bool deep_compare = (m_type == Slic3r::Preset::TYPE_PRINTER || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL); auto dirty_options = m_presets->current_dirty_options(deep_compare); auto nonsys_options = m_presets->current_different_from_parent_options(deep_compare); if (m_type == Slic3r::Preset::TYPE_PRINTER) { @@ -2395,7 +2395,7 @@ void Tab::load_current_preset() (preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); update(); - if (m_name == "printer") { + if (m_type == Slic3r::Preset::TYPE_PRINTER) { // For the printer profile, generate the extruder pages. if (preset.printer_technology() == ptFFF) on_preset_loaded(); @@ -2425,7 +2425,7 @@ void Tab::load_current_preset() update_tab_ui(); // update show/hide tabs - if (m_name == "printer") { + if (m_type == Slic3r::Preset::TYPE_PRINTER) { const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); if (printer_technology != static_cast(this)->m_printer_technology) { @@ -2458,7 +2458,7 @@ void Tab::load_current_preset() } else { on_presets_changed(); - if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT)// if (m_name == "print") + if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT) update_frequently_changed_parameters(); } @@ -2526,20 +2526,35 @@ void Tab::update_page_tree_visibility() } -// Called by the UI combo box when the user switches profiles. +// Called by the UI combo box when the user switches profiles, and also to delete the current profile. // Select a preset by a name.If !defined(name), then the default preset is selected. // If the current profile is modified, user is asked to save the changes. -void Tab::select_preset(std::string preset_name) +void Tab::select_preset(std::string preset_name, bool delete_current) { - // If no name is provided, select the "-- default --" preset. - if (preset_name.empty()) - preset_name = m_presets->default_preset().name; - bool current_dirty = m_presets->current_is_dirty(); + if (preset_name.empty()) { + if (delete_current) { + // Find an alternate preset to be selected after the current preset is deleted. + const std::deque &presets = this->m_presets->get_presets(); + size_t idx_current = this->m_presets->get_idx_selected(); + // Find the next visible preset. + size_t idx_new = idx_current + 1; + if (idx_new < presets.size()) + for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ; + if (idx_new == presets.size()) + for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new); + preset_name = presets[idx_new].name; + } else { + // If no name is provided, select the "-- default --" preset. + preset_name = m_presets->default_preset().name; + } + } + assert(! delete_current || (m_presets->get_edited_preset().name != preset_name && m_presets->get_edited_preset().is_user())); + bool current_dirty = ! delete_current && m_presets->current_is_dirty(); bool print_tab = m_presets->type() == Preset::TYPE_PRINT || m_presets->type() == Preset::TYPE_SLA_PRINT; bool printer_tab = m_presets->type() == Preset::TYPE_PRINTER; bool canceled = false; m_dependent_tabs = {}; - if (current_dirty && !may_discard_current_dirty_preset()) { + if (current_dirty && ! may_discard_current_dirty_preset()) { canceled = true; } else if (print_tab) { // Before switching the print profile to a new one, verify, whether the currently active filament or SLA material @@ -2602,6 +2617,19 @@ void Tab::select_preset(std::string preset_name) } } } + + if (! canceled && delete_current) { + // Delete the file and select some other reasonable preset. + // It does not matter which preset will be made active as the preset will be re-selected from the preset_name variable. + // The 'external' presets will only be removed from the preset list, their files will not be deleted. + try { + m_presets->delete_current_preset(); + } catch (const std::exception & /* e */) { + //FIXME add some error reporting! + canceled = true; + } + } + if (canceled) { update_tab_ui(); // Trigger the on_presets_changed event so that we also restore the previous value in the plater selector, @@ -2610,17 +2638,19 @@ void Tab::select_preset(std::string preset_name) } else { if (current_dirty) m_presets->discard_current_changes(); - const bool is_selected = m_presets->select_preset_by_name(preset_name, false); + + const bool is_selected = m_presets->select_preset_by_name(preset_name, false) || delete_current; + assert(m_presets->get_edited_preset().name == preset_name || ! is_selected); // Mark the print & filament enabled if they are compatible with the currently selected preset. // The following method should not discard changes of current print or filament presets on change of a printer profile, // if they are compatible with the current printer. - if (current_dirty || print_tab || printer_tab) + if (current_dirty || delete_current || print_tab || printer_tab) m_preset_bundle->update_compatible(true); // Initialize the UI from the current preset. if (printer_tab) static_cast(this)->update_pages(); - if (!is_selected && printer_tab) + if (! is_selected && printer_tab) { /* There is a case, when : * after Config Wizard applying we try to select previously selected preset, but @@ -2631,15 +2661,10 @@ void Tab::select_preset(std::string preset_name) * to the corresponding printer_technology */ const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); - if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT || - printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT ) - { - m_dependent_tabs.clear(); - if (printer_technology == ptFFF) - m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT }; - else - m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL }; - } + if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT) + m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT }; + else if (printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT) + m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL }; } load_current_preset(); } @@ -2771,11 +2796,14 @@ void Tab::save_preset(std::string name /*= ""*/) //! m_treectrl->OnSetFocus(); if (name.empty()) { - auto preset = m_presets->get_selected_preset(); + const Preset &preset = m_presets->get_selected_preset(); auto default_name = preset.is_default ? "Untitled" : preset.name; + if (preset.is_system) { + default_name += " - "; + default_name += _(L("Copy")).ToUTF8().data(); + } bool have_extention = boost::iends_with(default_name, ".ini"); - if (have_extention) - { + if (have_extention) { size_t len = default_name.length()-4; default_name.resize(len); } @@ -2819,7 +2847,7 @@ void Tab::save_preset(std::string name /*= ""*/) // If current profile is saved, "delete preset" button have to be enabled m_btn_delete_preset->Enable(true); - if (m_name == "printer") + if (m_type == Preset::TYPE_PRINTER) static_cast(this)->m_initial_extruders_count = static_cast(this)->m_extruders_count; update_changed_ui(); } @@ -2836,15 +2864,9 @@ void Tab::delete_preset() if (current_preset.is_default || wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) return; - // Delete the file and select some other reasonable preset. - // The 'external' presets will only be removed from the preset list, their files will not be deleted. - try{ m_presets->delete_current_preset(); } - catch (const std::exception & /* e */) - { - return; - } - // Load the newly selected preset into the UI, update selection combo boxes with their dirty flags. - load_current_preset(); + // Select will handle of the preset dependencies, of saving & closing the depending profiles, and + // finally of deleting the preset. + this->select_preset("", true); } void Tab::toggle_show_hide_incompatible() diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 15ae0443c4..58950990cf 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -239,7 +239,8 @@ public: void load_current_preset(); void rebuild_page_tree(); void update_page_tree_visibility(); - void select_preset(std::string preset_name = ""); + // Select a new preset, possibly delete the current one. + void select_preset(std::string preset_name = "", bool delete_current = false); bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); bool may_switch_to_SLA_preset(); From db21c67f1869eed13483c56ce0a42bfd9d982056 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 13:03:34 +0100 Subject: [PATCH 15/29] Changed logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index ac79784adf..1b6570eabd 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -411,24 +411,19 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) // mouse anywhere if (evt.Moving()) + { m_tooltip = update_hover_state(mouse_pos, parent); + if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) + m_mouse_capture.reset(); + } else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) m_mouse_capture.middle = false; else if (evt.RightUp()) m_mouse_capture.right = false; - else if (m_mouse_capture.any()) - { - if (evt.Dragging()) - processed = true; - else if (evt.Entering() && (m_mouse_capture.parent == &parent)) - // Resets the mouse capture state to avoid setting the dragging event as processed when, for example, - // the item action opens a modal dialog - // Keeps the mouse capture state if the entering event happens on different parent from the one - // who received the button down event, to prevent, for example, dragging when switching between scene views - m_mouse_capture.reset(); - } + else if (evt.Dragging() && m_mouse_capture.any()) + processed = true; int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) From 6bf0cf946669cba253c9b19db449727d0c003670 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 22 Mar 2019 14:35:26 +0100 Subject: [PATCH 16/29] Another tweak to the logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 30 +++++++++++++++++++++++++++--- src/slic3r/GUI/GLToolbar.hpp | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 1b6570eabd..1a8539aefc 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -157,7 +157,9 @@ GLToolbar::GLToolbar(GLToolbar::EType type) #if ENABLE_SVG_ICONS , m_icons_texture_dirty(true) #endif // ENABLE_SVG_ICONS - , m_mouse_capture({ false, false, false, nullptr }) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// , m_mouse_capture({ false, false, false, nullptr }) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ , m_tooltip("") { } @@ -410,12 +412,27 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool processed = false; // mouse anywhere - if (evt.Moving()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) { - m_tooltip = update_hover_state(mouse_pos, parent); if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) + { m_mouse_capture.reset(); + std::cout << "Dragging restored by toolbar" << std::endl; + } } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + if (evt.Moving()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// { +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + m_tooltip = update_hover_state(mouse_pos, parent); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) +// m_mouse_capture.reset(); +// } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) @@ -423,7 +440,14 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) else if (evt.RightUp()) m_mouse_capture.right = false; else if (evt.Dragging() && m_mouse_capture.any()) +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + { + std::cout << "Dragging prevented by toolbar" << std::endl; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ processed = true; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 95953795f0..3d72266c9f 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -238,6 +238,10 @@ private: bool right; GLCanvas3D* parent; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + MouseCapture() { reset(); } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + bool any() const { return left || middle || right; } void reset() { left = middle = right = false; parent = nullptr; } }; From d165dbb49842a6fd44193318443259dabc0b0ef6 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:31:38 +0100 Subject: [PATCH 17/29] Refactoring changes to the slice index. --- src/libslic3r/MTUtils.hpp | 107 +++++++++++++++++ src/libslic3r/SLAPrint.cpp | 206 +++++++++------------------------ src/libslic3r/SLAPrint.hpp | 119 +++++++++++-------- src/slic3r/GUI/GLCanvas3D.cpp | 26 +++-- src/slic3r/GUI/GUI_Preview.cpp | 6 +- 5 files changed, 249 insertions(+), 215 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 1e0fb426aa..1f6ca1a237 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -56,6 +56,113 @@ public: } }; +template +class IndexBasedIterator { + static const size_t NONE = size_t(-1); + + std::reference_wrapper m_index_ref; + size_t m_idx = NONE; +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) {} + + // 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++() { + ++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) { + 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) { + auto cpy = *this; cpy -= l; return cpy; + } + + operator difference_type() { return difference_type(m_idx); } + + inline bool is_end() const { return m_idx >= m_index_ref.get().size();} + + inline Value & operator*() const { + assert(m_idx < m_index_ref.get().size()); + return m_index_ref.get().operator[](m_idx); + } + + inline Value * operator->() const { + assert(m_idx < m_index_ref.get().size()); + return &m_index_ref.get().operator[](m_idx); + } + + 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) { + return !(*this == other); + } + + inline bool operator <=(const IndexBasedIterator& other) { + return (m_idx < other.m_idx) || (*this == other); + } + + inline bool operator <(const IndexBasedIterator& other) { + return m_idx < other.m_idx && (*this != other); + } + + inline bool operator >=(const IndexBasedIterator& other) { + return m_idx > other.m_idx || *this == other; + } + + inline bool operator >(const IndexBasedIterator& other) { + return m_idx > other.m_idx && *this != other; + } +}; + +template class Range { + It from, to; +public: + It begin() const { return from; } + It end() const { return to; } + using Type = It; + + Range() = default; + Range(It &&b, It &&e): + from(std::forward(b)), to(std::forward(e)) {} + + inline size_t size() const { return end() - begin(); } + inline bool empty() const { return size() == 0; } +}; + } #endif // MTUTILS_HPP diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 58386c0bdb..4d34b8e7d4 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -626,8 +626,8 @@ void SLAPrint::process() double lhd = m_objects.front()->m_config.layer_height.getFloat(); float lh = float(lhd); - LevelID ilhs = ilhd / SCALING_FACTOR; - LevelID lhs = lhd / SCALING_FACTOR; + auto ilhs = LevelID(ilhd / SCALING_FACTOR); + auto lhs = LevelID(lhd / SCALING_FACTOR); const size_t objcount = m_objects.size(); const unsigned min_objstatus = 0; // where the per object operations start @@ -657,17 +657,15 @@ void SLAPrint::process() double minZ = bb3d.min(Z) - po.get_elevation(); double maxZ = bb3d.max(Z); - LevelID minZs = minZ / SCALING_FACTOR; - LevelID maxZs = maxZ / SCALING_FACTOR; - - auto slh = [](float h) { return LevelID( double(h) / SCALING_FACTOR); }; + auto minZs = LevelID(minZ / SCALING_FACTOR); + auto maxZs = LevelID(maxZ / SCALING_FACTOR); po.m_slice_index.clear(); po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1); - po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilh / 2.f, ilh); + po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh); for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) { - po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lh / 2.f, lh); + po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh); } auto slindex_it = po.search_slice_index(float(bb3d.min(Z))); @@ -867,8 +865,10 @@ void SLAPrint::process() // be part of the slices) auto slice_supports = [](SLAPrintObject& po) { auto& sd = po.m_supportdata; + + if(sd) sd->support_slices.clear(); + if(sd && sd->support_tree_ptr) { - sd->support_slices.clear(); std::vector heights; heights.reserve(po.m_slice_index.size()); @@ -891,75 +891,6 @@ void SLAPrint::process() // We have the layer polygon collection but we need to unite them into // an index where the key is the height level in discrete levels (clipper) auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) { -// po.m_slice_index.clear(); -// auto sih = LevelID(scale_(ilhd)); - -// // Establish the slice grid boundaries -// auto bb = po.transformed_mesh().bounding_box(); -// double modelgnd = bb.min(Z); -// double elevation = po.get_elevation(); -// double lh = po.m_config.layer_height.getFloat(); -// double minZ = modelgnd - elevation; - -// // scaled values: -// auto sminZ = LevelID(scale_(minZ)); -// auto smaxZ = LevelID(scale_(bb.max(Z))); -// auto smodelgnd = LevelID(scale_(modelgnd)); -// auto slh = LevelID(scale_(lh)); - -// // It is important that the next levels match the levels in -// // model_slice method. Only difference is that here it works with -// // scaled coordinates -// po.m_level_ids.clear(); -// for(LevelID h = sminZ + sih; h < smaxZ; h += slh) -// if(h >= smodelgnd) po.m_level_ids.emplace_back(h); - -// std::vector& oslices = po.m_model_slices; - -// // If everything went well this code should not run at all, but -// // let's be robust... -// // assert(levelids.size() == oslices.size()); -// if(po.m_level_ids.size() < oslices.size()) { // extend the levels until... - -// BOOST_LOG_TRIVIAL(warning) -// << "Height level mismatch at rasterization!\n"; - -// LevelID lastlvl = po.m_level_ids.back(); -// while(po.m_level_ids.size() < oslices.size()) { -// lastlvl += slh; -// po.m_level_ids.emplace_back(lastlvl); -// } -// } - -// for(size_t i = 0; i < oslices.size(); ++i) { -// LevelID h = po.m_level_ids[i]; - -// float fh = float(double(h) * SCALING_FACTOR); - -// // now for the public slice index: -// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; -// // There should be only one slice layer for each print object -// assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE); -// sr.model_slices_idx = i; -// } - -// if(po.m_supportdata) { // deal with the support slices if present -// std::vector& sslices = po.m_supportdata->support_slices; -// po.m_supportdata->level_ids.clear(); -// po.m_supportdata->level_ids.reserve(sslices.size()); - -// for(int i = 0; i < int(sslices.size()); ++i) { -// LevelID h = sminZ + sih + i * slh; -// po.m_supportdata->level_ids.emplace_back(h); - -// float fh = float(double(h) * SCALING_FACTOR); - -// SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh]; -// assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE); -// sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i); -// } -// } - // Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices. report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW); }; @@ -975,41 +906,16 @@ void SLAPrint::process() LevelID gndlvl = o->get_slice_index().front().key(); for(auto& slicerecord : o->get_slice_index()) { auto& lyrs = m_printer_input[slicerecord.key() - gndlvl]; - auto objslit = slicerecord.get_slices(*o, soModel); - auto supslit = slicerecord.get_slices(*o, soSupport); - if(objslit != o->get_model_slices().end()) - lyrs.emplace_back(*objslit, o->instances()); + const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel); + const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport); - if(supslit != o->get_support_slices().end()) - lyrs.emplace_back(*supslit, o->instances()); + if(!objslices.empty()) + lyrs.emplace_back(objslices, o->instances()); + + if(!supslices.empty()) + lyrs.emplace_back(supslices, o->instances()); } - -// auto& po = *o; -// std::vector& oslices = po.m_model_slices; - -// // We need to adjust the min Z level of the slices to be zero -// LevelID smfirst = -// po.m_supportdata && !po.m_supportdata->level_ids.empty() ? -// po.m_supportdata->level_ids.front() : 0; -// LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front(); -// LevelID gndlvl = -(std::min(smfirst, mfirst)); - -// // now merge this object's support and object slices with the rest -// // of the print object slices - -// for(size_t i = 0; i < oslices.size(); ++i) { -// auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]]; -// lyrs.emplace_back(oslices[i], po.m_instances); -// } - -// if(!po.m_supportdata) continue; -// std::vector& sslices = po.m_supportdata->support_slices; -// for(size_t i = 0; i < sslices.size(); ++i) { -// LayerRefs& lyrs = -// m_printer_input[gndlvl + po.m_supportdata->level_ids[i]]; -// lyrs.emplace_back(sslices[i], po.m_instances); -// } } // collect all the keys @@ -1355,13 +1261,13 @@ void SLAPrint::fill_statistics() record = &(*it); } - auto modelslice_it = record->get_slices(*po, soModel); - if (modelslice_it != po->get_model_slices().end()) - append(model_polygons, get_all_polygons(*modelslice_it, po->instances())); - - auto supportslice_it = record->get_slices(*po, soSupport); - if (supportslice_it != po->get_support_slices().end()) - append(supports_polygons, get_all_polygons(*supportslice_it, po->instances())); + const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel); + if (!modelslices.empty()) + append(model_polygons, get_all_polygons(modelslices, po->instances())); + + const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport); + if (!supportslices.empty()) + append(supports_polygons, get_all_polygons(supportslices, po->instances())); } model_polygons = union_(model_polygons); @@ -1561,6 +1467,7 @@ double SLAPrintObject::get_current_elevation() const namespace { // dummy empty static containers for return values in some methods const std::vector EMPTY_SLICES; const TriangleMesh EMPTY_MESH; +const ExPolygons EMPTY_SLICE; } const std::vector& SLAPrintObject::get_support_points() const @@ -1597,7 +1504,8 @@ SLAPrintObject::search_slice_index(float slice_level) const } SLAPrintObject::SliceIndex::iterator -SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key, + bool exact) { _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(), @@ -1608,13 +1516,15 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + if(exact && it != m_slice_index.end() && it->key() != key) + it = m_slice_index.end(); return it; } SLAPrintObject::SliceIndex::const_iterator -SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const +SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key, + bool exact) const { _SliceRecord query(key, 0.f, 0.f); auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(), @@ -1625,28 +1535,12 @@ SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key) const }); // Return valid iterator only if the keys really match - if(it != m_slice_index.end() && it->key() != key) it = m_slice_index.end(); + if(exact && it != m_slice_index.end() && it->key() != key) + it = m_slice_index.end(); return it; } -SliceRange SLAPrintObject::get_slices(SliceOrigin so, - float from_level, - float to_level) const -{ - auto it_from = search_slice_index(from_level); - auto it_to = search_slice_index(to_level); - - SliceRange ret; - - auto endit = so == soModel? get_model_slices().end() : get_support_slices().end(); - - ret.from = it_from == m_slice_index.end() ? endit : it_from->get_slices(*this, so); - ret.to = it_to == m_slice_index.end() ? endit : it_to->get_slices(*this, so); - - return ret; -} - const std::vector &SLAPrintObject::get_support_slices() const { // assert(is_step_done(slaposSliceSupports)); @@ -1654,6 +1548,28 @@ const std::vector &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } +const ExPolygons &SLAPrintObject::get_slices_from_record( + const _SliceRecord &rec, + SliceOrigin o) const +{ + size_t idx = o == soModel ? rec.get_model_slice_idx() : + rec.get_support_slice_idx(); + + const std::vector& v = o == soModel? get_model_slices() : + get_support_slices(); + + if(idx >= v.size()) return EMPTY_SLICE; + + return idx >= v.size() ? EMPTY_SLICE : v[idx]; +} + +const ExPolygons &SLAPrintObject::get_slices_from_record( + SLAPrintObject::SliceRecordConstIterator it, SliceOrigin o) const +{ + if(it.is_end()) return EMPTY_SLICE; + return get_slices_from_record(*it, o); +} + const std::vector& SLAPrintObject::get_slice_index() const { @@ -1778,18 +1694,4 @@ std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) return final_path; } -SliceIterator SLAPrintObject::_SliceRecord::get_slices(const SLAPrintObject &po, - SliceOrigin so) const -{ - - const std::vector& v = so == soModel? po.get_model_slices() : - po.get_support_slices(); - - size_t idx = so == soModel ? m_model_slices_idx : m_support_slices_idx; - - using DiffT = std::vector::const_iterator::difference_type; - - return idx == NONE? v.end() : v.begin() + DiffT(idx); -} - } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index b33bfdeb08..ff715fb5ed 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -6,6 +6,7 @@ #include "PrintExport.hpp" #include "Point.hpp" #include "MTUtils.hpp" +#include namespace Slic3r { @@ -35,23 +36,8 @@ using _SLAPrintObjectBase = // the printer (rasterizer) in the SLAPrint class. using LevelID = long long; -template struct Range { - It from, to; - It begin() const { return from; } - It end() const { return to; } - using Type = It; - - Range() = default; - explicit Range(It &&b, It &&e): - from(std::forward(b)), to(std::forward(e)) {} -}; - enum SliceOrigin { soSupport, soModel }; -using SliceStore = std::vector; -using SliceIterator = SliceStore::const_iterator; -using SliceRange = Range; - class SLAPrintObject : public _SLAPrintObjectBase { private: // Prevents erroneous use by other classes. @@ -107,12 +93,14 @@ public: // This method returns the support points of this SLAPrintObject. const std::vector& get_support_points() const; + // The public Slice record structure. It corresponds to one printable layer. + // To get the sliced polygons, use SLAPrintObject::get_slices_from_record class SliceRecord { public: using Key = LevelID; private: - LevelID m_print_z = 0; // Top of the layer + Key m_print_z = 0; // Top of the layer float m_slice_z = 0.f; // Exact level of the slice float m_height = 0.f; // Height of the sliced layer @@ -139,8 +127,9 @@ private: // levels of the model in scaled-clipper coordinates. The levels correspond // to the z coordinate of the object coordinate system. class _SliceRecord: public SliceRecord { - private: + public: static const size_t NONE = size_t(-1); // this will be the max limit of size_t + private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; @@ -148,14 +137,12 @@ private: _SliceRecord(Key key, float slicez, float height): SliceRecord(key, slicez, height) {} - // Returns the slices for either the model or the supports. The return - // value is an iterator to po.get_model_slices() or po.get_support_slices - // depending on the SliceOrigin parameter. - SliceIterator get_slices(const SLAPrintObject& po, SliceOrigin so) const; - - // Methods for setting the indixes into the slice vectors. + // Methods for setting the indices into the slice vectors. void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } + + inline size_t get_model_slice_idx() const { return m_model_slices_idx; } + inline size_t get_support_slice_idx() const { return m_support_slices_idx; } }; // Slice index will be a plain vector sorted by the integer height levels @@ -171,37 +158,78 @@ private: // Search the slice index for a particular level in integer coordinates. // If no such layer is present, it will return m_slice_index.end() - SliceIndex::iterator search_slice_index(_SliceRecord::Key key); - SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key) const; + // This behavior can be suppressed by the second parameter. If it is true + // the method will return the closest (non-equal) record + SliceIndex::iterator search_slice_index(_SliceRecord::Key key, bool exact = false); + SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key, bool = false) const; + + const std::vector& get_model_slices() const; + const std::vector& get_support_slices() const; public: - // ///////////////////////////////////////////////////////////////////////// - // The following methods can be used after the model and the support slicing - // steps have been succesfully finished. - // ///////////////////////////////////////////////////////////////////////// - - // Getting slices (model or supports) for a Z coordinate range. The returned - // iterators should include the slices for the given boundaries as well. - SliceRange get_slices( - SliceOrigin so, - float from_level, - float to_level = std::numeric_limits::infinity()) const; + // Should work as a polymorphic bidirectional iterator to the slice records + using SliceRecordConstIterator = + IndexBasedIterator; + // ///////////////////////////////////////////////////////////////////////// + // // These two methods should be callable on the client side (e.g. UI thread) // when the appropriate steps slaposObjectSlice and slaposSliceSupports // are ready. All the print objects are processed before slapsRasterize so // it is safe to call them during and/or after slapsRasterize. - const std::vector& get_model_slices() const; - const std::vector& get_support_slices() const; + // + // ///////////////////////////////////////////////////////////////////////// - // Returns the total number of slices in the slice grid (model and supports) - inline size_t get_slice_count() const { return m_slice_index.size(); } + // Get the slice records from a range of slice levels (inclusive). Floating + // point keys are the levels where the model was sliced with the mesh + // slicer. Integral keys are the keys of the slice records, which + // correspond to the top of each layer.. The end() method of the returned + // range points *after* the last valid element. This is for being + // consistent with std and makeing range based for loops work. use + // std::prev(range.end()) or --range.end() to get the last element. + template Range + get_slice_records(Key from, Key to = std::numeric_limits::max()) const + { + SliceIndex::const_iterator it_from, it_to; + if(std::is_integral::value) { + it_from = search_slice_index(SliceRecord::Key(from)); + it_to = search_slice_index(SliceRecord::Key(to)); + } else if(std::is_floating_point::value) { + it_from = search_slice_index(float(from)); + it_to = search_slice_index(float(to)); + } else return { + SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ), + SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ), + }; - inline const SliceRecord& get_slice_record(size_t idx) const { - return m_slice_index[idx]; + auto start = m_slice_index.begin(); + + size_t bidx = it_from == m_slice_index.end() ? _SliceRecord::NONE : + size_t(it_from - start); + + size_t eidx = it_to == m_slice_index.end() ? _SliceRecord::NONE : + size_t(it_to - start) + 1; + + return { + SliceRecordConstIterator(m_slice_index, bidx), + SliceRecordConstIterator(m_slice_index, eidx), + }; } + // Get all the slice records as a range. + inline Range get_slice_records() const { + return { + SliceRecordConstIterator(m_slice_index, 0), + SliceRecordConstIterator(m_slice_index, m_slice_index.size()) + }; + } + + const ExPolygons& get_slices_from_record(SliceRecordConstIterator it, + SliceOrigin o) const; + + const ExPolygons& get_slices_from_record(const _SliceRecord& rec, + SliceOrigin o) const; protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -242,7 +270,7 @@ private: // Exact (float) height levels mapped to the slices. Each record contains // the index to the model and the support slice vectors. - std::vector<_SliceRecord> m_slice_index; + std::vector<_SliceRecord> m_slice_index; std::vector m_model_height_levels; @@ -335,11 +363,6 @@ private: // Invalidate steps based on a set of parameters changed. bool invalidate_state_by_config_options(const std::vector &opt_keys); - std::vector calculate_heights(const BoundingBoxf3& bb, - float elevation, - float initial_layer_height, - float layer_height) const; - void fill_statistics(); SLAPrintConfig m_print_config; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0f1e15b76c..8acb5ad537 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5014,26 +5014,28 @@ void GLCanvas3D::_render_sla_slices() const if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { // FIXME: is this all right (by Tamas)? - SliceRange obj_range = obj->get_slices(soModel, float(min_z), float(max_z)); - SliceRange sup_range = obj->get_slices(soSupport, float(min_z), float(max_z)); - auto obj_end = obj->get_model_slices().end(); - auto sup_end = obj->get_support_slices().end(); + auto slice_range = obj->get_slice_records(coord_t(min_z / SCALING_FACTOR), + coord_t(max_z / SCALING_FACTOR)); + const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_range.begin(), soModel); + const ExPolygons& obj_top = obj->get_slices_from_record(std::prev(slice_range.end()), soModel); + const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_range.begin(), soSupport); + const ExPolygons& sup_top = obj->get_slices_from_record(std::prev(slice_range.end()), soSupport); // calculate model bottom cap - if(bottom_obj_triangles.empty() && obj_range.from != obj_end) - bottom_obj_triangles = triangulate_expolygons_3d(*obj_range.from, min_z, true); + if(bottom_obj_triangles.empty() && !obj_bottom.empty()) + bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, min_z, true); // calculate support bottom cap - if(bottom_sup_triangles.empty() && sup_range.from != sup_end) - bottom_sup_triangles = triangulate_expolygons_3d(*sup_range.from, min_z, true); + if(bottom_sup_triangles.empty() && !sup_bottom.empty()) + bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true); // calculate model top cap - if(top_obj_triangles.empty() && obj_range.to != obj_end) - top_obj_triangles = triangulate_expolygons_3d(*obj_range.to, max_z, false); + if(top_obj_triangles.empty() && !obj_top.empty()) + top_obj_triangles = triangulate_expolygons_3d(obj_top, max_z, false); // calculate support top cap - if(top_sup_triangles.empty() && sup_range.to != sup_end) - top_sup_triangles = triangulate_expolygons_3d(*sup_range.to, max_z, false); + if(top_sup_triangles.empty() && !sup_top.empty()) + top_sup_triangles = triangulate_expolygons_3d(sup_top, max_z, false); // const std::vector& model_slices = obj->get_model_slices(); // const std::vector& support_slices = obj->get_support_slices(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 10a4a12c7e..5edca6c969 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -775,10 +775,10 @@ void Preview::load_print_as_sla() double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { - size_t cnt = obj->get_slice_count(); - for (size_t i = 0; i < cnt; i++) + auto slicerecords = obj->get_slice_records(); + for (auto& rec : slicerecords) { - zs.insert(shift_z + obj->get_slice_record(i).key() * SCALING_FACTOR); + zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR); } } } From ae9356904402ada309f9a2f82e2a53084f379528 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 15:45:51 +0100 Subject: [PATCH 18/29] Call Config Wizard from the Printer combo box at both the plater and the parameter tab. --- src/slic3r/GUI/Plater.cpp | 9 ++++--- src/slic3r/GUI/Plater.hpp | 8 ++++-- src/slic3r/GUI/Preset.cpp | 47 +++++++++++++++++++++++++++++++-- src/slic3r/GUI/Preset.hpp | 5 ++++ src/slic3r/GUI/PresetBundle.cpp | 1 + src/slic3r/GUI/Tab.cpp | 3 +++ 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 906a5009ae..a2ab8c3f1c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -57,6 +57,7 @@ #include "BackgroundSlicingProcess.hpp" #include "ProgressStatusBar.hpp" #include "PrintHostDialogs.hpp" +#include "ConfigWizard.hpp" #include "../Utils/ASCIIFolding.hpp" #include "../Utils/PrintHost.hpp" #include "../Utils/FixModelByWin10.hpp" @@ -233,9 +234,11 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * auto selected_item = this->GetSelection(); auto marker = reinterpret_cast(this->GetClientData(selected_item)); - if (marker == LABEL_ITEM_MARKER) { + if (marker == LABEL_ITEM_MARKER || marker == LABEL_ITEM_CONFIG_WIZARD) { this->SetSelection(this->last_selected); evt.StopPropagation(); + if (marker == LABEL_ITEM_CONFIG_WIZARD) + wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); } else if ( this->last_selected != selected_item || wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) { this->last_selected = selected_item; @@ -317,9 +320,9 @@ PresetComboBox::~PresetComboBox() } -void PresetComboBox::set_label_marker(int item) +void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type) { - this->SetClientData(item, (void*)LABEL_ITEM_MARKER); + this->SetClientData(item, (void*)label_item_type); } void PresetComboBox::check_selection() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f3e195ad09..f830edce3f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -48,14 +48,18 @@ public: wxButton* edit_btn { nullptr }; - void set_label_marker(int item); + enum LabelItemType { + LABEL_ITEM_MARKER = 0x4d, + LABEL_ITEM_CONFIG_WIZARD = 0x4e + }; + + void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER); void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; } int get_extruder_idx() const { return extruder_idx; } void check_selection(); private: typedef std::size_t Marker; - enum { LABEL_ITEM_MARKER = 0x4d }; Preset::Type preset_type; int last_selected; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index e63ae32f7f..6ed711c95b 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -519,6 +519,7 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vectorLoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG); } +bool PresetCollection::load_bitmap_add(const std::string &file_name) +{ + return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG); +} + const Preset* PresetCollection::get_selected_preset_parent() const { const std::string &inherits = this->get_edited_preset().inherits(); @@ -903,7 +911,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) wxString selected = ""; if (!this->m_presets.front().is_visible) ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); - for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { + for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) continue; @@ -953,6 +961,30 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) selected_preset_item = ui->GetCount() - 1; } } + if (m_type == Preset::TYPE_PRINTER) { + std::string bitmap_key = ""; + // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left + // to the filament color image. + if (wide_icons) + bitmap_key += "wide,"; + bitmap_key += "add_printer"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + if (wide_icons) + // Paint a red flag for incompatible presets. + bmps.emplace_back(m_bitmap_cache->mkclear(16, 16)); + // Paint the color bars. + bmps.emplace_back(m_bitmap_cache->mkclear(4, 16)); + bmps.emplace_back(*m_bitmap_main_frame); + // Paint a lock at the system presets. + bmps.emplace_back(m_bitmap_cache->mkclear(6, 16)); + bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } + ui->set_label_marker(ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); @@ -1001,7 +1033,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati if (i == m_idx_selected) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } - if (i + 1 == m_num_default_presets) + if (i + 1 == m_num_default_presets) ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); } if (!nonsys_presets.empty()) @@ -1013,6 +1045,17 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati selected_preset_item = ui->GetCount() - 1; } } + if (m_type == Preset::TYPE_PRINTER) { + wxBitmap *bmp = m_bitmap_cache->find("add_printer_tab"); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + bmps.emplace_back(*m_bitmap_main_frame); + bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); + bmp = m_bitmap_cache->insert("add_printer_tab", bmps); + } + ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp); + } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index c84c37029e..cc0a515889 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -277,6 +277,9 @@ public: // Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame. bool load_bitmap_default(const std::string &file_name); + // Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame. + bool load_bitmap_add(const std::string &file_name); + // Compatible & incompatible marks, to be placed at the wxBitmapComboBox items. void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; } void set_bitmap_incompatible(const wxBitmap *bmp) { m_bitmap_incompatible = bmp; } @@ -467,6 +470,8 @@ private: // Marks placed at the wxBitmapComboBox of a MainFrame. // These bitmaps are owned by PresetCollection. wxBitmap *m_bitmap_main_frame; + // "Add printer profile" icon, owned by PresetCollection. + wxBitmap *m_bitmap_add; // Path to the directory to store the config files into. std::string m_dir_path; diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index b8c9fedacc..b7e26a66ce 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -107,6 +107,7 @@ PresetBundle::PresetBundle() : this->filaments .load_bitmap_default("spool.png"); this->sla_materials.load_bitmap_default("package_green.png"); this->printers .load_bitmap_default("printer_empty.png"); + this->printers .load_bitmap_add("add.png"); this->load_compatible_bitmaps(); // Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index d38e96ca28..e5044935ec 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -29,6 +29,7 @@ #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" +#include "ConfigWizard.hpp" namespace Slic3r { namespace GUI { @@ -252,6 +253,8 @@ void Tab::create_preset_tab() /*selected_string == "------- System presets -------" || selected_string == "------- User presets -------"*/) { m_presets_choice->SetSelection(m_selected_preset_item); + if (selected_string == "------- " + _(L("Add a new printer")) + " -------") + wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); return; } m_selected_preset_item = selected_item; From 8e18605bd720f895cc6f0088b1dd27c49dd4fb69 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 22 Mar 2019 15:48:20 +0100 Subject: [PATCH 19/29] Fix for incorrect model slices after elevation has changed. --- src/libslic3r/SLAPrint.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 4d34b8e7d4..79834908f2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1363,11 +1363,15 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector Date: Fri, 22 Mar 2019 17:07:12 +0100 Subject: [PATCH 20/29] Refactored the -------- xxxx ---------- menu items to use a generic code to generate these separators. Now using the connected dashes (unicode emdash characters) on OSX and Windows. --- src/slic3r/GUI/Preset.cpp | 21 +++++++++++++-------- src/slic3r/GUI/Preset.hpp | 9 +++++++++ src/slic3r/GUI/PresetBundle.cpp | 8 ++++---- src/slic3r/GUI/Tab.cpp | 4 ++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 6ed711c95b..3da4c18716 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -910,7 +910,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) std::map nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) @@ -950,11 +950,11 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (i + 1 == m_num_default_presets) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected) @@ -983,7 +983,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } - ui->set_label_marker(ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); } ui->SetSelection(selected_preset_item); @@ -1002,7 +1002,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati std::map nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) @@ -1034,11 +1034,11 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (i + 1 == m_num_default_presets) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); } if (!nonsys_presets.empty()) { - ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected) @@ -1054,7 +1054,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert("add_printer_tab", bmps); } - ui->Append("------- " + _(L("Add a new printer")) + " -------", *bmp); + ui->Append(PresetCollection::separator("Add a new printer"), *bmp); } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); @@ -1284,6 +1284,11 @@ std::string PresetCollection::path_from_name(const std::string &new_name) const return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); } +wxString PresetCollection::separator(const std::string &label) +{ + return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail()); +} + const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const { const ConfigOptionEnumGeneric *opt_printer_technology = config.opt("printer_technology"); diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index cc0a515889..ee795f2b9b 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -410,6 +410,15 @@ public: // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. std::string path_from_name(const std::string &new_name) const; +#ifdef __linux__ + static const char* separator_head() { return "------- "; } + static const char* separator_tail() { return " -------"; } +#else /* __linux__ */ + static const char* separator_head() { return "————— "; } + static const char* separator_tail() { return " —————"; } +#endif /* __linux__ */ + static wxString separator(const std::string &label); + protected: // Select a preset, if it exists. If it does not exist, select an invalid (-1) index. // This is a temporary state, which shall be fixed immediately by the following step. diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index b7e26a66ce..9f42613726 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1406,7 +1406,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst // an optional "(modified)" suffix will be removed from the filament name. void PresetBundle::set_filament_preset(size_t idx, const std::string &name) { - if (name.find_first_of("-------") == 0) + if (name.find_first_of(PresetCollection::separator_head()) == 0) return; if (idx >= filament_presets.size()) @@ -1462,7 +1462,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr std::map nonsys_presets; wxString selected_str = ""; if (!this->filaments().front().is_visible) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) { const Preset &preset = this->filaments.preset(i); bool selected = this->filament_presets[idx_extruder] == preset.name; @@ -1515,12 +1515,12 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); } if (preset.is_default) - ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected_str) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e5044935ec..48d9ece478 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -249,11 +249,11 @@ void Tab::create_preset_tab() return; if (selected_item >= 0) { std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); - if (selected_string.find("-------") == 0 + if (selected_string.find(PresetCollection::separator_head()) == 0 /*selected_string == "------- System presets -------" || selected_string == "------- User presets -------"*/) { m_presets_choice->SetSelection(m_selected_preset_item); - if (selected_string == "------- " + _(L("Add a new printer")) + " -------") + if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer"))) wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); return; } From 2fe27a29e0eb9420f14a2cad0e6cb42276be27d4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 21:26:58 +0100 Subject: [PATCH 21/29] Fixed the SLA layer preview. --- src/libslic3r/SLAPrint.hpp | 5 ++ src/slic3r/GUI/GLCanvas3D.cpp | 91 ++++++++++++---------------------- src/slic3r/GUI/GUI_Preview.cpp | 18 +++---- 3 files changed, 44 insertions(+), 70 deletions(-) diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index ff715fb5ed..fbe2821b21 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -350,6 +350,11 @@ public: } const PrintObjects& objects() const { return m_objects; } + const SLAPrintConfig& print_config() const { return m_print_config; } + const SLAPrinterConfig& printer_config() const { return m_printer_config; } + const SLAMaterialConfig& material_config() const { return m_material_config; } + + std::string output_filename() const override; const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0018ae1cc4..8be187dece 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4971,24 +4971,20 @@ void GLCanvas3D::_render_sla_slices() const { const SLAPrintObject* obj = print_objects[i]; - double shift_z = obj->get_current_elevation(); - double min_z = clip_min_z - shift_z; - double max_z = clip_max_z - shift_z; - SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i); SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i); { if (it_caps_bottom == m_sla_caps[0].triangles.end()) it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first; - if (! m_sla_caps[0].matches(min_z)) { - m_sla_caps[0].z = min_z; + if (! m_sla_caps[0].matches(clip_min_z)) { + m_sla_caps[0].z = clip_min_z; it_caps_bottom->second.object.clear(); it_caps_bottom->second.supports.clear(); } if (it_caps_top == m_sla_caps[1].triangles.end()) it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first; - if (! m_sla_caps[1].matches(max_z)) { - m_sla_caps[1].z = max_z; + if (! m_sla_caps[1].matches(clip_max_z)) { + m_sla_caps[1].z = clip_max_z; it_caps_top->second.object.clear(); it_caps_top->second.supports.clear(); } @@ -5008,61 +5004,40 @@ void GLCanvas3D::_render_sla_slices() const std::vector instance_transforms; for (const SLAPrintObject::Instance& inst : instances) { - instance_transforms.push_back({ to_3d(unscale(inst.shift), shift_z), Geometry::rad2deg(inst.rotation) }); + instance_transforms.push_back({ to_3d(unscale(inst.shift), 0.), Geometry::rad2deg(inst.rotation) }); } if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices)) { - // FIXME: is this all right (by Tamas)? - auto slice_range = obj->get_slice_records(coord_t(min_z / SCALING_FACTOR), - coord_t(max_z / SCALING_FACTOR)); - const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_range.begin(), soModel); - const ExPolygons& obj_top = obj->get_slices_from_record(std::prev(slice_range.end()), soModel); - const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_range.begin(), soSupport); - const ExPolygons& sup_top = obj->get_slices_from_record(std::prev(slice_range.end()), soSupport); + double initial_layer_height = print->material_config().initial_layer_height.value; + LevelID key_zero = obj->get_slice_records().begin()->key(); + LevelID key_low = LevelID((clip_min_z - initial_layer_height) / SCALING_FACTOR) + key_zero; + LevelID key_high = LevelID((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero; + auto slice_range = obj->get_slice_records(key_low - LevelID(SCALED_EPSILON), key_high - LevelID(SCALED_EPSILON)); + auto it_low = slice_range.begin(); + auto it_high = std::prev(slice_range.end()); + + if (! it_low.is_end() && it_low->key() < key_low + LevelID(SCALED_EPSILON)) { + const ExPolygons& obj_bottom = obj->get_slices_from_record(it_low, soModel); + const ExPolygons& sup_bottom = obj->get_slices_from_record(it_low, soSupport); + // calculate model bottom cap + if (bottom_obj_triangles.empty() && !obj_bottom.empty()) + bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z, true); + // calculate support bottom cap + if (bottom_sup_triangles.empty() && !sup_bottom.empty()) + bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z, true); + } - // calculate model bottom cap - if(bottom_obj_triangles.empty() && !obj_bottom.empty()) - bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, min_z, true); - - // calculate support bottom cap - if(bottom_sup_triangles.empty() && !sup_bottom.empty()) - bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, min_z, true); - - // calculate model top cap - if(top_obj_triangles.empty() && !obj_top.empty()) - top_obj_triangles = triangulate_expolygons_3d(obj_top, max_z, false); - - // calculate support top cap - if(top_sup_triangles.empty() && !sup_top.empty()) - top_sup_triangles = triangulate_expolygons_3d(sup_top, max_z, false); - -// const std::vector& model_slices = obj->get_model_slices(); -// const std::vector& support_slices = obj->get_support_slices(); - -// const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); -// SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; }); -// SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; }); - -// if (it_min_z != index.end()) -// { -// // calculate model bottom cap -// if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) -// bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true); -// // calculate support bottom cap -// if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) -// bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true); -// } - -// if (it_max_z != index.end()) -// { -// // calculate model top cap -// if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) -// top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false); -// // calculate support top cap -// if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) -// top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false); -// } + if (! it_high.is_end() && it_high->key() < key_high + LevelID(SCALED_EPSILON)) { + const ExPolygons& obj_top = obj->get_slices_from_record(it_high, soModel); + const ExPolygons& sup_top = obj->get_slices_from_record(it_high, soSupport); + // calculate model top cap + if (top_obj_triangles.empty() && !obj_top.empty()) + top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z, false); + // calculate support top cap + if (top_sup_triangles.empty() && !sup_top.empty()) + top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z, false); + } } if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty()) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 5edca6c969..2361ff6d39 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -769,19 +769,17 @@ void Preview::load_print_as_sla() unsigned int n_layers = 0; const SLAPrint* print = m_process->sla_print(); - std::set zs; + std::vector zs; + double initial_layer_height = print->material_config().initial_layer_height.value; for (const SLAPrintObject* obj : print->objects()) - { - double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { auto slicerecords = obj->get_slice_records(); + auto low_coord = slicerecords.begin()->key(); for (auto& rec : slicerecords) - { - zs.insert(shift_z + /*rec.slice_level()*/ rec.key() * SCALING_FACTOR); - } + zs.emplace_back(initial_layer_height + (rec.key() - low_coord) * SCALING_FACTOR); } - } + sort_remove_duplicates(zs); n_layers = (unsigned int)zs.size(); if (n_layers == 0) @@ -796,11 +794,7 @@ void Preview::load_print_as_sla() show_hide_ui_elements("none"); if (n_layers > 0) - { - std::vector layer_zs; - std::copy(zs.begin(), zs.end(), std::back_inserter(layer_zs)); - update_sliders(layer_zs); - } + update_sliders(zs); m_loaded = true; } From b2ef3ba291e3df265a52e8e69e3b99b10178aa75 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 23:00:23 +0100 Subject: [PATCH 22/29] Fixed the options override box at the side bar. --- src/slic3r/GUI/GUI_ObjectSettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 3781cbf450..db9af7cce3 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -40,7 +40,7 @@ void OG_Settings::Hide() void OG_Settings::UpdateAndShow(const bool show) { Show(show); -// m_parent->Layout(); +// m_parent->Layout(); } wxSizer* OG_Settings::get_sizer() @@ -119,7 +119,7 @@ void ObjectSettings::update_settings_list() if (cat.second.size() == 1 && cat.second[0] == "extruder") continue; - auto optgroup = std::make_shared(m_parent, cat.first, config, false, extra_column); + auto optgroup = std::make_shared(m_og->ctrl_parent(), cat.first, config, false, extra_column); optgroup->label_width = 15 * wxGetApp().em_unit();//150; optgroup->sidetext_width = 7 * wxGetApp().em_unit();//70; From c623cbc4d72bbd5e05c27946292139fd2576b7fc Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Mar 2019 23:10:11 +0100 Subject: [PATCH 23/29] Fix of Perl bindings --- src/slic3r/GUI/Preset.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index ee795f2b9b..ac1171e183 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -11,9 +11,10 @@ #include "slic3r/Utils/Semver.hpp" class wxBitmap; -class wxChoice; class wxBitmapComboBox; +class wxChoice; class wxItemContainer; +class wxString; namespace Slic3r { From 4f585f11575d49dd086bc65badd4b3ebe2f10955 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 23 Mar 2019 08:23:22 +0100 Subject: [PATCH 24/29] Improved rendering when deleting an option from object's overrides. Replaced the single column icon with an empty icon. Will it break something? The single column added an ugly spacer in front of non-editable combo boxes. --- src/slic3r/GUI/Field.cpp | 5 ++++- src/slic3r/GUI/GUI_ObjectSettings.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 026b62ab59..9cd933160e 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -540,7 +540,10 @@ void Choice::BUILD() { else{ for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) { const wxString& str = _(el);//m_opt_id == "support" ? _(el) : el; - temp->Append(str, create_scaled_bitmap("empty_icon.png")); + //FIXME Vojtech: Why is the single column empty icon necessary? It is a workaround of some kind, but what for? + // Please document such workarounds by comments! + // temp->Append(str, create_scaled_bitmap("empty_icon.png")); + temp->Append(str, wxNullBitmap); } set_selection(); } diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index db9af7cce3..dbfdb8e6c5 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -10,6 +10,8 @@ #include "I18N.hpp" +#include + namespace Slic3r { namespace GUI @@ -84,6 +86,7 @@ void ObjectSettings::update_settings_list() btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) { config->erase(opt_key); wxTheApp->CallAfter([this]() { + wxWindowUpdateLocker noUpdates(m_parent); update_settings_list(); m_parent->Layout(); }); From 9652e8193a48d53441c2210a6f2d988b3ba811e1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 23 Mar 2019 10:04:44 +0100 Subject: [PATCH 25/29] Fixed caching of profile selections at the plater. --- src/slic3r/GUI/Plater.cpp | 6 +----- src/slic3r/GUI/Preset.cpp | 1 + src/slic3r/GUI/PresetBundle.cpp | 1 + 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a2ab8c3f1c..f9c598ce39 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -327,8 +327,7 @@ void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type) void PresetComboBox::check_selection() { - if (this->last_selected != GetSelection()) - this->last_selected = GetSelection(); + this->last_selected = GetSelection(); } // Frequently changed parameters @@ -829,10 +828,7 @@ void Sidebar::update_presets(Preset::Type preset_type) preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); } // Update the printer choosers, update the dirty flags. - auto prev_selection = p->combo_printer->GetSelection(); preset_bundle.printers.update_platter_ui(p->combo_printer); - if (prev_selection != p->combo_printer->GetSelection()) - p->combo_printer->check_selection(); // Update the filament choosers to only contain the compatible presets, update the color preview, // update the dirty flags. if (print_tech == ptFFF) { diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 3da4c18716..82223b15c0 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -988,6 +988,7 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->check_selection(); ui->Thaw(); } diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 9f42613726..f78a04126f 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1529,6 +1529,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr } ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->check_selection(); ui->Thaw(); } From 3f7f8f978eb6b08e27454c2c090f28dcb4c00a96 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Sun, 24 Mar 2019 13:35:09 +0100 Subject: [PATCH 26/29] Fix of sla gizmo (it sometimes showed supports for hidden objects) --- src/slic3r/GUI/GLCanvas3D.cpp | 10 ++++++---- src/slic3r/GUI/GLCanvas3D.hpp | 5 ++++- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8be187dece..3192e7861e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2293,11 +2293,13 @@ int GLCanvas3D::check_volumes_outside_state() const return (int)state; } -void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible) +void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { for (GLVolume* vol : m_volumes.volumes) { - if (vol->composite_id.volume_id < 0) - vol->is_active = visible; + if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) + && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) + && vol->composite_id.volume_id < 0) + vol->is_active = visible; } m_render_sla_auxiliaries = visible; @@ -2313,7 +2315,7 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } } if (visible && !mo) - toggle_sla_auxiliaries_visibility(true); + toggle_sla_auxiliaries_visibility(true, mo, instance_idx); if (!mo && !visible && !m_model->objects.empty() && (m_model->objects.size() > 1 || m_model->objects.front()->instances.size() > 1)) _set_warning_texture(WarningTexture::SomethingNotShown, true); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d9e38c4e0e..29e0fbb088 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -584,6 +584,9 @@ private: bool m_regenerate_volumes; bool m_moving; bool m_tab_down; + + // Following variable is obsolete and it should be safe to remove it. + // I just don't want to do it now before a release (Lukas Matena 24.3.2019) bool m_render_sla_auxiliaries; std::string m_color_by; @@ -610,7 +613,7 @@ public: void reset_volumes(); int check_volumes_outside_state() const; - void toggle_sla_auxiliaries_visibility(bool visible); + void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void set_config(const DynamicPrintConfig* config); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c629f21729..31f6b0278a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -666,7 +666,7 @@ RENDER_AGAIN: m_imgui->end(); if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode - m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode); + m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode, m_model_object, m_active_instance); force_refresh = true; } m_old_editing_state = m_editing_mode; From dd3ac4017a3001da6ab01d2b9ce54f42d0891b99 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 08:48:41 +0100 Subject: [PATCH 27/29] Yet another tweak to the logic for releasing mouse capture into GLToolbar::on_mouse() --- src/slic3r/GUI/GLToolbar.cpp | 59 ++++++++++++++++++++++++++++++++---- src/slic3r/GUI/GLToolbar.hpp | 2 +- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 1a8539aefc..00596a9cce 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -413,14 +413,60 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) // mouse anywhere //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) + if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr)) { - if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) - { - m_mouse_capture.reset(); - std::cout << "Dragging restored by toolbar" << std::endl; - } + if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())) + // prevents loosing selection into the scene if mouse down was done inside the toolbar and mouse up was down outside it, + // as when switching between views + processed = true; + + m_mouse_capture.reset(); + + + std::cout << "Dragging restored by toolbar ["; + if (evt.Entering()) + std::cout << "Entering"; + else if (evt.Leaving()) + std::cout << "Leaving"; + else if (evt.Dragging()) + std::cout << "Dragging"; + else if (evt.Moving()) + std::cout << "Moving"; + else if (evt.Magnify()) + std::cout << "Magnify"; + else if (evt.LeftDown()) + std::cout << "LeftDown"; + else if (evt.LeftUp()) + std::cout << "LeftUp"; + else if (evt.LeftDClick()) + std::cout << "LeftDClick"; + else if (evt.MiddleDown()) + std::cout << "MiddleDown"; + else if (evt.MiddleUp()) + std::cout << "MiddleUp"; + else if (evt.MiddleDClick()) + std::cout << "MiddleDClick"; + else if (evt.RightDown()) + std::cout << "RightDown"; + else if (evt.RightUp()) + std::cout << "RightUp"; + else if (evt.RightDClick()) + std::cout << "RightDClick"; + else + std::cout << "UNKNOWN "; + std::cout << "]" << std::endl; } + + +// if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) +// { +// std::cout << m_name << " - " << (void*)m_mouse_capture.parent << std::endl; +// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) +// { +// m_mouse_capture.reset(); +// std::cout << "Dragging restored by toolbar" << std::endl; +// } +// } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (evt.Moving()) @@ -444,6 +490,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) { std::cout << "Dragging prevented by toolbar" << std::endl; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + // if the button down was done on this toolbar, prevent from dragging into the scene processed = true; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 3d72266c9f..a0c0d9ca7a 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -239,7 +239,7 @@ private: GLCanvas3D* parent; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - MouseCapture() { reset(); } + MouseCapture() { reset(); } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ bool any() const { return left || middle || right; } From 149551946ca2f6f932d7e9f1f0ba461b956615cb Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 12:07:43 +0100 Subject: [PATCH 28/29] Fix of #1998 --- src/libslic3r/Format/AMF.cpp | 11 ++++++----- src/slic3r/GUI/Plater.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index f5219263d6..ff1da37cc1 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -175,6 +175,11 @@ struct AMFParserContext bool mirrory_set; float mirrorz; bool mirrorz_set; + + bool anything_set() const { return deltax_set || deltay_set || deltaz_set || + rx_set || ry_set || rz_set || + scalex_set || scaley_set || scalez_set || + mirrorx_set || mirrory_set || mirrorz_set; } }; struct Object { @@ -644,11 +649,7 @@ void AMFParserContext::endDocument() continue; } for (const Instance &instance : object.second.instances) -#if ENABLE_VOLUMES_CENTERING_FIXES - { -#else - if (instance.deltax_set && instance.deltay_set) { -#endif // ENABLE_VOLUMES_CENTERING_FIXES + if (instance.anything_set()) { ModelInstance *mi = m_model.objects[object.second.idx]->add_instance(); mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0)); mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f9c598ce39..e158821257 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1713,8 +1713,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode object->center_around_origin(); new_instances.emplace_back(object->add_instance()); #else /* AUTOPLACEMENT_ON_LOAD */ - // if object has no defined position(s) we need to rearrange everything after loading object->center_around_origin(); - need_arrange = true; + // if object has no defined position(s) we need to rearrange everything after loading + need_arrange = true; // add a default instance and center object around origin object->center_around_origin(); // also aligns object to Z = 0 ModelInstance* instance = object->add_instance(); From 3e0ec8098bce46673c4b0325b85825008ead9d03 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 25 Mar 2019 14:13:20 +0100 Subject: [PATCH 29/29] Code cleanup --- src/slic3r/GUI/GLToolbar.cpp | 65 ------------------------------------ src/slic3r/GUI/GLToolbar.hpp | 2 -- 2 files changed, 67 deletions(-) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 00596a9cce..2f7f13f6fc 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -157,9 +157,6 @@ GLToolbar::GLToolbar(GLToolbar::EType type) #if ENABLE_SVG_ICONS , m_icons_texture_dirty(true) #endif // ENABLE_SVG_ICONS -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// , m_mouse_capture({ false, false, false, nullptr }) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ , m_tooltip("") { } @@ -412,7 +409,6 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool processed = false; // mouse anywhere -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr)) { if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())) @@ -421,64 +417,10 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) processed = true; m_mouse_capture.reset(); - - - std::cout << "Dragging restored by toolbar ["; - if (evt.Entering()) - std::cout << "Entering"; - else if (evt.Leaving()) - std::cout << "Leaving"; - else if (evt.Dragging()) - std::cout << "Dragging"; - else if (evt.Moving()) - std::cout << "Moving"; - else if (evt.Magnify()) - std::cout << "Magnify"; - else if (evt.LeftDown()) - std::cout << "LeftDown"; - else if (evt.LeftUp()) - std::cout << "LeftUp"; - else if (evt.LeftDClick()) - std::cout << "LeftDClick"; - else if (evt.MiddleDown()) - std::cout << "MiddleDown"; - else if (evt.MiddleUp()) - std::cout << "MiddleUp"; - else if (evt.MiddleDClick()) - std::cout << "MiddleDClick"; - else if (evt.RightDown()) - std::cout << "RightDown"; - else if (evt.RightUp()) - std::cout << "RightUp"; - else if (evt.RightDClick()) - std::cout << "RightDClick"; - else - std::cout << "UNKNOWN "; - std::cout << "]" << std::endl; } - -// if (evt.Moving() || evt.LeftDown() || evt.MiddleDown() || evt.RightDown() || evt.LeftDClick() || evt.RightDClick()) -// { -// std::cout << m_name << " - " << (void*)m_mouse_capture.parent << std::endl; -// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) -// { -// m_mouse_capture.reset(); -// std::cout << "Dragging restored by toolbar" << std::endl; -// } -// } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - if (evt.Moving()) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// { -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ m_tooltip = update_hover_state(mouse_pos, parent); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// if ((m_mouse_capture.parent != nullptr) && (m_mouse_capture.parent != &parent)) -// m_mouse_capture.reset(); -// } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ else if (evt.LeftUp()) m_mouse_capture.left = false; else if (evt.MiddleUp()) @@ -486,15 +428,8 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) else if (evt.RightUp()) m_mouse_capture.right = false; else if (evt.Dragging() && m_mouse_capture.any()) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - { - std::cout << "Dragging prevented by toolbar" << std::endl; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // if the button down was done on this toolbar, prevent from dragging into the scene processed = true; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ int item_id = contains_mouse(mouse_pos, parent); if (item_id == -1) diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index a0c0d9ca7a..5fac1f5b2e 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -238,9 +238,7 @@ private: bool right; GLCanvas3D* parent; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MouseCapture() { reset(); } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ bool any() const { return left || middle || right; } void reset() { left = middle = right = false; parent = nullptr; }