Draw train track connection boxes in the manipulator to match the scaling with the other gizmos.

This commit is contained in:
Leonardo Zide
2025-05-01 12:26:34 -07:00
parent e07c069bb1
commit e86208caab
7 changed files with 127 additions and 90 deletions
+2 -2
View File
@@ -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
+30 -2
View File
@@ -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:
+1
View File
@@ -75,6 +75,7 @@ enum class lcTrackTool
RotateTrainTrackRight,
RotateTrainTrackLeft,
InsertTrainTrack,
SelectTrainTrack,
ScalePlus,
ScaleMinus,
Eraser,
+93 -4
View File
@@ -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<lcTrainTrackConnection>& 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<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove()
std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove(lcTrackButton TrackButton)
{
lcModel* ActiveModel = mView->GetActiveModel();
const float OverlayScale = mView->GetOverlayScale();
@@ -1110,7 +1166,7 @@ std::pair<lcTrackTool, quint32> 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<lcTrackTool, quint32, float> lcViewManipulator::UpdateSelectMoveTrain
}
}
const std::vector<lcTrainTrackConnection>& 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 };
}
+1 -1
View File
@@ -10,7 +10,7 @@ public:
void DrawSelectMove(lcTrackButton TrackButton, lcTrackTool TrackTool, quint32 TrackToolSection);
void DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackTool);
std::pair<lcTrackTool, quint32> UpdateSelectMove();
std::pair<lcTrackTool, quint32> UpdateSelectMove(lcTrackButton TrackButton);
lcTrackTool UpdateRotate();
static void CreateResources(lcContext* Context);
-79
View File
@@ -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<lcTrainTrackConnection>& 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<lcPiece*>(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<lcTrainTrackConnection>& 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)
-2
View File
@@ -312,8 +312,6 @@ protected:
void DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const;
void DrawTrainTrackInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const;
lcObjectProperty<lcVector3> mPosition = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
lcObjectProperty<lcMatrix33> mRotation = lcObjectProperty<lcMatrix33>(lcMatrix33Identity());