mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-19 06:41:14 -06:00
Cut: Initial porting of Cut Gizmo
This commit is contained in:
parent
ce2836a7f9
commit
18406c31c0
34 changed files with 5638 additions and 1361 deletions
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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¢er, 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¢er_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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue