diff --git a/common/lc_glwidget.h b/common/lc_glwidget.h index 6f8f6205..5c11d29c 100644 --- a/common/lc_glwidget.h +++ b/common/lc_glwidget.h @@ -10,7 +10,8 @@ enum LC_CURSOR_TYPE LC_CURSOR_SPOTLIGHT, LC_CURSOR_CAMERA, LC_CURSOR_SELECT, - LC_CURSOR_SELECT_GROUP, + LC_CURSOR_SELECT_ADD, + LC_CURSOR_SELECT_REMOVE, LC_CURSOR_MOVE, LC_CURSOR_ROTATE, LC_CURSOR_ROTATEX, diff --git a/common/lc_model.cpp b/common/lc_model.cpp index ae0627c6..9f3237ec 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3326,7 +3326,7 @@ void lcModel::FocusOrDeselectObject(const lcObjectSection& ObjectSection) Object->SetFocused(Section, true); } else - Object->SetSelected(Section, false); + Object->SetFocused(Section, false); bool IsSelected = Object->IsSelected(); @@ -3386,7 +3386,7 @@ void lcModel::AddToSelection(const lcArray& Objects) lcObject* Object = Objects[ObjectIdx]; bool WasSelected = Object->IsSelected(); - Object->SetSelected(Objects[ObjectIdx]); + Object->SetSelected(true); if (!WasSelected && Object->GetType() == LC_OBJECT_PIECE) SelectGroup(((lcPiece*)Object)->GetTopGroup(), true); @@ -3396,6 +3396,39 @@ void lcModel::AddToSelection(const lcArray& Objects) gMainWindow->UpdateAllViews(); } +void lcModel::RemoveFromSelection(const lcArray& Objects) +{ + for (int ObjectIdx = 0; ObjectIdx < Objects.GetSize(); ObjectIdx++) + { + lcObject* Object = Objects[ObjectIdx]; + + bool WasSelected = Object->IsSelected(); + Object->SetSelected(false); + + if (WasSelected && Object->GetType() == LC_OBJECT_PIECE) + SelectGroup(((lcPiece*)Object)->GetTopGroup(), false); + } + + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateAllViews(); +} + +void lcModel::RemoveFromSelection(const lcObjectSection& ObjectSection) +{ + lcObject* Object = ObjectSection.Object; + + if (!Object) + return; + + if (Object->IsFocused(ObjectSection.Section)) + Object->SetSelected(ObjectSection.Section, false); + else + Object->SetSelected(false); + + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateAllViews(); +} + void lcModel::SelectAllPieces() { for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) diff --git a/common/lc_model.h b/common/lc_model.h index 6b32d429..19048fd1 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -253,6 +253,8 @@ public: void ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection); void SetSelectionAndFocus(const lcArray& Selection, lcObject* Focus, lcuint32 Section); void AddToSelection(const lcArray& Objects); + void RemoveFromSelection(const lcArray& Objects); + void RemoveFromSelection(const lcObjectSection& ObjectSection); void SelectAllPieces(); void InvertSelection(); diff --git a/common/view.cpp b/common/view.cpp index 7dbcf0bf..deb841ca 100644 --- a/common/view.cpp +++ b/common/view.cpp @@ -349,8 +349,14 @@ lcMatrix44 View::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int LC_CURSOR_TYPE View::GetCursor() const { - if (mTrackTool == LC_TRACKTOOL_SELECT && (mInputState.Modifiers & Qt::ControlModifier)) - return LC_CURSOR_SELECT_GROUP; + if (mTrackTool == LC_TRACKTOOL_SELECT) + { + if (mInputState.Modifiers & Qt::ControlModifier) + return LC_CURSOR_SELECT_ADD; + + if (mInputState.Modifiers & Qt::ShiftModifier) + return LC_CURSOR_SELECT_REMOVE; + } const LC_CURSOR_TYPE CursorFromTrackTool[] = { @@ -1997,7 +2003,7 @@ void View::UpdateTrackTool() } } - if (CurrentTool == LC_TOOL_SELECT && NewTrackTool == LC_TRACKTOOL_SELECT) + if (CurrentTool == LC_TOOL_SELECT && NewTrackTool == LC_TRACKTOOL_SELECT && mInputState.Modifiers == Qt::NoModifier) { lcObjectSection ObjectSection = FindObjectUnderPointer(false, false); lcObject* Object = ObjectSection.Object; @@ -2405,6 +2411,8 @@ void View::StopTracking(bool Accept) if (mInputState.Modifiers & Qt::ControlModifier) mModel->AddToSelection(Objects); + else if (mInputState.Modifiers & Qt::ShiftModifier) + mModel->RemoveFromSelection(Objects); else mModel->SetSelectionAndFocus(Objects, nullptr, 0); } @@ -2519,6 +2527,8 @@ void View::OnButtonDown(lcTrackButton TrackButton) if (mInputState.Modifiers & Qt::ControlModifier) mModel->FocusOrDeselectObject(ObjectSection); + else if (mInputState.Modifiers & Qt::ShiftModifier) + mModel->RemoveFromSelection(ObjectSection); else mModel->ClearSelectionAndSetFocus(ObjectSection); @@ -2606,6 +2616,8 @@ void View::OnLeftButtonDoubleClick() if (mInputState.Modifiers & Qt::ControlModifier) mModel->FocusOrDeselectObject(ObjectSection); + else if (mInputState.Modifiers & Qt::ShiftModifier) + mModel->RemoveFromSelection(ObjectSection); else mModel->ClearSelectionAndSetFocus(ObjectSection); } diff --git a/leocad.qrc b/leocad.qrc index fa8ff916..51699b42 100644 --- a/leocad.qrc +++ b/leocad.qrc @@ -50,7 +50,8 @@ resources/cursor_rotatey.png resources/cursor_rotate_view.png resources/cursor_select.png - resources/cursor_select_multiple.png + resources/cursor_select_add.png + resources/cursor_select_remove.png resources/cursor_spotlight.png resources/cursor_zoom.png resources/cursor_zoom_region.png diff --git a/qt/lc_qglwidget.cpp b/qt/lc_qglwidget.cpp index 1466b44d..24860dd4 100644 --- a/qt/lc_qglwidget.cpp +++ b/qt/lc_qglwidget.cpp @@ -43,26 +43,29 @@ void lcGLWidget::SetCursor(LC_CURSOR_TYPE CursorType) const lcCursorInfo Cursors[LC_CURSOR_COUNT] = { - { 0, 0, "" }, // LC_CURSOR_DEFAULT - { 8, 3, ":/resources/cursor_insert" }, // LC_CURSOR_BRICK - { 15, 15, ":/resources/cursor_light" }, // LC_CURSOR_LIGHT - { 7, 10, ":/resources/cursor_spotlight" }, // LC_CURSOR_SPOTLIGHT - { 15, 9, ":/resources/cursor_camera" }, // LC_CURSOR_CAMERA - { 0, 2, ":/resources/cursor_select" }, // LC_CURSOR_SELECT - { 0, 2, ":/resources/cursor_select_multiple" }, // LC_CURSOR_SELECT_GROUP - { 15, 15, ":/resources/cursor_move" }, // LC_CURSOR_MOVE - { 15, 15, ":/resources/cursor_rotate" }, // LC_CURSOR_ROTATE - { 15, 15, ":/resources/cursor_rotatex" }, // LC_CURSOR_ROTATEX - { 15, 15, ":/resources/cursor_rotatey" }, // LC_CURSOR_ROTATEY - { 0, 10, ":/resources/cursor_delete" }, // LC_CURSOR_DELETE - { 14, 14, ":/resources/cursor_paint" }, // LC_CURSOR_PAINT - { 15, 15, ":/resources/cursor_zoom" }, // LC_CURSOR_ZOOM - { 9, 9, ":/resources/cursor_zoom_region" }, // LC_CURSOR_ZOOM_REGION - { 15, 15, ":/resources/cursor_pan" }, // LC_CURSOR_PAN - { 15, 15, ":/resources/cursor_roll" }, // LC_CURSOR_ROLL - { 15, 15, ":/resources/cursor_rotate_view" }, // LC_CURSOR_ROTATE_VIEW + { 0, 0, "" }, // LC_CURSOR_DEFAULT + { 8, 3, ":/resources/cursor_insert" }, // LC_CURSOR_BRICK + { 15, 15, ":/resources/cursor_light" }, // LC_CURSOR_LIGHT + { 7, 10, ":/resources/cursor_spotlight" }, // LC_CURSOR_SPOTLIGHT + { 15, 9, ":/resources/cursor_camera" }, // LC_CURSOR_CAMERA + { 0, 2, ":/resources/cursor_select" }, // LC_CURSOR_SELECT + { 0, 2, ":/resources/cursor_select_add" }, // LC_CURSOR_SELECT_ADD + { 0, 2, ":/resources/cursor_select_remove" }, // LC_CURSOR_SELECT_REMOVE + { 15, 15, ":/resources/cursor_move" }, // LC_CURSOR_MOVE + { 15, 15, ":/resources/cursor_rotate" }, // LC_CURSOR_ROTATE + { 15, 15, ":/resources/cursor_rotatex" }, // LC_CURSOR_ROTATEX + { 15, 15, ":/resources/cursor_rotatey" }, // LC_CURSOR_ROTATEY + { 0, 10, ":/resources/cursor_delete" }, // LC_CURSOR_DELETE + { 14, 14, ":/resources/cursor_paint" }, // LC_CURSOR_PAINT + { 15, 15, ":/resources/cursor_zoom" }, // LC_CURSOR_ZOOM + { 9, 9, ":/resources/cursor_zoom_region" }, // LC_CURSOR_ZOOM_REGION + { 15, 15, ":/resources/cursor_pan" }, // LC_CURSOR_PAN + { 15, 15, ":/resources/cursor_roll" }, // LC_CURSOR_ROLL + { 15, 15, ":/resources/cursor_rotate_view" }, // LC_CURSOR_ROTATE_VIEW }; + static_assert(sizeof(Cursors) / sizeof(Cursors[0]) == LC_CURSOR_COUNT, "Array size mismatch"); + QGLWidget* widget = (QGLWidget*)mWidget; if (CursorType != LC_CURSOR_DEFAULT && CursorType < LC_CURSOR_COUNT) @@ -171,7 +174,7 @@ void lcQGLWidget::paintGL() void lcQGLWidget::keyPressEvent(QKeyEvent *event) { - if (isView && event->key() == Qt::Key_Control) + if (isView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift)) { widget->mInputState.Modifiers = event->modifiers(); widget->OnUpdateCursor(); @@ -182,7 +185,7 @@ void lcQGLWidget::keyPressEvent(QKeyEvent *event) void lcQGLWidget::keyReleaseEvent(QKeyEvent *event) { - if (isView && event->key() == Qt::Key_Control) + if (isView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift)) { widget->mInputState.Modifiers = event->modifiers(); widget->OnUpdateCursor(); diff --git a/resources/cursor_select_multiple.png b/resources/cursor_select_add.png similarity index 100% rename from resources/cursor_select_multiple.png rename to resources/cursor_select_add.png diff --git a/resources/cursor_select_remove.png b/resources/cursor_select_remove.png new file mode 100644 index 00000000..ce0abcda Binary files /dev/null and b/resources/cursor_select_remove.png differ