From b541bc208f75547acf63cef4b87bf209dfb90e66 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 17:55:59 -0500 Subject: [PATCH 01/10] Avoid using wxString Printf, instead use Format() and use wxRealPoint (floating point) instead of wxPoint (integer) --- src/GUI/Plater/Plate2D.cpp | 7 ++----- src/GUI/Plater/Plate2D.hpp | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/GUI/Plater/Plate2D.cpp b/src/GUI/Plater/Plate2D.cpp index fb0b172a9..e2a4162bf 100644 --- a/src/GUI/Plater/Plate2D.cpp +++ b/src/GUI/Plater/Plate2D.cpp @@ -76,11 +76,8 @@ void Plate2D::repaint(wxPaintEvent& e) { dc->SetTextForeground(wxColor(0,0,0)); dc->SetFont(wxFont(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); - wxString val {}; - val.Printf("X = %.0f", this->print_center.x); - dc->DrawLabel(val , wxRect(0,0, center.x*2, this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); - val.Printf("Y = %.0f", this->print_center.y); - dc->DrawRotatedText(val, 0, center.y + 15, 90); + dc->DrawLabel(wxString::Format("X = %.0f", this->print_center.x), wxRect(0,0, center.x*2, this->GetSize().GetHeight()), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); + dc->DrawRotatedText(wxString::Format("Y = %.0f", this->print_center.y), 0, center.y + 15, 90); } } diff --git a/src/GUI/Plater/Plate2D.hpp b/src/GUI/Plater/Plate2D.hpp index 61c097422..1db726a11 100644 --- a/src/GUI/Plater/Plate2D.hpp +++ b/src/GUI/Plater/Plate2D.hpp @@ -90,8 +90,8 @@ private: void update_bed_size(); /// private class variables to stash bits for drawing the print bed area. - wxPoint bed_origin {}; - wxPoint print_center {}; + wxRealPoint bed_origin {}; + wxRealPoint print_center {}; Slic3r::Polygon bed_polygon {}; std::vector grid {}; From 10f4bf9be9e5ecd99b04a3ce126ef048808493a0 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 19:36:28 -0500 Subject: [PATCH 02/10] add log function to build strings for vectors --- xs/src/libslic3r/Log.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/xs/src/libslic3r/Log.hpp b/xs/src/libslic3r/Log.hpp index 5eddac995..255b2e7a6 100644 --- a/xs/src/libslic3r/Log.hpp +++ b/xs/src/libslic3r/Log.hpp @@ -2,6 +2,8 @@ #define slic3r_LOG_HPP #include +#include +#include namespace Slic3r { @@ -28,6 +30,28 @@ public: }; +/// Utility debug function to transform a std::vector of anything that +/// supports ostream& operator<<() into a std::string. +template +std::string +log_string(const std::vector& in) +{ + std::stringstream ss; + bool first {true}; + ss << "[ "; + for (auto& c : in) { + if (!first) { + ss << ", "; + } + ss << c; + first = false; + } + + ss << " ]"; + + return ss.str(); +} + } #endif // slic3r_LOG_HPP From 2e74c9f3ada5390d8acaf431c0177f557158f85e Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 19:37:25 -0500 Subject: [PATCH 03/10] Remember that std::vector<>.size() needs to be offset by 1 if it's being used to find the last index. --- src/GUI/Plater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GUI/Plater.cpp b/src/GUI/Plater.cpp index 16a74a828..d94e51005 100644 --- a/src/GUI/Plater.cpp +++ b/src/GUI/Plater.cpp @@ -244,7 +244,7 @@ std::vector Plater::load_model_objects(ModelObjectPtrs model_objects) { tmpobj.identifier = (this->object_identifier)++; this->objects.push_back(tmpobj); - obj_idx.push_back(this->objects.size()); + obj_idx.push_back(this->objects.size() - 1); Slic3r::Log::info(LogChannel, LOG_WSTRING("Object array new size: " << this->objects.size())); Slic3r::Log::info(LogChannel, LOG_WSTRING("Instances: " << obj->instances.size())); From ad2295639189a53ef3de3922c7ffff7a06f35155 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 19:38:11 -0500 Subject: [PATCH 04/10] Use .at() instead of [] because that'll throw an exception if out of bounds instead of a hard-to-find memory crash. --- src/GUI/Plater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GUI/Plater.cpp b/src/GUI/Plater.cpp index d94e51005..994adbe44 100644 --- a/src/GUI/Plater.cpp +++ b/src/GUI/Plater.cpp @@ -199,8 +199,8 @@ std::vector Plater::load_file(const wxString& file, const int obj_idx_to_lo } for (const auto &j : obj_idx) { - this->objects[j].input_file = file; - this->objects[j].input_file_obj_idx = i++; + this->objects.at(j).input_file = file; + this->objects.at(j).input_file_obj_idx = i++; } GetFrame()->statusbar->SetStatusText(_("Loaded ") + input_file.GetName()); From 08611ffc8ca282df39a3ee47d0fefa67cd205df8 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 19:39:34 -0500 Subject: [PATCH 05/10] Use std::string internally instead of wxString. --- src/GUI/Plater.cpp | 10 +++++----- src/GUI/Plater.hpp | 2 +- src/GUI/Plater/PlaterObject.hpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GUI/Plater.cpp b/src/GUI/Plater.cpp index 994adbe44..02cfae165 100644 --- a/src/GUI/Plater.cpp +++ b/src/GUI/Plater.cpp @@ -119,7 +119,7 @@ void Plater::add() { const auto& input_files{open_model(this, *(this->settings), wxTheApp->GetTopWindow())}; for (const auto& f : input_files) { Log::info(LogChannel, (wxString(L"Calling Load File for ") + f).ToStdWstring()); - this->load_file(f); + this->load_file(f.ToStdString()); } // abort if no objects actually added. @@ -144,7 +144,7 @@ void Plater::add() { } -std::vector Plater::load_file(const wxString& file, const int obj_idx_to_load) { +std::vector Plater::load_file(const std::string file, const int obj_idx_to_load) { auto input_file {wxFileName(file)}; settings->skein_directory = input_file.GetPath(); @@ -158,7 +158,7 @@ std::vector Plater::load_file(const wxString& file, const int obj_idx_to_lo progress_dialog->Pulse(); //TODO: Add a std::wstring so we can handle non-roman characters as file names. try { - model = Slic3r::Model::read_from_file(file.ToStdString()); + model = Slic3r::Model::read_from_file(file); } catch (std::runtime_error& e) { show_error(this, e.what()); Slic3r::Log::error(LogChannel, LOG_WSTRING(file << " failed to load: " << e.what())); @@ -177,10 +177,10 @@ std::vector Plater::load_file(const wxString& file, const int obj_idx_to_lo for (auto i = 0U; i < model.objects.size(); i++) { auto object {model.objects[i]}; - object->input_file = file.ToStdString(); + object->input_file = file; for (auto j = 0U; j < object->volumes.size(); j++) { auto volume {object->volumes.at(j)}; - volume->input_file = file.ToStdString(); + volume->input_file = file; volume->input_file_obj_idx = i; volume->input_file_vol_idx = j; } diff --git a/src/GUI/Plater.hpp b/src/GUI/Plater.hpp index 7f84f0ca1..d4eb41abf 100644 --- a/src/GUI/Plater.hpp +++ b/src/GUI/Plater.hpp @@ -61,7 +61,7 @@ private: Plate2D* canvas2D {}; //< 2D plater canvas /// Handles the actual load of the file from the dialog handoff. - std::vector load_file(const wxString& file, const int obj_idx_to_load = -1); + std::vector load_file(const std::string file, const int obj_idx_to_load = -1); const std::string LogChannel {"GUI_Plater"}; //< Which log these messages should go to. diff --git a/src/GUI/Plater/PlaterObject.hpp b/src/GUI/Plater/PlaterObject.hpp index 7fb6602cb..a99b20ca6 100644 --- a/src/GUI/Plater/PlaterObject.hpp +++ b/src/GUI/Plater/PlaterObject.hpp @@ -12,9 +12,9 @@ namespace Slic3r { namespace GUI { class PlaterObject { public: - wxString name {L""}; + std::string name {""}; size_t identifier {0U}; - wxString input_file {L""}; + std::string input_file {""}; int input_file_obj_idx {-1}; From 9cbc2810b44c3881fcc36345f1dd8fc9869979c0 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 20:36:40 -0500 Subject: [PATCH 06/10] Add additional translate() functions to accept a Point or Pointf for convenience. --- xs/src/libslic3r/ExPolygonCollection.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xs/src/libslic3r/ExPolygonCollection.hpp b/xs/src/libslic3r/ExPolygonCollection.hpp index 57f512336..b11e41ecd 100644 --- a/xs/src/libslic3r/ExPolygonCollection.hpp +++ b/xs/src/libslic3r/ExPolygonCollection.hpp @@ -24,6 +24,8 @@ class ExPolygonCollection operator ExPolygons&(); void scale(double factor); void translate(double x, double y); + void translate(const Point offset) { translate(static_cast(offset.x), static_cast(offset.y)); } + void translate(const Pointf offset) { translate(offset.x, offset.y); } void rotate(double angle, const Point ¢er); template bool contains(const T &item) const; bool contains_b(const Point &point) const; From 00fd19331efdbb83a93100bac105891c2572737c Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 20:37:18 -0500 Subject: [PATCH 07/10] Added convenience function to build a Point from a Pointf that is scaled. --- xs/src/libslic3r/Point.cpp | 5 +++++ xs/src/libslic3r/Point.hpp | 3 +++ 2 files changed, 8 insertions(+) diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index 9a4a71ac2..465f78db8 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -18,6 +18,11 @@ Point::operator==(const Point& rhs) const return this->coincides_with(rhs); } +Point +Point::new_scale(Pointf p) { + return Point(scale_(p.x), scale_(p.y)); +} + std::string Point::wkt() const { diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 57a9ef7e8..3c0b5f299 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -36,6 +36,9 @@ class Point static Point new_scale(coordf_t x, coordf_t y) { return Point(scale_(x), scale_(y)); }; + + /// Scale and create a Point from a Pointf. + static Point new_scale(Pointf p); bool operator==(const Point& rhs) const; std::string wkt() const; std::string dump_perl() const; From b1c6d28411fc2b6a564d756296ddedd2c910fac7 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 20:37:49 -0500 Subject: [PATCH 08/10] Ported clean_instance_thumbnails --- src/GUI/Plater/Plate2D.cpp | 4 ++++ src/GUI/Plater/Plate2D.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/GUI/Plater/Plate2D.cpp b/src/GUI/Plater/Plate2D.cpp index e2a4162bf..36997560e 100644 --- a/src/GUI/Plater/Plate2D.cpp +++ b/src/GUI/Plater/Plate2D.cpp @@ -97,6 +97,10 @@ void Plate2D::repaint(wxPaintEvent& e) { } +void Plate2D::clean_instance_thumbnails() { + for (auto& obj : this->objects) { + obj.instance_thumbnails.clear(); + } } void Plate2D::mouse_drag(wxMouseEvent& e) { diff --git a/src/GUI/Plater/Plate2D.hpp b/src/GUI/Plater/Plate2D.hpp index 1db726a11..42ec6f786 100644 --- a/src/GUI/Plater/Plate2D.hpp +++ b/src/GUI/Plater/Plate2D.hpp @@ -119,6 +119,9 @@ private: return this->point_to_model_units(pt.x, pt.y); } + /// Remove all instance thumbnails. + void clean_instance_thumbnails(); + }; } } // Namespace Slic3r::GUI From e6caa8aa618955c984047ad1bc60466b7bd796e1 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 20:39:29 -0500 Subject: [PATCH 09/10] Started work on component to draw thumbnails from repaint() method. --- src/GUI/Plater/Plate2D.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/GUI/Plater/Plate2D.cpp b/src/GUI/Plater/Plate2D.cpp index 36997560e..c235debb4 100644 --- a/src/GUI/Plater/Plate2D.cpp +++ b/src/GUI/Plater/Plate2D.cpp @@ -96,6 +96,32 @@ void Plate2D::repaint(wxPaintEvent& e) { } } + // Draw thumbnails + + dc->SetPen(dark_pen); + this->clean_instance_thumbnails(); + for (auto& obj : this->objects) { + auto model_object {this->model->objects.at(obj.identifier)}; + if (obj.thumbnail.expolygons.size() == 0) + continue; // if there's no thumbnail move on + for (size_t instance_idx = 0U; instance_idx < model_object->instances.size(); instance_idx++) { + auto& instance {model_object->instances.at(instance_idx)}; + if (obj.transformed_thumbnail.expolygons.size()) continue; + auto thumbnail {obj.transformed_thumbnail}; // starts in unscaled model coords + + thumbnail.translate(Point::new_scale(instance->offset)); + + obj.instance_thumbnails.emplace_back(thumbnail); + + for (auto& poly : obj.instance_thumbnails) { + for (const auto& points : poly.expolygons) { + auto poly { this->scaled_points_to_pixel(Polygon(points), 1) }; + dc->DrawPolygon(poly.size(), poly.data(), 0, 0); + } + } + } + } +} void Plate2D::clean_instance_thumbnails() { for (auto& obj : this->objects) { From 17074c14b89b5a5742261d9c164b0803ede7ffd5 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Sun, 6 May 2018 20:39:50 -0500 Subject: [PATCH 10/10] Remember to put the event skip in during repaint. --- src/GUI/Plater/Plate2D.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GUI/Plater/Plate2D.cpp b/src/GUI/Plater/Plate2D.cpp index c235debb4..04250c7ae 100644 --- a/src/GUI/Plater/Plate2D.cpp +++ b/src/GUI/Plater/Plate2D.cpp @@ -121,6 +121,7 @@ void Plate2D::repaint(wxPaintEvent& e) { } } } + e.Skip(); } void Plate2D::clean_instance_thumbnails() {