mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #16151 from IntelOrca/refactor/imageid-painting
Refactor most map paint routines to use ImageId
This commit is contained in:
commit
b4f256be87
|
@ -1474,9 +1474,9 @@ static bool is_pixel_present_rle(const uint8_t* esi, int32_t x_start_point, int3
|
|||
* @return value originally stored in 0x00141F569
|
||||
*/
|
||||
static bool is_sprite_interacted_with_palette_set(
|
||||
rct_drawpixelinfo* dpi, int32_t imageId, const ScreenCoordsXY& coords, const PaletteMap& paletteMap)
|
||||
rct_drawpixelinfo* dpi, ImageId imageId, const ScreenCoordsXY& coords, const PaletteMap& paletteMap)
|
||||
{
|
||||
const rct_g1_element* g1 = gfx_get_g1_element(imageId & 0x7FFFF);
|
||||
const rct_g1_element* g1 = gfx_get_g1_element(imageId);
|
||||
if (g1 == nullptr)
|
||||
{
|
||||
return false;
|
||||
|
@ -1502,8 +1502,8 @@ static bool is_sprite_interacted_with_palette_set(
|
|||
/* .zoom_level = */ dpi->zoom_level - 1,
|
||||
};
|
||||
|
||||
return is_sprite_interacted_with_palette_set(
|
||||
&zoomed_dpi, imageId - g1->zoomed_offset, { coords.x / 2, coords.y / 2 }, paletteMap);
|
||||
auto zoomImageId = imageId.WithIndex(imageId.GetIndex() - g1->zoomed_offset);
|
||||
return is_sprite_interacted_with_palette_set(&zoomed_dpi, zoomImageId, { coords.x / 2, coords.y / 2 }, paletteMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1618,19 +1618,22 @@ static bool is_sprite_interacted_with_palette_set(
|
|||
* rct2: 0x00679023
|
||||
*/
|
||||
|
||||
static bool is_sprite_interacted_with(rct_drawpixelinfo* dpi, int32_t imageId, const ScreenCoordsXY& coords)
|
||||
static bool is_sprite_interacted_with(rct_drawpixelinfo* dpi, ImageId imageId, const ScreenCoordsXY& coords)
|
||||
{
|
||||
auto paletteMap = PaletteMap::GetDefault();
|
||||
imageId &= ~IMAGE_TYPE_TRANSPARENT;
|
||||
if (imageId & IMAGE_TYPE_REMAP)
|
||||
if (imageId.HasPrimary() || imageId.IsRemap())
|
||||
{
|
||||
_currentImageType = IMAGE_TYPE_REMAP;
|
||||
int32_t index = (imageId >> 19) & 0x7F;
|
||||
if (imageId & IMAGE_TYPE_REMAP_2_PLUS)
|
||||
uint8_t paletteIndex;
|
||||
if (imageId.HasSecondary())
|
||||
{
|
||||
index &= 0x1F;
|
||||
paletteIndex = imageId.GetPrimary();
|
||||
}
|
||||
if (auto pm = GetPaletteMapForColour(index); pm.has_value())
|
||||
else
|
||||
{
|
||||
paletteIndex = imageId.GetRemap();
|
||||
}
|
||||
if (auto pm = GetPaletteMapForColour(paletteIndex); pm.has_value())
|
||||
{
|
||||
paletteMap = pm.value();
|
||||
}
|
||||
|
@ -1659,7 +1662,8 @@ InteractionInfo set_interaction_info_from_paint_session(paint_session* session,
|
|||
while (next_ps != nullptr)
|
||||
{
|
||||
ps = next_ps;
|
||||
if (is_sprite_interacted_with(dpi, ps->image_id, { ps->x, ps->y }))
|
||||
auto imageId = ImageId::FromUInt32(ps->image_id, ps->tertiary_colour);
|
||||
if (is_sprite_interacted_with(dpi, imageId, { ps->x, ps->y }))
|
||||
{
|
||||
if (PSSpriteTypeIsInFilter(ps, filter))
|
||||
{
|
||||
|
@ -1671,7 +1675,8 @@ InteractionInfo set_interaction_info_from_paint_session(paint_session* session,
|
|||
|
||||
for (attached_paint_struct* attached_ps = ps->attached_ps; attached_ps != nullptr; attached_ps = attached_ps->next)
|
||||
{
|
||||
if (is_sprite_interacted_with(dpi, attached_ps->image_id, { (attached_ps->x + ps->x), (attached_ps->y + ps->y) }))
|
||||
auto imageId = ImageId::FromUInt32(attached_ps->image_id, attached_ps->tertiary_colour);
|
||||
if (is_sprite_interacted_with(dpi, imageId, { (attached_ps->x + ps->x), (attached_ps->y + ps->y) }))
|
||||
{
|
||||
if (PSSpriteTypeIsInFilter(ps, filter))
|
||||
{
|
||||
|
|
|
@ -65,3 +65,20 @@ void EntranceObject::ReadJson(IReadObjectContext* context, json_t& root)
|
|||
|
||||
PopulateTablesFromJson(context, root);
|
||||
}
|
||||
|
||||
ImageIndex EntranceObject::GetImage(uint8_t sequence, Direction direction) const
|
||||
{
|
||||
if (sequence > 2)
|
||||
return ImageIndexUndefined;
|
||||
return _legacyType.image_id + ((direction & 3) * 3) + sequence;
|
||||
}
|
||||
|
||||
uint8_t EntranceObject::GetScrollingMode() const
|
||||
{
|
||||
return _legacyType.scrolling_mode;
|
||||
}
|
||||
|
||||
uint8_t EntranceObject::GetTextHeight() const
|
||||
{
|
||||
return _legacyType.text_height;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../world/Entrance.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "Object.h"
|
||||
|
||||
class EntranceObject final : public Object
|
||||
|
@ -29,4 +30,8 @@ public:
|
|||
void Unload() override;
|
||||
|
||||
void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override;
|
||||
|
||||
ImageIndex GetImage(uint8_t sequence, Direction direction) const;
|
||||
uint8_t GetScrollingMode() const;
|
||||
uint8_t GetTextHeight() const;
|
||||
};
|
||||
|
|
|
@ -41,8 +41,8 @@ void StationObject::Unload()
|
|||
gfx_object_free_images(BaseImageId, GetImageTable().GetCount());
|
||||
|
||||
NameStringId = 0;
|
||||
BaseImageId = 0;
|
||||
ShelterImageId = 0;
|
||||
BaseImageId = ImageIndexUndefined;
|
||||
ShelterImageId = ImageIndexUndefined;
|
||||
}
|
||||
|
||||
void StationObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../drawing/ImageId.hpp"
|
||||
#include "Object.h"
|
||||
|
||||
namespace STATION_OBJECT_FLAGS
|
||||
|
@ -24,8 +25,8 @@ class StationObject final : public Object
|
|||
{
|
||||
public:
|
||||
rct_string_id NameStringId{};
|
||||
uint32_t BaseImageId{};
|
||||
uint32_t ShelterImageId{};
|
||||
ImageIndex BaseImageId = ImageIndexUndefined;
|
||||
ImageIndex ShelterImageId = ImageIndexUndefined;
|
||||
uint32_t Flags{};
|
||||
int32_t Height{};
|
||||
uint8_t ScrollingMode{};
|
||||
|
|
|
@ -177,6 +177,7 @@ static paint_struct* CreateNormalPaintStruct(
|
|||
}
|
||||
|
||||
ps->image_id = image_id.ToUInt32();
|
||||
ps->tertiary_colour = image_id.GetTertiary();
|
||||
ps->x = imagePos.x;
|
||||
ps->y = imagePos.y;
|
||||
ps->bounds.x_end = rotBoundBoxSize.x + rotBoundBoxOffset.x + session->SpritePosition.x;
|
||||
|
@ -867,12 +868,12 @@ paint_struct* PaintAddImageAsChild(
|
|||
* @param y (cx)
|
||||
* @return (!CF) success
|
||||
*/
|
||||
bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int32_t x, int32_t y)
|
||||
bool PaintAttachToPreviousAttach(paint_session* session, ImageId imageId, int32_t x, int32_t y)
|
||||
{
|
||||
auto* previousAttachedPS = session->LastAttachedPS;
|
||||
if (previousAttachedPS == nullptr)
|
||||
{
|
||||
return PaintAttachToPreviousPS(session, image_id, x, y);
|
||||
return PaintAttachToPreviousPS(session, imageId, x, y);
|
||||
}
|
||||
|
||||
auto* ps = session->AllocateAttachedPaintEntry();
|
||||
|
@ -881,7 +882,8 @@ bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int3
|
|||
return false;
|
||||
}
|
||||
|
||||
ps->image_id = image_id;
|
||||
ps->image_id = imageId.ToUInt32();
|
||||
ps->tertiary_colour = imageId.GetTertiary();
|
||||
ps->x = x;
|
||||
ps->y = y;
|
||||
ps->flags = 0;
|
||||
|
@ -920,6 +922,7 @@ bool PaintAttachToPreviousPS(paint_session* session, ImageId image_id, int32_t x
|
|||
}
|
||||
|
||||
ps->image_id = image_id.ToUInt32();
|
||||
ps->tertiary_colour = image_id.GetTertiary();
|
||||
ps->x = x;
|
||||
ps->y = y;
|
||||
ps->flags = 0;
|
||||
|
|
|
@ -331,7 +331,7 @@ paint_struct* PaintAddImageAsParentRotated(
|
|||
|
||||
void paint_util_push_tunnel_rotated(paint_session* session, uint8_t direction, uint16_t height, uint8_t type);
|
||||
|
||||
bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int32_t x, int32_t y);
|
||||
bool PaintAttachToPreviousAttach(paint_session* session, ImageId imageId, int32_t x, int32_t y);
|
||||
bool PaintAttachToPreviousPS(paint_session* session, ImageId image_id, int32_t x, int32_t y);
|
||||
bool PaintAttachToPreviousPS(paint_session* session, uint32_t image_id, int32_t x, int32_t y);
|
||||
void PaintFloatingMoneyEffect(
|
||||
|
|
|
@ -1169,7 +1169,7 @@ bool metal_b_supports_paint_setup(
|
|||
* @return Whether supports were drawn
|
||||
*/
|
||||
bool path_a_supports_paint_setup(
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
|
||||
const FootpathPaintInfo& pathPaintInfo, bool* underground)
|
||||
{
|
||||
if (underground != nullptr)
|
||||
|
@ -1204,7 +1204,7 @@ bool path_a_supports_paint_setup(
|
|||
{
|
||||
// save dx2
|
||||
PaintAddImageAsParent(
|
||||
session, (pathPaintInfo.BridgeImageId + 48) | imageColourFlags, { 0, 0, baseHeight - 2 }, { 32, 32, 0 });
|
||||
session, imageTemplate.WithIndex(pathPaintInfo.BridgeImageId + 48), { 0, 0, baseHeight - 2 }, { 32, 32, 0 });
|
||||
hasSupports = true;
|
||||
}
|
||||
else if (session->Support.slope & 0x10)
|
||||
|
@ -1221,11 +1221,11 @@ bool path_a_supports_paint_setup(
|
|||
+ pathPaintInfo.BridgeImageId;
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
session, imageTemplate.WithIndex(imageId), { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
baseHeight += 16;
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, (imageId + 4) | imageColourFlags, { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
session, imageTemplate.WithIndex(imageId + 4), { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
baseHeight += 16;
|
||||
|
||||
hasSupports = true;
|
||||
|
@ -1243,7 +1243,8 @@ bool path_a_supports_paint_setup(
|
|||
uint32_t ebx = (supportType * 24) + word_97B3C4[session->Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
|
||||
+ pathPaintInfo.BridgeImageId;
|
||||
|
||||
PaintAddImageAsParent(session, ebx | imageColourFlags, { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
PaintAddImageAsParent(
|
||||
session, imageTemplate.WithIndex(ebx), { 0, 0, baseHeight }, { 32, 32, 11 }, { 0, 0, baseHeight + 2 });
|
||||
|
||||
hasSupports = true;
|
||||
baseHeight += 16;
|
||||
|
@ -1256,7 +1257,7 @@ bool path_a_supports_paint_setup(
|
|||
uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 23;
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 1) ? 7 : 12) });
|
||||
session, imageTemplate.WithIndex(imageId), { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 1) ? 7 : 12) });
|
||||
heightSteps -= 1;
|
||||
baseHeight += 16;
|
||||
hasSupports = true;
|
||||
|
@ -1266,7 +1267,7 @@ bool path_a_supports_paint_setup(
|
|||
uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 22;
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 2) ? 23 : 28) });
|
||||
session, imageTemplate.WithIndex(imageId), { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 2) ? 23 : 28) });
|
||||
heightSteps -= 2;
|
||||
baseHeight += 32;
|
||||
hasSupports = true;
|
||||
|
@ -1277,7 +1278,7 @@ bool path_a_supports_paint_setup(
|
|||
{
|
||||
uint16_t specialIndex = (special - 1) & 0xFFFF;
|
||||
|
||||
uint32_t imageId = pathPaintInfo.BridgeImageId + 55 + specialIndex;
|
||||
ImageIndex imageIndex = pathPaintInfo.BridgeImageId + 55 + specialIndex;
|
||||
|
||||
const unk_supports_desc& supportsDesc = byte_98D8D4[specialIndex];
|
||||
const unk_supports_desc_bound_box& boundBox = supportsDesc.bounding_box;
|
||||
|
@ -1285,14 +1286,14 @@ bool path_a_supports_paint_setup(
|
|||
if (supportsDesc.var_6 == 0 || session->WoodenSupportsPrependTo == nullptr)
|
||||
{
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { 0, 0, baseHeight }, boundBox.length,
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, baseHeight }, boundBox.length,
|
||||
{ boundBox.offset.x, boundBox.offset.y, baseHeight + boundBox.offset.z });
|
||||
hasSupports = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_struct* paintStruct = PaintAddImageAsOrphan(
|
||||
session, ImageId::FromUInt32(imageId | imageColourFlags), { 0, 0, baseHeight }, boundBox.length,
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, baseHeight }, boundBox.length,
|
||||
{ boundBox.offset.x, boundBox.offset.y, baseHeight + boundBox.offset.z });
|
||||
hasSupports = true;
|
||||
if (paintStruct != nullptr)
|
||||
|
@ -1321,7 +1322,7 @@ bool path_a_supports_paint_setup(
|
|||
* @return Whether supports were drawn
|
||||
*/
|
||||
bool path_b_supports_paint_setup(
|
||||
paint_session* session, int32_t segment, int32_t special, int32_t height, uint32_t imageColourFlags,
|
||||
paint_session* session, int32_t segment, int32_t special, int32_t height, ImageId imageTemplate,
|
||||
const FootpathPaintInfo& pathPaintInfo)
|
||||
{
|
||||
support_height* supportSegments = session->SupportSegments;
|
||||
|
@ -1354,7 +1355,7 @@ bool path_b_supports_paint_setup(
|
|||
baseHeight = supportSegments[segment].height;
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, (pathPaintInfo.BridgeImageId + 37 + imageOffset) | imageColourFlags,
|
||||
session, imageTemplate.WithIndex(pathPaintInfo.BridgeImageId + 37 + imageOffset),
|
||||
{ SupportBoundBoxes[segment].x, SupportBoundBoxes[segment].y, baseHeight }, { 0, 0, 5 });
|
||||
baseHeight += 6;
|
||||
}
|
||||
|
@ -1373,7 +1374,7 @@ bool path_b_supports_paint_setup(
|
|||
if (heightDiff > 0)
|
||||
{
|
||||
PaintAddImageAsParent(
|
||||
session, (pathPaintInfo.BridgeImageId + 20 + (heightDiff - 1)) | imageColourFlags,
|
||||
session, imageTemplate.WithIndex(pathPaintInfo.BridgeImageId + 20 + (heightDiff - 1)),
|
||||
{ SupportBoundBoxes[segment], baseHeight }, { 0, 0, heightDiff - 1 });
|
||||
}
|
||||
|
||||
|
@ -1406,7 +1407,7 @@ bool path_b_supports_paint_setup(
|
|||
}
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, (pathPaintInfo.BridgeImageId + 20 + (z - 1)) | imageColourFlags,
|
||||
session, imageTemplate.WithIndex(pathPaintInfo.BridgeImageId + 20 + (z - 1)),
|
||||
{ SupportBoundBoxes[segment], baseHeight }, { 0, 0, (z - 1) });
|
||||
|
||||
baseHeight += z;
|
||||
|
@ -1417,14 +1418,14 @@ bool path_b_supports_paint_setup(
|
|||
break;
|
||||
}
|
||||
|
||||
uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1);
|
||||
ImageIndex imageIndex = pathPaintInfo.BridgeImageId + 20 + (z - 1);
|
||||
if (z == 16)
|
||||
{
|
||||
imageId += 1;
|
||||
imageIndex += 1;
|
||||
}
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { SupportBoundBoxes[segment], baseHeight }, { 0, 0, (z - 1) });
|
||||
session, imageTemplate.WithIndex(imageIndex), { SupportBoundBoxes[segment], baseHeight }, { 0, 0, (z - 1) });
|
||||
|
||||
baseHeight += z;
|
||||
}
|
||||
|
@ -1451,9 +1452,9 @@ bool path_b_supports_paint_setup(
|
|||
break;
|
||||
}
|
||||
|
||||
uint32_t imageId = pathPaintInfo.BridgeImageId + 20 + (z - 1);
|
||||
ImageIndex imageIndex = pathPaintInfo.BridgeImageId + 20 + (z - 1);
|
||||
PaintAddImageAsParent(
|
||||
session, imageId | imageColourFlags, { SupportBoundBoxes[segment], baseHeight }, { 0, 0, 0 },
|
||||
session, imageTemplate.WithIndex(imageIndex), { SupportBoundBoxes[segment], baseHeight }, { 0, 0, 0 },
|
||||
{ SupportBoundBoxes[segment], baseHeight });
|
||||
|
||||
baseHeight += z;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
#include "../drawing/ImageId.hpp"
|
||||
#include "../world/Footpath.h"
|
||||
|
||||
struct FootpathPaintInfo;
|
||||
|
@ -25,10 +26,10 @@ bool metal_a_supports_paint_setup(
|
|||
bool metal_b_supports_paint_setup(
|
||||
paint_session* session, uint8_t supportType, uint8_t segment, int32_t special, int32_t height, uint32_t imageColourFlags);
|
||||
bool path_a_supports_paint_setup(
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
|
||||
const FootpathPaintInfo& pathPaintInfo, bool* underground);
|
||||
bool path_b_supports_paint_setup(
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, uint32_t imageColourFlags,
|
||||
paint_session* session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
|
||||
const FootpathPaintInfo& pathPaintInfo);
|
||||
|
||||
// There are 13 types of metal supports. A graphic showing all of them is available here:
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "../Paint.h"
|
||||
#include "Paint.TileElement.h"
|
||||
|
||||
/** rct2: 0x0098D884 */
|
||||
// BannerBoundBoxes[rotation][0] is for the pole in the back
|
||||
// BannerBoundBoxes[rotation][1] is for the pole and the banner in the front
|
||||
constexpr CoordsXY BannerBoundBoxes[][2] = {
|
||||
|
@ -29,20 +28,45 @@ constexpr CoordsXY BannerBoundBoxes[][2] = {
|
|||
{ { 2, 1 }, { 29, 1 } },
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B9CC4
|
||||
*/
|
||||
void PaintBanner(paint_session* session, uint8_t direction, int32_t height, const BannerElement& bannerElement)
|
||||
static void PaintBannerScrollingText(
|
||||
paint_session* session, const BannerSceneryEntry& bannerEntry, Banner& banner, const BannerElement& bannerElement,
|
||||
Direction direction, int32_t height, const CoordsXYZ& bbOffset)
|
||||
{
|
||||
rct_drawpixelinfo* dpi = &session->DPI;
|
||||
|
||||
session->InteractionType = ViewportInteractionItem::Banner;
|
||||
|
||||
if (dpi->zoom_level > ZoomLevel{ 1 } || gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
// If text on hidden direction or ghost
|
||||
direction = direction_reverse(direction) - 1;
|
||||
if (direction >= 2 || (bannerElement.IsGhost()))
|
||||
return;
|
||||
|
||||
height -= 16;
|
||||
auto scrollingMode = bannerEntry.scrolling_mode + (direction & 3);
|
||||
if (scrollingMode >= MAX_SCROLLING_TEXT_MODES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto ft = Formatter();
|
||||
banner.FormatTextTo(ft, true);
|
||||
|
||||
char text[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
|
||||
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
||||
auto scroll = (gCurrentTicks / 2) % stringWidth;
|
||||
auto imageId = scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode, COLOUR_BLACK);
|
||||
PaintAddImageAsChild(session, imageId, { 0, 0, height + 22 }, { 1, 1, 21 }, bbOffset);
|
||||
}
|
||||
|
||||
void PaintBanner(paint_session* session, uint8_t direction, int32_t height, const BannerElement& bannerElement)
|
||||
{
|
||||
if (session->DPI.zoom_level > ZoomLevel{ 1 } || gTrackDesignSaveMode
|
||||
|| (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
return;
|
||||
|
||||
auto banner = bannerElement.GetBanner();
|
||||
if (banner == nullptr)
|
||||
|
@ -56,65 +80,35 @@ void PaintBanner(paint_session* session, uint8_t direction, int32_t height, cons
|
|||
return;
|
||||
}
|
||||
|
||||
session->InteractionType = ViewportInteractionItem::Banner;
|
||||
|
||||
height -= 16;
|
||||
|
||||
direction += bannerElement.GetPosition();
|
||||
direction &= 3;
|
||||
|
||||
CoordsXYZ boundBoxOffset = CoordsXYZ(BannerBoundBoxes[direction][0], height + 2);
|
||||
|
||||
uint32_t base_id = (direction << 1) + bannerEntry->image;
|
||||
uint32_t image_id = base_id;
|
||||
|
||||
if (bannerElement.IsGhost()) // if being placed
|
||||
ImageId imageTemplate;
|
||||
if (bannerElement.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&bannerElement)))
|
||||
{
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
else
|
||||
{
|
||||
image_id |= (banner->colour << 19) | IMAGE_TYPE_REMAP;
|
||||
imageTemplate = ImageId().WithPrimary(banner->colour);
|
||||
}
|
||||
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 1, 1, 0x15 }, boundBoxOffset);
|
||||
boundBoxOffset.x = BannerBoundBoxes[direction][1].x;
|
||||
boundBoxOffset.y = BannerBoundBoxes[direction][1].y;
|
||||
auto imageIndex = (direction << 1) + bannerEntry->image;
|
||||
auto imageId = imageTemplate.WithIndex(imageIndex);
|
||||
auto bbOffset = CoordsXYZ(BannerBoundBoxes[direction][0], height + 2);
|
||||
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 1, 1, 21 }, bbOffset);
|
||||
|
||||
image_id++;
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 1, 1, 0x15 }, boundBoxOffset);
|
||||
bbOffset = CoordsXYZ(BannerBoundBoxes[direction][1], height + 2);
|
||||
PaintAddImageAsParent(session, imageId.WithIndexOffset(1), { 0, 0, height }, { 1, 1, 21 }, bbOffset);
|
||||
|
||||
// Opposite direction
|
||||
direction = direction_reverse(direction);
|
||||
direction--;
|
||||
// If text not showing / ghost
|
||||
if (direction >= 2 || (bannerElement.IsGhost()))
|
||||
return;
|
||||
|
||||
uint16_t scrollingMode = bannerEntry->scrolling_mode;
|
||||
if (scrollingMode >= MAX_SCROLLING_TEXT_MODES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scrollingMode += direction;
|
||||
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft, /*addColour*/ true);
|
||||
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
|
||||
uint16_t string_width = gfx_get_string_width(gCommonStringFormatBuffer, FontSpriteBase::TINY);
|
||||
uint16_t scroll = (gCurrentTicks / 2) % string_width;
|
||||
auto scrollIndex = scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode, COLOUR_BLACK);
|
||||
PaintAddImageAsChild(
|
||||
session, scrollIndex, 0, 0, 1, 1, 0x15, height + 22, boundBoxOffset.x, boundBoxOffset.y, boundBoxOffset.z);
|
||||
PaintBannerScrollingText(session, *bannerEntry, *banner, bannerElement, direction, height, bbOffset);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "../../drawing/LightFX.h"
|
||||
#include "../../interface/Viewport.h"
|
||||
#include "../../localisation/Localisation.h"
|
||||
#include "../../object/EntranceObject.h"
|
||||
#include "../../object/ObjectManager.h"
|
||||
#include "../../object/StationObject.h"
|
||||
#include "../../ride/RideData.h"
|
||||
#include "../../ride/TrackDesign.h"
|
||||
|
@ -26,30 +28,61 @@
|
|||
#include "../Supports.h"
|
||||
#include "Paint.TileElement.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066508C, 0x00665540
|
||||
*/
|
||||
static void ride_entrance_exit_paint(
|
||||
paint_session* session, uint8_t direction, int32_t height, const EntranceElement& tile_element)
|
||||
{
|
||||
uint8_t is_exit = tile_element.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT;
|
||||
using namespace OpenRCT2;
|
||||
|
||||
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
static void PaintRideEntranceExitScrollingText(
|
||||
paint_session* session, const EntranceElement& entranceEl, const StationObject& stationObj, Direction direction,
|
||||
int32_t height)
|
||||
{
|
||||
if (stationObj.ScrollingMode == SCROLLING_MODE_NONE)
|
||||
return;
|
||||
|
||||
if (entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT)
|
||||
return;
|
||||
|
||||
auto ride = get_ride(entranceEl.GetRideIndex());
|
||||
if (ride == nullptr)
|
||||
return;
|
||||
|
||||
auto ft = Formatter();
|
||||
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_NAME);
|
||||
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
||||
{
|
||||
if (tile_element.GetRideIndex() != gTrackDesignSaveRideIndex)
|
||||
return;
|
||||
ride->FormatNameTo(ft);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_CLOSED);
|
||||
}
|
||||
|
||||
char text[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
||||
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
|
||||
PaintAddImageAsChild(
|
||||
session, scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, stationObj.ScrollingMode, COLOUR_BLACK), 0,
|
||||
0, 28, 28, 51, height + stationObj.Height, 2, 2, height + stationObj.Height);
|
||||
}
|
||||
|
||||
static void PaintRideEntranceExitLightEffects(paint_session* session, int32_t height, const EntranceElement& entranceEl)
|
||||
{
|
||||
#ifdef __ENABLE_LIGHTFX__
|
||||
if (lightfx_is_available())
|
||||
{
|
||||
if (!is_exit)
|
||||
if (entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE)
|
||||
{
|
||||
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 0, 0, height + 45, LightType::Lantern3);
|
||||
}
|
||||
|
||||
switch (tile_element.GetDirection())
|
||||
switch (entranceEl.GetDirection())
|
||||
{
|
||||
case 0:
|
||||
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 16, 0, height + 16, LightType::Lantern2);
|
||||
|
@ -66,8 +99,18 @@ static void ride_entrance_exit_paint(
|
|||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
auto ride = get_ride(tile_element.GetRideIndex());
|
||||
static void PaintRideEntranceExit(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceEl)
|
||||
{
|
||||
auto rideIndex = entranceEl.GetRideIndex();
|
||||
if ((gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
&& (rideIndex != gTrackDesignSaveRideIndex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto ride = get_ride(rideIndex);
|
||||
if (ride == nullptr)
|
||||
{
|
||||
return;
|
||||
|
@ -79,44 +122,28 @@ static void ride_entrance_exit_paint(
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t colour_1, colour_2;
|
||||
uint32_t transparant_image_id = 0, image_id = 0;
|
||||
if (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
|
||||
session->InteractionType = ViewportInteractionItem::Ride;
|
||||
|
||||
PaintRideEntranceExitLightEffects(session, height, entranceEl);
|
||||
|
||||
auto hasGlass = (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT) != 0;
|
||||
auto colourPrimary = ride->track_colour[0].main;
|
||||
auto colourSecondary = ride->track_colour[0].additional;
|
||||
auto imageTemplate = ImageId(0, colourPrimary, colourSecondary);
|
||||
ImageId glassImageTemplate;
|
||||
if (hasGlass)
|
||||
{
|
||||
colour_1 = EnumValue(GlassPaletteIds[ride->track_colour[0].main]);
|
||||
transparant_image_id = (colour_1 << 19) | IMAGE_TYPE_TRANSPARENT;
|
||||
glassImageTemplate = ImageId().WithTransparancy(colourPrimary);
|
||||
}
|
||||
|
||||
colour_1 = ride->track_colour[0].main;
|
||||
colour_2 = ride->track_colour[0].additional;
|
||||
image_id = (colour_1 << 19) | (colour_2 << 24) | IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS;
|
||||
|
||||
session->InteractionType = ViewportInteractionItem::Ride;
|
||||
uint32_t entranceImageId = 0;
|
||||
|
||||
if (tile_element.IsGhost())
|
||||
if (entranceEl.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
image_id = CONSTRUCTION_MARKER;
|
||||
entranceImageId = image_id;
|
||||
if (transparant_image_id)
|
||||
transparant_image_id = image_id;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&tile_element)))
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&entranceEl)))
|
||||
{
|
||||
image_id = CONSTRUCTION_MARKER;
|
||||
entranceImageId = image_id;
|
||||
if (transparant_image_id)
|
||||
transparant_image_id = image_id;
|
||||
}
|
||||
|
||||
if (is_exit)
|
||||
{
|
||||
image_id |= stationObj->BaseImageId + direction + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
image_id |= stationObj->BaseImageId + direction;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
// Format modified to stop repeated code
|
||||
|
@ -124,250 +151,206 @@ static void ride_entrance_exit_paint(
|
|||
// Each entrance is split into 2 images for drawing
|
||||
// Certain entrance styles have another 2 images to draw for coloured windows
|
||||
|
||||
int8_t ah = is_exit ? 0x23 : 0x33;
|
||||
|
||||
int16_t lengthY = (direction & 1) ? 28 : 2;
|
||||
int16_t lengthX = (direction & 1) ? 2 : 28;
|
||||
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { lengthX, lengthY, ah }, { 2, 2, height });
|
||||
|
||||
if (transparant_image_id)
|
||||
{
|
||||
if (is_exit)
|
||||
{
|
||||
transparant_image_id |= stationObj->BaseImageId + direction + 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
transparant_image_id |= stationObj->BaseImageId + direction + 16;
|
||||
}
|
||||
|
||||
PaintAddImageAsChild(session, transparant_image_id, 0, 0, lengthX, lengthY, ah, height, 2, 2, height);
|
||||
}
|
||||
|
||||
image_id += 4;
|
||||
auto isExit = entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT;
|
||||
auto lengthY = (direction & 1) ? 28 : 2;
|
||||
auto lengthX = (direction & 1) ? 2 : 28;
|
||||
auto lengthZ = isExit ? 35 : 51;
|
||||
|
||||
// Back
|
||||
ImageIndex imageIndex = isExit ? stationObj->BaseImageId + direction + 8 : stationObj->BaseImageId + direction;
|
||||
ImageIndex glassImageIndex = isExit ? stationObj->BaseImageId + direction + 24 : stationObj->BaseImageId + direction + 16;
|
||||
PaintAddImageAsParent(
|
||||
session, image_id, { 0, 0, height }, { lengthX, lengthY, ah },
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ }, { 2, 2, height });
|
||||
if (hasGlass)
|
||||
{
|
||||
PaintAddImageAsChild(
|
||||
session, glassImageTemplate.WithIndex(glassImageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
||||
{ 2, 2, height });
|
||||
}
|
||||
|
||||
// Front
|
||||
imageIndex += 4;
|
||||
PaintAddImageAsParent(
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
||||
{ (direction & 1) ? 28 : 2, (direction & 1) ? 2 : 28, height });
|
||||
|
||||
if (transparant_image_id)
|
||||
if (hasGlass)
|
||||
{
|
||||
transparant_image_id += 4;
|
||||
glassImageIndex += 4;
|
||||
PaintAddImageAsChild(
|
||||
session, transparant_image_id, 0, 0, lengthX, lengthY, ah, height, (direction & 1) ? 28 : 2,
|
||||
(direction & 1) ? 2 : 28, height);
|
||||
session, glassImageTemplate.WithIndex(glassImageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
||||
{ (direction & 1) ? 28 : 2, (direction & 1) ? 2 : 28, height });
|
||||
}
|
||||
|
||||
if (direction & 1)
|
||||
paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_SQUARE_FLAT);
|
||||
|
||||
if (!entranceEl.IsGhost())
|
||||
PaintRideEntranceExitScrollingText(session, entranceEl, *stationObj, direction, height);
|
||||
|
||||
auto supportsImageTemplate = imageTemplate;
|
||||
if (!entranceEl.IsGhost())
|
||||
{
|
||||
paint_util_push_tunnel_right(session, height, TUNNEL_SQUARE_FLAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_util_push_tunnel_left(session, height, TUNNEL_SQUARE_FLAT);
|
||||
supportsImageTemplate = ImageId().WithPrimary(COLOUR_SATURATED_BROWN);
|
||||
}
|
||||
wooden_a_supports_paint_setup(session, direction & 1, 0, height, supportsImageTemplate.ToUInt32());
|
||||
|
||||
if (!is_exit && !(tile_element.IsGhost()) && tile_element.GetRideIndex() != RIDE_ID_NULL
|
||||
&& stationObj->ScrollingMode != SCROLLING_MODE_NONE)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_NAME);
|
||||
|
||||
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
||||
{
|
||||
ride->FormatNameTo(ft);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_CLOSED);
|
||||
}
|
||||
|
||||
utf8 entrance_string[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(entrance_string, sizeof(entrance_string), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(entrance_string, sizeof(entrance_string), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
|
||||
uint16_t stringWidth = gfx_get_string_width(entrance_string, FontSpriteBase::TINY);
|
||||
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
|
||||
PaintAddImageAsChild(
|
||||
session, scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, stationObj->ScrollingMode, COLOUR_BLACK),
|
||||
0, 0, 0x1C, 0x1C, 0x33, height + stationObj->Height, 2, 2, height + stationObj->Height);
|
||||
}
|
||||
|
||||
image_id = entranceImageId;
|
||||
if (image_id == 0)
|
||||
{
|
||||
image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN);
|
||||
}
|
||||
wooden_a_supports_paint_setup(session, direction & 1, 0, height, image_id);
|
||||
|
||||
height += isExit ? 40 : 56;
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
||||
|
||||
height += is_exit ? 40 : 56;
|
||||
paint_util_set_general_support_height(session, height, 0x20);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006658ED
|
||||
*/
|
||||
static void park_entrance_paint(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& tile_element)
|
||||
static void PaintParkEntranceScrollingText(
|
||||
paint_session* session, const EntranceObject& entrance, Direction direction, int32_t height)
|
||||
{
|
||||
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
if ((direction + 1) & (1 << 1))
|
||||
return;
|
||||
|
||||
auto scrollingMode = entrance.GetScrollingMode();
|
||||
if (scrollingMode == SCROLLING_MODE_NONE)
|
||||
return;
|
||||
|
||||
auto ft = Formatter();
|
||||
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
|
||||
{
|
||||
const auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark();
|
||||
auto name = park.Name.c_str();
|
||||
ft.Add<rct_string_id>(STR_STRING);
|
||||
ft.Add<const char*>(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.Add<rct_string_id>(STR_BANNER_TEXT_CLOSED);
|
||||
ft.Add<uint32_t>(0);
|
||||
}
|
||||
|
||||
char text[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
|
||||
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
||||
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
auto imageIndex = scrolling_text_setup(
|
||||
session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode + direction / 2, COLOUR_BLACK);
|
||||
auto textHeight = height + entrance.GetTextHeight();
|
||||
PaintAddImageAsChild(session, ImageId(imageIndex), { 0, 0, textHeight }, { 28, 28, 47 }, { 2, 2, textHeight });
|
||||
}
|
||||
|
||||
static void PaintParkEntranceLightEffects(paint_session* session)
|
||||
{
|
||||
#ifdef __ENABLE_LIGHTFX__
|
||||
if (lightfx_is_available())
|
||||
{
|
||||
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 0, 0, 155, LightType::Lantern3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PaintParkEntrance(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceEl)
|
||||
{
|
||||
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
return;
|
||||
|
||||
PaintParkEntranceLightEffects(session);
|
||||
|
||||
session->InteractionType = ViewportInteractionItem::ParkEntrance;
|
||||
uint32_t image_id, ghost_id = 0;
|
||||
if (tile_element.IsGhost())
|
||||
|
||||
ImageId imageTemplate;
|
||||
if (entranceEl.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
ghost_id = CONSTRUCTION_MARKER;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&tile_element)))
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&entranceEl)))
|
||||
{
|
||||
ghost_id = CONSTRUCTION_MARKER;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
// Index to which part of the entrance
|
||||
// Middle, left, right
|
||||
uint8_t part_index = tile_element.GetSequenceIndex();
|
||||
const PathSurfaceDescriptor* surfaceDescriptor = nullptr;
|
||||
|
||||
// The left and right of the park entrance often have this set to 127.
|
||||
// So only attempt to get the footpath type if we're dealing with the middle bit of the entrance.
|
||||
if (part_index == 0)
|
||||
auto& objManager = GetContext()->GetObjectManager();
|
||||
auto entrance = reinterpret_cast<EntranceObject*>(objManager.GetLoadedObject(ObjectType::ParkEntrance, 0));
|
||||
auto sequence = entranceEl.GetSequenceIndex();
|
||||
switch (sequence)
|
||||
{
|
||||
surfaceDescriptor = tile_element.GetPathSurfaceDescriptor();
|
||||
}
|
||||
|
||||
rct_entrance_type* entrance;
|
||||
uint8_t di = ((direction / 2 + part_index / 2) & 1) ? 0x1A : 0x20;
|
||||
|
||||
switch (part_index)
|
||||
{
|
||||
case 0:
|
||||
case EntranceSequence::Centre:
|
||||
{
|
||||
// Footpath
|
||||
auto surfaceDescriptor = entranceEl.GetPathSurfaceDescriptor();
|
||||
if (surfaceDescriptor != nullptr)
|
||||
{
|
||||
image_id = (surfaceDescriptor->Image + 5 * (1 + (direction & 1))) | ghost_id;
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 32, 0x1C, 0 }, { 0, 2, height });
|
||||
auto imageIndex = (surfaceDescriptor->Image + 5 * (1 + (direction & 1)));
|
||||
PaintAddImageAsParent(
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 32, 28, 0 }, { 0, 2, height });
|
||||
}
|
||||
|
||||
entrance = static_cast<rct_entrance_type*>(object_entry_get_chunk(ObjectType::ParkEntrance, 0));
|
||||
if (entrance == nullptr)
|
||||
// Entrance
|
||||
if (entrance != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
image_id = (entrance->image_id + direction * 3) | ghost_id;
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 0x1C, 0x1C, 0x2F }, { 2, 2, height + 32 });
|
||||
auto imageIndex = entrance->GetImage(sequence, direction);
|
||||
PaintAddImageAsParent(
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 28, 28, 47 }, { 2, 2, height + 32 });
|
||||
|
||||
if ((direction + 1) & (1 << 1))
|
||||
break;
|
||||
if (ghost_id != 0)
|
||||
break;
|
||||
|
||||
{
|
||||
auto ft = Formatter();
|
||||
|
||||
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
|
||||
{
|
||||
const auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark();
|
||||
auto name = park.Name.c_str();
|
||||
ft.Add<rct_string_id>(STR_STRING);
|
||||
ft.Add<const char*>(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.Add<rct_string_id>(STR_BANNER_TEXT_CLOSED);
|
||||
ft.Add<uint32_t>(0);
|
||||
}
|
||||
|
||||
utf8 park_name[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(park_name, sizeof(park_name), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(park_name, sizeof(park_name), STR_BANNER_TEXT_FORMAT, ft.Data());
|
||||
}
|
||||
|
||||
uint16_t stringWidth = gfx_get_string_width(park_name, FontSpriteBase::TINY);
|
||||
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
|
||||
if (entrance->scrolling_mode == SCROLLING_MODE_NONE)
|
||||
break;
|
||||
|
||||
int32_t stsetup = scrolling_text_setup(
|
||||
session, STR_BANNER_TEXT_FORMAT, ft, scroll, entrance->scrolling_mode + direction / 2, COLOUR_BLACK);
|
||||
int32_t text_height = height + entrance->text_height;
|
||||
PaintAddImageAsChild(session, stsetup, 0, 0, 0x1C, 0x1C, 0x2F, text_height, 2, 2, text_height);
|
||||
if (!entranceEl.IsGhost())
|
||||
PaintParkEntranceScrollingText(session, *entrance, direction, height);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
entrance = static_cast<rct_entrance_type*>(object_entry_get_chunk(ObjectType::ParkEntrance, 0));
|
||||
if (entrance == nullptr)
|
||||
}
|
||||
case EntranceSequence::Left:
|
||||
case EntranceSequence::Right:
|
||||
if (entrance != nullptr)
|
||||
{
|
||||
return;
|
||||
auto imageIndex = entrance->GetImage(sequence, direction);
|
||||
auto y = ((direction / 2 + sequence / 2) & 1) ? 26 : 32;
|
||||
PaintAddImageAsParent(
|
||||
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 26, y, 79 }, { 3, 3, height });
|
||||
}
|
||||
image_id = (entrance->image_id + part_index + direction * 3) | ghost_id;
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 0x1A, di, 0x4F }, { 3, 3, height });
|
||||
break;
|
||||
}
|
||||
|
||||
image_id = ghost_id;
|
||||
if (image_id == 0)
|
||||
auto supportsImageTemplate = imageTemplate;
|
||||
if (!entranceEl.IsGhost())
|
||||
{
|
||||
image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN);
|
||||
supportsImageTemplate = ImageId().WithPrimary(COLOUR_SATURATED_BROWN);
|
||||
}
|
||||
wooden_a_supports_paint_setup(session, direction & 1, 0, height, image_id);
|
||||
wooden_a_supports_paint_setup(session, direction & 1, 0, height, supportsImageTemplate.ToUInt32());
|
||||
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
||||
paint_util_set_general_support_height(session, height + 80, 0x20);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00664FD4
|
||||
*/
|
||||
static void PaintHeightMarkers(paint_session* session, const EntranceElement& entranceEl, int32_t height)
|
||||
{
|
||||
if (PaintShouldShowHeightMarkers(session, VIEWPORT_FLAG_PATH_HEIGHTS))
|
||||
{
|
||||
if (entranceEl.GetDirections() & 0xF)
|
||||
{
|
||||
auto heightMarkerBaseZ = entranceEl.GetBaseZ() + 3;
|
||||
ImageIndex baseImageIndex = SPR_HEIGHT_MARKER_BASE;
|
||||
baseImageIndex += heightMarkerBaseZ / 16;
|
||||
baseImageIndex += get_height_marker_offset();
|
||||
baseImageIndex -= gMapBaseZ;
|
||||
auto imageId = ImageId(baseImageIndex, COLOUR_GREY);
|
||||
PaintAddImageAsParent(session, imageId, { 16, 16, height }, { 1, 1, 0 }, { 31, 31, heightMarkerBaseZ + 64 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaintEntrance(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceElement)
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::Label;
|
||||
|
||||
if (PaintShouldShowHeightMarkers(session, VIEWPORT_FLAG_PATH_HEIGHTS))
|
||||
{
|
||||
if (entranceElement.GetDirections() & 0xF)
|
||||
{
|
||||
int32_t z = entranceElement.GetBaseZ() + 3;
|
||||
uint32_t image_id = 0x20101689 + get_height_marker_offset() + (z / 16);
|
||||
image_id -= gMapBaseZ;
|
||||
|
||||
PaintAddImageAsParent(session, image_id, { 16, 16, height }, { 1, 1, 0 }, { 31, 31, z + 64 });
|
||||
}
|
||||
}
|
||||
|
||||
PaintHeightMarkers(session, entranceElement, height);
|
||||
switch (entranceElement.GetEntranceType())
|
||||
{
|
||||
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
||||
case ENTRANCE_TYPE_RIDE_EXIT:
|
||||
ride_entrance_exit_paint(session, direction, height, entranceElement);
|
||||
PaintRideEntranceExit(session, direction, height, entranceElement);
|
||||
break;
|
||||
case ENTRANCE_TYPE_PARK_ENTRANCE:
|
||||
park_entrance_paint(session, direction, height, entranceElement);
|
||||
PaintParkEntrance(session, direction, height, entranceElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../../Game.h"
|
||||
#include "../../config/Config.h"
|
||||
#include "../../core/Numerics.hpp"
|
||||
#include "../../core/String.hpp"
|
||||
#include "../../interface/Viewport.h"
|
||||
#include "../../localisation/Localisation.h"
|
||||
#include "../../object/LargeSceneryObject.h"
|
||||
|
@ -25,171 +26,6 @@
|
|||
#include "../Supports.h"
|
||||
#include "Paint.TileElement.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
// 6B8172:
|
||||
static void large_scenery_paint_supports(
|
||||
paint_session* session, uint8_t direction, uint16_t height, const LargeSceneryElement& tileElement, uint32_t dword_F4387C,
|
||||
const rct_large_scenery_tile* tile)
|
||||
{
|
||||
if (tile->flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t ax = 0;
|
||||
int32_t supportHeight = height;
|
||||
|
||||
if (supportHeight & 0xF)
|
||||
{
|
||||
supportHeight &= 0xFFFFFFF0;
|
||||
ax = 49;
|
||||
}
|
||||
|
||||
int32_t supportImageColourFlags = IMAGE_TYPE_REMAP;
|
||||
|
||||
if (dword_F4387C)
|
||||
{
|
||||
supportImageColourFlags = dword_F4387C;
|
||||
}
|
||||
|
||||
wooden_b_supports_paint_setup(session, (direction & 1), ax, supportHeight, supportImageColourFlags);
|
||||
|
||||
int32_t clearanceHeight = ceil2(tileElement.GetClearanceZ() + 15, 16);
|
||||
|
||||
if (tile->flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE)
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, clearanceHeight, 0x20);
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
||||
}
|
||||
|
||||
paint_util_set_general_support_height(session, clearanceHeight, 0x20);
|
||||
}
|
||||
|
||||
static rct_large_scenery_text_glyph* large_scenery_sign_get_glyph(LargeSceneryText* text, uint32_t codepoint)
|
||||
{
|
||||
if (codepoint >= std::size(text->glyphs))
|
||||
{
|
||||
return &text->glyphs[static_cast<size_t>('?')];
|
||||
}
|
||||
return &text->glyphs[codepoint];
|
||||
}
|
||||
|
||||
static int32_t large_scenery_sign_text_width(const utf8* str, LargeSceneryText* text)
|
||||
{
|
||||
int32_t width = 0;
|
||||
uint32_t codepoint;
|
||||
while ((codepoint = utf8_get_next(str, &str)) != 0)
|
||||
{
|
||||
width += large_scenery_sign_get_glyph(text, codepoint)->width;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
static int32_t large_scenery_sign_text_height(const utf8* str, LargeSceneryText* text)
|
||||
{
|
||||
int32_t height = 0;
|
||||
uint32_t codepoint;
|
||||
while ((codepoint = utf8_get_next(str, &str)) != 0)
|
||||
{
|
||||
height += large_scenery_sign_get_glyph(text, codepoint)->height;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
static void large_scenery_sign_fit_text(const utf8* str, LargeSceneryText* text, bool height, utf8* fitStr, size_t bufLen)
|
||||
{
|
||||
utf8* fitStrEnd = fitStr;
|
||||
safe_strcpy(fitStr, str, bufLen);
|
||||
int32_t w = 0;
|
||||
uint32_t codepoint;
|
||||
while (w <= text->max_width && (codepoint = utf8_get_next(fitStrEnd, const_cast<const utf8**>(&fitStrEnd))) != 0)
|
||||
{
|
||||
if (height)
|
||||
{
|
||||
w += large_scenery_sign_get_glyph(text, codepoint)->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
w += large_scenery_sign_get_glyph(text, codepoint)->width;
|
||||
}
|
||||
}
|
||||
*fitStrEnd = 0;
|
||||
}
|
||||
|
||||
static int32_t div_to_minus_infinity(int32_t a, int32_t b)
|
||||
{
|
||||
return (a / b) - (a % b < 0);
|
||||
}
|
||||
|
||||
static void large_scenery_sign_paint_line(
|
||||
paint_session* session, const utf8* str, LargeSceneryText* text, int32_t textImage, int32_t textColour, uint8_t direction,
|
||||
int32_t y_offset)
|
||||
{
|
||||
utf8 fitStr[32];
|
||||
large_scenery_sign_fit_text(str, text, false, fitStr, sizeof(fitStr));
|
||||
int32_t width = large_scenery_sign_text_width(fitStr, text);
|
||||
int32_t x_offset = text->offset[(direction & 1)].x;
|
||||
int32_t acc = y_offset * ((direction & 1) ? -1 : 1);
|
||||
if (!(text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL))
|
||||
{
|
||||
// sign is horizontal, centre text:
|
||||
x_offset -= (width / 2);
|
||||
acc -= (width / 2);
|
||||
}
|
||||
uint32_t codepoint;
|
||||
const utf8* fitStrPtr = fitStr;
|
||||
while ((codepoint = utf8_get_next(fitStrPtr, &fitStrPtr)) != 0)
|
||||
{
|
||||
int32_t glyph_offset = large_scenery_sign_get_glyph(text, codepoint)->image_offset;
|
||||
uint8_t glyph_type = direction & 1;
|
||||
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{ // vertical sign
|
||||
glyph_offset *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_offset *= 4;
|
||||
// set slightly different glyph on horizontal sign, which was rendered 1/2 pixel lower to deal with aliasing:
|
||||
if (direction & 1)
|
||||
{
|
||||
if (!(acc & 1))
|
||||
{
|
||||
glyph_type += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((acc & 1))
|
||||
{
|
||||
glyph_type += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32_t image_id = (textImage + glyph_offset + glyph_type) | textColour;
|
||||
if (direction == 3)
|
||||
{
|
||||
PaintAttachToPreviousPS(session, image_id, x_offset, -div_to_minus_infinity(acc, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{
|
||||
PaintAttachToPreviousPS(session, image_id, x_offset, div_to_minus_infinity(acc, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
PaintAttachToPreviousAttach(session, image_id, x_offset, div_to_minus_infinity(acc, 2));
|
||||
}
|
||||
}
|
||||
x_offset += large_scenery_sign_get_glyph(text, codepoint)->width;
|
||||
acc += large_scenery_sign_get_glyph(text, codepoint)->width;
|
||||
}
|
||||
}
|
||||
|
||||
struct boundbox
|
||||
{
|
||||
CoordsXY offset;
|
||||
|
@ -197,7 +33,7 @@ struct boundbox
|
|||
};
|
||||
|
||||
// clang-format off
|
||||
static constexpr const boundbox s98E3C4[] = {
|
||||
static constexpr const boundbox LargeSceneryBoundBoxes[] = {
|
||||
{ { 3, 3 }, { 26, 26 } },
|
||||
{ { 17, 17 }, { 12, 12 } },
|
||||
{ { 17, 3 }, { 12, 12 } },
|
||||
|
@ -218,19 +54,279 @@ static constexpr const boundbox s98E3C4[] = {
|
|||
};
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
*
|
||||
* rct2: 0x006B7F0C
|
||||
*/
|
||||
static void PaintLargeScenerySupports(
|
||||
paint_session* session, uint8_t direction, uint16_t height, const LargeSceneryElement& tileElement, ImageId imageTemplate,
|
||||
const rct_large_scenery_tile& tile)
|
||||
{
|
||||
if (tile.flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS)
|
||||
return;
|
||||
|
||||
auto special = 0;
|
||||
auto supportHeight = height;
|
||||
if (supportHeight & 0xF)
|
||||
{
|
||||
supportHeight &= ~0xF;
|
||||
special = 49;
|
||||
}
|
||||
|
||||
wooden_b_supports_paint_setup(session, (direction & 1), special, supportHeight, imageTemplate.ToUInt32());
|
||||
|
||||
int32_t clearanceHeight = ceil2(tileElement.GetClearanceZ() + 15, 16);
|
||||
if (tile.flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE)
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, clearanceHeight, 0x20);
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
||||
}
|
||||
paint_util_set_general_support_height(session, clearanceHeight, 0x20);
|
||||
}
|
||||
|
||||
static std::string_view LargeSceneryCalculateDisplayText(const LargeSceneryText& text, std::string_view s, bool height)
|
||||
{
|
||||
size_t totalSize = 0;
|
||||
CodepointView view(s);
|
||||
auto it = view.begin();
|
||||
while (it != view.end() && totalSize <= text.max_width)
|
||||
{
|
||||
auto glyph = text.GetGlyph(*it, ' ');
|
||||
totalSize += height ? glyph.height : glyph.width;
|
||||
it++;
|
||||
}
|
||||
|
||||
auto totalLength = it.GetIndex();
|
||||
return s.substr(0, totalLength);
|
||||
}
|
||||
|
||||
static int32_t DivToMinusInfinity(int32_t a, int32_t b)
|
||||
{
|
||||
return (a / b) - (a % b < 0);
|
||||
}
|
||||
|
||||
static void PaintLargeScenery3DTextLine(
|
||||
paint_session* session, const LargeSceneryEntry& sceneryEntry, const LargeSceneryText& text, std::string_view line,
|
||||
ImageId imageTemplate, Direction direction, int32_t offsetY)
|
||||
{
|
||||
line = LargeSceneryCalculateDisplayText(text, line, false);
|
||||
auto width = text.MeasureWidth(line);
|
||||
auto offsetX = text.offset[(direction & 1)].x;
|
||||
auto acc = offsetY * ((direction & 1) ? -1 : 1);
|
||||
if (!(text.flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL))
|
||||
{
|
||||
// sign is horizontal, centre text:
|
||||
offsetX -= (width / 2);
|
||||
acc -= (width / 2);
|
||||
}
|
||||
|
||||
for (auto codepoint : CodepointView(line))
|
||||
{
|
||||
auto glyph = text.GetGlyph(codepoint, ' ');
|
||||
auto glyphOffset = glyph.image_offset;
|
||||
auto glyphType = direction & 1;
|
||||
if (text.flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{
|
||||
glyphOffset *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyphOffset *= 4;
|
||||
// set slightly different glyph on horizontal sign, which was rendered 1/2 pixel lower to deal with aliasing:
|
||||
if (direction & 1)
|
||||
{
|
||||
if (!(acc & 1))
|
||||
{
|
||||
glyphType += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((acc & 1))
|
||||
{
|
||||
glyphType += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto imageIndex = sceneryEntry.text_image + glyphOffset + glyphType;
|
||||
auto imageId = imageTemplate.WithIndex(imageIndex);
|
||||
if (direction == 3)
|
||||
{
|
||||
PaintAttachToPreviousPS(session, imageId, offsetX, -DivToMinusInfinity(acc, 2));
|
||||
}
|
||||
else if (text.flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{
|
||||
PaintAttachToPreviousPS(session, imageId, offsetX, DivToMinusInfinity(acc, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
PaintAttachToPreviousAttach(session, imageId, offsetX, DivToMinusInfinity(acc, 2));
|
||||
}
|
||||
offsetX += glyph.width;
|
||||
acc += glyph.width;
|
||||
}
|
||||
}
|
||||
|
||||
static bool Is3DTextSingleLine(const LargeSceneryText& text, std::string_view s)
|
||||
{
|
||||
if (text.flags & LARGE_SCENERY_TEXT_FLAG_TWO_LINE)
|
||||
{
|
||||
auto width = text.MeasureWidth(s);
|
||||
return width <= text.max_width;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PaintLargeScenery3DText(
|
||||
paint_session* session, const LargeSceneryEntry& sceneryEntry, const rct_large_scenery_tile& tile,
|
||||
const LargeSceneryElement& tileElement, uint8_t direction, uint16_t height, bool isGhost)
|
||||
{
|
||||
if (sceneryEntry.tiles[1].x_offset != -1)
|
||||
{
|
||||
auto sequenceDirection = (tileElement.GetSequenceIndex() - 1) & 3;
|
||||
if (sequenceDirection != direction)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (session->DPI.zoom_level > ZoomLevel{ 1 })
|
||||
return;
|
||||
|
||||
auto banner = tileElement.GetBanner();
|
||||
if (banner == nullptr)
|
||||
return;
|
||||
|
||||
const auto* text = sceneryEntry.text;
|
||||
if (text == nullptr)
|
||||
return;
|
||||
|
||||
auto textColour = isGhost ? static_cast<colour_t>(COLOUR_GREY) : tileElement.GetSecondaryColour();
|
||||
auto imageTemplate = ImageId().WithPrimary(textColour);
|
||||
|
||||
char signString[256];
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
format_string(signString, sizeof(signString), STR_STRINGID, ft.Data());
|
||||
|
||||
auto offsetY = text->offset[(direction & 1)].y * 2;
|
||||
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{
|
||||
// Vertical sign
|
||||
offsetY++;
|
||||
auto displayText = LargeSceneryCalculateDisplayText(*text, signString, true);
|
||||
auto displayTextHeight = text->MeasureHeight(displayText);
|
||||
for (auto codepoint : CodepointView(displayText))
|
||||
{
|
||||
char line[8]{};
|
||||
utf8_write_codepoint(line, codepoint);
|
||||
PaintLargeScenery3DTextLine(
|
||||
session, sceneryEntry, *text, line, imageTemplate, direction, offsetY - displayTextHeight);
|
||||
|
||||
auto glyph = text->GetGlyph(codepoint, ' ');
|
||||
offsetY += glyph.height * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Horizontal sign
|
||||
offsetY -= (direction & 1);
|
||||
if (Is3DTextSingleLine(*text, signString))
|
||||
{
|
||||
PaintLargeScenery3DTextLine(session, sceneryEntry, *text, signString, imageTemplate, direction, offsetY);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lineHeight = text->GetGlyph('A')->height + 1;
|
||||
offsetY -= lineHeight;
|
||||
|
||||
// Split the string into two lines at best position
|
||||
auto current = std::string_view(signString);
|
||||
std::string_view next;
|
||||
for (int32_t lineIndex = 0; lineIndex < 2; lineIndex++)
|
||||
{
|
||||
std::string_view best;
|
||||
|
||||
CodepointView view(current);
|
||||
auto lineWidth = 0;
|
||||
auto it = view.begin();
|
||||
while (it != view.end() && lineWidth < text->max_width)
|
||||
{
|
||||
// Trim any leading spaces
|
||||
auto codepoint = *it;
|
||||
if (codepoint != ' ' || lineWidth != 0)
|
||||
{
|
||||
// Determine if this is a good place to split
|
||||
if (codepoint == ' ' || codepoint == '\n')
|
||||
{
|
||||
auto index = it.GetIndex();
|
||||
best = current.substr(0, index);
|
||||
next = current.substr(index + 1);
|
||||
if (codepoint == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
auto glyph = text->GetGlyph(*it, ' ');
|
||||
lineWidth += glyph.width;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
if (best.empty())
|
||||
{
|
||||
// No good split found, or reached end of string
|
||||
auto index = it.GetIndex();
|
||||
best = current.substr(0, index);
|
||||
next = current.substr(index);
|
||||
}
|
||||
|
||||
PaintLargeScenery3DTextLine(session, sceneryEntry, *text, best, imageTemplate, direction, offsetY);
|
||||
|
||||
current = next;
|
||||
offsetY += lineHeight * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PaintLargeSceneryScrollingText(
|
||||
paint_session* session, const LargeSceneryEntry& sceneryEntry, const LargeSceneryElement& tileElement, uint8_t direction,
|
||||
uint16_t height, const CoordsXYZ& bbOffset, bool isGhost)
|
||||
{
|
||||
auto textColour = isGhost ? static_cast<colour_t>(COLOUR_GREY) : tileElement.GetSecondaryColour();
|
||||
auto textPaletteIndex = direction == 0 ? ColourMapA[textColour].mid_dark : ColourMapA[textColour].light;
|
||||
|
||||
auto banner = tileElement.GetBanner();
|
||||
if (banner == nullptr)
|
||||
return;
|
||||
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
|
||||
char text[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(text, sizeof(text), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(text, sizeof(text), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
|
||||
auto scrollMode = sceneryEntry.scrolling_mode + ((direction + 1) & 3);
|
||||
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
||||
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
auto imageId = scrolling_text_setup(session, STR_SCROLLING_SIGN_TEXT, ft, scroll, scrollMode, textPaletteIndex);
|
||||
PaintAddImageAsChild(session, imageId, { 0, 0, height + 25 }, { 1, 1, 21 }, bbOffset);
|
||||
}
|
||||
|
||||
void PaintLargeScenery(paint_session* session, uint8_t direction, uint16_t height, const LargeSceneryElement& tileElement)
|
||||
{
|
||||
if (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
session->InteractionType = ViewportInteractionItem::LargeScenery;
|
||||
const uint32_t sequenceNum = tileElement.GetSequenceIndex();
|
||||
const LargeSceneryObject* object = tileElement.GetObject();
|
||||
|
||||
auto sequenceNum = tileElement.GetSequenceIndex();
|
||||
const auto* object = tileElement.GetObject();
|
||||
if (object == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -238,218 +334,64 @@ void PaintLargeScenery(paint_session* session, uint8_t direction, uint16_t heigh
|
|||
if (sceneryEntry == nullptr)
|
||||
return;
|
||||
|
||||
uint32_t image_id = (sequenceNum << 2) + sceneryEntry->image + 4 + direction;
|
||||
const rct_large_scenery_tile* tile = object->GetTileForSequence(sequenceNum);
|
||||
const auto* tile = object->GetTileForSequence(sequenceNum);
|
||||
if (tile == nullptr)
|
||||
return;
|
||||
|
||||
uint32_t dword_F4387C = 0;
|
||||
image_id |= SPRITE_ID_PALETTE_COLOUR_2(tileElement.GetPrimaryColour(), tileElement.GetSecondaryColour());
|
||||
if (gTrackDesignSaveMode)
|
||||
session->InteractionType = ViewportInteractionItem::LargeScenery;
|
||||
|
||||
auto isGhost = false;
|
||||
ImageId imageTemplate;
|
||||
if (gTrackDesignSaveMode && !track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&tileElement)))
|
||||
{
|
||||
if (!track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&tileElement)))
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
dword_F4387C = SPRITE_ID_PALETTE_COLOUR_1(EnumValue(FilterPaletteID::Palette46));
|
||||
image_id |= dword_F4387C;
|
||||
}
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette46);
|
||||
isGhost = true;
|
||||
}
|
||||
if (tileElement.IsGhost())
|
||||
else if (tileElement.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
image_id &= 0x7FFFF;
|
||||
dword_F4387C = CONSTRUCTION_MARKER;
|
||||
image_id |= dword_F4387C;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
isGhost = true;
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&tileElement)))
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
dword_F4387C = CONSTRUCTION_MARKER;
|
||||
image_id |= dword_F4387C;
|
||||
}
|
||||
|
||||
int32_t boxlengthZ = tile->z_clearance;
|
||||
if (boxlengthZ > 0x80)
|
||||
{
|
||||
boxlengthZ = 0x80;
|
||||
}
|
||||
boxlengthZ -= 3;
|
||||
uint16_t edi = tile->flags;
|
||||
int32_t esi = 16;
|
||||
if (edi & 0xF00)
|
||||
{
|
||||
edi &= 0xF000;
|
||||
edi = Numerics::rol16(edi, direction);
|
||||
esi = (edi & 0xF) | (edi >> 12);
|
||||
}
|
||||
const CoordsXYZ bbOffset = { s98E3C4[esi].offset, height };
|
||||
const CoordsXYZ bbLength = { s98E3C4[esi].length, boxlengthZ };
|
||||
PaintAddImageAsParent(session, image_id, { 0, 0, height }, bbLength, bbOffset);
|
||||
if (sceneryEntry->scrolling_mode == SCROLLING_MODE_NONE || direction == 1 || direction == 2)
|
||||
{
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
return;
|
||||
}
|
||||
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_3D_TEXT)
|
||||
{
|
||||
if (sceneryEntry->tiles[1].x_offset != static_cast<int16_t>(static_cast<uint16_t>(0xFFFF)))
|
||||
{
|
||||
int32_t sequenceDirection = (tileElement.GetSequenceIndex() - 1) & 3;
|
||||
if (sequenceDirection != direction)
|
||||
{
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rct_drawpixelinfo* dpi = &session->DPI;
|
||||
if (dpi->zoom_level > ZoomLevel{ 1 })
|
||||
{
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
return;
|
||||
}
|
||||
// 6B8331:
|
||||
// Draw sign text:
|
||||
int32_t textColour = tileElement.GetSecondaryColour();
|
||||
if (dword_F4387C)
|
||||
{
|
||||
textColour = COLOUR_GREY;
|
||||
}
|
||||
textColour = (textColour << 19) | IMAGE_TYPE_REMAP;
|
||||
auto banner = tileElement.GetBanner();
|
||||
if (banner != nullptr)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
utf8 signString[256];
|
||||
format_string(signString, sizeof(signString), STR_STRINGID, ft.Data());
|
||||
LargeSceneryText* text = sceneryEntry->text;
|
||||
int32_t y_offset = (text->offset[(direction & 1)].y * 2);
|
||||
if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
|
||||
{
|
||||
// Draw vertical sign:
|
||||
y_offset += 1;
|
||||
utf8 fitStr[32];
|
||||
large_scenery_sign_fit_text(signString, text, true, fitStr, sizeof(fitStr));
|
||||
safe_strcpy(fitStr, fitStr, sizeof(fitStr));
|
||||
const utf8* fitStrPtr = fitStr;
|
||||
int32_t height2 = large_scenery_sign_text_height(fitStr, text);
|
||||
uint32_t codepoint;
|
||||
while ((codepoint = utf8_get_next(fitStrPtr, &fitStrPtr)) != 0)
|
||||
{
|
||||
utf8 str[5] = { 0 };
|
||||
utf8_write_codepoint(str, codepoint);
|
||||
large_scenery_sign_paint_line(
|
||||
session, str, sceneryEntry->text, sceneryEntry->text_image, textColour, direction, y_offset - height2);
|
||||
y_offset += large_scenery_sign_get_glyph(text, codepoint)->height * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y_offset -= (direction & 1);
|
||||
if (text->flags & LARGE_SCENERY_TEXT_FLAG_TWO_LINE)
|
||||
{
|
||||
// Draw two-line sign:
|
||||
int32_t width = large_scenery_sign_text_width(signString, text);
|
||||
if (width > text->max_width)
|
||||
{
|
||||
y_offset -= large_scenery_sign_get_glyph(text, 'A')->height + 1;
|
||||
utf8* src = signString;
|
||||
for (int32_t i = 0; i < 2; i++)
|
||||
{
|
||||
utf8 str1[64] = { 0 };
|
||||
utf8* dst = str1;
|
||||
utf8* srcold = src;
|
||||
utf8* spacesrc = nullptr;
|
||||
utf8* spacedst = nullptr;
|
||||
int32_t w = 0;
|
||||
uint32_t codepoint = utf8_get_next(src, const_cast<const utf8**>(&src));
|
||||
do
|
||||
{
|
||||
w += large_scenery_sign_get_glyph(text, codepoint)->width;
|
||||
if (codepoint == ' ')
|
||||
{
|
||||
spacesrc = src;
|
||||
spacedst = dst;
|
||||
}
|
||||
} while (w <= text->max_width && (dst = utf8_write_codepoint(dst, codepoint)) != nullptr
|
||||
&& (srcold = src) != nullptr
|
||||
&& (codepoint = utf8_get_next(src, const_cast<const utf8**>(&src))) != '\0');
|
||||
src = srcold;
|
||||
if (spacesrc && codepoint)
|
||||
{
|
||||
*spacedst = 0;
|
||||
src = spacesrc;
|
||||
}
|
||||
large_scenery_sign_paint_line(
|
||||
session, str1, sceneryEntry->text, sceneryEntry->text_image, textColour, direction, y_offset);
|
||||
y_offset += (large_scenery_sign_get_glyph(text, 'A')->height + 1) * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
large_scenery_sign_paint_line(
|
||||
session, signString, sceneryEntry->text, sceneryEntry->text_image, textColour, direction, y_offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw one-line sign:
|
||||
large_scenery_sign_paint_line(
|
||||
session, signString, sceneryEntry->text, sceneryEntry->text_image, textColour, direction, y_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
rct_drawpixelinfo* dpi = &session->DPI;
|
||||
if (dpi->zoom_level > ZoomLevel{ 0 })
|
||||
{
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
return;
|
||||
}
|
||||
uint8_t sequenceDirection2 = (tileElement.GetSequenceIndex() - 1) & 3;
|
||||
if (sequenceDirection2 != direction)
|
||||
{
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
return;
|
||||
}
|
||||
// Draw scrolling text:
|
||||
uint8_t textColour = tileElement.GetSecondaryColour();
|
||||
if (dword_F4387C)
|
||||
{
|
||||
textColour = COLOUR_GREY;
|
||||
}
|
||||
if (direction == 0)
|
||||
{
|
||||
textColour = ColourMapA[textColour].mid_dark;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
isGhost = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
textColour = ColourMapA[textColour].light;
|
||||
imageTemplate = ImageId(0, tileElement.GetPrimaryColour(), tileElement.GetSecondaryColour());
|
||||
}
|
||||
// 6B809A:
|
||||
uint16_t scrollMode = sceneryEntry->scrolling_mode + ((direction + 1) & 0x3);
|
||||
auto banner = tileElement.GetBanner();
|
||||
if (banner != nullptr)
|
||||
|
||||
auto boxlengthZ = std::min<uint8_t>(tile->z_clearance, 128) - 3;
|
||||
auto flags = tile->flags;
|
||||
auto bbIndex = 16;
|
||||
if (flags & 0xF00)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
utf8 signString[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
|
||||
uint16_t stringWidth = gfx_get_string_width(signString, FontSpriteBase::TINY);
|
||||
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
PaintAddImageAsChild(
|
||||
session, scrolling_text_setup(session, STR_SCROLLING_SIGN_TEXT, ft, scroll, scrollMode, textColour), 0, 0, 1, 1, 21,
|
||||
height + 25, bbOffset.x, bbOffset.y, bbOffset.z);
|
||||
flags &= 0xF000;
|
||||
flags = Numerics::rol16(flags, direction);
|
||||
bbIndex = (flags & 0xF) | (flags >> 12);
|
||||
}
|
||||
const CoordsXYZ bbOffset = { LargeSceneryBoundBoxes[bbIndex].offset, height };
|
||||
const CoordsXYZ bbLength = { LargeSceneryBoundBoxes[bbIndex].length, boxlengthZ };
|
||||
|
||||
large_scenery_paint_supports(session, direction, height, tileElement, dword_F4387C, tile);
|
||||
auto imageIndex = sceneryEntry->image + 4 + (sequenceNum << 2) + direction;
|
||||
PaintAddImageAsParent(session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, bbLength, bbOffset);
|
||||
|
||||
if (sceneryEntry->scrolling_mode != SCROLLING_MODE_NONE && direction != 1 && direction != 2)
|
||||
{
|
||||
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_3D_TEXT)
|
||||
{
|
||||
PaintLargeScenery3DText(session, *sceneryEntry, *tile, tileElement, direction, height, isGhost);
|
||||
}
|
||||
else if (session->DPI.zoom_level <= ZoomLevel{ 0 })
|
||||
{
|
||||
auto sequenceDirection2 = (tileElement.GetSequenceIndex() - 1) & 3;
|
||||
if (sequenceDirection2 == direction)
|
||||
{
|
||||
PaintLargeSceneryScrollingText(session, *sceneryEntry, tileElement, direction, height, bbOffset, isGhost);
|
||||
}
|
||||
}
|
||||
}
|
||||
PaintLargeScenerySupports(session, direction, height, tileElement, isGhost ? imageTemplate : ImageId(), *tile);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,77 @@ static constexpr const CoordsXY lengths[] = {
|
|||
{ 26, 12 },
|
||||
};
|
||||
|
||||
static void PaintSmallScenerySupports(
|
||||
paint_session* session, const SmallSceneryEntry& sceneryEntry, const SmallSceneryElement& sceneryElement,
|
||||
Direction direction, int32_t height, ImageId imageTemplate)
|
||||
{
|
||||
if (!sceneryElement.NeedsSupports())
|
||||
return;
|
||||
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_NO_SUPPORTS))
|
||||
return;
|
||||
|
||||
auto special = 0;
|
||||
auto supportHeight = height;
|
||||
if (supportHeight & 0xF)
|
||||
{
|
||||
supportHeight &= ~0xF;
|
||||
special = 49;
|
||||
}
|
||||
|
||||
auto supportImageTemplate = ImageId().WithRemap(0);
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_PAINT_SUPPORTS))
|
||||
{
|
||||
supportImageTemplate = ImageId().WithPrimary(sceneryElement.GetPrimaryColour());
|
||||
}
|
||||
if (imageTemplate.IsRemap())
|
||||
{
|
||||
supportImageTemplate = imageTemplate;
|
||||
}
|
||||
|
||||
auto supportType = (direction & 1) ? 1 : 0;
|
||||
wooden_b_supports_paint_setup(session, supportType, special, supportHeight, supportImageTemplate.ToUInt32());
|
||||
}
|
||||
|
||||
static void SetSupportHeights(
|
||||
paint_session* session, const SmallSceneryEntry& sceneryEntry, const SmallSceneryElement& sceneryElement, int32_t height)
|
||||
{
|
||||
height += sceneryEntry.height;
|
||||
|
||||
paint_util_set_general_support_height(session, ceil2(height, 8), 0x20);
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP))
|
||||
{
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENT_C4, height, 0x20);
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~SEGMENT_C4, height, 0x20);
|
||||
}
|
||||
}
|
||||
else if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
auto direction = (sceneryElement.GetSceneryQuadrant() + session->CurrentRotation) % 4;
|
||||
paint_util_set_segment_support_height(
|
||||
session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), height, 0x20);
|
||||
}
|
||||
}
|
||||
else if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG27 | SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENT_C4, 0xFFFF, 0);
|
||||
if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~SEGMENT_C4, 0xFFFF, 0);
|
||||
}
|
||||
}
|
||||
else if (sceneryEntry.HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
auto direction = (sceneryElement.GetSceneryQuadrant() + session->CurrentRotation) % 4;
|
||||
paint_util_set_segment_support_height(
|
||||
session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), 0xFFFF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006DFF47
|
||||
|
@ -38,197 +109,149 @@ void PaintSmallScenery(paint_session* session, uint8_t direction, int32_t height
|
|||
{
|
||||
return;
|
||||
}
|
||||
session->InteractionType = ViewportInteractionItem::Scenery;
|
||||
CoordsXYZ boxlength;
|
||||
CoordsXYZ boxoffset;
|
||||
boxoffset.x = 0;
|
||||
boxoffset.y = 0;
|
||||
boxoffset.z = height;
|
||||
uint32_t marker = 0;
|
||||
const int32_t rotation = session->CurrentRotation;
|
||||
if (gTrackDesignSaveMode)
|
||||
{
|
||||
if (!track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&sceneryElement)))
|
||||
{
|
||||
marker = SPRITE_ID_PALETTE_COLOUR_1(EnumValue(FilterPaletteID::Palette46));
|
||||
}
|
||||
}
|
||||
if (sceneryElement.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
marker = CONSTRUCTION_MARKER;
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&sceneryElement)))
|
||||
{
|
||||
marker = CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
auto* sceneryEntry = sceneryElement.GetEntry();
|
||||
|
||||
if (sceneryEntry == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t baseImageid = sceneryEntry->image + direction;
|
||||
boxlength.x = 2;
|
||||
boxlength.y = 2;
|
||||
int8_t x_offset = 0;
|
||||
int8_t y_offset = 0;
|
||||
session->InteractionType = ViewportInteractionItem::Scenery;
|
||||
CoordsXYZ boxLength;
|
||||
CoordsXYZ boxOffset{ 0, 0, height };
|
||||
ImageId imageTemplate;
|
||||
if (gTrackDesignSaveMode)
|
||||
{
|
||||
if (!track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&sceneryElement)))
|
||||
{
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette46);
|
||||
}
|
||||
}
|
||||
if (sceneryElement.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&sceneryElement)))
|
||||
{
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
boxLength.x = 2;
|
||||
boxLength.y = 2;
|
||||
|
||||
CoordsXYZ offset = { 0, 0, height };
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HALF_SPACE))
|
||||
{
|
||||
// 6DFFE3:
|
||||
static constexpr const CoordsXY scenery_half_tile_offsets[] = {
|
||||
static constexpr const CoordsXY sceneryHalfTileOffsets[] = {
|
||||
{ 3, 3 },
|
||||
{ 3, 17 },
|
||||
{ 17, 3 },
|
||||
{ 3, 3 },
|
||||
};
|
||||
boxoffset.x = scenery_half_tile_offsets[direction].x;
|
||||
boxoffset.y = scenery_half_tile_offsets[direction].y;
|
||||
boxlength.x = lengths[direction].x;
|
||||
boxlength.y = lengths[direction].y;
|
||||
x_offset = 3;
|
||||
y_offset = 3;
|
||||
boxOffset.x = sceneryHalfTileOffsets[direction].x;
|
||||
boxOffset.y = sceneryHalfTileOffsets[direction].y;
|
||||
boxLength.x = lengths[direction].x;
|
||||
boxLength.y = lengths[direction].y;
|
||||
offset.x = 3;
|
||||
offset.y = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
x_offset = 15;
|
||||
y_offset = 15;
|
||||
offset.x = 15;
|
||||
offset.y = 15;
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
x_offset = 3;
|
||||
y_offset = 3;
|
||||
boxlength.x = 26;
|
||||
boxlength.y = 26;
|
||||
offset.x = 3;
|
||||
offset.y = 3;
|
||||
boxLength.x = 26;
|
||||
boxLength.y = 26;
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_NO_WALLS))
|
||||
{
|
||||
x_offset = 1;
|
||||
y_offset = 1;
|
||||
boxlength.x = 30;
|
||||
boxlength.y = 30;
|
||||
offset.x = 1;
|
||||
offset.y = 1;
|
||||
boxLength.x = 30;
|
||||
boxLength.y = 30;
|
||||
}
|
||||
}
|
||||
boxoffset.x = x_offset;
|
||||
boxoffset.y = y_offset;
|
||||
boxOffset.x = offset.x;
|
||||
boxOffset.y = offset.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 6DFFC2:
|
||||
uint8_t quadrant = (sceneryElement.GetSceneryQuadrant() + rotation) & 3;
|
||||
x_offset = SceneryQuadrantOffsets[quadrant].x;
|
||||
y_offset = SceneryQuadrantOffsets[quadrant].y;
|
||||
boxoffset.x = x_offset;
|
||||
boxoffset.y = y_offset;
|
||||
uint8_t quadrant = (sceneryElement.GetSceneryQuadrant() + session->CurrentRotation) & 3;
|
||||
offset.x = SceneryQuadrantOffsets[quadrant].x;
|
||||
offset.y = SceneryQuadrantOffsets[quadrant].y;
|
||||
boxOffset.x = offset.x;
|
||||
boxOffset.y = offset.y;
|
||||
}
|
||||
// 6E007F:
|
||||
boxlength.z = sceneryEntry->height - 4;
|
||||
if (boxlength.z > 128 || boxlength.z < 0)
|
||||
boxLength.z = sceneryEntry->height - 4;
|
||||
if (boxLength.z > 128 || boxLength.z < 0)
|
||||
{
|
||||
boxlength.z = 128;
|
||||
boxLength.z = 128;
|
||||
}
|
||||
boxLength.z--;
|
||||
|
||||
ImageIndex baseImageIndex = sceneryEntry->image + direction;
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_CAN_WITHER))
|
||||
{
|
||||
if (sceneryElement.GetAge() >= SCENERY_WITHER_AGE_THRESHOLD_1)
|
||||
{
|
||||
baseImageid += 4;
|
||||
baseImageIndex += 4;
|
||||
}
|
||||
if (sceneryElement.GetAge() >= SCENERY_WITHER_AGE_THRESHOLD_2)
|
||||
{
|
||||
baseImageid += 4;
|
||||
baseImageIndex += 4;
|
||||
}
|
||||
}
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
||||
{
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
|
||||
{
|
||||
baseImageid |= SPRITE_ID_PALETTE_COLOUR_2(sceneryElement.GetPrimaryColour(), sceneryElement.GetSecondaryColour());
|
||||
}
|
||||
else
|
||||
{
|
||||
baseImageid |= SPRITE_ID_PALETTE_COLOUR_1(sceneryElement.GetPrimaryColour());
|
||||
}
|
||||
}
|
||||
if (marker != 0)
|
||||
{
|
||||
baseImageid = (baseImageid & 0x7FFFF) | marker;
|
||||
}
|
||||
if (!(sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED)))
|
||||
{
|
||||
PaintAddImageAsParent(
|
||||
session, baseImageid, { x_offset, y_offset, height }, { boxlength.x, boxlength.y, boxlength.z - 1 }, boxoffset);
|
||||
auto imageId = imageTemplate.WithIndex(baseImageIndex);
|
||||
if (!imageTemplate.IsRemap() && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
||||
{
|
||||
imageId = imageId.WithPrimary(sceneryElement.GetPrimaryColour());
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
|
||||
{
|
||||
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
|
||||
}
|
||||
}
|
||||
PaintAddImageAsParent(session, imageId, offset, boxLength, boxOffset);
|
||||
}
|
||||
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_GLASS))
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_GLASS) && !imageTemplate.IsRemap())
|
||||
{
|
||||
if (marker == 0)
|
||||
{
|
||||
// Draw translucent overlay:
|
||||
// TODO: Name palette entries
|
||||
int32_t image_id = (baseImageid & 0x7FFFF) + (EnumValue(GlassPaletteIds[sceneryElement.GetPrimaryColour()]) << 19)
|
||||
+ 0x40000004;
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
}
|
||||
auto imageId = ImageId(baseImageIndex + 4).WithTransparancy(sceneryElement.GetPrimaryColour());
|
||||
PaintAddImageAsChild(session, imageId, offset, boxLength, boxOffset);
|
||||
}
|
||||
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ANIMATED))
|
||||
{
|
||||
rct_drawpixelinfo* dpi = &session->DPI;
|
||||
if ((sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED)) || (dpi->zoom_level <= ZoomLevel{ 1 }))
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED) || (session->DPI.zoom_level <= ZoomLevel{ 1 }))
|
||||
{
|
||||
// 6E01A9:
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1))
|
||||
{
|
||||
// 6E0512:
|
||||
int32_t image_id = ((gCurrentTicks / 2) & 0xF) + sceneryEntry->image + 4;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
auto imageIndex = sceneryEntry->image + 4 + ((gCurrentTicks / 2) & 0xF);
|
||||
auto imageId = imageTemplate.WithIndex(imageIndex);
|
||||
PaintAddImageAsChild(session, imageId, offset, boxLength, boxOffset);
|
||||
}
|
||||
else if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4))
|
||||
{
|
||||
// 6E043B:
|
||||
int32_t image_id = ((gCurrentTicks / 2) & 0xF) + sceneryEntry->image + 8;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
auto imageIndex = sceneryEntry->image + 8 + ((gCurrentTicks / 2) & 0xF);
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
|
||||
image_id = direction + sceneryEntry->image + 4;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
imageIndex = direction + sceneryEntry->image + 4;
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
|
||||
image_id = ((gCurrentTicks / 2) & 0xF) + sceneryEntry->image + 24;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
imageIndex = sceneryEntry->image + 24 + ((gCurrentTicks / 2) & 0xF);
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
}
|
||||
else if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_IS_CLOCK))
|
||||
{
|
||||
// 6E035C:
|
||||
int32_t minuteImageOffset = ((gRealTimeOfDay.minute + 6) * 17) / 256;
|
||||
int32_t timeImageBase = gRealTimeOfDay.hour;
|
||||
auto minuteImageOffset = ((gRealTimeOfDay.minute + 6) * 17) / 256;
|
||||
auto timeImageBase = gRealTimeOfDay.hour;
|
||||
while (timeImageBase >= 12)
|
||||
{
|
||||
timeImageBase -= 12;
|
||||
|
@ -238,177 +261,75 @@ void PaintSmallScenery(paint_session* session, uint8_t direction, int32_t height
|
|||
{
|
||||
timeImageBase -= 48;
|
||||
}
|
||||
int32_t image_id = timeImageBase + (direction * 12);
|
||||
if (image_id >= 48)
|
||||
auto imageIndex = timeImageBase + (direction * 12);
|
||||
if (imageIndex >= 48)
|
||||
{
|
||||
image_id -= 48;
|
||||
imageIndex -= 48;
|
||||
}
|
||||
|
||||
image_id = image_id + sceneryEntry->image + 68;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
imageIndex = sceneryEntry->image + 68 + imageIndex;
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
|
||||
image_id = gRealTimeOfDay.minute + (direction * 15);
|
||||
if (image_id >= 60)
|
||||
imageIndex = gRealTimeOfDay.minute + (direction * 15);
|
||||
if (imageIndex >= 60)
|
||||
{
|
||||
image_id -= 60;
|
||||
imageIndex -= 60;
|
||||
}
|
||||
image_id = image_id + sceneryEntry->image + 8;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
imageIndex = sceneryEntry->image + 8 + imageIndex;
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
}
|
||||
else if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_SWAMP_GOO))
|
||||
{
|
||||
// 6E02F6:
|
||||
int32_t image_id = gCurrentTicks;
|
||||
image_id += session->SpritePosition.x / 4;
|
||||
image_id += session->SpritePosition.y / 4;
|
||||
image_id = (image_id / 4) & 15;
|
||||
image_id += sceneryEntry->image;
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
auto imageIndex = gCurrentTicks;
|
||||
imageIndex += session->SpritePosition.x / 4;
|
||||
imageIndex += session->SpritePosition.y / 4;
|
||||
imageIndex = sceneryEntry->image + ((imageIndex / 4) % 16);
|
||||
PaintAddImageAsChild(session, imageTemplate.WithIndex(imageIndex), offset, boxLength, boxOffset);
|
||||
}
|
||||
else if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS))
|
||||
{
|
||||
int32_t frame = gCurrentTicks;
|
||||
auto delay = sceneryEntry->animation_delay & 0xFF;
|
||||
auto frame = gCurrentTicks;
|
||||
if (!(sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_COG)))
|
||||
{
|
||||
// 6E01F8:
|
||||
frame += ((session->SpritePosition.x / 4) + (session->SpritePosition.y / 4));
|
||||
frame += sceneryElement.GetSceneryQuadrant() << 2;
|
||||
}
|
||||
// 6E0222:
|
||||
uint16_t delay = sceneryEntry->animation_delay & 0xFF;
|
||||
frame >>= delay;
|
||||
frame &= sceneryEntry->animation_mask;
|
||||
int32_t image_id = 0;
|
||||
frame = (frame >> delay) & sceneryEntry->animation_mask;
|
||||
|
||||
auto imageIndex = 0;
|
||||
if (frame < sceneryEntry->num_frames)
|
||||
{
|
||||
image_id = sceneryEntry->frame_offsets[frame];
|
||||
imageIndex = sceneryEntry->frame_offsets[frame];
|
||||
}
|
||||
image_id = (image_id * 4) + direction + sceneryEntry->image;
|
||||
imageIndex = (imageIndex * 4) + direction + sceneryEntry->image;
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED | SMALL_SCENERY_FLAG17))
|
||||
{
|
||||
image_id += 4;
|
||||
imageIndex += 4;
|
||||
}
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
||||
|
||||
auto imageId = imageTemplate.WithIndex(imageIndex);
|
||||
if (!imageTemplate.IsRemap() && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
|
||||
{
|
||||
imageId = ImageId(imageIndex).WithPrimary(sceneryElement.GetPrimaryColour());
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
|
||||
{
|
||||
image_id |= SPRITE_ID_PALETTE_COLOUR_2(
|
||||
sceneryElement.GetPrimaryColour(), sceneryElement.GetSecondaryColour());
|
||||
}
|
||||
else
|
||||
{
|
||||
image_id |= SPRITE_ID_PALETTE_COLOUR_1(sceneryElement.GetPrimaryColour());
|
||||
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
|
||||
}
|
||||
}
|
||||
if (marker != 0)
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | marker;
|
||||
}
|
||||
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED))
|
||||
{
|
||||
PaintAddImageAsParent(
|
||||
session, image_id, { x_offset, y_offset, height }, { boxlength.x, boxlength.y, boxlength.z - 1 },
|
||||
boxoffset);
|
||||
PaintAddImageAsParent(session, imageId, offset, boxLength, boxOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x,
|
||||
boxoffset.y, boxoffset.z);
|
||||
PaintAddImageAsChild(session, imageId, offset, boxLength, boxOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 6E0556: Draw supports:
|
||||
if (sceneryElement.NeedsSupports())
|
||||
{
|
||||
if (!(sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_NO_SUPPORTS)))
|
||||
{
|
||||
int32_t ax = 0;
|
||||
int32_t supportHeight = height;
|
||||
if (supportHeight & 0xF)
|
||||
{
|
||||
supportHeight &= 0xFFFFFFF0;
|
||||
ax = 49;
|
||||
}
|
||||
uint32_t supportImageColourFlags = IMAGE_TYPE_REMAP;
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_PAINT_SUPPORTS))
|
||||
{
|
||||
supportImageColourFlags = SPRITE_ID_PALETTE_COLOUR_1(sceneryElement.GetPrimaryColour());
|
||||
}
|
||||
if (marker != 0)
|
||||
{
|
||||
supportImageColourFlags = marker;
|
||||
}
|
||||
if (direction & 1)
|
||||
{
|
||||
wooden_b_supports_paint_setup(session, 1, ax, supportHeight, supportImageColourFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
wooden_b_supports_paint_setup(session, 0, ax, supportHeight, supportImageColourFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 6E05D1:
|
||||
height += sceneryEntry->height;
|
||||
|
||||
paint_util_set_general_support_height(session, ceil2(height, 8), 0x20);
|
||||
// 6E05FF:
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP))
|
||||
{
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
// 6E0825:
|
||||
paint_util_set_segment_support_height(session, SEGMENT_C4, height, 0x20);
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~SEGMENT_C4, height, 0x20);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
// 6E075C:
|
||||
direction = (sceneryElement.GetSceneryQuadrant() + rotation) % 4;
|
||||
paint_util_set_segment_support_height(
|
||||
session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), height, 0x20);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG27 | SMALL_SCENERY_FLAG_FULL_TILE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENT_C4, 0xFFFF, 0);
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~SEGMENT_C4, 0xFFFF, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))
|
||||
{
|
||||
direction = (sceneryElement.GetSceneryQuadrant() + rotation) % 4;
|
||||
paint_util_set_segment_support_height(
|
||||
session, paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, direction), 0xFFFF, 0);
|
||||
return;
|
||||
}
|
||||
PaintSmallScenerySupports(session, *sceneryEntry, sceneryElement, direction, height, imageTemplate);
|
||||
SetSupportHeights(session, *sceneryEntry, sceneryElement, height);
|
||||
}
|
||||
|
|
|
@ -313,34 +313,34 @@ static const TerrainSurfaceObject* get_surface_object(size_t index)
|
|||
return result;
|
||||
}
|
||||
|
||||
static uint32_t get_surface_image(
|
||||
static ImageId get_surface_image(
|
||||
const paint_session* session, ObjectEntryIndex index, int32_t offset, uint8_t rotation, int32_t grassLength, bool grid,
|
||||
bool underground)
|
||||
{
|
||||
auto image = static_cast<uint32_t>(SPR_NONE);
|
||||
ImageId image;
|
||||
auto obj = get_surface_object(index);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
image = obj->GetImageId(
|
||||
{ session->MapPosition.x >> 5, session->MapPosition.y >> 5 }, grassLength, rotation, offset, grid, underground);
|
||||
image = ImageId(obj->GetImageId(
|
||||
{ session->MapPosition.x >> 5, session->MapPosition.y >> 5 }, grassLength, rotation, offset, grid, underground));
|
||||
if (obj->Colour != 255)
|
||||
{
|
||||
image |= SPRITE_ID_PALETTE_COLOUR_1(obj->Colour);
|
||||
image = image.WithPrimary(obj->Colour);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
static uint32_t get_surface_pattern(uint8_t index, int32_t offset)
|
||||
static ImageId get_surface_pattern(uint8_t index, int32_t offset)
|
||||
{
|
||||
auto image = static_cast<uint32_t>(SPR_NONE);
|
||||
ImageId image;
|
||||
auto obj = get_surface_object(index);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
image = obj->PatternBaseImageId + offset;
|
||||
image = ImageId(obj->PatternBaseImageId + offset);
|
||||
if (obj->Colour != 255)
|
||||
{
|
||||
image |= SPRITE_ID_PALETTE_COLOUR_1(obj->Colour);
|
||||
image = image.WithPrimary(obj->Colour);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
|
@ -366,20 +366,20 @@ static bool surface_should_smooth(uint8_t index)
|
|||
return false;
|
||||
}
|
||||
|
||||
static uint32_t get_edge_image_with_offset(uint8_t index, uint32_t offset)
|
||||
static ImageId get_edge_image_with_offset(uint8_t index, uint32_t offset)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
ImageId result;
|
||||
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
|
||||
auto obj = objMgr.GetLoadedObject(ObjectType::TerrainEdge, index);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
auto tobj = static_cast<TerrainEdgeObject*>(obj);
|
||||
return tobj->BaseImageId + offset;
|
||||
result = ImageId(tobj->BaseImageId + offset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t get_edge_image(uint8_t index, uint8_t type)
|
||||
static ImageId get_edge_image(uint8_t index, uint8_t type)
|
||||
{
|
||||
static constexpr uint32_t offsets[] = {
|
||||
0,
|
||||
|
@ -388,7 +388,7 @@ static uint32_t get_edge_image(uint8_t index, uint8_t type)
|
|||
30,
|
||||
};
|
||||
|
||||
uint32_t result = 0;
|
||||
ImageId result;
|
||||
if (type < std::size(offsets))
|
||||
{
|
||||
result = get_edge_image_with_offset(index, offsets[type]);
|
||||
|
@ -396,7 +396,7 @@ static uint32_t get_edge_image(uint8_t index, uint8_t type)
|
|||
return result;
|
||||
}
|
||||
|
||||
static uint32_t get_tunnel_image(ObjectEntryIndex index, uint8_t type)
|
||||
static ImageId get_tunnel_image(ObjectEntryIndex index, uint8_t type, edge_t edge)
|
||||
{
|
||||
static constexpr uint32_t offsets[TUNNEL_TYPE_COUNT] = { 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80,
|
||||
36, 48, 60, 72, 76, 80, 84, 88, 92, 96, 100 };
|
||||
|
@ -413,10 +413,10 @@ static uint32_t get_tunnel_image(ObjectEntryIndex index, uint8_t type)
|
|||
if (!hasDoors && type >= REGULAR_TUNNEL_TYPE_COUNT && type < std::size(offsets))
|
||||
type = TUNNEL_0;
|
||||
|
||||
uint32_t result = 0;
|
||||
ImageId result;
|
||||
if (type < std::size(offsets))
|
||||
{
|
||||
result = get_edge_image_with_offset(index, offsets[type]);
|
||||
result = get_edge_image_with_offset(index, offsets[type]).WithIndexOffset(edge == EDGE_BOTTOMRIGHT ? 2 : 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ static void viewport_surface_smoothen_edge(
|
|||
{
|
||||
attached_paint_struct* out = session->LastAttachedPS;
|
||||
// set content and enable masking
|
||||
out->colour_image_id = get_surface_pattern(neighbour.terrain, cl);
|
||||
out->colour_image_id = get_surface_pattern(neighbour.terrain, cl).ToUInt32();
|
||||
out->flags |= PAINT_STRUCT_FLAG_IS_MASKED;
|
||||
}
|
||||
}
|
||||
|
@ -629,15 +629,15 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t base_image_id = get_edge_image(edgeStyle, 0);
|
||||
auto baseImageId = get_edge_image(edgeStyle, 0);
|
||||
if (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
|
||||
{
|
||||
base_image_id = get_edge_image(edgeStyle, 1);
|
||||
baseImageId = get_edge_image(edgeStyle, 1);
|
||||
}
|
||||
|
||||
if (edge == EDGE_BOTTOMRIGHT)
|
||||
{
|
||||
base_image_id += 5;
|
||||
baseImageId = baseImageId.WithIndexOffset(5);
|
||||
}
|
||||
|
||||
uint8_t curHeight = std::min(neighbourCornerHeight1, neighbourCornerHeight2);
|
||||
|
@ -653,8 +653,8 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
|
||||
if (curHeight != cornerHeight1 && curHeight != cornerHeight2)
|
||||
{
|
||||
uint32_t image_id = base_image_id + image_offset;
|
||||
PaintAddImageAsParent(session, image_id, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
auto imageId = baseImageId.WithIndexOffset(image_offset);
|
||||
PaintAddImageAsParent(session, imageId, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
curHeight++;
|
||||
}
|
||||
}
|
||||
|
@ -677,8 +677,8 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
}
|
||||
}
|
||||
|
||||
const uint32_t image_id = base_image_id + image_offset;
|
||||
PaintAddImageAsParent(session, image_id, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
auto imageId = baseImageId.WithIndexOffset(image_offset);
|
||||
PaintAddImageAsParent(session, imageId, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
|
||||
if (isWater || curHeight != tunnelArray[tunnelIndex].height)
|
||||
{
|
||||
PaintAddImageAsParent(session, base_image_id, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
PaintAddImageAsParent(session, baseImageId, { offset, curHeight * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
|
||||
curHeight++;
|
||||
continue;
|
||||
|
@ -720,9 +720,9 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
boundBoxLength -= 16;
|
||||
}
|
||||
|
||||
uint32_t image_id = get_tunnel_image(edgeStyle, tunnelType) + (edge == EDGE_BOTTOMRIGHT ? 2 : 0);
|
||||
auto imageId = get_tunnel_image(edgeStyle, tunnelType, edge);
|
||||
PaintAddImageAsParent(
|
||||
session, image_id, { offset, zOffset }, { tunnelBounds.x, tunnelBounds.y, boundBoxLength - 1 },
|
||||
session, imageId, { offset, zOffset }, { tunnelBounds.x, tunnelBounds.y, boundBoxLength - 1 },
|
||||
{ 0, 0, boundBoxOffsetZ });
|
||||
|
||||
boundBoxOffsetZ = curHeight * COORDS_Z_PER_TINY_Z;
|
||||
|
@ -734,9 +734,9 @@ static void viewport_surface_draw_tile_side_bottom(
|
|||
boundBoxLength -= 16;
|
||||
}
|
||||
|
||||
image_id = get_tunnel_image(edgeStyle, tunnelType) + (edge == EDGE_BOTTOMRIGHT ? 2 : 0) + 1;
|
||||
imageId = get_tunnel_image(edgeStyle, tunnelType, edge).WithIndexOffset(1);
|
||||
PaintAddImageAsParent(
|
||||
session, image_id, { offset, curHeight * COORDS_Z_PER_TINY_Z },
|
||||
session, imageId, { offset, curHeight * COORDS_Z_PER_TINY_Z },
|
||||
{ tunnelBounds.x, tunnelBounds.y, boundBoxLength - 1 },
|
||||
{ tunnelTopBoundBoxOffset.x, tunnelTopBoundBoxOffset.y, boundBoxOffsetZ });
|
||||
|
||||
|
@ -831,28 +831,27 @@ static void viewport_surface_draw_tile_side_top(
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t base_image_id;
|
||||
|
||||
ImageId baseImageId;
|
||||
if (isWater)
|
||||
{
|
||||
base_image_id = get_edge_image(terrain, 2); // var_08
|
||||
baseImageId = get_edge_image(terrain, 2); // var_08
|
||||
if (session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
|
||||
{
|
||||
base_image_id = get_edge_image(terrain, 1); // var_04
|
||||
baseImageId = get_edge_image(terrain, 1); // var_04
|
||||
}
|
||||
base_image_id += (edge == EDGE_TOPLEFT ? 5 : 0);
|
||||
baseImageId = baseImageId.WithIndexOffset(edge == EDGE_TOPLEFT ? 5 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(session->ViewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE))
|
||||
{
|
||||
const uint8_t incline = (cornerHeight2 - cornerHeight1) + 1;
|
||||
const uint32_t image_id = get_edge_image(terrain, 3) + (edge == EDGE_TOPLEFT ? 3 : 0) + incline; // var_c;
|
||||
const auto imageId = get_edge_image(terrain, 3).WithIndexOffset((edge == EDGE_TOPLEFT ? 3 : 0) + incline);
|
||||
const int16_t y = (height - cornerHeight1) * COORDS_Z_PER_TINY_Z;
|
||||
PaintAttachToPreviousPS(session, image_id, 0, y);
|
||||
PaintAttachToPreviousPS(session, imageId, 0, y);
|
||||
return;
|
||||
}
|
||||
base_image_id = get_edge_image(terrain, 1) + (edge == EDGE_TOPLEFT ? 5 : 0); // var_04
|
||||
baseImageId = get_edge_image(terrain, 1).WithIndexOffset(edge == EDGE_TOPLEFT ? 5 : 0);
|
||||
}
|
||||
|
||||
uint8_t cur_height = std::min(neighbourCornerHeight2, neighbourCornerHeight1);
|
||||
|
@ -867,9 +866,9 @@ static void viewport_surface_draw_tile_side_top(
|
|||
|
||||
if (cur_height != cornerHeight1 && cur_height != cornerHeight2)
|
||||
{
|
||||
const uint32_t image_id = base_image_id + image_offset;
|
||||
auto imageId = baseImageId.WithIndexOffset(image_offset);
|
||||
PaintAddImageAsParent(
|
||||
session, image_id, { offset.x, offset.y, cur_height * COORDS_Z_PER_TINY_Z }, { bounds.x, bounds.y, 15 });
|
||||
session, imageId, { offset.x, offset.y, cur_height * COORDS_Z_PER_TINY_Z }, { bounds.x, bounds.y, 15 });
|
||||
cur_height++;
|
||||
}
|
||||
}
|
||||
|
@ -884,7 +883,7 @@ static void viewport_surface_draw_tile_side_top(
|
|||
|
||||
while (cur_height < cornerHeight1 && cur_height < neighbourCornerHeight1)
|
||||
{
|
||||
PaintAddImageAsParent(session, base_image_id, { offset, cur_height * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
PaintAddImageAsParent(session, baseImageId, { offset, cur_height * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
cur_height++;
|
||||
}
|
||||
|
||||
|
@ -899,8 +898,8 @@ static void viewport_surface_draw_tile_side_top(
|
|||
}
|
||||
}
|
||||
|
||||
const uint32_t image_id = base_image_id + image_offset;
|
||||
PaintAddImageAsParent(session, image_id, { offset, cur_height * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
auto imageId = baseImageId.WithIndexOffset(image_offset);
|
||||
PaintAddImageAsParent(session, imageId, { offset, cur_height * COORDS_Z_PER_TINY_Z }, { bounds, 15 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1058,20 +1057,23 @@ void PaintSurface(paint_session* session, uint8_t direction, uint16_t height, co
|
|||
assert(surfaceShape < std::size(byte_97B444));
|
||||
const uint8_t image_offset = byte_97B444[surfaceShape];
|
||||
|
||||
auto imageId = get_surface_image(session, terrain_type, image_offset, rotation, grassLength, showGridlines, false);
|
||||
ImageId imageId;
|
||||
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
|
||||
{
|
||||
imageId = SPR_TERRAIN_TRACK_DESIGNER;
|
||||
imageId = ImageId(SPR_TERRAIN_TRACK_DESIGNER);
|
||||
}
|
||||
else
|
||||
{
|
||||
imageId = get_surface_image(session, terrain_type, image_offset, rotation, grassLength, showGridlines, false);
|
||||
}
|
||||
if (session->ViewFlags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE))
|
||||
{
|
||||
imageId &= 0xDC07FFFF; // remove colour
|
||||
imageId |= 0x41880000;
|
||||
imageId = imageId.WithRemap(FilterPaletteID::PaletteDarken1).WithBlended(true);
|
||||
}
|
||||
|
||||
if (OpenRCT2::TileInspector::IsElementSelected(elementPtr))
|
||||
{
|
||||
imageId |= CONSTRUCTION_MARKER;
|
||||
imageId = imageId.WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 32, 32, -1 });
|
||||
|
@ -1265,8 +1267,8 @@ void PaintSurface(paint_session* session, uint8_t direction, uint16_t height, co
|
|||
&& !(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)))
|
||||
{
|
||||
const uint8_t image_offset = byte_97B444[surfaceShape];
|
||||
const uint32_t image_id = get_surface_image(session, terrain_type, image_offset, rotation, 1, false, true);
|
||||
PaintAttachToPreviousPS(session, image_id, 0, 0);
|
||||
auto imageId = get_surface_image(session, terrain_type, image_offset, rotation, 1, false, true);
|
||||
PaintAttachToPreviousPS(session, imageId, 0, 0);
|
||||
}
|
||||
|
||||
if (!(session->ViewFlags & VIEWPORT_FLAG_HIDE_VERTICAL))
|
||||
|
|
|
@ -77,7 +77,6 @@ enum
|
|||
SPR_TERRAIN_SELECTION_QUARTER = 3081,
|
||||
SPR_WATER_MASK = 5048,
|
||||
SPR_WATER_OVERLAY = 5053,
|
||||
SPR_HEIGHT_MARKER_BASE = 5769,
|
||||
|
||||
SPR_TERRAIN_BOUNDARY_FENCES_1 = 22872,
|
||||
SPR_TERRAIN_BOUNDARY_FENCES_2 = 22873,
|
||||
|
|
|
@ -24,275 +24,189 @@
|
|||
#include "../Paint.h"
|
||||
#include "Paint.TileElement.h"
|
||||
|
||||
static constexpr const uint8_t byte_9A406C[] = {
|
||||
static constexpr const uint8_t DirectionToDoorImageOffset0[] = {
|
||||
2, 2, 22, 26, 30, 34, 34, 34, 34, 34, 30, 26, 22, 2, 6, 2, 2, 2, 6, 10, 14, 18, 18, 18, 18, 18, 14, 10, 6, 2, 22, 2,
|
||||
};
|
||||
|
||||
static constexpr const uint8_t byte_9A408C[] = {
|
||||
static constexpr const uint8_t DirectionToDoorImageOffset1[] = {
|
||||
0, 0, 4, 8, 12, 16, 16, 16, 16, 16, 12, 8, 4, 0, 20, 0, 0, 0, 20, 24, 28, 32, 32, 32, 32, 32, 28, 24, 20, 0, 4, 0,
|
||||
};
|
||||
|
||||
static constexpr const uint8_t byte_9A40AC[] = {
|
||||
static constexpr const uint8_t DirectionToDoorImageOffset2[] = {
|
||||
2, 2, 6, 10, 14, 18, 18, 18, 18, 18, 14, 10, 6, 2, 22, 2, 2, 2, 22, 26, 30, 34, 34, 34, 34, 34, 30, 26, 22, 2, 6, 2,
|
||||
};
|
||||
|
||||
static constexpr const uint8_t byte_9A40CC[] = {
|
||||
static constexpr const uint8_t DirectionToDoorImageOffset3[] = {
|
||||
0, 0, 20, 24, 28, 32, 32, 32, 32, 32, 28, 24, 20, 0, 4, 0, 0, 0, 4, 8, 12, 16, 16, 16, 16, 16, 12, 8, 4, 0, 20, 0,
|
||||
};
|
||||
|
||||
static constexpr const uint8_t* DirectionToDoorImageOffset[] = { DirectionToDoorImageOffset0, DirectionToDoorImageOffset1,
|
||||
DirectionToDoorImageOffset2, DirectionToDoorImageOffset3 };
|
||||
|
||||
static void PaintWallDoor(
|
||||
paint_session* session, uint32_t imageId, WallSceneryEntry* wallEntry, uint32_t imageColourFlags, uint32_t tertiaryColour,
|
||||
uint32_t dword_141F710, CoordsXYZ offset, CoordsXYZ boundsR1, CoordsXYZ boundsR1_, CoordsXYZ boundsR2, CoordsXYZ boundsR2_,
|
||||
CoordsXYZ boundsL1, CoordsXYZ boundsL1_)
|
||||
paint_session* session, const WallSceneryEntry& wallEntry, ImageId imageId, CoordsXYZ offset, CoordsXYZ bbLengthR1,
|
||||
CoordsXYZ bbOffsetR1, CoordsXYZ bbLengthR2, CoordsXYZ bbOffsetR2, CoordsXYZ bbLengthL, CoordsXYZ bbOffsetL)
|
||||
{
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
|
||||
auto newImageId0 = imageId;
|
||||
auto newImageId1 = imageId.WithIndexOffset(1);
|
||||
if (wallEntry.flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
{
|
||||
imageId |= imageColourFlags;
|
||||
}
|
||||
|
||||
if (dword_141F710 != 0)
|
||||
{
|
||||
imageId = (imageId & 0x7FFFF) | dword_141F710;
|
||||
}
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
{
|
||||
paint_struct* ps;
|
||||
|
||||
ps = PaintAddImageAsParent(session, imageId, offset, boundsR1, boundsR1_);
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = tertiaryColour;
|
||||
}
|
||||
|
||||
ps = PaintAddImageAsParent(session, imageId + 1, offset, boundsR2, boundsR2_);
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = tertiaryColour;
|
||||
}
|
||||
PaintAddImageAsParent(session, newImageId0, offset, bbLengthR1, bbOffsetR1);
|
||||
PaintAddImageAsParent(session, newImageId1, offset, bbLengthR2, bbOffsetR2);
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_struct* ps;
|
||||
PaintAddImageAsParent(session, newImageId0, offset, bbLengthL, bbOffsetL);
|
||||
PaintAddImageAsChild(session, newImageId1, offset, bbLengthL, bbOffsetL);
|
||||
}
|
||||
}
|
||||
|
||||
ps = PaintAddImageAsParent(session, imageId, offset, boundsL1, boundsL1_);
|
||||
if (ps != nullptr)
|
||||
static void PaintWallDoor(
|
||||
paint_session* session, const WallSceneryEntry& wallEntry, const WallElement& wallElement, ImageId imageTemplate,
|
||||
Direction direction, int32_t height)
|
||||
{
|
||||
auto bbHeight = wallEntry.height * 8 - 2;
|
||||
auto animationFrame = wallElement.GetAnimationFrame();
|
||||
|
||||
// Add the direction as well
|
||||
if (wallElement.AnimationIsBackwards())
|
||||
animationFrame |= (1 << 4);
|
||||
|
||||
auto imageId = wallEntry.image + DirectionToDoorImageOffset[direction & 3][animationFrame];
|
||||
switch (direction)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ps->tertiary_colour = tertiaryColour;
|
||||
CoordsXYZ bbLengthR1 = { 1, 3, bbHeight - 5 };
|
||||
CoordsXYZ bbOffsetR1 = { 1, 1, height + 1 };
|
||||
CoordsXYZ bbLengthR2 = { 1, 28, 3 };
|
||||
CoordsXYZ bbOffsetR2 = { 1, 1, height + bbHeight - 9 };
|
||||
|
||||
CoordsXYZ bbLengthL = { 1, 28, bbHeight };
|
||||
CoordsXYZ bbOffsetL = { 1, 1, height + 1 };
|
||||
|
||||
CoordsXYZ offset = { 0, 0, height };
|
||||
|
||||
PaintWallDoor(
|
||||
session, wallEntry, imageTemplate.WithIndex(imageId), offset, bbLengthR1, bbOffsetR1, bbLengthR2, bbOffsetR2,
|
||||
bbLengthL, bbOffsetL);
|
||||
break;
|
||||
}
|
||||
|
||||
ps = PaintAddImageAsChild(
|
||||
session, imageId + 1, static_cast<int8_t>(offset.x), static_cast<int8_t>(offset.y), boundsL1.x, boundsL1.y,
|
||||
static_cast<int8_t>(boundsL1.z), offset.z, boundsL1_.x, boundsL1_.y, boundsL1_.z);
|
||||
if (ps != nullptr)
|
||||
case 1:
|
||||
{
|
||||
ps->tertiary_colour = tertiaryColour;
|
||||
CoordsXYZ bbLengthR1 = { 3, 3, bbHeight - 5 };
|
||||
CoordsXYZ bbOffsetR1 = { 1, 30, height + 1 };
|
||||
CoordsXYZ bbLengthR2 = { 29, 3, 2 };
|
||||
CoordsXYZ bbOffsetR2 = { 1, 30, height + bbHeight - 8 };
|
||||
|
||||
CoordsXYZ bbLengthL = { 29, 1, bbHeight };
|
||||
CoordsXYZ bbOffsetL = { 2, 30, height + 1 };
|
||||
|
||||
CoordsXYZ offset = { 1, 31, height };
|
||||
|
||||
PaintWallDoor(
|
||||
session, wallEntry, imageTemplate.WithIndex(imageId), offset, bbLengthR1, bbOffsetR1, bbLengthR2, bbOffsetR2,
|
||||
bbLengthL, bbOffsetL);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
CoordsXYZ bbLengthR1 = { 3, 3, bbHeight - 5 };
|
||||
CoordsXYZ bbOffsetR1 = { 30, 1, height + 1 };
|
||||
CoordsXYZ bbLengthR2 = { 3, 29, 2 };
|
||||
CoordsXYZ bbOffsetR2 = { 30, 1, height + bbHeight - 8 };
|
||||
|
||||
CoordsXYZ bbLengthL = { 1, 29, bbHeight };
|
||||
CoordsXYZ bbOffsetL = { 30, 2, height + 1 };
|
||||
|
||||
CoordsXYZ offset = { 31, 0, height };
|
||||
|
||||
PaintWallDoor(
|
||||
session, wallEntry, imageTemplate.WithIndex(imageId), offset, bbLengthR1, bbOffsetR1, bbLengthR2, bbOffsetR2,
|
||||
bbLengthL, bbOffsetL);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
CoordsXYZ bbLengthR1 = { 3, 1, bbHeight - 5 };
|
||||
CoordsXYZ bbOffsetR1 = { 1, 1, height + 1 };
|
||||
CoordsXYZ bbLengthR2 = { 28, 1, 3 };
|
||||
CoordsXYZ bbOffsetR2 = { 1, 1, height + bbHeight - 9 };
|
||||
|
||||
CoordsXYZ bbLengthL = { 28, 1, bbHeight };
|
||||
CoordsXYZ bbOffsetL = { 1, 1, height + 1 };
|
||||
|
||||
CoordsXYZ offset = { 2, 1, height };
|
||||
|
||||
PaintWallDoor(
|
||||
session, wallEntry, imageTemplate.WithIndex(imageId), offset, bbLengthR1, bbOffsetR1, bbLengthR2, bbOffsetR2,
|
||||
bbLengthL, bbOffsetL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PaintWallWall(
|
||||
paint_session* session, uint32_t frameNum, const WallSceneryEntry* wallEntry, uint32_t dword_141F710,
|
||||
uint32_t imageColourFlags, uint32_t dword_141F718, uint32_t tertiaryColour, uint32_t imageOffset, CoordsXYZ offset,
|
||||
CoordsXYZ bounds, CoordsXYZ boundsOffset)
|
||||
paint_session* session, const WallSceneryEntry& wallEntry, ImageId imageTemplate, uint32_t imageOffset, CoordsXYZ offset,
|
||||
CoordsXYZ bounds, CoordsXYZ boundsOffset, bool isGhost)
|
||||
{
|
||||
uint32_t baseImageId = wallEntry->image + imageOffset + frameNum;
|
||||
uint32_t imageId = baseImageId;
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_GLASS)
|
||||
auto frameNum = (wallEntry.flags2 & WALL_SCENERY_2_ANIMATED) ? (gCurrentTicks & 7) * 2 : 0;
|
||||
auto imageIndex = wallEntry.image + imageOffset + frameNum;
|
||||
PaintAddImageAsParent(session, imageTemplate.WithIndex(imageIndex), offset, bounds, boundsOffset);
|
||||
if ((wallEntry.flags & WALL_SCENERY_HAS_GLASS) && !isGhost)
|
||||
{
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
|
||||
{
|
||||
imageId |= imageColourFlags;
|
||||
}
|
||||
auto glassImageId = ImageId(imageIndex + 6).WithTransparancy(imageTemplate.GetPrimary());
|
||||
PaintAddImageAsChild(session, glassImageId, offset, bounds, boundsOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (dword_141F710 != 0)
|
||||
{
|
||||
imageId = (imageId & 0x7FFFF) | dword_141F710;
|
||||
}
|
||||
static void PaintWallScrollingText(
|
||||
paint_session* session, const WallSceneryEntry& wallEntry, const WallElement& wallElement, Direction direction,
|
||||
int32_t height, const CoordsXYZ& boundsOffset, bool isGhost)
|
||||
{
|
||||
if (direction != 0 && direction != 3)
|
||||
return;
|
||||
|
||||
PaintAddImageAsParent(session, imageId, offset, bounds, boundsOffset);
|
||||
if (dword_141F710 == 0)
|
||||
{
|
||||
imageId = baseImageId + dword_141F718;
|
||||
PaintAddImageAsChild(
|
||||
session, imageId, static_cast<int8_t>(offset.x), static_cast<int8_t>(offset.y), bounds.x, bounds.y,
|
||||
static_cast<int8_t>(bounds.z), offset.z, boundsOffset.x, boundsOffset.y, boundsOffset.z);
|
||||
}
|
||||
auto scrollingMode = wallEntry.scrolling_mode;
|
||||
if (scrollingMode == SCROLLING_MODE_NONE)
|
||||
return;
|
||||
|
||||
scrollingMode = wallEntry.scrolling_mode + ((direction + 1) & 3);
|
||||
if (scrollingMode >= MAX_SCROLLING_TEXT_MODES)
|
||||
return;
|
||||
|
||||
auto banner = wallElement.GetBanner();
|
||||
if (banner == nullptr)
|
||||
return;
|
||||
|
||||
auto textColour = isGhost ? static_cast<colour_t>(COLOUR_GREY) : wallElement.GetSecondaryColour();
|
||||
auto textPaletteIndex = direction == 0 ? ColourMapA[textColour].mid_dark : ColourMapA[textColour].light;
|
||||
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
char signString[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
|
||||
{
|
||||
imageId |= imageColourFlags;
|
||||
}
|
||||
|
||||
if (dword_141F710 != 0)
|
||||
{
|
||||
imageId = (imageId & 0x7FFFF) | dword_141F710;
|
||||
}
|
||||
|
||||
paint_struct* paint = PaintAddImageAsParent(session, imageId, offset, bounds, boundsOffset);
|
||||
if (paint != nullptr)
|
||||
{
|
||||
paint->tertiary_colour = tertiaryColour;
|
||||
}
|
||||
format_string(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
|
||||
auto stringWidth = gfx_get_string_width(signString, FontSpriteBase::TINY);
|
||||
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
auto imageId = scrolling_text_setup(session, STR_SCROLLING_SIGN_TEXT, ft, scroll, scrollingMode, textPaletteIndex);
|
||||
PaintAddImageAsChild(session, imageId, { 0, 0, height + 8 }, { 1, 1, 13 }, boundsOffset);
|
||||
}
|
||||
/**
|
||||
* rct2: 0x006E44B0
|
||||
* @param direction (cl)
|
||||
* @param height (dx)
|
||||
* @param tile_element (esi)
|
||||
*/
|
||||
void PaintWall(paint_session* session, uint8_t direction, int32_t height, const WallElement& wallElement)
|
||||
|
||||
static void PaintWallWall(
|
||||
paint_session* session, const WallSceneryEntry& wallEntry, const WallElement& wallElement, ImageId imageTemplate,
|
||||
Direction direction, int32_t height, bool isGhost)
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::Wall;
|
||||
|
||||
auto* wallEntry = wallElement.GetEntry();
|
||||
if (wallEntry == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint32_t frameNum = 0;
|
||||
|
||||
if (wallEntry->flags2 & WALL_SCENERY_2_ANIMATED)
|
||||
{
|
||||
frameNum = (gCurrentTicks & 7) * 2;
|
||||
}
|
||||
|
||||
int32_t primaryColour = wallElement.GetPrimaryColour();
|
||||
uint32_t imageColourFlags = SPRITE_ID_PALETTE_COLOUR_1(primaryColour);
|
||||
uint32_t dword_141F718 = imageColourFlags + 0x23800006;
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
{
|
||||
uint8_t secondaryColour = wallElement.GetSecondaryColour();
|
||||
imageColourFlags |= secondaryColour << 24 | IMAGE_TYPE_REMAP_2_PLUS;
|
||||
}
|
||||
|
||||
uint32_t tertiaryColour = 0;
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_TERNARY_COLOUR)
|
||||
{
|
||||
tertiaryColour = wallElement.GetTertiaryColour();
|
||||
imageColourFlags &= 0x0DFFFFFFF;
|
||||
}
|
||||
|
||||
paint_util_set_general_support_height(session, 8 * wallElement.clearance_height, 0x20);
|
||||
|
||||
uint32_t dword_141F710 = 0;
|
||||
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
{
|
||||
if (!track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&wallElement)))
|
||||
{
|
||||
dword_141F710 = SPRITE_ID_PALETTE_COLOUR_1(EnumValue(FilterPaletteID::Palette46));
|
||||
}
|
||||
}
|
||||
|
||||
if (wallElement.IsGhost())
|
||||
{
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
dword_141F710 = CONSTRUCTION_MARKER;
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&wallElement)))
|
||||
{
|
||||
dword_141F710 = CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
// Save tile_element
|
||||
|
||||
uint8_t ah = wallEntry->height * 8 - 2;
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOOR)
|
||||
{
|
||||
CoordsXYZ offset;
|
||||
CoordsXYZ boundsR1, boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_;
|
||||
uint8_t animationFrame = wallElement.GetAnimationFrame();
|
||||
// Add the direction as well
|
||||
if (wallElement.AnimationIsBackwards())
|
||||
animationFrame |= (1 << 4);
|
||||
uint32_t imageId;
|
||||
switch (direction)
|
||||
{
|
||||
case 0:
|
||||
imageId = wallEntry->image + byte_9A406C[animationFrame];
|
||||
|
||||
boundsR1 = { 1, 3, static_cast<int16_t>(ah - 5) };
|
||||
boundsR1_ = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
boundsR2 = { 1, 28, 3 };
|
||||
boundsR2_ = { 1, 1, static_cast<int16_t>(height + ah - 9) };
|
||||
|
||||
boundsL1 = { 1, 28, ah };
|
||||
boundsL1_ = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
|
||||
offset = { 0, 0, static_cast<int16_t>(height) };
|
||||
|
||||
PaintWallDoor(
|
||||
session, imageId, wallEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1, boundsR1_,
|
||||
boundsR2, boundsR2_, boundsL1, boundsL1_);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
imageId = wallEntry->image + byte_9A408C[animationFrame];
|
||||
|
||||
boundsR1 = { 3, 3, static_cast<int16_t>(ah - 5) };
|
||||
boundsR1_ = { 1, 30, static_cast<int16_t>(height + 1) };
|
||||
boundsR2 = { 29, 3, 2 };
|
||||
boundsR2_ = { 1, 30, static_cast<int16_t>(height + ah - 8) };
|
||||
|
||||
boundsL1 = { 29, 1, ah };
|
||||
boundsL1_ = { 2, 30, static_cast<int16_t>(height + 1) };
|
||||
|
||||
offset = { 1, 31, static_cast<int16_t>(height) };
|
||||
|
||||
PaintWallDoor(
|
||||
session, imageId, wallEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1, boundsR1_,
|
||||
boundsR2, boundsR2_, boundsL1, boundsL1_);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
imageId = wallEntry->image + byte_9A40AC[animationFrame];
|
||||
|
||||
boundsR1 = { 3, 3, static_cast<int16_t>(ah - 5) };
|
||||
boundsR1_ = { 30, 1, static_cast<int16_t>(height + 1) };
|
||||
boundsR2 = { 3, 29, 2 };
|
||||
boundsR2_ = { 30, 1, static_cast<int16_t>(height + ah - 8) };
|
||||
|
||||
boundsL1 = { 1, 29, ah };
|
||||
boundsL1_ = { 30, 2, static_cast<int16_t>(height + 1) };
|
||||
|
||||
offset = { 31, 0, static_cast<int16_t>(height) };
|
||||
|
||||
PaintWallDoor(
|
||||
session, imageId, wallEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1, boundsR1_,
|
||||
boundsR2, boundsR2_, boundsL1, boundsL1_);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
imageId = wallEntry->image + byte_9A40CC[animationFrame];
|
||||
|
||||
boundsR1 = { 3, 1, static_cast<int16_t>(ah - 5) };
|
||||
boundsR1_ = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
boundsR2 = { 28, 1, 3 };
|
||||
boundsR2_ = { 1, 1, static_cast<int16_t>(height + ah - 9) };
|
||||
|
||||
boundsL1 = { 28, 1, ah };
|
||||
boundsL1_ = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
|
||||
offset = { 2, 1, static_cast<int16_t>(height) };
|
||||
|
||||
PaintWallDoor(
|
||||
session, imageId, wallEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1, boundsR1_,
|
||||
boundsR2, boundsR2_, boundsL1, boundsL1_);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t imageOffset = 0;
|
||||
CoordsXYZ offset = { 0, 0, 0 }, bounds = { 0, 0, 0 }, boundsOffset = { 0, 0, 0 };
|
||||
|
||||
uint8_t bbHeight = wallEntry.height * 8 - 2;
|
||||
ImageIndex imageOffset = 0;
|
||||
CoordsXYZ offset, bounds, boundsOffset;
|
||||
switch (direction)
|
||||
{
|
||||
case 0:
|
||||
|
@ -309,9 +223,9 @@ void PaintWall(paint_session* session, uint8_t direction, int32_t height, const
|
|||
imageOffset = 1;
|
||||
}
|
||||
|
||||
offset = { 0, 0, static_cast<int16_t>(height) };
|
||||
bounds = { 1, 28, ah };
|
||||
boundsOffset = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
offset = { 0, 0, height };
|
||||
bounds = { 1, 28, bbHeight };
|
||||
boundsOffset = { 1, 1, height + 1 };
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -328,24 +242,24 @@ void PaintWall(paint_session* session, uint8_t direction, int32_t height, const
|
|||
imageOffset = 0;
|
||||
}
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_GLASS)
|
||||
if (wallEntry.flags & WALL_SCENERY_HAS_GLASS)
|
||||
{
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
if (wallEntry.flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
{
|
||||
imageOffset += 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
if (wallEntry.flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
{
|
||||
imageOffset += 6;
|
||||
}
|
||||
}
|
||||
|
||||
offset = { 1, 31, static_cast<int16_t>(height) };
|
||||
bounds = { 29, 1, ah };
|
||||
boundsOffset = { 2, 30, static_cast<int16_t>(height + 1) };
|
||||
offset = { 1, 31, height };
|
||||
bounds = { 29, 1, bbHeight };
|
||||
boundsOffset = { 2, 30, height + 1 };
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
@ -362,14 +276,14 @@ void PaintWall(paint_session* session, uint8_t direction, int32_t height, const
|
|||
imageOffset = 1;
|
||||
}
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
if (wallEntry.flags & WALL_SCENERY_IS_DOUBLE_SIDED)
|
||||
{
|
||||
imageOffset += 6;
|
||||
}
|
||||
|
||||
offset = { 31, 0, static_cast<int16_t>(height) };
|
||||
bounds = { 1, 29, ah };
|
||||
boundsOffset = { 30, 2, static_cast<int16_t>(height + 1) };
|
||||
offset = { 31, 0, height };
|
||||
bounds = { 1, 29, bbHeight };
|
||||
boundsOffset = { 30, 2, height + 1 };
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -386,66 +300,70 @@ void PaintWall(paint_session* session, uint8_t direction, int32_t height, const
|
|||
imageOffset = 0;
|
||||
}
|
||||
|
||||
offset = { 2, 1, static_cast<int16_t>(height) };
|
||||
bounds = { 28, 1, ah };
|
||||
boundsOffset = { 1, 1, static_cast<int16_t>(height + 1) };
|
||||
offset = { 2, 1, height };
|
||||
bounds = { 28, 1, bbHeight };
|
||||
boundsOffset = { 1, 1, height + 1 };
|
||||
break;
|
||||
}
|
||||
|
||||
PaintWallWall(
|
||||
session, frameNum, wallEntry, dword_141F710, imageColourFlags, dword_141F718, tertiaryColour, imageOffset, offset,
|
||||
bounds, boundsOffset);
|
||||
PaintWallWall(session, wallEntry, imageTemplate, imageOffset, offset, bounds, boundsOffset, isGhost);
|
||||
PaintWallScrollingText(session, wallEntry, wallElement, direction, height, boundsOffset, isGhost);
|
||||
}
|
||||
|
||||
if (wallEntry->scrolling_mode == SCROLLING_MODE_NONE)
|
||||
void PaintWall(paint_session* session, uint8_t direction, int32_t height, const WallElement& wallElement)
|
||||
{
|
||||
auto* wallEntry = wallElement.GetEntry();
|
||||
if (wallEntry == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction != 0 && direction != 3)
|
||||
session->InteractionType = ViewportInteractionItem::Wall;
|
||||
|
||||
ImageId imageTemplate;
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
|
||||
{
|
||||
return;
|
||||
imageTemplate = imageTemplate.WithPrimary(wallElement.GetPrimaryColour());
|
||||
}
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
{
|
||||
imageTemplate = imageTemplate.WithSecondary(wallElement.GetSecondaryColour());
|
||||
}
|
||||
if (wallEntry->flags & WALL_SCENERY_HAS_TERNARY_COLOUR)
|
||||
{
|
||||
imageTemplate = imageTemplate.WithTertiary(wallElement.GetTertiaryColour());
|
||||
}
|
||||
|
||||
auto secondaryColour = wallElement.GetSecondaryColour();
|
||||
if (dword_141F710 != 0)
|
||||
paint_util_set_general_support_height(session, 8 * wallElement.clearance_height, 0x20);
|
||||
|
||||
auto isGhost = false;
|
||||
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
||||
{
|
||||
secondaryColour = COLOUR_GREY;
|
||||
if (!track_design_save_contains_tile_element(reinterpret_cast<const TileElement*>(&wallElement)))
|
||||
{
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette46);
|
||||
isGhost = true;
|
||||
}
|
||||
}
|
||||
if (direction == 0)
|
||||
|
||||
if (wallElement.IsGhost())
|
||||
{
|
||||
secondaryColour = ColourMapA[secondaryColour].mid_dark;
|
||||
session->InteractionType = ViewportInteractionItem::None;
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
isGhost = true;
|
||||
}
|
||||
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&wallElement)))
|
||||
{
|
||||
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
||||
isGhost = true;
|
||||
}
|
||||
|
||||
if (wallEntry->flags & WALL_SCENERY_IS_DOOR)
|
||||
{
|
||||
PaintWallDoor(session, *wallEntry, wallElement, imageTemplate, direction, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
secondaryColour = ColourMapA[secondaryColour].light;
|
||||
}
|
||||
|
||||
uint16_t scrollingMode = wallEntry->scrolling_mode + ((direction + 1) & 0x3);
|
||||
if (scrollingMode >= MAX_SCROLLING_TEXT_MODES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto banner = wallElement.GetBanner();
|
||||
if (banner != nullptr)
|
||||
{
|
||||
auto ft = Formatter();
|
||||
banner->FormatTextTo(ft);
|
||||
utf8 signString[256];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
{
|
||||
format_string_to_upper(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
format_string(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, ft.Data());
|
||||
}
|
||||
|
||||
uint16_t stringWidth = gfx_get_string_width(signString, FontSpriteBase::TINY);
|
||||
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
||||
|
||||
PaintAddImageAsChild(
|
||||
session, scrolling_text_setup(session, STR_SCROLLING_SIGN_TEXT, ft, scroll, scrollingMode, secondaryColour), 0, 0,
|
||||
1, 1, 13, height + 8, boundsOffset.x, boundsOffset.y, boundsOffset.z);
|
||||
PaintWallWall(session, *wallEntry, wallElement, imageTemplate, direction, height, isGhost);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -796,23 +796,16 @@ bool track_paint_util_draw_station_covers_2(
|
|||
return false;
|
||||
}
|
||||
|
||||
auto baseImageIndex = stationObject->ShelterImageId;
|
||||
if (baseImageIndex == ImageIndexUndefined)
|
||||
return false;
|
||||
|
||||
static constexpr const int16_t heights[][2] = {
|
||||
{ 22, 0 },
|
||||
{ 30, 0 },
|
||||
{ 46, 0 },
|
||||
};
|
||||
|
||||
uint32_t imageId;
|
||||
uint32_t baseImageId = stationObject->ShelterImageId;
|
||||
if (stationObject->Flags & STATION_OBJECT_FLAGS::HAS_SECONDARY_COLOUR)
|
||||
{
|
||||
baseImageId |= IMAGE_TYPE_REMAP_2_PLUS;
|
||||
}
|
||||
if (stationObject->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
|
||||
{
|
||||
baseImageId |= IMAGE_TYPE_TRANSPARENT;
|
||||
}
|
||||
|
||||
int32_t imageOffset = 0;
|
||||
CoordsXYZ bounds, boundsOffset;
|
||||
CoordsXYZ offset = CoordsXYZ(0, 0, height);
|
||||
|
@ -840,38 +833,21 @@ bool track_paint_util_draw_station_covers_2(
|
|||
break;
|
||||
}
|
||||
|
||||
if (session->TrackColours[SCHEME_MISC] != IMAGE_TYPE_REMAP)
|
||||
{
|
||||
baseImageId &= 0x7FFFF;
|
||||
}
|
||||
|
||||
if (baseImageId <= 0x20)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stationVariant == STATION_VARIANT_TALL)
|
||||
{
|
||||
imageOffset += SPR_STATION_COVER_OFFSET_TALL;
|
||||
}
|
||||
|
||||
if (baseImageId & IMAGE_TYPE_TRANSPARENT)
|
||||
{
|
||||
imageId = (baseImageId & ~IMAGE_TYPE_TRANSPARENT) + imageOffset;
|
||||
PaintAddImageAsParent(session, imageId, offset, bounds, boundsOffset);
|
||||
|
||||
uint32_t edi = session->TrackColours[SCHEME_TRACK] & (0b11111 << 19);
|
||||
|
||||
// weird jump
|
||||
imageId = (baseImageId | edi) + ((1 << 23) | (1 << 24) | (1 << 25)) + imageOffset + 12;
|
||||
PaintAddImageAsChild(
|
||||
session, imageId, static_cast<int8_t>(offset.x), static_cast<int8_t>(offset.y), bounds.x, bounds.y,
|
||||
static_cast<int8_t>(bounds.z), offset.z, boundsOffset.x, boundsOffset.y, boundsOffset.z);
|
||||
return true;
|
||||
}
|
||||
|
||||
imageId = (baseImageId + imageOffset) | session->TrackColours[SCHEME_TRACK];
|
||||
auto imageTemplate = ImageId::FromUInt32(session->TrackColours[SCHEME_TRACK]);
|
||||
auto imageId = imageTemplate.WithIndex(baseImageIndex + imageOffset);
|
||||
PaintAddImageAsParent(session, imageId, offset, bounds, boundsOffset);
|
||||
|
||||
// Glass
|
||||
if (session->TrackColours[SCHEME_MISC] == IMAGE_TYPE_REMAP && (stationObject->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT))
|
||||
{
|
||||
imageId = ImageId(baseImageIndex + imageOffset + 12).WithTransparancy(imageTemplate.GetPrimary());
|
||||
PaintAddImageAsChild(session, imageId, offset, bounds, boundsOffset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -929,69 +929,72 @@ const vehicle_boundbox VehicleBoundboxes[16][224] = {
|
|||
}
|
||||
};
|
||||
|
||||
static void PaintVehicleRiders(
|
||||
paint_session* session, const Vehicle* vehicle, const rct_ride_entry_vehicle* vehicleEntry, uint32_t baseImageId, int32_t z,
|
||||
const vehicle_boundbox& bb)
|
||||
{
|
||||
baseImageId += vehicleEntry->no_vehicle_images;
|
||||
for (auto i = 0; i < 8; i++)
|
||||
{
|
||||
if (vehicle->num_peeps > (i * 2) && vehicleEntry->no_seating_rows > i)
|
||||
{
|
||||
auto offsetImageId = baseImageId;
|
||||
if (i == 0 && (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_RIDER_ANIMATION))
|
||||
{
|
||||
offsetImageId += (vehicleEntry->no_vehicle_images * vehicle->animation_frame);
|
||||
}
|
||||
|
||||
auto peepColour0 = vehicle->peep_tshirt_colours[i * 2];
|
||||
auto peepColour1 = vehicle->peep_tshirt_colours[(i * 2) + 1];
|
||||
auto imageId = ImageId(offsetImageId, peepColour0, peepColour1);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
imageId = ImageId(offsetImageId).WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
PaintAddImageAsChild(
|
||||
session, imageId, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
|
||||
{ bb.offset_x, bb.offset_y, bb.offset_z + z });
|
||||
baseImageId += vehicleEntry->no_vehicle_images;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 6D5214
|
||||
static void vehicle_sprite_paint(
|
||||
paint_session* session, const Vehicle* vehicle, int32_t ebx, int32_t ecx, int32_t z,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
int32_t baseImage_id = ebx;
|
||||
if (vehicleEntry->draw_order >= std::size(VehicleBoundboxes))
|
||||
{
|
||||
return;
|
||||
}
|
||||
vehicle_boundbox bb = VehicleBoundboxes[vehicleEntry->draw_order][ecx];
|
||||
|
||||
const auto& bb = VehicleBoundboxes[vehicleEntry->draw_order][ecx];
|
||||
|
||||
auto baseImageId = static_cast<uint32_t>(ebx);
|
||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES)
|
||||
{
|
||||
baseImage_id += (vehicle->spin_sprite / 8) & 31;
|
||||
baseImageId += (vehicle->spin_sprite / 8) & 31;
|
||||
}
|
||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION)
|
||||
{
|
||||
baseImage_id += vehicle->animation_frame;
|
||||
baseImageId += vehicle->animation_frame;
|
||||
}
|
||||
int32_t image_id = baseImage_id | (vehicle->colours.body_colour << 19) | (vehicle->colours.trim_colour << 24)
|
||||
| IMAGE_TYPE_REMAP_2_PLUS;
|
||||
|
||||
auto imageId = ImageId(baseImageId, vehicle->colours.body_colour, vehicle->colours.trim_colour, vehicle->colours_extended);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
imageId = ImageId(baseImageId).WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
paint_struct* ps = PaintAddImageAsParent(
|
||||
session, image_id, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
|
||||
PaintAddImageAsParent(
|
||||
session, imageId, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
|
||||
{ bb.offset_x, bb.offset_y, bb.offset_z + z });
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
}
|
||||
rct_drawpixelinfo* dpi = &session->DPI;
|
||||
|
||||
auto* dpi = &session->DPI;
|
||||
if (dpi->zoom_level < ZoomLevel{ 2 } && vehicle->num_peeps > 0 && vehicleEntry->no_seating_rows > 0)
|
||||
{
|
||||
baseImage_id += vehicleEntry->no_vehicle_images;
|
||||
for (int32_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (vehicle->num_peeps > (i * 2) && vehicleEntry->no_seating_rows > i)
|
||||
{
|
||||
image_id = baseImage_id
|
||||
| SPRITE_ID_PALETTE_COLOUR_2(
|
||||
vehicle->peep_tshirt_colours[i * 2], vehicle->peep_tshirt_colours[(i * 2) + 1]);
|
||||
if (i == 0 && vehicleEntry->flags & VEHICLE_ENTRY_FLAG_RIDER_ANIMATION)
|
||||
{
|
||||
image_id += (vehicleEntry->no_vehicle_images * vehicle->animation_frame);
|
||||
}
|
||||
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id &= 0x7FFFF;
|
||||
image_id |= CONSTRUCTION_MARKER;
|
||||
}
|
||||
|
||||
PaintAddImageAsChild(
|
||||
session, image_id, 0, 0, bb.length_x, bb.length_y, bb.length_z, z, bb.offset_x, bb.offset_y,
|
||||
bb.offset_z + z);
|
||||
baseImage_id += vehicleEntry->no_vehicle_images;
|
||||
}
|
||||
}
|
||||
PaintVehicleRiders(session, vehicle, vehicleEntry, baseImageId, z, bb);
|
||||
}
|
||||
vehicle_visual_splash_effect(session, z, vehicle, vehicleEntry);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,38 @@ enum
|
|||
SPR_OBSERVATION_TOWER_SEGMENT_TOP = 14988,
|
||||
};
|
||||
|
||||
static uint32_t GetObservationTowerVehicleBaseImageId(
|
||||
const Vehicle* vehicle, const rct_ride_entry_vehicle* vehicleEntry, int32_t imageDirection)
|
||||
{
|
||||
uint32_t result = (vehicle->restraints_position / 64);
|
||||
if (vehicle->restraints_position >= 64)
|
||||
{
|
||||
auto directionOffset = imageDirection / 8;
|
||||
if ((directionOffset == 0) || (directionOffset == 3))
|
||||
{
|
||||
result = vehicleEntry->base_image_id + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
result *= 2;
|
||||
result += vehicleEntry->base_image_id;
|
||||
if (directionOffset == 1)
|
||||
{
|
||||
result += 28;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += 22;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (vehicle->animation_frame * 2) + vehicleEntry->base_image_id + 8;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D6258
|
||||
|
@ -33,53 +65,19 @@ void vehicle_visual_observation_tower(
|
|||
paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const Vehicle* vehicle,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
int32_t image_id;
|
||||
int32_t baseImage_id = (vehicle->restraints_position / 64);
|
||||
if (vehicle->restraints_position >= 64)
|
||||
{
|
||||
auto directionOffset = imageDirection / 8;
|
||||
if ((directionOffset == 0) || (directionOffset == 3))
|
||||
{
|
||||
baseImage_id = vehicleEntry->base_image_id + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseImage_id *= 2;
|
||||
baseImage_id += vehicleEntry->base_image_id;
|
||||
if (directionOffset == 1)
|
||||
{
|
||||
baseImage_id += 28;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseImage_id += 22;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
baseImage_id = (vehicle->animation_frame * 2) + vehicleEntry->base_image_id + 8;
|
||||
}
|
||||
|
||||
image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_3(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
auto baseImageId = GetObservationTowerVehicleBaseImageId(vehicle, vehicleEntry, imageDirection);
|
||||
auto imageId0 = ImageId(
|
||||
baseImageId + 0, vehicle->colours.body_colour, vehicle->colours.trim_colour, vehicle->colours_extended);
|
||||
auto imageId1 = ImageId(
|
||||
baseImageId + 1, vehicle->colours.body_colour, vehicle->colours.trim_colour, vehicle->colours_extended);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
image_id = (image_id & 0x7FFFF) | CONSTRUCTION_MARKER;
|
||||
}
|
||||
paint_struct* ps = PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 2, 2, 41 }, { -11, -11, z + 1 });
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
}
|
||||
|
||||
image_id++;
|
||||
|
||||
ps = PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 16, 16, 41 }, { -5, -5, z + 1 });
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
imageId0 = ImageId(baseImageId + 0).WithRemap(FilterPaletteID::Palette44);
|
||||
imageId1 = ImageId(baseImageId + 1).WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
PaintAddImageAsParent(session, imageId0, { 0, 0, z }, { 2, 2, 41 }, { -11, -11, z + 1 });
|
||||
PaintAddImageAsParent(session, imageId1, { 0, 0, z }, { 16, 16, 41 }, { -5, -5, z + 1 });
|
||||
assert(vehicleEntry->effect_visual == 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,37 @@
|
|||
#include "../Vehicle.h"
|
||||
#include "../VehiclePaint.h"
|
||||
|
||||
#ifndef NO_VEHICLES
|
||||
static uint32_t SubmarineVehicleGetBaseImageId(
|
||||
const Vehicle* vehicle, const rct_ride_entry_vehicle* vehicleEntry, int32_t imageDirection)
|
||||
{
|
||||
uint32_t result = imageDirection;
|
||||
if (vehicle->restraints_position >= 64)
|
||||
{
|
||||
if ((vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION) && !(imageDirection & 3))
|
||||
{
|
||||
result /= 8;
|
||||
result += ((vehicle->restraints_position - 64) / 64) * 4;
|
||||
result *= vehicleEntry->base_num_frames;
|
||||
result += vehicleEntry->restraint_image_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
|
||||
{
|
||||
result /= 2;
|
||||
}
|
||||
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES)
|
||||
{
|
||||
result /= 8;
|
||||
}
|
||||
result *= vehicleEntry->base_num_frames;
|
||||
result += vehicleEntry->base_image_id;
|
||||
result += vehicle->SwingSprite;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D44D5
|
||||
|
@ -25,61 +55,25 @@ void vehicle_visual_submarine(
|
|||
paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const Vehicle* vehicle,
|
||||
const rct_ride_entry_vehicle* vehicleEntry)
|
||||
{
|
||||
auto imageFlags = SPRITE_ID_PALETTE_COLOUR_3(vehicle->colours.body_colour, vehicle->colours.trim_colour);
|
||||
auto baseImageId = SubmarineVehicleGetBaseImageId(vehicle, vehicleEntry, imageDirection);
|
||||
auto imageId0 = ImageId(
|
||||
baseImageId + 0, vehicle->colours.body_colour, vehicle->colours.trim_colour, vehicle->colours_extended);
|
||||
auto imageId1 = ImageId(
|
||||
baseImageId + 1, vehicle->colours.body_colour, vehicle->colours.trim_colour, vehicle->colours_extended);
|
||||
if (vehicle->IsGhost())
|
||||
{
|
||||
imageFlags = CONSTRUCTION_MARKER;
|
||||
imageId0 = ImageId(baseImageId + 0).WithRemap(FilterPaletteID::Palette44);
|
||||
imageId1 = ImageId(baseImageId + 1).WithRemap(FilterPaletteID::Palette44);
|
||||
}
|
||||
|
||||
int32_t baseImage_id = imageDirection;
|
||||
int32_t image_id;
|
||||
if (vehicle->restraints_position >= 64)
|
||||
{
|
||||
if ((vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION) && !(imageDirection & 3))
|
||||
{
|
||||
baseImage_id /= 8;
|
||||
baseImage_id += ((vehicle->restraints_position - 64) / 64) * 4;
|
||||
baseImage_id *= vehicleEntry->base_num_frames;
|
||||
baseImage_id += vehicleEntry->restraint_image_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vehicleEntry->flags & VEHICLE_ENTRY_FLAG_USE_16_ROTATION_FRAMES)
|
||||
{
|
||||
baseImage_id /= 2;
|
||||
}
|
||||
if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_USE_4_ROTATION_FRAMES)
|
||||
{
|
||||
baseImage_id /= 8;
|
||||
}
|
||||
baseImage_id *= vehicleEntry->base_num_frames;
|
||||
baseImage_id += vehicleEntry->base_image_id;
|
||||
baseImage_id += vehicle->SwingSprite;
|
||||
}
|
||||
|
||||
vehicle_boundbox bb = VehicleBoundboxes[vehicleEntry->draw_order][imageDirection / 2];
|
||||
|
||||
image_id = baseImage_id | imageFlags;
|
||||
paint_struct* ps = PaintAddImageAsParent(
|
||||
session, image_id, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
|
||||
const auto& bb = VehicleBoundboxes[vehicleEntry->draw_order][imageDirection / 2];
|
||||
PaintAddImageAsParent(
|
||||
session, imageId0, { 0, 0, z }, { bb.length_x, bb.length_y, bb.length_z },
|
||||
{ bb.offset_x, bb.offset_y, bb.offset_z + z });
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
}
|
||||
|
||||
image_id = (baseImage_id + 1) | imageFlags;
|
||||
ps = PaintAddImageAsParent(
|
||||
session, image_id, { 0, 0, z }, { bb.length_x, bb.length_y, 2 }, { bb.offset_x, bb.offset_y, bb.offset_z + z - 10 });
|
||||
if (ps != nullptr)
|
||||
{
|
||||
ps->tertiary_colour = vehicle->colours_extended;
|
||||
}
|
||||
|
||||
PaintAddImageAsParent(
|
||||
session, imageId1, { 0, 0, z }, { bb.length_x, bb.length_y, 2 }, { bb.offset_x, bb.offset_y, bb.offset_z + z - 10 });
|
||||
assert(vehicleEntry->effect_visual == 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void submarine_ride_paint_track_station(
|
||||
paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height,
|
||||
|
|
|
@ -28,6 +28,9 @@ enum
|
|||
SPR_EDGE_WOOD_BLACK_BASE = 1663,
|
||||
SPR_EDGE_ICE_BASE = 1831,
|
||||
|
||||
SPR_TERRAIN_STAFF = 2618,
|
||||
SPR_TERRAIN_STAFF_SLOPED = 2619,
|
||||
|
||||
SPR_TERRAIN_SELECTION_SQUARE_SIMPLE = 2624, // Used for showing peep spawn
|
||||
SPR_TERRAIN_SELECTION_SQUARE = 2625, // Used to show land owned by park
|
||||
SPR_TERRAIN_SELECTION_DOTTED = 2644, // Used to show construction rights owned by park
|
||||
|
@ -531,6 +534,8 @@ enum
|
|||
SPR_CONSTRUCTION_FOOTPATH_LAND = 5639,
|
||||
SPR_CONSTRUCTION_FOOTPATH_BRIDGE = 5640,
|
||||
|
||||
SPR_HEIGHT_MARKER_BASE = 5769,
|
||||
|
||||
SPR_6410 = 6410,
|
||||
|
||||
SPR_PEEP_PICKUP_COUNT = 12,
|
||||
|
|
|
@ -34,6 +34,13 @@ enum
|
|||
ENTRANCE_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 0),
|
||||
};
|
||||
|
||||
namespace EntranceSequence
|
||||
{
|
||||
constexpr const uint8_t Centre = 0;
|
||||
constexpr const uint8_t Left = 1;
|
||||
constexpr const uint8_t Right = 2;
|
||||
}; // namespace EntranceSequence
|
||||
|
||||
constexpr const uint8_t ParkEntranceHeight = 12 * COORDS_Z_STEP;
|
||||
constexpr const uint8_t RideEntranceHeight = 7 * COORDS_Z_STEP;
|
||||
constexpr const uint8_t RideExitHeight = 5 * COORDS_Z_STEP;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "../actions/SmallSceneryRemoveAction.h"
|
||||
#include "../actions/WallRemoveAction.h"
|
||||
#include "../common.h"
|
||||
#include "../core/String.hpp"
|
||||
#include "../entity/Fountain.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../network/network.h"
|
||||
|
@ -64,6 +65,61 @@ const CoordsXY SceneryQuadrantOffsets[] = {
|
|||
{ 23, 7 },
|
||||
};
|
||||
|
||||
LargeSceneryText::LargeSceneryText(const rct_large_scenery_text& original)
|
||||
{
|
||||
for (size_t i = 0; i < std::size(original.offset); i++)
|
||||
{
|
||||
offset[i].x = original.offset[i].x;
|
||||
offset[i].y = original.offset[i].y;
|
||||
}
|
||||
max_width = original.max_width;
|
||||
flags = original.flags;
|
||||
num_images = original.num_images;
|
||||
for (size_t i = 0; i < std::size(original.glyphs); i++)
|
||||
{
|
||||
glyphs[i] = original.glyphs[i];
|
||||
}
|
||||
}
|
||||
|
||||
const rct_large_scenery_text_glyph* LargeSceneryText::GetGlyph(char32_t codepoint) const
|
||||
{
|
||||
if (codepoint >= std::size(glyphs))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &glyphs[codepoint];
|
||||
}
|
||||
|
||||
const rct_large_scenery_text_glyph& LargeSceneryText::GetGlyph(char32_t codepoint, char32_t defaultCodepoint) const
|
||||
{
|
||||
auto glyph = GetGlyph(codepoint);
|
||||
if (glyph == nullptr)
|
||||
{
|
||||
glyph = GetGlyph(defaultCodepoint);
|
||||
}
|
||||
return *glyph;
|
||||
}
|
||||
|
||||
int32_t LargeSceneryText::MeasureWidth(std::string_view text) const
|
||||
{
|
||||
auto result = 0;
|
||||
for (auto codepoint : CodepointView(text))
|
||||
{
|
||||
result += GetGlyph(codepoint, ' ').width;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t LargeSceneryText::MeasureHeight(std::string_view text) const
|
||||
{
|
||||
auto result = 0;
|
||||
for (auto codepoint : CodepointView(text))
|
||||
{
|
||||
result += GetGlyph(codepoint, ' ').height;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void scenery_update_tile(const CoordsXY& sceneryPos)
|
||||
{
|
||||
TileElement* tileElement;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "TileElement.h"
|
||||
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_1 0x28
|
||||
#define SCENERY_WITHER_AGE_THRESHOLD_2 0x37
|
||||
|
@ -178,22 +179,11 @@ struct LargeSceneryText
|
|||
rct_large_scenery_text_glyph glyphs[256];
|
||||
|
||||
LargeSceneryText() = default;
|
||||
|
||||
explicit LargeSceneryText(const rct_large_scenery_text& original)
|
||||
{
|
||||
for (size_t i = 0; i < std::size(original.offset); i++)
|
||||
{
|
||||
offset[i].x = original.offset[i].x;
|
||||
offset[i].y = original.offset[i].y;
|
||||
}
|
||||
max_width = original.max_width;
|
||||
flags = original.flags;
|
||||
num_images = original.num_images;
|
||||
for (size_t i = 0; i < std::size(original.glyphs); i++)
|
||||
{
|
||||
glyphs[i] = original.glyphs[i];
|
||||
}
|
||||
}
|
||||
explicit LargeSceneryText(const rct_large_scenery_text& original);
|
||||
const rct_large_scenery_text_glyph* GetGlyph(char32_t codepoint) const;
|
||||
const rct_large_scenery_text_glyph& GetGlyph(char32_t codepoint, char32_t defaultCodepoint) const;
|
||||
int32_t MeasureWidth(std::string_view text) const;
|
||||
int32_t MeasureHeight(std::string_view text) const;
|
||||
};
|
||||
|
||||
struct rct_scenery_group_entry
|
||||
|
|
Loading…
Reference in New Issue