mirror of
https://github.com/leozide/leocad
synced 2025-01-13 08:01:38 +01:00
Added gizmo to rotate train tracks.
This commit is contained in:
parent
41097f8489
commit
fd61c1c9f9
9 changed files with 162 additions and 22 deletions
|
@ -2383,7 +2383,7 @@ void lcModel::UpdateTrainTrackConnections(lcPiece* FocusPiece) const
|
|||
continue;
|
||||
|
||||
for (int ConnectionIndex = 0; ConnectionIndex < ConnectionCount; ConnectionIndex++)
|
||||
if (!Connections[ConnectionIndex] && lcTrainTrackInfo::ArePiecesConnected(FocusPiece, ConnectionIndex, Piece.get()))
|
||||
if (!Connections[ConnectionIndex] && lcTrainTrackInfo::GetPieceConnectionIndex(FocusPiece, ConnectionIndex, Piece.get()) != -1)
|
||||
Connections[ConnectionIndex] = true;
|
||||
}
|
||||
|
||||
|
@ -4395,6 +4395,54 @@ void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag
|
|||
UpdateAllViews();
|
||||
}
|
||||
|
||||
void lcModel::RotateTrainTrackToolClicked(quint32 ConnectionIndex)
|
||||
{
|
||||
const lcObject* Focus = GetFocusObject();
|
||||
|
||||
if (!Focus || !Focus->IsPiece())
|
||||
return;
|
||||
|
||||
lcPiece* FocusPiece = (lcPiece*)Focus;
|
||||
const lcTrainTrackInfo* TrainTrackInfo = FocusPiece->mPieceInfo->GetTrainTrackInfo();
|
||||
|
||||
if (!TrainTrackInfo)
|
||||
return;
|
||||
|
||||
lcPiece* ConnectedPiece = nullptr;
|
||||
int ConnectedPieceConnectionIndex = -1;
|
||||
|
||||
for (const std::unique_ptr<lcPiece>& Piece : mPieces)
|
||||
{
|
||||
if (Piece.get() == FocusPiece || !Piece->mPieceInfo->GetTrainTrackInfo())
|
||||
continue;
|
||||
|
||||
ConnectedPieceConnectionIndex = lcTrainTrackInfo::GetPieceConnectionIndex(FocusPiece, ConnectionIndex, Piece.get());
|
||||
|
||||
if (ConnectedPieceConnectionIndex != -1)
|
||||
{
|
||||
ConnectedPiece = Piece.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ConnectedPiece)
|
||||
return;
|
||||
|
||||
quint32 NewConnectionIndex = (ConnectionIndex + 1) % TrainTrackInfo->GetConnections().size();
|
||||
std::optional<lcMatrix44> Transform = lcTrainTrackInfo::GetConnectionTransform(ConnectedPiece, ConnectedPieceConnectionIndex, FocusPiece->mPieceInfo, NewConnectionIndex);
|
||||
|
||||
if (!Transform)
|
||||
return;
|
||||
|
||||
FocusPiece->SetPosition(Transform.value().GetTranslation(), mCurrentStep, gMainWindow->GetAddKeys());
|
||||
FocusPiece->SetRotation(lcMatrix33(Transform.value()), mCurrentStep, gMainWindow->GetAddKeys());
|
||||
FocusPiece->UpdatePosition(mCurrentStep);
|
||||
|
||||
gMainWindow->UpdateSelectedObjects(true);
|
||||
UpdateAllViews();
|
||||
SaveCheckpoint(tr("Rotating"));
|
||||
}
|
||||
|
||||
void lcModel::UpdateScaleTool(const float Scale)
|
||||
{
|
||||
ScaleSelectedPieces(Scale, true, false);
|
||||
|
|
|
@ -334,6 +334,7 @@ public:
|
|||
void UpdateCameraTool(const lcVector3& Position);
|
||||
void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);
|
||||
void UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag);
|
||||
void RotateTrainTrackToolClicked(quint32 ConnectionIndex);
|
||||
void UpdateScaleTool(const float Scale);
|
||||
void EraserToolClicked(lcObject* Object);
|
||||
void PaintToolClicked(lcObject* Object);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
// shortcuts for changing active connection
|
||||
// move config to json
|
||||
// add other track types
|
||||
// crash when focusing a track during in place submodel editing because GetScene doesn't have the focus piece
|
||||
// macros to encode/decode mTrackToolSection
|
||||
|
||||
void lcTrainTrackInit(lcPiecesLibrary* Library)
|
||||
{
|
||||
|
@ -127,16 +129,18 @@ std::pair<PieceInfo*, lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPi
|
|||
return { Info, Transform };
|
||||
}
|
||||
|
||||
bool lcTrainTrackInfo::ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2)
|
||||
int lcTrainTrackInfo::GetPieceConnectionIndex(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2)
|
||||
{
|
||||
const lcTrainTrackInfo* TrainTrackInfo1 = Piece1->mPieceInfo->GetTrainTrackInfo();
|
||||
const lcTrainTrackInfo* TrainTrackInfo2 = Piece2->mPieceInfo->GetTrainTrackInfo();
|
||||
|
||||
const std::vector<lcTrainTrackConnection>& Connections2 = TrainTrackInfo2->GetConnections();
|
||||
lcMatrix44 Transform1 = lcMul(TrainTrackInfo1->GetConnections()[ConnectionIndex1].Transform, Piece1->mModelWorld);
|
||||
|
||||
for (const lcTrainTrackConnection& Connection2 : TrainTrackInfo2->GetConnections())
|
||||
for (int ConnectionIndex2 = 0; ConnectionIndex2 < static_cast<int>(Connections2.size()); ConnectionIndex2++)
|
||||
{
|
||||
lcMatrix44 Transform2 = lcMul(Connection2.Transform, Piece2->mModelWorld);
|
||||
const lcTrainTrackConnection& Connection2 = Connections2[ConnectionIndex2];
|
||||
const lcMatrix44 Transform2 = lcMul(Connection2.Transform, Piece2->mModelWorld);
|
||||
|
||||
if (lcLengthSquared(Transform1.GetTranslation() - Transform2.GetTranslation()) > 0.1f)
|
||||
continue;
|
||||
|
@ -144,17 +148,14 @@ bool lcTrainTrackInfo::ArePiecesConnected(const lcPiece* Piece1, int ConnectionI
|
|||
float Dot = lcDot3(Transform1[0], Transform2[0]);
|
||||
|
||||
if (Dot < -0.99f && Dot > -1.01f)
|
||||
return true;
|
||||
return ConnectionIndex2;
|
||||
}
|
||||
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info)
|
||||
{
|
||||
if (!CurrentPiece || !Info)
|
||||
return std::nullopt;
|
||||
|
||||
const lcTrainTrackInfo* CurrentTrackInfo = CurrentPiece->mPieceInfo->GetTrainTrackInfo();
|
||||
|
||||
if (!CurrentTrackInfo || CurrentTrackInfo->GetConnections().empty())
|
||||
|
@ -177,25 +178,38 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur
|
|||
ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
}
|
||||
|
||||
if (ConnectionIndex >= CurrentTrackInfo->GetConnections().size())
|
||||
return GetConnectionTransform(CurrentPiece, ConnectionIndex, Info, 0);
|
||||
}
|
||||
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetConnectionTransform(lcPiece* CurrentPiece, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex)
|
||||
{
|
||||
if (!CurrentPiece || !Info)
|
||||
return std::nullopt;
|
||||
|
||||
const lcTrainTrackInfo* CurrentTrackInfo = CurrentPiece->mPieceInfo->GetTrainTrackInfo();
|
||||
|
||||
if (!CurrentTrackInfo || CurrentTrackInfo->GetConnections().empty())
|
||||
return std::nullopt;
|
||||
|
||||
if (CurrentConnectionIndex >= CurrentTrackInfo->GetConnections().size())
|
||||
return std::nullopt;
|
||||
|
||||
lcTrainTrackInfo* NewTrackInfo = Info->GetTrainTrackInfo();
|
||||
|
||||
if (!NewTrackInfo || NewTrackInfo->mConnections.empty())
|
||||
if (!NewTrackInfo || NewConnectionIndex >= NewTrackInfo->mConnections.size())
|
||||
return std::nullopt;
|
||||
|
||||
lcMatrix44 Transform;
|
||||
|
||||
// if (TrainTrackType != lcTrainTrackType::Left)
|
||||
Transform = NewTrackInfo->mConnections[0].Transform;
|
||||
// Transform = NewTrackInfo->mConnections[NewConnectionIndex].Transform;
|
||||
// else
|
||||
// {
|
||||
// Transform = lcMatrix44AffineInverse(TrainTrackInfo->mConnections[0].Transform);
|
||||
// Transform = lcMul(Transform, lcMatrix44RotationZ(LC_PI));
|
||||
Transform = lcMatrix44AffineInverse(NewTrackInfo->mConnections[NewConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, lcMatrix44RotationZ(LC_PI));
|
||||
// }
|
||||
|
||||
Transform = lcMul(Transform, CurrentTrackInfo->GetConnections()[ConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, CurrentTrackInfo->GetConnections()[CurrentConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, CurrentPiece->mModelWorld);
|
||||
|
||||
return Transform;
|
||||
|
|
|
@ -27,7 +27,8 @@ public:
|
|||
|
||||
std::pair<PieceInfo*, lcMatrix44> GetPieceInsertTransform(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const;
|
||||
static std::optional<lcMatrix44> GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info);
|
||||
static bool ArePiecesConnected(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2);
|
||||
static std::optional<lcMatrix44> GetConnectionTransform(lcPiece* CurrentPiece, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex);
|
||||
static int GetPieceConnectionIndex(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2);
|
||||
|
||||
void AddConnection(const lcTrainTrackConnection& TrainTrackConnection)
|
||||
{
|
||||
|
|
|
@ -1925,6 +1925,7 @@ lcCursor lcView::GetCursor() const
|
|||
lcCursor::Rotate, // lcTrackTool::RotateZ
|
||||
lcCursor::Rotate, // lcTrackTool::RotateXY
|
||||
lcCursor::Rotate, // lcTrackTool::RotateXYZ
|
||||
lcCursor::Rotate, // lcTrackTool::RotateTrainTrack
|
||||
lcCursor::Move, // lcTrackTool::ScalePlus
|
||||
lcCursor::Move, // lcTrackTool::ScaleMinus
|
||||
lcCursor::Delete, // lcTrackTool::Eraser
|
||||
|
@ -2034,6 +2035,7 @@ lcTool lcView::GetCurrentTool() const
|
|||
lcTool::Rotate, // lcTrackTool::RotateZ
|
||||
lcTool::Rotate, // lcTrackTool::RotateXY
|
||||
lcTool::Rotate, // lcTrackTool::RotateXYZ
|
||||
lcTool::Rotate, // lcTrackTool::RotateTrainTrack
|
||||
lcTool::Move, // lcTrackTool::ScalePlus
|
||||
lcTool::Move, // lcTrackTool::ScaleMinus
|
||||
lcTool::Eraser, // lcTrackTool::Eraser
|
||||
|
@ -2560,6 +2562,18 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
|
|||
StartTracking(TrackButton);
|
||||
break;
|
||||
|
||||
case lcTrackTool::RotateTrainTrack:
|
||||
{
|
||||
quint32 ConnectionIndex = mTrackToolSection & 0xff;
|
||||
|
||||
ActiveModel->RotateTrainTrackToolClicked(ConnectionIndex);
|
||||
|
||||
mToolClicked = true;
|
||||
UpdateTrackTool();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case lcTrackTool::ScalePlus:
|
||||
case lcTrackTool::ScaleMinus:
|
||||
if (ActiveModel->AnyPiecesSelected())
|
||||
|
@ -2992,6 +3006,7 @@ void lcView::OnMouseMove()
|
|||
}
|
||||
break;
|
||||
|
||||
case lcTrackTool::RotateTrainTrack:
|
||||
case lcTrackTool::Eraser:
|
||||
case lcTrackTool::Paint:
|
||||
case lcTrackTool::ColorPicker:
|
||||
|
|
|
@ -70,6 +70,7 @@ enum class lcTrackTool
|
|||
RotateZ,
|
||||
RotateXY,
|
||||
RotateXYZ,
|
||||
RotateTrainTrack,
|
||||
ScalePlus,
|
||||
ScaleMinus,
|
||||
Eraser,
|
||||
|
|
|
@ -762,6 +762,9 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe
|
|||
case lcTrackTool::RotateXYZ:
|
||||
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z)) == (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z);
|
||||
|
||||
case lcTrackTool::RotateTrainTrack:
|
||||
return true;
|
||||
|
||||
case lcTrackTool::ScalePlus:
|
||||
case lcTrackTool::ScaleMinus:
|
||||
return AllowedTransforms & (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z);
|
||||
|
@ -996,6 +999,23 @@ std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
lcObjectRayTest ObjectRayTest;
|
||||
|
||||
ObjectRayTest.PiecesOnly = true;
|
||||
ObjectRayTest.IgnoreSelected = false;
|
||||
ObjectRayTest.ViewCamera = mView->GetCamera();
|
||||
ObjectRayTest.Start = StartEnd[0];
|
||||
ObjectRayTest.End = StartEnd[1];
|
||||
|
||||
Piece->RayTestConnectedTrainTracks(ObjectRayTest);
|
||||
|
||||
if (ObjectRayTest.Distance < ClosestIntersectionDistance && ObjectRayTest.ObjectSection.Section >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
{
|
||||
NewTrackTool = lcTrackTool::RotateTrainTrack;
|
||||
ClosestIntersectionDistance = ObjectRayTest.Distance;
|
||||
NewTrackSection = ObjectRayTest.ObjectSection.Section - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -463,6 +463,41 @@ void lcPiece::RemoveTime(lcStep Start, lcStep Time)
|
|||
mRotation.RemoveTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcPiece::RayTestConnectedTrainTracks(lcObjectRayTest& ObjectRayTest) const
|
||||
{
|
||||
const lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mModelWorld);
|
||||
const lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix);
|
||||
const lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix);
|
||||
|
||||
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<lcTrainTrackConnection>& Connections = mPieceInfo->GetTrainTrackInfo()->GetConnections();
|
||||
|
||||
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);
|
||||
|
||||
float Distance;
|
||||
lcVector3 Plane;
|
||||
|
||||
if (lcBoundingBoxRayIntersectDistance(Min, Max, PointStart, PointEnd, &Distance, nullptr, &Plane))
|
||||
{
|
||||
ObjectRayTest.ObjectSection.Object = const_cast<lcPiece*>(this);
|
||||
ObjectRayTest.ObjectSection.Section = LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex;
|
||||
ObjectRayTest.Distance = Distance;
|
||||
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const
|
||||
{
|
||||
const lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mModelWorld);
|
||||
|
@ -731,19 +766,23 @@ 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);
|
||||
Context->SetVertexFormatPosition(3);
|
||||
Context->SetIndexBufferPointer(Indices);
|
||||
|
||||
if (IsFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex))
|
||||
Context->SetColor(ConnectionFocusedColor);
|
||||
if (mTrainTrackConnections[ConnectionIndex])
|
||||
{
|
||||
Context->SetColor(lcVector4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
Context->SetColor(ConnectionColor);
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
}
|
||||
|
||||
void RayTest(lcObjectRayTest& ObjectRayTest) const override;
|
||||
void RayTestConnectedTrainTracks(lcObjectRayTest& ObjectRayTest) const;
|
||||
void BoxTest(lcObjectBoxTest& ObjectBoxTest) const override;
|
||||
void DrawInterface(lcContext* Context, const lcScene& Scene) const override;
|
||||
QVariant GetPropertyValue(lcObjectPropertyId PropertyId) const override;
|
||||
|
|
Loading…
Reference in a new issue