Rotating/panning the view, using mouse left/right + CTRL modifier, while any gizmo is active

This commit is contained in:
enricoturri1966 2020-10-19 15:55:16 +02:00
parent 0f8f412e90
commit 68a7e5ce41
3 changed files with 131 additions and 134 deletions

View file

@ -3505,40 +3505,35 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
}
if (m_main_toolbar.on_mouse(evt, *this))
{
if (m_main_toolbar.on_mouse(evt, *this)) {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
m_mouse.set_start_position_3D_as_invalid();
return;
}
if (m_undoredo_toolbar.on_mouse(evt, *this))
{
if (m_undoredo_toolbar.on_mouse(evt, *this)) {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
m_mouse.set_start_position_3D_as_invalid();
return;
}
if (wxGetApp().plater()->get_collapse_toolbar().on_mouse(evt, *this))
{
if (wxGetApp().plater()->get_collapse_toolbar().on_mouse(evt, *this)) {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
m_mouse.set_start_position_3D_as_invalid();
return;
}
if (wxGetApp().plater()->get_view_toolbar().on_mouse(evt, *this))
{
if (wxGetApp().plater()->get_view_toolbar().on_mouse(evt, *this)) {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
m_mouse.set_start_position_3D_as_invalid();
return;
}
if (m_gizmos.on_mouse(evt))
{
if (m_gizmos.on_mouse(evt)) {
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
mouse_up_cleanup();
@ -3547,12 +3542,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return;
}
#if ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
bool any_gizmo_active = m_gizmos.get_current() != nullptr;
#endif // ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
int selected_object_idx = m_selection.get_object_idx();
int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
m_layers_editing.select_object(*m_model, layer_editing_object_idx);
if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
{
if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos)) {
m_mouse.drag.move_requires_threshold = false;
m_mouse.set_move_start_threshold_position_2D_as_invalid();
}
@ -3561,8 +3559,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// Grab keyboard focus on any mouse click event.
m_canvas->SetFocus();
if (evt.Entering())
{
if (evt.Entering()) {
//#if defined(__WXMSW__) || defined(__linux__)
// // On Windows and Linux needs focus in order to catch key events
// Set focus in order to remove it from sidebar fields
@ -3587,49 +3584,49 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.set_start_position_2D_as_invalid();
//#endif
}
else if (evt.Leaving())
{
else if (evt.Leaving()) {
_deactivate_undo_redo_toolbar_items();
// to remove hover on objects when the mouse goes out of this canvas
m_mouse.position = Vec2d(-1.0, -1.0);
m_dirty = true;
}
else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown())
{
else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) {
if (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item())
return;
// If user pressed left or right button we first check whether this happened
// on a volume or not.
m_layers_editing.state = LayersEditing::Unknown;
if ((layer_editing_object_idx != -1) && m_layers_editing.bar_rect_contains(*this, pos(0), pos(1)))
{
if (layer_editing_object_idx != -1 && m_layers_editing.bar_rect_contains(*this, pos(0), pos(1))) {
// A volume is selected and the mouse is inside the layer thickness bar.
// Start editing the layer height.
m_layers_editing.state = LayersEditing::Editing;
_perform_layer_editing_action(&evt);
}
else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled)
{
else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
&& m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
&& m_gizmos.get_current_type() != GLGizmosManager::Seam)
{
&& m_gizmos.get_current_type() != GLGizmosManager::Seam) {
m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect);
m_dirty = true;
}
}
else
{
else {
#if ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
// Select volume in this 3D canvas.
// Don't deselect a volume if layer editing is enabled or any gizmo is active. We want the object to stay selected
// during the scene manipulation.
if (m_picking_enabled && !any_gizmo_active && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
#else
// Select volume in this 3D canvas.
// Don't deselect a volume if layer editing is enabled. We want the object to stay selected
// during the scene manipulation.
if (m_picking_enabled && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()))
{
if (evt.LeftDown() && !m_hover_volume_idxs.empty())
{
if (m_picking_enabled && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
#endif // ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
if (evt.LeftDown() && !m_hover_volume_idxs.empty()) {
int volume_idx = get_first_hover_volume_idx();
bool already_selected = m_selection.contains_volume(volume_idx);
bool ctrl_down = evt.CmdDown();
@ -3638,8 +3635,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (already_selected && ctrl_down)
m_selection.remove(volume_idx);
else
{
else {
m_selection.add(volume_idx, !ctrl_down, true);
m_mouse.drag.move_requires_threshold = !already_selected;
if (already_selected)
@ -3649,8 +3645,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
// propagate event through callback
if (curr_idxs != m_selection.get_volume_idxs())
{
if (curr_idxs != m_selection.get_volume_idxs()) {
if (m_selection.is_empty())
m_gizmos.reset_all_states();
else
@ -3663,16 +3658,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
if (!m_hover_volume_idxs.empty())
{
if (evt.LeftDown() && m_moving_enabled && (m_mouse.drag.move_volume_idx == -1))
{
if (!m_hover_volume_idxs.empty()) {
if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) {
// Only accept the initial position, if it is inside the volume bounding box.
int volume_idx = get_first_hover_volume_idx();
BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box();
volume_bbox.offset(1.0);
if (volume_bbox.contains(m_mouse.scene_position))
{
#if ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
if (!any_gizmo_active && volume_bbox.contains(m_mouse.scene_position)) {
#else
if (volume_bbox.contains(m_mouse.scene_position)) {
#endif // ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None;
// The dragging operation is initiated.
m_mouse.drag.move_volume_idx = volume_idx;
@ -3684,18 +3680,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
}
else if (evt.Dragging() && evt.LeftIsDown() && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.move_volume_idx != -1))
{
if (!m_mouse.drag.move_requires_threshold)
{
else if (evt.Dragging() && evt.LeftIsDown() && m_layers_editing.state == LayersEditing::Unknown && m_mouse.drag.move_volume_idx != -1) {
if (!m_mouse.drag.move_requires_threshold) {
m_mouse.dragging = true;
Vec3d cur_pos = m_mouse.drag.start_position_3D;
// we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
if (m_selection.contains_volume(get_first_hover_volume_idx()))
{
if (m_selection.contains_volume(get_first_hover_volume_idx())) {
const Camera& camera = wxGetApp().plater()->get_camera();
if (std::abs(camera.get_dir_forward()(2)) < EPSILON)
{
if (std::abs(camera.get_dir_forward()(2)) < EPSILON) {
// side view -> move selected volumes orthogonally to camera view direction
Linef3 ray = mouse_ray(pos);
Vec3d dir = ray.unit_vector();
@ -3717,8 +3709,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// apply offset
cur_pos = m_mouse.drag.start_position_3D + projection_x * camera_right + projection_z * camera_up;
}
else
{
else {
// Generic view
// Get new position at the same Z of the initial click point.
float z0 = 0.0f;
@ -3732,35 +3723,32 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
}
else if (evt.Dragging() && evt.LeftIsDown() && m_picking_enabled && m_rectangle_selection.is_dragging())
{
else if (evt.Dragging() && evt.LeftIsDown() && m_picking_enabled && m_rectangle_selection.is_dragging()) {
m_rectangle_selection.dragging(pos.cast<double>());
m_dirty = true;
}
else if (evt.Dragging())
{
else if (evt.Dragging()) {
m_mouse.dragging = true;
if ((m_layers_editing.state != LayersEditing::Unknown) && (layer_editing_object_idx != -1))
{
if (m_layers_editing.state == LayersEditing::Editing)
{
if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
if (m_layers_editing.state == LayersEditing::Editing) {
_perform_layer_editing_action(&evt);
m_mouse.position = pos.cast<double>();
}
}
// do not process the dragging if the left mouse was set down in another canvas
else if (evt.LeftIsDown())
{
else if (evt.LeftIsDown()) {
// if dragging over blank area with left button, rotate
if (m_hover_volume_idxs.empty() && m_mouse.is_start_position_3D_defined())
{
#if ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
#else
if (m_hover_volume_idxs.empty() && m_mouse.is_start_position_3D_defined()) {
#endif // ENABLE_PAN_ROTATE_SCENE_IN_GIZMOS
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
if (wxGetApp().app_config->get("use_free_camera") == "1")
// Virtual track ball (similar to the 3DConnexion mouse).
wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.));
else
{
else {
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
// It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
// which checks an atomics (flushes CPU caches).
@ -3774,11 +3762,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
}
else if (evt.MiddleIsDown() || evt.RightIsDown())
{
else if (evt.MiddleIsDown() || evt.RightIsDown()) {
// If dragging over blank area with right button, pan.
if (m_mouse.is_start_position_2D_defined())
{
if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0
float z = 0.0f;
const Vec3d& cur_pos = _mouse_to_3d(pos, &z);
@ -3798,43 +3784,36 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.drag.start_position_2D = pos;
}
}
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
{
if (m_layers_editing.state != LayersEditing::Unknown)
{
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) {
if (m_layers_editing.state != LayersEditing::Unknown) {
m_layers_editing.state = LayersEditing::Unknown;
_stop_timer();
m_layers_editing.accept_changes(*this);
}
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
{
else if (m_mouse.drag.move_volume_idx != -1 && m_mouse.dragging) {
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.
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
}
else if (evt.LeftUp() && m_picking_enabled && m_rectangle_selection.is_dragging())
{
else if (evt.LeftUp() && m_picking_enabled && m_rectangle_selection.is_dragging()) {
if (evt.ShiftDown() || evt.AltDown())
_update_selection_from_hover();
m_rectangle_selection.stop_dragging();
}
else if (evt.LeftUp() && !m_mouse.ignore_left_up && !m_mouse.dragging && m_hover_volume_idxs.empty() && !is_layers_editing_enabled())
{
else if (evt.LeftUp() && !m_mouse.ignore_left_up && !m_mouse.dragging && m_hover_volume_idxs.empty() && !is_layers_editing_enabled()) {
// deselect and propagate event through callback
if (!evt.ShiftDown() && m_picking_enabled)
deselect_all();
}
else if (evt.RightUp())
{
else if (evt.RightUp()) {
m_mouse.position = pos.cast<double>();
// forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
// the context menu is already shown
render();
if (!m_hover_volume_idxs.empty())
{
if (!m_hover_volume_idxs.empty()) {
// if right clicking on volume, propagate event through callback (shows context menu)
int volume_idx = get_first_hover_volume_idx();
if (!m_volumes.volumes[volume_idx]->is_wipe_tower // no context menu for the wipe tower
@ -3866,8 +3845,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
mouse_up_cleanup();
}
else if (evt.Moving())
{
else if (evt.Moving()) {
m_mouse.position = pos.cast<double>();
// updates gizmos overlay