Speed up TerrainSurfaceObject::GetImageId()

This commit is contained in:
mrmbernardi 2024-04-26 09:52:19 +02:00 committed by GitHub
parent 5837a33a60
commit f4cebb11df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 70 additions and 65 deletions

View File

@ -69,7 +69,7 @@ void LandTool::ShowSurfaceStyleDropdown(WindowBase* w, Widget* widget, ObjectEnt
if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages()) if (surfaceObj != nullptr && !surfaceObj->UsesFallbackImages())
{ {
auto imageId = ImageId(surfaceObj->IconImageId); auto imageId = ImageId(surfaceObj->IconImageId);
if (surfaceObj->Colour != 255) if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue)
imageId = imageId.WithPrimary(surfaceObj->Colour); imageId = imageId.WithPrimary(surfaceObj->Colour);
gDropdownItems[itemIndex].Format = Dropdown::FormatLandPicker; gDropdownItems[itemIndex].Format = Dropdown::FormatLandPicker;

View File

@ -325,7 +325,7 @@ static Widget window_land_widgets[] = {
if (surfaceObj != nullptr) if (surfaceObj != nullptr)
{ {
surfaceImage = ImageId(surfaceObj->IconImageId); surfaceImage = ImageId(surfaceObj->IconImageId);
if (surfaceObj->Colour != 255) if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue)
surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour); surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour);
} }

View File

@ -678,7 +678,7 @@ static uint64_t PressedWidgets[WINDOW_MAPGEN_PAGE_COUNT] = {
if (surfaceObj != nullptr) if (surfaceObj != nullptr)
{ {
surfaceImage = ImageId(surfaceObj->IconImageId); surfaceImage = ImageId(surfaceObj->IconImageId);
if (surfaceObj->Colour != 255) if (surfaceObj->Colour != TerrainSurfaceObject::kNoValue)
{ {
surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour); surfaceImage = surfaceImage.WithPrimary(surfaceObj->Colour);
} }

View File

@ -12,11 +12,9 @@
#include "TerrainSurfaceObject.h" #include "TerrainSurfaceObject.h"
#include "../Context.h" #include "../Context.h"
#include "../core/IStream.hpp" #include "../core/Guard.hpp"
#include "../core/Json.hpp" #include "../core/Json.hpp"
#include "../core/String.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Localisation.h"
#include "../world/Location.hpp" #include "../world/Location.hpp"
#include "ObjectManager.h" #include "ObjectManager.h"
@ -34,7 +32,7 @@ void TerrainSurfaceObject::Load()
{ {
EntryBaseImageId = IconImageId + 1; EntryBaseImageId = IconImageId + 1;
} }
NumEntries = (GetImageTable().GetCount() - EntryBaseImageId) / NUM_IMAGES_IN_ENTRY; NumEntries = (GetImageTable().GetCount() - EntryBaseImageId) / kNumImagesInEntry;
} }
void TerrainSurfaceObject::Unload() void TerrainSurfaceObject::Unload()
@ -52,7 +50,7 @@ void TerrainSurfaceObject::Unload()
void TerrainSurfaceObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const void TerrainSurfaceObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const
{ {
auto imageId = ImageId(GetImageId({}, 1, 0, 0, false, false)); auto imageId = ImageId(GetImageId({}, 1, 0, 0, false, false));
if (Colour != 255) if (Colour != kNoValue)
{ {
imageId = imageId.WithPrimary(Colour); imageId = imageId.WithPrimary(Colour);
} }
@ -84,7 +82,7 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root)
if (properties.is_object()) if (properties.is_object())
{ {
Colour = Colour::FromString(Json::GetString(properties["colour"]), 255); Colour = Colour::FromString(Json::GetString(properties["colour"]), kNoValue);
Rotations = Json::GetNumber<int8_t>(properties["rotations"], 1); Rotations = Json::GetNumber<int8_t>(properties["rotations"], 1);
Price = Json::GetNumber<money64>(properties["price"]); Price = Json::GetNumber<money64>(properties["price"]);
Flags = Json::GetFlags<TERRAIN_SURFACE_FLAGS>( Flags = Json::GetFlags<TERRAIN_SURFACE_FLAGS>(
@ -108,13 +106,17 @@ void TerrainSurfaceObject::ReadJson(IReadObjectContext* context, json_t& root)
if (el.is_object()) if (el.is_object())
{ {
SpecialEntry entry; SpecialEntry entry;
entry.Index = Json::GetNumber<uint32_t>(el["index"]); entry.Index = Json::GetNumber<uint8_t>(el["index"]);
entry.Length = Json::GetNumber<int32_t>(el["length"], -1); entry.Length = Json::GetNumber<uint8_t>(el["length"], kNoValue);
entry.Rotation = Json::GetNumber<int32_t>(el["rotation"], -1); entry.Rotation = Json::GetNumber<uint8_t>(el["rotation"], kNoValue);
entry.Variation = Json::GetNumber<int32_t>(el["variation"], -1); entry.Variation = Json::GetNumber<uint8_t>(el["variation"], kNoValue);
entry.Grid = Json::GetBoolean(el["grid"]);
entry.Underground = Json::GetBoolean(el["underground"]); if (Json::GetBoolean(el["underground"]))
SpecialEntries.push_back(std::move(entry)); 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); PopulateTablesFromJson(context, root);
} }
uint32_t TerrainSurfaceObject::GetImageId( ImageId TerrainSurfaceObject::GetImageId(
const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const 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<const SpecialEntry> entries(SpecialEntries);
if (underground)
{
result = DefaultUndergroundEntry;
entries = std::span<const SpecialEntry>(SpecialEntriesUnderground);
}
else if (grid)
{
result = DefaultGridEntry;
entries = std::span<const SpecialEntry>(SpecialEntriesGrid);
}
TileCoordsXY tilePos(position);
uint8_t variation = ((tilePos.x << 1) & 0b10) | (tilePos.y & 0b01);
// Look for a matching special // Look for a matching special
auto variation = ((position.x << 1) & 0b10) | (position.y & 0b01); for (const SpecialEntry& special : entries)
for (const auto& special : SpecialEntries)
{ {
if ((special.Length == -1 || special.Length == length) && (special.Rotation == -1 || special.Rotation == rotation) if ((special.Length == kNoValue || special.Length == length)
&& (special.Variation == -1 || special.Variation == variation) && special.Grid == grid && (special.Rotation == kNoValue || special.Rotation == rotation)
&& special.Underground == underground) && (special.Variation == kNoValue || special.Variation == variation))
{ {
result = special.Index; result = special.Index;
break; 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) TerrainSurfaceObject* TerrainSurfaceObject::GetById(ObjectEntryIndex entryIndex)

View File

@ -26,17 +26,16 @@ class TerrainSurfaceObject final : public Object
private: private:
struct SpecialEntry struct SpecialEntry
{ {
uint32_t Index{}; uint8_t Index{};
int32_t Length{}; uint8_t Length{};
int32_t Rotation{}; uint8_t Rotation{};
int32_t Variation{}; uint8_t Variation{};
bool Grid{};
bool Underground{};
}; };
static constexpr auto NUM_IMAGES_IN_ENTRY = 19; static constexpr auto kNumImagesInEntry = 19;
public: public:
static constexpr uint8_t kNoValue = 0xFF;
StringId NameStringId{}; StringId NameStringId{};
uint32_t IconImageId{}; uint32_t IconImageId{};
uint32_t PatternBaseImageId{}; uint32_t PatternBaseImageId{};
@ -47,7 +46,8 @@ public:
uint32_t DefaultGridEntry{}; uint32_t DefaultGridEntry{};
uint32_t DefaultUndergroundEntry{}; uint32_t DefaultUndergroundEntry{};
std::vector<SpecialEntry> SpecialEntries; std::vector<SpecialEntry> SpecialEntries;
std::vector<uint32_t> SpecialEntryMap; std::vector<SpecialEntry> SpecialEntriesUnderground;
std::vector<SpecialEntry> SpecialEntriesGrid;
colour_t Colour{}; colour_t Colour{};
uint8_t Rotations{}; uint8_t Rotations{};
@ -61,8 +61,8 @@ public:
void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override; void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override;
uint32_t GetImageId( ImageId GetImageId(
const CoordsXY& position, int32_t length, int32_t rotation, int32_t offset, bool grid, bool underground) const; const CoordsXY& position, uint8_t length, uint8_t rotation, uint8_t offset, bool grid, bool underground) const;
static TerrainSurfaceObject* GetById(ObjectEntryIndex entryIndex); static TerrainSurfaceObject* GetById(ObjectEntryIndex entryIndex);
}; };

View File

@ -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) static ImageId GetSurfacePattern(const TerrainSurfaceObject* surfaceObject, int32_t offset)
{ {
ImageId image; ImageId image;
if (surfaceObject != nullptr) if (surfaceObject != nullptr)
{ {
image = ImageId(surfaceObject->PatternBaseImageId + offset); image = ImageId(surfaceObject->PatternBaseImageId + offset);
if (surfaceObject->Colour != 255) if (surfaceObject->Colour != TerrainSurfaceObject::kNoValue)
{ {
image = image.WithPrimary(surfaceObject->Colour); 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); 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)); assert(surfaceShape < std::size(Byte97B444));
const uint8_t image_offset = Byte97B444[surfaceShape]; 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); 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)) 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))) && !(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)))
{ {
const uint8_t image_offset = Byte97B444[surfaceShape]; 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); PaintAttachToPreviousPS(session, imageId, 0, 0);
} }