#ifndef slic3r_GLGizmoAdvancedCut_hpp_ #define slic3r_GLGizmoAdvancedCut_hpp_ #include "GLGizmoBase.hpp" #include "GLGizmoRotate.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/CutUtils.hpp" namespace Slic3r { enum class CutConnectorType : int; class ModelVolume; struct CutConnectorAttributes; namespace GUI { enum class SLAGizmoEventType : unsigned char; namespace CommonGizmosDataObjects { class ObjectClipper; } class PartSelection { public: PartSelection() = default; PartSelection( const ModelObject *mo, const Transform3d &cut_matrix, int instance_idx, const Vec3d ¢er, const Vec3d &normal, const CommonGizmosDataObjects::ObjectClipper &oc); PartSelection(const ModelObject *mo, int instance_idx_in); ~PartSelection() { m_model.clear_objects(); for (size_t i = 0; i < m_cut_parts.size(); i++) { if (m_cut_parts[i].raycaster) { delete m_cut_parts[i].raycaster; } } } struct PartPara { GLModel glmodel; MeshRaycaster* raycaster; bool is_up_part; Transform3d trans; }; void part_render(const Vec3d *normal); void toggle_selection(const Vec2d &mouse_pos); void toggle_selection(int id); void turn_over_selection(); ModelObject* model_object() { return m_model.objects.front(); } bool valid() const { return m_valid; } bool is_one_object() const; const std::vector *get_ignored_contours_ptr() const { return (valid() ? &m_ignored_contours : nullptr); } std::vector get_cut_parts(); std::vector &get_parts() { return m_cut_parts; } bool has_modified_cut_parts(); private: Model m_model; int m_instance_idx; std::vector m_cut_parts; std::vector m_back_cut_parts_state; bool m_valid = false; std::vector, std::vector>> m_contour_to_parts; // for each contour, there is a vector of parts above and a vector of parts below std::vector m_ignored_contours; // contour that should not be rendered (the parts on both sides will both be parts of the same object) std::vector m_contour_points; // Debugging std::vector> m_debug_pts; // Debugging void add_object(const ModelObject *object); }; class GLGizmoAdvancedCut : public GLGizmoRotate3D { private: unsigned int m_last_active_item_imgui{0}; double m_snap_step{1.0}; // archived values Vec3d m_ar_plane_center{Vec3d::Zero()}; // plane_center and so on Vec3d m_plane_center{Vec3d::Zero()};//old name:m_cut_plane_center Vec3d m_plane_center_drag_start{Vec3d::Zero()}; Vec3d m_plane_drag_start{Vec3d::Zero()}; Vec3d m_bb_center{Vec3d::Zero()};//box center Vec3d m_center_offset{Vec3d::Zero()}; Vec3d m_plane_normal{Vec3d::UnitZ()}; //old namce:Vec3d m_cut_normal//m_cut_plane_normal Vec3d m_plane_x_direction{Vec3d::UnitY()}; Vec3d m_clp_normal{Vec3d::Ones()}; // data to check position of the cut palne center on gizmo activation Vec3d m_min_pos{Vec3d::Zero()}; Vec3d m_max_pos{Vec3d::Zero()}; static const double Offset; static const double Margin; static const std::array GrabberColor; static const std::array GrabberHoverColor; mutable double m_movement; double m_start_movement; double m_start_height; Vec3d m_rotation; Vec3d m_buffered_rotation; double m_buffered_movement; double m_buffered_height; Vec3d m_drag_pos_start; bool m_keep_upper; bool m_keep_lower; bool m_cut_to_parts{false}; bool m_place_on_cut_upper{true}; bool m_place_on_cut_lower{false}; bool m_rotate_upper{false}; bool m_rotate_lower{false}; bool m_do_segment; double m_segment_smoothing_alpha; int m_segment_number; mutable Grabber m_move_z_grabber; mutable Grabber m_move_x_grabber; bool m_connectors_editing{false}; bool m_add_connector_ok{false}; std::vector m_invalid_connectors_idxs; bool m_show_shortcuts{false}; std::vector> m_connector_shortcuts; std::vector> m_cut_plane_shortcuts; std::vector> m_cut_groove_shortcuts; double m_label_width{150.0}; double m_control_width{ 200.0 }; double m_editing_window_width; CutMode m_cut_mode{CutMode::cutPlanar}; CutConnectorType m_connector_type; size_t m_connector_style; size_t m_connector_shape_id; // Dovetail para Groove m_groove; bool m_groove_editing{false}; float m_contour_width{0.4f}; float m_cut_plane_radius_koef{1.5f}; float m_shortcut_label_width{-1.f}; bool m_is_slider_editing_done{false}; bool m_hide_cut_plane{false}; double m_radius{0.0}; double m_grabber_radius{0.0}; double m_grabber_connection_len{0.0}; Vec3d m_cut_plane_start_move_pos{Vec3d::Zero()}; bool m_cut_plane_as_circle{false}; std::vector m_groove_vertices; bool m_was_cut_plane_dragged{false}; bool m_was_contour_selected{false}; bool m_is_dragging{false}; std::shared_ptr m_part_selection{nullptr}; // dragging angel in hovered axes double m_rotate_angle{0.0}; bool m_imperial_units{false}; BoundingBoxf3 m_bounding_box; BoundingBoxf3 m_transformed_bounding_box; float m_connector_depth_ratio{3.f}; float m_connector_depth_ratio_tolerance{CUT_TOLERANCE}; float m_connector_size{2.5f}; float m_connector_size_tolerance{CUT_TOLERANCE}; // Input params for cut with snaps float m_snap_space_proportion{0.3f}; float m_snap_bulge_proportion{0.15f}; TriangleMesh m_connector_mesh; // remember the connectors which is selected mutable std::vector m_selected; int m_selected_count{0}; GLModel m_plane; // old name:PickingModel Vec3d m_cut_line_begin{Vec3d::Zero()}; Vec3d m_cut_line_end{Vec3d::Zero()}; Transform3d m_rotate_matrix{Transform3d::Identity()}; Transform3d m_start_dragging_m{Transform3d::Identity()}; std::map m_shapes; struct InvalidConnectorsStatistics { unsigned int outside_cut_contour; unsigned int outside_bb; bool is_overlap; void invalidate() { outside_cut_contour = 0; outside_bb = 0; is_overlap = false; } } m_info_stats; //GLSelectionRectangle m_selection_rectangle; public: GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); bool on_key(wxKeyEvent &evt); double get_movement() const { return m_movement; } void finish_rotation(); std::string get_tooltip() const override; BoundingBoxf3 bounding_box() const; BoundingBoxf3 transformed_bounding_box(const Vec3d &plane_center, const Transform3d &rotation_m = Transform3d::Identity()) const; bool is_looking_forward() const; bool unproject_on_cut_plane(const Vec2d &mouse_pos, Vec3d &pos, Vec3d &pos_world, bool respect_contours = true); virtual bool apply_clipping_plane() { return m_connectors_editing; } protected: virtual bool on_init(); virtual void on_load(cereal::BinaryInputArchive &ar) override; virtual void on_save(cereal::BinaryOutputArchive &ar) const override; virtual void data_changed(bool is_serializing) override; virtual std::string on_get_name() const; virtual std::string on_get_name_str() override { return "Cut"; } virtual void on_set_state(); virtual bool on_is_activable() const; virtual CommonGizmosDataID on_get_requirements() const override; virtual void on_start_dragging() override; virtual void on_stop_dragging() override; virtual void update_plate_center(Axis axis_type, double projection, bool is_abs_move); // old name:dragging_grabber_move virtual void update_plate_normal_boundingbox_clipper(const Transform3d &rotation_tmp); // old name:dragging_grabber_rotation virtual void on_update(const UpdateData& data); virtual void on_render(); virtual void on_render_for_picking(); virtual void on_render_input_window(float x, float y, float bottom_limit); void show_tooltip_information(float x, float y); virtual void on_enable_grabber(unsigned int id) { if (id < 3) m_gizmos[id].enable_grabber(0); else if (id == 3) this->enable_grabber(0); } virtual void on_disable_grabber(unsigned int id) { if (id < 3) m_gizmos[id].disable_grabber(0); else if (id == 3) this->disable_grabber(0); } virtual void on_set_hover_id() { for (int i = 0; i < 3; ++i) m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); } private: void perform_cut(const Selection& selection); bool can_perform_cut() const; void apply_connectors_in_model(ModelObject *mo, int &dowels_count); bool is_selection_changed(bool alt_down, bool shift_down); void select_connector(int idx, bool select); double calc_projection(const Vec3d &drag_pos, const Linef3 &mouse_ray, const Vec3d &project_dir) const; Vec3d get_plane_normal() const; Vec3d get_plane_center() const; void reset_cut_plane(); void reset_all(); // update the connectors position so that the connectors are on the cut plane void put_connectors_on_cut_plane(const Vec3d &cp_normal, double cp_offset); void update_plane_normal(); void update_clipper(); // on render void render_cut_plane_and_grabbers(); void on_render_rotate_gizmos(); void render_connectors(); void render_clipper_cut(); void render_cut_line(); void clear_selection(); void init_connector_shapes(); void set_connectors_editing(bool connectors_editing); void reset_connectors(); void update_connector_shape(); void apply_selected_connectors(std::function apply_fn); void select_all_connectors(); void unselect_all_connectors(); void validate_connector_settings(); bool add_connector(CutConnectors &connectors, const Vec2d &mouse_position); bool delete_selected_connectors(); bool is_outside_of_cut_contour(size_t idx, const CutConnectors &connectors, const Vec3d cur_pos); bool is_conflict_for_connector(size_t idx, const CutConnectors &connectors, const Vec3d cur_pos); //deal groove void switch_to_mode(CutMode new_mode); void flip_cut_plane(); void update_plane_model(); void init_picking_models(); bool has_valid_groove() const; bool has_valid_contour() const; void reset_cut_by_contours(); void process_contours(); void toggle_model_objects_visibility(bool show_in_3d = false); void deal_connector_pos_by_type(Vec3d &pos, float &height, CutConnectorType, CutConnectorStyle, bool looking_forward, bool is_edit, const Vec3d &clp_normal); void update_bb(); void check_and_update_connectors_state(); void set_center(const Vec3d ¢er, bool update_tbb = false); bool set_center_pos(const Vec3d ¢er_pos, bool update_tbb = false); void invalidate_cut_plane(); void rotate_vec3d_around_plane_center(Vec3d &vec, const Transform3d &rotate_matrix, const Vec3d ¢er); Transform3d get_cut_matrix(const Selection &selection); // render input window void update_buffer_data(); bool render_cut_mode_combo(double label_width,float item_width); void render_color_marker(float size, const ColorRGBA &color); void render_cut_plane_input_window(float x, float y, float bottom_limit); void init_connectors_input_window_data(); void render_connectors_input_window(float x, float y, float bottom_limit); void render_input_window_warning() const; bool render_reset_button(const std::string &label_id, const std::string &tooltip) const; bool render_connect_type_radio_button(CutConnectorType type); bool render_slider_double_input(const std::string &label, float &value_in, float &tolerance_in); bool render_slider_double_input_by_format(const std::string &label, float &value_in, float value_min, float value_max, DoubleShowType show_type = DoubleShowType::Normal); bool cut_line_processing() const; void discard_cut_line_processing(); bool process_cut_line(SLAGizmoEventType action, const Vec2d &mouse_position); }; } // namespace GUI } // namespace Slic3r #endif // slic3r_GLGizmoAdvancedCut_hpp_