diff options
Diffstat (limited to 'src/slic3r/AppController.cpp')
-rw-r--r-- | src/slic3r/AppController.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/slic3r/AppController.cpp b/src/slic3r/AppController.cpp new file mode 100644 index 000000000..4a36b5d7f --- /dev/null +++ b/src/slic3r/AppController.cpp @@ -0,0 +1,167 @@ +#include "AppController.hpp" + +#include <future> +#include <chrono> +#include <sstream> +#include <cstdarg> +#include <thread> +#include <unordered_map> + +#include <slic3r/GUI/GUI.hpp> +#include <ModelArrange.hpp> +#include <slic3r/GUI/PresetBundle.hpp> + +#include <Geometry.hpp> +#include <PrintConfig.hpp> +#include <Print.hpp> +#include <Model.hpp> +#include <Utils.hpp> + +namespace Slic3r { + +class AppControllerBoilerplate::PriData { +public: + std::mutex m; + std::thread::id ui_thread; + + inline explicit PriData(std::thread::id uit): ui_thread(uit) {} +}; + +AppControllerBoilerplate::AppControllerBoilerplate() + :pri_data_(new PriData(std::this_thread::get_id())) {} + +AppControllerBoilerplate::~AppControllerBoilerplate() { + pri_data_.reset(); +} + +bool AppControllerBoilerplate::is_main_thread() const +{ + return pri_data_->ui_thread == std::this_thread::get_id(); +} + +namespace GUI { +PresetBundle* get_preset_bundle(); +} + +AppControllerBoilerplate::ProgresIndicatorPtr +AppControllerBoilerplate::global_progress_indicator() { + ProgresIndicatorPtr ret; + + pri_data_->m.lock(); + ret = global_progressind_; + pri_data_->m.unlock(); + + return ret; +} + +void AppControllerBoilerplate::global_progress_indicator( + AppControllerBoilerplate::ProgresIndicatorPtr gpri) +{ + pri_data_->m.lock(); + global_progressind_ = gpri; + pri_data_->m.unlock(); +} + +void ProgressIndicator::message_fmt( + const std::string &fmtstr, ...) { + std::stringstream ss; + va_list args; + va_start(args, fmtstr); + + auto fmt = fmtstr.begin(); + + while (*fmt != '\0') { + if (*fmt == 'd') { + int i = va_arg(args, int); + ss << i << '\n'; + } else if (*fmt == 'c') { + // note automatic conversion to integral type + int c = va_arg(args, int); + ss << static_cast<char>(c) << '\n'; + } else if (*fmt == 'f') { + double d = va_arg(args, double); + ss << d << '\n'; + } + ++fmt; + } + + va_end(args); + message(ss.str()); +} + +void AppController::arrange_model() +{ + using Coord = libnest2d::TCoord<libnest2d::PointImpl>; + + if(arranging_.load()) return; + + // to prevent UI reentrancies + arranging_.store(true); + + unsigned count = 0; + for(auto obj : model_->objects) count += obj->instances.size(); + + auto pind = global_progress_indicator(); + + float pmax = 1.0; + + if(pind) { + pmax = pind->max(); + + // Set the range of the progress to the object count + pind->max(count); + + pind->on_cancel([this](){ + arranging_.store(false); + }); + } + + auto dist = print_ctl()->config().min_object_distance(); + + // Create the arranger config + auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR); + + auto& bedpoints = print_ctl()->config().bed_shape.values; + Polyline bed; bed.points.reserve(bedpoints.size()); + for(auto& v : bedpoints) + bed.append(Point::new_scale(v(0), v(1))); + + if(pind) pind->update(0, L("Arranging objects...")); + + try { + arr::BedShapeHint hint; + // TODO: from Sasha from GUI + hint.type = arr::BedShapeType::WHO_KNOWS; + + arr::arrange(*model_, + min_obj_distance, + bed, + hint, + false, // create many piles not just one pile + [this, pind, count](unsigned rem) { + if(pind) + pind->update(count - rem, L("Arranging objects...")); + + process_events(); + }, [this] () { return !arranging_.load(); }); + } catch(std::exception& e) { + std::cerr << e.what() << std::endl; + report_issue(IssueType::ERR, + L("Could not arrange model objects! " + "Some geometries may be invalid."), + L("Exception occurred")); + } + + // Restore previous max value + if(pind) { + pind->max(pmax); + pind->update(0, arranging_.load() ? L("Arranging done.") : + L("Arranging canceled.")); + + pind->on_cancel(/*remove cancel function*/); + } + + arranging_.store(false); +} + +} |