diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index db51dfe386..5267499b47 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1192,13 +1192,14 @@ sub arrange { # my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($self->{config}->bed_shape); # my $success = $self->{model}->arrange_objects(wxTheApp->{preset_bundle}->full_config->min_object_distance, $bb); + # Update is not implemented in C++ so we cannot call this for now $self->{appController}->arrange_model; # ignore arrange failures on purpose: user has visual feedback and we don't need to warn him # when parts don't fit in print bed # Force auto center of the aligned grid of of objects on the print bed. - $self->update(1); + $self->update(0); } sub split_object { diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 1565296e49..c222dcf890 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -20,7 +20,7 @@ #include #include -#include +// #include namespace Slic3r { @@ -387,17 +387,17 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb, // Create the arranger config auto min_obj_distance = static_cast(dist/SCALING_FACTOR); - Benchmark bench; + // Benchmark bench; - std::cout << "Creating model siluett..." << std::endl; + // std::cout << "Creating model siluett..." << std::endl; - bench.start(); + // bench.start(); // Get the 2D projected shapes with their 3D model instance pointers auto shapemap = arr::projectModelFromTop(model); - bench.stop(); + // bench.stop(); - std::cout << "Model siluett created in " << bench.getElapsedSec() - << " seconds. " << "Min object distance = " << min_obj_distance << std::endl; + // std::cout << "Model siluett created in " << bench.getElapsedSec() + // << " seconds. " << "Min object distance = " << min_obj_distance << std::endl; // std::cout << "{" << std::endl; // std::for_each(shapemap.begin(), shapemap.end(), @@ -436,7 +436,8 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb, biggest = &item; } } - if(it.second.vertexCount() > 3) shapes.push_back(std::ref(it.second)); + /*if(it.second.vertexCount() > 3)*/ + shapes.push_back(std::ref(it.second)); }); Box bin; @@ -468,27 +469,27 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb, scfg.try_reverse_order = false; scfg.force_parallel = true; + pcfg.alignment = Arranger::PlacementConfig::Alignment::CENTER; + + // TODO cannot use rotations until multiple objects of same geometry can + // handle different rotations + // arranger.useMinimumBoundigBoxRotation(); + pcfg.rotations = { 0.0 }; Arranger arranger(bin, min_obj_distance, pcfg, scfg); - arranger.useMinimumBoundigBoxRotation(); arranger.progressIndicator(progressind); - std::cout << "Arranging model..." << std::endl; - bench.start(); + // std::cout << "Arranging model..." << std::endl; + // bench.start(); // Arrange and return the items with their respective indices within the // input sequence. - ArrangeResult result; - try { - result = arranger.arrangeIndexed(shapes.begin(), shapes.end()); - } catch(std::exception& e) { - std::cerr << "An exception occured: " << e.what() << std::endl; - } + auto result = arranger.arrangeIndexed(shapes.begin(), shapes.end()); - bench.stop(); - std::cout << "Model arranged in " << bench.getElapsedSec() - << " seconds." << std::endl; + // bench.stop(); + // std::cout << "Model arranged in " << bench.getElapsedSec() + // << " seconds." << std::endl; auto applyResult = [&shapemap](ArrangeResult::value_type& group, @@ -505,29 +506,25 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb, // appropriately auto off = item.translation(); Radians rot = item.rotation(); - Pointf foff(off.X*SCALING_FACTOR, + Pointf foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR); // write the tranformation data into the model instance inst_ptr->rotation = rot; inst_ptr->offset = foff; - inst_ptr->offset_z = -batch_offset; } }; - std::cout << "Applying result..." << std::endl; - bench.start(); + // std::cout << "Applying result..." << std::endl; + // bench.start(); if(first_bin_only) { applyResult(result.front(), 0); } else { const auto STRIDE_PADDING = 1.2; - const auto MIN_STRIDE = 100; - - auto h = STRIDE_PADDING * model.bounding_box().size().z; - h = h < MIN_STRIDE ? MIN_STRIDE : h; - Coord stride = static_cast(h); + Coord stride = static_cast(STRIDE_PADDING* + bin.width()*SCALING_FACTOR); Coord batch_offset = 0; for(auto& group : result) { @@ -539,9 +536,9 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb, batch_offset += stride; } } - bench.stop(); - std::cout << "Result applied in " << bench.getElapsedSec() - << " seconds." << std::endl; + // bench.stop(); + // std::cout << "Result applied in " << bench.getElapsedSec() + // << " seconds." << std::endl; for(auto objptr : model.objects) objptr->invalidate_bounding_box(); @@ -556,8 +553,7 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb, { bool ret = false; if(bb != nullptr && bb->defined) { - const bool FIRST_BIN_ONLY = false; - ret = arr::arrange(*this, dist, bb, FIRST_BIN_ONLY, progressind); + ret = arr::arrange(*this, dist, bb, false, progressind); } else { // get the (transformed) size of each instance so that we take // into account their different transformations when packing @@ -1266,7 +1262,7 @@ void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) cons mesh->rotate_z(this->rotation); // rotate around mesh origin mesh->scale(this->scaling_factor); // scale around mesh origin if (!dont_translate) - mesh->translate(this->offset.x, this->offset.y, this->offset_z); + mesh->translate(this->offset.x, this->offset.y, 0); } BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 8fd225a83b..3337f4d9ad 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -206,7 +206,6 @@ public: double rotation; // Rotation around the Z axis, in radians around mesh center point double scaling_factor; Pointf offset; // in unscaled coordinates - double offset_z = 0; ModelObject* get_object() const { return this->object; } diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index bd7a2e7027..06e2cd0934 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -1,6 +1,7 @@ #include "AppController.hpp" #include +#include #include #include #include @@ -9,6 +10,7 @@ #include #include +#include #include #include #include @@ -58,14 +60,18 @@ void AppControllerBoilerplate::progress_indicator( progressind_->m.unlock(); } -void AppControllerBoilerplate::progress_indicator(unsigned statenum, - const std::string &title, - const std::string &firstmsg) +AppControllerBoilerplate::ProgresIndicatorPtr +AppControllerBoilerplate::progress_indicator( + unsigned statenum, + const std::string &title, + const std::string &firstmsg) { progressind_->m.lock(); - progressind_->store[std::this_thread::get_id()] = + auto ret = progressind_->store[std::this_thread::get_id()] = create_progress_indicator(statenum, title, firstmsg);; progressind_->m.unlock(); + + return ret; } AppControllerBoilerplate::ProgresIndicatorPtr @@ -266,6 +272,11 @@ void PrintController::slice() Slic3r::trace(3, "Slicing process finished."); } +const PrintConfig &PrintController::config() const +{ + return print_->config; +} + void IProgressIndicator::message_fmt( const std::string &fmtstr, ...) { std::stringstream ss; @@ -295,19 +306,46 @@ void IProgressIndicator::message_fmt( void AppController::arrange_model() { - std::async(supports_asynch()? std::launch::async : std::launch::deferred, + auto ftr = std::async( + supports_asynch()? std::launch::async : std::launch::deferred, [this]() { -// auto pind = progress_indicator(); + unsigned count = 0; + for(auto obj : model_->objects) count += obj->instances.size(); - // my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($self->{config}->bed_shape); - // my $success = $self->{model}->arrange_objects(wxTheApp->{preset_bundle}->full_config->min_object_distance, $bb); -// double dist = GUI::get_preset_bundle()->full_config().option("min_object_distance")->getFloat(); + auto pind = progress_indicator(); + auto pmax = pind->max(); -// std::cout << dist << std::endl; + // Set the range of the progress to the object count + pind->max(count); - std::cout << "ITTT vagyok" << std::endl; + auto dist = print_ctl()->config().min_object_distance(); + + BoundingBoxf bb(print_ctl()->config().bed_shape.values); + + pind->update(0, "Arranging objects..."); + + try { + model_->arrange_objects(dist, &bb, [pind, count](unsigned rem){ + pind->update(count - rem, "Arranging objects..."); + }); + } catch(std::exception& e) { + std::cerr << e.what() << std::endl; + report_issue(IssueType::ERR, + "Could not arrange model objects! " + "Some geometries may be invalid.", + "Exception occurred"); + } + + // Restore previous max value + pind->max(pmax); + pind->update(0, "Arranging done."); }); + + while( ftr.wait_for(std::chrono::milliseconds(10)) + != std::future_status::ready) { + process_events(); + } } } diff --git a/xs/src/slic3r/AppController.hpp b/xs/src/slic3r/AppController.hpp index 1dc825526c..9b4ff913cf 100644 --- a/xs/src/slic3r/AppController.hpp +++ b/xs/src/slic3r/AppController.hpp @@ -14,6 +14,7 @@ namespace Slic3r { class Model; class Print; class PrintObject; +class PrintConfig; /** * @brief A boilerplate class for creating application logic. It should provide @@ -108,9 +109,9 @@ public: * @param title The title of the procedure. * @param firstmsg The message for the first subtask to be displayed. */ - void progress_indicator(unsigned statenum, - const std::string& title, - const std::string& firstmsg = ""); + ProgresIndicatorPtr progress_indicator(unsigned statenum, + const std::string& title, + const std::string& firstmsg = ""); /** * @brief Return the progress indicator set up for the current thread. This @@ -147,6 +148,8 @@ public: */ bool supports_asynch() const; + void process_events(); + protected: /** @@ -205,6 +208,8 @@ public: * @brief Slice the loaded print scene. */ void slice(); + + const PrintConfig& config() const; }; /** diff --git a/xs/src/slic3r/AppControllerWx.cpp b/xs/src/slic3r/AppControllerWx.cpp index c54c02d55b..836a48996e 100644 --- a/xs/src/slic3r/AppControllerWx.cpp +++ b/xs/src/slic3r/AppControllerWx.cpp @@ -25,6 +25,11 @@ bool AppControllerBoilerplate::supports_asynch() const return true; } +void AppControllerBoilerplate::process_events() +{ + wxSafeYield(); +} + AppControllerBoilerplate::PathList AppControllerBoilerplate::query_destination_paths( const std::string &title, @@ -79,7 +84,7 @@ bool AppControllerBoilerplate::report_issue(IssueType issuetype, case IssueType::FATAL: icon = wxICON_ERROR; } - auto ret = wxMessageBox(description, brief, icon | style); + auto ret = wxMessageBox(_(description), _(brief), icon | style); return ret != wxCANCEL; } @@ -216,7 +221,7 @@ class Wrapper: public IProgressIndicator, public wxEvtHandler { } void _state(unsigned st) { - if( st <= max() ) { + if( st <= IProgressIndicator::max() ) { Base::state(st); if(!gauge_->IsShown()) showProgress(true); @@ -253,7 +258,14 @@ public: } virtual void state(float val) override { - if(val >= 1.0) state(unsigned(val)); + state(unsigned(val)); + } + + virtual void max(float val) override { + if(val > 1.0) { + gauge_->SetRange(static_cast(val)); + IProgressIndicator::max(val); + } } void state(unsigned st) { @@ -261,7 +273,9 @@ public: auto evt = new wxCommandEvent(PROGRESS_STATUS_UPDATE_EVENT, id_); evt->SetInt(st); wxQueueEvent(this, evt); - } else _state(st); + } else { + _state(st); + } } virtual void message(const std::string & msg) override {