diff --git a/src/openrct2-ui/interface/LandTool.cpp b/src/openrct2-ui/interface/LandTool.cpp index 8298660472..bd3fff5b24 100644 --- a/src/openrct2-ui/interface/LandTool.cpp +++ b/src/openrct2-ui/interface/LandTool.cpp @@ -69,7 +69,7 @@ void LandTool::ShowSurfaceStyleDropdown(WindowBase* w, Widget* widget, ObjectEnt if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages()) { auto imageId = ImageId(surfaceObj->IconImageId); - if (surfaceObj->Colour != 255) + if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue) imageId = imageId.WithPrimary(surfaceObj->Colour); gDropdownItems[itemIndex].Format = Dropdown::FormatLandPicker; diff --git a/src/openrct2-ui/windows/Land.cpp b/src/openrct2-ui/windows/Land.cpp index fffa262959..9d53d9c5df 100644 --- a/src/openrct2-ui/windows/Land.cpp +++ b/src/openrct2-ui/windows/Land.cpp @@ -325,7 +325,7 @@ static Widget window_land_widgets[] = { if (surfaceObj != nullptr) { surfaceImage = ImageId(surfaceObj->IconImageId); - if (surfaceObj->Colour != 255) + if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue) surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour); } diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index 5f1b608fda..56a5ddd44c 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -678,7 +678,7 @@ static uint64_t PressedWidgets[WINDOW_MAPGEN_PAGE_COUNT] = { if (surfaceObj != nullptr) { surfaceImage = ImageId(surfaceObj->IconImageId); - if (surfaceObj->Colour != 255) + if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue) { surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour); } diff --git a/src/openrct2/object/TerrainSurfaceObject.cpp b/src/openrct2/object/TerrainSurfaceObject.cpp index 2fa8d951c4..1f114d94d0 100644 --- a/src/openrct2/object/TerrainSurfaceObject.cpp +++ b/src/openrct2/object/TerrainSurfaceObject.cpp @@ -12,11 +12,9 @@ #include "TerrainSurfaceObject.h" #include "../Context.h" -#include "../core/IStream.hpp" +#include "../core/Guard.hpp" #include "../core/Json.hpp" -#include "../core/String.hpp" #include "../drawing/Drawing.h" -#include "../localisation/Localisation.h" #include "../world/Location.hpp" #include "ObjectManager.h" @@ -34,7 +32,7 @@ void TerrainSurfaceObject::Load() { EntryBaseImageId = IconImageId + 1; } - NumEntries = (GetImageTable().GetCount() - EntryBaseImageId) / NUM_IMAGES_IN_ENTRY; + NumEntries = (GetImageTable().GetCount() - EntryBaseImageId) / kNumImagesInEntry; } void TerrainSurfaceObject::Unload() @@ -52,7 +50,7 @@ void TerrainSurfaceObject::Unload() void TerrainSurfaceObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const { auto imageId = ImageId(GetImageId({}, 1, 0, 0, false, false)); - if (Colour != 255) + if (Colour != kNoValue) { imageId = imageId.WithPrimary(Colour); } @@ -84,7 +82,7 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root) if (properties.is_object()) { - Colour = Colour::FromString(Json::GetString(properties["colour"]), 255); + Colour = Colour::FromString(Json::GetString(properties["colour"]), kNoValue); Rotations = Json::GetNumber(properties["rotations"], 1); Price = Json::GetNumber(properties["price"]); Flags = Json::GetFlags( @@ -108,13 +106,17 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root) if (el.is_object()) { SpecialEntry entry; - entry.Index = Json::GetNumber(el["index"]); - entry.Length = Json::GetNumber(el["length"], -1); - entry.Rotation = Json::GetNumber(el["rotation"], -1); - entry.Variation = Json::GetNumber(el["variation"], -1); - entry.Grid = Json::GetBoolean(el["grid"]); - entry.Underground = Json::GetBoolean(el["underground"]); - SpecialEntries.push_back(std::move(entry)); + entry.Index = Json::GetNumber(el["index"]); + entry.Length = Json::GetNumber(el["length"], kNoValue); + entry.Rotation = Json::GetNumber(el["rotation"], kNoValue); + entry.Variation = Json::GetNumber(el["variation"], kNoValue); + + if (Json::GetBoolean(el["underground"])) + SpecialEntriesUnderground.push_back(entry); + else if (Json::GetBoolean(el["grid"])) + SpecialEntriesGrid.push_back(entry); + else + SpecialEntries.push_back(entry); } } } @@ -136,24 +138,43 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root) PopulateTablesFromJson(context, root); } -uint32_t TerrainSurfaceObject::GetImageId( - const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const +ImageId TerrainSurfaceObject::GetImageId( + const CoordsXY& position, uint8_t length, uint8_t rotation, uint8_t offset, bool grid, bool underground) const { - uint32_t result = (underground ? DefaultUndergroundEntry : (grid ? DefaultGridEntry : DefaultEntry)); + uint32_t result = DefaultEntry; + std::span entries(SpecialEntries); + if (underground) + { + result = DefaultUndergroundEntry; + entries = std::span(SpecialEntriesUnderground); + } + else if (grid) + { + result = DefaultGridEntry; + entries = std::span(SpecialEntriesGrid); + } + + TileCoordsXY tilePos(position); + uint8_t variation = ((tilePos.x << 1) & 0b10) | (tilePos.y & 0b01); // Look for a matching special - auto variation = ((position.x << 1) & 0b10) | (position.y & 0b01); - for (const auto& special : SpecialEntries) + for (const SpecialEntry& special : entries) { - if ((special.Length == -1 || special.Length == length) && (special.Rotation == -1 || special.Rotation == rotation) - && (special.Variation == -1 || special.Variation == variation) && special.Grid == grid - && special.Underground == underground) + if ((special.Length == kNoValue || special.Length == length) + && (special.Rotation == kNoValue || special.Rotation == rotation) + && (special.Variation == kNoValue || special.Variation == variation)) { result = special.Index; break; } } - return EntryBaseImageId + (result * NUM_IMAGES_IN_ENTRY) + offset; + + ImageId image(EntryBaseImageId + (result * kNumImagesInEntry) + offset); + if (Colour != kNoValue) + { + image = image.WithPrimary(Colour); + } + return image; } TerrainSurfaceObject* TerrainSurfaceObject::GetById(ObjectEntryIndex entryIndex) diff --git a/src/openrct2/object/TerrainSurfaceObject.h b/src/openrct2/object/TerrainSurfaceObject.h index 6f61aa6820..18d78e1d8f 100644 --- a/src/openrct2/object/TerrainSurfaceObject.h +++ b/src/openrct2/object/TerrainSurfaceObject.h @@ -26,17 +26,16 @@ class TerrainSurfaceObject final : public Object private: struct SpecialEntry { - uint32_t Index{}; - int32_t Length{}; - int32_t Rotation{}; - int32_t Variation{}; - bool Grid{}; - bool Underground{}; + uint8_t Index{}; + uint8_t Length{}; + uint8_t Rotation{}; + uint8_t Variation{}; }; - static constexpr auto NUM_IMAGES_IN_ENTRY = 19; + static constexpr auto kNumImagesInEntry = 19; public: + static constexpr uint8_t kNoValue = 0xFF; StringId NameStringId{}; uint32_t IconImageId{}; uint32_t PatternBaseImageId{}; @@ -47,7 +46,8 @@ public: uint32_t DefaultGridEntry{}; uint32_t DefaultUndergroundEntry{}; std::vector SpecialEntries; - std::vector SpecialEntryMap; + std::vector SpecialEntriesUnderground; + std::vector SpecialEntriesGrid; colour_t Colour{}; uint8_t Rotations{}; @@ -61,8 +61,8 @@ public: void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override; - uint32_t GetImageId( - const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const; + ImageId GetImageId( + const CoordsXY& position, uint8_t length, uint8_t rotation, uint8_t offset, bool grid, bool underground) const; static TerrainSurfaceObject* GetById(ObjectEntryIndex entryIndex); }; diff --git a/src/openrct2/paint/tile_element/Paint.Surface.cpp b/src/openrct2/paint/tile_element/Paint.Surface.cpp index d1c50f19c2..ee04200a74 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.cpp +++ b/src/openrct2/paint/tile_element/Paint.Surface.cpp @@ -302,30 +302,13 @@ static constexpr TileSurfaceBoundaryData _tileSurfaceBoundaries[4] = { }, }; -static ImageId GetSurfaceImage( - const PaintSession& session, const TerrainSurfaceObject* surfaceObject, int32_t offset, uint8_t rotation, - int32_t grassLength, bool grid, bool underground) -{ - ImageId image; - if (surfaceObject != nullptr) - { - image = ImageId(surfaceObject->GetImageId( - { session.MapPosition.x >> 5, session.MapPosition.y >> 5 }, grassLength, rotation, offset, grid, underground)); - if (surfaceObject->Colour != 255) - { - image = image.WithPrimary(surfaceObject->Colour); - } - } - return image; -} - static ImageId GetSurfacePattern(const TerrainSurfaceObject* surfaceObject, int32_t offset) { ImageId image; if (surfaceObject != nullptr) { image = ImageId(surfaceObject->PatternBaseImageId + offset); - if (surfaceObject->Colour != 255) + if (surfaceObject->Colour != TerrainSurfaceObject::kNoValue) { image = image.WithPrimary(surfaceObject->Colour); } @@ -1108,15 +1091,6 @@ void PaintSurface(PaintSession& session, uint8_t direction, uint16_t height, con { const bool showGridlines = (session.ViewFlags & VIEWPORT_FLAG_GRIDLINES); - auto grassLength = -1; - if (zoomLevel <= ZoomLevel{ 0 }) - { - if ((session.ViewFlags & (VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE)) == 0) - { - grassLength = tileElement.GetGrassLength() & 0x7; - } - } - assert(surfaceShape < std::size(Byte97B444)); const uint8_t image_offset = Byte97B444[surfaceShape]; @@ -1125,9 +1099,17 @@ void PaintSurface(PaintSession& session, uint8_t direction, uint16_t height, con { imageId = ImageId(SPR_TERRAIN_TRACK_DESIGNER); } - else + else if (surfaceObject != nullptr) { - imageId = GetSurfaceImage(session, surfaceObject, image_offset, rotation, grassLength, showGridlines, false); + uint8_t grassLength = TerrainSurfaceObject::kNoValue; + if (zoomLevel <= ZoomLevel{ 0 }) + { + if ((session.ViewFlags & (VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE)) == 0) + { + grassLength = tileElement.GetGrassLength() & 0x7; + } + } + imageId = surfaceObject->GetImageId(session.MapPosition, grassLength, rotation, image_offset, showGridlines, false); } if (session.ViewFlags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE)) { @@ -1299,7 +1281,9 @@ void PaintSurface(PaintSession& session, uint8_t direction, uint16_t height, con && !(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))) { const uint8_t image_offset = Byte97B444[surfaceShape]; - auto imageId = GetSurfaceImage(session, surfaceObject, image_offset, rotation, 1, false, true); + ImageId imageId; + if (surfaceObject != nullptr) + imageId = surfaceObject->GetImageId(session.MapPosition, 1, rotation, image_offset, false, true); PaintAttachToPreviousPS(session, imageId, 0, 0); }