Ursprung
f58d09bc7e
Commit
8ec71e496d
@ -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:
|
||||
|
||||
@ -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},
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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]()
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -9,6 +9,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"on_train_reserved": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "train"
|
||||
},
|
||||
{
|
||||
"name": "block"
|
||||
},
|
||||
{
|
||||
"name": "direction"
|
||||
}
|
||||
]
|
||||
},
|
||||
"on_train_removed": {
|
||||
"parameters": [
|
||||
{
|
||||
|
||||
@ -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."
|
||||
}
|
||||
]
|
||||
@ -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(¤t.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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {}; }
|
||||
|
||||
@ -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];
|
||||
|
||||
34
server/src/enum/blockside.hpp
Normale Datei
34
server/src/enum/blockside.hpp
Normale Datei
@ -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
|
||||
34
server/src/enum/bridgepath.hpp
Normale Datei
34
server/src/enum/bridgepath.hpp
Normale Datei
@ -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
|
||||
@ -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, \
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
enum class CrossState : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
Unset = 0,
|
||||
AC = 1,
|
||||
BD = 2,
|
||||
};
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren