Automatically add sleepers to 12V tracks.
This commit is contained in:
+33
-19
@@ -2281,12 +2281,12 @@ lcMatrix33 lcModel::GetRelativeRotation() const
|
||||
return lcMatrix33Identity();
|
||||
}
|
||||
|
||||
lcPiece* lcModel::AddPiece(PieceInfo* PieceInfo, quint32 Section)
|
||||
lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section)
|
||||
{
|
||||
if (!PieceInfo)
|
||||
PieceInfo = gMainWindow->GetCurrentPieceInfo();
|
||||
if (!Info)
|
||||
Info = gMainWindow->GetCurrentPieceInfo();
|
||||
|
||||
if (!PieceInfo)
|
||||
if (!Info)
|
||||
return nullptr;
|
||||
|
||||
lcPiece* Last = mPieces.empty() ? nullptr : mPieces.back().get();
|
||||
@@ -2300,43 +2300,57 @@ lcPiece* lcModel::AddPiece(PieceInfo* PieceInfo, quint32 Section)
|
||||
}
|
||||
}
|
||||
|
||||
lcMatrix44 WorldMatrix;
|
||||
const lcBoundingBox& PieceInfoBoundingBox = PieceInfo->GetBoundingBox();
|
||||
const lcBoundingBox& PieceInfoBoundingBox = Info->GetBoundingBox();
|
||||
lcPiece* Piece = nullptr;
|
||||
|
||||
auto CreatePiece=[this, &Piece](PieceInfo* Info, const lcMatrix44& WorldMatrix, int ColorIndex)
|
||||
{
|
||||
Piece = new lcPiece(Info);
|
||||
Piece->Initialize(WorldMatrix, mCurrentStep);
|
||||
Piece->SetColorIndex(ColorIndex);
|
||||
AddPiece(Piece);
|
||||
};
|
||||
|
||||
if (Last)
|
||||
{
|
||||
bool TransformValid = false;
|
||||
std::vector<lcTrainTrackInsert> TrainTracks;
|
||||
|
||||
if (PieceInfo->GetTrainTrackInfo() && Last->mPieceInfo->GetTrainTrackInfo())
|
||||
if (Info->GetTrainTrackInfo() && Last->mPieceInfo->GetTrainTrackInfo())
|
||||
{
|
||||
std::optional<lcMatrix44> TrainTrackTransform = lcTrainTrackInfo::GetPieceInsertTransform(Last, PieceInfo, Section);
|
||||
quint32 FocusSection = Last->GetFocusSection();
|
||||
|
||||
if (TrainTrackTransform)
|
||||
if (FocusSection != LC_PIECE_SECTION_INVALID && FocusSection >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
Section = FocusSection;
|
||||
|
||||
TrainTracks = lcTrainTrackInfo::GetPieceInsertTransforms(Last, Info, Section);
|
||||
|
||||
for (const lcTrainTrackInsert& TrainTrack : TrainTracks)
|
||||
{
|
||||
TransformValid = true;
|
||||
WorldMatrix = TrainTrackTransform.value();
|
||||
int ColorIndex = TrainTrack.ColorCode == 16 ? gMainWindow->mColorIndex : lcGetColorIndex(TrainTrack.ColorCode);
|
||||
|
||||
CreatePiece(TrainTrack.Info, TrainTrack.Transform, ColorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TransformValid)
|
||||
if (TrainTracks.empty())
|
||||
{
|
||||
const lcBoundingBox& LastBoundingBox = Last->GetBoundingBox();
|
||||
lcVector3 Dist(0, 0, LastBoundingBox.Max.z - PieceInfoBoundingBox.Min.z);
|
||||
Dist = SnapPosition(Dist);
|
||||
|
||||
WorldMatrix = Last->mModelWorld;
|
||||
lcMatrix44 WorldMatrix = Last->mModelWorld;
|
||||
WorldMatrix.SetTranslation(lcMul31(Dist, Last->mModelWorld));
|
||||
|
||||
CreatePiece(Info, WorldMatrix, gMainWindow->mColorIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldMatrix = lcMatrix44Translation(lcVector3(0.0f, 0.0f, -PieceInfoBoundingBox.Min.z));
|
||||
lcMatrix44 WorldMatrix = lcMatrix44Translation(lcVector3(0.0f, 0.0f, -PieceInfoBoundingBox.Min.z));
|
||||
|
||||
CreatePiece(Info, WorldMatrix, gMainWindow->mColorIndex);
|
||||
}
|
||||
|
||||
lcPiece* Piece = new lcPiece(PieceInfo);
|
||||
Piece->Initialize(WorldMatrix, mCurrentStep);
|
||||
Piece->SetColorIndex(gMainWindow->mColorIndex);
|
||||
AddPiece(Piece);
|
||||
gMainWindow->UpdateTimeline(false, false);
|
||||
ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, false);
|
||||
|
||||
|
||||
+46
-19
@@ -7,6 +7,9 @@
|
||||
|
||||
// todo:
|
||||
// add the rest of the 9v and 12v tracks, look into 4.5v
|
||||
// see if we should remove some of the 12v tracks to avoid bloat
|
||||
// data driven sleepers
|
||||
// lcView::GetPieceInsertTransform should use track connections when dragging a new track over an existing one
|
||||
// better insert gizmo mouse detection
|
||||
// auto replace cross when going over a straight section
|
||||
// set focus connection after adding
|
||||
@@ -53,20 +56,20 @@ void lcTrainTrackInit(lcPiecesLibrary* Library)
|
||||
|
||||
float Rotation = JsonConnection["Rotation"].toDouble() * LC_DTOR;
|
||||
QString ConnectionGroup = JsonConnection["Type"].toString();
|
||||
int ConnectionDirection = 0;
|
||||
lcTrainTrackConnectionSleeper ConnectionSleeper = lcTrainTrackConnectionSleeper::None;
|
||||
|
||||
if (ConnectionGroup.startsWith('+'))
|
||||
{
|
||||
ConnectionDirection = 1;
|
||||
ConnectionSleeper = lcTrainTrackConnectionSleeper::NeedsSleeper;
|
||||
ConnectionGroup = ConnectionGroup.mid(1);
|
||||
}
|
||||
else if (ConnectionGroup.startsWith('-'))
|
||||
{
|
||||
ConnectionDirection = -1;
|
||||
ConnectionSleeper = lcTrainTrackConnectionSleeper::HasSleeper;
|
||||
ConnectionGroup = ConnectionGroup.mid(1);
|
||||
}
|
||||
|
||||
TrainTrackInfo->AddConnection(lcMatrix44(lcMatrix33RotationZ(Rotation), Position), { qHash(ConnectionGroup), ConnectionDirection } );
|
||||
TrainTrackInfo->AddConnection(lcMatrix44(lcMatrix33RotationZ(Rotation), Position), { qHash(ConnectionGroup), ConnectionSleeper } );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,21 +100,17 @@ int lcTrainTrackInfo::GetPieceConnectionIndex(const lcPiece* Piece1, int Connect
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info, quint32 Section)
|
||||
std::vector<lcTrainTrackInsert> lcTrainTrackInfo::GetPieceInsertTransforms(lcPiece* CurrentPiece, PieceInfo* Info, quint32 Section)
|
||||
{
|
||||
std::vector<lcTrainTrackInsert> Pieces;
|
||||
const lcTrainTrackInfo* CurrentTrackInfo = CurrentPiece->mPieceInfo->GetTrainTrackInfo();
|
||||
|
||||
if (!CurrentTrackInfo || CurrentTrackInfo->GetConnections().empty())
|
||||
return std::nullopt;
|
||||
return Pieces;
|
||||
|
||||
const quint32 FocusSection = CurrentPiece->GetFocusSection();
|
||||
quint32 ConnectionIndex = 0;
|
||||
|
||||
if (FocusSection != LC_PIECE_SECTION_INVALID && FocusSection >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
{
|
||||
ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
}
|
||||
else if (Section != LC_PIECE_SECTION_INVALID && Section >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
if (Section != LC_PIECE_SECTION_INVALID && Section >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
||||
{
|
||||
ConnectionIndex = Section - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
||||
}
|
||||
@@ -122,7 +121,7 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur
|
||||
break;
|
||||
|
||||
if (ConnectionIndex == CurrentTrackInfo->GetConnections().size())
|
||||
return std::nullopt;
|
||||
return Pieces;
|
||||
}
|
||||
|
||||
const lcTrainTrackConnectionType& CurrentConnectionType = CurrentTrackInfo->GetConnections()[ConnectionIndex].Type;
|
||||
@@ -134,17 +133,45 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetPieceInsertTransform(lcPiece* Cur
|
||||
break;
|
||||
|
||||
if (NewConnectionIndex == NewConnections.size())
|
||||
return std::nullopt;
|
||||
return Pieces;
|
||||
|
||||
return GetConnectionTransform(CurrentPiece, ConnectionIndex, Info, NewConnectionIndex);
|
||||
if (CurrentConnectionType.Sleeper == lcTrainTrackConnectionSleeper::NeedsSleeper && NewConnections[NewConnectionIndex].Type.Sleeper == lcTrainTrackConnectionSleeper::NeedsSleeper)
|
||||
{
|
||||
PieceInfo* SleeperInfo = lcGetPiecesLibrary()->FindPiece("4166a.dat", nullptr, false, false); // todo: data driven
|
||||
|
||||
if (!SleeperInfo)
|
||||
return Pieces;
|
||||
|
||||
std::optional<lcMatrix44> SleeperTransform = GetConnectionTransform(CurrentPiece->mPieceInfo, CurrentPiece->mModelWorld, ConnectionIndex, SleeperInfo, 0);
|
||||
|
||||
if (!SleeperTransform)
|
||||
return Pieces;
|
||||
|
||||
std::optional<lcMatrix44> Transform = GetConnectionTransform(SleeperInfo, SleeperTransform.value(), 1, Info, NewConnectionIndex);
|
||||
|
||||
if (Transform)
|
||||
{
|
||||
Pieces.emplace_back(lcTrainTrackInsert{ SleeperInfo, SleeperTransform.value(), 8 });
|
||||
Pieces.emplace_back(lcTrainTrackInsert{ Info, Transform.value(), 16 });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::optional<lcMatrix44> Transform = GetConnectionTransform(CurrentPiece->mPieceInfo, CurrentPiece->mModelWorld, ConnectionIndex, Info, NewConnectionIndex);
|
||||
|
||||
if (Transform)
|
||||
Pieces.emplace_back(lcTrainTrackInsert{ Info, Transform.value(), 16 });
|
||||
}
|
||||
|
||||
return Pieces;
|
||||
}
|
||||
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetConnectionTransform(lcPiece* CurrentPiece, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex)
|
||||
std::optional<lcMatrix44> lcTrainTrackInfo::GetConnectionTransform(PieceInfo* CurrentInfo, const lcMatrix44& CurrentTransform, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex)
|
||||
{
|
||||
if (!CurrentPiece || !Info)
|
||||
if (!CurrentInfo || !Info)
|
||||
return std::nullopt;
|
||||
|
||||
const lcTrainTrackInfo* CurrentTrackInfo = CurrentPiece->mPieceInfo->GetTrainTrackInfo();
|
||||
const lcTrainTrackInfo* CurrentTrackInfo = CurrentInfo->GetTrainTrackInfo();
|
||||
|
||||
if (!CurrentTrackInfo || CurrentTrackInfo->GetConnections().empty())
|
||||
return std::nullopt;
|
||||
@@ -168,7 +195,7 @@ std::optional<lcMatrix44> lcTrainTrackInfo::GetConnectionTransform(lcPiece* Curr
|
||||
// }
|
||||
|
||||
Transform = lcMul(Transform, CurrentTrackInfo->GetConnections()[CurrentConnectionIndex].Transform);
|
||||
Transform = lcMul(Transform, CurrentPiece->mModelWorld);
|
||||
Transform = lcMul(Transform, CurrentTransform);
|
||||
|
||||
return Transform;
|
||||
}
|
||||
|
||||
+34
-4
@@ -4,11 +4,19 @@
|
||||
|
||||
class lcPiece;
|
||||
class lcPiecesLibrary;
|
||||
class PieceInfo;
|
||||
|
||||
enum class lcTrainTrackConnectionSleeper
|
||||
{
|
||||
None,
|
||||
HasSleeper,
|
||||
NeedsSleeper
|
||||
};
|
||||
|
||||
struct lcTrainTrackConnectionType
|
||||
{
|
||||
quint32 Group;
|
||||
int Format;
|
||||
lcTrainTrackConnectionSleeper Sleeper;
|
||||
};
|
||||
|
||||
struct lcTrainTrackConnection
|
||||
@@ -17,13 +25,20 @@ struct lcTrainTrackConnection
|
||||
lcTrainTrackConnectionType Type;
|
||||
};
|
||||
|
||||
struct lcTrainTrackInsert
|
||||
{
|
||||
PieceInfo* Info;
|
||||
lcMatrix44 Transform;
|
||||
int ColorCode;
|
||||
};
|
||||
|
||||
class lcTrainTrackInfo
|
||||
{
|
||||
public:
|
||||
lcTrainTrackInfo() = default;
|
||||
|
||||
static std::optional<lcMatrix44> GetPieceInsertTransform(lcPiece* CurrentPiece, PieceInfo* Info, quint32 Section);
|
||||
static std::optional<lcMatrix44> GetConnectionTransform(lcPiece* CurrentPiece, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex);
|
||||
static std::vector<lcTrainTrackInsert> GetPieceInsertTransforms(lcPiece* CurrentPiece, PieceInfo* Info, quint32 Section);
|
||||
static std::optional<lcMatrix44> GetConnectionTransform(PieceInfo* CurrentInfo, const lcMatrix44& CurrentTransform, quint32 CurrentConnectionIndex, PieceInfo* Info, quint32 NewConnectionIndex);
|
||||
static std::optional<lcMatrix44> CalculateTransformToConnection(const lcMatrix44& ConnectionTransform, PieceInfo* Info, quint32 ConnectionIndex);
|
||||
static int GetPieceConnectionIndex(const lcPiece* Piece1, int ConnectionIndex1, const lcPiece* Piece2);
|
||||
|
||||
@@ -49,7 +64,22 @@ public:
|
||||
protected:
|
||||
static bool AreConnectionsCompatible(const lcTrainTrackConnectionType& a, const lcTrainTrackConnectionType& b)
|
||||
{
|
||||
return a.Group == b.Group && a.Format + b.Format == 0;
|
||||
if (a.Group != b.Group)
|
||||
return false;
|
||||
|
||||
switch (a.Sleeper)
|
||||
{
|
||||
case lcTrainTrackConnectionSleeper::None:
|
||||
return b.Sleeper == lcTrainTrackConnectionSleeper::None;
|
||||
|
||||
case lcTrainTrackConnectionSleeper::HasSleeper:
|
||||
return b.Sleeper == lcTrainTrackConnectionSleeper::NeedsSleeper;
|
||||
|
||||
case lcTrainTrackConnectionSleeper::NeedsSleeper:
|
||||
return b.Sleeper == lcTrainTrackConnectionSleeper::HasSleeper || b.Sleeper == lcTrainTrackConnectionSleeper::NeedsSleeper;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<lcTrainTrackConnection> mConnections;
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
},
|
||||
"Train Track Sleeper Plate 2 x 8":
|
||||
{
|
||||
"Parts": [ "4166a.dat" ],
|
||||
"Parts": [ "4166a.dat", "4166b.dat" ],
|
||||
"Connections":
|
||||
[
|
||||
{
|
||||
@@ -279,6 +279,23 @@
|
||||
"Type": "+12V"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Train Track 4.5V Slotted Straight Without End Sleepers":
|
||||
{
|
||||
"Parts": [ "3228bc02.dat" ],
|
||||
"Connections":
|
||||
[
|
||||
{
|
||||
"Position": [ 160.0, 0.0, 0.0 ],
|
||||
"Rotation": 0.0,
|
||||
"Type": "+4.5V"
|
||||
},
|
||||
{
|
||||
"Position": [ -160.0, 0.0, 0.0 ],
|
||||
"Rotation": -180.0,
|
||||
"Type": "+4.5V"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user