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,18 +2811,17 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
gcode += m_ooze_prevention.pre_toolchange(*this);
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.
if (!toolchange_gcode.empty()) {
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("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config);
check_add_eol(gcode);
}
}
// We inform the writer about what is happening, but we may not use the resulting gcode.
std::string toolchange_command = m_writer.toolchange(extruder_id);

View file

@ -604,6 +604,7 @@ void GLCanvas3D::LayersEditing::accept_changes(GLCanvas3D& canvas)
{
if (last_object_id >= 0) {
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;
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_view_toolbar(view_toolbar)
, m_toolbar(GLToolbar::Normal, "Top")
, m_gizmos(*this)
, m_use_clipping_planes(false)
, m_sidebar_field("")
, m_keep_dirty(false)
@ -1318,7 +1320,7 @@ bool GLCanvas3D::init()
// if (!m_volumes.empty())
// 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;
if (!_init_toolbar())
@ -1719,7 +1721,7 @@ void GLCanvas3D::deselect_all()
m_selection.set_mode(Selection::Instance);
wxGetApp().obj_manipul()->set_dirty();
m_gizmos.reset_all_states();
m_gizmos.update_data(*this);
m_gizmos.update_data();
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)
{
m_selection.mirror(axis);
do_mirror("Mirror Object");
do_mirror(L("Mirror Object"));
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_gizmos.update_data(*this);
m_gizmos.refresh_on_off_state(m_selection);
m_gizmos.update_data();
m_gizmos.refresh_on_off_state();
// Update the toolbar
if (update_object_list)
@ -2323,7 +2325,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items())
return;
if (m_gizmos.on_char(evt, *this))
if (m_gizmos.on_char(evt))
return;
//#ifdef __APPLE__
@ -2450,7 +2452,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
else
{
if (!m_gizmos.on_key(evt, *this))
if (!m_gizmos.on_key(evt))
{
if (evt.GetEventType() == wxEVT_KEY_UP) {
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.
if (m_gizmos.on_mouse_wheel(evt, *this))
if (m_gizmos.on_mouse_wheel(evt))
return;
// Calculate the zoom delta and apply it to the current zoom factor
@ -2688,7 +2690,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return;
}
if (m_gizmos.on_mouse(evt, *this))
if (m_gizmos.on_mouse(evt))
{
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
@ -2815,9 +2817,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_selection.is_empty())
m_gizmos.reset_all_states();
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));
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)
{
m_regenerate_volumes = false;
do_move("Move Object");
do_move(L("Move Object"));
wxGetApp().obj_manipul()->set_dirty();
// Let the plater know that the dragging finished, so a delayed refresh
// 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
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));
m_gizmos.update_data(*this);
m_gizmos.update_data();
wxGetApp().obj_manipul()->set_dirty();
// forces a frame render to update the view before the context menu is shown
render();
@ -3113,7 +3115,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
return;
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
bool object_moved = false;
@ -3175,7 +3177,7 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
return;
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
@ -3235,7 +3237,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
return;
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
@ -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)
{
if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(L(snapshot_type)));
wxGetApp().plater()->take_snapshot(_(snapshot_type));
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)
@ -3301,7 +3303,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
return;
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
@ -3355,8 +3357,8 @@ void GLCanvas3D::set_camera_zoom(double zoom)
void GLCanvas3D::update_gizmos_on_off_state()
{
set_as_dirty();
m_gizmos.update_data(*this);
m_gizmos.refresh_on_off_state(get_selection());
m_gizmos.update_data();
m_gizmos.refresh_on_off_state();
}
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())
::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)
glsafe(::glEnable(GL_MULTISAMPLE));
@ -4072,7 +4074,7 @@ void GLCanvas3D::_render_volumes_for_picking() 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
@ -4088,7 +4090,7 @@ void GLCanvas3D::_render_gizmos_overlay() const
m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
#endif /* __WXMSW__ */
m_gizmos.render_overlay(*this, m_selection);
m_gizmos.render_overlay();
}
void GLCanvas3D::_render_toolbar() const
@ -5661,9 +5663,9 @@ void GLCanvas3D::_update_selection_from_hover()
if (m_selection.is_empty())
m_gizmos.reset_all_states();
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));
m_dirty = true;
}

View file

@ -517,6 +517,9 @@ public:
const Selection& get_selection() const { 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 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_volumes();
// 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);
});
return sizer;
@ -323,7 +323,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_volumes();
// 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);
});
@ -709,7 +709,7 @@ void ObjectManipulation::change_position_value(int axis, double value)
Selection& selection = canvas->get_selection();
selection.start_dragging();
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_rounded(axis) = DBL_MAX;
@ -740,7 +740,7 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
selection.rotate(
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
transformation_type);
canvas->do_rotate("Set Orientation");
canvas->do_rotate(L("Set Orientation"));
m_cache.rotation = rotation;
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.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)

View file

@ -132,6 +132,7 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
glsafe(::glEnd());
}
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: m_parent(parent)
, m_group_id(-1)
@ -179,7 +180,7 @@ void GLGizmoBase::disable_grabber(unsigned int id)
on_disable_grabber(id);
}
void GLGizmoBase::start_dragging(const Selection& selection)
void GLGizmoBase::start_dragging()
{
m_dragging = true;
@ -188,7 +189,7 @@ void GLGizmoBase::start_dragging(const Selection& selection)
m_grabbers[i].dragging = (m_hover_id == i);
}
on_start_dragging(selection);
on_start_dragging();
}
void GLGizmoBase::stop_dragging()
@ -203,10 +204,10 @@ void GLGizmoBase::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)
on_update(data, selection);
on_update(data);
}
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/Selection.hpp"
#include <cereal/archives/binary.hpp>
class wxWindow;
class GLUquadric;
@ -75,10 +76,10 @@ public:
struct UpdateData
{
const Linef3 mouse_ray;
const Point* mouse_pos;
const Linef3& mouse_ray;
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)
{}
};
@ -105,6 +106,9 @@ public:
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(); }
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; }
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(); }
unsigned int get_sprite_id() const { return m_sprite_id; }
@ -131,32 +135,34 @@ public:
void enable_grabber(unsigned int id);
void disable_grabber(unsigned int id);
void start_dragging(const Selection& selection);
void start_dragging();
void stop_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_for_picking(const Selection& selection) const { on_render_for_picking(selection); }
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() const { on_render(); }
void render_for_picking() const { on_render_for_picking(); }
void render_input_window(float x, float y, float bottom_limit) { on_render_input_window(x, y, bottom_limit); }
protected:
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 void on_set_state() {}
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 void on_enable_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_update(const UpdateData& data, const Selection& selection) = 0;
virtual void on_render(const Selection& selection) const = 0;
virtual void on_render_for_picking(const Selection& selection) const = 0;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) {}
virtual void on_update(const UpdateData& data) {}
virtual void on_render() const = 0;
virtual void on_render_for_picking() const = 0;
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
// 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)
{}
bool GLGizmoCut::on_init()
{
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();
}
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();
m_start_z = m_cut_z;
update_max_z(selection);
@ -66,19 +68,21 @@ void GLGizmoCut::on_start_dragging(const Selection& selection)
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) {
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) {
set_tooltip("Z: " + format(m_cut_z, 2));
}
const Selection& selection = m_parent.get_selection();
update_max_z(selection);
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));
}
void GLGizmoCut::on_render_for_picking(const Selection& selection) const
void GLGizmoCut::on_render_for_picking() const
{
glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(selection.get_bounding_box());
render_grabbers_for_picking(m_parent.get_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);
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();
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:
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 void on_set_state();
virtual bool on_is_activable(const Selection& selection) const;
virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
virtual bool on_is_activable() const;
virtual void on_start_dragging();
virtual void on_update(const UpdateData& data);
virtual void on_render() const;
virtual void on_render_for_picking() const;
virtual void on_render_input_window(float x, float y, float bottom_limit);
private:
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 "GLGizmoFlatten.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include <numeric>
@ -22,28 +24,46 @@ bool GLGizmoFlatten::on_init()
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
{
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)
{
assert(m_planes_valid);
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(::glEnable(GL_DEPTH_TEST));
@ -78,8 +98,10 @@ void GLGizmoFlatten::on_render(const Selection& selection) const
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_BLEND));
@ -115,6 +137,7 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
m_planes_valid = false;
}
m_model_object = model_object;
m_model_object_id = model_object ? model_object->id() : 0;
}
void GLGizmoFlatten::update_planes()

View file

@ -31,6 +31,7 @@ private:
bool m_planes_valid = false;
mutable Vec3d m_starting_center;
const ModelObject* m_model_object = nullptr;
ObjectID m_model_object_id = 0;
std::vector<const Transform3d*> instances_matrices;
void update_planes();
@ -45,16 +46,11 @@ public:
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const Selection& selection) const;
virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const Selection& selection) {}
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_set_state()
{
if (m_state == On && is_plane_update_necessary())
update_planes();
}
virtual bool on_is_activable() const;
virtual void on_start_dragging();
virtual void on_render() const;
virtual void on_render_for_picking() const;
virtual void on_set_state() override;
};
} // 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 "GLGizmoMove.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -47,12 +48,12 @@ std::string GLGizmoMove3D::on_get_name() const
return (_(L("Move")) + " [M]").ToUTF8().data();
}
void GLGizmoMove3D::on_start_dragging(const Selection& selection)
void GLGizmoMove3D::on_start_dragging()
{
if (m_hover_id != -1)
{
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_box_center = box.center();
m_starting_box_bottom_center = box.center();
@ -65,7 +66,7 @@ void GLGizmoMove3D::on_stop_dragging()
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)
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);
}
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();
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));
const BoundingBoxf3& box = selection.get_bounding_box();
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
render_grabbers_for_picking(box);
render_grabber_extension(X, box, true);
render_grabber_extension(Y, 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
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();
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->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
}
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
double GLGizmoMove3D::calc_projection(const UpdateData& data) const
{

View file

@ -33,12 +33,14 @@ public:
protected:
virtual bool on_init();
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_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
virtual void on_update(const UpdateData& data);
virtual void on_render() const;
virtual void on_render_for_picking() const;
#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:
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 "GLGizmoRotate.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -72,9 +73,9 @@ bool GLGizmoRotate::on_init()
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_radius = Offset + box.radius();
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;
}
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 new_dir = mouse_pos.normalized();
@ -118,11 +119,12 @@ void GLGizmoRotate::on_update(const UpdateData& data, const Selection& selection
m_angle = theta;
}
void GLGizmoRotate::on_render(const Selection& selection) const
void GLGizmoRotate::on_render() const
{
if (!m_grabbers[0].enabled)
return;
const Selection& selection = m_parent.get_selection();
const BoundingBoxf3& box = selection.get_bounding_box();
std::string axis;
@ -175,8 +177,10 @@ void GLGizmoRotate::on_render(const Selection& selection) const
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(::glPushMatrix());
@ -445,10 +449,10 @@ std::string GLGizmoRotate3D::on_get_name() const
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))
m_gizmos[m_hover_id].start_dragging(selection);
m_gizmos[m_hover_id].start_dragging();
}
void GLGizmoRotate3D::on_stop_dragging()
@ -457,23 +461,23 @@ void GLGizmoRotate3D::on_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));
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))
m_gizmos[Y].render(selection);
m_gizmos[Y].render();
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
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()));
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->input_vec3("", rotation, 100.0f, "%.2f");
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:
virtual bool on_init();
virtual std::string on_get_name() const { return ""; }
virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_start_dragging();
virtual void on_update(const UpdateData& data);
virtual void on_render() const;
virtual void on_render_for_picking() const;
private:
void render_circle() const;
@ -98,7 +98,6 @@ protected:
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)
{
if ((0 <= id) && (id < 3))
@ -109,25 +108,26 @@ protected:
if ((0 <= id) && (id < 3))
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_update(const UpdateData& data, const Selection& selection)
virtual void on_update(const UpdateData& data)
{
for (GLGizmoRotate& g : m_gizmos)
{
g.update(data, selection);
g.update(data);
}
}
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const
virtual void on_render() const;
virtual void on_render_for_picking() const
{
for (const GLGizmoRotate& g : m_gizmos)
{
g.render_for_picking(selection);
g.render_for_picking();
}
}
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
};

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 "GLGizmoScale.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -48,13 +47,18 @@ std::string GLGizmoScale3D::on_get_name() const
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)
{
m_starting.drag_position = m_grabbers[m_hover_id].center;
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();
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))
do_scale_along_axis(X, data);
@ -78,8 +82,10 @@ void GLGizmoScale3D::on_update(const UpdateData& data, const Selection& selectio
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_volume = selection.is_single_modifier() || selection.is_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));
render_grabbers_for_picking(selection.get_bounding_box());
render_grabbers_for_picking(m_parent.get_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
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();
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->input_vec3("", m_scale * 100.f, 100.0f, "%.2f");
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
{

View file

@ -45,12 +45,14 @@ public:
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
virtual bool on_is_activable() const;
virtual void on_start_dragging();
virtual void on_update(const UpdateData& data);
virtual void on_render() const;
virtual void on_render_for_picking() const;
#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:
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 (m_state == On
&& (m_model_object != selection.get_model()->objects[selection.get_object_idx()]
@ -104,6 +106,9 @@ void GLGizmoSlaSupports::on_render(const Selection& selection) const
return;
}
if (! m_its || ! m_mesh)
const_cast<GLGizmoSlaSupports*>(this)->update_mesh();
glsafe(::glEnable(GL_BLEND));
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
m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z();
#endif
@ -384,20 +390,28 @@ bool GLGizmoSlaSupports::is_mesh_update_necessary() const
void GLGizmoSlaSupports::update_mesh()
{
if (! m_model_object)
return;
wxBusyCursor wait;
// this way we can use that mesh directly.
// This mesh does not account for the possible Z up SLA offset.
m_mesh = &m_model_object->volumes.front()->mesh();
m_its = &m_mesh->its;
m_current_mesh_object_id = m_model_object->id();
m_editing_mode = false;
// 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_editing_mode = false;
}
// Unprojects the mouse position on the mesh and return the hit point and normal of the facet.
// The function throws if no intersection if found.
std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
@ -702,12 +716,12 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
//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;
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; }
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)
return;
@ -1002,8 +1016,10 @@ RENDER_AGAIN:
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
|| !selection.is_from_single_instance())
return false;
@ -1029,6 +1045,25 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::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
const ModelObject* old_model_object = m_model_object;
m_model_object = nullptr;
for (const auto mo : *wxGetApp().model_objects()) {
if (mo->id() == m_current_mesh_object_id) {
m_model_object = mo;
break;
}
}
// If ModelObject pointer really changed, invalidate mesh and do everything
// as if the gizmo was switched from Off state
if (m_model_object == nullptr || old_model_object != m_model_object) {
m_mesh = nullptr;
m_its = nullptr;
m_old_state = Off;
}
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
if (is_mesh_update_necessary())
update_mesh();
@ -1075,7 +1110,7 @@ void GLGizmoSlaSupports::on_set_state()
void GLGizmoSlaSupports::on_start_dragging(const Selection& selection)
void GLGizmoSlaSupports::on_start_dragging()
{
if (m_hover_id != -1) {
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)
{
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
// taken from the backend and copying them to ModelObject would needlessly invalidate them.
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_support_points.clear();
for (const CacheEntry& cache_entry : m_editing_mode_cache)
@ -1199,6 +1255,7 @@ void GLGizmoSlaSupports::auto_generate()
)), _(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) {
wxGetApp().plater()->take_snapshot(_(L("Autogenerate support points")));
m_model_object->sla_support_points.clear();
m_model_object->sla_points_status = sla::PointsStatus::Generating;
m_editing_mode_cache.clear();

View file

@ -14,6 +14,8 @@
#include "libslic3r/SLAPrint.hpp"
#include <wx/dialog.h>
#include <cereal/types/vector.hpp>
namespace Slic3r {
namespace GUI {
@ -49,12 +51,21 @@ private:
class CacheEntry {
public:
CacheEntry() :
support_point(sla::SupportPoint()), selected(false), normal(Vec3f::Zero()) {}
CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) :
support_point(point), selected(sel), normal(norm) {}
sla::SupportPoint support_point;
bool selected; // whether the point is selected
Vec3f normal;
template<class Archive>
void serialize(Archive & ar)
{
ar(support_point, selected, normal);
}
};
public:
@ -70,9 +81,9 @@ public:
private:
bool on_init();
void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const Selection& selection) const;
void on_update(const UpdateData& data);
virtual void on_render() const;
virtual void on_render_for_picking() const;
//void render_selection_rectangle() 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)
m_hover_id = -1;
}
void on_start_dragging(const Selection& selection) override;
virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) override;
void on_start_dragging() override;
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
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 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;
GLGizmosManager::GLGizmosManager()
: m_enabled(false)
GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
: m_parent(parent)
, m_enabled(false)
, m_icons_texture_dirty(true)
, m_current(Undefined)
, m_overlay_icons_size(Default_Icons_Size)
@ -23,6 +24,7 @@ GLGizmosManager::GLGizmosManager()
, m_overlay_border(5.0f)
, m_overlay_gap_y(5.0f)
, m_tooltip("")
, m_serializing(false)
{
}
@ -31,7 +33,7 @@ GLGizmosManager::~GLGizmosManager()
reset();
}
bool GLGizmosManager::init(GLCanvas3D& parent)
bool GLGizmosManager::init()
{
m_background_texture.metadata.filename = "toolbar_background.png";
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)
return false;
@ -57,7 +59,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
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)
return false;
@ -66,7 +68,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
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)
{
reset();
@ -81,7 +83,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
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)
return false;
@ -92,7 +94,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
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)
return false;
@ -103,7 +105,7 @@ bool GLGizmosManager::init(GLCanvas3D& parent)
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)
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);
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);
m_current = Undefined;
@ -153,6 +158,9 @@ void GLGizmosManager::reset_all_states()
if (!m_enabled)
return;
if (m_serializing)
return;
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
{
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)
return;
GLGizmoBase* curr = get_current();
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)
return;
const Selection& selection = canvas.get_selection();
const Selection& selection = m_parent.get_selection();
bool is_wipe_tower = selection.is_wipe_tower();
enable_grabber(Move, 2, !is_wipe_tower);
@ -228,7 +236,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_rotation(Vec3d::Zero());
ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()];
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())
{
@ -236,7 +244,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_scale(volume->get_volume_scaling_factor());
set_rotation(Vec3d::Zero());
set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection);
set_sla_support_data(nullptr);
}
else if (is_wipe_tower)
{
@ -244,14 +252,14 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_scale(Vec3d::Ones());
set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value));
set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection);
set_sla_support_data(nullptr);
}
else
{
set_scale(Vec3d::Ones());
set_rotation(Vec3d::Zero());
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;
}
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;
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();
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))
{
@ -314,14 +325,14 @@ bool GLGizmosManager::is_dragging() const
return (curr != nullptr) ? curr->is_dragging() : false;
}
void GLGizmosManager::start_dragging(const Selection& selection)
void GLGizmosManager::start_dragging()
{
if (!m_enabled)
return;
GLGizmoBase* curr = get_current();
if (curr != nullptr)
curr->start_dragging(selection);
curr->start_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);
}
void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Selection& selection)
void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
{
if (!m_enabled)
return;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
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.
@ -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)
return;
GLGizmoBase* curr = get_current();
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)
return;
GLGizmoBase* curr = get_current();
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)
return;
@ -473,10 +484,10 @@ void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection&
if (m_icons_texture_dirty)
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;
@ -489,14 +500,12 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas)
return processed;
}
bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
{
Point pos(evt.GetX(), 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();
bool processed = false;
@ -512,7 +521,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
// mouse anywhere
if (evt.Moving())
m_tooltip = update_hover_state(canvas, mouse_pos);
m_tooltip = update_hover_state(mouse_pos);
else if (evt.LeftUp())
m_mouse_capture.left = false;
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
processed = true;
if (!overlay_contains_mouse(canvas, mouse_pos))
if (!overlay_contains_mouse(mouse_pos))
{
// mouse is outside the toolbar
m_tooltip = "";
@ -535,40 +544,40 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
processed = true;
else if (!selection.is_empty() && grabber_contains_mouse())
{
update_data(canvas);
update_data();
selection.start_dragging();
start_dragging(selection);
start_dragging();
if (m_current == Flatten)
{
// 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();
}
canvas.set_as_dirty();
m_parent.set_as_dirty();
processed = true;
}
}
else if (evt.RightDown() && (selected_object_idx != -1) && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::RightDown))
// event was taken care of by the SlaSupports gizmo
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
processed = true;
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
canvas.set_as_dirty();
m_parent.set_as_dirty();
processed = true;
}
else if (evt.Dragging() && is_dragging())
{
if (!canvas.get_wxglcanvas()->HasCapture())
canvas.get_wxglcanvas()->CaptureMouse();
if (!m_parent.get_wxglcanvas()->HasCapture())
m_parent.get_wxglcanvas()->CaptureMouse();
canvas.set_mouse_as_dragging();
update(canvas.mouse_ray(pos), selection, &pos);
m_parent.set_mouse_as_dragging();
update(m_parent.mouse_ray(pos), pos);
switch (m_current)
{
@ -605,7 +614,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
break;
}
canvas.set_as_dirty();
m_parent.set_as_dirty();
processed = true;
}
else if (evt.LeftUp() && is_dragging())
@ -614,18 +623,18 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
{
case Move:
{
canvas.disable_regenerate_volumes();
canvas.do_move("Gizmo-Move Object");
m_parent.disable_regenerate_volumes();
m_parent.do_move(L("Gizmo-Move"));
break;
}
case Scale:
{
canvas.do_scale("Gizmo-Scale Object");
m_parent.do_scale(L("Gizmo-Scale"));
break;
}
case Rotate:
{
canvas.do_rotate("Gizmo-Rotate Object");
m_parent.do_rotate(L("Gizmo-Rotate"));
break;
}
default:
@ -633,25 +642,25 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
}
stop_dragging();
update_data(canvas);
update_data();
wxGetApp().obj_manipul()->set_dirty();
// Let the platter know that the dragging finished, so a delayed refresh
// 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
canvas.refresh_camera_scene_box();
m_parent.refresh_camera_scene_box();
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
// object moving or selecting is suppressed in that case
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
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
processed = true;
@ -663,24 +672,24 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
if (evt.LeftDown() || evt.LeftDClick())
{
m_mouse_capture.left = true;
m_mouse_capture.parent = &canvas;
m_mouse_capture.parent = &m_parent;
processed = true;
if (!selection.is_empty())
{
update_on_off_state(canvas, mouse_pos, selection);
update_data(canvas);
canvas.set_as_dirty();
update_on_off_state(mouse_pos);
update_data();
m_parent.set_as_dirty();
}
}
else if (evt.MiddleDown())
{
m_mouse_capture.middle = true;
m_mouse_capture.parent = &canvas;
m_mouse_capture.parent = &m_parent;
}
else if (evt.RightDown())
{
m_mouse_capture.right = true;
m_mouse_capture.parent = &canvas;
m_mouse_capture.parent = &m_parent;
}
else if (evt.LeftUp())
processed = true;
@ -689,7 +698,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
return processed;
}
bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
bool GLGizmosManager::on_char(wxKeyEvent& evt)
{
// see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode();
@ -797,20 +806,20 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
if (!processed && !evt.HasModifiers())
{
if (handle_shortcut(keyCode, canvas.get_selection()))
if (handle_shortcut(keyCode))
{
update_data(canvas);
update_data();
processed = true;
}
}
if (processed)
canvas.set_as_dirty();
m_parent.set_as_dirty();
return processed;
}
bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
bool GLGizmosManager::on_key(wxKeyEvent& evt)
{
const int keyCode = evt.GetKeyCode();
bool processed = false;
@ -836,23 +845,29 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
}
// if (processed)
// canvas.set_cursor(GLCanvas3D::Standard);
// m_parent.set_cursor(GLCanvas3D::Standard);
}
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())
{
// canvas.set_cursor(GLCanvas3D::Cross);
// m_parent.set_cursor(GLCanvas3D::Cross);
processed = true;
}
}
if (processed)
canvas.set_as_dirty();
m_parent.set_as_dirty();
return processed;
}
void GLGizmosManager::update_after_undo_redo()
{
update_data();
m_serializing = false;
}
void GLGizmosManager::reset()
{
for (GizmosMap::value_type& gizmo : m_gizmos)
@ -864,14 +879,14 @@ void GLGizmosManager::reset()
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())
return;
float cnv_w = (float)canvas.get_canvas_size().get_width();
float cnv_h = (float)canvas.get_canvas_size().get_height();
float zoom = (float)canvas.get_camera().get_zoom();
float cnv_w = (float)m_parent.get_canvas_size().get_width();
float cnv_h = (float)m_parent.get_canvas_size().get_height();
float zoom = (float)m_parent.get_camera().get_zoom();
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
float 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 } });
if (it->second->get_state() == GLGizmoBase::On) {
float toolbar_top = (float)cnv_h - canvas.get_view_toolbar_height();
it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
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);
}
top_y -= scaled_stride_y;
}
@ -1047,12 +1062,12 @@ bool GLGizmosManager::generate_icons_texture() const
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)
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 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;
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))
{
@ -1091,16 +1106,14 @@ void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d&
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 = "";
if (!m_enabled)
return name;
const Selection& selection = canvas.get_selection();
float cnv_h = (float)canvas.get_canvas_size().get_height();
float cnv_h = (float)m_parent.get_canvas_size().get_height();
float height = get_total_overlay_height();
float scaled_icons_size = m_overlay_icons_size * 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)
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);
top_y += scaled_stride_y;
@ -1126,12 +1139,12 @@ std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const
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)
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 scaled_icons_size = m_overlay_icons_size * m_overlay_scale;

View file

@ -4,14 +4,13 @@
#include "slic3r/GUI/GLTexture.hpp"
#include "slic3r/GUI/GLToolbar.hpp"
#include "slic3r/GUI/Gizmos/GLGizmos.hpp"
#include "libslic3r/ObjectID.hpp"
#include <map>
namespace Slic3r {
namespace GUI {
class Selection;
class GLGizmoBase;
class GLCanvas3D;
class ClippingPlane;
@ -43,7 +42,7 @@ public:
float get_height() const { return m_top - m_bottom; }
};
class GLGizmosManager
class GLGizmosManager : public Slic3r::ObjectBase
{
public:
static const float Default_Icons_Size;
@ -61,6 +60,7 @@ public:
};
private:
GLCanvas3D& m_parent;
bool m_enabled;
typedef std::map<EType, GLGizmoBase*> GizmosMap;
GizmosMap m_gizmos;
@ -89,12 +89,44 @@ private:
MouseCapture m_mouse_capture;
std::string m_tooltip;
bool m_serializing;
public:
GLGizmosManager();
explicit GLGizmosManager(GLCanvas3D& parent);
~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; }
void set_enabled(bool enable) { m_enabled = enable; }
@ -102,23 +134,22 @@ public:
void set_overlay_icon_size(float size);
void set_overlay_scale(float scale);
void refresh_on_off_state(const Selection& selection);
void refresh_on_off_state();
void reset_all_states();
void set_hover_id(int id);
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_data(GLCanvas3D& canvas);
void update(const Linef3& mouse_ray, const Point& mouse_pos);
void update_data();
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
EType get_current_type() const { return m_current; }
bool is_running() const;
bool handle_shortcut(int key, const Selection& selection);
bool handle_shortcut(int key);
bool is_dragging() const;
void start_dragging(const Selection& selection);
void start_dragging();
void stop_dragging();
Vec3d get_displacement() const;
@ -135,26 +166,28 @@ public:
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);
ClippingPlane get_sla_clipping_plane() const;
void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const;
void render_current_gizmo() 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; }
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas);
bool on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas);
bool on_char(wxKeyEvent& evt, GLCanvas3D& canvas);
bool on_key(wxKeyEvent& evt, GLCanvas3D& canvas);
bool on_mouse(wxMouseEvent& evt);
bool on_mouse_wheel(wxMouseEvent& evt);
bool on_char(wxKeyEvent& evt);
bool on_key(wxKeyEvent& evt);
void update_after_undo_redo();
private:
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_width() const;
@ -163,13 +196,18 @@ private:
bool generate_icons_texture() const;
void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos);
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
void update_on_off_state(const Vec2d& mouse_pos);
std::string update_hover_state(const Vec2d& mouse_pos);
bool overlay_contains_mouse(const Vec2d& mouse_pos) const;
bool grabber_contains_mouse() const;
};
} // namespace GUI
} // namespace Slic3r
namespace cereal
{
template <class Archive> struct specialize<Archive, Slic3r::GUI::GLGizmosManager, cereal::specialization::member_load_save> {};
}
#endif // slic3r_GUI_GLGizmosManager_hpp_

View file

@ -1646,7 +1646,7 @@ struct Plater::priv
if (this->m_prevent_snapshots > 0)
return;
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();
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,26 +3630,26 @@ int Plater::priv::get_active_snapshot_index()
void Plater::priv::undo()
{
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);
}
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();
}
void Plater::priv::undo_to(size_t time_to_load)
{
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);
}
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();
}
@ -3665,6 +3665,7 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
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)
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();
@ -3924,7 +3925,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return;
}
Plater::TakeSnapshot snapshot(this, _(L("Cut")));
Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane")));
wxBusyCursor wait;
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
start_dragging();
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
start_dragging();
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();
}

View file

@ -441,18 +441,14 @@ public:
return memsize;
}
// The Undo / Redo stack is being initialized with an empty model and an empty selection.
// The first snapshot cannot be removed.
void initialize(const Slic3r::Model &model, const Slic3r::GUI::Selection &selection);
// 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);
void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos);
void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos);
bool has_undo_snapshot() const;
bool has_redo_snapshot() const;
bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t jump_to_time);
bool redo(Slic3r::Model &model, 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, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time);
void release_least_recently_used();
// Snapshot history (names with timestamps).
@ -641,6 +637,7 @@ namespace cereal
#include <libslic3r/Model.hpp>
#include <libslic3r/TriangleMesh.hpp>
#include <slic3r/GUI/Selection.hpp>
#include <slic3r/GUI/Gizmos/GLGizmosManager.hpp>
namespace Slic3r {
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.
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.
assert(m_active_snapshot_time <= m_current_time);
@ -740,6 +737,7 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
for (unsigned int volume_idx : selection.get_volume_idxs())
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<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos);
// Save the snapshot info.
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id);
m_active_snapshot_time = m_current_time;
@ -755,7 +753,7 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
#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.
const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp));
@ -769,6 +767,8 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model &model)
model.update_links_bottom_up_recursive();
m_selection.volumes_and_instances.clear();
this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection);
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());
this->m_active_snapshot_time = timestamp;
@ -789,7 +789,7 @@ bool StackImpl::has_redo_snapshot() const
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());
if (time_to_load == SIZE_MAX) {
@ -803,7 +803,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
bool new_snapshot_taken = false;
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.
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.
assert(m_snapshots.back().is_topmost());
assert(! m_snapshots.back().is_topmost_captured());
@ -815,7 +815,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
assert(m_snapshots.back().is_topmost_captured());
new_snapshot_taken = true;
}
this->load_snapshot(time_to_load, model);
this->load_snapshot(time_to_load, model, gizmos);
if (new_snapshot_taken) {
// 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
@ -829,7 +829,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
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());
if (time_to_load == SIZE_MAX) {
@ -840,7 +840,7 @@ bool StackImpl::redo(Slic3r::Model &model, size_t time_to_load)
}
assert(time_to_load > m_active_snapshot_time);
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
std::cout << "After redo" << std::endl;
this->print();
@ -925,11 +925,11 @@ Stack::~Stack() {}
void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); }
size_t Stack::memsize() const { return pimpl->memsize(); }
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_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::redo(Slic3r::Model &model, size_t time_to_load) { return pimpl->redo(model, 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, 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 std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); }

View file

@ -15,6 +15,7 @@ class Model;
namespace GUI {
class Selection;
class GLGizmosManager;
} // namespace GUI
namespace UndoRedo {
@ -65,7 +66,7 @@ public:
void release_least_recently_used();
// 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.
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.
// 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.
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).
// 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('temperature', [200, 180, 170, 160]);
$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);