diff --git a/common/lc_traintrack.cpp b/common/lc_traintrack.cpp index 631f4e7e..d5b63a24 100644 --- a/common/lc_traintrack.cpp +++ b/common/lc_traintrack.cpp @@ -7,10 +7,10 @@ #include "lc_application.h" // todo: -// when moving existing pieces, lcView::OnMouseMove calls UpdateMoveTool which only takes a position and can't rotate curves +// when moving existing pieces, lcView::OnMouseMove calls UpdateMoveTool which only takes a position and can't rotate pieces +// detect the closest connection when dragging over pieces // hide some of the 12v tracks to avoid bloat // better insert gizmo mouse detection -// part picker preview should use the json colors // auto replace cross when going over a straight section // set focus connection after adding diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 94190b25..0d48f9d4 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -974,7 +974,7 @@ void lcView::OnDraw() if (DrawOverlays) DrawAxes(); - if (DrawInterface) + if (DrawInterface && mTrackTool != lcTrackTool::Insert) { lcTool Tool = gMainWindow->GetTool(); lcModel* ActiveModel = GetActiveModel(); @@ -1931,6 +1931,7 @@ lcCursor lcView::GetCursor() const lcCursor::Select, // lcTrackTool::RotateTrainTrackRight lcCursor::Select, // lcTrackTool::RotateTrainTrackLeft lcCursor::Select, // lcTrackTool::InsertTrainTrack + lcCursor::Select, // lcTrackTool::SelectTrainTrack lcCursor::Move, // lcTrackTool::ScalePlus lcCursor::Move, // lcTrackTool::ScaleMinus lcCursor::Delete, // lcTrackTool::Eraser @@ -2043,6 +2044,7 @@ lcTool lcView::GetCurrentTool() const lcTool::Rotate, // lcTrackTool::RotateTrainTrackRight lcTool::Rotate, // lcTrackTool::RotateTrainTrackLeft lcTool::Insert, // lcTrackTool::InsertTrainTrack + lcTool::Select, // lcTrackTool::SelectTrainTrack lcTool::Move, // lcTrackTool::ScalePlus lcTool::Move, // lcTrackTool::ScaleMinus lcTool::Eraser, // lcTrackTool::Eraser @@ -2113,7 +2115,7 @@ void lcView::UpdateTrackTool() case lcTool::Move: { mMouseDownPiece = nullptr; - std::tie(NewTrackTool, NewTrackSection) = mViewManipulator->UpdateSelectMove(); + std::tie(NewTrackTool, NewTrackSection) = mViewManipulator->UpdateSelectMove(mTrackButton); mTrackToolFromOverlay = NewTrackTool != lcTrackTool::MoveXYZ && NewTrackTool != lcTrackTool::Select; Redraw = NewTrackTool != mTrackTool || NewTrackSection != mTrackToolSection; @@ -2593,6 +2595,31 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) } break; + case lcTrackTool::SelectTrainTrack: + { + lcObject* Focus = ActiveModel->GetFocusObject(); + + if (!Focus || !Focus->IsPiece()) + break; + + lcPiece* Piece = (lcPiece*)Focus; + const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo(); + + if (!TrainTrackInfo) + break; + + if (mTrackToolSection < LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST) + break; + + lcObjectSection ObjectSection; + + ObjectSection.Object = Focus; + ObjectSection.Section = mTrackToolSection; + + ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true); + } + break; + case lcTrackTool::ScalePlus: case lcTrackTool::ScaleMinus: if (ActiveModel->AnyPiecesSelected()) @@ -3044,6 +3071,7 @@ void lcView::OnMouseMove() case lcTrackTool::RotateTrainTrackRight: case lcTrackTool::RotateTrainTrackLeft: case lcTrackTool::InsertTrainTrack: + case lcTrackTool::SelectTrainTrack: case lcTrackTool::Eraser: case lcTrackTool::Paint: case lcTrackTool::ColorPicker: diff --git a/common/lc_view.h b/common/lc_view.h index b4aa46a4..52e157d0 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -75,6 +75,7 @@ enum class lcTrackTool RotateTrainTrackRight, RotateTrainTrackLeft, InsertTrainTrack, + SelectTrainTrack, ScalePlus, ScaleMinus, Eraser, diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index ffea103e..97511921 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -464,7 +464,7 @@ void lcViewManipulator::DrawSelectMove(lcTrackButton TrackButton, lcTrackTool Tr Context->DrawPrimitives(GL_TRIANGLE_STRIP, 2, 18); Context->DrawPrimitives(GL_TRIANGLE_STRIP, 20, 18); } - else if (Piece->mPieceInfo->GetTrainTrackInfo()) + else if (Piece->mPieceInfo->GetTrainTrackInfo() && TrackButton == lcTrackButton::None) { DrawTrainTrack(Piece, Context, TrackTool, TrackToolSection); } @@ -544,7 +544,7 @@ void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, lcTra Context->SetWorldMatrix(WorldMatrix); - if (TrackToolSection == LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex) + if (TrackToolSection == LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex && TrackTool != lcTrackTool::SelectTrainTrack) Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f); else Context->SetColor(TrainTrackColor); @@ -552,6 +552,61 @@ void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, lcTra Context->DrawIndexedPrimitives(GL_TRIANGLES, 72, GL_UNSIGNED_SHORT, (108 + 360 + 12 + 192) * 2); } } + + float Verts[8 * 3]; + float* CurVert = Verts; + + constexpr float TrainTrackBoxSize = 0.15f; + lcVector3 CubeMin(-TrainTrackBoxSize, -TrainTrackBoxSize, -TrainTrackBoxSize); + lcVector3 CubeMax(TrainTrackBoxSize, TrainTrackBoxSize, TrainTrackBoxSize); + + *CurVert++ = CubeMin[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMin[2]; + *CurVert++ = CubeMin[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMin[2]; + *CurVert++ = CubeMax[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMin[2]; + *CurVert++ = CubeMax[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMin[2]; + *CurVert++ = CubeMin[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMax[2]; + *CurVert++ = CubeMin[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMax[2]; + *CurVert++ = CubeMax[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMax[2]; + *CurVert++ = CubeMax[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMax[2]; + + const GLushort Indices[36] = + { + 0, 1, 2, 0, 2, 3, 7, 6, 5, 7, 5, 4, 5, 1, 0, 4, 5, 0, + 7, 3, 2, 6, 7, 2, 0, 3, 7, 0, 7, 4, 6, 2, 1, 5, 6, 1 + }; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + + const lcVector4 ConnectionColor = lcVector4FromColor(Preferences.mControlPointColor); + const lcVector4 ConnectionFocusedColor = lcVector4FromColor(Preferences.mControlPointFocusedColor); + + const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo(); + const std::vector& Connections = TrainTrackInfo->GetConnections(); + + for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) + { + lcMatrix44 WorldMatrix = lcMul(Connections[ConnectionIndex].Transform, Piece->mModelWorld); + lcModel* ActiveModel = mView->GetActiveModel(); + + if (ActiveModel != mView->GetModel()) + WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform()); + + const float OverlayScale = mView->GetOverlayScale(); + WorldMatrix = lcMul(lcMatrix44Scale(lcVector3(OverlayScale, OverlayScale, OverlayScale)), WorldMatrix); + + Context->SetWorldMatrix(WorldMatrix); + + if (Piece->IsFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex)) + Context->SetColor(ConnectionFocusedColor); + else if (TrackToolSection == LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex && TrackTool == lcTrackTool::SelectTrainTrack) + Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f); + else + Context->SetColor(ConnectionColor); + + Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); + } } void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackTool) @@ -911,6 +966,7 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe case lcTrackTool::RotateTrainTrackRight: case lcTrackTool::RotateTrainTrackLeft: case lcTrackTool::InsertTrainTrack: + case lcTrackTool::SelectTrainTrack: return true; case lcTrackTool::ScalePlus: @@ -936,7 +992,7 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe return false; } -std::pair lcViewManipulator::UpdateSelectMove() +std::pair lcViewManipulator::UpdateSelectMove(lcTrackButton TrackButton) { lcModel* ActiveModel = mView->GetActiveModel(); const float OverlayScale = mView->GetOverlayScale(); @@ -1110,7 +1166,7 @@ std::pair lcViewManipulator::UpdateSelectMove() } } - if (CurrentTool == lcTool::Select && Focus && Focus->IsPiece()) + if (CurrentTool == lcTool::Select && Focus && Focus->IsPiece() && TrackButton == lcTrackButton::None) { auto [TrainTrackTool, TrainTrackSection, TrainDistance] = UpdateSelectMoveTrainTrack((lcPiece*)Focus, OverlayCenter, OverlayScale, Start, End, PlaneNormals); @@ -1233,6 +1289,39 @@ std::tuple lcViewManipulator::UpdateSelectMoveTrain } } + const std::vector& Connections = TrainTrackInfo->GetConnections(); + + for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) + { + lcMatrix44 WorldMatrix = lcMul(Connections[ConnectionIndex].Transform, Piece->mModelWorld); + lcModel* ActiveModel = mView->GetActiveModel(); + + if (ActiveModel != mView->GetModel()) + WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform()); + + lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(WorldMatrix); + InverseWorldMatrix = lcMul(InverseWorldMatrix, lcMatrix44Scale(lcVector3(1.0f / OverlayScale, 1.0f / OverlayScale, 1.0f / OverlayScale))); + + lcVector3 LocalStart = lcMul31(Start, InverseWorldMatrix); + lcVector3 LocalEnd = lcMul31(End, InverseWorldMatrix); + + constexpr float TrainTrackBoxSize = 0.15f; + lcVector3 CubeMin(-TrainTrackBoxSize, -TrainTrackBoxSize, -TrainTrackBoxSize); + lcVector3 CubeMax(TrainTrackBoxSize, TrainTrackBoxSize, TrainTrackBoxSize); + + float Distance; + + if (lcBoundingBoxRayIntersectDistance(CubeMin, CubeMax, LocalStart, LocalEnd, &Distance, nullptr, nullptr)) + { + if (Distance < ClosestIntersectionDistance) + { + NewTrackTool = lcTrackTool::SelectTrainTrack; + NewTrackSection = LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex; + ClosestIntersectionDistance = Distance; + } + } + } + return { NewTrackTool, NewTrackSection, ClosestIntersectionDistance }; } diff --git a/common/lc_viewmanipulator.h b/common/lc_viewmanipulator.h index ff432702..570e014c 100644 --- a/common/lc_viewmanipulator.h +++ b/common/lc_viewmanipulator.h @@ -10,7 +10,7 @@ public: void DrawSelectMove(lcTrackButton TrackButton, lcTrackTool TrackTool, quint32 TrackToolSection); void DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackTool); - std::pair UpdateSelectMove(); + std::pair UpdateSelectMove(lcTrackButton TrackButton); lcTrackTool UpdateRotate(); static void CreateResources(lcContext* Context); diff --git a/common/piece.cpp b/common/piece.cpp index 269c1277..df4e8ea6 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -511,31 +511,6 @@ void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const } } } - - if (mPieceInfo->GetTrainTrackInfo() && AreTrainTrackConnectionsVisible()) - { - const lcVector3 Min(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); - const lcVector3 Max(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); - const std::vector& Connections = mPieceInfo->GetTrainTrackInfo()->GetConnections(); - - for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) - { - const lcMatrix44 InverseTransform = lcMatrix44AffineInverse(Connections[ConnectionIndex].Transform); - const lcVector3 PointStart = lcMul31(Start, InverseTransform); - const lcVector3 PointEnd = lcMul31(End, InverseTransform); - - float Distance; - lcVector3 Plane; - - if (lcBoundingBoxRayIntersectDistance(Min, Max, PointStart, PointEnd, &Distance, nullptr, &Plane)) - { - ObjectRayTest.ObjectSection.Object = const_cast(this); - ObjectRayTest.ObjectSection.Section = LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex; - ObjectRayTest.Distance = Distance; - ObjectRayTest.PieceInfoRayTest.Plane = Plane; - } - } - } } void lcPiece::BoxTest(lcObjectBoxTest& ObjectBoxTest) const @@ -636,8 +611,6 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const if (mPieceInfo->GetSynthInfo()) DrawSynthInterface(Context, WorldMatrix); - else if (mPieceInfo->GetTrainTrackInfo()) - DrawTrainTrackInterface(Context, WorldMatrix); } void lcPiece::DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const @@ -693,58 +666,6 @@ void lcPiece::DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatr Context->EnableColorBlend(false); } -void lcPiece::DrawTrainTrackInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const -{ - if (!AreTrainTrackConnectionsVisible()) - return; - - float Verts[8 * 3]; - float* CurVert = Verts; - - lcVector3 CubeMin(-LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE, -LC_PIECE_CONTROL_POINT_SIZE); - lcVector3 CubeMax(LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE, LC_PIECE_CONTROL_POINT_SIZE); - - *CurVert++ = CubeMin[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMin[2]; - *CurVert++ = CubeMin[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMin[2]; - *CurVert++ = CubeMax[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMin[2]; - *CurVert++ = CubeMax[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMin[2]; - *CurVert++ = CubeMin[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMax[2]; - *CurVert++ = CubeMin[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMax[2]; - *CurVert++ = CubeMax[0]; *CurVert++ = CubeMax[1]; *CurVert++ = CubeMax[2]; - *CurVert++ = CubeMax[0]; *CurVert++ = CubeMin[1]; *CurVert++ = CubeMax[2]; - - const GLushort Indices[36] = - { - 0, 1, 2, 0, 2, 3, 7, 6, 5, 7, 5, 4, 5, 1, 0, 4, 5, 0, - 7, 3, 2, 6, 7, 2, 0, 3, 7, 0, 7, 4, 6, 2, 1, 5, 6, 1 - }; - - const lcPreferences& Preferences = lcGetPreferences(); - const lcVector4 ConnectionColor = lcVector4FromColor(Preferences.mControlPointColor); - const lcVector4 ConnectionFocusedColor = lcVector4FromColor(Preferences.mControlPointFocusedColor); - - const lcTrainTrackInfo* TrainTrackInfo = mPieceInfo->GetTrainTrackInfo(); - const std::vector& Connections = TrainTrackInfo->GetConnections(); - - for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) - { - Context->SetWorldMatrix(lcMul(Connections[ConnectionIndex].Transform, WorldMatrix)); - - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); - Context->SetIndexBufferPointer(Indices); - - if (IsFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex)) - Context->SetColor(ConnectionFocusedColor); - else - Context->SetColor(ConnectionColor); - - Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); - } - - mPieceInfo->GetTrainTrackInfo()->GetConnections(); -} - QVariant lcPiece::GetPropertyValue(lcObjectPropertyId PropertyId) const { switch (PropertyId) diff --git a/common/piece.h b/common/piece.h index 14ecf903..950479c0 100644 --- a/common/piece.h +++ b/common/piece.h @@ -312,8 +312,6 @@ protected: void DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const; - void DrawTrainTrackInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const; - lcObjectProperty mPosition = lcObjectProperty(lcVector3(0.0f, 0.0f, 0.0f)); lcObjectProperty mRotation = lcObjectProperty(lcMatrix33Identity());