diff --git a/common/lc_model.cpp b/common/lc_model.cpp index c6e4cb09..e9bb4b75 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1316,10 +1316,15 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig if (mPieceInfo) mPieceInfo->AddRenderMesh(*Scene); + lcPiece* FocusPiece = nullptr; + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsVisible(mCurrentStep)) { + if (Piece->IsFocused()) + FocusPiece = Piece.get(); + const lcStep StepShow = Piece->GetStepShow(); Piece->AddMainModelRenderMeshes(Scene, AllowHighlight && StepShow == mCurrentStep, AllowFade && StepShow < mCurrentStep); } @@ -1327,6 +1332,9 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig if (Scene->GetDrawInterface() && !Scene->GetActiveSubmodelInstance()) { + if (FocusPiece) + UpdateTrainTrackConnections(FocusPiece); + for (const std::unique_ptr& Camera : mCameras) if (Camera.get() != ViewCamera && Camera->IsVisible()) Scene->AddInterfaceObject(Camera.get()); @@ -2356,6 +2364,32 @@ void lcModel::InsertPiece(lcPiece* Piece, size_t Index) mPieces.insert(mPieces.begin() + Index, std::unique_ptr(Piece)); } +void lcModel::UpdateTrainTrackConnections(lcPiece* FocusPiece) const +{ + if (!FocusPiece || !FocusPiece->IsFocused()) + return; + + const lcTrainTrackInfo* TrainTrackInfo = FocusPiece->mPieceInfo->GetTrainTrackInfo(); + + if (!TrainTrackInfo) + return; + + const int ConnectionCount = static_cast(TrainTrackInfo->GetConnections().size()); + std::vector Connections(ConnectionCount, false); + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece.get() == FocusPiece || !Piece->mPieceInfo->GetTrainTrackInfo()) + continue; + + for (int ConnectionIndex = 0; ConnectionIndex < ConnectionCount; ConnectionIndex++) + if (!Connections[ConnectionIndex] && lcTrainTrackInfo::ArePiecesConnected(FocusPiece, ConnectionIndex, Piece.get())) + Connections[ConnectionIndex] = true; + } + + FocusPiece->SetTrainTrackConnections(std::move(Connections)); +} + void lcModel::DeleteAllCameras() { if (mCameras.empty()) @@ -3782,11 +3816,13 @@ void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool if (Object->IsPiece()) { - SelectGroup(((lcPiece*)Object)->GetTopGroup(), true); + lcPiece* Piece = dynamic_cast(Object); + + SelectGroup(Piece->GetTopGroup(), true); if (EnableSelectionMode) { - std::vector Pieces = GetSelectionModePieces((lcPiece*)Object); + std::vector Pieces = GetSelectionModePieces(Piece); AddToSelection(Pieces, false, false); } } diff --git a/common/lc_model.h b/common/lc_model.h index 311200e4..963ae353 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -390,6 +390,8 @@ protected: void AddPiece(lcPiece* Piece); void InsertPiece(lcPiece* Piece, size_t Index); + void UpdateTrainTrackConnections(lcPiece* FocusPiece) const; + lcPOVRayOptions mPOVRayOptions; lcModelProperties mProperties; Project* const mProject; diff --git a/common/lc_traintrack.cpp b/common/lc_traintrack.cpp index 786dc27c..03365949 100644 --- a/common/lc_traintrack.cpp +++ b/common/lc_traintrack.cpp @@ -111,6 +111,29 @@ std::pair lcTrainTrackInfo::GetPieceInsertTransform(lcPi return { Info, Transform }; } +bool lcTrainTrackInfo::ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2) +{ + const lcTrainTrackInfo* TrainTrackInfo1 = Piece1->mPieceInfo->GetTrainTrackInfo(); + const lcTrainTrackInfo* TrainTrackInfo2 = Piece2->mPieceInfo->GetTrainTrackInfo(); + + lcMatrix44 Transform1 = lcMul(TrainTrackInfo1->GetConnections()[ConnectionIndex1].Transform, Piece1->mModelWorld); + + for (const lcTrainTrackConnection& Connection2 : TrainTrackInfo2->GetConnections()) + { + lcMatrix44 Transform2 = lcMul(Connection2.Transform, Piece2->mModelWorld); + + if (lcLengthSquared(Transform1.GetTranslation() - Transform2.GetTranslation()) > 0.1f) + continue; + + float Dot = lcDot3(Transform1[0], Transform2[0]); + + if (Dot < -0.99f && Dot > -1.01f) + return true; + } + + return false; +} + std::optional lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info) { if (!CurrentPiece || !Info) @@ -126,7 +149,9 @@ std::optional lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur if (FocusSection == LC_PIECE_SECTION_POSITION || FocusSection == LC_PIECE_SECTION_INVALID) { - // todo: search model for open connection + for (ConnectionIndex = 0; ConnectionIndex < CurrentTrackInfo->GetConnections().size(); ConnectionIndex++) + if (CurrentPiece->IsTrainTrackConnectionVisible(ConnectionIndex)) + break; } else { @@ -134,11 +159,11 @@ std::optional lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur return std::nullopt; ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST; - - if (ConnectionIndex >= CurrentTrackInfo->GetConnections().size()) - return std::nullopt; } + if (ConnectionIndex >= CurrentTrackInfo->GetConnections().size()) + return std::nullopt; + lcTrainTrackInfo* NewTrackInfo = Info->GetTrainTrackInfo(); if (!NewTrackInfo || NewTrackInfo->mConnections.empty()) diff --git a/common/lc_traintrack.h b/common/lc_traintrack.h index ce3275ad..dcb00b79 100644 --- a/common/lc_traintrack.h +++ b/common/lc_traintrack.h @@ -27,6 +27,7 @@ public: std::pair GetPieceInsertTransform(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const; static std::optional GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info); + static bool ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2); void AddConnection(const lcTrainTrackConnection& TrainTrackConnection) { diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index b646c8b6..3afc88f1 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -371,26 +371,32 @@ void lcViewManipulator::DrawSelectMove(lcTrackButton TrackButton, lcTrackTool Tr void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, float OverlayScale) { const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo(); + const std::vector& Connections = TrainTrackInfo->GetConnections(); - for (const lcTrainTrackConnection& TrainTrackConnection : TrainTrackInfo->GetConnections()) + for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) { + if (!Piece->IsTrainTrackConnectionVisible(ConnectionIndex)) + continue; + + const lcMatrix44& Transform = Connections[ConnectionIndex].Transform; + lcVector3 Verts[static_cast(lcTrainTrackType::Count) * 2]; int NumVerts = 0; - Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcVector3(TrainTrackConnection.Transform[0]) * 100) / OverlayScale; + Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale; + Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / OverlayScale; - Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / OverlayScale; + Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / OverlayScale; - Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / OverlayScale; + Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / OverlayScale; - Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / OverlayScale; + Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / OverlayScale; - Verts[NumVerts++] = TrainTrackConnection.Transform.GetTranslation() / OverlayScale; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / OverlayScale; + Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / OverlayScale; Context->SetColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -956,17 +962,22 @@ std::pair lcViewManipulator::UpdateSelectMove() if (TrainTrackInfo) { - for (quint32 Section = 0; Section < TrainTrackInfo->GetConnections().size(); Section++) + const std::vector& Connections = TrainTrackInfo->GetConnections(); + + for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) { - const lcTrainTrackConnection& TrainTrackConnection = TrainTrackInfo->GetConnections()[Section]; + if (!Piece->IsTrainTrackConnectionVisible(ConnectionIndex)) + continue; + + const lcMatrix44& Transform = Connections[ConnectionIndex].Transform; lcVector3 Verts[static_cast(lcTrainTrackType::Count)]; int NumVerts = 0; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcVector3(TrainTrackConnection.Transform[0]) * 100) / 1; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / 1; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / 1; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / 1; - Verts[NumVerts++] = (TrainTrackConnection.Transform.GetTranslation() + lcMul31(lcVector3(TrainTrackConnection.Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / 1; + Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / 1; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / 1; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / 1; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / 1; + Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / 1; for (int VertexIndex = 0; VertexIndex < NumVerts; VertexIndex++) { @@ -981,7 +992,7 @@ std::pair lcViewManipulator::UpdateSelectMove() NewTrackTool = lcTrackTool::Insert; ClosestIntersectionDistance = IntersectionDistance; - NewTrackSection = Section | (VertexIndex << 8); + NewTrackSection = ConnectionIndex | (VertexIndex << 8); } } } diff --git a/common/piece.cpp b/common/piece.cpp index 720e257b..1dc4d425 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -520,6 +520,9 @@ void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) { + if (mTrainTrackConnections[ConnectionIndex]) + continue; + const lcMatrix44 InverseTransform = lcMatrix44AffineInverse(Connections[ConnectionIndex].Transform); const lcVector3 PointStart = lcMul31(Start, InverseTransform); const lcVector3 PointEnd = lcMul31(End, InverseTransform); @@ -728,6 +731,9 @@ void lcPiece::DrawTrainTrackInterface(lcContext* Context, const lcMatrix44& Worl for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++) { + if (mTrainTrackConnections[ConnectionIndex]) + continue; + Context->SetWorldMatrix(lcMul(Connections[ConnectionIndex].Transform, WorldMatrix)); Context->SetVertexBufferPointer(Verts); diff --git a/common/piece.h b/common/piece.h index 66dc3ef1..165d167c 100644 --- a/common/piece.h +++ b/common/piece.h @@ -150,6 +150,16 @@ public: UpdateMesh(); } + bool IsTrainTrackConnectionVisible(int ConnectionIndex) const + { + return !mTrainTrackConnections[ConnectionIndex]; + } + + void SetTrainTrackConnections(std::vector&& Connections) + { + mTrainTrackConnections = std::move(Connections); + } + const QString& GetID() const { return mID; @@ -367,5 +377,6 @@ protected: bool mSelected = false; quint32 mFocusedSection = LC_PIECE_SECTION_INVALID; std::vector mControlPoints; + std::vector mTrainTrackConnections; lcMesh* mMesh = nullptr; };