Cut WIP: Undo/Redo implementation

This commit is contained in:
YuSanka 2022-05-02 12:44:47 +02:00
parent 73469ffa21
commit 94f3aaacd4
6 changed files with 100 additions and 25 deletions

View File

@ -17,16 +17,21 @@ src/slic3r/GUI/GalleryDialog.cpp
src/slic3r/GUI/GCodeViewer.cpp
src/slic3r/GUI/GLCanvas3D.cpp
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp
src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp
src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
src/slic3r/GUI/GUI.cpp

View File

@ -584,7 +584,8 @@ private:
Internal::StaticSerializationWrapper<LayerHeightProfile> layer_heigth_profile_wrapper(layer_height_profile);
ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper,
sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation,
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
cut_connectors, cut_id);
}
// Called by Print::validate() from the UI thread.

View File

@ -14,6 +14,7 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/TriangleMeshSlicer.hpp"
@ -88,6 +89,8 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event)
return false;
if (m_rotation_gizmo.on_mouse(mouse_event)) {
if (mouse_event.LeftUp())
on_stop_dragging();
update_clipper();
return true;
}
@ -221,7 +224,7 @@ void GLGizmoCut3D::update_clipper()
void GLGizmoCut3D::update_clipper_on_render()
{
update_clipper();
suppress_update_clipper_on_render = true;
force_update_clipper_on_render = false;
}
void GLGizmoCut3D::set_center(const Vec3d& center)
@ -595,6 +598,27 @@ bool GLGizmoCut3D::on_init()
return true;
}
void GLGizmoCut3D::on_load(cereal::BinaryInputArchive& ar)
{
ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, //m_selected,
m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id,
m_ar_plane_center, m_ar_rotations);
set_center_pos(m_ar_plane_center);
m_rotation_gizmo.set_center(m_ar_plane_center);
m_rotation_gizmo.set_rotation(m_ar_rotations);
force_update_clipper_on_render = true;
m_parent.request_extra_frame();
}
void GLGizmoCut3D::on_save(cereal::BinaryOutputArchive& ar) const
{
ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, //m_selected,
m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id,
m_ar_plane_center, m_ar_rotations);
}
std::string GLGizmoCut3D::on_get_name() const
{
return _u8L("Cut");
@ -602,13 +626,22 @@ std::string GLGizmoCut3D::on_get_name() const
void GLGizmoCut3D::on_set_state()
{
if (get_state() == On)
if (m_state == On) {
update_bb();
// initiate archived values
m_ar_plane_center = m_plane_center;
m_ar_rotations = m_rotation_gizmo.get_rotation();
m_parent.request_extra_frame();
}
else
m_c->object_clipper()->release();
m_rotation_gizmo.set_center(m_plane_center);
m_rotation_gizmo.set_state(m_state);
suppress_update_clipper_on_render = m_state != On;
force_update_clipper_on_render = m_state == On;
}
void GLGizmoCut3D::on_set_hover_id()
@ -674,6 +707,24 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
}
}
void GLGizmoCut3D::on_start_dragging()
{
if (m_hover_id > m_group_id && m_connector_mode == CutConnectorMode::Manual)
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move connector"), UndoRedo::SnapshotType::GizmoAction);
}
void GLGizmoCut3D::on_stop_dragging()
{
if (m_hover_id < m_group_id) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Rotate cut plane"), UndoRedo::SnapshotType::GizmoAction);
m_ar_rotations = m_rotation_gizmo.get_rotation();
}
else if (m_hover_id == m_group_id) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move cut plane"), UndoRedo::SnapshotType::GizmoAction);
m_ar_plane_center = m_plane_center;
}
}
void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos)
{
m_plane_center = center_pos;
@ -778,6 +829,9 @@ void GLGizmoCut3D::on_render()
if (!m_sphere.is_initialized())
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0));
if (force_update_clipper_on_render)
update_clipper_on_render();
render_connectors(false);
m_c->object_clipper()->render_cut();
@ -790,9 +844,6 @@ void GLGizmoCut3D::on_render()
m_rotation_gizmo.render();
}
}
if (!suppress_update_clipper_on_render)
update_clipper_on_render();
}
void GLGizmoCut3D::on_render_for_picking()
@ -963,7 +1014,7 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
ImGui::Separator();
m_imgui->disabled_begin((!m_keep_upper && !m_keep_lower) || !can_perform_cut());
m_imgui->disabled_begin(!can_perform_cut());
const bool cut_clicked = m_imgui->button(_L("Perform cut"));
m_imgui->disabled_end();
@ -1024,13 +1075,16 @@ void GLGizmoCut3D::render_connectors(bool picking)
{
m_has_invalid_connector = false;
if (m_connector_mode == CutConnectorMode::Auto)
if (m_connector_mode == CutConnectorMode::Auto || !m_c->selection_info())
return;
const ModelObject* mo = m_c->selection_info()->model_object();
const CutConnectors& connectors = mo->cut_connectors;
if (connectors.size() != m_selected.size())
return;
if (connectors.size() != m_selected.size()) {
// #ysFIXME
m_selected.clear();
m_selected.resize(connectors.size(), false);
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
@ -1145,7 +1199,7 @@ void GLGizmoCut3D::render_connectors(bool picking)
bool GLGizmoCut3D::can_perform_cut() const
{
if (m_has_invalid_connector)
if (m_has_invalid_connector || (!m_keep_upper && !m_keep_lower))
return false;
BoundingBoxf3 box = bounding_box();
@ -1172,9 +1226,16 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
Vec3d cut_center_offset = m_plane_center - instance_offset;
cut_center_offset[Z] -= first_glvolume->get_sla_shift_z();
Plater* plater = wxGetApp().plater();
bool create_dowels_as_separate_object = false;
if (0.0 < object_cut_z && can_perform_cut()) {
ModelObject* mo = wxGetApp().plater()->model().objects[object_idx];
ModelObject* mo = plater->model().objects[object_idx];
if(!mo)
return;
Plater::TakeSnapshot snapshot(plater, _L("Cut by Plane"));
const bool has_connectors = !mo->cut_connectors.empty();
// update connectors pos as offset of its center before cut performing
if (has_connectors && m_connector_mode == CutConnectorMode::Manual) {
@ -1198,7 +1259,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
create_dowels_as_separate_object = true;
}
wxGetApp().plater()->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(),
plater->cut(object_idx, instance_idx, cut_center_offset, m_rotation_gizmo.get_rotation(),
only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) |
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
@ -1306,7 +1367,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
const Vec3d& normal = pos_and_normal.second;
// The clipping plane was clicked, hit containts coordinates of the hit in world coords.
std::cout << hit.x() << "\t" << hit.y() << "\t" << hit.z() << std::endl;
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"));
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction);
connectors.emplace_back(hit, m_rotation_gizmo.get_rotation(), float(m_connector_size * 0.5), float(m_connector_depth_ratio));
update_model_object();
@ -1326,7 +1387,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
if (m_hover_id < m_connectors_group_id)
return false;
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Delete connector"));
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Delete connector"), UndoRedo::SnapshotType::GizmoAction);
size_t connector_id = m_hover_id - m_connectors_group_id;
connectors.erase(connectors.begin() + connector_id);

View File

@ -24,6 +24,10 @@ class GLGizmoCut3D : public GLGizmoBase
double m_snap_step{ 1.0 };
int m_connectors_group_id;
// archived values
Vec3d m_ar_plane_center { Vec3d::Zero() };
Vec3d m_ar_rotations { Vec3d::Zero() };
Vec3d m_plane_center{ Vec3d::Zero() };
// data to check position of the cut palne center on gizmo activation
Vec3d m_min_pos{ Vec3d::Zero() };
@ -38,7 +42,7 @@ class GLGizmoCut3D : public GLGizmoBase
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLModel m_plane;
GLModel m_grabber_connection;
// GLModel m_grabber_connection;
GLModel m_cone;
GLModel m_sphere;
Vec3d m_old_center;
@ -57,7 +61,7 @@ class GLGizmoCut3D : public GLGizmoBase
float m_label_width{ 150.0 };
float m_control_width{ 200.0 };
bool m_imperial_units{ false };
bool suppress_update_clipper_on_render{false};
bool force_update_clipper_on_render{false};
mutable std::vector<bool> m_selected; // which pins are currently selected
bool m_selection_empty = true;
@ -123,18 +127,24 @@ public:
protected:
bool on_init() override;
void on_load(cereal::BinaryInputArchive& ar) override { ar(m_keep_upper, m_keep_lower, m_rotate_lower); }
void on_save(cereal::BinaryOutputArchive& ar) const override { ar(m_keep_upper, m_keep_lower, m_rotate_lower); }
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;
void on_dragging(const UpdateData& data) override;
void on_start_dragging() override;
void on_stop_dragging() override;
void on_render() override;
void on_render_for_picking() override;
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() override { return _u8L("Cut gizmo editing"); }
private:
void set_center(const Vec3d& center);

View File

@ -836,7 +836,8 @@ void GLGizmoRotate3D::on_start_dragging()
void GLGizmoRotate3D::on_stop_dragging()
{
assert(0 <= m_hover_id && m_hover_id < 3);
m_parent.do_rotate(L("Gizmo-Rotate"));
if (!m_use_only_grabbers)
m_parent.do_rotate(L("Gizmo-Rotate"));
m_gizmos[m_hover_id].stop_dragging();
}

View File

@ -5915,10 +5915,7 @@ void Slic3r::GUI::Plater::cut(size_t obj_idx, size_t instance_idx, const Vec3d&
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
if (!attributes.has(ModelObjectCutAttribute::KeepUpper) && !attributes.has(ModelObjectCutAttribute::KeepLower))
return;
Plater::TakeSnapshot snapshot(this, _L("Cut by Plane"));
//Plater::TakeSnapshot snapshot(this, _L("Cut by Plane"));
wxBusyCursor wait;
const auto new_objects = object->cut(instance_idx, cut_center, cut_rotation, attributes);