From a82d398afdf55e24bbb52b9e3e827542a537b0d3 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek <1478678+Gymnasiast@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:15:17 +0200 Subject: [PATCH] Abstract flags access in track design scenery --- src/openrct2/ride/TrackDesign.cpp | 199 +++++++++++++++++--------- src/openrct2/ride/TrackDesign.h | 36 +++-- src/openrct2/ride/TrackDesignSave.cpp | 170 +++++++++++----------- 3 files changed, 244 insertions(+), 161 deletions(-) diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index b4803dac6e..ae708b34a3 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -70,6 +70,20 @@ #include #include +namespace TrackDesignSceneryElementFlags +{ + static constexpr uint8_t kRotationMask = 0b00000011; + + static constexpr uint8_t kQuadrantMask = 0b00001100; + + static constexpr uint8_t kEdgesMask = 0b00001111; + static constexpr uint8_t kHasSlopeMask = 0b00010000; + static constexpr uint8_t kSlopeDirectionMask = 0b01100000; + static constexpr uint8_t kIsQueueMask = 0b10000000; +} // namespace TrackDesignSceneryElementFlags + +using namespace TrackDesignSceneryElementFlags; + using namespace OpenRCT2; using namespace OpenRCT2::Drawing; using namespace OpenRCT2::TrackMetaData; @@ -495,40 +509,27 @@ ResultWithMessage TrackDesign::CreateTrackDesignScenery(TrackDesignState& tds) { case ObjectType::Paths: { - uint8_t slope = (scenery.flags & 0x60) >> 5; - slope -= _saveDirection; + uint8_t slope = (scenery.getSlopeDirection() - _saveDirection) % NumOrthogonalDirections; + scenery.setSlopeDirection(slope); - scenery.flags &= 0x9F; - scenery.flags |= ((slope & 3) << 5); - - // Direction of connection on path - uint8_t direction = scenery.flags & 0xF; - // Rotate the direction by the track direction - direction = ((direction << 4) >> _saveDirection); - - scenery.flags &= 0xF0; - scenery.flags |= (direction & 0xF) | (direction >> 4); + uint8_t edges = Numerics::ror4(scenery.getEdges(), _saveDirection); + scenery.setEdges(edges); break; } case ObjectType::Walls: { - uint8_t direction = scenery.flags & 3; - direction -= _saveDirection; - - scenery.flags &= 0xFC; - scenery.flags |= (direction & 3); + auto direction = (scenery.getRotation() - _saveDirection) % NumOrthogonalDirections; + scenery.setRotation(direction); break; } default: { - uint8_t direction = scenery.flags & 3; - uint8_t quadrant = (scenery.flags & 0x0C) >> 2; + auto direction = (scenery.getRotation() - _saveDirection) % NumOrthogonalDirections; + scenery.setRotation(direction); - direction -= _saveDirection; - quadrant -= _saveDirection; + auto quadrant = (scenery.getQuadrant() - _saveDirection) % NumOrthogonalDirections; + scenery.setQuadrant(quadrant); - scenery.flags &= 0xF0; - scenery.flags |= (direction & 3) | ((quadrant & 3) << 2); break; } } @@ -698,7 +699,7 @@ static std::optional TrackDesignPlaceSceneryElementGetEntry(c auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager(); if (scenery.sceneryObject.GetType() == ObjectType::Paths) { - auto footpathMapping = RCT2::GetFootpathSurfaceId(scenery.sceneryObject, true, scenery.IsQueue()); + auto footpathMapping = RCT2::GetFootpathSurfaceId(scenery.sceneryObject, true, scenery.isQueue()); if (footpathMapping == nullptr) { // Check if legacy path object is loaded @@ -717,12 +718,12 @@ static std::optional TrackDesignPlaceSceneryElementGetEntry(c { result.Type = ObjectType::FootpathSurface; result.Index = objectMgr.GetLoadedObjectEntryIndex( - ObjectEntryDescriptor(scenery.IsQueue() ? footpathMapping->QueueSurface : footpathMapping->NormalSurface)); + ObjectEntryDescriptor(scenery.isQueue() ? footpathMapping->QueueSurface : footpathMapping->NormalSurface)); result.SecondaryIndex = objectMgr.GetLoadedObjectEntryIndex(ObjectEntryDescriptor(footpathMapping->Railing)); } if (result.Index == OBJECT_ENTRY_INDEX_NULL) - result.Index = TrackDesignGetDefaultSurfaceIndex(scenery.IsQueue()); + result.Index = TrackDesignGetDefaultSurfaceIndex(scenery.isQueue()); if (result.SecondaryIndex == OBJECT_ENTRY_INDEX_NULL) result.SecondaryIndex = TrackDesignGetDefaultRailingIndex(); @@ -794,7 +795,7 @@ static void TrackDesignMirrorScenery(TrackDesign* td6) } } - switch (scenery.flags & 3) + switch (scenery.getRotation()) { case 0: scenery.loc.y = -(scenery.loc.y + y1) - y2; @@ -802,7 +803,6 @@ static void TrackDesignMirrorScenery(TrackDesign* td6) case 1: scenery.loc.x = scenery.loc.x + y2 + y1; scenery.loc.y = -scenery.loc.y; - scenery.flags ^= (1 << 1); break; case 2: scenery.loc.y = -(scenery.loc.y - y2) + y1; @@ -810,9 +810,9 @@ static void TrackDesignMirrorScenery(TrackDesign* td6) case 3: scenery.loc.x = scenery.loc.x - y2 - y1; scenery.loc.y = -scenery.loc.y; - scenery.flags ^= (1 << 1); break; } + scenery.setRotation(DirectionFlipXAxis(scenery.getRotation())); break; } case ObjectType::SmallScenery: @@ -822,28 +822,22 @@ static void TrackDesignMirrorScenery(TrackDesign* td6) if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_DIAGONAL)) { - scenery.flags ^= (1 << 0); + scenery.setRotation(scenery.getRotation() ^ (1 << 0)); if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE)) { - scenery.flags ^= (1 << 2); + scenery.setQuadrant(scenery.getQuadrant() ^ (1 << 0)); } break; } - if (scenery.flags & (1 << 0)) - { - scenery.flags ^= (1 << 1); - } - scenery.flags ^= (1 << 2); + scenery.setRotation(DirectionFlipXAxis(scenery.getRotation())); + scenery.setQuadrant(scenery.getQuadrant() ^ (1 << 0)); break; } case ObjectType::Walls: { scenery.loc.y = -scenery.loc.y; - if (scenery.flags & (1 << 0)) - { - scenery.flags ^= (1 << 1); - } + scenery.setRotation(DirectionFlipXAxis(scenery.getRotation())); break; } case ObjectType::Paths: @@ -851,15 +845,14 @@ static void TrackDesignMirrorScenery(TrackDesign* td6) { scenery.loc.y = -scenery.loc.y; - if (scenery.flags & (1 << 5)) + if (scenery.hasSlope()) { - scenery.flags ^= (1 << 6); + scenery.setSlopeDirection(DirectionFlipXAxis(scenery.getSlopeDirection())); } - uint8_t flags = scenery.flags; - flags = ((flags & (1 << 3)) >> 2) | ((flags & (1 << 1)) << 2); - scenery.flags &= 0xF5; - scenery.flags |= flags; + uint8_t edges = scenery.getEdges(); + edges = ((edges & 0b1000) >> 2) | ((edges & 0b0010) << 2) | (edges & 0b0101); + scenery.setEdges(edges); break; } default: @@ -970,7 +963,7 @@ static GameActions::Result TrackDesignPlaceSceneryElementRemoveGhost( } int32_t z = scenery.loc.z + originZ; - uint8_t sceneryRotation = (rotation + scenery.flags) & kTileElementDirectionMask; + uint8_t sceneryRotation = (rotation + scenery.getRotation()) & kTileElementDirectionMask; const uint32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; std::unique_ptr ga; @@ -978,7 +971,7 @@ static GameActions::Result TrackDesignPlaceSceneryElementRemoveGhost( { case ObjectType::SmallScenery: { - uint8_t quadrant = (scenery.flags >> 2) + _currentTrackPieceDirection; + uint8_t quadrant = scenery.getQuadrant() + _currentTrackPieceDirection; quadrant &= 3; auto* sceneryEntry = OpenRCT2::ObjectManager::GetObjectEntry(entryInfo->Index); @@ -1059,7 +1052,6 @@ static GameActions::Result TrackDesignPlaceSceneryElement( int16_t z; uint8_t flags; - uint8_t quadrant; switch (entryInfo->Type) { @@ -1070,10 +1062,10 @@ static GameActions::Result TrackDesignPlaceSceneryElement( return GameActions::Result(); } - rotation += scenery.flags; + rotation += scenery.getRotation(); rotation &= 3; z = scenery.loc.z + originZ; - quadrant = ((scenery.flags >> 2) + _currentTrackPieceDirection) & 3; + uint8_t quadrant = (scenery.getQuadrant() + _currentTrackPieceDirection) & 3; flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_TRACK_DESIGN; if (tds.PlaceOperation == PTD_OPERATION_PLACE_TRACK_PREVIEW) @@ -1113,7 +1105,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement( return GameActions::Result(); } - rotation += scenery.flags; + rotation += scenery.getRotation(); rotation &= 3; z = scenery.loc.z + originZ; @@ -1155,7 +1147,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement( } z = scenery.loc.z + originZ; - rotation += scenery.flags; + rotation += scenery.getRotation(); rotation &= 3; flags = GAME_COMMAND_FLAG_APPLY; @@ -1192,16 +1184,6 @@ static GameActions::Result TrackDesignPlaceSceneryElement( z = scenery.loc.z + originZ; if (mode == 0) { - auto isQueue = scenery.IsQueue(); - - uint8_t bh = ((scenery.flags & 0xF) << rotation); - flags = bh >> 4; - bh = (bh | flags) & 0xF; - flags = (((scenery.flags >> 5) + rotation) & 3) << 5; - bh |= flags; - - bh |= scenery.flags & 0x90; - flags = GAME_COMMAND_FLAG_APPLY; if (tds.PlaceOperation == PTD_OPERATION_PLACE_TRACK_PREVIEW) { @@ -1220,10 +1202,12 @@ static GameActions::Result TrackDesignPlaceSceneryElement( { flags |= GAME_COMMAND_FLAG_REPLAY; } - uint8_t slope = ((bh >> 5) & 0x3) | ((bh >> 2) & 0x4); - uint8_t edges = bh & 0xF; + uint8_t slope = (scenery.getSlopeDirection() + rotation) & 0x3; + if (scenery.hasSlope()) + slope |= FOOTPATH_PROPERTIES_FLAG_IS_SLOPED; + uint8_t edges = Numerics::rol4(scenery.getEdges(), rotation); PathConstructFlags constructFlags = 0; - if (isQueue) + if (scenery.isQueue()) constructFlags |= PathConstructFlag::IsQueue; if (entryInfo->Type == ObjectType::Paths) constructFlags |= PathConstructFlag::IsLegacyPathObject; @@ -1990,6 +1974,89 @@ static bool TrackDesignPlacePreview(TrackDesignState& tds, TrackDesign* td6, mon return false; } +Direction TrackDesignSceneryElement::getRotation() const +{ + return flags & kRotationMask; +} + +void TrackDesignSceneryElement::setRotation(Direction rotation) +{ + flags &= ~kRotationMask; + flags |= (rotation & kRotationMask); +} + +// Small scenery +uint8_t TrackDesignSceneryElement::getQuadrant() const +{ + return (flags & kQuadrantMask) >> 2; +} + +void TrackDesignSceneryElement::setQuadrant(uint8_t quadrant) +{ + flags &= ~kQuadrantMask; + flags |= ((quadrant << 2) & kQuadrantMask); +} + +// Path +bool TrackDesignSceneryElement::hasSlope() const +{ + return (flags & kHasSlopeMask) != 0; +} + +void TrackDesignSceneryElement::setHasSlope(bool on) +{ + if (on) + flags |= kHasSlopeMask; + else + flags &= ~kHasSlopeMask; +} + +Direction TrackDesignSceneryElement::getSlopeDirection() const +{ + return (flags >> 5) % NumOrthogonalDirections; +} + +void TrackDesignSceneryElement::setSlopeDirection(Direction slope) +{ + flags &= ~kSlopeDirectionMask; + flags |= ((slope << 5) & kSlopeDirectionMask); +} + +uint8_t TrackDesignSceneryElement::getEdges() const +{ + return (flags & kEdgesMask); +} + +void TrackDesignSceneryElement::setEdges(uint8_t edges) +{ + flags &= ~kEdgesMask; + flags |= (edges & kEdgesMask); +} + +bool TrackDesignSceneryElement::isQueue() const +{ + return (flags & kIsQueueMask) != 0; +} + +void TrackDesignSceneryElement::setIsQueue(bool on) +{ + if (on) + flags |= kIsQueueMask; + else + flags &= ~kIsQueueMask; +} + +bool TrackDesignSceneryElement::operator==(const TrackDesignSceneryElement& rhs) +{ + return sceneryObject == rhs.sceneryObject && loc == rhs.loc && flags == rhs.flags && primaryColour == rhs.primaryColour + && secondaryColour == rhs.secondaryColour && tertiaryColour == rhs.tertiaryColour; +} + +bool TrackDesignSceneryElement::operator!=(const TrackDesignSceneryElement& rhs) +{ + return !((*this) == rhs); +} + #pragma region Track Design Preview /** diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index e4c2deac63..260a598c89 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -46,17 +46,35 @@ struct TrackDesignEntranceElement struct TrackDesignSceneryElement { - ObjectEntryDescriptor sceneryObject; - CoordsXYZ loc; - uint8_t flags; - colour_t primaryColour; - colour_t secondaryColour; + ObjectEntryDescriptor sceneryObject{}; + CoordsXYZ loc{}; + uint8_t flags{}; + colour_t primaryColour{}; + colour_t secondaryColour{}; colour_t tertiaryColour = COLOUR_DARK_BROWN; - bool IsQueue() const - { - return (flags & (1 << 7)) != 0; - } + Direction getRotation() const; + void setRotation(Direction rotation); + + // Small scenery + uint8_t getQuadrant() const; + void setQuadrant(uint8_t quadrant); + + // Path + bool hasSlope() const; + void setHasSlope(bool on); + + Direction getSlopeDirection() const; + void setSlopeDirection(Direction slope); + + uint8_t getEdges() const; + void setEdges(uint8_t edges); + + bool isQueue() const; + void setIsQueue(bool on); + + bool operator==(const TrackDesignSceneryElement& rhs); + bool operator!=(const TrackDesignSceneryElement& rhs); }; enum class TrackDesignTrackElementFlag : uint8_t diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 9814b04e89..d0859d8b5e 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -208,33 +208,37 @@ static bool TrackDesignSaveIsSupportedObject(const Object* obj) return !entry.IsEmpty(); } -static void TrackDesignSavePushTileElementDesc( - const RCTObjectEntry& entry, const CoordsXYZ& loc, uint8_t flags, colour_t primaryColour, colour_t secondaryColour, - colour_t tertiaryColour) +static TrackDesignSceneryElement TrackDesignCreateTileElementDesc(const RCTObjectEntry& entry, const CoordsXYZ& loc) { TrackDesignSceneryElement item{}; item.sceneryObject = ObjectEntryDescriptor(entry); item.loc = loc; - item.flags = flags; - item.primaryColour = primaryColour; - item.secondaryColour = secondaryColour; - item.tertiaryColour = tertiaryColour; - - _trackSavedTileElementsDesc.push_back(std::move(item)); + return item; } -static void TrackDesignSavePushTileElementDesc( - const Object* obj, const CoordsXYZ& loc, uint8_t flags, uint8_t primaryColour, uint8_t secondaryColour, - colour_t tertiaryColour) +static TrackDesignSceneryElement TrackDesignCreateTileElementDesc(const Object& obj, const CoordsXYZ& loc) { - const auto& entry = obj->GetObjectEntry(); + const auto& entry = obj.GetObjectEntry(); if (entry.IsEmpty()) { // Unsupported, should have been blocked earlier assert(false); } - TrackDesignSavePushTileElementDesc(entry, loc, flags, primaryColour, secondaryColour, tertiaryColour); + return TrackDesignCreateTileElementDesc(entry, loc); +} + +static TrackDesignSceneryElement TrackDesignSaveCreateSmallSceneryDesc( + const Object& object, const CoordsXY& loc, const SmallSceneryElement& smallSceneryElement) +{ + auto item = TrackDesignCreateTileElementDesc(object, { loc, smallSceneryElement.GetBaseZ() }); + item.setRotation(smallSceneryElement.GetDirection()); + item.setQuadrant(smallSceneryElement.GetSceneryQuadrant()); + item.primaryColour = smallSceneryElement.GetPrimaryColour(); + item.secondaryColour = smallSceneryElement.GetSecondaryColour(); + item.tertiaryColour = smallSceneryElement.GetTertiaryColour(); + + return item; } static TrackDesignAddStatus TrackDesignSaveAddSmallScenery(const CoordsXY& loc, SmallSceneryElement* sceneryElement) @@ -243,23 +247,27 @@ static TrackDesignAddStatus TrackDesignSaveAddSmallScenery(const CoordsXY& loc, auto obj = ObjectEntryGetObject(ObjectType::SmallScenery, entryIndex); if (obj != nullptr && TrackDesignSaveIsSupportedObject(obj)) { - uint8_t flags = 0; - flags |= sceneryElement->GetDirection(); - flags |= sceneryElement->GetSceneryQuadrant() << 2; - - auto primaryColour = sceneryElement->GetPrimaryColour(); - auto secondaryColour = sceneryElement->GetSecondaryColour(); - auto tertiaryColour = sceneryElement->GetTertiaryColour(); - + auto item = TrackDesignSaveCreateSmallSceneryDesc(*obj, loc, *sceneryElement); TrackDesignSavePushTileElement(loc, reinterpret_cast(sceneryElement)); - TrackDesignSavePushTileElementDesc( - obj, { loc.x, loc.y, sceneryElement->GetBaseZ() }, flags, primaryColour, secondaryColour, tertiaryColour); + _trackSavedTileElementsDesc.push_back(std::move(item)); return TrackDesignAddStatus::Success(); } return TrackDesignAddStatus::Fail(STR_UNSUPPORTED_OBJECT_FORMAT); } +static TrackDesignSceneryElement TrackDesignSaveCreateLargeSceneryDesc( + const Object& object, const CoordsXYZ& loc, const LargeSceneryElement& largeSceneryElement) +{ + auto item = TrackDesignCreateTileElementDesc(object, loc); + item.setRotation(largeSceneryElement.GetDirection()); + item.primaryColour = largeSceneryElement.GetPrimaryColour(); + item.secondaryColour = largeSceneryElement.GetSecondaryColour(); + item.tertiaryColour = largeSceneryElement.GetTertiaryColour(); + + return item; +} + static TrackDesignAddStatus TrackDesignSaveAddLargeScenery(const CoordsXY& loc, LargeSceneryElement* tileElement) { auto entryIndex = tileElement->GetEntryIndex(); @@ -295,14 +303,10 @@ static TrackDesignAddStatus TrackDesignSaveAddLargeScenery(const CoordsXY& loc, { if (sequence == 0) { - uint8_t flags = largeElement->GetDirection(); - auto primaryColour = largeElement->GetPrimaryColour(); - auto secondaryColour = largeElement->GetSecondaryColour(); - auto tertiaryColour = largeElement->GetTertiaryColour(); - - TrackDesignSavePushTileElementDesc(obj, tileLoc, flags, primaryColour, secondaryColour, tertiaryColour); + auto item = TrackDesignSaveCreateLargeSceneryDesc(*obj, tileLoc, *largeElement); + _trackSavedTileElementsDesc.push_back(std::move(item)); } - TrackDesignSavePushTileElement({ tileLoc.x, tileLoc.y }, reinterpret_cast(largeElement)); + TrackDesignSavePushTileElement(tileLoc, reinterpret_cast(largeElement)); } } return TrackDesignAddStatus::Success(); @@ -311,32 +315,37 @@ static TrackDesignAddStatus TrackDesignSaveAddLargeScenery(const CoordsXY& loc, return TrackDesignAddStatus::Fail(STR_UNSUPPORTED_OBJECT_FORMAT); } +static TrackDesignSceneryElement TrackDesignSaveCreateWallDesc( + const Object& object, const CoordsXY& loc, const WallElement& wallElement) +{ + auto item = TrackDesignCreateTileElementDesc(object, { loc, wallElement.GetBaseZ() }); + item.setRotation(wallElement.GetDirection()); + item.primaryColour = wallElement.GetPrimaryColour(); + item.secondaryColour = wallElement.GetSecondaryColour(); + item.tertiaryColour = wallElement.GetTertiaryColour(); + + return item; +} + static TrackDesignAddStatus TrackDesignSaveAddWall(const CoordsXY& loc, WallElement* wallElement) { auto entryIndex = wallElement->GetEntryIndex(); auto obj = ObjectEntryGetObject(ObjectType::Walls, entryIndex); if (obj != nullptr && TrackDesignSaveIsSupportedObject(obj)) { - uint8_t flags = 0; - flags |= wallElement->GetDirection(); - - auto primaryColour = wallElement->GetPrimaryColour(); - auto secondaryColour = wallElement->GetSecondaryColour(); - auto tertiaryColour = wallElement->GetTertiaryColour(); - + auto item = TrackDesignSaveCreateWallDesc(*obj, loc, *wallElement); TrackDesignSavePushTileElement(loc, reinterpret_cast(wallElement)); - TrackDesignSavePushTileElementDesc( - obj, { loc.x, loc.y, wallElement->GetBaseZ() }, flags, primaryColour, secondaryColour, tertiaryColour); + _trackSavedTileElementsDesc.push_back(std::move(item)); return TrackDesignAddStatus::Success(); } return TrackDesignAddStatus::Fail(STR_UNSUPPORTED_OBJECT_FORMAT); } -static std::optional TrackDesignSaveFootpathGetBestEntry(PathElement* pathElement) +static std::optional TrackDesignSaveFootpathGetBestEntry(const PathElement& pathElement) { RCTObjectEntry pathEntry; - auto legacyPathObj = pathElement->GetLegacyPathEntry(); + auto legacyPathObj = pathElement.GetLegacyPathEntry(); if (legacyPathObj != nullptr) { pathEntry = legacyPathObj->GetObjectEntry(); @@ -347,36 +356,42 @@ static std::optional TrackDesignSaveFootpathGetBestEntry(PathEle } else { - auto surfaceEntry = pathElement->GetSurfaceEntry(); + auto surfaceEntry = pathElement.GetSurfaceEntry(); if (surfaceEntry != nullptr) { auto surfaceId = surfaceEntry->GetIdentifier(); - auto railingsEntry = pathElement->GetRailingsEntry(); + auto railingsEntry = pathElement.GetRailingsEntry(); auto railingsId = railingsEntry == nullptr ? "" : railingsEntry->GetIdentifier(); return RCT2::GetBestObjectEntryForSurface(surfaceId, railingsId); } } - return {}; + return std::nullopt; +} + +static TrackDesignSceneryElement TrackDesignSaveCreateFootpathDesc( + const RCTObjectEntry& pathEntry, const CoordsXY& loc, const PathElement& pathElement) +{ + auto item = TrackDesignCreateTileElementDesc(pathEntry, { loc, pathElement.GetBaseZ() }); + item.setEdges(pathElement.GetEdges()); + item.setHasSlope(pathElement.IsSloped()); + item.setSlopeDirection(pathElement.GetSlopeDirection()); + item.setIsQueue(pathElement.IsQueue()); + + return item; } static TrackDesignAddStatus TrackDesignSaveAddFootpath(const CoordsXY& loc, PathElement* pathElement) { - auto pathEntry = TrackDesignSaveFootpathGetBestEntry(pathElement); - if (!pathElement) + auto pathEntry = TrackDesignSaveFootpathGetBestEntry(*pathElement); + if (!pathEntry.has_value()) { return TrackDesignAddStatus::Fail(STR_UNSUPPORTED_OBJECT_FORMAT); } - uint8_t flags = 0; - flags |= pathElement->GetEdges(); - flags |= (pathElement->GetSlopeDirection()) << 5; - if (pathElement->IsSloped()) - flags |= 0b00010000; - if (pathElement->IsQueue()) - flags |= 1 << 7; - + auto item = TrackDesignSaveCreateFootpathDesc(pathEntry.value(), loc, *pathElement); TrackDesignSavePushTileElement(loc, reinterpret_cast(pathElement)); - TrackDesignSavePushTileElementDesc(*pathEntry, { loc.x, loc.y, pathElement->GetBaseZ() }, flags, 0, 0, 0); + + _trackSavedTileElementsDesc.push_back(std::move(item)); return TrackDesignAddStatus::Success(); } @@ -434,17 +449,13 @@ static void TrackDesignSavePopTileElement(const CoordsXY& loc, TileElement* tile * * rct2: 0x006D2FDD */ -static void TrackDesignSavePopTileElementDesc(const ObjectEntryDescriptor& entry, const CoordsXYZ& loc, uint8_t flags) +static void TrackDesignSavePopTileElementDesc(const TrackDesignSceneryElement& desc) { size_t removeIndex = SIZE_MAX; for (size_t i = 0; i < _trackSavedTileElementsDesc.size(); i++) { - TrackDesignSceneryElement* item = &_trackSavedTileElementsDesc[i]; - if (item->loc != loc) - continue; - if (item->flags != flags) - continue; - if (item->sceneryObject != entry) + TrackDesignSceneryElement& item = _trackSavedTileElementsDesc[i]; + if (item != desc) continue; removeIndex = i; @@ -462,12 +473,9 @@ static void TrackDesignSaveRemoveSmallScenery(const CoordsXY& loc, SmallSceneryE auto obj = ObjectEntryGetObject(ObjectType::SmallScenery, entryIndex); if (obj != nullptr) { - uint8_t flags = 0; - flags |= sceneryElement->GetDirection(); - flags |= sceneryElement->GetSceneryQuadrant() << 2; - + auto item = TrackDesignSaveCreateSmallSceneryDesc(*obj, loc, *sceneryElement); TrackDesignSavePopTileElement(loc, reinterpret_cast(sceneryElement)); - TrackDesignSavePopTileElementDesc(obj->GetDescriptor(), { loc.x, loc.y, sceneryElement->GetBaseZ() }, flags); + TrackDesignSavePopTileElementDesc(item); } } @@ -512,8 +520,8 @@ static void TrackDesignSaveRemoveLargeScenery(const CoordsXY& loc, LargeSceneryE { if (sequence == 0) { - uint8_t flags = largeElement->GetDirection(); - TrackDesignSavePopTileElementDesc(obj->GetDescriptor(), tileLoc, flags); + auto item = TrackDesignSaveCreateLargeSceneryDesc(*obj, tileLoc, *largeElement); + TrackDesignSavePopTileElementDesc(item); } TrackDesignSavePopTileElement({ tileLoc.x, tileLoc.y }, reinterpret_cast(largeElement)); } @@ -527,30 +535,20 @@ static void TrackDesignSaveRemoveWall(const CoordsXY& loc, WallElement* wallElem auto obj = ObjectEntryGetObject(ObjectType::Walls, entryIndex); if (obj != nullptr) { - uint8_t flags = 0; - flags |= wallElement->GetDirection(); - flags |= wallElement->GetTertiaryColour() << 2; - + auto item = TrackDesignSaveCreateWallDesc(*obj, loc, *wallElement); TrackDesignSavePopTileElement(loc, reinterpret_cast(wallElement)); - TrackDesignSavePopTileElementDesc(obj->GetDescriptor(), { loc.x, loc.y, wallElement->GetBaseZ() }, flags); + TrackDesignSavePopTileElementDesc(item); } } static void TrackDesignSaveRemoveFootpath(const CoordsXY& loc, PathElement* pathElement) { - auto pathEntry = TrackDesignSaveFootpathGetBestEntry(pathElement); - if (pathElement) + auto pathEntry = TrackDesignSaveFootpathGetBestEntry(*pathElement); + if (pathEntry.has_value()) { - uint8_t flags = 0; - flags |= pathElement->GetEdges(); - flags |= (pathElement->GetSlopeDirection()) << 5; - if (pathElement->IsSloped()) - flags |= 0b00010000; - if (pathElement->IsQueue()) - flags |= 1 << 7; - + auto item = TrackDesignSaveCreateFootpathDesc(pathEntry.value(), loc, *pathElement); TrackDesignSavePopTileElement(loc, reinterpret_cast(pathElement)); - TrackDesignSavePopTileElementDesc(ObjectEntryDescriptor(*pathEntry), { loc.x, loc.y, pathElement->GetBaseZ() }, flags); + TrackDesignSavePopTileElementDesc(item); } }