#ifndef slic3r_GLGizmoSimplify_hpp_ #define slic3r_GLGizmoSimplify_hpp_ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, // which overrides our localization "L" macro. #include "GLGizmoBase.hpp" #include "slic3r/GUI/3DScene.hpp" #include "admesh/stl.h" // indexed_triangle_set #include #include namespace Slic3r { class ModelVolume; class Model; namespace GUI { class NotificationManager; // for simplify suggestion class GLGizmoSimplify: public GLGizmoBase { public: GLGizmoSimplify(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoSimplify(); bool on_esc_key_down(); static void add_simplify_suggestion_notification( const std::vector &object_ids, const std::vector & objects, NotificationManager & manager); protected: virtual std::string on_get_name() const override; virtual std::string on_get_name_str() override { return "Simplify"; } virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual bool on_is_activable() const override; virtual bool on_is_selectable() const override { return false; } virtual void on_set_state() override; // must implement virtual bool on_init() override { return true;}; virtual void on_render() override; virtual void on_render_for_picking() override{}; CommonGizmosDataID on_get_requirements() const override; private: void apply_simplify(); void close(); void process(); void stop_worker_thread_request(); void worker_finished(); void create_gui_cfg(); void request_rerender(bool force = false); void init_model(const indexed_triangle_set& its); void set_center_position(); struct Configuration { bool use_count = false; float decimate_ratio = 50.f; // in percent uint32_t wanted_count = 0; // initialize by percents float max_error = 1.; // maximal quadric error void fix_count_by_ratio(size_t triangle_count); bool operator==(const Configuration& rhs) { return (use_count == rhs.use_count && decimate_ratio == rhs.decimate_ratio && wanted_count == rhs.wanted_count && max_error == rhs.max_error); } bool operator!=(const Configuration& rhs) { return ! (*this == rhs); } }; Configuration m_configuration; bool m_move_to_center; // opening gizmo const ModelVolume *m_volume; // keep pointer to actual working volume bool m_show_wireframe; GLModel m_glmodel; size_t m_triangle_count; // triangle count of the model currently shown // Timestamp of the last rerender request. Only accessed from UI thread. int64_t m_last_rerender_timestamp = std::numeric_limits::min(); // Following struct is accessed by both UI and worker thread. // Accesses protected by a mutex. struct State { enum Status { idle, running, cancelling }; Status status = idle; int progress = 0; // percent of done work Configuration config; // Configuration we started with. const ModelVolume* mv = nullptr; std::unique_ptr result; }; std::thread m_worker; std::mutex m_state_mutex; // guards m_state State m_state; // accessed by both threads // This configs holds GUI layout size given by translated texts. // etc. When language changes, GUI is recreated and this class constructed again, // so the change takes effect. (info by GLGizmoFdmSupports.hpp) struct GuiCfg { int top_left_width = 100; int bottom_left_width = 100; int input_width = 100; int window_offset_x = 100; int window_offset_y = 100; int window_padding = 0; // trunc model name when longer size_t max_char_in_name = 30; // to prevent freezing when move in gui // delay before process in [ms] std::chrono::duration prcess_delay = std::chrono::milliseconds(250); }; std::optional m_gui_cfg; // translations used for calc window size const std::string tr_mesh_name; const std::string tr_triangles; const std::string tr_detail_level; const std::string tr_decimate_ratio; // cancel exception class SimplifyCanceledException: public std::exception { public: const char *what() const throw() { return L("Model simplification has been canceled"); } }; }; } // namespace GUI } // namespace Slic3r #endif // slic3r_GLGizmoSimplify_hpp_