Separate GizmoManager on_move into gizmo itself

This commit is contained in:
Filip Sykala 2021-12-10 09:09:53 +01:00
parent 2ab44546bd
commit c751d6327d
22 changed files with 614 additions and 469 deletions

View File

@ -3600,15 +3600,6 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
m_dirty = true;
}
void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_type)
{
if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(snapshot_type));
m_selection.flattening_rotate(normal);
do_rotate(""); // avoid taking another snapshot
}
void GLCanvas3D::do_mirror(const std::string& snapshot_type)
{
if (m_model == nullptr)

View File

@ -759,7 +759,6 @@ public:
void do_move(const std::string& snapshot_type);
void do_rotate(const std::string& snapshot_type);
void do_scale(const std::string& snapshot_type);
void do_flatten(const Vec3d& normal, const std::string& snapshot_type);
void do_mirror(const std::string& snapshot_type);
void update_gizmos_on_off_state();

View File

@ -5,6 +5,8 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
// TODO: Display tooltips quicker on Linux
namespace Slic3r {
@ -97,11 +99,15 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u
void GLGizmoBase::set_hover_id(int id)
{
if (m_grabbers.empty() || (id < (int)m_grabbers.size()))
{
m_hover_id = id;
on_set_hover_id();
}
// do not change hover id during dragging
if (m_dragging) return;
// allow empty grabbers when not using grabbers but use hover_id - flatten, rotate
if (!m_grabbers.empty() && id >= (int) m_grabbers.size())
return;
m_hover_id = id;
on_set_hover_id();
}
void GLGizmoBase::set_highlight_color(const std::array<float, 4>& color)
@ -149,18 +155,12 @@ void GLGizmoBase::stop_dragging()
on_stop_dragging();
}
void GLGizmoBase::update(const UpdateData& data)
{
if (m_hover_id != -1)
on_update(data);
}
bool GLGizmoBase::update_items_state()
{
bool res = m_dirty;
m_dirty = false;
return res;
};
}
std::array<float, 4> GLGizmoBase::picking_color_component(unsigned int id) const
{
@ -212,6 +212,62 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
}
}
// help function to process grabbers
// call start_dragging, stop_dragging, on_dragging
bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
if (mouse_event.Moving()) {
assert(!m_dragging);
// only for sure
if (m_dragging) m_dragging = false;
return false;
}
if (mouse_event.LeftDown()) {
Selection &selection = m_parent.get_selection();
if (!selection.is_empty() && m_hover_id != -1) {
selection.start_dragging();
start_dragging();
// Let the plater know that the dragging started
m_parent.post_event(
SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED));
m_parent.set_as_dirty();
return true;
}
} else if (m_dragging) {
if (mouse_event.Dragging()) {
m_parent.set_mouse_as_dragging();
Point mouse_coord(mouse_event.GetX(), mouse_event.GetY());
UpdateData data{m_parent.mouse_ray(mouse_coord), mouse_coord};
on_dragging(data);
wxGetApp().obj_manipul()->set_dirty();
m_parent.set_as_dirty();
return true;
} else if (mouse_event.LeftUp()) {
stop_dragging();
m_parent.get_gizmos_manager().update_data();
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.
m_parent.post_event(
SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints
m_parent.refresh_camera_scene_box();
return true;
} else if (mouse_event.Leaving()) {
m_dragging = false;
}
}
return false;
}
std::string GLGizmoBase::format(float value, unsigned int decimals) const
{
return Slic3r::string_printf("%.*f", decimals, value);

View File

@ -156,8 +156,6 @@ public:
bool is_dragging() const { return m_dragging; }
void update(const UpdateData& data);
// returns True when Gizmo changed its state
bool update_items_state();
@ -186,9 +184,12 @@ protected:
virtual CommonGizmosDataID on_get_requirements() const { return CommonGizmosDataID(0); }
virtual void on_enable_grabber(unsigned int id) {}
virtual void on_disable_grabber(unsigned int id) {}
// called inside use_grabbers
virtual void on_start_dragging() {}
virtual void on_stop_dragging() {}
virtual void on_update(const UpdateData& data) {}
virtual void on_dragging(const UpdateData& data) {}
virtual void on_render() = 0;
virtual void on_render_for_picking() = 0;
virtual void on_render_input_window(float x, float y, float bottom_limit) {}
@ -204,6 +205,13 @@ protected:
// Mark gizmo as dirty to Re-Render when idle()
void set_dirty();
/// <summary>
///
/// </summary>
/// <param name="mouse_event"></param>
/// <returns></returns>
bool use_grabbers(const wxMouseEvent &mouse_event);
private:
// Flag for dirty visible state of Gizmo
// When True then need new rendering

View File

@ -38,6 +38,11 @@ std::string GLGizmoCut::get_tooltip() const
return (m_hover_id == 0 || m_grabbers[0].dragging) ? "Z: " + format(cut_z, 2) : "";
}
bool GLGizmoCut::on_mouse(const wxMouseEvent &mouse_event)
{
return use_grabbers(mouse_event);
}
bool GLGizmoCut::on_init()
{
m_grabbers.emplace_back();
@ -76,10 +81,10 @@ void GLGizmoCut::on_start_dragging()
m_drag_center.z() = m_cut_z;
}
void GLGizmoCut::on_update(const UpdateData& data)
void GLGizmoCut::on_dragging(const UpdateData &data)
{
if (m_hover_id != -1)
set_cut_z(m_start_z + calc_projection(data.mouse_ray));
assert(m_hover_id != -1);
set_cut_z(m_start_z + calc_projection(data.mouse_ray));
}
void GLGizmoCut::on_render()

View File

@ -45,6 +45,13 @@ public:
std::string get_tooltip() const override;
/// <summary>
/// Drag of plane
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
virtual bool on_init() override;
virtual void on_load(cereal::BinaryInputArchive& ar) override { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
@ -53,7 +60,7 @@ protected:
virtual void on_set_state() override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_update(const UpdateData& data) override;
virtual void on_dragging(const UpdateData& data) override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
virtual void on_render_input_window(float x, float y, float bottom_limit) override;

View File

@ -16,9 +16,32 @@ namespace GUI {
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
, m_normal(Vec3d::Zero())
, m_starting_center(Vec3d::Zero())
{}
bool GLGizmoFlatten::on_mouse(const wxMouseEvent &mouse_event)
{
if (mouse_event.Moving()) {
// only for sure
m_mouse_left_down = false;
if (m_hover_id != -1) m_parent.set_as_dirty();
return false;
}
if (mouse_event.LeftDown() && m_hover_id != -1) {
Selection &selection = m_parent.get_selection();
if (selection.is_single_full_instance()) {
// Rotate the object so the normal points downward:
selection.flattening_rotate(m_planes[m_hover_id].normal);
m_parent.do_rotate(L("Gizmo-Place on Face"));
}
m_mouse_left_down = true;
return true;
} else if (m_mouse_left_down && mouse_event.LeftUp()) {
// responsible for mouse left up
m_mouse_left_down = false;
return true;
}
return false;
}
bool GLGizmoFlatten::on_init()
@ -48,15 +71,6 @@ bool GLGizmoFlatten::on_is_activable() const
return m_parent.get_selection().is_single_full_instance();
}
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 = m_parent.get_selection().get_bounding_box().center();
}
}
void GLGizmoFlatten::on_render()
{
const Selection& selection = m_parent.get_selection();
@ -115,7 +129,6 @@ void GLGizmoFlatten::on_render_for_picking()
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
{
m_starting_center = Vec3d::Zero();
if (model_object != m_old_model_object) {
m_planes.clear();
m_planes_valid = false;
@ -364,13 +377,5 @@ bool GLGizmoFlatten::is_plane_update_necessary() const
return false;
}
Vec3d GLGizmoFlatten::get_flattening_normal() const
{
Vec3d out = m_normal;
m_normal = Vec3d::Zero();
m_starting_center = Vec3d::Zero();
return out;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -18,7 +18,6 @@ class GLGizmoFlatten : public GLGizmoBase
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
private:
mutable Vec3d m_normal;
struct PlaneData {
std::vector<Vec3d> vertices; // should be in fact local in update_planes()
@ -34,8 +33,8 @@ private:
Vec3d m_first_instance_mirror;
std::vector<PlaneData> m_planes;
bool m_mouse_left_down = false;
bool m_planes_valid = false;
mutable Vec3d m_starting_center;
const ModelObject* m_old_model_object = nullptr;
std::vector<const Transform3d*> instances_matrices;
@ -46,17 +45,22 @@ public:
GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
void set_flattening_data(const ModelObject* model_object);
Vec3d get_flattening_normal() const;
/// <summary>
/// Apply rotation on select plane
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
virtual void on_set_state() override;
virtual CommonGizmosDataID on_get_requirements() const override;
bool on_init() override;
std::string on_get_name() const override;
bool on_is_activable() const override;
void on_render() override;
void on_render_for_picking() override;
void on_set_state() override;
CommonGizmosDataID on_get_requirements() const override;
};
} // namespace GUI

View File

@ -412,19 +412,33 @@ void GLGizmoHollow::delete_selected_points()
select_point(NoPoints);
}
void GLGizmoHollow::on_update(const UpdateData& data)
bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event)
{
sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
if (mouse_event.Moving()) return false;
if (use_grabbers(mouse_event)) return true;
if (m_hover_id != -1) {
std::pair<Vec3f, Vec3f> pos_and_normal;
if (! unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
return;
drain_holes[m_hover_id].pos = pos_and_normal.first;
drain_holes[m_hover_id].normal = -pos_and_normal.second;
// wxCoord == int --> wx/types.h
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
Vec2d mouse_pos = mouse_coord.cast<double>();
Selection & selection = m_parent.get_selection();
static bool pending_right_up = false;
if (mouse_event.RightDown() && selection.get_object_idx() != -1 &&
gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) {
// we need to set the following right up as processed to avoid showing
// the context menu if the user release the mouse over the object
pending_right_up = true;
// event was taken care of by the SlaSupports gizmo
return true;
}
if (pending_right_up && mouse_event.RightUp()) {
pending_right_up = false;
return true;
}
}
return false;
}
void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
{
@ -822,6 +836,17 @@ void GLGizmoHollow::on_stop_dragging()
}
void GLGizmoHollow::on_dragging(const UpdateData &data)
{
assert(m_hover_id != -1);
std::pair<Vec3f, Vec3f> pos_and_normal;
if (!unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
return;
sla::DrainHoles &drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
drain_holes[m_hover_id].pos = pos_and_normal.first;
drain_holes[m_hover_id].normal = -pos_and_normal.second;
}
void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar)
{

View File

@ -35,10 +35,16 @@ public:
bool is_selection_rectangle_dragging() const {
return m_selection_rectangle.is_dragging();
}
/// <summary>
/// Postpone to Grabber for move
/// Detect move of object by dragging
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
private:
bool on_init() override;
void on_update(const UpdateData& data) override;
void on_render() override;
void on_render_for_picking() override;
@ -93,6 +99,7 @@ protected:
void on_set_hover_id() override;
void on_start_dragging() override;
void on_stop_dragging() override;
void on_dragging(const UpdateData &data) override;
void on_render_input_window(float x, float y, float bottom_limit) override;
virtual CommonGizmosDataID on_get_requirements() const override;

View File

@ -39,6 +39,10 @@ std::string GLGizmoMove3D::get_tooltip() const
return "";
}
bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
return use_grabbers(mouse_event);
}
bool GLGizmoMove3D::on_init()
{
for (int i = 0; i < 3; ++i) {
@ -62,22 +66,23 @@ bool GLGizmoMove3D::on_is_activable() const
void GLGizmoMove3D::on_start_dragging()
{
if (m_hover_id != -1) {
m_displacement = Vec3d::Zero();
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();
m_starting_box_bottom_center(2) = box.min(2);
}
assert(m_hover_id != -1);
m_displacement = Vec3d::Zero();
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();
m_starting_box_bottom_center(2) = box.min(2);
}
void GLGizmoMove3D::on_stop_dragging()
{
m_parent.do_move(L("Gizmo-Move"));
m_displacement = Vec3d::Zero();
}
void GLGizmoMove3D::on_update(const UpdateData& data)
void GLGizmoMove3D::on_dragging(const UpdateData& data)
{
if (m_hover_id == 0)
m_displacement.x() = calc_projection(data);
@ -85,6 +90,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data)
m_displacement.y() = calc_projection(data);
else if (m_hover_id == 2)
m_displacement.z() = calc_projection(data);
Selection &selection = m_parent.get_selection();
selection.translate(m_displacement);
}
void GLGizmoMove3D::on_render()

View File

@ -28,19 +28,24 @@ public:
double get_snap_step(double step) const { return m_snap_step; }
void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_displacement() const { return m_displacement; }
std::string get_tooltip() const override;
/// <summary>
/// Postpone to Grabber for move
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_stop_dragging() override;
virtual void on_update(const UpdateData& data) override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
bool on_init() override;
std::string on_get_name() const override;
bool on_is_activable() const override;
void on_start_dragging() override;
void on_stop_dragging() override;
void on_dragging(const UpdateData& data) override;
void on_render() override;
void on_render_for_picking() override;
private:
double calc_projection(const UpdateData& data) const;

View File

@ -570,7 +570,108 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
return false;
}
bool GLGizmoPainterBase::on_mouse(const wxMouseEvent &mouse_event)
{
// TODO: distribute implementation into gizmos itself
GLGizmosManager & mng = m_parent.get_gizmos_manager();
GLGizmosManager::EType current_type = mng.get_current_type();
// wxCoord == int --> wx/types.h
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
Vec2d mouse_pos = mouse_coord.cast<double>();
if (mouse_event.Moving()) {
if (current_type == GLGizmosManager::MmuSegmentation ||
current_type == GLGizmosManager::FdmSupports)
gizmo_event(SLAGizmoEventType::Moving, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(),
false);
}
// when control is down we allow scene pan and rotation even when clicking
// over some object
bool control_down = mouse_event.CmdDown();
bool grabber_contains_mouse = (get_hover_id() != -1);
const Selection &selection = m_parent.get_selection();
int selected_object_idx = selection.get_object_idx();
if (mouse_event.LeftDown() && (!control_down || grabber_contains_mouse)) {
if ((current_type == GLGizmosManager::SlaSupports ||
current_type == GLGizmosManager::Hollow ||
current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation) &&
gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(), false))
// the gizmo got the event and took some action, there is no need
// to do anything more
return true;
} else if (mouse_event.RightDown() && !control_down && selected_object_idx != -1 &&
(current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation) &&
gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) {
// event was taken care of by the FdmSupports / Seam / MMUPainting gizmo
return true;
} else if (mouse_event.Dragging() &&
m_parent.get_move_volume_id() != -1 &&
(current_type == GLGizmosManager::SlaSupports ||
current_type == GLGizmosManager::Hollow ||
current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation))
// don't allow dragging objects with the Sla gizmo on
return true;
else if (mouse_event.Dragging() && !control_down &&
(current_type == GLGizmosManager::SlaSupports ||
current_type == GLGizmosManager::Hollow ||
current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation) &&
gizmo_event(SLAGizmoEventType::Dragging, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(), false)) {
// the gizmo got the event and took some action, no need to do
// anything more here
m_parent.set_as_dirty();
return true;
} else if (mouse_event.Dragging() && control_down &&
(mouse_event.LeftIsDown() || mouse_event.RightIsDown())) {
// CTRL has been pressed while already dragging -> stop current action
if (mouse_event.LeftIsDown())
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(), true);
else if (mouse_event.RightIsDown())
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(), true);
} else if (mouse_event.LeftUp() &&
(current_type == GLGizmosManager::SlaSupports ||
current_type == GLGizmosManager::Hollow ||
current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation) &&
!m_parent.is_mouse_dragging()) {
// in case SLA/FDM 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,
mouse_event.ShiftDown(), mouse_event.AltDown(),
control_down);
return true;
} else if (mouse_event.RightUp() &&
(current_type == GLGizmosManager::FdmSupports ||
current_type == GLGizmosManager::Seam ||
current_type == GLGizmosManager::MmuSegmentation) &&
!m_parent.is_mouse_dragging()) {
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos,
mouse_event.ShiftDown(), mouse_event.AltDown(),
control_down);
return true;
}
return false;
}
void GLGizmoPainterBase::update_raycast_cache(const Vec2d& mouse_position,
const Camera& camera,

View File

@ -126,6 +126,15 @@ public:
virtual const float get_cursor_radius_max() const { return CursorRadiusMax; }
virtual const float get_cursor_radius_step() const { return CursorRadiusStep; }
/// <summary>
/// Implement when want to process mouse events in gizmo
/// Click, Right click, move, drag, ...
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information and don't want to
/// propagate it otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
virtual void render_triangles(const Selection& selection) const;
void render_cursor() const;
@ -224,9 +233,6 @@ private:
protected:
void on_set_state() override;
void on_start_dragging() override {}
void on_stop_dragging() override {}
virtual void on_opening() = 0;
virtual void on_shutdown() = 0;
virtual PainterGizmoType get_painter_type() const = 0;

View File

@ -73,6 +73,13 @@ std::string GLGizmoRotate::get_tooltip() const
return (m_hover_id == 0 || m_grabbers[0].dragging) ? axis + ": " + format((float)Geometry::rad2deg(m_angle), 4) : "";
}
bool GLGizmoRotate::on_mouse(const wxMouseEvent &mouse_event)
{
return use_grabbers(mouse_event);
}
void GLGizmoRotate::dragging(const UpdateData &data) { on_dragging(data); }
bool GLGizmoRotate::on_init()
{
m_grabbers.push_back(Grabber());
@ -90,7 +97,7 @@ void GLGizmoRotate::on_start_dragging()
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
}
void GLGizmoRotate::on_update(const UpdateData& data)
void GLGizmoRotate::on_dragging(const UpdateData &data)
{
Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection()));
@ -445,16 +452,25 @@ GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_fil
load_rotoptimize_state();
}
bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event) {
if (mouse_event.Dragging() && m_dragging) {
// Apply new temporary rotations
TransformationType transformation_type(
TransformationType::World_Relative_Joint);
if (mouse_event.AltDown()) transformation_type.set_independent();
m_parent.get_selection().rotate(get_rotation(), transformation_type);
}
return use_grabbers(mouse_event);
}
bool GLGizmoRotate3D::on_init()
{
for (GLGizmoRotate& g : m_gizmos) {
if (!g.init())
return false;
}
for (GLGizmoRotate& g : m_gizmos)
if (!g.init()) return false;
for (unsigned int i = 0; i < 3; ++i) {
for (unsigned int i = 0; i < 3; ++i)
m_gizmos[i].set_highlight_color(AXES_COLOR[i]);
}
m_shortcut_key = WXK_CONTROL_R;
@ -473,14 +489,21 @@ bool GLGizmoRotate3D::on_is_activable() const
void GLGizmoRotate3D::on_start_dragging()
{
if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].start_dragging();
assert(0 <= m_hover_id && m_hover_id < 3);
m_gizmos[m_hover_id].start_dragging();
}
void GLGizmoRotate3D::on_stop_dragging()
{
if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].stop_dragging();
assert(0 <= m_hover_id && m_hover_id < 3);
m_parent.do_rotate(L("Gizmo-Rotate"));
m_gizmos[m_hover_id].stop_dragging();
}
void GLGizmoRotate3D::on_dragging(const UpdateData &data)
{
assert(0 <= m_hover_id && m_hover_id < 3);
m_gizmos[m_hover_id].dragging(data);
}
void GLGizmoRotate3D::on_render()

View File

@ -50,11 +50,19 @@ public:
std::string get_tooltip() const override;
/// <summary>
/// Postpone to Grabber for move
/// Detect move of object by dragging
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
void dragging(const UpdateData &data);
protected:
bool on_init() override;
std::string on_get_name() const override { return ""; }
void on_start_dragging() override;
void on_update(const UpdateData& data) override;
void on_dragging(const UpdateData &data) override;
void on_render() override;
void on_render_for_picking() override;
@ -92,6 +100,13 @@ public:
return tooltip;
}
/// <summary>
/// Postpone to Rotation
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
bool on_init() override;
std::string on_get_name() const override;
@ -118,12 +133,8 @@ protected:
bool on_is_activable() const override;
void on_start_dragging() override;
void on_stop_dragging() override;
void on_update(const UpdateData& data) override
{
for (GLGizmoRotate& g : m_gizmos) {
g.update(data);
}
}
void on_dragging(const UpdateData &data) override;
void on_render() override;
void on_render_for_picking() override
{

View File

@ -52,6 +52,22 @@ std::string GLGizmoScale3D::get_tooltip() const
return "";
}
bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
{
if (mouse_event.Dragging()) {
if (m_dragging) {
// Apply new temporary scale factors
TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
if (mouse_event.AltDown()) transformation_type.set_independent();
Selection &selection = m_parent.get_selection();
selection.scale(get_scale(), transformation_type);
if (mouse_event.CmdDown()) selection.translate(m_offset, true);
}
}
return use_grabbers(mouse_event);
}
bool GLGizmoScale3D::on_init()
{
for (int i = 0; i < 10; ++i)
@ -87,23 +103,25 @@ bool GLGizmoScale3D::on_is_activable() const
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 : m_parent.get_selection().get_bounding_box();
assert(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 : 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));
m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min(0), center(1), center(2));
m_starting.pivots[2] = m_transform * Vec3d(center(0), m_starting.box.max(1), center(2));
m_starting.pivots[3] = m_transform * Vec3d(center(0), m_starting.box.min(1), center(2));
m_starting.pivots[4] = m_transform * Vec3d(center(0), center(1), m_starting.box.max(2));
m_starting.pivots[5] = m_transform * Vec3d(center(0), center(1), m_starting.box.min(2));
}
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[1] = m_transform * Vec3d(m_starting.box.min(0), center(1), center(2));
m_starting.pivots[2] = m_transform * Vec3d(center(0), m_starting.box.max(1), center(2));
m_starting.pivots[3] = m_transform * Vec3d(center(0), m_starting.box.min(1), center(2));
m_starting.pivots[4] = m_transform * Vec3d(center(0), center(1), m_starting.box.max(2));
m_starting.pivots[5] = m_transform * Vec3d(center(0), center(1), m_starting.box.min(2));
}
void GLGizmoScale3D::on_update(const UpdateData& data)
void GLGizmoScale3D::on_stop_dragging() {
m_parent.do_scale(L("Gizmo-Scale"));
}
void GLGizmoScale3D::on_dragging(const UpdateData& data)
{
if ((m_hover_id == 0) || (m_hover_id == 1))
do_scale_along_axis(X, data);

View File

@ -42,16 +42,22 @@ public:
const Vec3d& get_scale() const { return m_scale; }
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
const Vec3d& get_offset() const { return m_offset; }
std::string get_tooltip() const override;
/// <summary>
/// Postpone to Grabber for scale
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_update(const UpdateData& data) override;
virtual void on_stop_dragging() override;
virtual void on_dragging(const UpdateData& data) override;
virtual void on_render() override;
virtual void on_render_for_picking() override;

View File

@ -530,22 +530,6 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
select_point(NoPoints);
}
void GLGizmoSlaSupports::on_update(const UpdateData& data)
{
if (! m_editing_mode)
return;
else {
if (m_hover_id != -1 && (! m_editing_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) {
std::pair<Vec3f, Vec3f> pos_and_normal;
if (! unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
return;
m_editing_cache[m_hover_id].support_point.pos = pos_and_normal.first;
m_editing_cache[m_hover_id].support_point.is_new_island = false;
m_editing_cache[m_hover_id].normal = pos_and_normal.second;
}
}
}
std::vector<const ConfigOption*> GLGizmoSlaSupports::get_config_options(const std::vector<std::string>& keys) const
{
std::vector<const ConfigOption*> out;
@ -966,7 +950,21 @@ void GLGizmoSlaSupports::on_stop_dragging()
m_point_before_drag = CacheEntry();
}
void GLGizmoSlaSupports::on_dragging(const UpdateData &data)
{
assert(m_hover_id != -1);
if (!m_editing_mode) return;
if (m_editing_cache[m_hover_id].support_point.is_new_island && m_lock_unique_islands)
return;
std::pair<Vec3f, Vec3f> pos_and_normal;
if (!unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
return;
m_editing_cache[m_hover_id].support_point.pos = pos_and_normal.first;
m_editing_cache[m_hover_id].support_point.is_new_island = false;
m_editing_cache[m_hover_id].normal = pos_and_normal.second;
}
void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar)
{
@ -1103,6 +1101,34 @@ void GLGizmoSlaSupports::reslice_SLA_supports(bool postpone_error_messages) cons
});
}
bool GLGizmoSlaSupports::on_mouse(const wxMouseEvent &mouse_event){
if (mouse_event.Moving()) return false;
if (use_grabbers(mouse_event)) return true;
// wxCoord == int --> wx/types.h
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
Vec2d mouse_pos = mouse_coord.cast<double>();
Selection &selection = m_parent.get_selection();
static bool pending_right_up = false;
if (mouse_event.RightDown() &&
selection.get_object_idx() != -1 &&
gizmo_event(SLAGizmoEventType::RightDown, mouse_pos, false, false, false)) {
// we need to set the following right up as processed to avoid showing
// the context menu if the user release the mouse over the object
pending_right_up = true;
// event was taken care of by the SlaSupports gizmo
return true;
}
if (pending_right_up && mouse_event.RightUp()) {
pending_right_up = false;
return true;
}
return false;
}
void GLGizmoSlaSupports::get_data_from_backend()
{
if (! has_backend_supports())

View File

@ -70,10 +70,16 @@ public:
bool wants_enter_leave_snapshots() const override { return true; }
std::string get_gizmo_entering_text() const override { return _u8L("Entering SLA support points"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving SLA support points"); }
/// <summary>
/// Process mouse event
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
private:
bool on_init() override;
void on_update(const UpdateData& data) override;
void on_render() override;
void on_render_for_picking() override;
@ -103,7 +109,6 @@ private:
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
bool is_mesh_point_clipped(const Vec3d& point) const;
bool is_point_in_hole(const Vec3f& pt) const;
//void find_intersecting_facets(const igl::AABB<Eigen::MatrixXf, 3>* aabb, const Vec3f& normal, double offset, std::vector<unsigned int>& out) const;
// Methods that do the model_object and editing cache synchronization,
@ -126,13 +131,13 @@ private:
protected:
void on_set_state() override;
void on_set_hover_id() override
{
if (! m_editing_mode || (int)m_editing_cache.size() <= m_hover_id)
m_hover_id = -1;
}
void on_start_dragging() override;
void on_stop_dragging() override;
void on_dragging(const UpdateData &data) override;
void on_render_input_window(float x, float y, float bottom_limit) override;
std::string on_get_name() const override;

View File

@ -38,6 +38,7 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
, m_enabled(false)
, m_icons_texture_dirty(true)
, m_current(Undefined)
, m_hover(Undefined)
, m_tooltip("")
, m_serializing(false)
{
@ -46,33 +47,34 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
{
std::vector<size_t> out;
out.reserve(m_gizmos.size());
for (size_t i=0; i<m_gizmos.size(); ++i)
if (m_gizmos[i]->is_selectable())
out.push_back(i);
return out;
}
size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
GLGizmosManager::EType GLGizmosManager::get_gizmo_from_mouse(const Vec2d &mouse_pos) const
{
if (! m_enabled)
return Undefined;
if (!m_enabled) return Undefined;
float cnv_h = (float)m_parent.get_canvas_size().get_height();
float height = get_scaled_total_height();
float cnv_h = (float) m_parent.get_canvas_size().get_height();
float height = get_scaled_total_height();
float icons_size = m_layout.scaled_icons_size();
float border = m_layout.scaled_border();
float stride_y = m_layout.scaled_stride_y();
float top_y = 0.5f * (cnv_h - height) + border;
float border = m_layout.scaled_border();
float stride_y = m_layout.scaled_stride_y();
float top_y = 0.5f * (cnv_h - height) + border;
// is mouse horizontally in the area?
if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) {
if ((border <= (float) mouse_pos(0) &&
((float) mouse_pos(0) <= border + icons_size))) {
// which icon is it on?
size_t from_top = (size_t)((float)mouse_pos(1) - top_y) / stride_y;
size_t from_top = (size_t) ((float) mouse_pos(1) - top_y) / stride_y;
// is it really on the icon or already past the border?
if ((float)mouse_pos(1) <= top_y + from_top * stride_y + icons_size) {
if ((float) mouse_pos(1) <= top_y + from_top * stride_y + icons_size) {
std::vector<size_t> selectable = get_selectable_idxs();
if (from_top < selectable.size())
return selectable[from_top];
if (from_top < selectable.size())
return static_cast<EType>(selectable[from_top]);
}
}
return Undefined;
@ -177,9 +179,13 @@ void GLGizmosManager::reset_all_states()
bool GLGizmosManager::open_gizmo(EType type)
{
int idx = int(type);
if (m_gizmos[idx]->is_activable()
&& activate_gizmo(m_current == idx ? Undefined : (EType)idx)) {
int idx = static_cast<int>(type);
// re-open same type cause closing
if (m_current == type) type = Undefined;
if (m_gizmos[idx]->is_activable() && activate_gizmo(type)) {
// remove update data into gizmo itself
update_data();
return true;
}
@ -219,16 +225,7 @@ void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
m_gizmos[type]->disable_grabber(id);
}
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));
}
// TODO: divide into gizmo: on init + on selection change
void GLGizmosManager::update_data()
{
if (!m_enabled)
@ -343,14 +340,6 @@ void GLGizmosManager::stop_dragging()
m_gizmos[m_current]->stop_dragging();
}
Vec3d GLGizmosManager::get_displacement() const
{
if (!m_enabled)
return Vec3d::Zero();
return dynamic_cast<GLGizmoMove3D*>(m_gizmos[Move].get())->get_displacement();
}
Vec3d GLGizmosManager::get_scale() const
{
if (!m_enabled)
@ -367,14 +356,6 @@ void GLGizmosManager::set_scale(const Vec3d& scale)
dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->set_scale(scale);
}
Vec3d GLGizmosManager::get_scale_offset() const
{
if (!m_enabled || m_gizmos.empty())
return Vec3d::Zero();
return dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->get_offset();
}
Vec3d GLGizmosManager::get_rotation() const
{
if (!m_enabled || m_gizmos.empty())
@ -390,14 +371,6 @@ void GLGizmosManager::set_rotation(const Vec3d& rotation)
dynamic_cast<GLGizmoRotate3D*>(m_gizmos[Rotate].get())->set_rotation(rotation);
}
Vec3d GLGizmosManager::get_flattening_normal() const
{
if (!m_enabled || m_gizmos.empty())
return Vec3d::Zero();
return dynamic_cast<GLGizmoFlatten*>(m_gizmos[Flatten].get())->get_flattening_normal();
}
void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
{
if (!m_enabled || m_gizmos.empty())
@ -517,7 +490,7 @@ std::string GLGizmosManager::get_tooltip() const
return (curr != nullptr) ? curr->get_tooltip() : "";
}
bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt)
bool GLGizmosManager::on_mouse_wheel(const wxMouseEvent &evt)
{
bool processed = false;
@ -530,227 +503,108 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt)
return processed;
}
bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
{
// used to set a right up event as processed when needed
static bool pending_right_up = false;
Point pos(evt.GetX(), evt.GetY());
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
Selection& selection = m_parent.get_selection();
int selected_object_idx = selection.get_object_idx();
bool processed = false;
// when control is down we allow scene pan and rotation even when clicking over some object
bool control_down = evt.CmdDown();
// mouse anywhere
if (evt.Moving()) {
m_tooltip = update_hover_state(mouse_pos);
if (m_current == MmuSegmentation || m_current == FdmSupports)
gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown());
} else if (evt.LeftUp()) {
if (m_mouse_capture.left) {
processed = true;
m_mouse_capture.left = false;
bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) {
assert(m_enabled);
// keep information about events to process
struct MouseCapture
{
bool left = false;
bool middle = false;
bool right = false;
bool exist_tooltip = false;
MouseCapture() = default;
bool any() const { return left || middle || right; }
void reset() {
left = false;
middle = false;
right = false;
}
else if (is_dragging()) {
switch (m_current) {
case Move: { m_parent.do_move(L("Gizmo-Move")); break; }
case Scale: { m_parent.do_scale(L("Gizmo-Scale")); break; }
case Rotate: { m_parent.do_rotate(L("Gizmo-Rotate")); break; }
default: break;
}
};
static MouseCapture mc;
stop_dragging();
update_data();
// wxCoord == int --> wx/types.h
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
Vec2d mouse_pos = mouse_coord.cast<double>();
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.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints
m_parent.refresh_camera_scene_box();
EType gizmo = get_gizmo_from_mouse(mouse_pos);
bool selected_gizmo = gizmo != Undefined;
processed = true;
}
// else
// return false;
}
else if (evt.MiddleUp()) {
if (m_mouse_capture.middle) {
processed = true;
m_mouse_capture.middle = false;
}
else
// fast reaction on move mouse
if (mouse_event.Moving()) {
assert(!mc.any());
if (selected_gizmo) {
mc.exist_tooltip = true;
update_hover_state(gizmo);
// at this moment is enebled to process mouse move under gizmo
// tools bar e.g. Do not interupt dragging.
return false;
} else if (mc.exist_tooltip) {
// first move out of gizmo tool bar - unselect tooltip
mc.exist_tooltip = false;
update_hover_state(Undefined);
return false;
}
return false;
}
else if (evt.RightUp()) {
if (pending_right_up) {
pending_right_up = false;
if (selected_gizmo) {
// mouse is above toolbar
if (mouse_event.LeftDown() || mouse_event.LeftDClick()) {
mc.left = true;
open_gizmo(gizmo);
return true;
} else if (mouse_event.RightDown()) {
mc.right = true;
return true;
} else if (mouse_event.MiddleDown()) {
mc.middle = true;
return true;
}
if (m_mouse_capture.right) {
processed = true;
m_mouse_capture.right = false;
}
// else
// return false;
}
else if (evt.Dragging() && !is_dragging()) {
if (m_mouse_capture.any())
// if the button down was done on this toolbar, prevent from dragging into the scene
processed = true;
// else
// return false;
}
else if (evt.Dragging() && is_dragging()) {
if (!m_parent.get_wxglcanvas()->HasCapture())
m_parent.get_wxglcanvas()->CaptureMouse();
m_parent.set_mouse_as_dragging();
update(m_parent.mouse_ray(pos), pos);
switch (m_current)
{
case Move:
{
// Apply new temporary offset
selection.translate(get_displacement());
wxGetApp().obj_manipul()->set_dirty();
break;
}
case Scale:
{
// Apply new temporary scale factors
TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
if (evt.AltDown())
transformation_type.set_independent();
selection.scale(get_scale(), transformation_type);
if (control_down)
selection.translate(get_scale_offset(), true);
wxGetApp().obj_manipul()->set_dirty();
break;
}
case Rotate:
{
// Apply new temporary rotations
TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (evt.AltDown())
transformation_type.set_independent();
selection.rotate(get_rotation(), transformation_type);
wxGetApp().obj_manipul()->set_dirty();
break;
}
default:
break;
}
m_parent.set_as_dirty();
processed = true;
}
if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) {
// mouse is outside the toolbar
m_tooltip.clear();
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
&& gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown()))
// the gizmo got the event and took some action, there is no need to do anything more
processed = true;
else if (!selection.is_empty() && grabber_contains_mouse()) {
update_data();
selection.start_dragging();
start_dragging();
// Let the plater know that the dragging started
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED));
if (m_current == Flatten) {
// Rotate the object so the normal points downward:
m_parent.do_flatten(get_flattening_normal(), L("Gizmo-Place on Face"));
wxGetApp().obj_manipul()->set_dirty();
}
m_parent.set_as_dirty();
processed = true;
if (mc.any()) {
// Check if exist release of event started above toolbar?
if (mouse_event.Dragging()) {
if (!selected_gizmo && mc.exist_tooltip) {
// dragging out of gizmo let tooltip disapear
mc.exist_tooltip = false;
update_hover_state(Undefined);
}
// draging start on toolbar so no propagation into scene
return true;
} else if (mc.left && mouse_event.LeftUp()) {
mc.left = false;
return true;
} else if (mc.right && mouse_event.RightUp()) {
mc.right = false;
return true;
} else if (mc.middle && mouse_event.MiddleUp()) {
mc.middle = false;
return true;
}
else if (evt.RightDown() && selected_object_idx != -1 && (m_current == SlaSupports || m_current == Hollow)
&& gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) {
// we need to set the following right up as processed to avoid showing the context menu if the user release the mouse over the object
pending_right_up = true;
// event was taken care of by the SlaSupports gizmo
processed = true;
}
else if (evt.RightDown() && !control_down && selected_object_idx != -1 && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
&& gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) {
// event was taken care of by the FdmSupports / Seam / MMUPainting gizmo
processed = true;
}
else if (evt.Dragging() && m_parent.get_move_volume_id() != -1
&& (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation))
// don't allow dragging objects with the Sla gizmo on
processed = true;
else if (evt.Dragging() && !control_down && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
&& gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown())) {
// the gizmo got the event and took some action, no need to do anything more here
m_parent.set_as_dirty();
processed = true;
}
else if (evt.Dragging() && control_down && (evt.LeftIsDown() || evt.RightIsDown())) {
// CTRL has been pressed while already dragging -> stop current action
if (evt.LeftIsDown())
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true);
else if (evt.RightIsDown())
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true);
}
else if (evt.LeftUp() && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) {
// in case SLA/FDM 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(), control_down);
processed = true;
}
else if (evt.LeftUp() && m_current == Flatten && m_gizmos[m_current]->get_hover_id() != -1) {
// to avoid to loose the selection when user clicks an the white faces of a different object while the Flatten gizmo is active
selection.stop_dragging();
wxGetApp().obj_manipul()->set_dirty();
processed = true;
}
else if (evt.RightUp() && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && !m_parent.is_mouse_dragging()) {
gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down);
processed = true;
}
else if (evt.LeftUp()) {
selection.stop_dragging();
wxGetApp().obj_manipul()->set_dirty();
}
}
else {
// mouse inside toolbar
if (evt.LeftDown() || evt.LeftDClick()) {
m_mouse_capture.left = true;
m_mouse_capture.parent = &m_parent;
processed = true;
if (!selection.is_empty()) {
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 = &m_parent;
}
else if (evt.RightDown()) {
m_mouse_capture.right = true;
m_mouse_capture.parent = &m_parent;
}
// event out of window is not porocessed
// left down on gizmo -> keep down -> move out of window -> release left
if (mouse_event.Leaving()) mc.reset();
}
return false;
}
return processed;
bool GLGizmosManager::on_mouse(const wxMouseEvent &mouse_event)
{
if (!m_enabled) return false;
// tool bar wants to use event?
if (gizmos_toolbar_on_mouse(mouse_event)) return true;
// current gizmo wants to use event?
if (m_current != Undefined &&
// check if gizmo override method could be slower than simple call virtual function
// &m_gizmos[m_current]->on_mouse != &GLGizmoBase::on_mouse &&
m_gizmos[m_current]->on_mouse(mouse_event))
return true;
return false;
}
bool GLGizmosManager::on_char(wxKeyEvent& evt)
@ -1182,42 +1036,26 @@ bool GLGizmosManager::generate_icons_texture() const
return res;
}
void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
void GLGizmosManager::update_hover_state(const EType &type)
{
if (!m_enabled)
assert(m_enabled);
if (type == Undefined) {
m_hover = Undefined;
m_tooltip.clear();
return;
size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx) {
activate_gizmo(m_current == idx ? Undefined : (EType)idx);
wxGetApp().obj_list()->select_object_item((EType)idx <= Rotate);
}
}
std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
{
std::string name = "";
if (!m_enabled)
return name;
m_hover = Undefined;
size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
if (idx != Undefined) {
name = m_gizmos[idx]->get_name();
if (m_gizmos[idx]->is_activable())
m_hover = (EType)idx;
}
return name;
const GLGizmoBase &hovered_gizmo = *m_gizmos[type];
m_hover = hovered_gizmo.is_activable() ? type : Undefined;
m_tooltip = hovered_gizmo.get_name();
}
bool GLGizmosManager::activate_gizmo(EType type)
{
if (m_gizmos.empty() || m_current == type)
return true;
assert(!m_gizmos.empty());
// already activated
if (m_current == type) return true;
if (m_current != Undefined) {
// clean up previous gizmo
@ -1226,31 +1064,36 @@ bool GLGizmosManager::activate_gizmo(EType type)
if (old_gizmo.get_state() != GLGizmoBase::Off)
return false; // gizmo refused to be turned off, do nothing.
if (!m_serializing
&& old_gizmo.wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(),
old_gizmo.get_gizmo_leaving_text(),
UndoRedo::SnapshotType::LeavingGizmoWithAction);
if (!m_serializing && old_gizmo.wants_enter_leave_snapshots())
Plater::TakeSnapshot
snapshot(wxGetApp().plater(),
old_gizmo.get_gizmo_leaving_text(),
UndoRedo::SnapshotType::LeavingGizmoWithAction);
}
// check deactivation of gizmo
if (type == Undefined) {
m_current = type;
// it is deactivation of gizmo
m_current = Undefined;
return true;
}
// set up new gizmo
GLGizmoBase& new_gizmo = *m_gizmos[type];
if (!new_gizmo.is_activable()) return false;
if (!m_serializing && new_gizmo.wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(),
new_gizmo.get_gizmo_entering_text(),
UndoRedo::SnapshotType::EnteringGizmo);
new_gizmo.get_gizmo_entering_text(),
UndoRedo::SnapshotType::EnteringGizmo);
m_current = type;
new_gizmo.set_state(GLGizmoBase::On);
if (new_gizmo.get_state() != GLGizmoBase::On)
if (new_gizmo.get_state() != GLGizmoBase::On) {
m_current = Undefined;
return false; // gizmo refused to be turned on.
}
// sucessful activation of gizmo
return true;
}

View File

@ -102,28 +102,22 @@ private:
std::pair<EType, bool> m_highlight; // bool true = higlightedShown, false = highlightedHidden
std::vector<size_t> get_selectable_idxs() const;
size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const;
EType get_gizmo_from_mouse(const Vec2d &mouse_pos) const;
bool activate_gizmo(EType type);
struct MouseCapture
{
bool left;
bool middle;
bool right;
GLCanvas3D* parent;
MouseCapture() { reset(); }
bool any() const { return left || middle || right; }
void reset() { left = middle = right = false; parent = nullptr; }
};
MouseCapture m_mouse_capture;
std::string m_tooltip;
bool m_serializing;
std::unique_ptr<CommonGizmosDataPool> m_common_gizmos_data;
/// <summary>
/// Process mouse event on gizmo toolbar
/// </summary>
/// <param name="mouse_event">Event descriptor</param>
/// <returns>TRUE when take responsibility for event otherwise FALSE.
/// On true, event should not be process by others.
/// On false, event should be process by others.</returns>
bool gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event);
public:
explicit GLGizmosManager(GLCanvas3D& parent);
@ -180,7 +174,6 @@ public:
void set_hover_id(int id);
void enable_grabber(EType type, unsigned int id, bool enable);
void update(const Linef3& mouse_ray, const Point& mouse_pos);
void update_data();
EType get_current_type() const { return m_current; }
@ -194,18 +187,12 @@ public:
void start_dragging();
void stop_dragging();
Vec3d get_displacement() const;
Vec3d get_scale() const;
void set_scale(const Vec3d& scale);
Vec3d get_scale_offset() const;
Vec3d get_rotation() const;
void set_rotation(const Vec3d& rotation);
Vec3d get_flattening_normal() const;
void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object);
@ -229,8 +216,8 @@ public:
std::string get_tooltip() const;
bool on_mouse(wxMouseEvent& evt);
bool on_mouse_wheel(wxMouseEvent& evt);
bool on_mouse(const wxMouseEvent &mouse_event);
bool on_mouse_wheel(const wxMouseEvent &evt);
bool on_char(wxKeyEvent& evt);
bool on_key(wxKeyEvent& evt);
@ -253,8 +240,7 @@ private:
bool generate_icons_texture() const;
void update_on_off_state(const Vec2d& mouse_pos);
std::string update_hover_state(const Vec2d& mouse_pos);
void update_hover_state(const EType &type);
bool grabber_contains_mouse() const;
};