Merge remote-tracking branch 'remotes/origin/master' into vb_undo_redo2

This commit is contained in:
bubnikv 2019-07-17 15:54:57 +02:00
commit 7176599a34
25 changed files with 544 additions and 366 deletions

View file

@ -2811,17 +2811,16 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
gcode += m_ooze_prevention.pre_toolchange(*this); gcode += m_ooze_prevention.pre_toolchange(*this);
const std::string& toolchange_gcode = m_config.toolchange_gcode.value; const std::string& toolchange_gcode = m_config.toolchange_gcode.value;
if (m_writer.extruder() != nullptr) {
// Process the custom toolchange_gcode. If it is empty, insert just a Tn command. // Process the custom toolchange_gcode. If it is empty, insert just a Tn command.
if (!toolchange_gcode.empty()) { if (!toolchange_gcode.empty()) {
DynamicConfig config; DynamicConfig config;
config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id())); config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.extruder() != nullptr ? m_writer.extruder()->id() : -1 )));
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id)); config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config); gcode += placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config);
check_add_eol(gcode); check_add_eol(gcode);
}
} }
// We inform the writer about what is happening, but we may not use the resulting gcode. // We inform the writer about what is happening, but we may not use the resulting gcode.

View file

@ -604,6 +604,7 @@ void GLCanvas3D::LayersEditing::accept_changes(GLCanvas3D& canvas)
{ {
if (last_object_id >= 0) { if (last_object_id >= 0) {
if (m_layer_height_profile_modified) { if (m_layer_height_profile_modified) {
wxGetApp().plater()->take_snapshot(_(L("Layers heights")));
const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile; const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile;
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
@ -1202,6 +1203,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
, m_camera(camera) , m_camera(camera)
, m_view_toolbar(view_toolbar) , m_view_toolbar(view_toolbar)
, m_toolbar(GLToolbar::Normal, "Top") , m_toolbar(GLToolbar::Normal, "Top")
, m_gizmos(*this)
, m_use_clipping_planes(false) , m_use_clipping_planes(false)
, m_sidebar_field("") , m_sidebar_field("")
, m_keep_dirty(false) , m_keep_dirty(false)
@ -1318,7 +1320,7 @@ bool GLCanvas3D::init()
// if (!m_volumes.empty()) // if (!m_volumes.empty())
// m_volumes.finalize_geometry(); // m_volumes.finalize_geometry();
if (m_gizmos.is_enabled() && !m_gizmos.init(*this)) if (m_gizmos.is_enabled() && !m_gizmos.init())
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl; std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
if (!_init_toolbar()) if (!_init_toolbar())
@ -1719,7 +1721,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));
} }
@ -1793,7 +1795,7 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
void GLCanvas3D::mirror_selection(Axis axis) void GLCanvas3D::mirror_selection(Axis axis)
{ {
m_selection.mirror(axis); m_selection.mirror(axis);
do_mirror("Mirror Object"); do_mirror(L("Mirror Object"));
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
} }
@ -2082,8 +2084,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 +2325,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 +2452,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 +2562,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 +2690,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 +2817,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;
} }
@ -2948,7 +2950,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging) else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
{ {
m_regenerate_volumes = false; m_regenerate_volumes = false;
do_move("Move Object"); do_move(L("Move Object"));
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
// Let the plater know that the dragging finished, so a delayed refresh // Let the plater 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.
@ -2985,9 +2987,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();
@ -3113,7 +3115,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
return; return;
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type))); wxGetApp().plater()->take_snapshot(_(snapshot_type));
std::set<std::pair<int, int>> done; // keeps track of modified instances std::set<std::pair<int, int>> done; // keeps track of modified instances
bool object_moved = false; bool object_moved = false;
@ -3175,7 +3177,7 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
return; return;
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type))); wxGetApp().plater()->take_snapshot(_(snapshot_type));
std::set<std::pair<int, int>> done; // keeps track of modified instances std::set<std::pair<int, int>> done; // keeps track of modified instances
@ -3235,7 +3237,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
return; return;
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type))); wxGetApp().plater()->take_snapshot(_(snapshot_type));
std::set<std::pair<int, int>> done; // keeps track of modified instances std::set<std::pair<int, int>> done; // keeps track of modified instances
@ -3289,10 +3291,10 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_type) void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_type)
{ {
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type))); wxGetApp().plater()->take_snapshot(_(snapshot_type));
m_selection.flattening_rotate(normal); m_selection.flattening_rotate(normal);
do_rotate(""); // avoid taking another snapshot do_rotate(L("")); // avoid taking another snapshot
} }
void GLCanvas3D::do_mirror(const std::string& snapshot_type) void GLCanvas3D::do_mirror(const std::string& snapshot_type)
@ -3301,7 +3303,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
return; return;
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type))); wxGetApp().plater()->take_snapshot(_(snapshot_type));
std::set<std::pair<int, int>> done; // keeps track of modified instances std::set<std::pair<int, int>> done; // keeps track of modified instances
@ -3355,8 +3357,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 +3764,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 +4074,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 +4090,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 +5663,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

@ -242,7 +242,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL); selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_volumes(); selection.synchronize_unselected_volumes();
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing. // Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
canvas->do_mirror("Set Mirror"); canvas->do_mirror(L("Set Mirror"));
UpdateAndShow(true); UpdateAndShow(true);
}); });
return sizer; return sizer;
@ -323,7 +323,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL); selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_volumes(); selection.synchronize_unselected_volumes();
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing. // Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
canvas->do_rotate("Set Rotation"); canvas->do_rotate(L("Set Rotation"));
UpdateAndShow(true); UpdateAndShow(true);
}); });
@ -709,7 +709,7 @@ void ObjectManipulation::change_position_value(int axis, double value)
Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
selection.start_dragging(); selection.start_dragging();
selection.translate(position - m_cache.position, selection.requires_local_axes()); selection.translate(position - m_cache.position, selection.requires_local_axes());
canvas->do_move("Set Position"); canvas->do_move(L("Set Position"));
m_cache.position = position; m_cache.position = position;
m_cache.position_rounded(axis) = DBL_MAX; m_cache.position_rounded(axis) = DBL_MAX;
@ -740,7 +740,7 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
selection.rotate( selection.rotate(
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation), (M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
transformation_type); transformation_type);
canvas->do_rotate("Set Orientation"); canvas->do_rotate(L("Set Orientation"));
m_cache.rotation = rotation; m_cache.rotation = rotation;
m_cache.rotation_rounded(axis) = DBL_MAX; m_cache.rotation_rounded(axis) = DBL_MAX;
@ -805,7 +805,7 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
selection.start_dragging(); selection.start_dragging();
selection.scale(scaling_factor * 0.01, transformation_type); selection.scale(scaling_factor * 0.01, transformation_type);
wxGetApp().plater()->canvas3D()->do_scale("Set Scale"); wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
} }
void ObjectManipulation::on_change(t_config_option_key opt_key, const boost::any& value) void ObjectManipulation::on_change(t_config_option_key opt_key, const boost::any& value)

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)
@ -179,7 +180,7 @@ void GLGizmoBase::disable_grabber(unsigned int id)
on_disable_grabber(id); on_disable_grabber(id);
} }
void GLGizmoBase::start_dragging(const Selection& selection) void GLGizmoBase::start_dragging()
{ {
m_dragging = true; m_dragging = true;
@ -188,7 +189,7 @@ void GLGizmoBase::start_dragging(const Selection& selection)
m_grabbers[i].dragging = (m_hover_id == i); m_grabbers[i].dragging = (m_hover_id == i);
} }
on_start_dragging(selection); on_start_dragging();
} }
void GLGizmoBase::stop_dragging() void GLGizmoBase::stop_dragging()
@ -203,10 +204,10 @@ void GLGizmoBase::stop_dragging()
on_stop_dragging(); on_stop_dragging();
} }
void GLGizmoBase::update(const UpdateData& data, const Selection& selection) void GLGizmoBase::update(const UpdateData& data)
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
on_update(data, selection); on_update(data);
} }
std::array<float, 3> GLGizmoBase::picking_color_component(unsigned int id) const std::array<float, 3> GLGizmoBase::picking_color_component(unsigned int id) const

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;
@ -75,10 +76,10 @@ public:
struct UpdateData struct UpdateData
{ {
const Linef3 mouse_ray; const Linef3& mouse_ray;
const Point* mouse_pos; const Point& mouse_pos;
UpdateData(const Linef3& mouse_ray, const Point* mouse_pos = nullptr) UpdateData(const Linef3& mouse_ray, const Point& mouse_pos)
: mouse_ray(mouse_ray), mouse_pos(mouse_pos) : mouse_ray(mouse_ray), mouse_pos(mouse_pos)
{} {}
}; };
@ -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; }
@ -118,7 +122,7 @@ public:
const std::string& get_icon_filename() const { return m_icon_filename; } const std::string& get_icon_filename() const { return m_icon_filename; }
bool is_activable(const Selection& selection) const { return on_is_activable(selection); } bool is_activable() const { return on_is_activable(); }
bool is_selectable() const { return on_is_selectable(); } bool is_selectable() const { return on_is_selectable(); }
unsigned int get_sprite_id() const { return m_sprite_id; } unsigned int get_sprite_id() const { return m_sprite_id; }
@ -131,32 +135,34 @@ public:
void enable_grabber(unsigned int id); void enable_grabber(unsigned int id);
void disable_grabber(unsigned int id); void disable_grabber(unsigned int id);
void start_dragging(const Selection& selection); void start_dragging();
void stop_dragging(); void stop_dragging();
bool is_dragging() const { return m_dragging; } bool is_dragging() const { return m_dragging; }
void update(const UpdateData& data, const Selection& selection); void update(const UpdateData& data);
void render(const Selection& selection) const { on_render(selection); } void render() const { on_render(); }
void render_for_picking(const Selection& selection) const { on_render_for_picking(selection); } void render_for_picking() const { on_render_for_picking(); }
void render_input_window(float x, float y, float bottom_limit, const Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); } void render_input_window(float x, float y, float bottom_limit) { on_render_input_window(x, y, bottom_limit); }
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() {}
virtual bool on_is_activable(const Selection& selection) const { return true; } virtual bool on_is_activable() const { return true; }
virtual bool on_is_selectable() const { return true; } virtual bool on_is_selectable() const { return true; }
virtual void on_enable_grabber(unsigned int id) {} virtual void on_enable_grabber(unsigned int id) {}
virtual void on_disable_grabber(unsigned int id) {} virtual void on_disable_grabber(unsigned int id) {}
virtual void on_start_dragging(const Selection& selection) {} virtual void on_start_dragging() {}
virtual void on_stop_dragging() {} virtual void on_stop_dragging() {}
virtual void on_update(const UpdateData& data, const Selection& selection) = 0; virtual void on_update(const UpdateData& data) {}
virtual void on_render(const Selection& selection) const = 0; virtual void on_render() const = 0;
virtual void on_render_for_picking(const Selection& selection) const = 0; virtual void on_render_for_picking() const = 0;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) {} virtual void on_render_input_window(float x, float y, float bottom_limit) {}
// Returns the picking color for the given id, based on the BASE_ID constant // Returns the picking color for the given id, based on the BASE_ID constant
// No check is made for clashing with other picking color (i.e. GLVolumes) // No check is made for clashing with other picking color (i.e. GLVolumes)

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();
@ -49,15 +48,18 @@ void GLGizmoCut::on_set_state()
} }
} }
bool GLGizmoCut::on_is_activable(const Selection& selection) const bool GLGizmoCut::on_is_activable() const
{ {
const Selection& selection = m_parent.get_selection();
return selection.is_single_full_instance() && !selection.is_wipe_tower(); return selection.is_single_full_instance() && !selection.is_wipe_tower();
} }
void GLGizmoCut::on_start_dragging(const Selection& selection) void GLGizmoCut::on_start_dragging()
{ {
if (m_hover_id == -1) { return; } if (m_hover_id == -1)
return;
const Selection& selection = m_parent.get_selection();
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = selection.get_bounding_box();
m_start_z = m_cut_z; m_start_z = m_cut_z;
update_max_z(selection); update_max_z(selection);
@ -66,19 +68,21 @@ void GLGizmoCut::on_start_dragging(const Selection& selection)
m_drag_center(2) = m_cut_z; m_drag_center(2) = m_cut_z;
} }
void GLGizmoCut::on_update(const UpdateData& data, const Selection& selection) void GLGizmoCut::on_update(const UpdateData& data)
{ {
if (m_hover_id != -1) { if (m_hover_id != -1) {
set_cut_z(m_start_z + calc_projection(data.mouse_ray)); set_cut_z(m_start_z + calc_projection(data.mouse_ray));
} }
} }
void GLGizmoCut::on_render(const Selection& selection) const void GLGizmoCut::on_render() const
{ {
if (m_grabbers[0].dragging) { if (m_grabbers[0].dragging) {
set_tooltip("Z: " + format(m_cut_z, 2)); set_tooltip("Z: " + format(m_cut_z, 2));
} }
const Selection& selection = m_parent.get_selection();
update_max_z(selection); update_max_z(selection);
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = selection.get_bounding_box();
@ -124,14 +128,13 @@ void GLGizmoCut::on_render(const Selection& selection) const
m_grabbers[0].render(m_hover_id == 0, (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0)); m_grabbers[0].render(m_hover_id == 0, (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0));
} }
void GLGizmoCut::on_render_for_picking(const Selection& selection) const void GLGizmoCut::on_render_for_picking() const
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
render_grabbers_for_picking(selection.get_bounding_box());
} }
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
{ {
const float approx_height = m_imgui->scaled(11.0f); const float approx_height = m_imgui->scaled(11.0f);
y = std::min(y, bottom_limit - approx_height); y = std::min(y, bottom_limit - approx_height);
@ -154,7 +157,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co
m_imgui->end(); m_imgui->end();
if (cut_clicked && (m_keep_upper || m_keep_lower)) { if (cut_clicked && (m_keep_upper || m_keep_lower)) {
perform_cut(selection); perform_cut(m_parent.get_selection());
} }
} }

View file

@ -27,14 +27,16 @@ 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;
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection); virtual void on_update(const UpdateData& data);
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking() const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit);
private: private:
void update_max_z(const Selection& selection) const; void update_max_z(const Selection& selection) const;

View file

@ -1,5 +1,7 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoFlatten.hpp" #include "GLGizmoFlatten.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include <numeric> #include <numeric>
@ -22,28 +24,46 @@ bool GLGizmoFlatten::on_init()
return true; return true;
} }
void GLGizmoFlatten::on_set_state()
{
// m_model_object pointer can be invalid (for instance because of undo/redo action),
// we should recover it from the object id
m_model_object = nullptr;
for (const auto mo : *wxGetApp().model_objects()) {
if (mo->id() == m_model_object_id) {
m_model_object = mo;
break;
}
}
if (m_state == On && is_plane_update_necessary())
update_planes();
}
std::string GLGizmoFlatten::on_get_name() const std::string GLGizmoFlatten::on_get_name() const
{ {
return (_(L("Place on face")) + " [F]").ToUTF8().data(); return (_(L("Place on face")) + " [F]").ToUTF8().data();
} }
bool GLGizmoFlatten::on_is_activable(const Selection& selection) const bool GLGizmoFlatten::on_is_activable() const
{ {
return selection.is_single_full_instance(); return m_parent.get_selection().is_single_full_instance();
} }
void GLGizmoFlatten::on_start_dragging(const Selection& selection) void GLGizmoFlatten::on_start_dragging()
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
assert(m_planes_valid); assert(m_planes_valid);
m_normal = m_planes[m_hover_id].normal; m_normal = m_planes[m_hover_id].normal;
m_starting_center = selection.get_bounding_box().center(); m_starting_center = m_parent.get_selection().get_bounding_box().center();
} }
} }
void GLGizmoFlatten::on_render(const Selection& selection) const void GLGizmoFlatten::on_render() const
{ {
const Selection& selection = m_parent.get_selection();
glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
@ -78,8 +98,10 @@ void GLGizmoFlatten::on_render(const Selection& selection) const
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
void GLGizmoFlatten::on_render_for_picking(const Selection& selection) const void GLGizmoFlatten::on_render_for_picking() const
{ {
const Selection& selection = m_parent.get_selection();
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
@ -115,6 +137,7 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
m_planes_valid = false; m_planes_valid = false;
} }
m_model_object = model_object; m_model_object = model_object;
m_model_object_id = model_object ? model_object->id() : 0;
} }
void GLGizmoFlatten::update_planes() void GLGizmoFlatten::update_planes()

View file

@ -31,6 +31,7 @@ private:
bool m_planes_valid = false; bool m_planes_valid = false;
mutable Vec3d m_starting_center; mutable Vec3d m_starting_center;
const ModelObject* m_model_object = nullptr; const ModelObject* m_model_object = nullptr;
ObjectID m_model_object_id = 0;
std::vector<const Transform3d*> instances_matrices; std::vector<const Transform3d*> instances_matrices;
void update_planes(); void update_planes();
@ -45,16 +46,11 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const Selection& selection) const; virtual bool on_is_activable() const;
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection) {} virtual void on_render() const;
virtual void on_render(const Selection& selection) const; virtual void on_render_for_picking() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_set_state() override;
virtual void on_set_state()
{
if (m_state == On && is_plane_update_necessary())
update_planes();
}
}; };
} // namespace GUI } // namespace GUI

View file

@ -1,5 +1,6 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoMove.hpp" #include "GLGizmoMove.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -47,12 +48,12 @@ std::string GLGizmoMove3D::on_get_name() const
return (_(L("Move")) + " [M]").ToUTF8().data(); return (_(L("Move")) + " [M]").ToUTF8().data();
} }
void GLGizmoMove3D::on_start_dragging(const Selection& selection) void GLGizmoMove3D::on_start_dragging()
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
m_displacement = Vec3d::Zero(); m_displacement = Vec3d::Zero();
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
m_starting_drag_position = m_grabbers[m_hover_id].center; m_starting_drag_position = m_grabbers[m_hover_id].center;
m_starting_box_center = box.center(); m_starting_box_center = box.center();
m_starting_box_bottom_center = box.center(); m_starting_box_bottom_center = box.center();
@ -65,7 +66,7 @@ void GLGizmoMove3D::on_stop_dragging()
m_displacement = Vec3d::Zero(); m_displacement = Vec3d::Zero();
} }
void GLGizmoMove3D::on_update(const UpdateData& data, const Selection& selection) void GLGizmoMove3D::on_update(const UpdateData& data)
{ {
if (m_hover_id == 0) if (m_hover_id == 0)
m_displacement(0) = calc_projection(data); m_displacement(0) = calc_projection(data);
@ -75,8 +76,10 @@ void GLGizmoMove3D::on_update(const UpdateData& data, const Selection& selection
m_displacement(2) = calc_projection(data); m_displacement(2) = calc_projection(data);
} }
void GLGizmoMove3D::on_render(const Selection& selection) const void GLGizmoMove3D::on_render() const
{ {
const Selection& selection = m_parent.get_selection();
bool show_position = selection.is_single_full_instance(); bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center(); const Vec3d& position = selection.get_bounding_box().center();
@ -152,20 +155,21 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
} }
} }
void GLGizmoMove3D::on_render_for_picking(const Selection& selection) const void GLGizmoMove3D::on_render_for_picking() const
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
render_grabbers_for_picking(box); render_grabbers_for_picking(box);
render_grabber_extension(X, box, true); render_grabber_extension(X, box, true);
render_grabber_extension(Y, box, true); render_grabber_extension(Y, box, true);
render_grabber_extension(Z, box, true); render_grabber_extension(Z, box, true);
} }
void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit)
{
const Selection& selection = m_parent.get_selection();
bool show_position = selection.is_single_full_instance(); bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center(); const Vec3d& position = selection.get_bounding_box().center();
@ -178,8 +182,8 @@ void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit,
m_imgui->input_vec3("", displacement, 100.0f, "%.2f"); m_imgui->input_vec3("", displacement, 100.0f, "%.2f");
m_imgui->end(); m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
} }
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
double GLGizmoMove3D::calc_projection(const UpdateData& data) const double GLGizmoMove3D::calc_projection(const UpdateData& data) const
{ {

View file

@ -33,12 +33,14 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_stop_dragging(); virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection); virtual void on_update(const UpdateData& data);
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking() const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection); #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit);
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
private: private:
double calc_projection(const UpdateData& data) const; double calc_projection(const UpdateData& data) const;

View file

@ -1,5 +1,6 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoRotate.hpp" #include "GLGizmoRotate.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -72,9 +73,9 @@ bool GLGizmoRotate::on_init()
return true; return true;
} }
void GLGizmoRotate::on_start_dragging(const Selection& selection) void GLGizmoRotate::on_start_dragging()
{ {
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
m_center = box.center(); m_center = box.center();
m_radius = Offset + box.radius(); m_radius = Offset + box.radius();
m_snap_coarse_in_radius = m_radius / 3.0f; m_snap_coarse_in_radius = m_radius / 3.0f;
@ -83,9 +84,9 @@ void GLGizmoRotate::on_start_dragging(const Selection& selection)
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
} }
void GLGizmoRotate::on_update(const UpdateData& data, const Selection& selection) void GLGizmoRotate::on_update(const UpdateData& data)
{ {
Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection)); Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection()));
Vec2d orig_dir = Vec2d::UnitX(); Vec2d orig_dir = Vec2d::UnitX();
Vec2d new_dir = mouse_pos.normalized(); Vec2d new_dir = mouse_pos.normalized();
@ -118,11 +119,12 @@ void GLGizmoRotate::on_update(const UpdateData& data, const Selection& selection
m_angle = theta; m_angle = theta;
} }
void GLGizmoRotate::on_render(const Selection& selection) const void GLGizmoRotate::on_render() const
{ {
if (!m_grabbers[0].enabled) if (!m_grabbers[0].enabled)
return; return;
const Selection& selection = m_parent.get_selection();
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = selection.get_bounding_box();
std::string axis; std::string axis;
@ -175,8 +177,10 @@ void GLGizmoRotate::on_render(const Selection& selection) const
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
} }
void GLGizmoRotate::on_render_for_picking(const Selection& selection) const void GLGizmoRotate::on_render_for_picking() const
{ {
const Selection& selection = m_parent.get_selection();
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
@ -445,10 +449,10 @@ std::string GLGizmoRotate3D::on_get_name() const
return (_(L("Rotate")) + " [R]").ToUTF8().data(); return (_(L("Rotate")) + " [R]").ToUTF8().data();
} }
void GLGizmoRotate3D::on_start_dragging(const Selection& selection) void GLGizmoRotate3D::on_start_dragging()
{ {
if ((0 <= m_hover_id) && (m_hover_id < 3)) if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].start_dragging(selection); m_gizmos[m_hover_id].start_dragging();
} }
void GLGizmoRotate3D::on_stop_dragging() void GLGizmoRotate3D::on_stop_dragging()
@ -457,23 +461,23 @@ void GLGizmoRotate3D::on_stop_dragging()
m_gizmos[m_hover_id].stop_dragging(); m_gizmos[m_hover_id].stop_dragging();
} }
void GLGizmoRotate3D::on_render(const Selection& selection) const void GLGizmoRotate3D::on_render() const
{ {
glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
if ((m_hover_id == -1) || (m_hover_id == 0)) if ((m_hover_id == -1) || (m_hover_id == 0))
m_gizmos[X].render(selection); m_gizmos[X].render();
if ((m_hover_id == -1) || (m_hover_id == 1)) if ((m_hover_id == -1) || (m_hover_id == 1))
m_gizmos[Y].render(selection); m_gizmos[Y].render();
if ((m_hover_id == -1) || (m_hover_id == 2)) if ((m_hover_id == -1) || (m_hover_id == 2))
m_gizmos[Z].render(selection); m_gizmos[Z].render();
} }
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
{
Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle())); Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));
wxString label = _(L("Rotation (deg)")); wxString label = _(L("Rotation (deg)"));
@ -482,8 +486,8 @@ void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limi
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", rotation, 100.0f, "%.2f"); m_imgui->input_vec3("", rotation, 100.0f, "%.2f");
m_imgui->end(); m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
} }
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI

View file

@ -52,10 +52,10 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const { return ""; } virtual std::string on_get_name() const { return ""; }
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection); virtual void on_update(const UpdateData& data);
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking() const;
private: private:
void render_circle() const; void render_circle() const;
@ -98,7 +98,6 @@ protected:
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
} }
} }
virtual bool on_is_activable(const Selection& selection) const { return true; }
virtual void on_enable_grabber(unsigned int id) virtual void on_enable_grabber(unsigned int id)
{ {
if ((0 <= id) && (id < 3)) if ((0 <= id) && (id < 3))
@ -109,25 +108,26 @@ protected:
if ((0 <= id) && (id < 3)) if ((0 <= id) && (id < 3))
m_gizmos[id].disable_grabber(0); m_gizmos[id].disable_grabber(0);
} }
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_stop_dragging(); virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection) virtual void on_update(const UpdateData& data)
{ {
for (GLGizmoRotate& g : m_gizmos) for (GLGizmoRotate& g : m_gizmos)
{ {
g.update(data, selection); g.update(data);
} }
} }
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const virtual void on_render_for_picking() const
{ {
for (const GLGizmoRotate& g : m_gizmos) for (const GLGizmoRotate& g : m_gizmos)
{ {
g.render_for_picking(selection); g.render_for_picking();
} }
} }
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit);
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
}; };

View file

@ -1,7 +1,6 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoScale.hpp" #include "GLGizmoScale.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -48,13 +47,18 @@ std::string GLGizmoScale3D::on_get_name() const
return (_(L("Scale")) + " [S]").ToUTF8().data(); return (_(L("Scale")) + " [S]").ToUTF8().data();
} }
void GLGizmoScale3D::on_start_dragging(const Selection& selection) bool GLGizmoScale3D::on_is_activable() const
{
return !m_parent.get_selection().is_wipe_tower();
}
void GLGizmoScale3D::on_start_dragging()
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
m_starting.drag_position = m_grabbers[m_hover_id].center; m_starting.drag_position = m_grabbers[m_hover_id].center;
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : selection.get_bounding_box(); m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box();
const Vec3d& center = m_starting.box.center(); const Vec3d& center = m_starting.box.center();
m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max(0), center(1), center(2)); m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max(0), center(1), center(2));
@ -66,7 +70,7 @@ void GLGizmoScale3D::on_start_dragging(const Selection& selection)
} }
} }
void GLGizmoScale3D::on_update(const UpdateData& data, const Selection& selection) void GLGizmoScale3D::on_update(const UpdateData& data)
{ {
if ((m_hover_id == 0) || (m_hover_id == 1)) if ((m_hover_id == 0) || (m_hover_id == 1))
do_scale_along_axis(X, data); do_scale_along_axis(X, data);
@ -78,8 +82,10 @@ void GLGizmoScale3D::on_update(const UpdateData& data, const Selection& selectio
do_scale_uniform(data); do_scale_uniform(data);
} }
void GLGizmoScale3D::on_render(const Selection& selection) const void GLGizmoScale3D::on_render() const
{ {
const Selection& selection = m_parent.get_selection();
bool single_instance = selection.is_single_full_instance(); bool single_instance = selection.is_single_full_instance();
bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
bool single_selection = single_instance || single_volume; bool single_selection = single_instance || single_volume;
@ -272,16 +278,16 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
} }
} }
void GLGizmoScale3D::on_render_for_picking(const Selection& selection) const void GLGizmoScale3D::on_render_for_picking() const
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
render_grabbers_for_picking(selection.get_bounding_box());
} }
void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit)
{
const Selection& selection = m_parent.get_selection();
bool single_instance = selection.is_single_full_instance(); bool single_instance = selection.is_single_full_instance();
wxString label = _(L("Scale (%)")); wxString label = _(L("Scale (%)"));
@ -290,8 +296,8 @@ void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f"); m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f");
m_imgui->end(); m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
} }
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const
{ {

View file

@ -45,12 +45,14 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); } virtual bool on_is_activable() const;
virtual void on_start_dragging(const Selection& selection); virtual void on_start_dragging();
virtual void on_update(const UpdateData& data, const Selection& selection); virtual void on_update(const UpdateData& data);
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking() const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection); #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit);
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
private: private:
void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const;

View file

@ -94,8 +94,10 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
} }
} }
void GLGizmoSlaSupports::on_render(const Selection& selection) const void GLGizmoSlaSupports::on_render() const
{ {
const Selection& selection = m_parent.get_selection();
// If current m_model_object does not match selection, ask GLCanvas3D to turn us off // If current m_model_object does not match selection, ask GLCanvas3D to turn us off
if (m_state == On if (m_state == On
&& (m_model_object != selection.get_model()->objects[selection.get_object_idx()] && (m_model_object != selection.get_model()->objects[selection.get_object_idx()]
@ -104,6 +106,9 @@ void GLGizmoSlaSupports::on_render(const Selection& selection) const
return; return;
} }
if (! m_its || ! m_mesh)
const_cast<GLGizmoSlaSupports*>(this)->update_mesh();
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
@ -252,8 +257,9 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
} }
void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const void GLGizmoSlaSupports::on_render_for_picking() const
{ {
const Selection& selection = m_parent.get_selection();
#if ENABLE_RENDER_PICKING_PASS #if ENABLE_RENDER_PICKING_PASS
m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z(); m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z();
#endif #endif
@ -384,18 +390,26 @@ bool GLGizmoSlaSupports::is_mesh_update_necessary() const
void GLGizmoSlaSupports::update_mesh() void GLGizmoSlaSupports::update_mesh()
{ {
if (! m_model_object)
return;
wxBusyCursor wait; wxBusyCursor wait;
// this way we can use that mesh directly. // this way we can use that mesh directly.
// This mesh does not account for the possible Z up SLA offset. // This mesh does not account for the possible Z up SLA offset.
m_mesh = &m_model_object->volumes.front()->mesh(); m_mesh = &m_model_object->volumes.front()->mesh();
m_its = &m_mesh->its; m_its = &m_mesh->its;
// If this is different mesh than last time or if the AABB tree is uninitialized, recalculate it.
if (m_current_mesh_object_id != m_model_object->id() || (m_AABB.m_left == NULL && m_AABB.m_right == NULL))
{
m_AABB.deinit();
m_AABB.init(
MapMatrixXfUnaligned(m_its->vertices.front().data(), m_its->vertices.size(), 3),
MapMatrixXiUnaligned(m_its->indices.front().data(), m_its->indices.size(), 3));
}
m_current_mesh_object_id = m_model_object->id(); m_current_mesh_object_id = m_model_object->id();
m_editing_mode = false; m_editing_mode = false;
m_AABB.deinit();
m_AABB.init(
MapMatrixXfUnaligned(m_its->vertices.front().data(), m_its->vertices.size(), 3),
MapMatrixXiUnaligned(m_its->indices.front().data(), m_its->indices.size(), 3));
} }
// Unprojects the mouse position on the mesh and return the hit point and normal of the facet. // Unprojects the mouse position on the mesh and return the hit point and normal of the facet.
@ -702,12 +716,12 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
//m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
void GLGizmoSlaSupports::on_update(const UpdateData& data, const Selection& selection) void GLGizmoSlaSupports::on_update(const UpdateData& data)
{ {
if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { if (m_editing_mode && m_hover_id != -1 && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) {
std::pair<Vec3f, Vec3f> pos_and_normal; std::pair<Vec3f, Vec3f> pos_and_normal;
try { try {
pos_and_normal = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); pos_and_normal = unproject_on_mesh(data.mouse_pos.cast<double>());
} }
catch (...) { return; } catch (...) { return; }
m_editing_mode_cache[m_hover_id].support_point.pos = pos_and_normal.first; m_editing_mode_cache[m_hover_id].support_point.pos = pos_and_normal.first;
@ -822,7 +836,7 @@ void GLGizmoSlaSupports::make_line_segments() const
*/ */
void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit)
{ {
if (!m_model_object) if (!m_model_object)
return; return;
@ -1002,11 +1016,13 @@ RENDER_AGAIN:
m_parent.set_as_dirty(); m_parent.set_as_dirty();
} }
bool GLGizmoSlaSupports::on_is_activable(const Selection& selection) const bool GLGizmoSlaSupports::on_is_activable() const
{ {
const Selection& selection = m_parent.get_selection();
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|| !selection.is_from_single_instance()) || !selection.is_from_single_instance())
return false; return false;
// Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside. // Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside.
const Selection::IndicesList& list = selection.get_volume_idxs(); const Selection::IndicesList& list = selection.get_volume_idxs();
@ -1029,53 +1045,72 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state() void GLGizmoSlaSupports::on_set_state()
{ {
if (m_state == On && m_old_state != On) { // the gizmo was just turned on // m_model_object pointer can be invalid (for instance because of undo/redo action),
if (is_mesh_update_necessary()) // we should recover it from the object id
update_mesh(); const ModelObject* old_model_object = m_model_object;
m_model_object = nullptr;
// we'll now reload support points: for (const auto mo : *wxGetApp().model_objects()) {
if (m_model_object) if (mo->id() == m_current_mesh_object_id) {
editing_mode_reload_cache(); m_model_object = mo;
break;
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
} }
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off }
wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem // If ModelObject pointer really changed, invalidate mesh and do everything
// on OSX with the wxMessageDialog being shown several times when clicked into. // as if the gizmo was switched from Off state
if (m_model_object) { if (m_model_object == nullptr || old_model_object != m_model_object) {
if (m_unsaved_changes) { m_mesh = nullptr;
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points?")) + "\n", m_its = nullptr;
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO); m_old_state = Off;
if (dlg.ShowModal() == wxID_YES) }
editing_mode_apply_changes();
else if (m_state == On && m_old_state != On) { // the gizmo was just turned on
editing_mode_discard_changes(); if (is_mesh_update_necessary())
} update_mesh();
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points?")) + "\n",
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
} }
m_parent.toggle_model_objects_visibility(true); }
m_editing_mode = false; // so it is not active next time the gizmo opens m_parent.toggle_model_objects_visibility(true);
m_editing_mode_cache.clear(); m_editing_mode = false; // so it is not active next time the gizmo opens
m_clipping_plane_distance = 0.f; m_editing_mode_cache.clear();
// Release triangle mesh slicer and the AABB spatial search structure. m_clipping_plane_distance = 0.f;
m_AABB.deinit(); // Release triangle mesh slicer and the AABB spatial search structure.
m_its = nullptr; m_AABB.deinit();
m_tms.reset(); m_its = nullptr;
m_supports_tms.reset(); m_tms.reset();
}); m_supports_tms.reset();
} });
m_old_state = m_state; }
m_old_state = m_state;
} }
void GLGizmoSlaSupports::on_start_dragging(const Selection& selection) void GLGizmoSlaSupports::on_start_dragging()
{ {
if (m_hover_id != -1) { if (m_hover_id != -1) {
select_point(NoPoints); select_point(NoPoints);
@ -1085,6 +1120,26 @@ void GLGizmoSlaSupports::on_start_dragging(const Selection& selection)
void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar)
{
ar(m_clipping_plane_distance,
m_clipping_plane_normal,
m_current_mesh_object_id
);
}
void GLGizmoSlaSupports::on_save(cereal::BinaryOutputArchive& ar) const
{
ar(m_clipping_plane_distance,
m_clipping_plane_normal,
m_current_mesh_object_id
);
}
void GLGizmoSlaSupports::select_point(int i) void GLGizmoSlaSupports::select_point(int i)
{ {
if (i == AllPoints || i == NoPoints) { if (i == AllPoints || i == NoPoints) {
@ -1141,6 +1196,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
// If there are no changes, don't touch the front-end. The data in the cache could have been // If there are no changes, don't touch the front-end. The data in the cache could have been
// taken from the backend and copying them to ModelObject would needlessly invalidate them. // taken from the backend and copying them to ModelObject would needlessly invalidate them.
if (m_unsaved_changes) { if (m_unsaved_changes) {
wxGetApp().plater()->take_snapshot(_(L("Support points edit")));
m_model_object->sla_points_status = sla::PointsStatus::UserModified; m_model_object->sla_points_status = sla::PointsStatus::UserModified;
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
for (const CacheEntry& cache_entry : m_editing_mode_cache) for (const CacheEntry& cache_entry : m_editing_mode_cache)
@ -1199,6 +1255,7 @@ void GLGizmoSlaSupports::auto_generate()
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO); )), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) { if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) {
wxGetApp().plater()->take_snapshot(_(L("Autogenerate support points")));
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
m_model_object->sla_points_status = sla::PointsStatus::Generating; m_model_object->sla_points_status = sla::PointsStatus::Generating;
m_editing_mode_cache.clear(); m_editing_mode_cache.clear();

View file

@ -14,6 +14,8 @@
#include "libslic3r/SLAPrint.hpp" #include "libslic3r/SLAPrint.hpp"
#include <wx/dialog.h> #include <wx/dialog.h>
#include <cereal/types/vector.hpp>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -49,12 +51,21 @@ private:
class CacheEntry { class CacheEntry {
public: public:
CacheEntry() :
support_point(sla::SupportPoint()), selected(false), normal(Vec3f::Zero()) {}
CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) : CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) :
support_point(point), selected(sel), normal(norm) {} support_point(point), selected(sel), normal(norm) {}
sla::SupportPoint support_point; sla::SupportPoint support_point;
bool selected; // whether the point is selected bool selected; // whether the point is selected
Vec3f normal; Vec3f normal;
template<class Archive>
void serialize(Archive & ar)
{
ar(support_point, selected, normal);
}
}; };
public: public:
@ -70,9 +81,9 @@ public:
private: private:
bool on_init(); bool on_init();
void on_update(const UpdateData& data, const Selection& selection); void on_update(const UpdateData& data);
virtual void on_render(const Selection& selection) const; virtual void on_render() const;
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking() const;
//void render_selection_rectangle() const; //void render_selection_rectangle() const;
void render_points(const Selection& selection, bool picking = false) const; void render_points(const Selection& selection, bool picking = false) const;
@ -133,12 +144,14 @@ protected:
if ((int)m_editing_mode_cache.size() <= m_hover_id) if ((int)m_editing_mode_cache.size() <= m_hover_id)
m_hover_id = -1; m_hover_id = -1;
} }
void on_start_dragging(const Selection& selection) override; void on_start_dragging() override;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) override; virtual void on_render_input_window(float x, float y, float bottom_limit) override;
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const Selection& selection) const; virtual bool on_is_activable() const;
virtual bool on_is_selectable() const; virtual bool on_is_selectable() const;
virtual void on_load(cereal::BinaryInputArchive& ar) override;
virtual void on_save(cereal::BinaryOutputArchive& ar) const override;
}; };

View file

@ -14,8 +14,9 @@ namespace GUI {
const float GLGizmosManager::Default_Icons_Size = 64; const float GLGizmosManager::Default_Icons_Size = 64;
GLGizmosManager::GLGizmosManager() GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
: m_enabled(false) : m_parent(parent)
, 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)
{ {
} }
@ -31,7 +33,7 @@ GLGizmosManager::~GLGizmosManager()
reset(); reset();
} }
bool GLGizmosManager::init(GLCanvas3D& parent) bool GLGizmosManager::init()
{ {
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;
@ -48,7 +50,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
} }
} }
GLGizmoBase* gizmo = new GLGizmoMove3D(parent, "move.svg", 0); GLGizmoBase* gizmo = new GLGizmoMove3D(m_parent, "move.svg", 0);
if (gizmo == nullptr) if (gizmo == nullptr)
return false; return false;
@ -57,7 +59,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); m_gizmos.insert(GizmosMap::value_type(Move, gizmo));
gizmo = new GLGizmoScale3D(parent, "scale.svg", 1); gizmo = new GLGizmoScale3D(m_parent, "scale.svg", 1);
if (gizmo == nullptr) if (gizmo == nullptr)
return false; return false;
@ -66,7 +68,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
m_gizmos.insert(GizmosMap::value_type(Scale, gizmo)); m_gizmos.insert(GizmosMap::value_type(Scale, gizmo));
gizmo = new GLGizmoRotate3D(parent, "rotate.svg", 2); gizmo = new GLGizmoRotate3D(m_parent, "rotate.svg", 2);
if (gizmo == nullptr) if (gizmo == nullptr)
{ {
reset(); reset();
@ -81,7 +83,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo)); m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
gizmo = new GLGizmoFlatten(parent, "place.svg", 3); gizmo = new GLGizmoFlatten(m_parent, "place.svg", 3);
if (gizmo == nullptr) if (gizmo == nullptr)
return false; return false;
@ -92,7 +94,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo)); m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
gizmo = new GLGizmoCut(parent, "cut.svg", 4); gizmo = new GLGizmoCut(m_parent, "cut.svg", 4);
if (gizmo == nullptr) if (gizmo == nullptr)
return false; return false;
@ -103,7 +105,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
m_gizmos.insert(GizmosMap::value_type(Cut, gizmo)); m_gizmos.insert(GizmosMap::value_type(Cut, gizmo));
gizmo = new GLGizmoSlaSupports(parent, "sla_supports.svg", 5); gizmo = new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 5);
if (gizmo == nullptr) if (gizmo == nullptr)
return false; return false;
@ -135,12 +137,15 @@ void GLGizmosManager::set_overlay_scale(float scale)
} }
} }
void GLGizmosManager::refresh_on_off_state(const Selection& selection) void GLGizmosManager::refresh_on_off_state()
{ {
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())
{ {
it->second->set_state(GLGizmoBase::Off); it->second->set_state(GLGizmoBase::Off);
m_current = Undefined; m_current = Undefined;
@ -153,6 +158,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 +200,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)
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));
} }
void GLGizmosManager::update_data(GLCanvas3D& canvas) void GLGizmosManager::update_data()
{ {
if (!m_enabled) if (!m_enabled)
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 +236,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 +244,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 +252,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 +272,12 @@ 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)
return false;
if (m_parent.get_selection().is_empty())
return false; return false;
EType old_current = m_current; EType old_current = m_current;
@ -278,7 +289,7 @@ bool GLGizmosManager::handle_shortcut(int key, const Selection& selection)
int it_key = it->second->get_shortcut_key(); int it_key = it->second->get_shortcut_key();
if (it->second->is_activable(selection) && ((it_key == key - 64) || (it_key == key - 96))) if (it->second->is_activable() && ((it_key == key - 64) || (it_key == key - 96)))
{ {
if ((it->second->get_state() == GLGizmoBase::On)) if ((it->second->get_state() == GLGizmoBase::On))
{ {
@ -314,14 +325,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)
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->start_dragging(selection); curr->start_dragging();
} }
void GLGizmosManager::stop_dragging() void GLGizmosManager::stop_dragging()
@ -409,14 +420,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)
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,27 +456,27 @@ 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)
return; return;
GLGizmoBase* curr = get_current(); GLGizmoBase* curr = get_current();
if (curr != nullptr) if (curr != nullptr)
curr->render(selection); curr->render();
} }
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)
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();
} }
void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const void GLGizmosManager::render_overlay() const
{ {
if (!m_enabled) if (!m_enabled)
return; return;
@ -473,10 +484,10 @@ void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection&
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)
{ {
bool processed = false; bool processed = false;
@ -489,14 +500,12 @@ 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)
{ {
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 +521,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 +532,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 +544,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(), L("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 +614,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 +623,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(L("Gizmo-Move"));
break; break;
} }
case Scale: case Scale:
{ {
canvas.do_scale("Gizmo-Scale Object"); m_parent.do_scale(L("Gizmo-Scale"));
break; break;
} }
case Rotate: case Rotate:
{ {
canvas.do_rotate("Gizmo-Rotate Object"); m_parent.do_rotate(L("Gizmo-Rotate"));
break; break;
} }
default: default:
@ -633,25 +642,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 +672,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,7 +698,7 @@ 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)
{ {
// see include/wx/defs.h enum wxKeyCode // see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode(); int keyCode = evt.GetKeyCode();
@ -797,20 +806,20 @@ 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)
{ {
const int keyCode = evt.GetKeyCode(); const int keyCode = evt.GetKeyCode();
bool processed = false; bool processed = false;
@ -836,23 +845,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 +879,14 @@ 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_gizmos.empty())
return; return;
float cnv_w = (float)canvas.get_canvas_size().get_width(); float cnv_w = (float)m_parent.get_canvas_size().get_width();
float cnv_h = (float)canvas.get_canvas_size().get_height(); float cnv_h = (float)m_parent.get_canvas_size().get_height();
float zoom = (float)canvas.get_camera().get_zoom(); 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,8 +999,8 @@ 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);
} }
top_y -= scaled_stride_y; top_y -= scaled_stride_y;
} }
@ -1047,12 +1062,12 @@ 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)
return; return;
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;
@ -1067,7 +1082,7 @@ void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d&
continue; continue;
bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
if (it->second->is_activable(selection) && inside) if (it->second->is_activable() && inside)
{ {
if ((it->second->get_state() == GLGizmoBase::On)) if ((it->second->get_state() == GLGizmoBase::On))
{ {
@ -1091,16 +1106,14 @@ 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)
return name; return name;
const Selection& selection = canvas.get_selection(); float cnv_h = (float)m_parent.get_canvas_size().get_height();
float cnv_h = (float)canvas.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;
@ -1117,7 +1130,7 @@ std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const
if (inside) if (inside)
name = it->second->get_name(); name = it->second->get_name();
if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On)) if (it->second->is_activable() && (it->second->get_state() != GLGizmoBase::On))
it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
top_y += scaled_stride_y; top_y += scaled_stride_y;
@ -1126,12 +1139,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)
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,12 +89,44 @@ private:
MouseCapture m_mouse_capture; MouseCapture m_mouse_capture;
std::string m_tooltip; std::string m_tooltip;
bool m_serializing;
public: public:
GLGizmosManager(); explicit GLGizmosManager(GLCanvas3D& parent);
~GLGizmosManager(); ~GLGizmosManager();
bool init(GLCanvas3D& parent); bool init();
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; }
@ -102,23 +134,22 @@ public:
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);
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

@ -1646,7 +1646,7 @@ 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());
this->undo_redo_stack.release_least_recently_used(); this->undo_redo_stack.release_least_recently_used();
BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info();
} }
@ -3630,27 +3630,27 @@ int Plater::priv::get_active_snapshot_index()
void Plater::priv::undo() void Plater::priv::undo()
{ {
bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active(); bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active();
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(temp_snapshot_was_taken); this->update_after_undo_redo(temp_snapshot_was_taken);
} }
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)
{ {
bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active(); bool temp_snapshot_was_taken = this->undo_redo_stack.temp_snapshot_active();
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(temp_snapshot_was_taken); this->update_after_undo_redo(temp_snapshot_was_taken);
} }
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(bool /* temp_snapshot_was_taken */) void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
@ -3665,6 +3665,7 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
this->undo_redo_stack.release_least_recently_used(); this->undo_redo_stack.release_least_recently_used();
//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();
@ -3924,7 +3925,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return; return;
} }
Plater::TakeSnapshot snapshot(this, _(L("Cut"))); Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane")));
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

@ -816,12 +816,12 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
// apply scale // apply scale
start_dragging(); start_dragging();
scale(s * Vec3d::Ones(), type); scale(s * Vec3d::Ones(), type);
wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot wxGetApp().plater()->canvas3D()->do_scale(L("")); // avoid storing another snapshot
// center selection on print bed // center selection on print bed
start_dragging(); start_dragging();
translate(print_volume.center() - get_bounding_box().center()); translate(print_volume.center() - get_bounding_box().center());
wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot wxGetApp().plater()->canvas3D()->do_move(L("")); // avoid storing another snapshot
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
} }

View file

@ -441,18 +441,14 @@ public:
return memsize; return memsize;
} }
// 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);
void release_least_recently_used(); void release_least_recently_used();
// Snapshot history (names with timestamps). // Snapshot history (names with timestamps).
@ -641,6 +637,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 {
@ -722,7 +719,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);
@ -740,7 +737,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
@ -755,7 +753,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));
@ -769,7 +767,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());
@ -789,8 +789,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));
@ -803,8 +803,8 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
bool new_snapshot_taken = false; bool new_snapshot_taken = false;
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_snapshot_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.
@ -815,7 +815,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
assert(m_snapshots.back().is_topmost_captured()); assert(m_snapshots.back().is_topmost_captured());
new_snapshot_taken = true; new_snapshot_taken = true;
} }
this->load_snapshot(time_to_load, model); this->load_snapshot(time_to_load, model, gizmos);
if (new_snapshot_taken) { if (new_snapshot_taken) {
// Release old snapshots if the memory allocated due to capturing the top most state is excessive. // Release old snapshots if the memory allocated due to capturing the top most state is excessive.
// Don't release the snapshots here, release them first after the scene and background processing gets updated, as this will release some references // Don't release the snapshots here, release them first after the scene and background processing gets updated, as this will release some references
@ -829,8 +829,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));
@ -840,7 +840,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();
@ -925,11 +925,11 @@ Stack::~Stack() {}
void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); } void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); }
size_t Stack::memsize() const { return pimpl->memsize(); } size_t Stack::memsize() const { return pimpl->memsize(); }
void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); } void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); }
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 {
@ -65,7 +66,7 @@ public:
void release_least_recently_used(); void release_least_recently_used();
// 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;
@ -73,10 +74,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.

View file

@ -25,7 +25,9 @@ use Slic3r::Test;
$config->set('extruder_offset', [ [0,0], [20,0], [0,20], [20,20] ]); $config->set('extruder_offset', [ [0,0], [20,0], [0,20], [20,20] ]);
$config->set('temperature', [200, 180, 170, 160]); $config->set('temperature', [200, 180, 170, 160]);
$config->set('first_layer_temperature', [206, 186, 166, 156]); $config->set('first_layer_temperature', [206, 186, 166, 156]);
$config->set('toolchange_gcode', ';toolchange'); # test that it doesn't crash when this is supplied $config->set('toolchange_gcode', 'T[next_extruder] ;toolchange'); # test that it doesn't crash when this is supplied
# Since July 2019, PrusaSlicer only emits automatic Tn command in case that the toolchange_gcode is empty
# The "T[next_extruder]" is therefore needed in this test.
my $print = Slic3r::Test::init_print('20mm_cube', config => $config); my $print = Slic3r::Test::init_print('20mm_cube', config => $config);