Framework to serialize gizmos into undo/redo stack

Serialization into undo/redo of Cut gizmo

Refactoring of GLGizmosManager
This commit is contained in:
Enrico Turri 2019-07-17 08:38:48 +02:00
parent 4865240a9c
commit 21624f5305
11 changed files with 254 additions and 168 deletions

View file

@ -1719,7 +1719,7 @@ void GLCanvas3D::deselect_all()
m_selection.set_mode(Selection::Instance); m_selection.set_mode(Selection::Instance);
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
m_gizmos.reset_all_states(); m_gizmos.reset_all_states();
m_gizmos.update_data(*this); m_gizmos.update_data();
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
} }
@ -2082,8 +2082,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_selection.volumes_changed(map_glvolume_old_to_new); m_selection.volumes_changed(map_glvolume_old_to_new);
} }
m_gizmos.update_data(*this); m_gizmos.update_data();
m_gizmos.refresh_on_off_state(m_selection); m_gizmos.refresh_on_off_state();
// Update the toolbar // Update the toolbar
if (update_object_list) if (update_object_list)
@ -2323,7 +2323,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items()) if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items())
return; return;
if (m_gizmos.on_char(evt, *this)) if (m_gizmos.on_char(evt))
return; return;
//#ifdef __APPLE__ //#ifdef __APPLE__
@ -2450,7 +2450,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
} }
else else
{ {
if (!m_gizmos.on_key(evt, *this)) if (!m_gizmos.on_key(evt))
{ {
if (evt.GetEventType() == wxEVT_KEY_UP) { if (evt.GetEventType() == wxEVT_KEY_UP) {
if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
@ -2560,7 +2560,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
} }
// Inform gizmos about the event so they have the opportunity to react. // Inform gizmos about the event so they have the opportunity to react.
if (m_gizmos.on_mouse_wheel(evt, *this)) if (m_gizmos.on_mouse_wheel(evt))
return; return;
// Calculate the zoom delta and apply it to the current zoom factor // Calculate the zoom delta and apply it to the current zoom factor
@ -2688,7 +2688,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return; return;
} }
if (m_gizmos.on_mouse(evt, *this)) if (m_gizmos.on_mouse(evt))
{ {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup(); mouse_up_cleanup();
@ -2815,9 +2815,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_selection.is_empty()) if (m_selection.is_empty())
m_gizmos.reset_all_states(); m_gizmos.reset_all_states();
else else
m_gizmos.refresh_on_off_state(m_selection); m_gizmos.refresh_on_off_state();
m_gizmos.update_data(*this); m_gizmos.update_data();
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
m_dirty = true; m_dirty = true;
} }
@ -2985,9 +2985,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{ {
// forces the selection of the volume // forces the selection of the volume
m_selection.add(volume_idx); m_selection.add(volume_idx);
m_gizmos.refresh_on_off_state(m_selection); m_gizmos.refresh_on_off_state();
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
m_gizmos.update_data(*this); m_gizmos.update_data();
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
// forces a frame render to update the view before the context menu is shown // forces a frame render to update the view before the context menu is shown
render(); render();
@ -3355,8 +3355,8 @@ void GLCanvas3D::set_camera_zoom(double zoom)
void GLCanvas3D::update_gizmos_on_off_state() void GLCanvas3D::update_gizmos_on_off_state()
{ {
set_as_dirty(); set_as_dirty();
m_gizmos.update_data(*this); m_gizmos.update_data();
m_gizmos.refresh_on_off_state(get_selection()); m_gizmos.refresh_on_off_state();
} }
void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool focus_on) void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool focus_on)
@ -3762,7 +3762,7 @@ void GLCanvas3D::_picking_pass() const
if (m_camera_clipping_plane.is_active()) if (m_camera_clipping_plane.is_active())
::glDisable(GL_CLIP_PLANE0); ::glDisable(GL_CLIP_PLANE0);
m_gizmos.render_current_gizmo_for_picking_pass(m_selection); m_gizmos.render_current_gizmo_for_picking_pass();
if (m_multisample_allowed) if (m_multisample_allowed)
glsafe(::glEnable(GL_MULTISAMPLE)); glsafe(::glEnable(GL_MULTISAMPLE));
@ -4072,7 +4072,7 @@ void GLCanvas3D::_render_volumes_for_picking() const
void GLCanvas3D::_render_current_gizmo() const void GLCanvas3D::_render_current_gizmo() const
{ {
m_gizmos.render_current_gizmo(m_selection); m_gizmos.render_current_gizmo();
} }
void GLCanvas3D::_render_gizmos_overlay() const void GLCanvas3D::_render_gizmos_overlay() const
@ -4088,7 +4088,7 @@ void GLCanvas3D::_render_gizmos_overlay() const
m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
#endif /* __WXMSW__ */ #endif /* __WXMSW__ */
m_gizmos.render_overlay(*this, m_selection); m_gizmos.render_overlay();
} }
void GLCanvas3D::_render_toolbar() const void GLCanvas3D::_render_toolbar() const
@ -5661,9 +5661,9 @@ void GLCanvas3D::_update_selection_from_hover()
if (m_selection.is_empty()) if (m_selection.is_empty())
m_gizmos.reset_all_states(); m_gizmos.reset_all_states();
else else
m_gizmos.refresh_on_off_state(m_selection); m_gizmos.refresh_on_off_state();
m_gizmos.update_data(*this); m_gizmos.update_data();
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
m_dirty = true; m_dirty = true;
} }

View file

@ -517,6 +517,9 @@ public:
const Selection& get_selection() const { return m_selection; } const Selection& get_selection() const { return m_selection; }
Selection& get_selection() { return m_selection; } Selection& get_selection() { return m_selection; }
const GLGizmosManager& get_gizmos_manager() const { return m_gizmos; }
GLGizmosManager& get_gizmos_manager() { return m_gizmos; }
void bed_shape_changed(); void bed_shape_changed();
void set_clipping_plane(unsigned int id, const ClippingPlane& plane) void set_clipping_plane(unsigned int id, const ClippingPlane& plane)

View file

@ -132,6 +132,7 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
glsafe(::glEnd()); glsafe(::glEnd());
} }
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: m_parent(parent) : m_parent(parent)
, m_group_id(-1) , m_group_id(-1)

View file

@ -6,6 +6,7 @@
#include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/Selection.hpp" #include "slic3r/GUI/Selection.hpp"
#include <cereal/archives/binary.hpp>
class wxWindow; class wxWindow;
class GLUquadric; class GLUquadric;
@ -105,6 +106,9 @@ public:
bool init() { return on_init(); } bool init() { return on_init(); }
void load(cereal::BinaryInputArchive& ar) { m_state = On; on_load(ar); }
void save(cereal::BinaryOutputArchive& ar) const { on_save(ar); }
std::string get_name() const { return on_get_name(); } std::string get_name() const { return on_get_name(); }
int get_group_id() const { return m_group_id; } int get_group_id() const { return m_group_id; }
@ -144,6 +148,8 @@ public:
protected: protected:
virtual bool on_init() = 0; virtual bool on_init() = 0;
virtual void on_load(cereal::BinaryInputArchive& ar) {}
virtual void on_save(cereal::BinaryOutputArchive& ar) const {}
virtual std::string on_get_name() const = 0; virtual std::string on_get_name() const = 0;
virtual void on_set_state() {} virtual void on_set_state() {}
virtual void on_set_hover_id() {} virtual void on_set_hover_id() {}

View file

@ -28,7 +28,6 @@ GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, uns
, m_rotate_lower(false) , m_rotate_lower(false)
{} {}
bool GLGizmoCut::on_init() bool GLGizmoCut::on_init()
{ {
m_grabbers.emplace_back(); m_grabbers.emplace_back();

View file

@ -27,6 +27,8 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual void on_load(cereal::BinaryInputArchive& ar) { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
virtual void on_save(cereal::BinaryOutputArchive& ar) const { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual void on_set_state(); virtual void on_set_state();
virtual bool on_is_activable(const Selection& selection) const; virtual bool on_is_activable(const Selection& selection) const;

View file

@ -15,7 +15,8 @@ namespace GUI {
const float GLGizmosManager::Default_Icons_Size = 64; const float GLGizmosManager::Default_Icons_Size = 64;
GLGizmosManager::GLGizmosManager() GLGizmosManager::GLGizmosManager()
: m_enabled(false) : m_parent(nullptr)
, m_enabled(false)
, m_icons_texture_dirty(true) , m_icons_texture_dirty(true)
, m_current(Undefined) , m_current(Undefined)
, m_overlay_icons_size(Default_Icons_Size) , m_overlay_icons_size(Default_Icons_Size)
@ -23,6 +24,7 @@ GLGizmosManager::GLGizmosManager()
, m_overlay_border(5.0f) , m_overlay_border(5.0f)
, m_overlay_gap_y(5.0f) , m_overlay_gap_y(5.0f)
, m_tooltip("") , m_tooltip("")
, m_serializing(false)
{ {
} }
@ -33,6 +35,8 @@ GLGizmosManager::~GLGizmosManager()
bool GLGizmosManager::init(GLCanvas3D& parent) bool GLGizmosManager::init(GLCanvas3D& parent)
{ {
m_parent = &parent;
m_background_texture.metadata.filename = "toolbar_background.png"; m_background_texture.metadata.filename = "toolbar_background.png";
m_background_texture.metadata.left = 16; m_background_texture.metadata.left = 16;
m_background_texture.metadata.top = 16; m_background_texture.metadata.top = 16;
@ -135,12 +139,18 @@ void GLGizmosManager::set_overlay_scale(float scale)
} }
} }
void GLGizmosManager::refresh_on_off_state(const Selection& selection) void GLGizmosManager::refresh_on_off_state()
{ {
if (m_parent == nullptr)
return;
if (m_serializing)
return;
GizmosMap::iterator it = m_gizmos.find(m_current); GizmosMap::iterator it = m_gizmos.find(m_current);
if ((it != m_gizmos.end()) && (it->second != nullptr)) if ((it != m_gizmos.end()) && (it->second != nullptr))
{ {
if (!it->second->is_activable(selection)) if (!it->second->is_activable(m_parent->get_selection()))
{ {
it->second->set_state(GLGizmoBase::Off); it->second->set_state(GLGizmoBase::Off);
m_current = Undefined; m_current = Undefined;
@ -153,6 +163,9 @@ void GLGizmosManager::reset_all_states()
if (!m_enabled) if (!m_enabled)
return; return;
if (m_serializing)
return;
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
{ {
if (it->second != nullptr) if (it->second != nullptr)
@ -192,22 +205,22 @@ void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
} }
} }
void GLGizmosManager::update(const Linef3& mouse_ray, const Selection& selection, const Point* mouse_pos) void GLGizmosManager::update(const Linef3& mouse_ray, const Point* mouse_pos)
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos), selection); curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos), m_parent->get_selection());
} }
void GLGizmosManager::update_data(GLCanvas3D& canvas) void GLGizmosManager::update_data()
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
const Selection& selection = canvas.get_selection(); const Selection& selection = m_parent->get_selection();
bool is_wipe_tower = selection.is_wipe_tower(); bool is_wipe_tower = selection.is_wipe_tower();
enable_grabber(Move, 2, !is_wipe_tower); enable_grabber(Move, 2, !is_wipe_tower);
@ -228,7 +241,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_rotation(Vec3d::Zero()); set_rotation(Vec3d::Zero());
ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()]; ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()];
set_flattening_data(model_object); set_flattening_data(model_object);
set_sla_support_data(model_object, selection); set_sla_support_data(model_object);
} }
else if (selection.is_single_volume() || selection.is_single_modifier()) else if (selection.is_single_volume() || selection.is_single_modifier())
{ {
@ -236,7 +249,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_scale(volume->get_volume_scaling_factor()); set_scale(volume->get_volume_scaling_factor());
set_rotation(Vec3d::Zero()); set_rotation(Vec3d::Zero());
set_flattening_data(nullptr); set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection); set_sla_support_data(nullptr);
} }
else if (is_wipe_tower) else if (is_wipe_tower)
{ {
@ -244,14 +257,14 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_scale(Vec3d::Ones()); set_scale(Vec3d::Ones());
set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value)); set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value));
set_flattening_data(nullptr); set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection); set_sla_support_data(nullptr);
} }
else else
{ {
set_scale(Vec3d::Ones()); set_scale(Vec3d::Ones());
set_rotation(Vec3d::Zero()); set_rotation(Vec3d::Zero());
set_flattening_data(selection.is_from_single_object() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); set_flattening_data(selection.is_from_single_object() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr);
set_sla_support_data(nullptr, selection); set_sla_support_data(nullptr);
} }
} }
@ -264,9 +277,13 @@ bool GLGizmosManager::is_running() const
return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false; return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
} }
bool GLGizmosManager::handle_shortcut(int key, const Selection& selection) bool GLGizmosManager::handle_shortcut(int key)
{ {
if (!m_enabled || selection.is_empty()) if (!m_enabled || (m_parent == nullptr))
return false;
const Selection& selection = m_parent->get_selection();
if (selection.is_empty())
return false; return false;
EType old_current = m_current; EType old_current = m_current;
@ -314,14 +331,14 @@ bool GLGizmosManager::is_dragging() const
return (curr != nullptr) ? curr->is_dragging() : false; return (curr != nullptr) ? curr->is_dragging() : false;
} }
void GLGizmosManager::start_dragging(const Selection& selection) void GLGizmosManager::start_dragging()
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->start_dragging(selection); curr->start_dragging(m_parent->get_selection());
} }
void GLGizmosManager::stop_dragging() void GLGizmosManager::stop_dragging()
@ -409,14 +426,14 @@ void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object); reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
} }
void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Selection& selection) void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end()) if (it != m_gizmos.end())
reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, selection); reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, m_parent->get_selection());
} }
// Returns true if the gizmo used the event to do something, false otherwise. // Returns true if the gizmo used the event to do something, false otherwise.
@ -445,39 +462,42 @@ ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
} }
void GLGizmosManager::render_current_gizmo(const Selection& selection) const void GLGizmosManager::render_current_gizmo() const
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->render(selection); curr->render(m_parent->get_selection());
} }
void GLGizmosManager::render_current_gizmo_for_picking_pass(const Selection& selection) const void GLGizmosManager::render_current_gizmo_for_picking_pass() const
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->render_for_picking(selection); curr->render_for_picking(m_parent->get_selection());
} }
void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const void GLGizmosManager::render_overlay() const
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
if (m_icons_texture_dirty) if (m_icons_texture_dirty)
generate_icons_texture(); generate_icons_texture();
do_render_overlay(canvas, selection); do_render_overlay();
} }
bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas) bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt)
{ {
if (m_parent == nullptr)
return false;
bool processed = false; bool processed = false;
if (m_current == SlaSupports) { if (m_current == SlaSupports) {
@ -489,14 +509,15 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas)
return processed; return processed;
} }
bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
{ {
if (m_parent == nullptr)
return false;
Point pos(evt.GetX(), evt.GetY()); Point pos(evt.GetX(), evt.GetY());
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY()); Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
Selection& selection = canvas.get_selection(); Selection& selection = m_parent->get_selection();
int selected_object_idx = selection.get_object_idx(); int selected_object_idx = selection.get_object_idx();
bool processed = false; bool processed = false;
@ -512,7 +533,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
// mouse anywhere // mouse anywhere
if (evt.Moving()) if (evt.Moving())
m_tooltip = update_hover_state(canvas, mouse_pos); m_tooltip = update_hover_state(mouse_pos);
else if (evt.LeftUp()) else if (evt.LeftUp())
m_mouse_capture.left = false; m_mouse_capture.left = false;
else if (evt.MiddleUp()) else if (evt.MiddleUp())
@ -523,7 +544,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
// if the button down was done on this toolbar, prevent from dragging into the scene // if the button down was done on this toolbar, prevent from dragging into the scene
processed = true; processed = true;
if (!overlay_contains_mouse(canvas, mouse_pos)) if (!overlay_contains_mouse(mouse_pos))
{ {
// mouse is outside the toolbar // mouse is outside the toolbar
m_tooltip = ""; m_tooltip = "";
@ -535,40 +556,40 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
processed = true; processed = true;
else if (!selection.is_empty() && grabber_contains_mouse()) else if (!selection.is_empty() && grabber_contains_mouse())
{ {
update_data(canvas); update_data();
selection.start_dragging(); selection.start_dragging();
start_dragging(selection); start_dragging();
if (m_current == Flatten) if (m_current == Flatten)
{ {
// Rotate the object so the normal points downward: // Rotate the object so the normal points downward:
canvas.do_flatten(get_flattening_normal(), "Place on Face"); m_parent->do_flatten(get_flattening_normal(), "Gizmo - Place on Face");
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
} }
canvas.set_as_dirty(); m_parent->set_as_dirty();
processed = true; processed = true;
} }
} }
else if (evt.RightDown() && (selected_object_idx != -1) && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::RightDown)) else if (evt.RightDown() && (selected_object_idx != -1) && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::RightDown))
// event was taken care of by the SlaSupports gizmo // event was taken care of by the SlaSupports gizmo
processed = true; processed = true;
else if (evt.Dragging() && (canvas.get_move_volume_id() != -1) && (m_current == SlaSupports)) else if (evt.Dragging() && (m_parent->get_move_volume_id() != -1) && (m_current == SlaSupports))
// don't allow dragging objects with the Sla gizmo on // don't allow dragging objects with the Sla gizmo on
processed = true; processed = true;
else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown())) else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
{ {
// the gizmo got the event and took some action, no need to do anything more here // the gizmo got the event and took some action, no need to do anything more here
canvas.set_as_dirty(); m_parent->set_as_dirty();
processed = true; processed = true;
} }
else if (evt.Dragging() && is_dragging()) else if (evt.Dragging() && is_dragging())
{ {
if (!canvas.get_wxglcanvas()->HasCapture()) if (!m_parent->get_wxglcanvas()->HasCapture())
canvas.get_wxglcanvas()->CaptureMouse(); m_parent->get_wxglcanvas()->CaptureMouse();
canvas.set_mouse_as_dragging(); m_parent->set_mouse_as_dragging();
update(canvas.mouse_ray(pos), selection, &pos); update(m_parent->mouse_ray(pos), &pos);
switch (m_current) switch (m_current)
{ {
@ -605,7 +626,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
break; break;
} }
canvas.set_as_dirty(); m_parent->set_as_dirty();
processed = true; processed = true;
} }
else if (evt.LeftUp() && is_dragging()) else if (evt.LeftUp() && is_dragging())
@ -614,18 +635,18 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
{ {
case Move: case Move:
{ {
canvas.disable_regenerate_volumes(); m_parent->disable_regenerate_volumes();
canvas.do_move("Gizmo-Move Object"); m_parent->do_move("Gizmo-Move Object");
break; break;
} }
case Scale: case Scale:
{ {
canvas.do_scale("Gizmo-Scale Object"); m_parent->do_scale("Gizmo-Scale Object");
break; break;
} }
case Rotate: case Rotate:
{ {
canvas.do_rotate("Gizmo-Rotate Object"); m_parent->do_rotate("Gizmo-Rotate Object");
break; break;
} }
default: default:
@ -633,25 +654,25 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
} }
stop_dragging(); stop_dragging();
update_data(canvas); update_data();
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
// Let the platter know that the dragging finished, so a delayed refresh // Let the platter know that the dragging finished, so a delayed refresh
// of the scene with the background processing data should be performed. // of the scene with the background processing data should be performed.
canvas.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); m_parent->post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints // updates camera target constraints
canvas.refresh_camera_scene_box(); m_parent->refresh_camera_scene_box();
processed = true; processed = true;
} }
else if (evt.LeftUp() && (m_current == SlaSupports) && !canvas.is_mouse_dragging()) else if (evt.LeftUp() && (m_current == SlaSupports) && !m_parent->is_mouse_dragging())
{ {
// in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither // in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither
// object moving or selecting is suppressed in that case // object moving or selecting is suppressed in that case
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()); gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
processed = true; processed = true;
} }
else if (evt.LeftUp() && (m_current == Flatten) && ((canvas.get_first_hover_volume_idx() != -1) || grabber_contains_mouse())) else if (evt.LeftUp() && (m_current == Flatten) && ((m_parent->get_first_hover_volume_idx() != -1) || grabber_contains_mouse()))
{ {
// to avoid to loose the selection when user clicks an object while the Flatten gizmo is active // to avoid to loose the selection when user clicks an object while the Flatten gizmo is active
processed = true; processed = true;
@ -663,24 +684,24 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
if (evt.LeftDown() || evt.LeftDClick()) if (evt.LeftDown() || evt.LeftDClick())
{ {
m_mouse_capture.left = true; m_mouse_capture.left = true;
m_mouse_capture.parent = &canvas; m_mouse_capture.parent = m_parent;
processed = true; processed = true;
if (!selection.is_empty()) if (!selection.is_empty())
{ {
update_on_off_state(canvas, mouse_pos, selection); update_on_off_state(mouse_pos);
update_data(canvas); update_data();
canvas.set_as_dirty(); m_parent->set_as_dirty();
} }
} }
else if (evt.MiddleDown()) else if (evt.MiddleDown())
{ {
m_mouse_capture.middle = true; m_mouse_capture.middle = true;
m_mouse_capture.parent = &canvas; m_mouse_capture.parent = m_parent;
} }
else if (evt.RightDown()) else if (evt.RightDown())
{ {
m_mouse_capture.right = true; m_mouse_capture.right = true;
m_mouse_capture.parent = &canvas; m_mouse_capture.parent = m_parent;
} }
else if (evt.LeftUp()) else if (evt.LeftUp())
processed = true; processed = true;
@ -689,8 +710,11 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
return processed; return processed;
} }
bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas) bool GLGizmosManager::on_char(wxKeyEvent& evt)
{ {
if (m_parent == nullptr)
return false;
// see include/wx/defs.h enum wxKeyCode // see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode(); int keyCode = evt.GetKeyCode();
int ctrlMask = wxMOD_CONTROL; int ctrlMask = wxMOD_CONTROL;
@ -797,21 +821,24 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
if (!processed && !evt.HasModifiers()) if (!processed && !evt.HasModifiers())
{ {
if (handle_shortcut(keyCode, canvas.get_selection())) if (handle_shortcut(keyCode))
{ {
update_data(canvas); update_data();
processed = true; processed = true;
} }
} }
if (processed) if (processed)
canvas.set_as_dirty(); m_parent->set_as_dirty();
return processed; return processed;
} }
bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas) bool GLGizmosManager::on_key(wxKeyEvent& evt)
{ {
if (m_parent == nullptr)
return false;
const int keyCode = evt.GetKeyCode(); const int keyCode = evt.GetKeyCode();
bool processed = false; bool processed = false;
@ -836,23 +863,29 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
} }
// if (processed) // if (processed)
// canvas.set_cursor(GLCanvas3D::Standard); // m_parent->set_cursor(GLCanvas3D::Standard);
} }
else if (evt.GetEventType() == wxEVT_KEY_DOWN) else if (evt.GetEventType() == wxEVT_KEY_DOWN)
{ {
if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT)) && reinterpret_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode()) if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT)) && reinterpret_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
{ {
// canvas.set_cursor(GLCanvas3D::Cross); // m_parent->set_cursor(GLCanvas3D::Cross);
processed = true; processed = true;
} }
} }
if (processed) if (processed)
canvas.set_as_dirty(); m_parent->set_as_dirty();
return processed; return processed;
} }
void GLGizmosManager::update_after_undo_redo()
{
update_data();
m_serializing = false;
}
void GLGizmosManager::reset() void GLGizmosManager::reset()
{ {
for (GizmosMap::value_type& gizmo : m_gizmos) for (GizmosMap::value_type& gizmo : m_gizmos)
@ -864,14 +897,16 @@ void GLGizmosManager::reset()
m_gizmos.clear(); m_gizmos.clear();
} }
void GLGizmosManager::do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const void GLGizmosManager::do_render_overlay() const
{ {
if (m_gizmos.empty()) if ((m_parent == nullptr) || m_gizmos.empty())
return; return;
float cnv_w = (float)canvas.get_canvas_size().get_width(); const Selection& selection = m_parent->get_selection();
float cnv_h = (float)canvas.get_canvas_size().get_height();
float zoom = (float)canvas.get_camera().get_zoom(); float cnv_w = (float)m_parent->get_canvas_size().get_width();
float cnv_h = (float)m_parent->get_canvas_size().get_height();
float zoom = (float)m_parent->get_camera().get_zoom();
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
float height = get_total_overlay_height(); float height = get_total_overlay_height();
@ -984,7 +1019,7 @@ void GLGizmosManager::do_render_overlay(const GLCanvas3D& canvas, const Selectio
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (it->second->get_state() == GLGizmoBase::On) { if (it->second->get_state() == GLGizmoBase::On) {
float toolbar_top = (float)cnv_h - canvas.get_view_toolbar_height(); float toolbar_top = (float)cnv_h - m_parent->get_view_toolbar_height();
it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
} }
top_y -= scaled_stride_y; top_y -= scaled_stride_y;
@ -1047,12 +1082,14 @@ bool GLGizmosManager::generate_icons_texture() const
return res; return res;
} }
void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection) void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return; return;
float cnv_h = (float)canvas.get_canvas_size().get_height(); const Selection& selection = m_parent->get_selection();
float cnv_h = (float)m_parent->get_canvas_size().get_height();
float height = get_total_overlay_height(); float height = get_total_overlay_height();
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
@ -1091,16 +1128,16 @@ void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d&
it->second->set_state(GLGizmoBase::On); it->second->set_state(GLGizmoBase::On);
} }
std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
{ {
std::string name = ""; std::string name = "";
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return name; return name;
const Selection& selection = canvas.get_selection(); const Selection& selection = m_parent->get_selection();
float cnv_h = (float)canvas.get_canvas_size().get_height(); float cnv_h = (float)m_parent->get_canvas_size().get_height();
float height = get_total_overlay_height(); float height = get_total_overlay_height();
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
float scaled_border = m_overlay_border * m_overlay_scale; float scaled_border = m_overlay_border * m_overlay_scale;
@ -1126,12 +1163,12 @@ std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const
return name; return name;
} }
bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const bool GLGizmosManager::overlay_contains_mouse(const Vec2d& mouse_pos) const
{ {
if (!m_enabled) if (!m_enabled || (m_parent == nullptr))
return false; return false;
float cnv_h = (float)canvas.get_canvas_size().get_height(); float cnv_h = (float)m_parent->get_canvas_size().get_height();
float height = get_total_overlay_height(); float height = get_total_overlay_height();
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;

View file

@ -4,14 +4,13 @@
#include "slic3r/GUI/GLTexture.hpp" #include "slic3r/GUI/GLTexture.hpp"
#include "slic3r/GUI/GLToolbar.hpp" #include "slic3r/GUI/GLToolbar.hpp"
#include "slic3r/GUI/Gizmos/GLGizmos.hpp" #include "slic3r/GUI/Gizmos/GLGizmos.hpp"
#include "libslic3r/ObjectID.hpp"
#include <map> #include <map>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
class Selection;
class GLGizmoBase;
class GLCanvas3D; class GLCanvas3D;
class ClippingPlane; class ClippingPlane;
@ -43,7 +42,7 @@ public:
float get_height() const { return m_top - m_bottom; } float get_height() const { return m_top - m_bottom; }
}; };
class GLGizmosManager class GLGizmosManager : public Slic3r::ObjectBase
{ {
public: public:
static const float Default_Icons_Size; static const float Default_Icons_Size;
@ -61,6 +60,7 @@ public:
}; };
private: private:
GLCanvas3D* m_parent;
bool m_enabled; bool m_enabled;
typedef std::map<EType, GLGizmoBase*> GizmosMap; typedef std::map<EType, GLGizmoBase*> GizmosMap;
GizmosMap m_gizmos; GizmosMap m_gizmos;
@ -89,6 +89,7 @@ private:
MouseCapture m_mouse_capture; MouseCapture m_mouse_capture;
std::string m_tooltip; std::string m_tooltip;
bool m_serializing;
public: public:
GLGizmosManager(); GLGizmosManager();
@ -96,29 +97,59 @@ public:
bool init(GLCanvas3D& parent); bool init(GLCanvas3D& parent);
template<class Archive>
void load(Archive& ar)
{
if (!m_enabled)
return;
m_serializing = true;
ar(m_current);
GLGizmoBase* curr = get_current();
if (curr != nullptr)
{
curr->set_state(GLGizmoBase::On);
curr->load(ar);
}
}
template<class Archive>
void save(Archive& ar) const
{
if (!m_enabled)
return;
ar(m_current);
GLGizmoBase* curr = get_current();
if (curr != nullptr)
curr->save(ar);
}
bool is_enabled() const { return m_enabled; } bool is_enabled() const { return m_enabled; }
void set_enabled(bool enable) { m_enabled = enable; } void set_enabled(bool enable) { m_enabled = enable; }
void set_overlay_icon_size(float size); void set_overlay_icon_size(float size);
void set_overlay_scale(float scale); void set_overlay_scale(float scale);
void refresh_on_off_state(const Selection& selection); void refresh_on_off_state();
void reset_all_states(); void reset_all_states();
void set_hover_id(int id); void set_hover_id(int id);
void enable_grabber(EType type, unsigned int id, bool enable); void enable_grabber(EType type, unsigned int id, bool enable);
void update(const Linef3& mouse_ray, const Selection& selection, const Point* mouse_pos = nullptr); void update(const Linef3& mouse_ray, const Point* mouse_pos = nullptr);
void update_data(GLCanvas3D& canvas); void update_data();
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
EType get_current_type() const { return m_current; } EType get_current_type() const { return m_current; }
bool is_running() const; bool is_running() const;
bool handle_shortcut(int key, const Selection& selection); bool handle_shortcut(int key);
bool is_dragging() const; bool is_dragging() const;
void start_dragging(const Selection& selection); void start_dragging();
void stop_dragging(); void stop_dragging();
Vec3d get_displacement() const; Vec3d get_displacement() const;
@ -135,26 +166,28 @@ public:
void set_flattening_data(const ModelObject* model_object); void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const Selection& selection); void set_sla_support_data(ModelObject* model_object);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_sla_clipping_plane() const; ClippingPlane get_sla_clipping_plane() const;
void render_current_gizmo(const Selection& selection) const; void render_current_gizmo() const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const; void render_current_gizmo_for_picking_pass() const;
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; void render_overlay() const;
const std::string& get_tooltip() const { return m_tooltip; } const std::string& get_tooltip() const { return m_tooltip; }
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas); bool on_mouse(wxMouseEvent& evt);
bool on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas); bool on_mouse_wheel(wxMouseEvent& evt);
bool on_char(wxKeyEvent& evt, GLCanvas3D& canvas); bool on_char(wxKeyEvent& evt);
bool on_key(wxKeyEvent& evt, GLCanvas3D& canvas); bool on_key(wxKeyEvent& evt);
void update_after_undo_redo();
private: private:
void reset(); void reset();
void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; void do_render_overlay() const;
float get_total_overlay_height() const; float get_total_overlay_height() const;
float get_total_overlay_width() const; float get_total_overlay_width() const;
@ -163,13 +196,18 @@ private:
bool generate_icons_texture() const; bool generate_icons_texture() const;
void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const Vec2d& mouse_pos);
std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); std::string update_hover_state(const Vec2d& mouse_pos);
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool overlay_contains_mouse(const Vec2d& mouse_pos) const;
bool grabber_contains_mouse() const; bool grabber_contains_mouse() const;
}; };
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r
namespace cereal
{
template <class Archive> struct specialize<Archive, Slic3r::GUI::GLGizmosManager, cereal::specialization::member_load_save> {};
}
#endif // slic3r_GUI_GLGizmosManager_hpp_ #endif // slic3r_GUI_GLGizmosManager_hpp_

View file

@ -1633,8 +1633,8 @@ struct Plater::priv
if (this->m_prevent_snapshots > 0) if (this->m_prevent_snapshots > 0)
return; return;
assert(this->m_prevent_snapshots >= 0); assert(this->m_prevent_snapshots >= 0);
this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection()); this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager());
} }
void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); }
int get_active_snapshot_index(); int get_active_snapshot_index();
void undo(); void undo();
@ -3611,34 +3611,35 @@ int Plater::priv::get_active_snapshot_index()
void Plater::priv::undo() void Plater::priv::undo()
{ {
if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection())) if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager()))
this->update_after_undo_redo(); this->update_after_undo_redo();
} }
void Plater::priv::redo() void Plater::priv::redo()
{ {
if (this->undo_redo_stack.redo(model)) if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager()))
this->update_after_undo_redo(); this->update_after_undo_redo();
} }
void Plater::priv::undo_to(size_t time_to_load) void Plater::priv::undo_to(size_t time_to_load)
{ {
if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), time_to_load)) if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load))
this->update_after_undo_redo(); this->update_after_undo_redo();
} }
void Plater::priv::redo_to(size_t time_to_load) void Plater::priv::redo_to(size_t time_to_load)
{ {
if (this->undo_redo_stack.redo(model, time_to_load)) if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load))
this->update_after_undo_redo(); this->update_after_undo_redo();
} }
void Plater::priv::update_after_undo_redo() void Plater::priv::update_after_undo_redo()
{ {
this->view3D->get_canvas3d()->get_selection().clear(); this->view3D->get_canvas3d()->get_selection().clear();
this->update(false); // update volumes from the deserializd model this->update(false); // update volumes from the deserializd model
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time) //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances); this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances);
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo();
wxGetApp().obj_list()->update_after_undo_redo(); wxGetApp().obj_list()->update_after_undo_redo();
@ -3884,7 +3885,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return; return;
} }
this->take_snapshot(_(L("Cut"))); this->take_snapshot(_(L("Gizmo - Cut")));
wxBusyCursor wait; wxBusyCursor wait;
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower); const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);

View file

@ -17,8 +17,6 @@
#define CEREAL_FUTURE_EXPERIMENTAL #define CEREAL_FUTURE_EXPERIMENTAL
#include <cereal/archives/adapters.hpp> #include <cereal/archives/adapters.hpp>
#include <libslic3r/ObjectID.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#ifndef NDEBUG #ifndef NDEBUG
@ -358,18 +356,14 @@ public:
// Stack needs to be initialized. An empty stack is not valid, there must be a "New Project" status stored at the beginning. // Stack needs to be initialized. An empty stack is not valid, there must be a "New Project" status stored at the beginning.
StackImpl() : m_active_snapshot_time(0), m_current_time(0) {} StackImpl() : m_active_snapshot_time(0), m_current_time(0) {}
// The Undo / Redo stack is being initialized with an empty model and an empty selection. // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
// The first snapshot cannot be removed. void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos);
void initialize(const Slic3r::Model &model, const Slic3r::GUI::Selection &selection); void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos);
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
void take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection);
void load_snapshot(size_t timestamp, Slic3r::Model &model);
bool has_undo_snapshot() const; bool has_undo_snapshot() const;
bool has_redo_snapshot() const; bool has_redo_snapshot() const;
bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t jump_to_time); bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t jump_to_time);
bool redo(Slic3r::Model &model, size_t jump_to_time); bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t jump_to_time);
// Snapshot history (names with timestamps). // Snapshot history (names with timestamps).
const std::vector<Snapshot>& snapshots() const { return m_snapshots; } const std::vector<Snapshot>& snapshots() const { return m_snapshots; }
@ -551,6 +545,7 @@ namespace cereal
#include <libslic3r/Model.hpp> #include <libslic3r/Model.hpp>
#include <libslic3r/TriangleMesh.hpp> #include <libslic3r/TriangleMesh.hpp>
#include <slic3r/GUI/Selection.hpp> #include <slic3r/GUI/Selection.hpp>
#include <slic3r/GUI/Gizmos/GLGizmosManager.hpp>
namespace Slic3r { namespace Slic3r {
namespace UndoRedo { namespace UndoRedo {
@ -632,7 +627,7 @@ template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Sl
} }
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection) void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos)
{ {
// Release old snapshot data. // Release old snapshot data.
assert(m_active_snapshot_time <= m_current_time); assert(m_active_snapshot_time <= m_current_time);
@ -650,7 +645,8 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
for (unsigned int volume_idx : selection.get_volume_idxs()) for (unsigned int volume_idx : selection.get_volume_idxs())
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id); m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
this->save_mutable_object<Selection, Selection>(m_selection); this->save_mutable_object<Selection, Selection>(m_selection);
// Save the snapshot info. this->save_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos);
// Save the snapshot info.
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id); m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id);
m_active_snapshot_time = m_current_time; m_active_snapshot_time = m_current_time;
// Save snapshot info of the last "current" aka "top most" state, that is only being serialized // Save snapshot info of the last "current" aka "top most" state, that is only being serialized
@ -665,7 +661,7 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
#endif /* SLIC3R_UNDOREDO_DEBUG */ #endif /* SLIC3R_UNDOREDO_DEBUG */
} }
void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model &model) void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos)
{ {
// Find the snapshot by time. It must exist. // Find the snapshot by time. It must exist.
const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp)); const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp));
@ -679,7 +675,9 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model &model)
model.update_links_bottom_up_recursive(); model.update_links_bottom_up_recursive();
m_selection.volumes_and_instances.clear(); m_selection.volumes_and_instances.clear();
this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection); this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection);
// Sort the volumes so that we may use binary search. gizmos.reset_all_states();
this->load_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
// Sort the volumes so that we may use binary search.
std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end()); std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
this->m_active_snapshot_time = timestamp; this->m_active_snapshot_time = timestamp;
assert(this->valid()); assert(this->valid());
@ -699,8 +697,8 @@ bool StackImpl::has_redo_snapshot() const
return ++ it != m_snapshots.end(); return ++ it != m_snapshots.end();
} }
bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load) bool StackImpl::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load)
{ {
assert(this->valid()); assert(this->valid());
if (time_to_load == SIZE_MAX) { if (time_to_load == SIZE_MAX) {
auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time)); auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
@ -712,8 +710,8 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load))); assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) { if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) {
// The current state is temporary. The current state needs to be captured to be redoable. // The current state is temporary. The current state needs to be captured to be redoable.
this->take_snapshot(topmost_snapsnot_name, model, selection); this->take_snapshot(topmost_snapsnot_name, model, selection, gizmos);
// The line above entered another topmost_snapshot_name. // The line above entered another topmost_snapshot_name.
assert(m_snapshots.back().is_topmost()); assert(m_snapshots.back().is_topmost());
assert(! m_snapshots.back().is_topmost_captured()); assert(! m_snapshots.back().is_topmost_captured());
// Pop it back, it is not needed as there is now a captured topmost state. // Pop it back, it is not needed as there is now a captured topmost state.
@ -723,7 +721,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
assert(m_snapshots.back().is_topmost()); assert(m_snapshots.back().is_topmost());
assert(m_snapshots.back().is_topmost_captured()); assert(m_snapshots.back().is_topmost_captured());
} }
this->load_snapshot(time_to_load, model); this->load_snapshot(time_to_load, model, gizmos);
#ifdef SLIC3R_UNDOREDO_DEBUG #ifdef SLIC3R_UNDOREDO_DEBUG
std::cout << "After undo" << std::endl; std::cout << "After undo" << std::endl;
this->print(); this->print();
@ -731,8 +729,8 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
return true; return true;
} }
bool StackImpl::redo(Slic3r::Model &model, size_t time_to_load) bool StackImpl::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load)
{ {
assert(this->valid()); assert(this->valid());
if (time_to_load == SIZE_MAX) { if (time_to_load == SIZE_MAX) {
auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time)); auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
@ -742,7 +740,7 @@ bool StackImpl::redo(Slic3r::Model &model, size_t time_to_load)
} }
assert(time_to_load > m_active_snapshot_time); assert(time_to_load > m_active_snapshot_time);
assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load))); assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
this->load_snapshot(time_to_load, model); this->load_snapshot(time_to_load, model, gizmos);
#ifdef SLIC3R_UNDOREDO_DEBUG #ifdef SLIC3R_UNDOREDO_DEBUG
std::cout << "After redo" << std::endl; std::cout << "After redo" << std::endl;
this->print(); this->print();
@ -767,11 +765,11 @@ void StackImpl::collect_garbage()
// Wrappers of the private implementation. // Wrappers of the private implementation.
Stack::Stack() : pimpl(new StackImpl()) {} Stack::Stack() : pimpl(new StackImpl()) {}
Stack::~Stack() {} Stack::~Stack() {}
void Stack::take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection) { pimpl->take_snapshot(snapshot_name, model, selection); } void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos) { pimpl->take_snapshot(snapshot_name, model, selection, gizmos); }
bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); } bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); }
bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); } bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); }
bool Stack::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load) { return pimpl->undo(model, selection, time_to_load); } bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->undo(model, selection, gizmos, time_to_load); }
bool Stack::redo(Slic3r::Model &model, size_t time_to_load) { return pimpl->redo(model, time_to_load); } bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->redo(model, gizmos, time_to_load); }
const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); }
const std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); } const std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); }

View file

@ -15,6 +15,7 @@ class Model;
namespace GUI { namespace GUI {
class Selection; class Selection;
class GLGizmosManager;
} // namespace GUI } // namespace GUI
namespace UndoRedo { namespace UndoRedo {
@ -56,7 +57,7 @@ public:
~Stack(); ~Stack();
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
void take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection); void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos);
// To be queried to enable / disable the Undo / Redo buttons at the UI. // To be queried to enable / disable the Undo / Redo buttons at the UI.
bool has_undo_snapshot() const; bool has_undo_snapshot() const;
@ -64,10 +65,10 @@ public:
// Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated. // Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated.
// Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible. // Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible.
bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load = SIZE_MAX); bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX);
// Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated. // Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated.
bool redo(Slic3r::Model &model, size_t time_to_load = SIZE_MAX); bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX);
// Snapshot history (names with timestamps). // Snapshot history (names with timestamps).
// Each snapshot indicates start of an interval in which this operation is performed. // Each snapshot indicates start of an interval in which this operation is performed.