diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 247c29d2a9..563d355a57 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -1116,7 +1116,7 @@ static void window_tile_inspector_mousedown(rct_window* w, rct_widgetindex widge // Set current value as checked rct_tile_element* const tileElement = window_tile_inspector_get_selected_element(w); - dropdown_set_checked(tileElement->GetSceneryQuadrant(), true); + dropdown_set_checked(tileElement->AsWall()->GetSlope(), true); break; } // switch widget index break; @@ -1570,10 +1570,10 @@ static void window_tile_inspector_invalidate(rct_window* w) w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].top = GBBT(propertiesAnchor, 1) - 5 + 7 * 1; w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].bottom = w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].top + 13; // This gets the relative rotation, by subtracting the camera's rotation, and wrapping it between 0-3 inclusive - bool N = tileElement->GetSceneryQuadrant() == ((0 - get_current_rotation()) & 3); - bool E = tileElement->GetSceneryQuadrant() == ((1 - get_current_rotation()) & 3); - bool S = tileElement->GetSceneryQuadrant() == ((2 - get_current_rotation()) & 3); - bool W = tileElement->GetSceneryQuadrant() == ((3 - get_current_rotation()) & 3); + bool N = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((0 - get_current_rotation()) & 3); + bool E = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((1 - get_current_rotation()) & 3); + bool S = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((2 - get_current_rotation()) & 3); + bool W = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((3 - get_current_rotation()) & 3); widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_N, N); widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_E, E); widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_S, S); @@ -1620,7 +1620,7 @@ static void window_tile_inspector_invalidate(rct_window* w) w->widgets[WIDX_WALL_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4; w->widgets[WIDX_WALL_DROPDOWN_SLOPE].top = GBBT(propertiesAnchor, 1) + 3; w->widgets[WIDX_WALL_DROPDOWN_SLOPE].bottom = GBBB(propertiesAnchor, 1) - 3; - w->widgets[WIDX_WALL_DROPDOWN_SLOPE].text = WallSlopeStringIds[tileElement->GetSceneryQuadrant()]; + w->widgets[WIDX_WALL_DROPDOWN_SLOPE].text = WallSlopeStringIds[tileElement->AsWall()->GetSlope()]; w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].top = GBBT(propertiesAnchor, 1) + 4; w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].bottom = GBBB(propertiesAnchor, 1) - 4; const uint8_t wallType = tileElement->properties.wall.type; @@ -1880,7 +1880,7 @@ static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi) const rct_scenery_entry* sceneryEntry = get_small_scenery_entry(tileElement->properties.scenery.type); if (!(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE))) { - int16_t quadrant = tileElement->GetSceneryQuadrant(); + int16_t quadrant = tileElement->AsSmallScenery()->GetSceneryQuadrant(); static rct_string_id quadrant_string_idx[] = { STR_TILE_INSPECTOR_SCENERY_QUADRANT_SW, STR_TILE_INSPECTOR_SCENERY_QUADRANT_NW, STR_TILE_INSPECTOR_SCENERY_QUADRANT_NE, diff --git a/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp b/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp index e99d47edec..2bf474d9ee 100644 --- a/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp +++ b/src/openrct2/paint/tile_element/Paint.SmallScenery.cpp @@ -114,7 +114,7 @@ void scenery_paint(paint_session* session, uint8_t direction, int32_t height, co else { // 6DFFC2: - uint8_t ecx = (tileElement->GetSceneryQuadrant() + rotation) & 3; + uint8_t ecx = (tileElement->AsSmallScenery()->GetSceneryQuadrant() + rotation) & 3; x_offset = ScenerySubTileOffsets[ecx].x; y_offset = ScenerySubTileOffsets[ecx].y; boxoffset.x = x_offset; @@ -386,7 +386,7 @@ void scenery_paint(paint_session* session, uint8_t direction, int32_t height, co if (scenery_small_entry_has_flag(entry, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)) { // 6E075C: - direction = (tileElement->GetSceneryQuadrant() + rotation) % 4; + direction = (tileElement->AsSmallScenery()->GetSceneryQuadrant() + rotation) % 4; paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), height, 0x20); return; @@ -404,7 +404,7 @@ void scenery_paint(paint_session* session, uint8_t direction, int32_t height, co } if (scenery_small_entry_has_flag(entry, SMALL_SCENERY_FLAG_VOFFSET_CENTRE)) { - direction = (tileElement->GetSceneryQuadrant() + rotation) % 4; + direction = (tileElement->AsSmallScenery()->GetSceneryQuadrant() + rotation) % 4; paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), 0xFFFF, 0); return; diff --git a/src/openrct2/world/TileElement.cpp b/src/openrct2/world/TileElement.cpp index 0e9e7f6522..41b06ce4ea 100644 --- a/src/openrct2/world/TileElement.cpp +++ b/src/openrct2/world/TileElement.cpp @@ -17,44 +17,49 @@ #include "LargeScenery.h" #include "Scenery.h" -uint8_t rct_tile_element::GetType() const +uint8_t TileElementBase::GetType() const { return this->type & TILE_ELEMENT_TYPE_MASK; } -void rct_tile_element::SetType(uint8_t newType) +void TileElementBase::SetType(uint8_t newType) { this->type &= ~TILE_ELEMENT_TYPE_MASK; this->type |= (newType & TILE_ELEMENT_TYPE_MASK); } -uint8_t rct_tile_element::GetDirection() const +uint8_t TileElementBase::GetDirection() const { return this->type & TILE_ELEMENT_DIRECTION_MASK; } -void rct_tile_element::SetDirection(uint8_t direction) +void TileElementBase::SetDirection(uint8_t direction) { this->type &= ~TILE_ELEMENT_DIRECTION_MASK; this->type |= (direction & TILE_ELEMENT_DIRECTION_MASK); } -uint8_t rct_tile_element::GetDirectionWithOffset(uint8_t offset) const +uint8_t TileElementBase::GetDirectionWithOffset(uint8_t offset) const { return ((this->type & TILE_ELEMENT_DIRECTION_MASK) + offset) & TILE_ELEMENT_DIRECTION_MASK; } -bool rct_tile_element::IsLastForTile() const +bool TileElementBase::IsLastForTile() const { return (this->flags & TILE_ELEMENT_FLAG_LAST_TILE) != 0; } -bool rct_tile_element::IsGhost() const +bool TileElementBase::IsGhost() const { return (this->flags & TILE_ELEMENT_FLAG_GHOST) != 0; } -uint8_t rct_tile_element::GetSceneryQuadrant() const +uint8_t SmallSceneryElement::GetSceneryQuadrant() const +{ + return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6; +} + +uint8_t WallElement::GetSlope() const { return (this->type & TILE_ELEMENT_QUADRANT_MASK) >> 6; } diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 86166f4b11..64ccaca4ef 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -121,38 +121,6 @@ union rct_tile_element_properties }; assert_struct_size(rct_tile_element_properties, 4); -/** - * Map element structure - * size: 0x08 - */ -struct rct_tile_element -{ - uint8_t type; // 0 - uint8_t flags; // 1 - uint8_t base_height; // 2 - uint8_t clearance_height; // 3 - rct_tile_element_properties properties; - - uint8_t GetType() const; - void SetType(uint8_t newType); - uint8_t GetDirection() const; - void SetDirection(uint8_t direction); - uint8_t GetDirectionWithOffset(uint8_t offset) const; - bool IsLastForTile() const; - bool IsGhost() const; - uint8_t GetSceneryQuadrant() const; -}; -assert_struct_size(rct_tile_element, 8); -#pragma pack(pop) - -enum -{ - TILE_ELEMENT_QUADRANT_SW, - TILE_ELEMENT_QUADRANT_NW, - TILE_ELEMENT_QUADRANT_NE, - TILE_ELEMENT_QUADRANT_SE -}; - enum { TILE_ELEMENT_TYPE_SURFACE = (0 << 2), @@ -168,6 +136,143 @@ enum TILE_ELEMENT_TYPE_CORRUPT = (8 << 2), }; +enum class TileElementType : uint8_t +{ + Surface = (0 << 2), + Path = (1 << 2), + Track = (2 << 2), + SmallScenery = (3 << 2), + Entrance = (4 << 2), + Wall = (5 << 2), + LargeScenery = (6 << 2), + Banner = (7 << 2), + Corrupt = (8 << 2), +}; + +struct SurfaceElement; +struct PathElement; +struct TrackElement; +struct SmallSceneryElement; +struct LargeSceneryElement; +struct WallElement; +struct EntranceElement; +struct BannerElement; +struct CorruptElement; + +struct TileElementBase +{ + uint8_t type; // 0 + uint8_t flags; // 1 + uint8_t base_height; // 2 + uint8_t clearance_height; // 3 + + uint8_t GetType() const; + void SetType(uint8_t newType); + uint8_t GetDirection() const; + void SetDirection(uint8_t direction); + uint8_t GetDirectionWithOffset(uint8_t offset) const; + bool IsLastForTile() const; + bool IsGhost() const; +}; + + +/** + * Map element structure + * size: 0x08 + */ +struct rct_tile_element : public TileElementBase +{ + // TODO: Remove this field. + rct_tile_element_properties properties; + + template + TType* as() const + { + return (TileElementType)GetType() == TClass ? (TType*)this : nullptr; + } + +public: + SurfaceElement* AsSurface() const { return as(); } + PathElement* AsPath() const { return as(); } + TrackElement* AsTrack() const { return as(); } + SmallSceneryElement* AsSmallScenery() const { return as(); } + LargeSceneryElement* AsLargeScenery() const { return as(); } + WallElement* AsWall() const { return as(); } + EntranceElement* AsEntrance() const { return as(); } + BannerElement* AsBanner() const { return as(); } + CorruptElement* AsCorrupt() const { return as(); } +}; +assert_struct_size(rct_tile_element, 8); + +struct SurfaceElement : TileElementBase +{ + rct_tile_element_surface_properties temp; +}; +assert_struct_size(SurfaceElement, 8); + +struct PathElement : TileElementBase +{ + rct_tile_element_path_properties temp; +}; +assert_struct_size(PathElement, 8); + +struct TrackElement : TileElementBase +{ + rct_tile_element_track_properties temp; +}; +assert_struct_size(TrackElement, 8); + +struct SmallSceneryElement : TileElementBase +{ + rct_tile_element_scenery_properties temp; +public: + uint8_t GetSceneryQuadrant() const; +}; +assert_struct_size(SmallSceneryElement, 8); + +struct LargeSceneryElement : TileElementBase +{ + rct_tile_element_scenerymultiple_properties temp; +}; +assert_struct_size(LargeSceneryElement, 8); + +struct WallElement : TileElementBase +{ + rct_tile_element_wall_properties temp; +public: + uint8_t GetSlope() const; +}; +assert_struct_size(WallElement, 8); + +struct EntranceElement : TileElementBase +{ + rct_tile_element_entrance_properties temp; +}; +assert_struct_size(EntranceElement, 8); + +struct BannerElement : TileElementBase +{ + rct_tile_element_banner_properties temp; +}; +assert_struct_size(BannerElement, 8); + +struct CorruptElement : TileElementBase +{ + uint8_t pad[4]; +}; +assert_struct_size(CorruptElement, 8); + + +#pragma pack(pop) + +enum +{ + TILE_ELEMENT_QUADRANT_SW, + TILE_ELEMENT_QUADRANT_NW, + TILE_ELEMENT_QUADRANT_NE, + TILE_ELEMENT_QUADRANT_SE +}; + enum { TILE_ELEMENT_TYPE_FLAG_HIGHLIGHT = (1 << 6)