Cut: Initial porting of Cut Gizmo

This commit is contained in:
enricoturri1966 2023-10-31 23:01:05 +08:00 committed by Noisyfox
parent ce2836a7f9
commit 18406c31c0
34 changed files with 5638 additions and 1361 deletions

View file

@ -411,6 +411,12 @@ private:
// plane coeffs for clipping in shaders
std::array<double, 4> m_clipping_plane;
// plane coeffs for render volumes with different colors in shaders
// used by cut gizmo
std::array<double, 4> m_color_clip_plane;
bool m_use_color_clip_plane{ false };
std::array<ColorRGBA, 2> m_color_clip_plane_colors{ ColorRGBA::RED(), ColorRGBA::BLUE() };
struct Slope
{
// toggle for slope rendering
@ -482,6 +488,14 @@ public:
const std::array<float, 2>& get_z_range() const { return m_z_range; }
const std::array<double, 4>& get_clipping_plane() const { return m_clipping_plane; }
void set_use_color_clip_plane(bool use) { m_use_color_clip_plane = use; }
void set_color_clip_plane(const Vec3d& cp_normal, double offset) {
for (int i = 0; i < 3; ++i)
m_color_clip_plane[i] = -cp_normal[i];
m_color_clip_plane[3] = offset;
}
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_color_clip_plane_colors = colors; }
bool is_slope_GlobalActive() const { return m_slope.isGlobalActive; }
bool is_slope_active() const { return m_slope.active; }
void set_slope_active(bool active) { m_slope.active = active; }

View file

@ -807,6 +807,10 @@ public:
bool get_use_clipping_planes() const { return m_use_clipping_planes; }
const std::array<ClippingPlane, 2> &get_clipping_planes() const { return m_clipping_planes; };
void set_use_color_clip_plane(bool use) { m_volumes.set_use_color_clip_plane(use); }
void set_color_clip_plane(const Vec3d& cp_normal, double offset) { m_volumes.set_color_clip_plane(cp_normal, offset); }
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_volumes.set_color_clip_plane_colors(colors); }
void refresh_camera_scene_box();
BoundingBoxf3 volumes_bounding_box(bool current_plate_only = false) const;

View file

@ -1,5 +1,10 @@
///|/ Copyright (c) Prusa Research 2019 - 2022 Enrico Turri @enricoturri1966, Filip Sykala @Jony01, Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "GLSelectionRectangle.hpp"
#include "Camera.hpp"
#include "CameraUtils.hpp"
#include "3DScene.hpp"
#include "GLCanvas3D.hpp"
#include "GUI_App.hpp"
@ -29,35 +34,19 @@ namespace GUI {
m_end_corner = mouse_position;
}
std::vector<unsigned int> GLSelectionRectangle::stop_dragging(const GLCanvas3D& canvas, const std::vector<Vec3d>& points)
std::vector<unsigned int> GLSelectionRectangle::contains(const std::vector<Vec3d>& points) const
{
std::vector<unsigned int> out;
if (!is_dragging())
return out;
m_state = Off;
const Camera& camera = wxGetApp().plater()->get_camera();
Matrix4d modelview = camera.get_view_matrix().matrix();
Matrix4d projection= camera.get_projection_matrix().matrix();
Vec4i viewport(camera.get_viewport().data());
// Convert our std::vector to Eigen dynamic matrix.
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign> pts(points.size(), 3);
for (size_t i=0; i<points.size(); ++i)
pts.block<1, 3>(i, 0) = points[i];
// Get the projections.
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign> projections;
igl::project(pts, modelview, projection, viewport, projections);
// bounding box created from the rectangle corners - will take care of order of the corners
BoundingBox rectangle(Points{ Point(m_start_corner.cast<coord_t>()), Point(m_end_corner.cast<coord_t>()) });
const BoundingBox rectangle(Points{ Point(m_start_corner.cast<coord_t>()), Point(m_end_corner.cast<coord_t>()) });
// Iterate over all points and determine whether they're in the rectangle.
for (int i = 0; i<projections.rows(); ++i)
if (rectangle.contains(Point(projections(i, 0), canvas.get_canvas_size().get_height() - projections(i, 1))))
const Camera &camera = wxGetApp().plater()->get_camera();
Points points_2d = CameraUtils::project(camera, points);
unsigned int size = static_cast<unsigned int>(points.size());
for (unsigned int i = 0; i< size; ++i)
if (rectangle.contains(points_2d[i]))
out.push_back(i);
return out;

View file

@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2019 - 2022 Enrico Turri @enricoturri1966, Lukáš Matěna @lukasmatena
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GLSelectionRectangle_hpp_
#define slic3r_GLSelectionRectangle_hpp_
@ -25,8 +29,8 @@ public:
void dragging(const Vec2d& mouse_position);
// Given a vector of points in world coordinates, the function returns indices of those
// that are in the rectangle. It then disables the rectangle.
std::vector<unsigned int> stop_dragging(const GLCanvas3D& canvas, const std::vector<Vec3d>& points);
// that are in the rectangle.
std::vector<unsigned int> contains(const std::vector<Vec3d>& points) const;
// Disables the rectangle.
void stop_dragging();

View file

@ -2811,7 +2811,7 @@ void ObjectList::merge(bool to_multipart_object)
}
}
void ObjectList::merge_volumes()
/*void ObjectList::merge_volumes()
{
std::vector<int> obj_idxs, vol_idxs;
get_selection_indexes(obj_idxs, vol_idxs);
@ -2839,11 +2839,11 @@ void ObjectList::merge_volumes()
else {
for (int vol_idx : vol_idxs)
selection.add_volume(last_obj_idx, vol_idx, 0, false);
}*/
}#1#
#else
wxGetApp().plater()->merge(obj_idxs[0], vol_idxs);
#endif
}
}*/
void ObjectList::layers_editing()
{

View file

@ -297,7 +297,7 @@ public:
void del_info_item(const int obj_idx, InfoItemType type);
void split();
void merge(bool to_multipart_object);
void merge_volumes(); // BBS: merge parts to single part
// void merge_volumes(); // BBS: merge parts to single part
void layers_editing();
void boolean(); // BBS: Boolean Operation of parts

View file

@ -222,6 +222,9 @@ public:
void register_raycasters_for_picking() { register_grabbers_for_picking(); on_register_raycasters_for_picking(); }
void unregister_raycasters_for_picking() { unregister_grabbers_for_picking(); on_unregister_raycasters_for_picking(); }
virtual bool is_in_editing_mode() const { return false; }
virtual bool is_selection_rectangle_dragging() const { return false; }
protected:
float last_input_window_width = 0;
virtual bool on_init() = 0;

File diff suppressed because it is too large Load diff

View file

@ -1,72 +1,391 @@
///|/ Copyright (c) Prusa Research 2019 - 2023 Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Enrico Turri @enricoturri1966, Filip Sykala @Jony01, Vojtěch Bubník @bubnikv
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GLGizmoCut_hpp_
#define slic3r_GLGizmoCut_hpp_
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLSelectionRectangle.hpp"
#include "slic3r/GUI/GLModel.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/ObjectID.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/CutUtils.hpp"
#include "imgui/imgui.h"
namespace Slic3r {
enum class CutConnectorType : int;
class ModelVolume;
class GLShaderProgram;
struct CutConnectorAttributes;
namespace GUI {
class Selection;
class GLGizmoCut : public GLGizmoBase
enum class SLAGizmoEventType : unsigned char;
namespace CommonGizmosDataObjects { class ObjectClipper; }
class GLGizmoCut3D : public GLGizmoBase
{
static const double Offset;
static const double Margin;
double m_cut_z{ 0.0 };
double m_max_z{ 0.0 };
double m_start_z{ 0.0 };
Vec3d m_drag_pos;
Vec3d m_drag_center;
bool m_keep_upper{ true };
bool m_keep_lower{ true };
bool m_rotate_lower{ false };
// BBS: m_do_segment
bool m_cut_to_parts {false};
bool m_do_segment{ false };
double m_segment_smoothing_alpha{ 0.5 };
int m_segment_number{ 5 };
struct CutContours
{
TriangleMesh mesh;
GLModel contours;
double cut_z{ 0.0 };
Vec3d position{ Vec3d::Zero() };
Vec3d shift{ Vec3d::Zero() };
ObjectID object_id;
int instance_idx{ -1 };
enum GrabberID {
X = 0,
Y,
Z,
CutPlane,
CutPlaneZRotation,
CutPlaneXMove,
CutPlaneYMove,
Count,
};
CutContours m_cut_contours;
Transform3d m_rotation_m{ Transform3d::Identity() };
double m_snap_step{ 1.0 };
int m_connectors_group_id;
// archived values
Vec3d m_ar_plane_center { Vec3d::Zero() };
Transform3d m_start_dragging_m{ Transform3d::Identity() };
Vec3d m_plane_center{ Vec3d::Zero() };
// data to check position of the cut palne center on gizmo activation
Vec3d m_min_pos{ Vec3d::Zero() };
Vec3d m_max_pos{ Vec3d::Zero() };
Vec3d m_bb_center{ Vec3d::Zero() };
Vec3d m_center_offset{ Vec3d::Zero() };
BoundingBoxf3 m_bounding_box;
BoundingBoxf3 m_transformed_bounding_box;
// values from RotationGizmo
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()};
double m_snap_coarse_in_radius{ 0.0 };
double m_snap_coarse_out_radius{ 0.0 };
double m_snap_fine_in_radius{ 0.0 };
double m_snap_fine_out_radius{ 0.0 };
// dragging angel in hovered axes
double m_angle{ 0.0 };
TriangleMesh m_connector_mesh;
// workaround for using of the clipping plane normal
Vec3d m_clp_normal{ Vec3d::Ones() };
Vec3d m_line_beg{ Vec3d::Zero() };
Vec3d m_line_end{ Vec3d::Zero() };
Vec2d m_ldown_mouse_position{ Vec2d::Zero() };
GLModel m_grabber_connection;
GLModel m_cut_line;
PickingModel m_plane;
PickingModel m_sphere;
PickingModel m_cone;
PickingModel m_cube;
std::map<CutConnectorAttributes, PickingModel> m_shapes;
std::vector<std::shared_ptr<SceneRaycasterItem>> m_raycasters;
GLModel m_circle;
GLModel m_scale;
GLModel m_snap_radii;
GLModel m_reference_radius;
GLModel m_angle_arc;
Vec3d m_old_center;
Vec3d m_cut_normal;
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;
bool m_keep_upper{ true };
bool m_keep_lower{ true };
bool m_keep_as_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 };
// Input params for cut with tongue and groove
Cut::Groove m_groove;
bool m_groove_editing { false };
bool m_is_slider_editing_done { false };
// Input params for cut with snaps
float m_snap_bulge_proportion{ 0.15f };
float m_snap_space_proportion{ 0.3f };
bool m_hide_cut_plane{ false };
bool m_connectors_editing{ false };
bool m_cut_plane_as_circle{ false };
float m_connector_depth_ratio{ 3.f };
float m_connector_size{ 2.5f };
float m_connector_angle{ 0.f };
float m_connector_depth_ratio_tolerance{ 0.1f };
float m_connector_size_tolerance{ 0.f };
float m_label_width{ 0.f };
float m_control_width{ 200.f };
bool m_imperial_units{ false };
float m_contour_width{ 0.4f };
float m_cut_plane_radius_koef{ 1.5f };
float m_shortcut_label_width{ -1.f };
mutable std::vector<bool> m_selected; // which pins are currently selected
int m_selected_count{ 0 };
GLSelectionRectangle m_selection_rectangle;
std::vector<size_t> m_invalid_connectors_idxs;
bool m_was_cut_plane_dragged { false };
bool m_was_contour_selected { false };
// Vertices of the groove used to detection if groove is valid
std::vector<Vec3d> m_groove_vertices;
class PartSelection {
public:
PartSelection() = default;
PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc);
PartSelection(const ModelObject* mo, int instance_idx_in);
~PartSelection() { m_model.clear_objects(); }
struct Part {
GLModel glmodel;
MeshRaycaster raycaster;
bool selected;
bool is_modifier;
};
void render(const Vec3d* normal, GLModel& sphere_model);
void toggle_selection(const Vec2d& mouse_pos);
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<Part>& parts() const { return m_parts; }
const std::vector<size_t>* get_ignored_contours_ptr() const { return (valid() ? &m_ignored_contours : nullptr); }
std::vector<Cut::Part> get_cut_parts();
private:
Model m_model;
int m_instance_idx;
std::vector<Part> m_parts;
bool m_valid = false;
std::vector<std::pair<std::vector<size_t>, std::vector<size_t>>> m_contour_to_parts; // for each contour, there is a vector of parts above and a vector of parts below
std::vector<size_t> m_ignored_contours; // contour that should not be rendered (the parts on both sides will both be parts of the same object)
std::vector<Vec3d> m_contour_points; // Debugging
std::vector<std::vector<Vec3d>> m_debug_pts; // Debugging
void add_object(const ModelObject* object);
};
PartSelection m_part_selection;
bool m_show_shortcuts{ false };
std::vector<std::pair<wxString, wxString>> m_shortcuts;
enum class CutMode {
cutPlanar
, cutTongueAndGroove
//, cutGrig
//,cutRadial
//,cutModular
};
enum class CutConnectorMode {
Auto
, Manual
};
std::vector<std::string> m_modes;
size_t m_mode{ size_t(CutMode::cutPlanar) };
std::vector<std::string> m_connector_modes;
CutConnectorMode m_connector_mode{ CutConnectorMode::Manual };
std::vector<std::string> m_connector_types;
CutConnectorType m_connector_type;
std::vector<std::string> m_connector_styles;
int m_connector_style;
std::vector<std::string> m_connector_shapes;
int m_connector_shape_id;
std::vector<std::string> m_axis_names;
std::map<std::string, wxString> m_part_orientation_names;
std::map<std::string, std::string> m_labels_map;
public:
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
double get_cut_z() const { return m_cut_z; }
void set_cut_z(double cut_z);
GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
std::string get_tooltip() const override;
bool unproject_on_cut_plane(const Vec2d& mouse_pos, Vec3d& pos, Vec3d& pos_world, bool respect_contours = true);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
bool is_in_editing_mode() const override { return m_connectors_editing; }
bool is_selection_rectangle_dragging() const override { return m_selection_rectangle.is_dragging(); }
bool is_looking_forward() const;
/// <summary>
/// Drag of plane
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
void shift_cut(double delta);
void rotate_vec3d_around_plane_center(Vec3d&vec);
void put_connectors_on_cut_plane(const Vec3d& cp_normal, double cp_offset);
void update_clipper();
void invalidate_cut_plane();
BoundingBoxf3 bounding_box() const;
BoundingBoxf3 transformed_bounding_box(const Vec3d& plane_center, const Transform3d& rotation_m = Transform3d::Identity()) const;
protected:
virtual bool on_init() override;
virtual void on_load(cereal::BinaryInputArchive& ar) override { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
virtual void on_save(cereal::BinaryOutputArchive& ar) const override { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
virtual std::string on_get_name() const override;
virtual void on_set_state() override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_update(const UpdateData& data) override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
bool on_init() override;
void on_load(cereal::BinaryInputArchive&ar) override;
void on_save(cereal::BinaryOutputArchive&ar) const override;
std::string on_get_name() const override;
void on_set_state() override;
CommonGizmosDataID on_get_requirements() const override;
void on_set_hover_id() override;
bool on_is_activable() const override;
bool on_is_selectable() const override;
Vec3d mouse_position_in_local_plane(GrabberID axis, const Linef3&mouse_ray) const;
void dragging_grabber_move(const GLGizmoBase::UpdateData &data);
void dragging_grabber_rotation(const GLGizmoBase::UpdateData &data);
void dragging_connector(const GLGizmoBase::UpdateData &data);
void on_dragging(const UpdateData&data) override;
void on_start_dragging() override;
void on_stop_dragging() override;
void on_render() override;
void render_debug_input_window(float x);
void adjust_window_position(float x, float y, float bottom_limit);
void unselect_all_connectors();
void select_all_connectors();
void render_shortcuts();
void apply_selected_connectors(std::function<void(size_t idx)> apply_fn);
void render_connectors_input_window(CutConnectors &connectors);
void render_build_size();
void reset_cut_plane();
void set_connectors_editing(bool connectors_editing);
void flip_cut_plane();
void process_contours();
void reset_cut_by_contours();
void render_flip_plane_button(bool disable_pred = false);
void add_vertical_scaled_interval(float interval);
void add_horizontal_scaled_interval(float interval);
void add_horizontal_shift(float shift);
void render_color_marker(float size, const ImU32& color);
void render_groove_float_input(const std::string &label, float &in_val, const float &init_val, float &in_tolerance);
void render_groove_angle_input(const std::string &label, float &in_val, const float &init_val, float min_val, float max_val);
bool render_angle_input(const std::string& label, float& in_val, const float& init_val, float min_val, float max_val);
void render_snap_specific_input(const std::string& label, const wxString& tooltip, float& in_val, const float& init_val, const float min_val, const float max_val);
void render_cut_plane_input_window(CutConnectors &connectors);
void init_input_window_data(CutConnectors &connectors);
void render_input_window_warning() const;
bool add_connector(CutConnectors&connectors, const Vec2d&mouse_position);
bool delete_selected_connectors(CutConnectors&connectors);
void select_connector(int idx, bool select);
bool is_selection_changed(bool alt_down, bool shift_down);
void process_selection_rectangle(CutConnectors &connectors);
virtual void on_register_raycasters_for_picking() override;
virtual void on_unregister_raycasters_for_picking() override;
void update_raycasters_for_picking();
void set_volumes_picking_state(bool state);
void update_raycasters_for_picking_transform();
void update_plane_model();
void on_render_input_window(float x, float y, float bottom_limit) override;
bool wants_enter_leave_snapshots() const override { return true; }
std::string get_gizmo_entering_text() const override { return _u8L("Entering Cut gizmo"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Cut gizmo"); }
std::string get_action_snapshot_name() const override { return _u8L("Cut gizmo editing"); }
void data_changed(bool is_serializing) override;
Transform3d get_cut_matrix(const Selection& selection);
private:
void perform_cut(const Selection& selection);
double calc_projection(const Linef3& mouse_ray) const;
BoundingBoxf3 bounding_box() const;
void update_contours();
void set_center(const Vec3d&center, bool update_tbb = false);
void switch_to_mode(size_t new_mode);
bool render_cut_mode_combo();
bool render_combo(const std::string&label, const std::vector<std::string>&lines, int&selection_idx);
bool render_double_input(const std::string& label, double& value_in);
bool render_slider_double_input(const std::string& label, float& value_in, float& tolerance_in, float min_val = -0.1f, float max_tolerance = -0.1f);
void render_move_center_input(int axis);
void render_connect_mode_radio_button(CutConnectorMode mode);
bool render_reset_button(const std::string& label_id, const std::string& tooltip) const;
bool render_connect_type_radio_button(CutConnectorType type);
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);
void render_connectors();
bool can_perform_cut() const;
bool has_valid_groove() const;
bool has_valid_contour() const;
void apply_connectors_in_model(ModelObject* mo, int &dowels_count);
bool cut_line_processing() const;
void discard_cut_line_processing();
void apply_color_clip_plane_colors();
void render_cut_plane();
static void render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix);
void render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width);
void render_rotation_snapping(GrabberID axis, const ColorRGBA& color);
void render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix, double line_len_koef = 1.0);
void render_cut_plane_grabbers();
void render_cut_line();
void perform_cut(const Selection&selection);
void set_center_pos(const Vec3d&center_pos, bool update_tbb = false);
void update_bb();
void init_picking_models();
void init_rendering_items();
void render_clipper_cut();
void clear_selection();
void reset_connectors();
void init_connector_shapes();
void update_connector_shape();
void validate_connector_settings();
bool process_cut_line(SLAGizmoEventType action, const Vec2d& mouse_position);
void check_and_update_connectors_state();
void toggle_model_objects_visibility();
indexed_triangle_set its_make_groove_plane();
indexed_triangle_set get_connector_mesh(CutConnectorAttributes connector_attributes);
void apply_cut_connectors(ModelObject* mo, const std::string& connector_name);
};
} // namespace GUI

View file

@ -20,8 +20,7 @@
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
// BBS
#include "slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp"
//#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
@ -193,7 +192,7 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, m_is_dark ? "toolbar_rotate_dark.svg" : "toolbar_rotate.svg", EType::Rotate, &m_object_manipulation));
m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, m_is_dark ? "toolbar_scale_dark.svg" : "toolbar_scale.svg", EType::Scale, &m_object_manipulation));
m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, m_is_dark ? "toolbar_flatten_dark.svg" : "toolbar_flatten.svg", EType::Flatten));
m_gizmos.emplace_back(new GLGizmoAdvancedCut(m_parent, m_is_dark ? "toolbar_cut_dark.svg" : "toolbar_cut.svg", EType::Cut));
m_gizmos.emplace_back(new GLGizmoCut3D(m_parent, m_is_dark ? "toolbar_cut_dark.svg" : "toolbar_cut.svg", EType::Cut));
m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg", EType::MeshBoolean));
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg", EType::FdmSupports));
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg", EType::Seam));
@ -446,7 +445,7 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
else if (m_current == Measure)
return dynamic_cast<GLGizmoMeasure*>(m_gizmos[Measure].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Cut)
return dynamic_cast<GLGizmoAdvancedCut *>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
return dynamic_cast<GLGizmoCut3D*>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == MeshBoolean)
return dynamic_cast<GLGizmoMeshBoolean*>(m_gizmos[MeshBoolean].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else
@ -861,13 +860,10 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
// m_parent.set_cursor(GLCanvas3D::Cross);
processed = true;
}
else*/ if (m_current == Cut)
{
// BBS
#if 0
else*/ if (m_current == Cut) {
auto do_move = [this, &processed](double delta_z) {
GLGizmoAdvancedCut* cut = dynamic_cast<GLGizmoAdvancedCut*>(get_current());
cut->set_cut_z(delta_z + cut->get_cut_z());
GLGizmoCut3D* cut = dynamic_cast<GLGizmoCut3D*>(get_current());
cut->shift_cut(delta_z);
processed = true;
};
@ -875,10 +871,13 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
{
case WXK_NUMPAD_UP: case WXK_UP: { do_move(1.0); break; }
case WXK_NUMPAD_DOWN: case WXK_DOWN: { do_move(-1.0); break; }
case WXK_SHIFT : case WXK_ALT: {
processed = get_current()->is_in_editing_mode();
}
default: { break; }
}
#endif
} else if (m_current == Simplify && keyCode == WXK_ESCAPE) {
}
else if (m_current == Simplify && keyCode == WXK_ESCAPE) {
GLGizmoSimplify *simplify = dynamic_cast<GLGizmoSimplify *>(get_current());
if (simplify != nullptr)
processed = simplify->on_esc_key_down();

View file

@ -511,10 +511,12 @@ void ImGuiWrapper::render()
m_new_frame_open = false;
}
ImVec2 ImGuiWrapper::calc_text_size(const wxString &text, float wrap_width) const
ImVec2 ImGuiWrapper::calc_text_size(const wxString &text,
bool hide_text_after_double_hash,
float wrap_width) const
{
auto text_utf8 = into_u8(text);
ImVec2 size = ImGui::CalcTextSize(text_utf8.c_str(), NULL, false, wrap_width);
ImVec2 size = ImGui::CalcTextSize(text_utf8.c_str(), NULL, hide_text_after_double_hash, wrap_width);
/*#ifdef __linux__
size.x *= m_style_scaling;
@ -773,16 +775,30 @@ void ImGuiWrapper::end()
ImGui::End();
}
bool ImGuiWrapper::button(const wxString &label)
bool ImGuiWrapper::button(const wxString &label, const wxString& tooltip)
{
auto label_utf8 = into_u8(label);
return ImGui::Button(label_utf8.c_str());
const bool ret = ImGui::Button(label_utf8.c_str());
if (!tooltip.IsEmpty() && ImGui::IsItemHovered()) {
auto tooltip_utf8 = into_u8(tooltip);
ImGui::SetTooltip(tooltip_utf8.c_str(), nullptr);
}
return ret;
}
bool ImGuiWrapper::bbl_button(const wxString &label)
bool ImGuiWrapper::bbl_button(const wxString &label, const wxString& tooltip)
{
auto label_utf8 = into_u8(label);
return ImGui::BBLButton(label_utf8.c_str());
const bool ret = ImGui::BBLButton(label_utf8.c_str());
if (!tooltip.IsEmpty() && ImGui::IsItemHovered()) {
auto tooltip_utf8 = into_u8(tooltip);
ImGui::SetTooltip(tooltip_utf8.c_str(), nullptr);
}
return ret;
}
bool ImGuiWrapper::button(const wxString& label, float width, float height)
@ -791,6 +807,17 @@ bool ImGuiWrapper::button(const wxString& label, float width, float height)
return ImGui::Button(label_utf8.c_str(), ImVec2(width, height));
}
bool ImGuiWrapper::button(const wxString& label, const ImVec2 &size, bool enable)
{
disabled_begin(!enable);
auto label_utf8 = into_u8(label);
bool res = ImGui::Button(label_utf8.c_str(), size);
disabled_end();
return (enable) ? res : false;
}
bool ImGuiWrapper::radio_button(const wxString &label, bool active)
{
auto label_utf8 = into_u8(label);
@ -965,6 +992,8 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float
m_last_slider_status.edited = ImGui::IsItemEdited();
m_last_slider_status.clicked = ImGui::IsItemClicked();
m_last_slider_status.deactivated_after_edit = ImGui::IsItemDeactivatedAfterEdit();
if (!m_last_slider_status.can_take_snapshot)
m_last_slider_status.can_take_snapshot = ImGui::IsItemClicked();
if (!tooltip.empty() && ImGui::IsItemHovered())
this->tooltip(into_u8(tooltip).c_str(), max_tooltip_width);
@ -1103,25 +1132,34 @@ bool ImGuiWrapper::image_button(const wchar_t icon, const wxString& tooltip)
return res;
}
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection)
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags/* = 0*/, float label_width/* = 0.0f*/, float item_width/* = 0.0f*/)
{
return combo(into_u8(label), options, selection, flags, label_width, item_width);
}
bool ImGuiWrapper::combo(const std::string& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags/* = 0*/, float label_width/* = 0.0f*/, float item_width/* = 0.0f*/)
{
// this is to force the label to the left of the widget:
text(label);
ImGui::SameLine();
const bool hidden_label = boost::starts_with(label, "##");
if (!label.empty() && !hidden_label) {
text(label);
ImGui::SameLine(label_width);
}
ImGui::PushItemWidth(item_width);
int selection_out = selection;
bool res = false;
const char *selection_str = selection < int(options.size()) && selection >= 0 ? options[selection].c_str() : "";
if (ImGui::BeginCombo("", selection_str)) {
if (ImGui::BeginCombo(hidden_label ? label.c_str() : ("##" + label).c_str(), selection_str, flags)) {
for (int i = 0; i < (int)options.size(); i++) {
if (ImGui::Selectable(options[i].c_str(), i == selection)) {
selection_out = i;
res = true;
}
}
ImGui::EndCombo();
res = true;
}
selection = selection_out;

View file

@ -74,6 +74,11 @@ public:
bool edited { false };
bool clicked { false };
bool deactivated_after_edit { false };
// flag to indicate possibility to take snapshot from the slider value
// It's used from Gizmos to take snapshots just from the very beginning of the editing
bool can_take_snapshot { false };
// When Undo/Redo snapshot is taken, then call this function
void invalidate_snapshot() { can_take_snapshot = false; }
};
ImGuiWrapper();
@ -95,12 +100,13 @@ public:
float scaled(float x) const { return x * m_font_size; }
ImVec2 scaled(float x, float y) const { return ImVec2(x * m_font_size, y * m_font_size); }
ImVec2 calc_text_size(const wxString &text, float wrap_width = -1.0f) const;
ImVec2 calc_text_size(const wxString &text, bool hide_text_after_double_hash = false, float wrap_width = -1.0f) const;
ImVec2 calc_button_size(const wxString &text, const ImVec2 &button_size = ImVec2(0, 0)) const;
ImVec2 get_item_spacing() const;
float get_slider_float_height() const;
const LastSliderStatus& get_last_slider_status() const { return m_last_slider_status; }
LastSliderStatus& get_last_slider_status() { return m_last_slider_status; }
void set_next_window_pos(float x, float y, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f);
void set_next_window_bg_alpha(float alpha);
@ -118,9 +124,10 @@ public:
bool begin(const wxString& name, bool* close, int flags = 0);
void end();
bool button(const wxString &label);
bool bbl_button(const wxString &label);
bool button(const wxString& label, float width, float height);
bool button(const wxString &label, const wxString& tooltip = {});
bool bbl_button(const wxString &label, const wxString& tooltip = {});
bool button(const wxString& label, float width, float height);
bool button(const wxString& label, const ImVec2 &size, bool enable); // default size = ImVec2(0.f, 0.f)
bool radio_button(const wxString &label, bool active);
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f");
@ -157,7 +164,9 @@ public:
bool image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0.0, 0.0), const ImVec2& uv1 = ImVec2(1.0, 1.0), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0.0, 0.0, 0.0, 0.0), const ImVec4& tint_col = ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags flags = 0);
bool image_button(const wchar_t icon, const wxString& tooltip = L"");
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
// Use selection = -1 to not mark any option as selected
bool combo(const std::string& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags = 0, float label_width = 0.0f, float item_width = 0.0f);
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags = 0, float label_width = 0.0f, float item_width = 0.0f);
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel);
void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
Search::OptionViewParameters &view_params,

View file

@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2018 - 2023 Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv, Enrico Turri @enricoturri1966, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Vojtěch Král @vojtechkral
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "MsgDialog.hpp"
#include <wx/settings.h>
@ -411,6 +415,58 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString&
finalize();
}
wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
{
wxString out;
for (size_t i = 0; i < in.size();) {
// Overwrite the character (space or newline) starting at ibreak?
bool overwrite = false;
// UTF8 representation of wxString.
// Where to break the line, index of character at the start of a UTF-8 sequence.
size_t ibreak = size_t(-1);
// Overwrite the character at ibreak (it is a whitespace) or not?
size_t j = i;
for (size_t cnt = 0; j < in.size();) {
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
// Overwrite the whitespace.
ibreak = j ++;
overwrite = true;
if (newline)
break;
} else if (in[j] == '/'
#ifdef _WIN32
|| in[j] == '\\'
#endif // _WIN32
) {
// Insert after the slash.
ibreak = ++ j;
overwrite = false;
} else
j += get_utf8_sequence_length(in.c_str() + j, in.size() - j);
if (++ cnt == line_len) {
if (ibreak == size_t(-1)) {
ibreak = j;
overwrite = false;
}
break;
}
}
if (j == in.size()) {
out.append(in.begin() + i, in.end());
break;
}
assert(ibreak != size_t(-1));
out.append(in.begin() + i, in.begin() + ibreak);
out.append('\n');
i = ibreak;
if (overwrite)
++ i;
}
return out;
}
// InfoDialog
DownloadDialog::DownloadDialog(wxWindow *parent, const wxString &msg, const wxString &title, bool is_marked_msg /* = false*/, long style /* = wxOK | wxICON_INFORMATION*/)
: MsgDialog(parent, title, msg, style), msg(msg)

View file

@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2018 - 2022 Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_MsgDialog_hpp_
#define slic3r_MsgDialog_hpp_
@ -128,6 +132,8 @@ public:
virtual ~WarningDialog() = default;
};
wxString get_wraped_wxString(const wxString& text_in, size_t line_len = 80);
#if 1
// Generic static line, used intead of wxStaticLine
//class StaticLine: public wxTextCtrl

View file

@ -1,3 +1,22 @@
///|/ Copyright (c) Prusa Research 2018 - 2023 Vojtěch Bubník @bubnikv, Lukáš Matěna @lukasmatena, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Tomáš Mészáros @tamasmeszaros, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Pavel Mikuš @Godrak, Filip Sykala @Jony01, Vojtěch Král @vojtechkral
///|/ Copyright (c) 2022 Michael Kirsch
///|/ Copyright (c) 2021 Boleslaw Ciesielski
///|/ Copyright (c) 2019 John Drake @foxox
///|/
///|/ ported from lib/Slic3r/GUI/Plater.pm:
///|/ Copyright (c) Prusa Research 2016 - 2019 Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Tomáš Mészáros @tamasmeszaros
///|/ Copyright (c) 2018 Martin Loidl @LoidlM
///|/ Copyright (c) 2017 Matthias Gazzari @qtux
///|/ Copyright (c) Slic3r 2012 - 2016 Alessandro Ranellucci @alranel
///|/ Copyright (c) 2017 Joseph Lenox @lordofhyphens
///|/ Copyright (c) 2015 Daren Schwenke
///|/ Copyright (c) 2014 Mark Hindess
///|/ Copyright (c) 2012 Mike Sheldrake @mesheldrake
///|/ Copyright (c) 2012 Henrik Brix Andersen @henrikbrixandersen
///|/ Copyright (c) 2012 Sam Wong
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "Plater.hpp"
#include "libslic3r/Config.hpp"
@ -128,6 +147,7 @@
#include "Gizmos/GLGizmosManager.hpp"
#endif // __APPLE__
#include <libslic3r/CutUtils.hpp>
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
#include "WipeTowerDialog.hpp"
@ -8273,14 +8293,6 @@ void Plater::add_model(bool imperial_units, std::string fname)
wxGetApp().mainframe->update_title();
}
}
std::array<Vec3d, 4> get_cut_plane(const BoundingBoxf3& bbox, const double& cut_height) {
std::array<Vec3d, 4> plane_pts;
plane_pts[0] = Vec3d(bbox.min(0), bbox.min(1), cut_height);
plane_pts[1] = Vec3d(bbox.max(0), bbox.min(1), cut_height);
plane_pts[2] = Vec3d(bbox.max(0), bbox.max(1), cut_height);
plane_pts[3] = Vec3d(bbox.min(0), bbox.max(1), cut_height);
return plane_pts;
}
void Plater::calib_pa(const Calib_Params& params)
{
@ -8403,6 +8415,36 @@ void Plater::_calib_pa_pattern(const Calib_Params& params)
changed_objects({ 0 });
}
void Plater::cut_horizontal(size_t obj_idx, size_t instance_idx, double z, ModelObjectCutAttributes attributes)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
auto *object = p->model.objects[obj_idx];
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
if (! attributes.has(ModelObjectCutAttribute::KeepUpper) && ! attributes.has(ModelObjectCutAttribute::KeepLower))
return;
wxBusyCursor wait;
const auto new_objects = Cut::cut_horizontal(object, instance_idx, z, attributes);
remove(obj_idx);
p->load_model_objects(new_objects);
// now process all updates of the 3d scene
update();
// Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(),
// which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call
for (size_t idx = 0; idx < p->model.objects.size(); idx++)
wxGetApp().obj_list()->update_info_items(idx);
Selection& selection = p->get_selection();
size_t last_id = p->model.objects.size() - 1;
for (size_t i = 0; i < new_objects.size(); ++i)
selection.add_object((unsigned int)(last_id - i), i == 0);
}
void Plater::_calib_pa_tower(const Calib_Params& params) {
add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/tower_with_seam.stl");
@ -8439,8 +8481,7 @@ void Plater::_calib_pa_tower(const Calib_Params& params) {
auto new_height = std::ceil((params.end - params.start) / params.step) + 1;
auto obj_bb = model().objects[0]->bounding_box();
if (new_height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, new_height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepLower);
}
_calib_pa_select_added_objects();
@ -8581,8 +8622,7 @@ void Plater::calib_temp(const Calib_Params& params) {
// add EPSILON offset to avoid cutting at the exact location where the flat surface is
auto new_height = block_count * 10.0 + EPSILON;
if (new_height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, new_height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepLower);
}
}
@ -8592,8 +8632,7 @@ void Plater::calib_temp(const Calib_Params& params) {
if(block_count > 0){
auto new_height = block_count * 10.0 + EPSILON;
if (new_height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, new_height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepUpper);
cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepUpper);
}
}
@ -8661,8 +8700,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params)
auto obj_bb = obj->bounding_box();
auto height = (params.end - params.start + 1) / params.step;
if (height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower);
}
auto new_params = params;
@ -8710,8 +8748,7 @@ void Plater::calib_retraction(const Calib_Params& params)
auto obj_bb = obj->bounding_box();
auto height = 1.0 + 0.4 + ((params.end - params.start)) / params.step;
if (height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower);
}
p->background_process.fff_print()->set_calib_params(params);
@ -8752,8 +8789,7 @@ void Plater::calib_VFA(const Calib_Params& params)
auto obj_bb = model().objects[0]->bounding_box();
auto height = 5 * ((params.end - params.start) / params.step + 1);
if (height < obj_bb.size().z()) {
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, height);
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower);
}
p->background_process.fff_print()->set_calib_params(params);
@ -9858,27 +9894,16 @@ void Plater::convert_unit(ConversionType conv_type)
}
}
// BBS: replace z with plane_points
void Plater::cut(size_t obj_idx, size_t instance_idx, std::array<Vec3d, 4> plane_points, ModelObjectCutAttributes attributes)
void Plater::apply_cut_object_to_model(size_t obj_idx, const ModelObjectPtrs& new_objects)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
auto *object = p->model.objects[obj_idx];
model().delete_object(obj_idx);
sidebar().obj_list()->delete_object_from_list(obj_idx);
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
if (! attributes.has(ModelObjectCutAttribute::KeepUpper) && ! attributes.has(ModelObjectCutAttribute::KeepLower))
return;
wxBusyCursor wait;
// BBS: replace z with plane_points
const auto new_objects = object->cut(instance_idx, plane_points, attributes);
remove(obj_idx);
p->load_model_objects(new_objects);
// suppress to call selection update for Object List to avoid call of early Gizmos on/off update
p->load_model_objects(new_objects, false, false);
// now process all updates of the 3d scene
update();
// Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(),
// which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call
for (size_t idx = 0; idx < p->model.objects.size(); idx++)
@ -9888,62 +9913,10 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, std::array<Vec3d, 4> plane
size_t last_id = p->model.objects.size() - 1;
for (size_t i = 0; i < new_objects.size(); ++i)
selection.add_object((unsigned int)(last_id - i), i == 0);
}
// BBS
void Plater::segment(size_t obj_idx, size_t instance_idx, double smoothing_alpha, int segment_number)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
auto* object = p->model.objects[obj_idx];
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
Plater::TakeSnapshot snapshot(this, "Segment");
wxBusyCursor wait;
// real process
PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
const size_t filament_cnt = print_tech != ptFFF ? 1 : preset_bundle.filament_presets.size();
const auto new_objects = object->segment(instance_idx, filament_cnt, smoothing_alpha, segment_number);
remove(obj_idx);
p->load_model_objects(new_objects);
Selection& selection = p->get_selection();
size_t last_id = p->model.objects.size() - 1;
for (size_t i = 0; i < new_objects.size(); ++i)
{
selection.add_object((unsigned int)(last_id - i), i == 0);
}
}
// BBS
void Plater::merge(size_t obj_idx, std::vector<int>& vol_indeces)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
auto* object = p->model.objects[obj_idx];
Plater::TakeSnapshot snapshot(this, "Merge");
wxBusyCursor wait;
// real process
PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
// BBS
const size_t filament_cnt = print_tech != ptFFF ? 1 : preset_bundle.filament_presets.size();
const auto new_objects = object->merge_volumes(vol_indeces);
remove(obj_idx);
p->load_model_objects(new_objects);
Selection& selection = p->get_selection();
size_t last_id = p->model.objects.size() - 1;
for (size_t i = 0; i < new_objects.size(); ++i)
{
selection.add_object((unsigned int)(last_id - i), i == 0);
}
// UIThreadWorker w;
// arrange(w, true);
// w.wait_for_idle();
}
void Plater::export_gcode(bool prefer_removable)

View file

@ -1,3 +1,19 @@
///|/ Copyright (c) Prusa Research 2018 - 2023 Tomáš Mészáros @tamasmeszaros, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv, Lukáš Matěna @lukasmatena, Pavel Mikuš @Godrak, Filip Sykala @Jony01, Vojtěch Král @vojtechkral
///|/
///|/ ported from lib/Slic3r/GUI/Plater.pm:
///|/ Copyright (c) Prusa Research 2016 - 2019 Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Tomáš Mészáros @tamasmeszaros
///|/ Copyright (c) 2018 Martin Loidl @LoidlM
///|/ Copyright (c) 2017 Matthias Gazzari @qtux
///|/ Copyright (c) Slic3r 2012 - 2016 Alessandro Ranellucci @alranel
///|/ Copyright (c) 2017 Joseph Lenox @lordofhyphens
///|/ Copyright (c) 2015 Daren Schwenke
///|/ Copyright (c) 2014 Mark Hindess
///|/ Copyright (c) 2012 Mike Sheldrake @mesheldrake
///|/ Copyright (c) 2012 Henrik Brix Andersen @henrikbrixandersen
///|/ Copyright (c) 2012 Sam Wong
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_Plater_hpp_
#define slic3r_Plater_hpp_
@ -25,6 +41,7 @@
#include "libslic3r/PrintBase.hpp"
#include "libslic3r/calib.hpp"
#include "libslic3r/CutUtils.hpp"
#define FILAMENT_SYSTEM_COLORS_NUM 16
@ -41,8 +58,6 @@ class BuildVolume;
enum class BuildVolume_Type : unsigned char;
class Model;
class ModelObject;
enum class ModelObjectCutAttribute : int;
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
class ModelInstance;
class Print;
class SLAPrint;
@ -323,12 +338,7 @@ public:
void scale_selection_to_fit_print_volume();
void convert_unit(ConversionType conv_type);
// BBS: replace z with plane_points
void cut(size_t obj_idx, size_t instance_idx, std::array<Vec3d, 4> plane_points, ModelObjectCutAttributes attributes);
// BBS: segment model with CGAL
void segment(size_t obj_idx, size_t instance_idx, double smoothing_alpha=0.5, int segment_number=5);
void merge(size_t obj_idx, std::vector<int>& vol_indeces);
void apply_cut_object_to_model(size_t init_obj_idx, const ModelObjectPtrs& cut_objects);
void send_to_printer(bool isall = false);
void export_gcode(bool prefer_removable);
@ -742,6 +752,8 @@ private:
void _calib_pa_tower(const Calib_Params& params);
void _calib_pa_select_added_objects();
void cut_horizontal(size_t obj_idx, size_t instance_idx, double z, ModelObjectCutAttributes attributes);
friend class SuppressBackgroundProcessingUpdate;
};