adding path reservation #WIP

see #14
Dieser Commit ist enthalten in:
Reinder Feenstra 2023-11-01 22:18:45 +01:00
Ursprung f58d09bc7e
Commit 8ec71e496d
33 geänderte Dateien mit 1076 neuen und 372 gelöschten Zeilen

Datei anzeigen

@ -518,6 +518,8 @@ void BoardAreaWidget::paintEvent(QPaintEvent* event)
const TileId id = it.second.id();
const TileRotate a = it.second.rotate();
const uint8_t state = it.second.state;
const bool isReserved = (state != 0);
painter.setBrush(Qt::NoBrush);
const QRectF r = drawTileRect(it.first.x - tileOriginX, it.first.y - tileOriginY, it.second.width(), it.second.height(), tileSize);
@ -526,16 +528,11 @@ void BoardAreaWidget::paintEvent(QPaintEvent* event)
case TileId::RailStraight:
case TileId::RailCurve45:
case TileId::RailCurve90:
case TileId::RailCross45:
case TileId::RailCross90:
case TileId::RailBridge45Left:
case TileId::RailBridge45Right:
case TileId::RailBridge90:
case TileId::RailBufferStop:
case TileId::RailTunnel:
case TileId::RailOneWay:
case TileId::RailLink:
tilePainter.draw(id, r, a);
tilePainter.draw(id, r, a, isReserved);
break;
case TileId::RailTurnoutLeft45:
@ -548,24 +545,35 @@ void BoardAreaWidget::paintEvent(QPaintEvent* event)
case TileId::RailTurnout3Way:
case TileId::RailTurnoutSingleSlip:
case TileId::RailTurnoutDoubleSlip:
tilePainter.drawTurnout(id, r, a, getTurnoutPosition(it.first));
tilePainter.drawTurnout(id, r, a, static_cast<TurnoutPosition>(state), getTurnoutPosition(it.first));
break;
case TileId::RailCross45:
case TileId::RailCross90:
tilePainter.drawCross(id, r, a, static_cast<CrossState>(state));
break;
case TileId::RailBridge45Left:
case TileId::RailBridge45Right:
case TileId::RailBridge90:
tilePainter.drawBridge(id, r, a, state & 0x01, state & 0x02);
break;
case TileId::RailSensor:
tilePainter.drawSensor(id, r, a, getSensorState(it.first));
tilePainter.drawSensor(id, r, a, isReserved, getSensorState(it.first));
break;
case TileId::RailSignal2Aspect:
case TileId::RailSignal3Aspect:
tilePainter.drawSignal(id, r, a, getSignalAspect(it.first));
tilePainter.drawSignal(id, r, a, isReserved, getSignalAspect(it.first));
break;
case TileId::RailBlock:
tilePainter.drawBlock(id, r, a, m_board.board().getTileObject(it.first));
tilePainter.drawBlock(id, r, a, state & 0x01, state & 0x02, m_board.board().getTileObject(it.first));
break;
case TileId::RailDirectionControl:
tilePainter.drawDirectionControl(id, r, a, getDirectionControlState(it.first));
tilePainter.drawDirectionControl(id, r, a, isReserved, getDirectionControlState(it.first));
break;
case TileId::PushButton:
@ -573,11 +581,11 @@ void BoardAreaWidget::paintEvent(QPaintEvent* event)
break;
case TileId::RailDecoupler:
tilePainter.drawRailDecoupler(r, a, getDecouplerState(it.first));
tilePainter.drawRailDecoupler(r, a, isReserved, getDecouplerState(it.first));
break;
case TileId::RailNXButton:
tilePainter.drawRailNX(r, a, getNXButtonPressed(it.first));
tilePainter.drawRailNX(r, a, isReserved, getNXButtonPressed(it.first));
break;
case TileId::None:

Datei anzeigen

@ -27,6 +27,8 @@ const BoardColorScheme BoardColorScheme::dark = {
/*.foreground =*/ {0xFF, 0xFF, 0xFF},
/*.track =*/ {0xC0, 0xC0, 0xC0},
/*.trackDisabled =*/ {0x40, 0x40, 0x40},
/*.trackReserved =*/ {Qt::yellow},
/*.trackReservedDisabled =*/ {0x99, 0x99, 0x00},
/*.blockFree =*/ {0x66, 0xC6, 0x66},
/*.blockReserved =*/ {Qt::yellow},
/*.blockOccupied =*/ {0xC6, 0x66, 0x66},
@ -47,6 +49,8 @@ const BoardColorScheme BoardColorScheme::light = {
/*.foreground =*/ {0x00, 0x00, 0x00},
/*.track =*/ {0x00, 0x00, 0x00},
/*.trackDisabled =*/ {0xA0, 0xA0, 0xA0},
/*.trackReserved =*/ {Qt::yellow},
/*.trackReservedDisabled =*/ {0x99, 0x99, 0x00},
/*.blockFree =*/ {0x44, 0xC6, 0x44},
/*.blockReserved =*/ {Qt::yellow},
/*.blockOccupied =*/ {0xC6, 0x44, 0x44},

Datei anzeigen

@ -34,6 +34,8 @@ struct BoardColorScheme
const QColor foreground;
const QColor track;
const QColor trackDisabled;
const QColor trackReserved;
const QColor trackReservedDisabled;
const QColor blockFree;
const QColor blockReserved;
const QColor blockOccupied;

Datei anzeigen

@ -695,11 +695,11 @@ void BoardWidget::tileClicked(int16_t x, int16_t y)
image.fill(Qt::transparent);
if(isRailTurnout(tileId))
tilePainter.drawTurnout(tileId, image.rect(), tileRotate, static_cast<TurnoutPosition>(n));
tilePainter.drawTurnout(tileId, image.rect(), tileRotate, TurnoutPosition::Unknown, static_cast<TurnoutPosition>(n));
else if(isRailSignal(tileId))
tilePainter.drawSignal(tileId, image.rect(), tileRotate, static_cast<SignalAspect>(n));
tilePainter.drawSignal(tileId, image.rect(), tileRotate, false, static_cast<SignalAspect>(n));
else if(tileId == TileId::RailDirectionControl)
tilePainter.drawDirectionControl(tileId, image.rect(), tileRotate, static_cast<DirectionControlState>(n));
tilePainter.drawDirectionControl(tileId, image.rect(), tileRotate, false, static_cast<DirectionControlState>(n));
connect(menu.addAction(QIcon(QPixmap::fromImage(image)), translateEnum(value->enumName(), n)), &QAction::triggered,
[this, setValue, n]()

Datei anzeigen

@ -42,68 +42,42 @@ TilePainter::TilePainter(QPainter& painter, int tileSize, const BoardColorScheme
m_blockPen{m_colorScheme.track},
m_trackPen(m_colorScheme.track, m_trackWidth, Qt::SolidLine, Qt::FlatCap),
m_trackDisabledPen(m_colorScheme.trackDisabled, m_trackWidth, Qt::SolidLine, Qt::FlatCap),
m_trackReservedPen(m_colorScheme.trackReserved, m_trackWidth, Qt::SolidLine, Qt::FlatCap),
m_trackReservedDisabledPen(m_colorScheme.trackReservedDisabled, m_trackWidth, Qt::SolidLine, Qt::FlatCap),
m_trackErasePen(m_colorScheme.background, m_trackWidth * 2, Qt::SolidLine, Qt::FlatCap),
m_turnoutStatePen(m_colorScheme.turnoutState, (m_trackWidth + 1) / 2, Qt::SolidLine, Qt::FlatCap),
m_painter{painter}
{
}
void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate, bool isReserved)
{
switch(id)
{
case TileId::RailStraight:
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
break;
case TileId::RailCurve45:
setTrackPen();
setTrackPen(isReserved);
drawCurve45(r, rotate);
break;
case TileId::RailCurve90:
setTrackPen();
setTrackPen(isReserved);
drawCurve90(r, rotate);
break;
case TileId::RailCross45:
setTrackPen();
drawStraight(r, rotate);
drawStraight(r, rotate - TileRotate::Deg45);
break;
case TileId::RailCross90:
setTrackPen();
drawStraight(r, rotate);
drawStraight(r, rotate + TileRotate::Deg90);
drawCross(id, r, rotate);
break;
case TileId::RailBridge45Left:
setTrackPen();
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate - TileRotate::Deg45);
setTrackPen();
drawStraight(r, rotate - TileRotate::Deg45);
break;
case TileId::RailBridge45Right:
setTrackPen();
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate + TileRotate::Deg45);
setTrackPen();
drawStraight(r, rotate + TileRotate::Deg45);
break;
case TileId::RailBridge90:
setTrackPen();
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate + TileRotate::Deg90);
setTrackPen();
drawStraight(r, rotate + TileRotate::Deg90);
drawBridge(id, r, rotate);
break;
case TileId::RailTurnoutLeft45:
@ -124,13 +98,13 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
break;
case TileId::RailBufferStop:
setTrackPen();
setTrackPen(isReserved);
drawBufferStop(r, rotate);
break;
case TileId::RailSignal2Aspect:
case TileId::RailSignal3Aspect:
drawSignal(id, r, rotate);
drawSignal(id, r, rotate, isReserved);
break;
case TileId::RailBlock:
@ -139,7 +113,7 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
case TileId::RailTunnel:
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
// tunnel arc:
@ -155,14 +129,14 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
break;
}
case TileId::RailDirectionControl:
drawDirectionControl(id, r, rotate);
drawDirectionControl(id, r, rotate, isReserved);
break;
case TileId::RailOneWay:
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
m_painter.setBrush(m_trackPen.color());
m_painter.setBrush(m_painter.pen().color());
const qreal m = r.width() / 4;
QRectF rTriangle = r.adjusted(m, m, -m, -m);
@ -182,16 +156,16 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
break;
case TileId::RailLink:
setTrackPen();
setTrackPen(isReserved);
drawLink(r, rotate);
break;
case TileId::RailDecoupler:
drawRailDecoupler(r, rotate);
drawRailDecoupler(r, rotate, isReserved);
break;
case TileId::RailNXButton:
drawRailNX(r, rotate);
drawRailNX(r, rotate, isReserved);
break;
case TileId::None:
@ -200,13 +174,118 @@ void TilePainter::draw(TileId id, const QRectF& r, TileRotate rotate)
}
}
void TilePainter::drawSensor(TileId id, const QRectF& r, TileRotate rotate, SensorState state)
void TilePainter::drawBridge(TileId id, const QRectF& r, TileRotate rotate, bool isReservedAC, bool isReservedBD)
{
switch(id)
{
case TileId::RailBridge45Left:
setTrackPen(isReservedAC);
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate - TileRotate::Deg45);
setTrackPen(isReservedBD);
drawStraight(r, rotate - TileRotate::Deg45);
break;
case TileId::RailBridge45Right:
setTrackPen(isReservedAC);
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate + TileRotate::Deg45);
setTrackPen(isReservedBD);
drawStraight(r, rotate + TileRotate::Deg45);
break;
case TileId::RailBridge90:
setTrackPen(isReservedAC);
drawStraight(r, rotate);
setTrackErasePen();
drawStraight(r, rotate + TileRotate::Deg90);
setTrackPen(isReservedBD);
drawStraight(r, rotate + TileRotate::Deg90);
break;
default:
break;
}
}
void TilePainter::drawCross(TileId id, const QRectF& r, TileRotate rotate, CrossState reservedState)
{
switch(id)
{
case TileId::RailCross45:
setTrackPen();
if(reservedState != CrossState::AC)
{
drawStraight(r, rotate);
}
if(reservedState != CrossState::BD)
{
drawStraight(r, rotate - TileRotate::Deg45);
}
if(reservedState != CrossState::Unset)
{
setTrackPen(true);
switch(reservedState)
{
case CrossState::AC:
drawStraight(r, rotate);
break;
case CrossState::BD:
drawStraight(r, rotate - TileRotate::Deg45);
break;
default:
break;
}
}
break;
case TileId::RailCross90:
setTrackPen();
if(reservedState != CrossState::AC)
{
drawStraight(r, rotate);
}
if(reservedState != CrossState::BD)
{
drawStraight(r, rotate - TileRotate::Deg90);
}
if(reservedState != CrossState::Unset)
{
setTrackPen(true);
switch(reservedState)
{
case CrossState::AC:
drawStraight(r, rotate);
break;
case CrossState::BD:
drawStraight(r, rotate - TileRotate::Deg90);
break;
default:
break;
}
}
break;
default:
break;
}
}
void TilePainter::drawSensor(TileId id, const QRectF& r, TileRotate rotate, bool isReserved, SensorState state)
{
switch(id)
{
case TileId::RailSensor:
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
const qreal sz = r.width() / 4;
drawLED(r.adjusted(sz, sz, -sz, -sz), sensorStateToColor(state), m_colorScheme.track);
@ -217,13 +296,13 @@ void TilePainter::drawSensor(TileId id, const QRectF& r, TileRotate rotate, Sens
}
}
void TilePainter::drawDirectionControl(TileId id, const QRectF& r, TileRotate rotate, DirectionControlState state)
void TilePainter::drawDirectionControl(TileId id, const QRectF& r, TileRotate rotate, bool isReserved, DirectionControlState state)
{
switch(id)
{
case TileId::RailDirectionControl:
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
QPen pen{m_trackPen};
@ -286,253 +365,24 @@ void TilePainter::drawDirectionControl(TileId id, const QRectF& r, TileRotate ro
}
}
void TilePainter::drawTurnout(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition position)
void TilePainter::drawTurnout(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition, TurnoutPosition position)
{
switch(id)
{
case TileId::RailTurnoutLeft45:
setTurnoutPen();
drawStraight(r, rotate);
drawCurve45(r, rotate);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Left:
drawCurve45(turnoutStateRect(r), rotate);
break;
default:
break;
}
break;
case TileId::RailTurnoutLeft90:
setTurnoutPen();
drawStraight(r, rotate);
drawCurve90(r, rotate);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Left:
drawCurve90(turnoutStateRect(r), rotate);
break;
default:
break;
}
break;
case TileId::RailTurnoutLeftCurved:
setTurnoutPen();
drawCurve45(r, rotate);
drawCurve90(r, rotate);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawCurve45(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Left:
drawCurve90(turnoutStateRect(r), rotate);
break;
default:
break;
}
break;
case TileId::RailTurnoutRight45:
setTurnoutPen();
drawStraight(r, rotate);
drawCurve45(r, rotate + TileRotate::Deg225);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Right:
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
break;
default:
break;
}
break;
case TileId::RailTurnoutRight90:
setTurnoutPen();
drawStraight(r, rotate);
drawCurve90(r, rotate + TileRotate::Deg270);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Right:
drawCurve90(turnoutStateRect(r), rotate + TileRotate::Deg270);
break;
default:
break;
}
break;
case TileId::RailTurnoutRightCurved:
setTurnoutPen();
drawCurve45(r, rotate + TileRotate::Deg225);
drawCurve90(r, rotate + TileRotate::Deg270);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
break;
case TurnoutPosition::Right:
drawCurve90(turnoutStateRect(r), rotate + TileRotate::Deg270);
break;
default:
break;
}
break;
case TileId::RailTurnoutWye:
setTurnoutPen();
drawCurve45(r, rotate);
drawCurve45(r, rotate + TileRotate::Deg225);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Left:
drawCurve45(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Right:
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
break;
default:
break;
}
break;
case TileId::RailTurnout3Way:
setTurnoutPen();
drawStraight(r, rotate);
drawCurve45(r, rotate);
drawCurve45(r, rotate + TileRotate::Deg225);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Straight:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Left:
drawCurve45(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Right:
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
break;
default:
break;
}
drawTurnoutStandard(id, r, rotate, reservedPosition, position);
break;
case TileId::RailTurnoutSingleSlip:
setTurnoutPen();
drawStraight(r, rotate);
drawStraight(r, rotate - TileRotate::Deg45);
drawCurve45(r, rotate);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Crossed:
drawStraight(turnoutStateRect(r), rotate);
drawStraight(turnoutStateRect(r), rotate - TileRotate::Deg45);
break;
case TurnoutPosition::Diverged:
drawCurve45(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::DoubleSlipStraightA:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::DoubleSlipStraightB:
drawStraight(turnoutStateRect(r), rotate - TileRotate::Deg45);
break;
default:
break;
}
break;
case TileId::RailTurnoutDoubleSlip:
setTurnoutPen();
drawStraight(r, rotate);
drawStraight(r, rotate - TileRotate::Deg45);
drawCurve45(r, rotate);
drawCurve45(r, rotate + TileRotate::Deg180);
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Left:
drawCurve45(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::Right:
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg180);
break;
case TurnoutPosition::Crossed:
drawStraight(turnoutStateRect(r), rotate);
drawStraight(turnoutStateRect(r), rotate - TileRotate::Deg45);
break;
case TurnoutPosition::Diverged:
drawCurve45(turnoutStateRect(r), rotate);
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg180);
break;
case TurnoutPosition::DoubleSlipStraightA:
drawStraight(turnoutStateRect(r), rotate);
break;
case TurnoutPosition::DoubleSlipStraightB:
drawStraight(turnoutStateRect(r), rotate - TileRotate::Deg45);
break;
default:
break;
}
drawTurnoutSlip(id, r, rotate, reservedPosition, position);
break;
default:
@ -541,19 +391,19 @@ void TilePainter::drawTurnout(TileId id, const QRectF& r, TileRotate rotate, Tur
}
}
void TilePainter::drawSignal(TileId id, const QRectF& r, TileRotate rotate, SignalAspect aspect)
void TilePainter::drawSignal(TileId id, const QRectF& r, TileRotate rotate, bool isReserved, SignalAspect aspect)
{
switch(id)
{
case TileId::RailSignal2Aspect:
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
drawSignalDirection(r, rotate);
drawSignal2Aspect(r, rotate, aspect);
break;
case TileId::RailSignal3Aspect:
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
drawSignalDirection(r, rotate);
drawSignal3Aspect(r, rotate, aspect);
@ -565,12 +415,12 @@ void TilePainter::drawSignal(TileId id, const QRectF& r, TileRotate rotate, Sign
}
}
void TilePainter::drawBlock(TileId id, const QRectF& r, TileRotate rotate, const ObjectPtr& blockTile)
void TilePainter::drawBlock(TileId id, const QRectF& r, TileRotate rotate, bool isReservedA, bool isReservedB, const ObjectPtr& blockTile)
{
switch(id)
{
case TileId::RailBlock:
drawRailBlock(r, rotate, blockTile);
drawRailBlock(r, rotate, isReservedA, isReservedB, blockTile);
break;
default:
@ -922,6 +772,302 @@ void TilePainter::drawLED(const QRectF& r, const QColor& color, const QColor& bo
m_painter.drawEllipse(r);
}
void TilePainter::drawTurnoutStandard(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition, TurnoutPosition position)
{
const bool hasLeft90 =
id == TileId::RailTurnoutLeft90 ||
id == TileId::RailTurnoutLeftCurved;
const bool hasLeft =
hasLeft90 ||
id == TileId::RailTurnoutLeft45 ||
id == TileId::RailTurnoutWye ||
id == TileId::RailTurnout3Way;
const bool hasStraight =
id == TileId::RailTurnoutLeft45 ||
id == TileId::RailTurnoutLeft90 ||
id == TileId::RailTurnoutLeftCurved ||
id == TileId::RailTurnoutRight45 ||
id == TileId::RailTurnoutRight90 ||
id == TileId::RailTurnoutRightCurved ||
id == TileId::RailTurnout3Way;
const bool hasRight90 =
id == TileId::RailTurnoutRight90 ||
id == TileId::RailTurnoutRightCurved;
const bool hasRight =
hasRight90 ||
id == TileId::RailTurnoutRight45 ||
id == TileId::RailTurnoutWye ||
id == TileId::RailTurnout3Way;
setTurnoutPen();
if(hasLeft && (m_turnoutDrawState || position != TurnoutPosition::Left) && reservedPosition != TurnoutPosition::Left)
{
if(hasLeft90)
{
drawCurve90(r, rotate);
}
else
{
drawCurve45(r, rotate);
}
}
if(hasStraight && (m_turnoutDrawState || position != TurnoutPosition::Straight) && reservedPosition != TurnoutPosition::Straight)
{
if(id == TileId::RailTurnoutLeftCurved)
{
drawCurve45(r, rotate);
}
else if(id == TileId::RailTurnoutRightCurved)
{
drawCurve45(r, rotate + TileRotate::Deg225);
}
else
{
drawStraight(r, rotate);
}
}
if(hasRight && (m_turnoutDrawState || position != TurnoutPosition::Right) && reservedPosition != TurnoutPosition::Right)
{
if(hasRight90)
{
drawCurve90(r, rotate + TileRotate::Deg270);
}
else
{
drawCurve45(r, rotate + TileRotate::Deg225);
}
}
if(reservedPosition != TurnoutPosition::Unknown)
{
m_painter.setPen(position == reservedPosition ? m_trackReservedPen : m_trackReservedDisabledPen);
switch(reservedPosition)
{
case TurnoutPosition::Left:
if(hasLeft90)
{
drawCurve90(r, rotate);
}
else
{
drawCurve45(r, rotate);
}
break;
case TurnoutPosition::Straight:
if(id == TileId::RailTurnoutLeftCurved)
{
drawCurve45(r, rotate);
}
else if(id == TileId::RailTurnoutRightCurved)
{
drawCurve45(r, rotate + TileRotate::Deg225);
}
else
{
drawStraight(r, rotate);
}
break;
case TurnoutPosition::Right:
if(hasRight90)
{
drawCurve90(r, rotate + TileRotate::Deg270);
}
else
{
drawCurve45(r, rotate + TileRotate::Deg225);
}
break;
default:
break;
}
}
if(m_turnoutDrawState || position != reservedPosition)
{
setTurnoutStatePen();
switch(position)
{
case TurnoutPosition::Left:
if(hasLeft90)
{
drawCurve90(turnoutStateRect(r), rotate);
}
else
{
drawCurve45(turnoutStateRect(r), rotate);
}
break;
case TurnoutPosition::Straight:
if(id == TileId::RailTurnoutLeftCurved)
{
drawCurve45(turnoutStateRect(r), rotate);
}
else if(id == TileId::RailTurnoutRightCurved)
{
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
}
else
{
drawStraight(turnoutStateRect(r), rotate);
}
break;
case TurnoutPosition::Right:
if(hasRight90)
{
drawCurve90(turnoutStateRect(r), rotate + TileRotate::Deg270);
}
else
{
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg225);
}
break;
default:
break;
}
}
}
void TilePainter::drawTurnoutSlip(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition, TurnoutPosition position)
{
// Double: Single:
// C C
// |\ |
// B --+-- D B --+-- D
// \| \|
// A A
const bool isDoubleSlip = id == TileId::RailTurnoutDoubleSlip;
const bool positionAB = position == TurnoutPosition::Left || position == TurnoutPosition::Diverged;
const bool positionAC = position == TurnoutPosition::DoubleSlipStraightA || position == TurnoutPosition::Crossed;
const bool positionBD = position == TurnoutPosition::DoubleSlipStraightB || position == TurnoutPosition::Crossed;
const bool positionCD = isDoubleSlip && (position == TurnoutPosition::Right || position == TurnoutPosition::Diverged);
const bool reservedPositionAB = reservedPosition == TurnoutPosition::Left || reservedPosition == TurnoutPosition::Diverged;
const bool reservedPositionAC = reservedPosition == TurnoutPosition::DoubleSlipStraightA || reservedPosition == TurnoutPosition::Crossed;
const bool reservedPositionBD = reservedPosition == TurnoutPosition::DoubleSlipStraightB || reservedPosition == TurnoutPosition::Crossed;
const bool reservedPositionCD = isDoubleSlip && (reservedPosition == TurnoutPosition::Right || reservedPosition == TurnoutPosition::Diverged);
setTurnoutPen();
if((m_turnoutDrawState || !positionAB) && !reservedPositionAB)
{
drawCurve45(r, rotate);
}
if((m_turnoutDrawState || !positionAC) && !reservedPositionAC)
{
drawStraight(r, rotate);
}
if((m_turnoutDrawState || !positionBD) && !reservedPositionBD)
{
drawStraight(r, rotate - TileRotate::Deg45);
}
if(isDoubleSlip && (m_turnoutDrawState || !positionCD) && !reservedPositionCD)
{
drawCurve45(r, rotate + TileRotate::Deg180);
}
if(!m_turnoutDrawState)
{
setTrackPen();
if(position == TurnoutPosition::Crossed)
{
if(!reservedPositionAC)
{
drawStraight(r, rotate);
}
if(!reservedPositionBD)
{
drawStraight(r, rotate - TileRotate::Deg45);
}
}
else if(position == TurnoutPosition::Diverged)
{
if(!reservedPositionAB)
{
drawCurve45(r, rotate);
}
if(isDoubleSlip && !reservedPositionCD)
{
drawCurve45(r, rotate + TileRotate::Deg180);
}
}
}
if(reservedPosition != TurnoutPosition::Unknown)
{
if(reservedPositionAB && !positionAB)
{
m_painter.setPen(m_trackReservedDisabledPen);
drawCurve45(r, rotate);
}
if(reservedPositionAC && !positionAC)
{
m_painter.setPen(m_trackReservedDisabledPen);
drawStraight(r, rotate);
}
if(reservedPositionBD && !positionBD)
{
m_painter.setPen(m_trackReservedDisabledPen);
drawStraight(r, rotate - TileRotate::Deg45);
}
if(reservedPositionCD && !positionCD)
{
m_painter.setPen(m_trackReservedDisabledPen);
drawCurve45(r, rotate + TileRotate::Deg180);
}
if(reservedPositionAB && positionAB)
{
m_painter.setPen(m_trackReservedPen);
drawCurve45(r, rotate);
}
if(reservedPositionAC && positionAC)
{
m_painter.setPen(m_trackReservedPen);
drawStraight(r, rotate);
}
if(reservedPositionBD && positionBD)
{
m_painter.setPen(m_trackReservedPen);
drawStraight(r, rotate - TileRotate::Deg45);
}
if(reservedPositionCD && positionCD)
{
m_painter.setPen(m_trackReservedPen);
drawCurve45(r, rotate + TileRotate::Deg180);
}
}
setTurnoutStatePen();
if(positionAB && (m_turnoutDrawState || reservedPositionAC || reservedPositionBD || (!reservedPositionAB && position != TurnoutPosition::Diverged)))
{
drawCurve45(turnoutStateRect(r), rotate);
}
if(positionAC && (m_turnoutDrawState || reservedPositionAB || reservedPositionCD || (!reservedPositionAC && position != TurnoutPosition::Crossed)))
{
drawStraight(turnoutStateRect(r), rotate);
}
if(positionBD && (m_turnoutDrawState || reservedPositionAB || reservedPositionCD || (!reservedPositionBD && position != TurnoutPosition::Crossed)))
{
drawStraight(turnoutStateRect(r), rotate - TileRotate::Deg45);
}
if(positionCD && (m_turnoutDrawState || reservedPositionAC || reservedPositionBD || (!reservedPositionCD && position != TurnoutPosition::Diverged)))
{
drawCurve45(turnoutStateRect(r), rotate + TileRotate::Deg180);
}
}
void TilePainter::drawSignal3Aspect(QRectF r, TileRotate rotate, SignalAspect aspect)
{
m_painter.save();
@ -999,7 +1145,7 @@ void TilePainter::drawSignalDirection(QRectF r, TileRotate rotate)
m_painter.restore();
}
void TilePainter::drawRailBlock(const QRectF& r, TileRotate rotate, const ObjectPtr& blockTile)
void TilePainter::drawRailBlock(const QRectF& r, TileRotate rotate, bool isReservedA, bool isReservedB, const ObjectPtr& blockTile)
{
const BlockState state = blockTile ? blockTile->getPropertyValueEnum<BlockState>("state", BlockState::Unknown) : BlockState::Unknown;
std::vector<SensorState> subStates;
@ -1052,11 +1198,13 @@ void TilePainter::drawRailBlock(const QRectF& r, TileRotate rotate, const Object
label = blockTile->getPropertyValueString("name");
}
setTrackPen();
if(rotate == TileRotate::Deg0)
{
m_painter.drawLine(topCenter(r), bottomCenter(r));
setTrackPen(isReservedA);
m_painter.drawLine(topCenter(r), r.center());
setTrackPen(isReservedB);
m_painter.drawLine(r.center(), bottomCenter(r));
setBlockStateBrush(state);
m_painter.setPen(m_blockPen);
const qreal m = 0.5 + qFloor(r.width() / 10);
@ -1089,7 +1237,11 @@ void TilePainter::drawRailBlock(const QRectF& r, TileRotate rotate, const Object
}
else if(rotate == TileRotate::Deg90)
{
m_painter.drawLine(centerLeft(r), centerRight(r));
setTrackPen(isReservedA);
m_painter.drawLine(centerLeft(r), r.center());
setTrackPen(isReservedB);
m_painter.drawLine(r.center(), centerRight(r));
setBlockStateBrush(state);
m_painter.setPen(m_blockPen);
const qreal m = 0.5 + qFloor(r.height() / 10);
@ -1121,9 +1273,9 @@ void TilePainter::drawRailBlock(const QRectF& r, TileRotate rotate, const Object
assert(false);
}
void TilePainter::drawRailDecoupler(const QRectF& r, TileRotate rotate, DecouplerState state)
void TilePainter::drawRailDecoupler(const QRectF& r, TileRotate rotate, bool isReserved, DecouplerState state)
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
m_painter.save();
@ -1137,9 +1289,9 @@ void TilePainter::drawRailDecoupler(const QRectF& r, TileRotate rotate, Decouple
m_painter.restore();
}
void TilePainter::drawRailNX(const QRectF& r, TileRotate rotate, bool pressed)
void TilePainter::drawRailNX(const QRectF& r, TileRotate rotate, bool isReserved, bool pressed)
{
setTrackPen();
setTrackPen(isReserved);
drawStraight(r, rotate);
drawPushButton(r, pressed ? Color::White : Color::Blue);
}

Datei anzeigen

@ -29,6 +29,7 @@
#include <traintastic/board/tileid.hpp>
#include <traintastic/enum/tilerotate.hpp>
#include <traintastic/enum/blockstate.hpp>
#include <traintastic/enum/crossstate.hpp>
#include <traintastic/enum/decouplerstate.hpp>
#include <traintastic/enum/directioncontrolstate.hpp>
#include <traintastic/enum/sensorstate.hpp>
@ -55,6 +56,8 @@ class TilePainter
const QPen m_blockPen;
const QPen m_trackPen;
const QPen m_trackDisabledPen;
const QPen m_trackReservedPen;
const QPen m_trackReservedDisabledPen;
const QPen m_trackErasePen;
const QPen m_turnoutPen;
const QPen m_turnoutStatePen;
@ -62,6 +65,7 @@ class TilePainter
QPainter& m_painter;
inline void setTrackPen() { m_painter.setPen(m_trackPen); }
inline void setTrackPen(bool isReserved) { m_painter.setPen(isReserved ? m_trackReservedPen : m_trackPen); }
inline void setTrackDisabledPen() { m_painter.setPen(m_trackDisabledPen); }
inline void setTrackErasePen() { m_painter.setPen(m_trackErasePen); }
inline void setTurnoutPen() { m_painter.setPen(m_turnoutDrawState ? m_trackPen : m_trackDisabledPen); }
@ -81,27 +85,32 @@ class TilePainter
void drawTriangle(const QRectF& r);
void drawLED(const QRectF& r, const QColor& color, const QColor& borderColor);
void drawTurnoutStandard(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition = TurnoutPosition::Unknown, TurnoutPosition position = TurnoutPosition::Unknown);
void drawTurnoutSlip(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition = TurnoutPosition::Unknown, TurnoutPosition position = TurnoutPosition::Unknown);
void drawSignal2Aspect(QRectF r, TileRotate rotate, SignalAspect aspect);
void drawSignal3Aspect(QRectF r, TileRotate rotate, SignalAspect aspect);
void drawSignalDirection(QRectF r, TileRotate rotate);
void drawRailBlock(const QRectF& r, TileRotate rotate, const ObjectPtr& blockTile = {});
void drawRailBlock(const QRectF& r, TileRotate rotate, bool isReservedA = false, bool isReservedB = false, const ObjectPtr& blockTile = {});
public:
TilePainter(QPainter& painter, int tileSize, const BoardColorScheme& colorScheme);
void draw(TileId id, const QRectF& r, TileRotate rotate);
void drawSensor(TileId id, const QRectF& r, TileRotate rotate, SensorState state = SensorState::Unknown);
void drawDirectionControl(TileId id, const QRectF& r, TileRotate rotate, DirectionControlState state = DirectionControlState::Both);
void drawTurnout(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition position = TurnoutPosition::Unknown);
void drawSignal(TileId id, const QRectF& r, TileRotate rotate, SignalAspect aspect = SignalAspect::Unknown);
void drawBlock(TileId id, const QRectF& r, TileRotate rotate, const ObjectPtr& blockTile = {});
void draw(TileId id, const QRectF& r, TileRotate rotate, bool isReserved = false);
void drawBridge(TileId id, const QRectF& r, TileRotate rotate, bool isReservedAC = false, bool isReservedBD = false);
void drawCross(TileId id, const QRectF& r, TileRotate rotate, CrossState reservedState = CrossState::Unset);
void drawSensor(TileId id, const QRectF& r, TileRotate rotate, bool isReserved = false, SensorState state = SensorState::Unknown);
void drawDirectionControl(TileId id, const QRectF& r, TileRotate rotate, bool isReserved = false, DirectionControlState state = DirectionControlState::Both);
void drawTurnout(TileId id, const QRectF& r, TileRotate rotate, TurnoutPosition reservedPosition = TurnoutPosition::Unknown, TurnoutPosition position = TurnoutPosition::Unknown);
void drawSignal(TileId id, const QRectF& r, TileRotate rotate, bool isReserved = false, SignalAspect aspect = SignalAspect::Unknown);
void drawBlock(TileId id, const QRectF& r, TileRotate rotate, bool isReservedA = false, bool isReservedB = false, const ObjectPtr& blockTile = {});
void drawPushButton(const QRectF& r, Color color = Color::Yellow);
void drawRailDecoupler(const QRectF& r, TileRotate rotate, DecouplerState active = DecouplerState::Deactivated);
void drawRailDecoupler(const QRectF& r, TileRotate rotate, bool isReserved = false, DecouplerState active = DecouplerState::Deactivated);
void drawRailNX(const QRectF& r, TileRotate rotate, bool pressed = false);
void drawRailNX(const QRectF& r, TileRotate rotate, bool isReserved = false, bool pressed = false);
};
#endif

Datei anzeigen

@ -9,6 +9,19 @@
}
]
},
"on_train_reserved": {
"parameters": [
{
"name": "train"
},
{
"name": "block"
},
{
"name": "direction"
}
]
},
"on_train_removed": {
"parameters": [
{

Datei anzeigen

@ -1365,7 +1365,7 @@
},
{
"term": "object.blockrailtile.on_train_removed.parameter.block:description",
"definition": "The block that the train is assigned to."
"definition": "The block that the train is removed from."
},
{
"term": "object.clock.freeze:description",
@ -1646,5 +1646,41 @@
{
"term": "object.identificationlist:title",
"definition": "Identification list"
},
{
"term": "enum.block_train_direction:title",
"definition": "Block train direction"
},
{
"term": "enum.block_train_direction:description",
"definition": "Train direction from the block perspective."
},
{
"term": "enum.block_train_direction.towards_a:description",
"definition": "Towards the west for horizontal blocks, towards the south for vertical blocks."
},
{
"term": "enum.block_train_direction.towards_b:description",
"definition": "Towards the east for horizontal blocks, towards the north for vertical blocks."
},
{
"term": "enum.block_train_direction.unknown:description",
"definition": "Unknown or invalid direction."
},
{
"term": "object.blockrailtile.on_train_reserved:description",
"definition": "Fired when a {ref:object.train} reserves the block."
},
{
"term": "object.blockrailtile.on_train_reserved.parameter.train:description",
"definition": "{ref:object.train} that is reserved the block."
},
{
"term": "object.blockrailtile.on_train_reserved.parameter.block:description",
"definition": "The block that is reserved."
},
{
"term": "object.blockrailtile.on_train_reserved.parameter.direction:description",
"definition": "Train direction from the block perspective, a {ref:enum.block_train_direction} value."
}
]

Datei anzeigen

@ -26,6 +26,7 @@
#include "node.hpp"
#include "link.hpp"
#include "../tile/rail/blockrailtile.hpp"
#include "../tile/rail/bridgerailtile.hpp"
#include "../tile/rail/crossrailtile.hpp"
#include "../tile/rail/directioncontrolrailtile.hpp"
#include "../tile/rail/signal/signalrailtile.hpp"
@ -33,8 +34,9 @@
#include "../tile/rail/linkrailtile.hpp"
#include "../tile/rail/nxbuttonrailtile.hpp"
#include "../../core/objectproperty.tpp"
#include "../../enum/bridgepath.hpp"
std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBlock)
std::vector<std::shared_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBlock)
{
const auto& node = startBlock.node()->get();
const auto& linkA = node.getLink(0);
@ -47,21 +49,21 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
struct Position
{
std::unique_ptr<BlockPath> path;
std::shared_ptr<BlockPath> path;
const Node* node;
const Link* link;
};
std::vector<std::unique_ptr<BlockPath>> paths;
std::vector<std::shared_ptr<BlockPath>> paths;
std::queue<Position> todo;
if(linkA)
{
todo.emplace(Position{std::make_unique<BlockPath>(startBlock, Side::A), &node, linkA.get()});
todo.emplace(Position{std::make_shared<BlockPath>(startBlock, BlockSide::A), &node, linkA.get()});
}
if(linkB)
{
todo.emplace(Position{std::make_unique<BlockPath>(startBlock, Side::B), &node, linkB.get()});
todo.emplace(Position{std::make_shared<BlockPath>(startBlock, BlockSide::B), &node, linkB.get()});
}
while(!todo.empty())
@ -72,6 +74,12 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
todo.pop(); // drop it, dead end
continue;
}
for(const auto& tile : current.link->tiles()) // add passive tiles to reserve
{
current.path->m_tiles.emplace_back(std::static_pointer_cast<RailTile>(tile));
}
assert(current.node);
const auto& nextNode = current.link->getNext(*current.node);
auto& tile = nextNode.tile();
@ -80,10 +88,6 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
{
case TileId::RailBlock:
{
// temp dummy use to fix warnings:
(void)current.path->m_fromBlock;
(void)current.path->m_fromSide;
if(current.node->tile().tileId() == TileId::RailNXButton)
{
current.path->m_nxButtonTo = current.node->tile().shared_ptr<NXButtonRailTile>();
@ -91,7 +95,7 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
auto& block = static_cast<BlockRailTile&>(tile);
current.path->m_toBlock = block.shared_ptr<BlockRailTile>();
current.path->m_toSide = nextNode.getLink(0).get() == current.link ? Side::A : Side::B;
current.path->m_toSide = nextNode.getLink(0).get() == current.link ? BlockSide::A : BlockSide::B;
paths.emplace_back(std::move(current.path));
todo.pop(); // complete
break;
@ -115,7 +119,7 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
{
for(size_t i = 1; i < links.size(); ++i)
{
auto path = std::make_unique<BlockPath>(*current.path); // "fork" path
auto path = std::make_shared<BlockPath>(*current.path); // "fork" path
path->m_turnouts.emplace_back(turnout->shared_ptr<TurnoutRailTile>(), links[i].turnoutPosition);
todo.emplace(Position{std::move(path), &nextNode, nextNode.getLink(links[i].linkIndex).get()});
}
@ -134,6 +138,7 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
// 0
if(nextNode.getLink(0).get() == current.link) // 0 -> 1 = allowed
{
current.path->m_tiles.emplace_back(tile.shared_ptr<RailTile>());
current.node = &nextNode;
current.link = nextNode.getLink(1).get();
}
@ -170,6 +175,7 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
{
current.node = &nextNode;
current.link = nextNode.getLink((i + 2) % 4).get(); // opposite
current.path->m_bridges.emplace_back(tile.shared_ptr<BridgeRailTile>(), i % 2 == 0 ? BridgePath::AC : BridgePath::BD);
break;
}
}
@ -199,6 +205,8 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
auto& linkTile = static_cast<LinkRailTile&>(tile);
if(linkTile.link) // is connected to another link
{
current.path->m_tiles.emplace_back(linkTile.shared_ptr<RailTile>());
current.path->m_tiles.emplace_back(linkTile.link->shared_ptr<RailTile>());
assert(linkTile.link->node());
auto& linkNode = linkTile.link->node()->get();
current.node = &linkNode;
@ -221,10 +229,12 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
else // 1 -> 0 = backside of signal, just pass
{
current.link = nextNode.getLink(0).get();
current.path->m_tiles.emplace_back(tile.shared_ptr<RailTile>());
}
break;
case TileId::RailDecoupler:
current.path->m_tiles.emplace_back(tile.shared_ptr<RailTile>());
current.node = &nextNode;
current.link = otherLink(nextNode, *current.link).get();
break;
@ -232,7 +242,11 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
case TileId::RailNXButton:
if(&current.node->tile() == &startBlock)
{
current.path->m_nxButtonFrom = nextNode.tile().shared_ptr<NXButtonRailTile>();
current.path->m_nxButtonFrom = tile.shared_ptr<NXButtonRailTile>();
}
else
{
current.path->m_tiles.emplace_back(tile.shared_ptr<RailTile>());
}
current.node = &nextNode;
current.link = otherLink(nextNode, *current.link).get();
@ -248,10 +262,10 @@ std::vector<std::unique_ptr<BlockPath>> BlockPath::find(BlockRailTile& startBloc
}
BlockPath::BlockPath(BlockRailTile& block, Side side)
BlockPath::BlockPath(BlockRailTile& block, BlockSide side)
: m_fromBlock{block}
, m_fromSide{side}
, m_toSide{static_cast<Side>(-1)}
, m_toSide{static_cast<BlockSide>(-1)}
{
}
@ -264,3 +278,138 @@ std::shared_ptr<NXButtonRailTile> BlockPath::nxButtonTo() const
{
return m_nxButtonTo.lock();
}
bool BlockPath::reserve(const std::shared_ptr<Train>& train, bool dryRun)
{
if(!dryRun && !reserve(train, true)) // dry run first, to make sure it will succeed (else we need rollback support)
{
return false;
}
if(!m_fromBlock.reserve(train, m_fromSide, dryRun))
{
assert(dryRun);
return false;
}
if(auto toBlock = m_toBlock.lock()) /*[[likely]]*/
{
if(!toBlock->reserve(train, m_toSide, dryRun))
{
assert(dryRun);
return false;
}
}
else
{
return false;
}
for(const auto& [turnoutWeak, position] : m_turnouts)
{
if(auto turnout = turnoutWeak.lock())
{
if(!turnout->reserve(position, dryRun))
{
assert(dryRun);
return false;
}
}
else /*[[unlikely]]*/
{
assert(dryRun);
return false;
}
}
for(const auto& [directionControlWeak, state] : m_directionControls)
{
if(auto directionControl = directionControlWeak.lock())
{
if(!directionControl->reserve(state, dryRun))
{
assert(dryRun);
return false;
}
}
else /*[[unlikely]]*/
{
assert(dryRun);
return false;
}
}
for(const auto& [crossWeak, state] : m_crossings)
{
if(auto cross = crossWeak.lock())
{
if(!cross->reserve(state, dryRun))
{
assert(dryRun);
return false;
}
}
else /*[[unlikely]]*/
{
assert(dryRun);
return false;
}
}
for(const auto& [bridgeWeak, path] : m_bridges)
{
if(auto bridge = bridgeWeak.lock())
{
if(!bridge->reserve(path, dryRun))
{
assert(dryRun);
return false;
}
}
else /*[[unlikely]]*/
{
assert(dryRun);
return false;
}
}
for(const auto& signalWeak : m_signals)
{
if(auto signal = signalWeak.lock())
{
if(!signal->reserve(SignalRailTile::Pass{}, dryRun))
{
assert(dryRun);
return false;
}
}
else /*[[unlikely]]*/
{
assert(dryRun);
return false;
}
}
if(!dryRun)
{
for(const auto& tileWeak : m_tiles)
{
if(auto tile = tileWeak.lock()) /*[[likely]]*/
{
static_cast<RailTile&>(*tile).reserve();
}
}
if(auto nxButton = m_nxButtonFrom.lock())
{
nxButton->reserve();
}
if(auto nxButton = m_nxButtonTo.lock())
{
nxButton->reserve();
}
}
return true;
}

Datei anzeigen

@ -29,8 +29,12 @@
#include <array>
#include <vector>
#include <utility>
#include "../../enum/blockside.hpp"
class RailTile;
class BlockRailTile;
class BridgeRailTile;
enum class BridgePath : uint8_t;
class CrossRailTile;
enum class CrossState : uint8_t;
class DirectionControlRailTile;
@ -39,35 +43,31 @@ class SignalRailTile;
class NXButtonRailTile;
class Node;
class Link;
class Train;
/**
* \brief A path between two blocks
*/
class BlockPath : public Path
{
public:
enum class Side
{
A = 0,
B = 1,
};
private:
BlockRailTile const& m_fromBlock;
const Side m_fromSide;
BlockRailTile& m_fromBlock;
const BlockSide m_fromSide;
std::weak_ptr<BlockRailTile> m_toBlock;
Side m_toSide;
BlockSide m_toSide;
std::vector<std::weak_ptr<RailTile>> m_tiles; //!< passive tiles to reserve
std::vector<std::pair<std::weak_ptr<TurnoutRailTile>, TurnoutPosition>> m_turnouts; //!< required turnout positions for the path
std::vector<std::pair<std::weak_ptr<DirectionControlRailTile>, DirectionControlState>> m_directionControls; //!< required direction control states for the path
std::vector<std::pair<std::weak_ptr<CrossRailTile>, CrossState>> m_crossings; //!< required crossing states for the path
std::vector<std::pair<std::weak_ptr<BridgeRailTile>, BridgePath>> m_bridges; //!< bridges to reserve
std::vector<std::weak_ptr<SignalRailTile>> m_signals; //!< signals in path
std::weak_ptr<NXButtonRailTile> m_nxButtonFrom;
std::weak_ptr<NXButtonRailTile> m_nxButtonTo;
public:
static std::vector<std::unique_ptr<BlockPath>> find(BlockRailTile& block);
static std::vector<std::shared_ptr<BlockPath>> find(BlockRailTile& block);
BlockPath(BlockRailTile& block, Side side);
BlockPath(BlockRailTile& block, BlockSide side);
bool hasNXButtons() const
{
@ -79,13 +79,25 @@ class BlockPath : public Path
return m_fromBlock;
}
BlockSide fromSide() const
{
return m_fromSide;
}
std::shared_ptr<BlockRailTile> toBlock() const
{
return m_toBlock.lock();
}
BlockSide toSide() const
{
return m_toSide;
}
std::shared_ptr<NXButtonRailTile> nxButtonFrom() const;
std::shared_ptr<NXButtonRailTile> nxButtonTo() const;
bool reserve(const std::shared_ptr<Train>& train, bool dryRun = false);
};
#endif

Datei anzeigen

@ -27,6 +27,7 @@
#include "../../core/method.tpp"
#include "../../core/objectproperty.tpp"
#include "../../log/log.hpp"
#include "../../train/trainblockstatus.hpp"
#include "../../world/getworld.hpp"
NXManager::NXManager(Object& parent_, std::string_view parentPropertyName)
@ -91,14 +92,30 @@ void NXManager::released(NXButtonRailTile& button)
bool NXManager::selectPath(const NXButtonRailTile& from, const NXButtonRailTile& to)
{
for(const auto& path : from.block->paths())
for(auto& path : from.block->paths())
{
if(path->nxButtonTo().get() == &to && path->nxButtonFrom().get() == &from)
{
LOG_DEBUG("Path selected:", path->fromBlock().name.value(), "->", path->toBlock()->name.value());
LOG_DEBUG("Path found:", path->fromBlock().name.value(), "->", path->toBlock()->name.value());
if(from.block->trains.empty())
{
continue; // no train in from block
}
const auto& status = path->fromSide() == BlockSide::A ? from.block->trains.front() : from.block->trains.back();
if(!status->train)
{
continue; // no train assigned in from block
}
if(!path->reserve(status->train.value()))
{
continue; // can't reserve path
}
return true;
}
}
return false;
return false; // no path found
}

Datei anzeigen

@ -159,6 +159,7 @@ BlockRailTile::BlockRailTile(World& world, std::string_view _id) :
}
}}
, onTrainAssigned{*this, "on_train_assigned", EventFlags::Scriptable}
, onTrainReserved{*this, "on_train_reserved", EventFlags::Scriptable}
, onTrainRemoved{*this, "on_train_removed", EventFlags::Scriptable}
{
inputMap.setValueInternal(std::make_shared<BlockInputMap>(*this, inputMap.name()));
@ -196,6 +197,7 @@ BlockRailTile::BlockRailTile(World& world, std::string_view _id) :
m_interfaceItems.add(flipTrain);
m_interfaceItems.add(onTrainAssigned);
m_interfaceItems.add(onTrainReserved);
m_interfaceItems.add(onTrainRemoved);
updateHeightWidthMax();
@ -269,6 +271,56 @@ void BlockRailTile::identificationEvent(BlockInputMapItem& /*item*/, Identificat
}
}
bool BlockRailTile::reserve(const std::shared_ptr<Train>& train, BlockSide side, bool dryRun)
{
const uint8_t mask = 1 << static_cast<uint8_t>(side);
if(state == BlockState::Unknown)
{
return false; // can't reserve block with unknown state
}
if((reservedState() & mask))
{
return false; // already reserved
}
if(state != BlockState::Free)
{
if(trains.empty())
{
return false; // not free block, but no train
}
const auto& status = (side == BlockSide::A) ? *trains.front() : *trains.back();
if(!status.train || status.train.value() != train)
{
return false; // no train or other train assigned to block
}
if((side == BlockSide::A && status.direction != BlockTrainDirection::TowardsA) ||
(side == BlockSide::B && status.direction != BlockTrainDirection::TowardsB))
{
//! \todo allow direction change, add block property, automatic for dead ends
return false; // invalid train direction
}
}
if(!dryRun)
{
RailTile::reserve(reservedState() | mask);
if(state == BlockState::Free)
{
const auto direction = side == BlockSide::A ? BlockTrainDirection::TowardsB : BlockTrainDirection::TowardsA;
trains.appendInternal(TrainBlockStatus::create(*this, *train, direction));
fireEvent<const std::shared_ptr<Train>&, const std::shared_ptr<BlockRailTile>&>(onTrainReserved, train, shared_ptr<BlockRailTile>(), direction);
}
updateState();
}
return true;
}
void BlockRailTile::updateState()
{
if(!inputMap->items.empty())

Datei anzeigen

@ -24,10 +24,12 @@
#define TRAINTASTIC_SERVER_BOARD_TILE_RAIL_BLOCKRAILTILE_HPP
#include "railtile.hpp"
#include <traintastic/enum/blocktraindirection.hpp>
#include "../../map/node.hpp"
#include "../../../core/method.hpp"
#include "../../../core/objectproperty.hpp"
#include "../../../core/vectorproperty.hpp"
#include "../../../enum/blockside.hpp"
#include "../../../enum/blockstate.hpp"
#include "../../../hardware/input/map/blockinputmap.hpp"
@ -44,7 +46,7 @@ class BlockRailTile : public RailTile
private:
Node m_node;
std::vector<std::unique_ptr<BlockPath>> m_paths;
std::vector<std::shared_ptr<BlockPath>> m_paths;
void updateHeightWidthMax();
@ -71,6 +73,7 @@ class BlockRailTile : public RailTile
Method<void()> removeTrain;
Method<void()> flipTrain;
Event<const std::shared_ptr<Train>&, const std::shared_ptr<BlockRailTile>&> onTrainAssigned;
Event<const std::shared_ptr<Train>&, const std::shared_ptr<BlockRailTile>&, BlockTrainDirection> onTrainReserved;
Event<const std::shared_ptr<Train>&, const std::shared_ptr<BlockRailTile>&> onTrainRemoved;
BlockRailTile(World& world, std::string_view _id);
@ -79,13 +82,15 @@ class BlockRailTile : public RailTile
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
void getConnectors(std::vector<Connector>& connectors) const final;
const std::vector<std::unique_ptr<BlockPath>>& paths() const
const std::vector<std::shared_ptr<BlockPath>>& paths() const
{
return m_paths;
}
void inputItemValueChanged(BlockInputMapItem& item);
void identificationEvent(BlockInputMapItem& item, IdentificationEventType eventType, uint16_t identifier, Direction direction, uint8_t category);
bool reserve(const std::shared_ptr<Train>& train, BlockSide side, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -28,3 +28,20 @@ BridgeRailTile::BridgeRailTile(World& world, std::string_view _id, TileId tileId
{
assert(isRailBridge(tileId_));
}
bool BridgeRailTile::reserve(BridgePath path, bool dryRun)
{
const uint8_t mask = 1 << static_cast<uint8_t>(path);
if((reservedState() & mask))
{
return false; // already reserved
}
if(!dryRun)
{
RailTile::reserve(reservedState() | mask);
}
return true;
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -26,6 +26,8 @@
#include "railtile.hpp"
#include "../../map/node.hpp"
enum class BridgePath : uint8_t;
class BridgeRailTile : public RailTile
{
private:
@ -37,6 +39,8 @@ class BridgeRailTile : public RailTile
public:
std::optional<std::reference_wrapper<const Node>> node() const final { return m_node; }
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
bool reserve(BridgePath path, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,10 +21,28 @@
*/
#include "crossrailtile.hpp"
#include <traintastic/enum/crossstate.hpp>
CrossRailTile::CrossRailTile(World& world, std::string_view _id, TileId tileId_)
: RailTile(world, _id, tileId_)
, m_node{*this, 4}
, m_crossState{CrossState::Unset}
{
assert(isRailCross(tileId_));
}
bool CrossRailTile::reserve(CrossState crossState, bool dryRun)
{
if(m_crossState != CrossState::Unset)
{
return false;
}
if(!dryRun)
{
m_crossState = crossState;
RailTile::reserve(static_cast<uint8_t>(m_crossState));
}
return true;
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -26,10 +26,13 @@
#include "railtile.hpp"
#include "../../map/node.hpp"
enum class CrossState : uint8_t;
class CrossRailTile : public RailTile
{
private:
Node m_node;
CrossState m_crossState; //!< indicates which path is reserved
protected:
CrossRailTile(World& world, std::string_view _id, TileId tileId_);
@ -37,6 +40,8 @@ class CrossRailTile : public RailTile
public:
std::optional<std::reference_wrapper<const Node>> node() const final { return m_node; }
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
bool reserve(CrossState crossState, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -119,6 +119,21 @@ DirectionControlRailTile::DirectionControlRailTile(World& world, std::string_vie
updateStateValues();
}
bool DirectionControlRailTile::reserve(DirectionControlState directionControlState, bool dryRun)
{
if(state != directionControlState && state != DirectionControlState::Both)
{
return false;
}
if(!dryRun)
{
StraightRailTile::reserve();
}
return true;
}
void DirectionControlRailTile::loaded()
{
StraightRailTile::loaded();

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
* Copyright (C) 2022-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -60,6 +60,8 @@ class DirectionControlRailTile final : public StraightRailTile
std::optional<std::reference_wrapper<const Node>> node() const final { return m_node; }
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
bool reserve(DirectionControlState turnoutPosition, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* Copyright (C) 2020,2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,8 +21,25 @@
*/
#include "railtile.hpp"
#include "../../board.hpp"
RailTile::RailTile(World& world, std::string_view _id, TileId tileId) :
Tile(world, _id, tileId)
{
}
void RailTile::reserve(uint8_t state)
{
assert(state != 0);
setReservedState(state);
}
void RailTile::setReservedState(uint8_t value)
{
if(m_reservedState != value)
{
m_reservedState = value;
auto& board = getBoard();
board.tileDataChanged(board, location(), data());
}
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* Copyright (C) 2020,2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -27,8 +27,26 @@
class RailTile : public Tile
{
private:
uint8_t m_reservedState = 0;
void setReservedState(uint8_t value);
protected:
RailTile(World& world, std::string_view _id, TileId tileId);
uint8_t reservedState() const final
{
return m_reservedState;
}
void reserve(uint8_t state);
public:
inline void reserve()
{
reserve(1);
}
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2022 Reinder Feenstra
* Copyright (C) 2020-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -54,6 +54,17 @@ SignalRailTile::SignalRailTile(World& world, std::string_view _id, TileId tileId
SignalRailTile::~SignalRailTile() = default; // default here, so we can use a forward declaration of SignalPath in the header.
bool SignalRailTile::reserve(Pass, bool dryRun)
{
// no conditions yet...
if(!dryRun)
{
RailTile::reserve();
}
return true;
}
void SignalRailTile::worldEvent(WorldState state, WorldEvent event)
{
StraightRailTile::worldEvent(state, event);

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2022 Reinder Feenstra
* Copyright (C) 2020-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -47,6 +47,10 @@ class SignalRailTile : public StraightRailTile
virtual bool doSetAspect(SignalAspect value);
public:
struct Pass
{
};
Property<std::string> name;
Property<SignalAspect> aspect;
ObjectProperty<SignalOutputMap> outputMap;
@ -56,6 +60,8 @@ class SignalRailTile : public StraightRailTile
std::optional<std::reference_wrapper<const Node>> node() const final { return m_node; }
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
bool reserve(Pass, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2022 Reinder Feenstra
* Copyright (C) 2020-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -53,6 +53,24 @@ TurnoutRailTile::TurnoutRailTile(World& world, std::string_view _id, TileId tile
// setPosition is added by sub class
}
bool TurnoutRailTile::reserve(TurnoutPosition turnoutPosition, bool dryRun)
{
if(!isValidPosition(turnoutPosition))
{
return false;
}
if(!dryRun)
{
if(!doSetPosition(turnoutPosition)) /*[[unlikely]]*/
{
return false;
}
RailTile::reserve(static_cast<uint8_t>(turnoutPosition));
}
return true;
}
void TurnoutRailTile::worldEvent(WorldState state, WorldEvent event)
{
RailTile::worldEvent(state, event);
@ -62,12 +80,19 @@ void TurnoutRailTile::worldEvent(WorldState state, WorldEvent event)
Attributes::setEnabled(name, editable);
}
bool TurnoutRailTile::doSetPosition(TurnoutPosition value)
bool TurnoutRailTile::isValidPosition(TurnoutPosition value)
{
const auto* values = setPosition.tryGetValuesAttribute(AttributeName::Values);
assert(values);
if(!values->contains(static_cast<int64_t>(value)))
return values->contains(static_cast<int64_t>(value));
}
bool TurnoutRailTile::doSetPosition(TurnoutPosition value)
{
if(!isValidPosition(value))
{
return false;
}
(*outputMap)[value]->execute();
position.setValueInternal(value);
positionChanged(*this, value);

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2022 Reinder Feenstra
* Copyright (C) 2020-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -42,6 +42,7 @@ class TurnoutRailTile : public RailTile
void worldEvent(WorldState state, WorldEvent event) override;
bool isValidPosition(TurnoutPosition value);
virtual bool doSetPosition(TurnoutPosition value);
public:
@ -54,6 +55,8 @@ class TurnoutRailTile : public RailTile
std::optional<std::reference_wrapper<const Node>> node() const final { return m_node; }
std::optional<std::reference_wrapper<Node>> node() final { return m_node; }
virtual bool reserve(TurnoutPosition turnoutPosition, bool dryRun = false);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2021 Reinder Feenstra
* Copyright (C) 2020-2021,2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -22,6 +22,9 @@
#include "tile.hpp"
#include "../../core/attributes.hpp"
#include "../board.hpp"
#include "../boardlist.hpp"
#include "../../world/world.hpp"
Tile::Tile(World& world, std::string_view _id, TileId tileId)
: IdObject(world, _id)
@ -51,6 +54,19 @@ Tile::Tile(World& world, std::string_view _id, TileId tileId)
m_interfaceItems.add(width);
}
Board& Tile::getBoard()
{
for(const auto& board : *m_world.boards)
{
if(board->getTile(location()).get() == this)
{
return *board;
}
}
assert(false);
abort();
}
bool Tile::resize(uint8_t w, uint8_t h)
{
assert(w >= 1);

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2022 Reinder Feenstra
* Copyright (C) 2020-2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,6 +31,7 @@
#include "../../enum/tilerotate.hpp"
class Node;
class Board;
class Tile : public IdObject
{
@ -42,6 +43,13 @@ class Tile : public IdObject
Tile(World& world, std::string_view _id, TileId tileId);
Board& getBoard();
virtual uint8_t reservedState() const
{
return 0;
}
virtual void boardModified() {}
virtual void setRotate(TileRotate value) { rotate.setValueInternal(value); }
bool resize(uint8_t w, uint8_t h);
@ -57,7 +65,7 @@ class Tile : public IdObject
TileId tileId() const { return m_tileId; }
inline TileLocation location() const { return {x.value(), y.value()}; }
inline TileData data() const { return TileData{m_tileId, rotate, width, height}; }
inline TileData data() const { return TileData{m_tileId, rotate, width, height, reservedState()}; }
virtual std::optional<std::reference_wrapper<const Node>> node() const { return {}; }
virtual std::optional<std::reference_wrapper<Node>> node() { return {}; }

Datei anzeigen

@ -53,6 +53,16 @@ class ObjectVectorProperty : public AbstractObjectVectorProperty
inline const_reverse_iterator rbegin() const { return m_values.rbegin(); }
inline const_reverse_iterator rend() const { return m_values.rend(); }
inline const std::shared_ptr<T>& front() const
{
return m_values.front();
}
inline const std::shared_ptr<T>& back() const
{
return m_values.back();
}
const std::shared_ptr<T>& operator [](size_t index) const
{
return m_values[index];

Datei anzeigen

@ -0,0 +1,34 @@
/**
* server/src/enum/blockside.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_ENUM_BLOCKSIDE_HPP
#define TRAINTASTIC_SERVER_ENUM_BLOCKSIDE_HPP
#include <cstdint>
enum class BlockSide : uint8_t
{
A = 0,
B = 1,
};
#endif

Datei anzeigen

@ -0,0 +1,34 @@
/**
* server/src/enum/bridgepath.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_ENUM_BRIDGEPATH_HPP
#define TRAINTASTIC_SERVER_ENUM_BRIDGEPATH_HPP
#include <cstdint>
enum class BridgePath : uint8_t
{
AC = 0,
BD = 1,
};
#endif

Datei anzeigen

@ -25,6 +25,7 @@
#include <lua.hpp>
#include "enum.hpp"
#include <traintastic/enum/blocktraindirection.hpp>
#include <traintastic/enum/decoderprotocol.hpp>
#include "../../src/enum/direction.hpp"
#include "../../src/enum/directioncontrolstate.hpp"
@ -37,6 +38,7 @@
#include "../../src/enum/worldscale.hpp"
#define LUA_ENUMS \
BlockTrainDirection, \
DecoderProtocol, \
Direction, \
DirectionControlState, \

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020-2021 Reinder Feenstra
* Copyright (C) 2020-2021,2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -33,12 +33,12 @@ struct TileData
uint16_t _header;
uint8_t _size;
uint8_t _reserved;
uint8_t state;
inline TileData(TileId _id = TileId::None, TileRotate _rotate = TileRotate::Deg0, uint8_t _width = 1, uint8_t _height = 1) :
inline TileData(TileId _id = TileId::None, TileRotate _rotate = TileRotate::Deg0, uint8_t _width = 1, uint8_t _height = 1, uint8_t state_ = 0) :
_header{static_cast<uint16_t>((static_cast<uint16_t>(_id) << 4) | (static_cast<uint16_t>(_rotate) << 1) | (::isActive(_id) ? 1 : 0))},
_size{0},
_reserved{0}
state{state_}
{
setSize(_width, _height);
}

Datei anzeigen

@ -28,7 +28,7 @@
enum class CrossState : uint8_t
{
Unknown = 0,
Unset = 0,
AC = 1,
BD = 2,
};