mirror of
https://github.com/leozide/leocad
synced 2024-12-25 21:58:23 +01:00
Connect train tracks when inserting with the keyboard.
This commit is contained in:
parent
5a2d8027af
commit
14e5e7d126
6 changed files with 274 additions and 109 deletions
|
@ -19,6 +19,7 @@
|
|||
#include <deque>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#if _MSC_VER
|
||||
#pragma warning(default : 4062) // enumerator 'identifier' in switch of enum 'enumeration' is not handled
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "lc_scene.h"
|
||||
#include "lc_texture.h"
|
||||
#include "lc_synth.h"
|
||||
#include "lc_traintrack.h"
|
||||
#include "lc_file.h"
|
||||
#include "pieceinf.h"
|
||||
#include "lc_view.h"
|
||||
|
@ -2287,6 +2288,8 @@ void lcModel::AddPiece()
|
|||
const lcBoundingBox& PieceInfoBoundingBox = PieceInfo->GetBoundingBox();
|
||||
|
||||
if (Last)
|
||||
{
|
||||
if (!PieceInfo->GetTrainTrackInfo() || !Last->mPieceInfo->GetTrainTrackInfo())
|
||||
{
|
||||
const lcBoundingBox& LastBoundingBox = Last->GetBoundingBox();
|
||||
lcVector3 Dist(0, 0, LastBoundingBox.Max.z - PieceInfoBoundingBox.Min.z);
|
||||
|
@ -2296,6 +2299,15 @@ void lcModel::AddPiece()
|
|||
WorldMatrix.SetTranslation(lcMul31(Dist, Last->mModelWorld));
|
||||
}
|
||||
else
|
||||
{
|
||||
lcTrainTrackInfo* CurrentTrackInfo = Last->mPieceInfo->GetTrainTrackInfo();
|
||||
std::optional<lcMatrix44> TrainTrackTransform = CurrentTrackInfo->GetPieceInsertPosition(Last, PieceInfo);
|
||||
|
||||
if (TrainTrackTransform)
|
||||
WorldMatrix = TrainTrackTransform.value();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldMatrix = lcMatrix44Translation(lcVector3(0.0f, 0.0f, -PieceInfoBoundingBox.Min.z));
|
||||
}
|
||||
|
|
|
@ -12,46 +12,6 @@
|
|||
// move config to json
|
||||
// add other track types
|
||||
|
||||
std::pair<PieceInfo*, lcMatrix44> lcTrainTrackInfo::GetPieceInsertPosition(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const
|
||||
{
|
||||
if (ConnectionIndex >= mConnections.size())
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
const char* PieceNames[] =
|
||||
{
|
||||
"74746.dat",
|
||||
"74747.dat",
|
||||
"74747.dat",
|
||||
"2861c04.dat",
|
||||
"2859c04.dat"
|
||||
};
|
||||
|
||||
PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(PieceNames[static_cast<int>(TrainTrackType)], nullptr, false, false);
|
||||
|
||||
if (!Info)
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
lcTrainTrackInfo* TrainTrackInfo = Info->GetTrainTrackInfo();
|
||||
|
||||
if (!TrainTrackInfo || TrainTrackInfo->mConnections.empty())
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
lcMatrix44 Transform;
|
||||
|
||||
if (TrainTrackType != lcTrainTrackType::Left)
|
||||
Transform = TrainTrackInfo->mConnections[0].Transform;
|
||||
else
|
||||
{
|
||||
Transform = lcMatrix44AffineInverse(TrainTrackInfo->mConnections[0].Transform);
|
||||
Transform = lcMul(Transform, lcMatrix44RotationZ(LC_PI));
|
||||
}
|
||||
|
||||
Transform = lcMul(Transform, mConnections[ConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, Piece->mModelWorld);
|
||||
|
||||
return { Info, Transform };
|
||||
}
|
||||
|
||||
void lcTrainTrackInit(lcPiecesLibrary* Library)
|
||||
{
|
||||
PieceInfo* Info = Library->FindPiece("74746.dat", nullptr, false, false);
|
||||
|
@ -110,3 +70,77 @@ void lcTrainTrackInit(lcPiecesLibrary* Library)
|
|||
Info->SetTrainTrackInfo(TrainTrackInfo);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<PieceInfo*, lcMatrix44> lcTrainTrackInfo::GetPieceInsertPosition(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const
|
||||
{
|
||||
if (ConnectionIndex >= mConnections.size())
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
const char* PieceNames[] =
|
||||
{
|
||||
"74746.dat",
|
||||
"74747.dat",
|
||||
"74747.dat",
|
||||
"2861c04.dat",
|
||||
"2859c04.dat"
|
||||
};
|
||||
|
||||
PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(PieceNames[static_cast<int>(TrainTrackType)], nullptr, false, false);
|
||||
|
||||
if (!Info)
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
lcTrainTrackInfo* TrainTrackInfo = Info->GetTrainTrackInfo();
|
||||
|
||||
if (!TrainTrackInfo || TrainTrackInfo->mConnections.empty())
|
||||
return { nullptr, lcMatrix44Identity() };
|
||||
|
||||
lcMatrix44 Transform;
|
||||
|
||||
if (TrainTrackType != lcTrainTrackType::Left)
|
||||
Transform = TrainTrackInfo->mConnections[0].Transform;
|
||||
else
|
||||
{
|
||||
Transform = lcMatrix44AffineInverse(TrainTrackInfo->mConnections[0].Transform);
|
||||
Transform = lcMul(Transform, lcMatrix44RotationZ(LC_PI));
|
||||
}
|
||||
|
||||
Transform = lcMul(Transform, mConnections[ConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, Piece->mModelWorld);
|
||||
|
||||
return { Info, Transform };
|
||||
}
|
||||
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertPosition(lcPiece* Piece, PieceInfo* Info) const
|
||||
{
|
||||
quint32 FocusSection = Piece->GetFocusSection();
|
||||
quint32 ConnectionIndex = 0;
|
||||
|
||||
if (FocusSection > LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
{
|
||||
ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
|
||||
if (ConnectionIndex >= mConnections.size())
|
||||
ConnectionIndex = 0;
|
||||
}
|
||||
|
||||
lcTrainTrackInfo* TrainTrackInfo = Info->GetTrainTrackInfo();
|
||||
|
||||
if (!TrainTrackInfo || TrainTrackInfo->mConnections.empty())
|
||||
return std::nullopt;
|
||||
|
||||
lcMatrix44 Transform;
|
||||
|
||||
// if (TrainTrackType != lcTrainTrackType::Left)
|
||||
Transform = TrainTrackInfo->mConnections[0].Transform;
|
||||
// else
|
||||
// {
|
||||
// Transform = lcMatrix44AffineInverse(TrainTrackInfo->mConnections[0].Transform);
|
||||
// Transform = lcMul(Transform, lcMatrix44RotationZ(LC_PI));
|
||||
// }
|
||||
|
||||
Transform = lcMul(Transform, mConnections[ConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, Piece->mModelWorld);
|
||||
|
||||
return Transform;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
lcTrainTrackInfo() = default;
|
||||
|
||||
std::pair<PieceInfo*, lcMatrix44> GetPieceInsertPosition(lcPiece* Piece, quint32 ConnectionIndex, lcTrainTrackType TrainTrackType) const;
|
||||
std::optional<lcMatrix44> GetPieceInsertPosition(lcPiece* Piece, PieceInfo* Info) const;
|
||||
|
||||
void AddConnection(const lcTrainTrackConnection& TrainTrackConnection)
|
||||
{
|
||||
|
|
135
common/piece.cpp
135
common/piece.cpp
|
@ -14,6 +14,7 @@
|
|||
#include "lc_scene.h"
|
||||
#include "lc_qutils.h"
|
||||
#include "lc_synth.h"
|
||||
#include "lc_traintrack.h"
|
||||
|
||||
constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f;
|
||||
|
||||
|
@ -487,7 +488,7 @@ void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const
|
|||
}
|
||||
}
|
||||
|
||||
if (AreControlPointsVisible())
|
||||
if (mPieceInfo->GetSynthInfo() && AreControlPointsVisible())
|
||||
{
|
||||
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);
|
||||
|
@ -510,6 +511,31 @@ 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
|
||||
|
@ -608,8 +634,17 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
if (!mControlPoints.empty() && AreControlPointsVisible())
|
||||
{
|
||||
if (mPieceInfo->GetSynthInfo())
|
||||
DrawSynthInterface(Context, WorldMatrix);
|
||||
else if (mPieceInfo->GetTrainTrackInfo())
|
||||
DrawTrainTrackInterface(Context, WorldMatrix);
|
||||
}
|
||||
|
||||
void lcPiece::DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const
|
||||
{
|
||||
if (mControlPoints.empty() || !AreControlPointsVisible())
|
||||
return;
|
||||
|
||||
float Verts[8 * 3];
|
||||
float* CurVert = Verts;
|
||||
|
||||
|
@ -634,6 +669,7 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
Context->EnableColorBlend(true);
|
||||
Context->EnableCullFace(true);
|
||||
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
const lcVector4 ControlPointColor = lcVector4FromColor(Preferences.mControlPointColor);
|
||||
const lcVector4 ControlPointFocusedColor = lcVector4FromColor(Preferences.mControlPointFocusedColor);
|
||||
|
||||
|
@ -655,7 +691,58 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
|
||||
Context->EnableCullFace(false);
|
||||
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
|
||||
|
@ -1094,6 +1181,48 @@ quint32 lcPiece::GetAllowedTransforms() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
lcVector3 lcPiece::GetSectionPosition(quint32 Section) const
|
||||
{
|
||||
if (Section == LC_PIECE_SECTION_POSITION)
|
||||
{
|
||||
if (mPivotPointValid)
|
||||
return lcMul(mPivotMatrix, mModelWorld).GetTranslation();
|
||||
else
|
||||
return mModelWorld.GetTranslation();
|
||||
}
|
||||
|
||||
if (mPieceInfo->GetSynthInfo())
|
||||
{
|
||||
if (Section >= LC_PIECE_SECTION_CONTROL_POINT_FIRST)
|
||||
{
|
||||
const quint32 ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST;
|
||||
|
||||
if (ControlPointIndex < mControlPoints.size())
|
||||
{
|
||||
const lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform;
|
||||
return lcMul(Transform, mModelWorld).GetTranslation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mPieceInfo->GetTrainTrackInfo())
|
||||
{
|
||||
if (Section >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
{
|
||||
const quint32 ConnectionIndex = Section - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
const std::vector<lcTrainTrackConnection>& Connections = mPieceInfo->GetTrainTrackInfo()->GetConnections();
|
||||
|
||||
if (ConnectionIndex < Connections.size())
|
||||
{
|
||||
const lcMatrix44& Transform = Connections[ConnectionIndex].Transform;
|
||||
return lcMul(Transform, mModelWorld).GetTranslation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lcVector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
bool lcPiece::CanAddControlPoint() const
|
||||
{
|
||||
if (mControlPoints.size() >= LC_MAX_CONTROL_POINTS)
|
||||
|
|
|
@ -14,6 +14,7 @@ enum lcPieceSection : quint32
|
|||
LC_PIECE_SECTION_POSITION = 0,
|
||||
LC_PIECE_SECTION_CONTROL_POINT_FIRST,
|
||||
LC_PIECE_SECTION_CONTROL_POINT_LAST = LC_PIECE_SECTION_CONTROL_POINT_FIRST + LC_MAX_CONTROL_POINTS - 1,
|
||||
LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST = 1
|
||||
};
|
||||
|
||||
struct lcPieceControlPoint
|
||||
|
@ -90,29 +91,7 @@ public:
|
|||
}
|
||||
|
||||
quint32 GetAllowedTransforms() const override;
|
||||
|
||||
lcVector3 GetSectionPosition(quint32 Section) const override
|
||||
{
|
||||
if (Section == LC_PIECE_SECTION_POSITION)
|
||||
{
|
||||
if (mPivotPointValid)
|
||||
return lcMul(mPivotMatrix, mModelWorld).GetTranslation();
|
||||
else
|
||||
return mModelWorld.GetTranslation();
|
||||
}
|
||||
else if (Section >= LC_PIECE_SECTION_CONTROL_POINT_FIRST)
|
||||
{
|
||||
const quint32 ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST;
|
||||
|
||||
if (ControlPointIndex < mControlPoints.size())
|
||||
{
|
||||
const lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform;
|
||||
return lcMul(Transform, mModelWorld).GetTranslation();
|
||||
}
|
||||
}
|
||||
|
||||
return lcVector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
lcVector3 GetSectionPosition(quint32 Section) const override;
|
||||
|
||||
void SaveLDraw(QTextStream& Stream) const;
|
||||
bool ParseLDrawLine(QTextStream& Stream);
|
||||
|
@ -360,6 +339,15 @@ protected:
|
|||
return IsSelected();
|
||||
}
|
||||
|
||||
void DrawSynthInterface(lcContext* Context, const lcMatrix44& WorldMatrix) const;
|
||||
|
||||
bool AreTrainTrackConnectionsVisible() const
|
||||
{
|
||||
return IsSelected();
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
|
Loading…
Reference in a new issue