Merge remote-tracking branch 'origin/et_new_camera_movements'

This commit is contained in:
enricoturri1966 2022-03-15 09:27:35 +01:00
commit 63237ae487
6 changed files with 151 additions and 53 deletions

View File

@ -80,6 +80,10 @@
#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1) #define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1)
// Enable recalculating toolpaths when switching to/from volumetric rate visualization // Enable recalculating toolpaths when switching to/from volumetric rate visualization
#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1) #define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified camera control using mouse
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified rectangle selection
#define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_ #endif // _prusaslicer_technologies_h_

View File

@ -1696,13 +1696,17 @@ void GLCanvas3D::render()
wxGetApp().imgui()->new_frame(); wxGetApp().imgui()->new_frame();
if (m_picking_enabled) { if (m_picking_enabled) {
if (m_rectangle_selection.is_dragging()) #if ENABLE_NEW_RECTANGLE_SELECTION
// picking pass using rectangle selection if (m_rectangle_selection.is_dragging() && !m_rectangle_selection.is_empty())
_rectangular_selection_picking_pass(); #else
else if (!m_volumes.empty()) if (m_rectangle_selection.is_dragging())
// regular picking pass #endif // ENABLE_NEW_RECTANGLE_SELECTION
_picking_pass(); // picking pass using rectangle selection
} _rectangular_selection_picking_pass();
else if (!m_volumes.empty())
// regular picking pass
_picking_pass();
}
#if ENABLE_RENDER_PICKING_PASS #if ENABLE_RENDER_PICKING_PASS
if (!m_picking_enabled || !m_show_picking_texture) { if (!m_picking_enabled || !m_show_picking_texture) {
@ -2924,8 +2928,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
if (imgui->update_key_data(evt)) { if (imgui->update_key_data(evt)) {
render(); render();
} }
else else {
{
if (!m_gizmos.on_key(evt)) { if (!m_gizmos.on_key(evt)) {
if (evt.GetEventType() == wxEVT_KEY_UP) { if (evt.GetEventType() == wxEVT_KEY_UP) {
if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) { if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) {
@ -2948,8 +2951,13 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
_update_selection_from_hover(); _update_selection_from_hover();
m_rectangle_selection.stop_dragging(); m_rectangle_selection.stop_dragging();
m_mouse.ignore_left_up = true; m_mouse.ignore_left_up = true;
#if !ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true; m_dirty = true;
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
} }
#if ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
// set_cursor(Standard); // set_cursor(Standard);
} }
else if (keyCode == WXK_ALT) { else if (keyCode == WXK_ALT) {
@ -2961,8 +2969,17 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
} }
// set_cursor(Standard); // set_cursor(Standard);
} }
else if (keyCode == WXK_CONTROL) else if (keyCode == WXK_CONTROL) {
#if ENABLE_NEW_CAMERA_MOVEMENTS
if (m_mouse.dragging) {
// if the user releases CTRL while rotating the 3D scene
// prevent from moving the selected volume
m_mouse.drag.move_volume_idx = -1;
m_mouse.set_start_position_3D_as_invalid();
}
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
m_dirty = true; m_dirty = true;
}
else if (m_gizmos.is_enabled() && !m_selection.is_empty()) { else if (m_gizmos.is_enabled() && !m_selection.is_empty()) {
translationProcessor.process(evt); translationProcessor.process(evt);
@ -2993,15 +3010,16 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
if (keyCode == WXK_SHIFT) { if (keyCode == WXK_SHIFT) {
translationProcessor.process(evt); translationProcessor.process(evt);
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) {
{
m_mouse.ignore_left_up = false; m_mouse.ignore_left_up = false;
// set_cursor(Cross); // set_cursor(Cross);
} }
#if ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
} }
else if (keyCode == WXK_ALT) { else if (keyCode == WXK_ALT) {
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) {
{
m_mouse.ignore_left_up = false; m_mouse.ignore_left_up = false;
// set_cursor(Cross); // set_cursor(Cross);
} }
@ -3420,6 +3438,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_layers_editing.state = LayersEditing::Editing; m_layers_editing.state = LayersEditing::Editing;
_perform_layer_editing_action(&evt); _perform_layer_editing_action(&evt);
} }
#if !ENABLE_NEW_RECTANGLE_SELECTION
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 if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
&& m_gizmos.get_current_type() != GLGizmosManager::FdmSupports && m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
@ -3429,23 +3448,52 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
} }
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
else { else {
#if ENABLE_NEW_RECTANGLE_SELECTION
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::MmuSegmentation) {
m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
m_dirty = true;
}
}
#endif // ENABLE_NEW_RECTANGLE_SELECTION
// Select volume in this 3D canvas. // 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 // 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. // during the scene manipulation.
#if ENABLE_NEW_RECTANGLE_SELECTION
if (m_picking_enabled && (!any_gizmo_active || !evt.ShiftDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) &&
!m_rectangle_selection.is_dragging()) {
#else
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) { if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (evt.LeftDown() && !m_hover_volume_idxs.empty()) { if (evt.LeftDown() && !m_hover_volume_idxs.empty()) {
int volume_idx = get_first_hover_volume_idx(); int volume_idx = get_first_hover_volume_idx();
bool already_selected = m_selection.contains_volume(volume_idx); bool already_selected = m_selection.contains_volume(volume_idx);
#if ENABLE_NEW_RECTANGLE_SELECTION
bool shift_down = evt.ShiftDown();
#else
bool ctrl_down = evt.CmdDown(); bool ctrl_down = evt.CmdDown();
#endif // ENABLE_NEW_RECTANGLE_SELECTION
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs(); Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
#if ENABLE_NEW_RECTANGLE_SELECTION
if (already_selected && shift_down)
m_selection.remove(volume_idx);
else {
m_selection.add(volume_idx, !shift_down, true);
#else
if (already_selected && ctrl_down) if (already_selected && ctrl_down)
m_selection.remove(volume_idx); m_selection.remove(volume_idx);
else { else {
m_selection.add(volume_idx, !ctrl_down, true); m_selection.add(volume_idx, !ctrl_down, true);
#endif // ENABLE_NEW_RECTANGLE_SELECTION
m_mouse.drag.move_requires_threshold = !already_selected; m_mouse.drag.move_requires_threshold = !already_selected;
if (already_selected) if (already_selected)
m_mouse.set_move_start_threshold_position_2D_as_invalid(); m_mouse.set_move_start_threshold_position_2D_as_invalid();
@ -3467,18 +3515,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
#if ENABLE_NEW_RECTANGLE_SELECTION
if (!m_hover_volume_idxs.empty() && !m_rectangle_selection.is_dragging()) {
#else
if (!m_hover_volume_idxs.empty()) { if (!m_hover_volume_idxs.empty()) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) { 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. // Only accept the initial position, if it is inside the volume bounding box.
int volume_idx = get_first_hover_volume_idx(); const int volume_idx = get_first_hover_volume_idx();
BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box();
volume_bbox.offset(1.0); volume_bbox.offset(1.0);
if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position)) { if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position)) {
m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None; m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None;
// The dragging operation is initiated. // The dragging operation is initiated.
m_mouse.drag.move_volume_idx = volume_idx; m_mouse.drag.move_volume_idx = volume_idx;
#if ENABLE_NEW_CAMERA_MOVEMENTS
m_selection.setup_cache(); m_selection.setup_cache();
m_mouse.drag.start_position_3D = m_mouse.scene_position; if (!evt.CmdDown())
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
m_mouse.drag.start_position_3D = m_mouse.scene_position;
m_sequential_print_clearance_first_displacement = true; m_sequential_print_clearance_first_displacement = true;
m_moving = true; m_moving = true;
} }
@ -3486,31 +3541,36 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
} }
#if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.Dragging() && evt.LeftIsDown() && !evt.CmdDown() && m_layers_editing.state == LayersEditing::Unknown &&
m_mouse.drag.move_volume_idx != -1 && m_mouse.is_start_position_3D_defined()) {
#else
else if (evt.Dragging() && evt.LeftIsDown() && m_layers_editing.state == LayersEditing::Unknown && m_mouse.drag.move_volume_idx != -1) { 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) { #endif // ENABLE_NEW_CAMERA_MOVEMENTS
if (!m_mouse.drag.move_requires_threshold) {
m_mouse.dragging = true; m_mouse.dragging = true;
Vec3d cur_pos = m_mouse.drag.start_position_3D; 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 // 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(); const Camera& camera = wxGetApp().plater()->get_camera();
if (std::abs(camera.get_dir_forward()(2)) < EPSILON) { if (std::abs(camera.get_dir_forward().z()) < EPSILON) {
// side view -> move selected volumes orthogonally to camera view direction // side view -> move selected volumes orthogonally to camera view direction
Linef3 ray = mouse_ray(pos); const Linef3 ray = mouse_ray(pos);
Vec3d dir = ray.unit_vector(); const Vec3d dir = ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view) // in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = ray.a + (m_mouse.drag.start_position_3D - ray.a).dot(dir) / dir.squaredNorm() * dir; const Vec3d inters = ray.a + (m_mouse.drag.start_position_3D - ray.a).dot(dir) / dir.squaredNorm() * dir;
// vector from the starting position to the found intersection // vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_mouse.drag.start_position_3D; const Vec3d inters_vec = inters - m_mouse.drag.start_position_3D;
Vec3d camera_right = camera.get_dir_right(); const Vec3d camera_right = camera.get_dir_right();
Vec3d camera_up = camera.get_dir_up(); const Vec3d camera_up = camera.get_dir_up();
// finds projection of the vector along the camera axes // finds projection of the vector along the camera axes
double projection_x = inters_vec.dot(camera_right); const double projection_x = inters_vec.dot(camera_right);
double projection_z = inters_vec.dot(camera_up); const double projection_z = inters_vec.dot(camera_up);
// apply offset // apply offset
cur_pos = m_mouse.drag.start_position_3D + projection_x * camera_right + projection_z * camera_up; cur_pos = m_mouse.drag.start_position_3D + projection_x * camera_right + projection_z * camera_up;
@ -3520,7 +3580,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// Get new position at the same Z of the initial click point. // Get new position at the same Z of the initial click point.
float z0 = 0.0f; float z0 = 0.0f;
float z1 = 1.0f; float z1 = 1.0f;
cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D.z());
} }
} }
@ -3532,7 +3592,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
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()) {
#if ENABLE_NEW_RECTANGLE_SELECTION
// keeps the mouse position updated while dragging the selection rectangle
m_mouse.position = pos.cast<double>();
m_rectangle_selection.dragging(m_mouse.position);
#else
m_rectangle_selection.dragging(pos.cast<double>()); m_rectangle_selection.dragging(pos.cast<double>());
#endif // ENABLE_NEW_RECTANGLE_SELECTION
m_dirty = true; m_dirty = true;
} }
else if (evt.Dragging()) { else if (evt.Dragging()) {
@ -3545,13 +3611,19 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
// do not process the dragging if the left mouse was set down in another canvas // do not process the dragging if the left mouse was set down in another canvas
else if (evt.LeftIsDown()) { #if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.LeftIsDown() || evt.MiddleIsDown()) {
// if dragging over blank area with left button, rotate // if dragging over blank area with left button, rotate
if ((any_gizmo_active || evt.CmdDown() || evt.MiddleIsDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
#else
// if dragging over blank area with left button, rotate
else if (evt.LeftIsDown()) {
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) { if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.); #endif // ENABLE_NEW_CAMERA_MOVEMENTS
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.0) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.0);
if (wxGetApp().app_config->get("use_free_camera") == "1") if (wxGetApp().app_config->get("use_free_camera") == "1")
// Virtual track ball (similar to the 3DConnexion mouse). // Virtual track ball (similar to the 3DConnexion mouse).
wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.)); wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.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. // 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(), // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
@ -3564,15 +3636,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0); m_mouse.drag.start_position_3D = Vec3d((double)pos.x(), (double)pos.y(), 0.0);
} }
#if ENABLE_NEW_CAMERA_MOVEMENTS
else if (evt.RightIsDown()) {
// If dragging with right button, pan.
#else
else if (evt.MiddleIsDown() || evt.RightIsDown()) { else if (evt.MiddleIsDown() || evt.RightIsDown()) {
// If dragging over blank area with right button, pan. // If dragging over blank area with right button, pan.
#endif // ENABLE_NEW_CAMERA_MOVEMENTS
if (m_mouse.is_start_position_2D_defined()) { if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0 // get point in model space at Z = 0
float z = 0.0f; float z = 0.0f;
const Vec3d& cur_pos = _mouse_to_3d(pos, &z); const Vec3d& cur_pos = _mouse_to_3d(pos, &z);
Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); const Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
Camera& camera = wxGetApp().plater()->get_camera(); Camera& camera = wxGetApp().plater()->get_camera();
if (wxGetApp().app_config->get("use_free_camera") != "1") if (wxGetApp().app_config->get("use_free_camera") != "1")
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation. // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
@ -3645,7 +3722,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (!m_mouse.dragging) { if (!m_mouse.dragging) {
// do not post the event if the user is panning the scene // do not post the event if the user is panning the scene
// or if right click was done over the wipe tower // or if right click was done over the wipe tower
bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower; const bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower;
if (post_right_click_event) if (post_right_click_event)
post_event(RBtnEvent(EVT_GLCANVAS_RIGHT_CLICK, { logical_pos, m_hover_volume_idxs.empty() })); post_event(RBtnEvent(EVT_GLCANVAS_RIGHT_CLICK, { logical_pos, m_hover_volume_idxs.empty() }));
} }
@ -6338,7 +6415,9 @@ void GLCanvas3D::_update_volumes_hover_state()
return; return;
} }
#if !ENABLE_NEW_RECTANGLE_SELECTION
bool selection_modifiers_only = m_selection.is_empty() || m_selection.is_any_modifier(); bool selection_modifiers_only = m_selection.is_empty() || m_selection.is_any_modifier();
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
bool hover_modifiers_only = true; bool hover_modifiers_only = true;
for (int i : m_hover_volume_idxs) { for (int i : m_hover_volume_idxs) {
@ -6367,9 +6446,14 @@ void GLCanvas3D::_update_volumes_hover_state()
if (volume.hover != GLVolume::HS_None) if (volume.hover != GLVolume::HS_None)
continue; continue;
#if ENABLE_NEW_RECTANGLE_SELECTION
bool deselect = volume.selected && ((shift_pressed && m_rectangle_selection.is_empty()) || (alt_pressed && !m_rectangle_selection.is_empty()));
bool select = !volume.selected && (m_rectangle_selection.is_empty() || (shift_pressed && !m_rectangle_selection.is_empty()));
#else
bool deselect = volume.selected && ((ctrl_pressed && !shift_pressed) || alt_pressed); bool deselect = volume.selected && ((ctrl_pressed && !shift_pressed) || alt_pressed);
// (volume->is_modifier && !selection_modifiers_only && !is_ctrl_pressed) -> allows hovering on selected modifiers belonging to selection of type Instance // (volume->is_modifier && !selection_modifiers_only && !is_ctrl_pressed) -> allows hovering on selected modifiers belonging to selection of type Instance
bool select = (!volume.selected || (volume.is_modifier && !selection_modifiers_only && !ctrl_pressed)) && !alt_pressed; bool select = (!volume.selected || (volume.is_modifier && !selection_modifiers_only && !ctrl_pressed)) && !alt_pressed;
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (select || deselect) { if (select || deselect) {
bool as_volume = bool as_volume =
@ -7287,7 +7371,7 @@ void GLCanvas3D::_update_selection_from_hover()
bool ctrl_pressed = wxGetKeyState(WXK_CONTROL); bool ctrl_pressed = wxGetKeyState(WXK_CONTROL);
if (m_hover_volume_idxs.empty()) { if (m_hover_volume_idxs.empty()) {
if (!ctrl_pressed && (m_rectangle_selection.get_state() == GLSelectionRectangle::Select)) if (!ctrl_pressed && m_rectangle_selection.get_state() == GLSelectionRectangle::EState::Select)
m_selection.remove_all(); m_selection.remove_all();
return; return;
@ -7304,7 +7388,10 @@ void GLCanvas3D::_update_selection_from_hover()
} }
bool selection_changed = false; bool selection_changed = false;
if (state == GLSelectionRectangle::Select) { #if ENABLE_NEW_RECTANGLE_SELECTION
if (!m_rectangle_selection.is_empty()) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (state == GLSelectionRectangle::EState::Select) {
bool contains_all = true; bool contains_all = true;
for (int i : m_hover_volume_idxs) { for (int i : m_hover_volume_idxs) {
if (!m_selection.contains_volume((unsigned int)i)) { if (!m_selection.contains_volume((unsigned int)i)) {
@ -7315,7 +7402,7 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Add) // the selection is going to be modified (Add)
if (!contains_all) { if (!contains_all) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Add from rectangle")), UndoRedo::SnapshotType::Selection); wxGetApp().plater()->take_snapshot(_L("Selection-Add from rectangle"), UndoRedo::SnapshotType::Selection);
selection_changed = true; selection_changed = true;
} }
} }
@ -7330,21 +7417,24 @@ void GLCanvas3D::_update_selection_from_hover()
// the selection is going to be modified (Remove) // the selection is going to be modified (Remove)
if (contains_any) { if (contains_any) {
wxGetApp().plater()->take_snapshot(_(L("Selection-Remove from rectangle")), UndoRedo::SnapshotType::Selection); wxGetApp().plater()->take_snapshot(_L("Selection-Remove from rectangle"), UndoRedo::SnapshotType::Selection);
selection_changed = true; selection_changed = true;
} }
} }
#if ENABLE_NEW_RECTANGLE_SELECTION
}
#endif // ENABLE_NEW_RECTANGLE_SELECTION
if (!selection_changed) if (!selection_changed)
return; return;
Plater::SuppressSnapshots suppress(wxGetApp().plater()); Plater::SuppressSnapshots suppress(wxGetApp().plater());
if ((state == GLSelectionRectangle::Select) && !ctrl_pressed) if (state == GLSelectionRectangle::EState::Select && !ctrl_pressed)
m_selection.clear(); m_selection.clear();
for (int i : m_hover_volume_idxs) { for (int i : m_hover_volume_idxs) {
if (state == GLSelectionRectangle::Select) { if (state == GLSelectionRectangle::EState::Select) {
if (hover_modifiers_only) { if (hover_modifiers_only) {
const GLVolume& v = *m_volumes.volumes[i]; const GLVolume& v = *m_volumes.volumes[i];
m_selection.add_volume(v.object_idx(), v.volume_idx(), v.instance_idx(), false); m_selection.add_volume(v.object_idx(), v.volume_idx(), v.instance_idx(), false);

View File

@ -13,12 +13,12 @@ namespace GUI {
void GLSelectionRectangle::start_dragging(const Vec2d& mouse_position, EState state) void GLSelectionRectangle::start_dragging(const Vec2d& mouse_position, EState state)
{ {
if (is_dragging() || (state == Off)) if (is_dragging() || state == EState::Off)
return; return;
m_state = state; m_state = state;
m_start_corner = mouse_position; m_start_corner = mouse_position;
m_end_corner = mouse_position; m_end_corner = mouse_position;
} }
void GLSelectionRectangle::dragging(const Vec2d& mouse_position) void GLSelectionRectangle::dragging(const Vec2d& mouse_position)
@ -36,7 +36,7 @@ namespace GUI {
if (!is_dragging()) if (!is_dragging())
return out; return out;
m_state = Off; m_state = EState::Off;
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
Matrix4d modelview = camera.get_view_matrix().matrix(); Matrix4d modelview = camera.get_view_matrix().matrix();
@ -66,7 +66,7 @@ namespace GUI {
void GLSelectionRectangle::stop_dragging() void GLSelectionRectangle::stop_dragging()
{ {
if (is_dragging()) if (is_dragging())
m_state = Off; m_state = EState::Off;
} }
void GLSelectionRectangle::render(const GLCanvas3D& canvas) void GLSelectionRectangle::render(const GLCanvas3D& canvas)
@ -108,8 +108,8 @@ namespace GUI {
glsafe(::glLineWidth(1.5f)); glsafe(::glLineWidth(1.5f));
#if !ENABLE_LEGACY_OPENGL_REMOVAL #if !ENABLE_LEGACY_OPENGL_REMOVAL
float color[3]; float color[3];
color[0] = (m_state == Select) ? 0.3f : 1.0f; color[0] = (m_state == EState::Select) ? 0.3f : 1.0f;
color[1] = (m_state == Select) ? 1.0f : 0.3f; color[1] = (m_state == EState::Select) ? 1.0f : 0.3f;
color[2] = 0.3f; color[2] = 0.3f;
glsafe(::glColor3fv(color)); glsafe(::glColor3fv(color));
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #endif // !ENABLE_LEGACY_OPENGL_REMOVAL
@ -169,7 +169,7 @@ namespace GUI {
shader->set_uniform("projection_matrix", Transform3d::Identity()); shader->set_uniform("projection_matrix", Transform3d::Identity());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
m_rectangle.set_color(ColorRGBA((m_state == Select) ? 0.3f : 1.0f, (m_state == Select) ? 1.0f : 0.3f, 0.3f, 1.0f)); m_rectangle.set_color(ColorRGBA((m_state == EState::Select) ? 0.3f : 1.0f, (m_state == EState::Select) ? 1.0f : 0.3f, 0.3f, 1.0f));
m_rectangle.render(); m_rectangle.render();
shader->stop_using(); shader->stop_using();
} }

View File

@ -14,7 +14,7 @@ class GLCanvas3D;
class GLSelectionRectangle { class GLSelectionRectangle {
public: public:
enum EState { enum class EState {
Off, Off,
Select, Select,
Deselect Deselect
@ -35,7 +35,11 @@ public:
void render(const GLCanvas3D& canvas); void render(const GLCanvas3D& canvas);
bool is_dragging() const { return m_state != Off; } bool is_dragging() const { return m_state != EState::Off; }
#if ENABLE_NEW_RECTANGLE_SELECTION
bool is_empty() const { return m_state == EState::Off || m_start_corner.isApprox(m_end_corner); }
#endif // ENABLE_NEW_RECTANGLE_SELECTION
EState get_state() const { return m_state; } EState get_state() const { return m_state; }
float get_width() const { return std::abs(m_start_corner.x() - m_end_corner.x()); } float get_width() const { return std::abs(m_start_corner.x() - m_end_corner.x()); }
@ -46,7 +50,7 @@ public:
float get_bottom() const { return std::min(m_start_corner.y(), m_end_corner.y()); } float get_bottom() const { return std::min(m_start_corner.y(), m_end_corner.y()); }
private: private:
EState m_state{ Off }; EState m_state{ EState::Off };
Vec2d m_start_corner{ Vec2d::Zero() }; Vec2d m_start_corner{ Vec2d::Zero() };
Vec2d m_end_corner{ Vec2d::Zero() }; Vec2d m_end_corner{ Vec2d::Zero() };
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL

View File

@ -293,7 +293,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) { if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
if (m_hover_id == -1) { if (m_hover_id == -1) {
if (shift_down || alt_down) { if (shift_down || alt_down) {
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect); m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
} }
} }
else { else {
@ -359,7 +359,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
trafo, wxGetApp().plater()->get_camera(), points_inside, trafo, wxGetApp().plater()->get_camera(), points_inside,
m_c->object_clipper()->get_clipping_plane())) m_c->object_clipper()->get_clipping_plane()))
{ {
if (rectangle_status == GLSelectionRectangle::Deselect) if (rectangle_status == GLSelectionRectangle::EState::Deselect)
unselect_point(points_idxs[idx]); unselect_point(points_idxs[idx]);
else else
select_point(points_idxs[idx]); select_point(points_idxs[idx]);

View File

@ -419,7 +419,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) { if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
if (m_hover_id == -1) { if (m_hover_id == -1) {
if (shift_down || alt_down) { if (shift_down || alt_down) {
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect); m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
} }
} }
else { else {
@ -490,7 +490,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
{ {
if (idx >= orig_pts_num) // this is a cone-base, get index of point it belongs to if (idx >= orig_pts_num) // this is a cone-base, get index of point it belongs to
idx -= orig_pts_num; idx -= orig_pts_num;
if (rectangle_status == GLSelectionRectangle::Deselect) if (rectangle_status == GLSelectionRectangle::EState::Deselect)
unselect_point(points_idxs[idx]); unselect_point(points_idxs[idx]);
else else
select_point(points_idxs[idx]); select_point(points_idxs[idx]);