1
0
Fork 0

Compare commits

...

14 Commits

Author SHA1 Message Date
Su 0165432e5d
Merge 5e984eec1a into b82ffa3542 2025-07-20 22:00:06 +00:00
Peter Nelson b82ffa3542
Codechange: Decouple glyph map from SpriteFontCache instances. (#14449)
This makes the map independent from the SpriteFontCache instances.
2025-07-20 22:58:43 +01:00
Peter Nelson 8e2df7809b
Codechange: Add distinct type to hold pixel drawing colour. (#14457)
This is used for individual pixels as well as line drawing.
2025-07-20 22:57:55 +01:00
Jonathan G Rennison 821784004d Fix: [Linkgraph] Incorrect NodeID to StationID conversion for EraseFlows 2025-07-20 16:07:11 +02:00
Jonathan G Rennison f0447d59d4 Codechange: Use StationID as StationIDStack Titem type 2025-07-20 16:06:03 +02:00
Jonathan G Rennison cbdd358ae8 Codechange: Allow SmallStack Titem type to be non-structural 2025-07-20 16:06:03 +02:00
Susan 5e984eec1a Cleanup: Deduplicate rewritten code 2025-07-17 08:59:37 +01:00
Susan a48f491f09 Cleanup: CodeQL fixes 2025-07-11 07:54:29 +01:00
Susan 3ef5783bf9 Codechange: Reorder returns 2025-07-11 07:03:03 +01:00
Susan 7f6b5d3103 Codechange: use BridgePiecePillarFlags in more places 2025-07-11 05:31:49 +01:00
Susan 5a1a8adb3f Codechange: Less indentation 2025-07-11 02:29:58 +01:00
Susan 1000875f88 Codechange: use BridgePiecePillarFlags instead of uint8_t 2025-07-10 03:06:34 +01:00
Susan 1f5ae37e2c Codechange: use BridgeSpecCtrlFlags instead of uint8_t 2025-07-09 23:48:28 +01:00
Susan 3be979cc05 Feature: Stations under bridges 2025-07-09 06:14:43 +01:00
71 changed files with 849 additions and 461 deletions

View File

@ -321,19 +321,19 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal); Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
} }
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8_t colour) void Blitter_32bppAnim::SetPixel(void *video, int x, int y, PixelColour colour)
{ {
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour.p);
/* Set the colour in the anim-buffer too, if we are rendering to the screen */ /* Set the colour in the anim-buffer too, if we are rendering to the screen */
if (_screen_disable_anim) return; if (_screen_disable_anim) return;
this->anim_buf[this->ScreenToAnimOffset((uint32_t *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8); this->anim_buf[this->ScreenToAnimOffset((uint32_t *)video) + x + y * this->anim_buf_pitch] = colour.p | (DEFAULT_BRIGHTNESS << 8);
} }
void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{ {
const Colour c = LookupColourInPalette(colour); const Colour c = LookupColourInPalette(colour.p);
if (_screen_disable_anim) { if (_screen_disable_anim) {
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) { this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
@ -341,7 +341,7 @@ void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
}); });
} else { } else {
uint16_t * const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)video); uint16_t * const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)video);
const uint16_t anim_colour = colour | (DEFAULT_BRIGHTNESS << 8); const uint16_t anim_colour = colour.p | (DEFAULT_BRIGHTNESS << 8);
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) { this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = c; *((Colour *)video + x + y * _screen.pitch) = c;
offset_anim_buf[x + y * this->anim_buf_pitch] = anim_colour; offset_anim_buf[x + y * this->anim_buf_pitch] = anim_colour;
@ -349,7 +349,7 @@ void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
} }
} }
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t colour) void Blitter_32bppAnim::DrawRect(void *video, int width, int height, PixelColour colour)
{ {
if (_screen_disable_anim) { if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@ -357,7 +357,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t col
return; return;
} }
Colour colour32 = LookupColourInPalette(colour); Colour colour32 = LookupColourInPalette(colour.p);
uint16_t *anim_line = this->ScreenToAnimOffset((uint32_t *)video) + this->anim_buf; uint16_t *anim_line = this->ScreenToAnimOffset((uint32_t *)video) + this->anim_buf;
do { do {
@ -367,7 +367,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8_t col
for (int i = width; i > 0; i--) { for (int i = width; i > 0; i--) {
*dst = colour32; *dst = colour32;
/* Set the colour in the anim-buffer too */ /* Set the colour in the anim-buffer too */
*anim = colour | (DEFAULT_BRIGHTNESS << 8); *anim = colour.p | (DEFAULT_BRIGHTNESS << 8);
dst++; dst++;
anim++; anim++;
} }

View File

@ -34,9 +34,9 @@ public:
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override; void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override; void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
void SetPixel(void *video, int x, int y, uint8_t colour) override; void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override; void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override; void DrawRect(void *video, int width, int height, PixelColour colour) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override; void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override; void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override; void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override;

View File

@ -18,22 +18,22 @@ void *Blitter_32bppBase::MoveTo(void *video, int x, int y)
return (uint32_t *)video + x + y * _screen.pitch; return (uint32_t *)video + x + y * _screen.pitch;
} }
void Blitter_32bppBase::SetPixel(void *video, int x, int y, uint8_t colour) void Blitter_32bppBase::SetPixel(void *video, int x, int y, PixelColour colour)
{ {
*((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour.p);
} }
void Blitter_32bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) void Blitter_32bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{ {
const Colour c = LookupColourInPalette(colour); const Colour c = LookupColourInPalette(colour.p);
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) { this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = c; *((Colour *)video + x + y * _screen.pitch) = c;
}); });
} }
void Blitter_32bppBase::DrawRect(void *video, int width, int height, uint8_t colour) void Blitter_32bppBase::DrawRect(void *video, int width, int height, PixelColour colour)
{ {
Colour colour32 = LookupColourInPalette(colour); Colour colour32 = LookupColourInPalette(colour.p);
do { do {
Colour *dst = (Colour *)video; Colour *dst = (Colour *)video;

View File

@ -19,9 +19,9 @@ class Blitter_32bppBase : public Blitter {
public: public:
uint8_t GetScreenDepth() override { return 32; } uint8_t GetScreenDepth() override { return 32; }
void *MoveTo(void *video, int x, int y) override; void *MoveTo(void *video, int x, int y) override;
void SetPixel(void *video, int x, int y, uint8_t colour) override; void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override; void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override; void DrawRect(void *video, int width, int height, PixelColour colour) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override; void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override; void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override; void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;

View File

@ -27,7 +27,7 @@ static FBlitter_40bppAnim iFBlitter_40bppAnim;
static const Colour _black_colour(0, 0, 0); static const Colour _black_colour(0, 0, 0);
void Blitter_40bppAnim::SetPixel(void *video, int x, int y, uint8_t colour) void Blitter_40bppAnim::SetPixel(void *video, int x, int y, PixelColour colour)
{ {
if (_screen_disable_anim) { if (_screen_disable_anim) {
Blitter_32bppOptimized::SetPixel(video, x, y, colour); Blitter_32bppOptimized::SetPixel(video, x, y, colour);
@ -35,11 +35,11 @@ void Blitter_40bppAnim::SetPixel(void *video, int x, int y, uint8_t colour)
size_t y_offset = static_cast<size_t>(y) * _screen.pitch; size_t y_offset = static_cast<size_t>(y) * _screen.pitch;
*((Colour *)video + x + y_offset) = _black_colour; *((Colour *)video + x + y_offset) = _black_colour;
VideoDriver::GetInstance()->GetAnimBuffer()[((uint32_t *)video - (uint32_t *)_screen.dst_ptr) + x + y_offset] = colour; VideoDriver::GetInstance()->GetAnimBuffer()[((uint32_t *)video - (uint32_t *)_screen.dst_ptr) + x + y_offset] = colour.p;
} }
} }
void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t colour) void Blitter_40bppAnim::DrawRect(void *video, int width, int height, PixelColour colour)
{ {
if (_screen_disable_anim) { if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@ -56,7 +56,7 @@ void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t col
for (int i = width; i > 0; i--) { for (int i = width; i > 0; i--) {
*dst = _black_colour; *dst = _black_colour;
*anim = colour; *anim = colour.p;
dst++; dst++;
anim++; anim++;
} }
@ -65,7 +65,7 @@ void Blitter_40bppAnim::DrawRect(void *video, int width, int height, uint8_t col
} while (--height); } while (--height);
} }
void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{ {
if (_screen_disable_anim) { if (_screen_disable_anim) {
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
@ -78,7 +78,7 @@ void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) { this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) {
*((Colour *)video + x + y * _screen.pitch) = _black_colour; *((Colour *)video + x + y * _screen.pitch) = _black_colour;
*(anim + x + y * _screen.pitch) = colour; *(anim + x + y * _screen.pitch) = colour.p;
}); });
} }

View File

@ -18,9 +18,9 @@
class Blitter_40bppAnim : public Blitter_32bppOptimized { class Blitter_40bppAnim : public Blitter_32bppOptimized {
public: public:
void SetPixel(void *video, int x, int y, uint8_t colour) override; void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override; void DrawRect(void *video, int width, int height, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override; void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override; void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override; void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override; void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;

View File

@ -29,23 +29,23 @@ void *Blitter_8bppBase::MoveTo(void *video, int x, int y)
return (uint8_t *)video + x + y * _screen.pitch; return (uint8_t *)video + x + y * _screen.pitch;
} }
void Blitter_8bppBase::SetPixel(void *video, int x, int y, uint8_t colour) void Blitter_8bppBase::SetPixel(void *video, int x, int y, PixelColour colour)
{ {
*((uint8_t *)video + x + y * _screen.pitch) = colour; *((uint8_t *)video + x + y * _screen.pitch) = colour.p;
} }
void Blitter_8bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) void Blitter_8bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash)
{ {
this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) { this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) {
*((uint8_t *)video + x + y * _screen.pitch) = colour; *((uint8_t *)video + x + y * _screen.pitch) = colour.p;
}); });
} }
void Blitter_8bppBase::DrawRect(void *video, int width, int height, uint8_t colour) void Blitter_8bppBase::DrawRect(void *video, int width, int height, PixelColour colour)
{ {
std::byte *p = static_cast<std::byte *>(video); std::byte *p = static_cast<std::byte *>(video);
do { do {
std::fill_n(p, width, static_cast<std::byte>(colour)); std::fill_n(p, width, static_cast<std::byte>(colour.p));
p += _screen.pitch; p += _screen.pitch;
} while (--height); } while (--height);
} }

View File

@ -18,9 +18,9 @@ public:
uint8_t GetScreenDepth() override { return 8; } uint8_t GetScreenDepth() override { return 8; }
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override; void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
void *MoveTo(void *video, int x, int y) override; void *MoveTo(void *video, int x, int y) override;
void SetPixel(void *video, int x, int y, uint8_t colour) override; void SetPixel(void *video, int x, int y, PixelColour colour) override;
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override; void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash) override;
void DrawRect(void *video, int width, int height, uint8_t colour) override; void DrawRect(void *video, int width, int height, PixelColour colour) override;
void CopyFromBuffer(void *video, const void *src, int width, int height) override; void CopyFromBuffer(void *video, const void *src, int width, int height) override;
void CopyToBuffer(const void *video, void *dst, int width, int height) override; void CopyToBuffer(const void *video, void *dst, int width, int height) override;
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override; void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;

View File

@ -95,18 +95,18 @@ public:
* @param video The destination pointer (video-buffer). * @param video The destination pointer (video-buffer).
* @param x The x position within video-buffer. * @param x The x position within video-buffer.
* @param y The y position within video-buffer. * @param y The y position within video-buffer.
* @param colour A 8bpp mapping colour. * @param colour A pixel colour.
*/ */
virtual void SetPixel(void *video, int x, int y, uint8_t colour) = 0; virtual void SetPixel(void *video, int x, int y, PixelColour colour) = 0;
/** /**
* Make a single horizontal line in a single colour on the video-buffer. * Make a single horizontal line in a single colour on the video-buffer.
* @param video The destination pointer (video-buffer). * @param video The destination pointer (video-buffer).
* @param width The length of the line. * @param width The length of the line.
* @param height The height of the line. * @param height The height of the line.
* @param colour A 8bpp mapping colour. * @param colour A pixel colour.
*/ */
virtual void DrawRect(void *video, int width, int height, uint8_t colour) = 0; virtual void DrawRect(void *video, int width, int height, PixelColour colour) = 0;
/** /**
* Draw a line with a given colour. * Draw a line with a given colour.
@ -117,11 +117,11 @@ public:
* @param y2 The y coordinate to where the lines goes. * @param y2 The y coordinate to where the lines goes.
* @param screen_width The width of the screen you are drawing in (to avoid buffer-overflows). * @param screen_width The width of the screen you are drawing in (to avoid buffer-overflows).
* @param screen_height The height of the screen you are drawing in (to avoid buffer-overflows). * @param screen_height The height of the screen you are drawing in (to avoid buffer-overflows).
* @param colour A 8bpp mapping colour. * @param colour A pixel colour.
* @param width Line width. * @param width Line width.
* @param dash Length of dashes for dashed lines. 0 means solid line. * @param dash Length of dashes for dashed lines. 0 means solid line.
*/ */
virtual void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash = 0) = 0; virtual void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash = 0) = 0;
/** /**
* Copy from a buffer to the screen. * Copy from a buffer to the screen.

View File

@ -20,9 +20,9 @@ public:
void DrawColourMappingRect(void *, int, int, PaletteID) override {}; void DrawColourMappingRect(void *, int, int, PaletteID) override {};
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override; Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
void *MoveTo(void *, int, int) override { return nullptr; }; void *MoveTo(void *, int, int) override { return nullptr; };
void SetPixel(void *, int, int, uint8_t) override {}; void SetPixel(void *, int, int, PixelColour) override {};
void DrawRect(void *, int, int, uint8_t) override {}; void DrawRect(void *, int, int, PixelColour) override {};
void DrawLine(void *, int, int, int, int, int, int, uint8_t, int, int) override {}; void DrawLine(void *, int, int, int, int, int, int, PixelColour, int, int) override {};
void CopyFromBuffer(void *, const void *, int, int) override {}; void CopyFromBuffer(void *, const void *, int, int) override {};
void CopyToBuffer(const void *, void *, int, int) override {}; void CopyToBuffer(const void *, void *, int, int) override {};
void CopyImageToBuffer(const void *, void *, int, int, int) override {}; void CopyImageToBuffer(const void *, void *, int, int, int) override {};

View File

@ -60,8 +60,8 @@ public:
void DrawWidget(const Rect &r, WidgetID) const override void DrawWidget(const Rect &r, WidgetID) const override
{ {
GfxFillRect(r.left, r.top, r.right, r.bottom, 4, FILLRECT_OPAQUE); GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{4}, FILLRECT_OPAQUE);
GfxFillRect(r.left, r.top, r.right, r.bottom, 0, FILLRECT_CHECKER); GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{0}, FILLRECT_CHECKER);
} }
}; };
@ -385,10 +385,10 @@ bool HandleBootstrap()
/* Initialise the palette. The biggest step is 'faking' some recolour sprites. /* Initialise the palette. The biggest step is 'faking' some recolour sprites.
* This way the mauve and gray colours work and we can show the user interface. */ * This way the mauve and gray colours work and we can show the user interface. */
GfxInitPalettes(); GfxInitPalettes();
static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 }; static const uint8_t offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) { for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) {
for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) { for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) {
SetColourGradient(i, j, offsets[i] + j); SetColourGradient(i, j, PixelColour(offsets[i] + j));
} }
} }

View File

@ -37,6 +37,30 @@ constexpr uint SPRITES_PER_BRIDGE_PIECE = 32; ///< Number of sprites there are p
typedef uint BridgeType; ///< Bridge spec number. typedef uint BridgeType; ///< Bridge spec number.
/**
* Actions that can be performed when the vehicle enters the depot.
*/
enum class BridgePiecePillarFlag : uint8_t {
BPPF_CORNER_W = 1 << 0,
BPPF_CORNER_S = 1 << 1,
BPPF_CORNER_E = 1 << 2,
BPPF_CORNER_N = 1 << 3,
BPPF_ALL_CORNERS = 0xF,
BPPF_EDGE_NE = 1 << 4,
BPPF_EDGE_SE = 1 << 5,
BPPF_EDGE_SW = 1 << 6,
BPPF_EDGE_NW = 1 << 7,
};
using BridgePiecePillarFlags = EnumBitSet<BridgePiecePillarFlag, uint8_t>;
enum class BridgeSpecCtrlFlag : uint8_t{
BSCF_CUSTOM_PILLAR_FLAGS,
BSCF_INVALID_PILLAR_FLAGS,
BSCF_NOT_AVAILABLE_TOWN,
BSCF_NOT_AVAILABLE_AI_GS,
};
using BridgeSpecCtrlFlags = EnumBitSet<BridgeSpecCtrlFlag, uint8_t>;
/** /**
* Struct containing information about a single bridge type * Struct containing information about a single bridge type
*/ */
@ -52,6 +76,8 @@ struct BridgeSpec {
StringID transport_name[2]; ///< description of the bridge, when built for road or rail StringID transport_name[2]; ///< description of the bridge, when built for road or rail
std::vector<std::vector<PalSpriteID>> sprite_table; ///< table of sprites for drawing the bridge std::vector<std::vector<PalSpriteID>> sprite_table; ///< table of sprites for drawing the bridge
uint8_t flags; ///< bit 0 set: disable drawing of far pillars. uint8_t flags; ///< bit 0 set: disable drawing of far pillars.
BridgeSpecCtrlFlags ctrl_flags; ///< control flags
std::array<BridgePiecePillarFlags, 12> pillar_flags; ///< bridge pillar flags: 6 x pairs of x and y flags
}; };
extern BridgeSpec _bridge[MAX_BRIDGES]; extern BridgeSpec _bridge[MAX_BRIDGES];
@ -75,6 +101,15 @@ void DrawBridgeMiddle(const TileInfo *ti);
CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlags flags = {}); CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlags flags = {});
int CalcBridgeLenCostFactor(int x); int CalcBridgeLenCostFactor(int x);
BridgePiecePillarFlags GetBridgeTilePillarFlags(TileIndex tile, TileIndex northern_bridge_end, TileIndex southern_bridge_end, BridgeType bridge_type, TransportType bridge_transport_type);
struct BridgePieceDebugInfo {
BridgePieces piece;
BridgePiecePillarFlags pillar_flags;
uint pillar_index;
};
BridgePieceDebugInfo GetBridgePieceDebugInfo(TileIndex tile);
void ResetBridges(); void ResetBridges();
#endif /* BRIDGE_H */ #endif /* BRIDGE_H */

View File

@ -382,6 +382,8 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
StringID errmsg = INVALID_STRING_ID; StringID errmsg = INVALID_STRING_ID;
CommandCost ret = Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()) | DoCommandFlag::QueryCost, end, start, transport_type, 0, road_rail_type); CommandCost ret = Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()) | DoCommandFlag::QueryCost, end, start, transport_type, 0, road_rail_type);
const bool query_per_bridge_type = ret.Failed() && (ret.GetErrorMessage() == STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION || ret.GetErrorMessage() == STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION);
GUIBridgeList bl; GUIBridgeList bl;
if (ret.Failed()) { if (ret.Failed()) {
errmsg = ret.GetErrorMessage(); errmsg = ret.GetErrorMessage();
@ -415,11 +417,13 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
} }
bool any_available = false; bool any_available = false;
StringID type_errmsg = INVALID_STRING_ID;
CommandCost type_check; CommandCost type_check;
/* loop for all bridgetypes */ /* loop for all bridgetypes */
for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) { for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
type_check = CheckBridgeAvailability(brd_type, bridge_len); type_check = CheckBridgeAvailability(brd_type, bridge_len);
if (type_check.Succeeded()) { if (type_check.Succeeded()) {
if (query_per_bridge_type && Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()) | DoCommandFlag::QueryCost, end, start, transport_type, brd_type, road_rail_type).Failed()) continue;
/* bridge is accepted, add to list */ /* bridge is accepted, add to list */
BuildBridgeData &item = bl.emplace_back(); BuildBridgeData &item = bl.emplace_back();
item.index = brd_type; item.index = brd_type;
@ -428,10 +432,12 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
* bridge itself (not computed with DoCommandFlag::QueryCost) */ * bridge itself (not computed with DoCommandFlag::QueryCost) */
item.cost = ret.GetCost() + (((int64_t)tot_bridgedata_len * _price[PR_BUILD_BRIDGE] * item.spec->price) >> 8) + infra_cost; item.cost = ret.GetCost() + (((int64_t)tot_bridgedata_len * _price[PR_BUILD_BRIDGE] * item.spec->price) >> 8) + infra_cost;
any_available = true; any_available = true;
} else if (type_check.GetErrorMessage() != INVALID_STRING_ID && !query_per_bridge_type) {
type_errmsg = type_check.GetErrorMessage();
} }
} }
/* give error cause if no bridges available here*/ /* give error cause if no bridges available here*/
if (!any_available) if (!any_available && type_errmsg != INVALID_STRING_ID) errmsg = type_errmsg;
{ {
errmsg = type_check.GetErrorMessage(); errmsg = type_check.GetErrorMessage();
} }

View File

@ -956,7 +956,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right; int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
int sprite_width = sprite_left + sprite_right; int sprite_width = sprite_left + sprite_right;
int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width); int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width);
int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); PixelColour linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
auto badge_column_widths = badge_classes.GetColumnWidths(); auto badge_column_widths = badge_classes.GetColumnWidths();

View File

@ -410,7 +410,7 @@ void VehicleCargoList::AgeCargo()
return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP; return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
} else if (cargo_next == current_station) { } else if (cargo_next == current_station) {
return MTA_DELIVER; return MTA_DELIVER;
} else if (next_station.Contains(cargo_next.base())) { } else if (next_station.Contains(cargo_next)) {
return MTA_KEEP; return MTA_KEEP;
} else { } else {
return MTA_TRANSFER; return MTA_TRANSFER;
@ -470,7 +470,7 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
new_shares.ChangeShare(current_station, INT_MIN); new_shares.ChangeShare(current_station, INT_MIN);
StationIDStack excluded = next_station; StationIDStack excluded = next_station;
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) { while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
new_shares.ChangeShare(StationID{excluded.Pop()}, INT_MIN); new_shares.ChangeShare(excluded.Pop(), INT_MIN);
} }
if (new_shares.GetShares()->empty()) { if (new_shares.GetShares()->empty()) {
cargo_next = StationID::Invalid(); cargo_next = StationID::Invalid();
@ -743,7 +743,7 @@ uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool incl
{ {
uint max_move = action.MaxMove(); uint max_move = action.MaxMove();
while (!next.IsEmpty()) { while (!next.IsEmpty()) {
this->ShiftCargo(action, StationID{next.Pop()}); this->ShiftCargo(action, next.Pop());
if (action.MaxMove() == 0) break; if (action.MaxMove() == 0) break;
} }
if (include_invalid && action.MaxMove() > 0) { if (include_invalid && action.MaxMove() > 0) {
@ -853,7 +853,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac
*/ */
uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge) uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
{ {
return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid.base(), false); return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false);
} }
/* /*

View File

@ -555,7 +555,7 @@ public:
inline bool HasCargoFor(StationIDStack next) const inline bool HasCargoFor(StationIDStack next) const
{ {
while (!next.IsEmpty()) { while (!next.IsEmpty()) {
if (this->packets.find(StationID{next.Pop()}) != this->packets.end()) return true; if (this->packets.find(next.Pop()) != this->packets.end()) return true;
} }
/* Packets for StationID::Invalid() can go anywhere. */ /* Packets for StationID::Invalid() can go anywhere. */
return this->packets.find(StationID::Invalid()) != this->packets.end(); return this->packets.find(StationID::Invalid()) != this->packets.end();

View File

@ -74,8 +74,8 @@ static const uint TOWN_PRODUCTION_DIVISOR = 256;
struct CargoSpec { struct CargoSpec {
CargoLabel label; ///< Unique label of the cargo type. CargoLabel label; ///< Unique label of the cargo type.
uint8_t bitnum = INVALID_CARGO_BITNUM; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec. uint8_t bitnum = INVALID_CARGO_BITNUM; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec.
uint8_t legend_colour; PixelColour legend_colour;
uint8_t rating_colour; PixelColour rating_colour;
uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg). uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
uint16_t multiplier = 0x100; ///< Capacity multiplier for vehicles. (8 fractional bits) uint16_t multiplier = 0x100; ///< Capacity multiplier for vehicles. (8 fractional bits)
CargoClasses classes; ///< Classes of this cargo type. @see CargoClass CargoClasses classes; ///< Classes of this cargo type. @see CargoClass

View File

@ -152,8 +152,8 @@ void SetLocalCompany(CompanyID new_company)
*/ */
TextColour GetDrawStringCompanyColour(CompanyID company) TextColour GetDrawStringCompanyColour(CompanyID company)
{ {
if (!Company::IsValidID(company)) return (TextColour)GetColourGradient(COLOUR_WHITE, SHADE_NORMAL) | TC_IS_PALETTE_COLOUR; if (!Company::IsValidID(company)) return GetColourGradient(COLOUR_WHITE, SHADE_NORMAL).ToTextColour();
return (TextColour)GetColourGradient(_company_colours[company], SHADE_NORMAL) | TC_IS_PALETTE_COLOUR; return GetColourGradient(_company_colours[company], SHADE_NORMAL).ToTextColour();
} }
/** /**

View File

@ -544,7 +544,7 @@ bool IsValidConsoleColour(TextColour c)
* colour gradient, so it must be one of those. */ * colour gradient, so it must be one of those. */
c &= ~TC_IS_PALETTE_COLOUR; c &= ~TC_IS_PALETTE_COLOUR;
for (Colours i = COLOUR_BEGIN; i < COLOUR_END; i++) { for (Colours i = COLOUR_BEGIN; i < COLOUR_END; i++) {
if (GetColourGradient(i, SHADE_NORMAL) == c) return true; if (GetColourGradient(i, SHADE_NORMAL).p == c) return true;
} }
return false; return false;

View File

@ -113,13 +113,14 @@ struct SmallStackItem {
* index types of the same length. * index types of the same length.
* @tparam Titem Value type to be used. * @tparam Titem Value type to be used.
* @tparam Tindex Index type to use for the pool. * @tparam Tindex Index type to use for the pool.
* @tparam Tinvalid Invalid item to keep at the bottom of each stack. * @tparam Tinvalid_value Value to construct invalid item to keep at the bottom of each stack.
* @tparam Tgrowth_step Growth step for pool. * @tparam Tgrowth_step Growth step for pool.
* @tparam Tmax_size Maximum size for pool. * @tparam Tmax_size Maximum size for pool.
*/ */
template <typename Titem, typename Tindex, Titem Tinvalid, Tindex Tgrowth_step, Tindex Tmax_size> template <typename Titem, typename Tindex, auto Tinvalid_value, Tindex Tgrowth_step, Tindex Tmax_size>
class SmallStack : public SmallStackItem<Titem, Tindex> { class SmallStack : public SmallStackItem<Titem, Tindex> {
public: public:
static constexpr Titem Tinvalid{Tinvalid_value};
typedef SmallStackItem<Titem, Tindex> Item; typedef SmallStackItem<Titem, Tindex> Item;

View File

@ -413,7 +413,7 @@ struct DepotWindow : Window {
*/ */
if (this->type == VEH_TRAIN && _consistent_train_width != 0) { if (this->type == VEH_TRAIN && _consistent_train_width != 0) {
int w = ScaleSpriteTrad(2 * _consistent_train_width); int w = ScaleSpriteTrad(2 * _consistent_train_width);
int col = GetColourGradient(wid->colour, SHADE_NORMAL); PixelColour col = GetColourGradient(wid->colour, SHADE_NORMAL);
Rect image = ir.Indent(this->header_width, rtl).Indent(this->count_width, !rtl); Rect image = ir.Indent(this->header_width, rtl).Indent(this->count_width, !rtl);
int first_line = w + (-this->hscroll->GetPosition()) % w; int first_line = w + (-this->hscroll->GetPosition()) % w;
if (rtl) { if (rtl) {

View File

@ -37,8 +37,8 @@ public:
void Draw(const Rect &full, const Rect &, bool, int, Colours bg_colour) const override void Draw(const Rect &full, const Rect &, bool, int, Colours bg_colour) const override
{ {
uint8_t c1 = GetColourGradient(bg_colour, SHADE_DARK); PixelColour c1 = GetColourGradient(bg_colour, SHADE_DARK);
uint8_t c2 = GetColourGradient(bg_colour, SHADE_LIGHTEST); PixelColour c2 = GetColourGradient(bg_colour, SHADE_LIGHTEST);
int mid = CentreBounds(full.top, full.bottom, 0); int mid = CentreBounds(full.top, full.bottom, 0);
GfxFillRect(full.left, mid - WidgetDimensions::scaled.bevel.bottom, full.right, mid - 1, c1); GfxFillRect(full.left, mid - WidgetDimensions::scaled.bevel.bottom, full.right, mid - 1, c1);

View File

@ -70,16 +70,6 @@ public:
*/ */
virtual int GetFontSize() const { return this->height; } virtual int GetFontSize() const { return this->height; }
/**
* Map a SpriteID to the key
* @param key The key to map to.
* @param sprite The sprite that is being mapped.
*/
virtual void SetUnicodeGlyph(char32_t key, SpriteID sprite) = 0;
/** Initialize the glyph map */
virtual void InitializeUnicodeGlyphMap() = 0;
/** Clear the font cache. */ /** Clear the font cache. */
virtual void ClearFontCache() = 0; virtual void ClearFontCache() = 0;
@ -153,20 +143,6 @@ public:
virtual bool IsBuiltInFont() = 0; virtual bool IsBuiltInFont() = 0;
}; };
/** Map a SpriteID to the font size and key */
inline void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite)
{
FontCache::Get(size)->SetUnicodeGlyph(key, sprite);
}
/** Initialize the glyph map */
inline void InitializeUnicodeGlyphMap()
{
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
FontCache::Get(fs)->InitializeUnicodeGlyphMap();
}
}
inline void ClearFontCache(FontSizes fontsizes) inline void ClearFontCache(FontSizes fontsizes)
{ {
for (FontSize fs : fontsizes) { for (FontSize fs : fontsizes) {
@ -237,4 +213,8 @@ void UninitFontCache();
bool GetFontAAState(); bool GetFontAAState();
void SetFont(FontSize fontsize, const std::string &font, uint size); void SetFont(FontSize fontsize, const std::string &font, uint size);
/* Implemented in spritefontcache.cpp */
void InitializeUnicodeGlyphMap();
void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite);
#endif /* FONTCACHE_H */ #endif /* FONTCACHE_H */

View File

@ -10,6 +10,7 @@
#include "../stdafx.h" #include "../stdafx.h"
#include "../fontcache.h" #include "../fontcache.h"
#include "../gfx_layout.h" #include "../gfx_layout.h"
#include "../string_func.h"
#include "../zoom_func.h" #include "../zoom_func.h"
#include "spritefontcache.h" #include "spritefontcache.h"
@ -31,41 +32,43 @@ static int ScaleFontTrad(int value)
return UnScaleByZoom(value * ZOOM_BASE, _font_zoom); return UnScaleByZoom(value * ZOOM_BASE, _font_zoom);
} }
/** static std::array<std::unordered_map<char32_t, SpriteID>, FS_END> _char_maps{}; ///< Glyph map for each font size.
* Create a new sprite font cache.
* @param fs The font size to create the cache for.
*/
SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs)
{
this->InitializeUnicodeGlyphMap();
this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs));
this->ascender = (this->height - ScaleFontTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2;
}
/** /**
* Get SpriteID associated with a character. * Get SpriteID associated with a character.
* @param key Character to find. * @param key Character to find.
* @return SpriteID for character, or 0 if not present. * @return SpriteID for character, or 0 if not present.
*/ */
SpriteID SpriteFontCache::GetUnicodeGlyph(char32_t key) static SpriteID GetUnicodeGlyph(FontSize fs, char32_t key)
{ {
const auto found = this->char_map.find(key); auto found = _char_maps[fs].find(key);
if (found == std::end(this->char_map)) return 0; if (found != std::end(_char_maps[fs])) return found->second;
return found->second; return 0;
} }
void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite) /**
* Set the SpriteID for a unicode character.
* @param fs Font size to set.
* @param key Unicode character to set.
* @param sprite SpriteID of character.
*/
void SetUnicodeGlyph(FontSize fs, char32_t key, SpriteID sprite)
{ {
this->char_map[key] = sprite; _char_maps[fs][key] = sprite;
} }
void SpriteFontCache::InitializeUnicodeGlyphMap() /**
* Initialize the glyph map for a font size.
* This populates the glyph map with the baseset font sprites.
* @param fs Font size to initialize.
*/
void InitializeUnicodeGlyphMap(FontSize fs)
{ {
/* Clear out existing glyph map if it exists */ /* Clear out existing glyph map if it exists */
this->char_map.clear(); _char_maps[fs].clear();
SpriteID base; SpriteID base;
switch (this->fs) { switch (fs) {
default: NOT_REACHED(); default: NOT_REACHED();
case FS_MONO: // Use normal as default for mono spaced font case FS_MONO: // Use normal as default for mono spaced font
case FS_NORMAL: base = SPR_ASCII_SPACE; break; case FS_NORMAL: base = SPR_ASCII_SPACE; break;
@ -76,24 +79,45 @@ void SpriteFontCache::InitializeUnicodeGlyphMap()
for (uint i = ASCII_LETTERSTART; i < 256; i++) { for (uint i = ASCII_LETTERSTART; i < 256; i++) {
SpriteID sprite = base + i - ASCII_LETTERSTART; SpriteID sprite = base + i - ASCII_LETTERSTART;
if (!SpriteExists(sprite)) continue; if (!SpriteExists(sprite)) continue;
this->SetUnicodeGlyph(i, sprite); SetUnicodeGlyph(fs, i, sprite);
this->SetUnicodeGlyph(i + SCC_SPRITE_START, sprite); SetUnicodeGlyph(fs, i + SCC_SPRITE_START, sprite);
} }
/* Modify map to move non-standard glyphs to a better unicode codepoint. */
for (const auto &unicode_map : _default_unicode_map) { for (const auto &unicode_map : _default_unicode_map) {
uint8_t key = unicode_map.key; uint8_t key = unicode_map.key;
if (key == CLRA) { if (key == CLRA) {
/* Clear the glyph. This happens if the glyph at this code point /* Clear the glyph. This happens if the glyph at this code point
* is non-standard and should be accessed by an SCC_xxx enum * is non-standard and should be accessed by an SCC_xxx enum
* entry only. */ * entry only. */
this->SetUnicodeGlyph(unicode_map.code, 0); SetUnicodeGlyph(fs, unicode_map.code, 0);
} else { } else {
SpriteID sprite = base + key - ASCII_LETTERSTART; SpriteID sprite = base + key - ASCII_LETTERSTART;
this->SetUnicodeGlyph(unicode_map.code, sprite); SetUnicodeGlyph(fs, unicode_map.code, sprite);
} }
} }
} }
/**
* Initialize the glyph map.
*/
void InitializeUnicodeGlyphMap()
{
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
InitializeUnicodeGlyphMap(fs);
}
}
/**
* Create a new sprite font cache.
* @param fs The font size to create the cache for.
*/
SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs)
{
this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs));
this->ascender = (this->height - ScaleFontTrad(FontCache::GetDefaultFontHeight(this->fs))) / 2;
}
void SpriteFontCache::ClearFontCache() void SpriteFontCache::ClearFontCache()
{ {
Layouter::ResetFontCache(this->fs); Layouter::ResetFontCache(this->fs);
@ -104,21 +128,21 @@ void SpriteFontCache::ClearFontCache()
const Sprite *SpriteFontCache::GetGlyph(GlyphID key) const Sprite *SpriteFontCache::GetGlyph(GlyphID key)
{ {
SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH); SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); if (sprite == 0) sprite = GetUnicodeGlyph(this->fs, '?');
return GetSprite(sprite, SpriteType::Font); return GetSprite(sprite, SpriteType::Font);
} }
uint SpriteFontCache::GetGlyphWidth(GlyphID key) uint SpriteFontCache::GetGlyphWidth(GlyphID key)
{ {
SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH); SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
if (sprite == 0) sprite = this->GetUnicodeGlyph('?'); if (sprite == 0) sprite = GetUnicodeGlyph(this->fs, '?');
return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0; return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0;
} }
GlyphID SpriteFontCache::MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback) GlyphID SpriteFontCache::MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback)
{ {
assert(IsPrintable(key)); assert(IsPrintable(key));
SpriteID sprite = this->GetUnicodeGlyph(key); SpriteID sprite = GetUnicodeGlyph(this->fs, key);
if (sprite == 0) return 0; if (sprite == 0) return 0;
return SPRITE_GLYPH | sprite; return SPRITE_GLYPH | sprite;
} }

View File

@ -10,15 +10,12 @@
#ifndef SPRITEFONTCACHE_H #ifndef SPRITEFONTCACHE_H
#define SPRITEFONTCACHE_H #define SPRITEFONTCACHE_H
#include "../string_func.h"
#include "../fontcache.h" #include "../fontcache.h"
/** Font cache for fonts that are based on a freetype font. */ /** Font cache for fonts that are based on a freetype font. */
class SpriteFontCache : public FontCache { class SpriteFontCache : public FontCache {
public: public:
SpriteFontCache(FontSize fs); SpriteFontCache(FontSize fs);
void SetUnicodeGlyph(char32_t key, SpriteID sprite) override;
void InitializeUnicodeGlyphMap() override;
void ClearFontCache() override; void ClearFontCache() override;
const Sprite *GetGlyph(GlyphID key) override; const Sprite *GetGlyph(GlyphID key) override;
uint GetGlyphWidth(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override;
@ -26,10 +23,6 @@ public:
GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override; GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override;
std::string GetFontName() override { return "sprite"; } std::string GetFontName() override { return "sprite"; }
bool IsBuiltInFont() override { return true; } bool IsBuiltInFont() override { return true; }
private:
std::unordered_map<char32_t, SpriteID> char_map{}; ///< Mapping of characters to sprite IDs.
SpriteID GetUnicodeGlyph(char32_t key);
}; };
#endif /* SPRITEFONTCACHE_H */ #endif /* SPRITEFONTCACHE_H */

View File

@ -46,8 +46,6 @@ public:
TrueTypeFontCache(FontSize fs, int pixels); TrueTypeFontCache(FontSize fs, int pixels);
virtual ~TrueTypeFontCache(); virtual ~TrueTypeFontCache();
int GetFontSize() const override { return this->used_size; } int GetFontSize() const override { return this->used_size; }
void SetUnicodeGlyph(char32_t key, SpriteID sprite) override { this->parent->SetUnicodeGlyph(key, sprite); }
void InitializeUnicodeGlyphMap() override { this->parent->InitializeUnicodeGlyphMap(); }
const Sprite *GetGlyph(GlyphID key) override; const Sprite *GetGlyph(GlyphID key) override;
void ClearFontCache() override; void ClearFontCache() override;
uint GetGlyphWidth(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override;

View File

@ -867,9 +867,9 @@ struct FrametimeGraphWindow : Window {
const int x_max = r.right; const int x_max = r.right;
const int y_zero = r.top + (int)this->graph_size.height; const int y_zero = r.top + (int)this->graph_size.height;
const int y_max = r.top; const int y_max = r.top;
const int c_grid = PC_DARK_GREY; const PixelColour c_grid = PC_DARK_GREY;
const int c_lines = PC_BLACK; const PixelColour c_lines = PC_BLACK;
const int c_peak = PC_DARK_RED; const PixelColour c_peak = PC_DARK_RED;
const TimingMeasurement draw_horz_scale = (TimingMeasurement)this->horizontal_scale * TIMESTAMP_PRECISION / 2; const TimingMeasurement draw_horz_scale = (TimingMeasurement)this->horizontal_scale * TIMESTAMP_PRECISION / 2;
const TimingMeasurement draw_vert_scale = (TimingMeasurement)this->vertical_scale; const TimingMeasurement draw_vert_scale = (TimingMeasurement)this->vertical_scale;
@ -959,7 +959,7 @@ struct FrametimeGraphWindow : Window {
/* If the peak value is significantly larger than the average, mark and label it */ /* If the peak value is significantly larger than the average, mark and label it */
if (points_drawn > 0 && peak_value > TIMESTAMP_PRECISION / 100 && 2 * peak_value > 3 * value_sum / points_drawn) { if (points_drawn > 0 && peak_value > TIMESTAMP_PRECISION / 100 && 2 * peak_value > 3 * value_sum / points_drawn) {
TextColour tc_peak = (TextColour)(TC_IS_PALETTE_COLOUR | c_peak); TextColour tc_peak = c_peak.ToTextColour();
GfxFillRect(peak_point.x - 1, peak_point.y - 1, peak_point.x + 1, peak_point.y + 1, c_peak); GfxFillRect(peak_point.x - 1, peak_point.y - 1, peak_point.x + 1, peak_point.y + 1, c_peak);
uint64_t value = peak_value * 1000 / TIMESTAMP_PRECISION; uint64_t value = peak_value * 1000 / TIMESTAMP_PRECISION;
int label_y = std::max(y_max, peak_point.y - GetCharacterHeight(FS_SMALL)); int label_y = std::max(y_max, peak_point.y - GetCharacterHeight(FS_SMALL));

View File

@ -113,7 +113,7 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
* FILLRECT_CHECKER: Like FILLRECT_OPAQUE, but only draw every second pixel (used to grey out things) * FILLRECT_CHECKER: Like FILLRECT_OPAQUE, but only draw every second pixel (used to grey out things)
* FILLRECT_RECOLOUR: Apply a recolour sprite to every pixel in the rectangle currently on screen * FILLRECT_RECOLOUR: Apply a recolour sprite to every pixel in the rectangle currently on screen
*/ */
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode) void GfxFillRect(int left, int top, int right, int bottom, const std::variant<PixelColour, PaletteID> &colour, FillRectMode mode)
{ {
Blitter *blitter = BlitterFactory::GetCurrentBlitter(); Blitter *blitter = BlitterFactory::GetCurrentBlitter();
const DrawPixelInfo *dpi = _cur_dpi; const DrawPixelInfo *dpi = _cur_dpi;
@ -142,17 +142,18 @@ void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectM
switch (mode) { switch (mode) {
default: // FILLRECT_OPAQUE default: // FILLRECT_OPAQUE
blitter->DrawRect(dst, right, bottom, (uint8_t)colour); blitter->DrawRect(dst, right, bottom, std::get<PixelColour>(colour));
break; break;
case FILLRECT_RECOLOUR: case FILLRECT_RECOLOUR:
blitter->DrawColourMappingRect(dst, right, bottom, GB(colour, 0, PALETTE_WIDTH)); blitter->DrawColourMappingRect(dst, right, bottom, GB(std::get<PaletteID>(colour), 0, PALETTE_WIDTH));
break; break;
case FILLRECT_CHECKER: { case FILLRECT_CHECKER: {
uint8_t bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1; uint8_t bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
PixelColour pc = std::get<PixelColour>(colour);
do { do {
for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, (uint8_t)colour); for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, pc);
dst = blitter->MoveTo(dst, 0, 1); dst = blitter->MoveTo(dst, 0, 1);
} while (--bottom > 0); } while (--bottom > 0);
break; break;
@ -209,7 +210,7 @@ static std::vector<LineSegment> MakePolygonSegments(std::span<const Point> shape
* FILLRECT_CHECKER: Fill every other pixel with the specified colour, in a checkerboard pattern. * FILLRECT_CHECKER: Fill every other pixel with the specified colour, in a checkerboard pattern.
* FILLRECT_RECOLOUR: Apply a recolour sprite to every pixel in the polygon. * FILLRECT_RECOLOUR: Apply a recolour sprite to every pixel in the polygon.
*/ */
void GfxFillPolygon(std::span<const Point> shape, int colour, FillRectMode mode) void GfxFillPolygon(std::span<const Point> shape, const std::variant<PixelColour, PaletteID> &colour, FillRectMode mode)
{ {
Blitter *blitter = BlitterFactory::GetCurrentBlitter(); Blitter *blitter = BlitterFactory::GetCurrentBlitter();
const DrawPixelInfo *dpi = _cur_dpi; const DrawPixelInfo *dpi = _cur_dpi;
@ -278,20 +279,22 @@ void GfxFillPolygon(std::span<const Point> shape, int colour, FillRectMode mode)
void *dst = blitter->MoveTo(dpi->dst_ptr, x1, y); void *dst = blitter->MoveTo(dpi->dst_ptr, x1, y);
switch (mode) { switch (mode) {
default: // FILLRECT_OPAQUE default: // FILLRECT_OPAQUE
blitter->DrawRect(dst, x2 - x1, 1, (uint8_t)colour); blitter->DrawRect(dst, x2 - x1, 1, std::get<PixelColour>(colour));
break; break;
case FILLRECT_RECOLOUR: case FILLRECT_RECOLOUR:
blitter->DrawColourMappingRect(dst, x2 - x1, 1, GB(colour, 0, PALETTE_WIDTH)); blitter->DrawColourMappingRect(dst, x2 - x1, 1, GB(std::get<PaletteID>(colour), 0, PALETTE_WIDTH));
break; break;
case FILLRECT_CHECKER: case FILLRECT_CHECKER: {
/* Fill every other pixel, offset such that the sum of filled pixels' X and Y coordinates is odd. /* Fill every other pixel, offset such that the sum of filled pixels' X and Y coordinates is odd.
* This creates a checkerboard effect. */ * This creates a checkerboard effect. */
PixelColour pc = std::get<PixelColour>(colour);
for (int x = (x1 + y) & 1; x < x2 - x1; x += 2) { for (int x = (x1 + y) & 1; x < x2 - x1; x += 2) {
blitter->SetPixel(dst, x, 0, (uint8_t)colour); blitter->SetPixel(dst, x, 0, pc);
} }
break; break;
} }
} }
}
/* Next line */ /* Next line */
++y; ++y;
@ -312,7 +315,7 @@ void GfxFillPolygon(std::span<const Point> shape, int colour, FillRectMode mode)
* @param width Width of the line. * @param width Width of the line.
* @param dash Length of dashes for dashed lines. 0 means solid line. * @param dash Length of dashes for dashed lines. 0 means solid line.
*/ */
static inline void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash = 0) static inline void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash = 0)
{ {
Blitter *blitter = BlitterFactory::GetCurrentBlitter(); Blitter *blitter = BlitterFactory::GetCurrentBlitter();
@ -385,7 +388,7 @@ static inline bool GfxPreprocessLine(DrawPixelInfo *dpi, int &x, int &y, int &x2
return true; return true;
} }
void GfxDrawLine(int x, int y, int x2, int y2, int colour, int width, int dash) void GfxDrawLine(int x, int y, int x2, int y2, PixelColour colour, int width, int dash)
{ {
DrawPixelInfo *dpi = _cur_dpi; DrawPixelInfo *dpi = _cur_dpi;
if (GfxPreprocessLine(dpi, x, y, x2, y2, width)) { if (GfxPreprocessLine(dpi, x, y, x2, y2, width)) {
@ -393,7 +396,7 @@ void GfxDrawLine(int x, int y, int x2, int y2, int colour, int width, int dash)
} }
} }
void GfxDrawLineUnscaled(int x, int y, int x2, int y2, int colour) void GfxDrawLineUnscaled(int x, int y, int x2, int y2, PixelColour colour)
{ {
DrawPixelInfo *dpi = _cur_dpi; DrawPixelInfo *dpi = _cur_dpi;
if (GfxPreprocessLine(dpi, x, y, x2, y2, 1)) { if (GfxPreprocessLine(dpi, x, y, x2, y2, 1)) {
@ -434,7 +437,7 @@ void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
* ....V. * ....V.
*/ */
static const uint8_t colour = PC_WHITE; static constexpr PixelColour colour = PC_WHITE;
GfxDrawLineUnscaled(x, y, x + dx1, y + dy1, colour); GfxDrawLineUnscaled(x, y, x + dx1, y + dy1, colour);
GfxDrawLineUnscaled(x, y, x + dx2, y + dy2, colour); GfxDrawLineUnscaled(x, y, x + dx2, y + dy2, colour);
@ -455,7 +458,7 @@ void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
* @param width Width of the outline. * @param width Width of the outline.
* @param dash Length of dashes for dashed lines. 0 means solid lines. * @param dash Length of dashes for dashed lines. 0 means solid lines.
*/ */
void DrawRectOutline(const Rect &r, int colour, int width, int dash) void DrawRectOutline(const Rect &r, PixelColour colour, int width, int dash)
{ {
GfxDrawLine(r.left, r.top, r.right, r.top, colour, width, dash); GfxDrawLine(r.left, r.top, r.right, r.top, colour, width, dash);
GfxDrawLine(r.left, r.top, r.left, r.bottom, colour, width, dash); GfxDrawLine(r.left, r.top, r.left, r.bottom, colour, width, dash);
@ -477,7 +480,7 @@ static void SetColourRemap(TextColour colour)
bool raw_colour = (colour & TC_IS_PALETTE_COLOUR) != 0; bool raw_colour = (colour & TC_IS_PALETTE_COLOUR) != 0;
colour &= ~(TC_NO_SHADE | TC_IS_PALETTE_COLOUR | TC_FORCED); colour &= ~(TC_NO_SHADE | TC_IS_PALETTE_COLOUR | TC_FORCED);
_string_colourremap[1] = raw_colour ? (uint8_t)colour : _string_colourmap[colour]; _string_colourremap[1] = raw_colour ? (uint8_t)colour : _string_colourmap[colour].p;
_string_colourremap[2] = no_shade ? 0 : 1; _string_colourremap[2] = no_shade ? 0 : 1;
_colour_remap_ptr = _string_colourremap; _colour_remap_ptr = _string_colourremap;
} }
@ -637,7 +640,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
} }
if (underline) { if (underline) {
GfxFillRect(left, y + h, right, y + h + WidgetDimensions::scaled.bevel.top - 1, _string_colourremap[1]); GfxFillRect(left, y + h, right, y + h + WidgetDimensions::scaled.bevel.top - 1, PixelColour{_string_colourremap[1]});
} }
return (align & SA_HOR_MASK) == SA_RIGHT ? left : right; return (align & SA_HOR_MASK) == SA_RIGHT ? left : right;

View File

@ -103,11 +103,11 @@ bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, s
void DrawCharCentered(char32_t c, const Rect &r, TextColour colour); void DrawCharCentered(char32_t c, const Rect &r, TextColour colour);
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE); void GfxFillRect(int left, int top, int right, int bottom, const std::variant<PixelColour, PaletteID> &colour, FillRectMode mode = FILLRECT_OPAQUE);
void GfxFillPolygon(std::span<const Point> shape, int colour, FillRectMode mode = FILLRECT_OPAQUE); void GfxFillPolygon(std::span<const Point> shape, const std::variant<PixelColour, PaletteID> &colour, FillRectMode mode = FILLRECT_OPAQUE);
void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0); void GfxDrawLine(int left, int top, int right, int bottom, PixelColour colour, int width = 1, int dash = 0);
void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
void DrawRectOutline(const Rect &r, int colour, int width = 1, int dash = 0); void DrawRectOutline(const Rect &r, PixelColour colour, int width = 1, int dash = 0);
/* Versions of DrawString/DrawStringMultiLine that accept a Rect instead of separate left, right, top and bottom parameters. */ /* Versions of DrawString/DrawStringMultiLine that accept a Rect instead of separate left, right, top and bottom parameters. */
inline int DrawString(const Rect &r, std::string_view str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL) inline int DrawString(const Rect &r, std::string_view str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL)
@ -135,7 +135,7 @@ inline bool DrawStringMultiLineWithClipping(const Rect &r, std::string_view str,
return DrawStringMultiLineWithClipping(r.left, r.right, r.top, r.bottom, str, colour, align, underline, fontsize); return DrawStringMultiLineWithClipping(r.left, r.right, r.top, r.bottom, str, colour, align, underline, fontsize);
} }
inline void GfxFillRect(const Rect &r, int colour, FillRectMode mode = FILLRECT_OPAQUE) inline void GfxFillRect(const Rect &r, const std::variant<PixelColour, PaletteID> &colour, FillRectMode mode = FILLRECT_OPAQUE)
{ {
GfxFillRect(r.left, r.top, r.right, r.bottom, colour, mode); GfxFillRect(r.left, r.top, r.right, r.bottom, colour, mode);
} }

View File

@ -245,7 +245,6 @@ using Colour = std::conditional_t<std::endian::native == std::endian::little, Co
static_assert(sizeof(Colour) == sizeof(uint32_t)); static_assert(sizeof(Colour) == sizeof(uint32_t));
/** Available font sizes */ /** Available font sizes */
enum FontSize : uint8_t { enum FontSize : uint8_t {
FS_NORMAL, ///< Index of the normal font in the font tables. FS_NORMAL, ///< Index of the normal font in the font tables.
@ -403,4 +402,14 @@ enum StringAlignment : uint8_t {
}; };
DECLARE_ENUM_AS_BIT_SET(StringAlignment) DECLARE_ENUM_AS_BIT_SET(StringAlignment)
/** Colour for pixel/line drawing. */
struct PixelColour {
uint8_t p; ///< Palette index.
constexpr PixelColour() : p(0) {}
explicit constexpr PixelColour(uint8_t p) : p(p) {}
constexpr inline TextColour ToTextColour() const { return static_cast<TextColour>(this->p) | TC_IS_PALETTE_COLOUR; }
};
#endif /* GFX_TYPE_H */ #endif /* GFX_TYPE_H */

View File

@ -165,11 +165,11 @@ struct ValuesInterval {
struct BaseGraphWindow : Window { struct BaseGraphWindow : Window {
protected: protected:
static const int GRAPH_MAX_DATASETS = 64; static const int GRAPH_MAX_DATASETS = 64;
static const int GRAPH_BASE_COLOUR = GREY_SCALE(2); static constexpr PixelColour GRAPH_BASE_COLOUR = GREY_SCALE(2);
static const int GRAPH_GRID_COLOUR = GREY_SCALE(3); static constexpr PixelColour GRAPH_GRID_COLOUR = GREY_SCALE(3);
static const int GRAPH_AXIS_LINE_COLOUR = GREY_SCALE(1); static constexpr PixelColour GRAPH_AXIS_LINE_COLOUR = GREY_SCALE(1);
static const int GRAPH_ZERO_LINE_COLOUR = GREY_SCALE(8); static constexpr PixelColour GRAPH_ZERO_LINE_COLOUR = GREY_SCALE(8);
static const int GRAPH_YEAR_LINE_COLOUR = GREY_SCALE(5); static constexpr PixelColour GRAPH_YEAR_LINE_COLOUR = GREY_SCALE(5);
static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph. static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph.
static const int GRAPH_PAYMENT_RATE_STEPS = 20; ///< Number of steps on Payment rate graph. static const int GRAPH_PAYMENT_RATE_STEPS = 20; ///< Number of steps on Payment rate graph.
static const int PAYMENT_GRAPH_X_STEP_DAYS = 10; ///< X-axis step label for cargo payment rates "Days in transit". static const int PAYMENT_GRAPH_X_STEP_DAYS = 10; ///< X-axis step label for cargo payment rates "Days in transit".
@ -204,7 +204,7 @@ protected:
struct DataSet { struct DataSet {
std::array<OverflowSafeInt64, GRAPH_NUM_MONTHS> values; std::array<OverflowSafeInt64, GRAPH_NUM_MONTHS> values;
uint8_t colour; PixelColour colour;
uint8_t exclude_bit; uint8_t exclude_bit;
uint8_t range_bit; uint8_t range_bit;
uint8_t dash; uint8_t dash;
@ -398,7 +398,7 @@ protected:
/* Draw the grid lines. */ /* Draw the grid lines. */
int gridline_width = WidgetDimensions::scaled.bevel.top; int gridline_width = WidgetDimensions::scaled.bevel.top;
int grid_colour = GRAPH_GRID_COLOUR; PixelColour grid_colour = GRAPH_GRID_COLOUR;
/* Don't draw the first line, as that's where the axis will be. */ /* Don't draw the first line, as that's where the axis will be. */
if (rtl) { if (rtl) {
@ -524,7 +524,7 @@ protected:
uint pointoffs1 = pointwidth / 2; uint pointoffs1 = pointwidth / 2;
uint pointoffs2 = pointwidth - pointoffs1; uint pointoffs2 = pointwidth - pointoffs1;
auto draw_dataset = [&](const DataSet &dataset, uint8_t colour) { auto draw_dataset = [&](const DataSet &dataset, PixelColour colour) {
if (HasBit(this->excluded_data, dataset.exclude_bit)) return; if (HasBit(this->excluded_data, dataset.exclude_bit)) return;
if (HasBit(this->excluded_range, dataset.range_bit)) return; if (HasBit(this->excluded_range, dataset.range_bit)) return;
@ -1222,7 +1222,7 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
/* Cargo-colour box with outline */ /* Cargo-colour box with outline */
const Rect cargo = text.WithWidth(this->legend_width, rtl); const Rect cargo = text.WithWidth(this->legend_width, rtl);
GfxFillRect(cargo, PC_BLACK); GfxFillRect(cargo, PC_BLACK);
uint8_t pc = cs->legend_colour; PixelColour pc = cs->legend_colour;
if (this->highlight_data == cs->Index()) pc = this->highlight_state ? PC_WHITE : PC_BLACK; if (this->highlight_data == cs->Index()) pc = this->highlight_state ? PC_WHITE : PC_BLACK;
GfxFillRect(cargo.Shrink(WidgetDimensions::scaled.bevel), pc); GfxFillRect(cargo.Shrink(WidgetDimensions::scaled.bevel), pc);
@ -1499,8 +1499,8 @@ struct PerformanceRatingDetailWindow : Window {
ScoreID score_type = (ScoreID)(widget - WID_PRD_SCORE_FIRST); ScoreID score_type = (ScoreID)(widget - WID_PRD_SCORE_FIRST);
/* The colours used to show how the progress is going */ /* The colours used to show how the progress is going */
int colour_done = GetColourGradient(COLOUR_GREEN, SHADE_NORMAL); PixelColour colour_done = GetColourGradient(COLOUR_GREEN, SHADE_NORMAL);
int colour_notdone = GetColourGradient(COLOUR_RED, SHADE_NORMAL); PixelColour colour_notdone = GetColourGradient(COLOUR_RED, SHADE_NORMAL);
/* Draw all the score parts */ /* Draw all the score parts */
int64_t val = _score_part[company][score_type]; int64_t val = _score_part[company][score_type];

View File

@ -305,7 +305,7 @@ private:
const int offset = (rtl ? -(int)this->column_size[VGC_FOLD].width : (int)this->column_size[VGC_FOLD].width) / 2; const int offset = (rtl ? -(int)this->column_size[VGC_FOLD].width : (int)this->column_size[VGC_FOLD].width) / 2;
const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent; const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent;
const int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); const PixelColour linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
if (indent > 0) { if (indent > 0) {
/* Draw tree continuation lines. */ /* Draw tree continuation lines. */

View File

@ -1986,8 +1986,8 @@ struct CargoesField {
static Dimension cargo_space; static Dimension cargo_space;
static Dimension cargo_stub; static Dimension cargo_stub;
static const int INDUSTRY_LINE_COLOUR; static const PixelColour INDUSTRY_LINE_COLOUR;
static const int CARGO_LINE_COLOUR; static const PixelColour CARGO_LINE_COLOUR;
static int small_height, normal_height; static int small_height, normal_height;
static int cargo_field_width; static int cargo_field_width;
@ -2395,8 +2395,8 @@ int CargoesField::vert_inter_industry_space; ///< Amount of space between two in
int CargoesField::blob_distance; ///< Distance of the industry legend colour from the edge of the industry box. int CargoesField::blob_distance; ///< Distance of the industry legend colour from the edge of the industry box.
const int CargoesField::INDUSTRY_LINE_COLOUR = PC_YELLOW; ///< Line colour of the industry type box. const PixelColour CargoesField::INDUSTRY_LINE_COLOUR = PC_YELLOW; ///< Line colour of the industry type box.
const int CargoesField::CARGO_LINE_COLOUR = PC_YELLOW; ///< Line colour around the cargo. const PixelColour CargoesField::CARGO_LINE_COLOUR = PC_YELLOW; ///< Line colour around the cargo.
/** A single row of #CargoesField. */ /** A single row of #CargoesField. */
struct CargoesRow { struct CargoesRow {

View File

@ -119,7 +119,7 @@ struct IndustrySpec {
IndustryLifeTypes life_type; ///< This is also known as Industry production flag, in newgrf specs IndustryLifeTypes life_type; ///< This is also known as Industry production flag, in newgrf specs
LandscapeTypes climate_availability; ///< Bitmask, giving landscape enums as bit position LandscapeTypes climate_availability; ///< Bitmask, giving landscape enums as bit position
IndustryBehaviours behaviour; ///< How this industry will behave, and how others entities can use it IndustryBehaviours behaviour; ///< How this industry will behave, and how others entities can use it
uint8_t map_colour; ///< colour used for the small map PixelColour map_colour; ///< colour used for the small map
StringID name; ///< Displayed name of the industry StringID name; ///< Displayed name of the industry
StringID new_industry_text; ///< Message appearing when the industry is built StringID new_industry_text; ///< Message appearing when the industry is built
StringID closure_text; ///< Message appearing when the industry closes StringID closure_text; ///< Message appearing when the industry closes

View File

@ -5244,6 +5244,8 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an
STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land
STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long
STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map
STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is too low for station
STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION :{WHITE}Bridge pillars obstruct station
# Tunnel related errors # Tunnel related errors
STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here...

View File

@ -30,26 +30,26 @@
* Colours for the various "load" states of links. Ordered from "unused" to * Colours for the various "load" states of links. Ordered from "unused" to
* "overloaded". * "overloaded".
*/ */
const uint8_t LinkGraphOverlay::LINK_COLOURS[][12] = { const PixelColour LinkGraphOverlay::LINK_COLOURS[][12] = {
{ {
0x0f, 0xd1, 0xd0, 0x57, PixelColour{0x0f}, PixelColour{0xd1}, PixelColour{0xd0}, PixelColour{0x57},
0x55, 0x53, 0xbf, 0xbd, PixelColour{0x55}, PixelColour{0x53}, PixelColour{0xbf}, PixelColour{0xbd},
0xba, 0xb9, 0xb7, 0xb5 PixelColour{0xba}, PixelColour{0xb9}, PixelColour{0xb7}, PixelColour{0xb5}
}, },
{ {
0x0f, 0xd1, 0xd0, 0x57, PixelColour{0x0f}, PixelColour{0xd1}, PixelColour{0xd0}, PixelColour{0x57},
0x55, 0x53, 0x96, 0x95, PixelColour{0x55}, PixelColour{0x53}, PixelColour{0x96}, PixelColour{0x95},
0x94, 0x93, 0x92, 0x91 PixelColour{0x94}, PixelColour{0x93}, PixelColour{0x92}, PixelColour{0x91}
}, },
{ {
0x0f, 0x0b, 0x09, 0x07, PixelColour{0x0f}, PixelColour{0x0b}, PixelColour{0x09}, PixelColour{0x07},
0x05, 0x03, 0xbf, 0xbd, PixelColour{0x05}, PixelColour{0x03}, PixelColour{0xbf}, PixelColour{0xbd},
0xba, 0xb9, 0xb7, 0xb5 PixelColour{0xba}, PixelColour{0xb9}, PixelColour{0xb7}, PixelColour{0xb5}
}, },
{ {
0x0f, 0x0b, 0x0a, 0x09, PixelColour{0x0f}, PixelColour{0x0b}, PixelColour{0x0a}, PixelColour{0x09},
0x08, 0x07, 0x06, 0x05, PixelColour{0x08}, PixelColour{0x07}, PixelColour{0x06}, PixelColour{0x05},
0x04, 0x03, 0x02, 0x01 PixelColour{0x04}, PixelColour{0x03}, PixelColour{0x02}, PixelColour{0x01}
} }
}; };
@ -297,7 +297,7 @@ void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &cargo) const void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &cargo) const
{ {
uint usage_or_plan = std::min(cargo.capacity * 2 + 1, cargo.Usage()); uint usage_or_plan = std::min(cargo.capacity * 2 + 1, cargo.Usage());
int colour = LinkGraphOverlay::LINK_COLOURS[_settings_client.gui.linkgraph_colours][usage_or_plan * lengthof(LinkGraphOverlay::LINK_COLOURS[0]) / (cargo.capacity * 2 + 2)]; PixelColour colour = LinkGraphOverlay::LINK_COLOURS[_settings_client.gui.linkgraph_colours][usage_or_plan * lengthof(LinkGraphOverlay::LINK_COLOURS[0]) / (cargo.capacity * 2 + 2)];
int width = ScaleGUITrad(this->scale); int width = ScaleGUITrad(this->scale);
int dash = cargo.shared ? width * 4 : 0; int dash = cargo.shared ? width * 4 : 0;
@ -345,7 +345,7 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
* @param colour Colour with which the vertex will be filled. * @param colour Colour with which the vertex will be filled.
* @param border_colour Colour for the border of the vertex. * @param border_colour Colour for the border of the vertex.
*/ */
/* static */ void LinkGraphOverlay::DrawVertex(int x, int y, int size, int colour, int border_colour) /* static */ void LinkGraphOverlay::DrawVertex(int x, int y, int size, PixelColour colour, PixelColour border_colour)
{ {
size--; size--;
int w1 = size / 2; int w1 = size / 2;
@ -607,7 +607,7 @@ void LinkGraphLegendWindow::DrawWidget(const Rect &r, WidgetID widget) const
DrawCompanyIcon(cid, CentreBounds(br.left, br.right, sprite_size.width), CentreBounds(br.top, br.bottom, sprite_size.height)); DrawCompanyIcon(cid, CentreBounds(br.left, br.right, sprite_size.width), CentreBounds(br.top, br.bottom, sprite_size.height));
} }
if (IsInsideMM(widget, WID_LGL_SATURATION_FIRST, WID_LGL_SATURATION_LAST + 1)) { if (IsInsideMM(widget, WID_LGL_SATURATION_FIRST, WID_LGL_SATURATION_LAST + 1)) {
uint8_t colour = LinkGraphOverlay::LINK_COLOURS[_settings_client.gui.linkgraph_colours][widget - WID_LGL_SATURATION_FIRST]; PixelColour colour = LinkGraphOverlay::LINK_COLOURS[_settings_client.gui.linkgraph_colours][widget - WID_LGL_SATURATION_FIRST];
GfxFillRect(br, colour); GfxFillRect(br, colour);
StringID str = STR_NULL; StringID str = STR_NULL;
if (widget == WID_LGL_SATURATION_FIRST) { if (widget == WID_LGL_SATURATION_FIRST) {

View File

@ -44,7 +44,7 @@ public:
typedef std::map<StationID, StationLinkMap> LinkMap; typedef std::map<StationID, StationLinkMap> LinkMap;
typedef std::vector<std::pair<StationID, uint> > StationSupplyList; typedef std::vector<std::pair<StationID, uint> > StationSupplyList;
static const uint8_t LINK_COLOURS[][12]; static const PixelColour LINK_COLOURS[][12];
/** /**
* Create a link graph overlay for the specified window. * Create a link graph overlay for the specified window.
@ -95,7 +95,7 @@ protected:
void RebuildCache(); void RebuildCache();
static void AddStats(CargoType new_cargo, uint new_cap, uint new_usg, uint new_flow, uint32_t time, bool new_shared, LinkProperties &cargo); static void AddStats(CargoType new_cargo, uint new_cap, uint new_usg, uint new_flow, uint32_t time, bool new_shared, LinkProperties &cargo);
static void DrawVertex(int x, int y, int size, int colour, int border_colour); static void DrawVertex(int x, int y, int size, PixelColour colour, PixelColour border_colour);
}; };
void ShowLinkGraphLegend(); void ShowLinkGraphLegend();

View File

@ -42,13 +42,13 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
} }
/** /**
* Erase all flows originating at a specific node. * Erase all flows originating at a specific station.
* @param from Node to erase flows for. * @param from StationID to erase flows for.
*/ */
void LinkGraphJob::EraseFlows(NodeID from) void LinkGraphJob::EraseFlows(StationID from)
{ {
for (NodeID node_id = 0; node_id < this->Size(); ++node_id) { for (NodeID node_id = 0; node_id < this->Size(); ++node_id) {
(*this)[node_id].flows.erase(StationID{from}); (*this)[node_id].flows.erase(from);
} }
} }
@ -106,7 +106,7 @@ LinkGraphJob::~LinkGraphJob()
/* The station can have been deleted. Remove all flows originating from it then. */ /* The station can have been deleted. Remove all flows originating from it then. */
Station *st = Station::GetIfValid(from.base.station); Station *st = Station::GetIfValid(from.base.station);
if (st == nullptr) { if (st == nullptr) {
this->EraseFlows(node_id); this->EraseFlows(from.base.station);
continue; continue;
} }
@ -114,7 +114,7 @@ LinkGraphJob::~LinkGraphJob()
* sure that everything is still consistent or ignore it otherwise. */ * sure that everything is still consistent or ignore it otherwise. */
GoodsEntry &ge = st->goods[this->Cargo()]; GoodsEntry &ge = st->goods[this->Cargo()];
if (ge.link_graph != this->link_graph.index || ge.node != node_id) { if (ge.link_graph != this->link_graph.index || ge.node != node_id) {
this->EraseFlows(node_id); this->EraseFlows(from.base.station);
continue; continue;
} }
@ -136,7 +136,7 @@ LinkGraphJob::~LinkGraphJob()
/* Delete old flows for source stations which have been deleted /* Delete old flows for source stations which have been deleted
* from the new flows. This avoids flow cycles between old and * from the new flows. This avoids flow cycles between old and
* new flows. */ * new flows. */
while (!erased.IsEmpty()) geflows.erase(StationID{erased.Pop()}); while (!erased.IsEmpty()) geflows.erase(erased.Pop());
} else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) { } else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) {
/* Edge is fully restricted. */ /* Edge is fully restricted. */
flows.RestrictFlows(to); flows.RestrictFlows(to);

View File

@ -167,7 +167,7 @@ protected:
std::atomic<bool> job_completed = false; ///< Is the job still running. This is accessed by multiple threads and reads may be stale. std::atomic<bool> job_completed = false; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
std::atomic<bool> job_aborted = false; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale. std::atomic<bool> job_aborted = false; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale.
void EraseFlows(NodeID from); void EraseFlows(StationID from);
void JoinThread(); void JoinThread();
void SpawnThread(); void SpawnThread();

View File

@ -556,7 +556,7 @@ void SetupColoursAndInitialWindow()
const uint8_t *b = GetNonSprite(GetColourPalette(i), SpriteType::Recolour) + 1; const uint8_t *b = GetNonSprite(GetColourPalette(i), SpriteType::Recolour) + 1;
assert(b != nullptr); assert(b != nullptr);
for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) { for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) {
SetColourGradient(i, j, b[0xC6 + j]); SetColourGradient(i, j, PixelColour{b[0xC6 + j]});
} }
} }

View File

@ -97,11 +97,11 @@ static ChangeInfoResult CargoReserveInfo(uint first, uint last, int prop, ByteRe
break; break;
case 0x13: // Colour for station rating bars case 0x13: // Colour for station rating bars
cs->rating_colour = buf.ReadByte(); cs->rating_colour = PixelColour{buf.ReadByte()};
break; break;
case 0x14: // Colour for cargo graph case 0x14: // Colour for cargo graph
cs->legend_colour = buf.ReadByte(); cs->legend_colour = PixelColour{buf.ReadByte()};
break; break;
case 0x15: // Freight status case 0x15: // Freight status

View File

@ -565,7 +565,7 @@ static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, By
break; break;
case 0x19: // Map colour case 0x19: // Map colour
indsp->map_colour = buf.ReadByte(); indsp->map_colour = PixelColour{buf.ReadByte()};
break; break;
case 0x1A: // Special industry flags to define special behavior case 0x1A: // Special industry flags to define special behavior

View File

@ -121,7 +121,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint first, uint last, int prop, Byte
break; break;
case 0x16: // Map colour case 0x16: // Map colour
rti->map_colour = buf.ReadByte(); rti->map_colour = PixelColour{buf.ReadByte()};
break; break;
case 0x17: // Introduction date case 0x17: // Introduction date

View File

@ -109,7 +109,7 @@ static ChangeInfoResult RoadTypeChangeInfo(uint first, uint last, int prop, Byte
break; break;
case 0x16: // Map colour case 0x16: // Map colour
rti->map_colour = buf.ReadByte(); rti->map_colour = PixelColour{buf.ReadByte()};
break; break;
case 0x17: // Introduction date case 0x17: // Introduction date

View File

@ -12,6 +12,7 @@
#ifndef NEWGRF_ROADSTATION_H #ifndef NEWGRF_ROADSTATION_H
#define NEWGRF_ROADSTATION_H #define NEWGRF_ROADSTATION_H
#include "bridge.h"
#include "newgrf_animation_type.h" #include "newgrf_animation_type.h"
#include "newgrf_spritegroup.h" #include "newgrf_spritegroup.h"
#include "newgrf_badge_type.h" #include "newgrf_badge_type.h"
@ -71,6 +72,12 @@ enum class RoadStopSpecFlag : uint8_t {
}; };
using RoadStopSpecFlags = EnumBitSet<RoadStopSpecFlag, uint8_t>; using RoadStopSpecFlags = EnumBitSet<RoadStopSpecFlag, uint8_t>;
enum class RoadStopSpecIntlFlag : uint8_t {
BridgeHeightsSet, ///< bridge_height[6] is set.
BridgeDisallowedPillarsSet, ///< bridge_disallowed_pillars[6] is set.
};
using RoadStopSpecIntlFlags = EnumBitSet<RoadStopSpecIntlFlag, uint8_t>;
enum RoadStopView : uint8_t { enum RoadStopView : uint8_t {
RSV_BAY_NE = 0, ///< Bay road stop, facing Northeast RSV_BAY_NE = 0, ///< Bay road stop, facing Northeast
RSV_BAY_SE = 1, ///< Bay road stop, facing Southeast RSV_BAY_SE = 1, ///< Bay road stop, facing Southeast
@ -133,17 +140,20 @@ struct RoadStopSpec : NewGRFSpecBase<RoadStopClassID> {
RoadStopDrawModes draw_mode = {RoadStopDrawMode::Road, RoadStopDrawMode::Overlay}; RoadStopDrawModes draw_mode = {RoadStopDrawMode::Road, RoadStopDrawMode::Overlay};
RoadStopCallbackMasks callback_mask{}; RoadStopCallbackMasks callback_mask{};
RoadStopSpecFlags flags{}; RoadStopSpecFlags flags{};
RoadStopSpecIntlFlags internal_flags{};
CargoTypes cargo_triggers = 0; ///< Bitmask of cargo types which cause trigger re-randomizing CargoTypes cargo_triggers = 0; ///< Bitmask of cargo types which cause trigger re-randomizing
AnimationInfo<StationAnimationTriggers> animation; AnimationInfo<StationAnimationTriggers> animation;
uint8_t bridge_height[6]; ///< Minimum height for a bridge above, 0 for none uint8_t bridge_height[6]; ///< Minimum height for a bridge above, 0 for none
uint8_t bridge_disallowed_pillars[6]; ///< Disallowed pillar flags for a bridge above BridgePiecePillarFlags bridge_disallowed_pillars[6]; ///< Disallowed pillar flags for a bridge above
uint8_t build_cost_multiplier = 16; ///< Build cost multiplier per tile. uint8_t build_cost_multiplier = 16; ///< Build cost multiplier per tile.
uint8_t clear_cost_multiplier = 16; ///< Clear cost multiplier per tile. uint8_t clear_cost_multiplier = 16; ///< Clear cost multiplier per tile.
uint8_t height; ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
std::vector<BadgeID> badges; std::vector<BadgeID> badges;
/** /**

View File

@ -10,6 +10,7 @@
#ifndef NEWGRF_STATION_H #ifndef NEWGRF_STATION_H
#define NEWGRF_STATION_H #define NEWGRF_STATION_H
#include "bridge.h"
#include "core/enum_type.hpp" #include "core/enum_type.hpp"
#include "newgrf_animation_type.h" #include "newgrf_animation_type.h"
#include "newgrf_badge_type.h" #include "newgrf_badge_type.h"
@ -118,6 +119,12 @@ enum class StationSpecFlag : uint8_t {
}; };
using StationSpecFlags = EnumBitSet<StationSpecFlag, uint8_t>; using StationSpecFlags = EnumBitSet<StationSpecFlag, uint8_t>;
enum class StationSpecIntlFlag : uint8_t {
BridgeHeightsSet, ///< bridge_height[8] is set.
BridgeDisallowedPillarsSet, ///< bridge_disallowed_pillars[8] is set.
};
using StationSpecIntlFlags = EnumBitSet<StationSpecIntlFlag, uint8_t>;
/** Station specification. */ /** Station specification. */
struct StationSpec : NewGRFSpecBase<StationClassID> { struct StationSpec : NewGRFSpecBase<StationClassID> {
StationSpec() : name(0), StationSpec() : name(0),
@ -162,6 +169,12 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
StationSpecFlags flags; ///< Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size StationSpecFlags flags; ///< Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size
struct BridgeAboveFlags {
uint8_t height = UINT8_MAX; ///< Minimum height for a bridge above, 0 for none
BridgePiecePillarFlags disallowed_pillars = {}; ///< Disallowed pillar flags for a bridge above
};
std::vector<BridgeAboveFlags> bridge_above_flags; ///< List of bridge above flags.
enum class TileFlag : uint8_t { enum class TileFlag : uint8_t {
Pylons = 0, ///< Tile should contain catenary pylons. Pylons = 0, ///< Tile should contain catenary pylons.
NoWires = 1, ///< Tile should NOT contain catenary wires. NoWires = 1, ///< Tile should NOT contain catenary wires.
@ -172,10 +185,18 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
AnimationInfo<StationAnimationTriggers> animation; AnimationInfo<StationAnimationTriggers> animation;
StationSpecIntlFlags internal_flags{}; ///< Bitmask of internal spec flags
/** Custom platform layouts, keyed by platform and length combined. */ /** Custom platform layouts, keyed by platform and length combined. */
std::unordered_map<uint16_t, std::vector<uint8_t>> layouts; std::unordered_map<uint16_t, std::vector<uint8_t>> layouts;
std::vector<BadgeID> badges; std::vector<BadgeID> badges;
BridgeAboveFlags GetBridgeAboveFlags(uint gfx) const
{
if (gfx < this->bridge_above_flags.size()) return this->bridge_above_flags[gfx];
return {};
}
}; };
/** Class containing information relating to station classes. */ /** Class containing information relating to station classes. */

View File

@ -368,7 +368,7 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI
next = v->cur_implicit_order_index; next = v->cur_implicit_order_index;
if (next >= this->GetNumOrders()) { if (next >= this->GetNumOrders()) {
next = this->GetFirstOrder(); next = this->GetFirstOrder();
if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid().base(); if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid();
} else { } else {
/* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list. /* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list.
* As the given "next" is already valid and a station in the list, we * As the given "next" is already valid and a station in the list, we
@ -404,11 +404,11 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI
if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) && if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) &&
orders[next].GetDestination() == v->last_station_visited && orders[next].GetDestination() == v->last_station_visited &&
(orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) { (orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
return StationID::Invalid().base(); return StationID::Invalid();
} }
} while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited); } while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited);
return orders[next].GetDestination().ToStationID().base(); return orders[next].GetDestination().ToStationID();
} }
/** /**

View File

@ -358,9 +358,9 @@ void DoPaletteAnimations()
* @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128. * @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128.
* @return TC_BLACK or TC_WHITE depending on what gives a better contrast. * @return TC_BLACK or TC_WHITE depending on what gives a better contrast.
*/ */
TextColour GetContrastColour(uint8_t background, uint8_t threshold) TextColour GetContrastColour(PixelColour background, uint8_t threshold)
{ {
Colour c = _cur_palette.palette[background]; Colour c = _cur_palette.palette[background.p];
/* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast. /* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast.
* The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */ * The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */
uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114; uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114;
@ -374,7 +374,7 @@ TextColour GetContrastColour(uint8_t background, uint8_t threshold)
*/ */
struct ColourGradients struct ColourGradients
{ {
using ColourGradient = std::array<uint8_t, SHADE_END>; using ColourGradient = std::array<PixelColour, SHADE_END>;
static inline std::array<ColourGradient, COLOUR_END> gradient{}; static inline std::array<ColourGradient, COLOUR_END> gradient{};
}; };
@ -385,7 +385,7 @@ struct ColourGradients
* @param shade Shade level from 1 to 7. * @param shade Shade level from 1 to 7.
* @returns palette index of colour. * @returns palette index of colour.
*/ */
uint8_t GetColourGradient(Colours colour, ColourShade shade) PixelColour GetColourGradient(Colours colour, ColourShade shade)
{ {
return ColourGradients::gradient[colour % COLOUR_END][shade % SHADE_END]; return ColourGradients::gradient[colour % COLOUR_END][shade % SHADE_END];
} }
@ -396,7 +396,7 @@ uint8_t GetColourGradient(Colours colour, ColourShade shade)
* @param shade Shade level from 1 to 7. * @param shade Shade level from 1 to 7.
* @param palette_index Palette index to set. * @param palette_index Palette index to set.
*/ */
void SetColourGradient(Colours colour, ColourShade shade, uint8_t palette_index) void SetColourGradient(Colours colour, ColourShade shade, PixelColour palette_index)
{ {
assert(colour < COLOUR_END); assert(colour < COLOUR_END);
assert(shade < SHADE_END); assert(shade < SHADE_END);

View File

@ -67,7 +67,7 @@ inline bool IsValidColours(Colours colours)
return colours < COLOUR_END; return colours < COLOUR_END;
} }
TextColour GetContrastColour(uint8_t background, uint8_t threshold = 128); TextColour GetContrastColour(PixelColour background, uint8_t threshold = 128);
enum ColourShade : uint8_t { enum ColourShade : uint8_t {
SHADE_BEGIN = 0, SHADE_BEGIN = 0,
@ -83,45 +83,45 @@ enum ColourShade : uint8_t {
}; };
DECLARE_INCREMENT_DECREMENT_OPERATORS(ColourShade) DECLARE_INCREMENT_DECREMENT_OPERATORS(ColourShade)
uint8_t GetColourGradient(Colours colour, ColourShade shade); PixelColour GetColourGradient(Colours colour, ColourShade shade);
void SetColourGradient(Colours colour, ColourShade shade, uint8_t palette_colour); void SetColourGradient(Colours colour, ColourShade shade, PixelColour palette_colour);
/** /**
* Return the colour for a particular greyscale level. * Return the colour for a particular greyscale level.
* @param level Intensity, 0 = black, 15 = white * @param level Intensity, 0 = black, 15 = white
* @return colour * @return colour
*/ */
constexpr uint8_t GREY_SCALE(uint8_t level) { return level; } inline constexpr PixelColour GREY_SCALE(uint8_t level) { return PixelColour{level}; }
static const uint8_t PC_BLACK = GREY_SCALE(1); ///< Black palette colour. static constexpr PixelColour PC_BLACK {GREY_SCALE(1)}; ///< Black palette colour.
static const uint8_t PC_DARK_GREY = GREY_SCALE(6); ///< Dark grey palette colour. static constexpr PixelColour PC_DARK_GREY {GREY_SCALE(6)}; ///< Dark grey palette colour.
static const uint8_t PC_GREY = GREY_SCALE(10); ///< Grey palette colour. static constexpr PixelColour PC_GREY {GREY_SCALE(10)}; ///< Grey palette colour.
static const uint8_t PC_WHITE = GREY_SCALE(15); ///< White palette colour. static constexpr PixelColour PC_WHITE {GREY_SCALE(15)}; ///< White palette colour.
static const uint8_t PC_VERY_DARK_RED = 0xB2; ///< Almost-black red palette colour. static constexpr PixelColour PC_VERY_DARK_RED {0xB2}; ///< Almost-black red palette colour.
static const uint8_t PC_DARK_RED = 0xB4; ///< Dark red palette colour. static constexpr PixelColour PC_DARK_RED {0xB4}; ///< Dark red palette colour.
static const uint8_t PC_RED = 0xB8; ///< Red palette colour. static constexpr PixelColour PC_RED {0xB8}; ///< Red palette colour.
static const uint8_t PC_VERY_DARK_BROWN = 0x56; ///< Almost-black brown palette colour. static constexpr PixelColour PC_VERY_DARK_BROWN {0x56}; ///< Almost-black brown palette colour.
static const uint8_t PC_ORANGE = 0xC2; ///< Orange palette colour. static constexpr PixelColour PC_ORANGE {0xC2}; ///< Orange palette colour.
static const uint8_t PC_YELLOW = 0xBF; ///< Yellow palette colour. static constexpr PixelColour PC_YELLOW {0xBF}; ///< Yellow palette colour.
static const uint8_t PC_LIGHT_YELLOW = 0x44; ///< Light yellow palette colour. static constexpr PixelColour PC_LIGHT_YELLOW {0x44}; ///< Light yellow palette colour.
static const uint8_t PC_VERY_LIGHT_YELLOW = 0x45; ///< Almost-white yellow palette colour. static constexpr PixelColour PC_VERY_LIGHT_YELLOW {0x45}; ///< Almost-white yellow palette colour.
static const uint8_t PC_GREEN = 0xD0; ///< Green palette colour. static constexpr PixelColour PC_GREEN {0xD0}; ///< Green palette colour.
static const uint8_t PC_VERY_DARK_BLUE = 0x9A; ///< Almost-black blue palette colour. static constexpr PixelColour PC_VERY_DARK_BLUE {0x9A}; ///< Almost-black blue palette colour.
static const uint8_t PC_DARK_BLUE = 0x9D; ///< Dark blue palette colour. static constexpr PixelColour PC_DARK_BLUE {0x9D}; ///< Dark blue palette colour.
static const uint8_t PC_LIGHT_BLUE = 0x98; ///< Light blue palette colour. static constexpr PixelColour PC_LIGHT_BLUE {0x98}; ///< Light blue palette colour.
static const uint8_t PC_ROUGH_LAND = 0x52; ///< Dark green palette colour for rough land. static constexpr PixelColour PC_ROUGH_LAND {0x52}; ///< Dark green palette colour for rough land.
static const uint8_t PC_GRASS_LAND = 0x54; ///< Dark green palette colour for grass land. static constexpr PixelColour PC_GRASS_LAND {0x54}; ///< Dark green palette colour for grass land.
static const uint8_t PC_BARE_LAND = 0x37; ///< Brown palette colour for bare land. static constexpr PixelColour PC_BARE_LAND {0x37}; ///< Brown palette colour for bare land.
static const uint8_t PC_RAINFOREST = 0x5C; ///< Pale green palette colour for rainforest. static constexpr PixelColour PC_RAINFOREST {0x5C}; ///< Pale green palette colour for rainforest.
static const uint8_t PC_FIELDS = 0x25; ///< Light brown palette colour for fields. static constexpr PixelColour PC_FIELDS {0x25}; ///< Light brown palette colour for fields.
static const uint8_t PC_TREES = 0x57; ///< Green palette colour for trees. static constexpr PixelColour PC_TREES {0x57}; ///< Green palette colour for trees.
static const uint8_t PC_WATER = 0xC9; ///< Dark blue palette colour for water. static constexpr PixelColour PC_WATER {0xC9}; ///< Dark blue palette colour for water.
#endif /* PALETTE_FUNC_H */ #endif /* PALETTE_FUNC_H */

View File

@ -234,7 +234,7 @@ public:
/** /**
* Colour on mini-map * Colour on mini-map
*/ */
uint8_t map_colour; PixelColour map_colour;
/** /**
* Introduction date. * Introduction date.

View File

@ -145,7 +145,7 @@ public:
/** /**
* Colour on mini-map * Colour on mini-map
*/ */
uint8_t map_colour; PixelColour map_colour;
/** /**
* Introduction date. * Introduction date.

View File

@ -99,7 +99,7 @@ uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int
int x = rtl ? right : left; int x = rtl ? right : left;
if (cur_row >= first_row) { if (cur_row >= first_row) {
int colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); PixelColour colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
/* Draw vertical for parent nesting levels */ /* Draw vertical for parent nesting levels */

View File

@ -1849,7 +1849,7 @@ void ShowGameOptions()
*/ */
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right) void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
{ {
int colour = GetColourGradient(button_colour, SHADE_DARKER); PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
Dimension dim = NWidgetScrollbar::GetHorizontalDimension(); Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1}; Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
@ -1881,7 +1881,7 @@ void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool c
*/ */
void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down) void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
{ {
int colour = GetColourGradient(button_colour, SHADE_DARKER); PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1}; Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
Rect ur = r.WithWidth(SETTING_BUTTON_WIDTH / 2, (_current_text_dir == TD_RTL)); Rect ur = r.WithWidth(SETTING_BUTTON_WIDTH / 2, (_current_text_dir == TD_RTL));
@ -1907,7 +1907,7 @@ void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool
*/ */
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable) void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
{ {
int colour = GetColourGradient(button_colour, SHADE_DARKER); PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1}; Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};

View File

@ -45,9 +45,9 @@ void DrawSliderWidget(Rect r, Colours wedge_colour, Colours handle_colour, TextC
int wx1 = r.left + sw / 2; int wx1 = r.left + sw / 2;
int wx2 = r.right - sw / 2; int wx2 = r.right - sw / 2;
if (_current_text_dir == TD_RTL) std::swap(wx1, wx2); if (_current_text_dir == TD_RTL) std::swap(wx1, wx2);
const uint shadow = GetColourGradient(wedge_colour, SHADE_DARK); const PixelColour shadow = GetColourGradient(wedge_colour, SHADE_DARK);
const uint fill = GetColourGradient(wedge_colour, SHADE_LIGHTER); const PixelColour fill = GetColourGradient(wedge_colour, SHADE_LIGHTER);
const uint light = GetColourGradient(wedge_colour, SHADE_LIGHTEST); const PixelColour light = GetColourGradient(wedge_colour, SHADE_LIGHTEST);
const std::array<Point, 3> wedge{ Point{wx1, r.bottom - ha}, Point{wx2, r.top + ha}, Point{wx2, r.bottom - ha} }; const std::array<Point, 3> wedge{ Point{wx1, r.bottom - ha}, Point{wx2, r.top + ha}, Point{wx2, r.bottom - ha} };
GfxFillPolygon(wedge, fill); GfxFillPolygon(wedge, fill);
GfxDrawLine(wedge[0].x, wedge[0].y, wedge[2].x, wedge[2].y, light, t); GfxDrawLine(wedge[0].x, wedge[0].y, wedge[2].x, wedge[2].y, light, t);

View File

@ -44,7 +44,7 @@ static int _smallmap_cargo_count; ///< Number of cargos in the link stats leg
/** Structure for holding relevant data for legends in small map */ /** Structure for holding relevant data for legends in small map */
struct LegendAndColour { struct LegendAndColour {
uint8_t colour; ///< Colour of the item on the map. PixelColour colour; ///< Colour of the item on the map.
StringID legend; ///< String corresponding to the coloured item. StringID legend; ///< String corresponding to the coloured item.
IndustryType type; ///< Type of industry. Only valid for industry entries. IndustryType type; ///< Type of industry. Only valid for industry entries.
uint8_t height; ///< Height in tiles. Only valid for height legend entries. uint8_t height; ///< Height in tiles. Only valid for height legend entries.
@ -63,16 +63,16 @@ static const int NUM_NO_COMPANY_ENTRIES = 4; ///< Number of entries in the owner
#define MK(a, b) {a, b, IT_INVALID, 0, CompanyID::Invalid(), true, false, false} #define MK(a, b) {a, b, IT_INVALID, 0, CompanyID::Invalid(), true, false, false}
/** Macro for a height legend entry with configurable colour. */ /** Macro for a height legend entry with configurable colour. */
#define MC(col_break) {0, STR_TINY_BLACK_HEIGHT, IT_INVALID, 0, CompanyID::Invalid(), true, false, col_break} #define MC(col_break) {{}, STR_TINY_BLACK_HEIGHT, IT_INVALID, 0, CompanyID::Invalid(), true, false, col_break}
/** Macro for non-company owned property entry of LegendAndColour */ /** Macro for non-company owned property entry of LegendAndColour */
#define MO(a, b) {a, b, IT_INVALID, 0, CompanyID::Invalid(), true, false, false} #define MO(a, b) {a, b, IT_INVALID, 0, CompanyID::Invalid(), true, false, false}
/** Macro used for forcing a rebuild of the owner legend the first time it is used. */ /** Macro used for forcing a rebuild of the owner legend the first time it is used. */
#define MOEND() {0, STR_NULL, IT_INVALID, 0, OWNER_NONE, true, true, false} #define MOEND() {{}, STR_NULL, IT_INVALID, 0, OWNER_NONE, true, true, false}
/** Macro for end of list marker in arrays of LegendAndColour */ /** Macro for end of list marker in arrays of LegendAndColour */
#define MKEND() {0, STR_NULL, IT_INVALID, 0, CompanyID::Invalid(), true, true, false} #define MKEND() {{}, STR_NULL, IT_INVALID, 0, CompanyID::Invalid(), true, true, false}
/** /**
* Macro for break marker in arrays of LegendAndColour. * Macro for break marker in arrays of LegendAndColour.
@ -149,7 +149,7 @@ static const LegendAndColour _legend_vegetation[] = {
static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = { static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER), MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER),
MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings. MO({}, STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings.
MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS), MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS),
MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES), MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES),
/* The legend will be terminated the first time it is used. */ /* The legend will be terminated the first time it is used. */
@ -258,15 +258,15 @@ static const LegendAndColour * const _legend_table[] = {
#define MKCOLOUR(x) TO_LE32(x) #define MKCOLOUR(x) TO_LE32(x)
#define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x)) #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x.p))
#define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x)) #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x.p))
#define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x)) #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x.p))
#define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y)) #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
#define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00) #define MKCOLOUR_0000 MKCOLOUR_XXXX(PixelColour{0x00})
#define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF) #define MKCOLOUR_F00F MKCOLOUR_X00X(PixelColour{0xFF})
#define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF) #define MKCOLOUR_FFFF MKCOLOUR_XXXX(PixelColour{0xFF})
#include "table/heightmap_colours.h" #include "table/heightmap_colours.h"
@ -279,9 +279,9 @@ struct SmallMapColourScheme {
/** Available colour schemes for height maps. */ /** Available colour schemes for height maps. */
static SmallMapColourScheme _heightmap_schemes[] = { static SmallMapColourScheme _heightmap_schemes[] = {
{{}, _green_map_heights, MKCOLOUR_XXXX(0x54)}, ///< Green colour scheme. {{}, _green_map_heights, MKCOLOUR_XXXX(PixelColour{0x54})}, ///< Green colour scheme.
{{}, _dark_green_map_heights, MKCOLOUR_XXXX(0x62)}, ///< Dark green colour scheme. {{}, _dark_green_map_heights, MKCOLOUR_XXXX(PixelColour{0x62})}, ///< Dark green colour scheme.
{{}, _violet_map_heights, MKCOLOUR_XXXX(0x81)}, ///< Violet colour scheme. {{}, _violet_map_heights, MKCOLOUR_XXXX(PixelColour{0x81})}, ///< Violet colour scheme.
}; };
/** /**
@ -329,7 +329,7 @@ void BuildLandLegend()
_legend_land_contours[i].col_break = j % rows == 0; _legend_land_contours[i].col_break = j % rows == 0;
_legend_land_contours[i].end = false; _legend_land_contours[i].end = false;
_legend_land_contours[i].height = j * delta; _legend_land_contours[i].height = j * delta;
_legend_land_contours[i].colour = static_cast<uint8_t>(_heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[_legend_land_contours[i].height]); _legend_land_contours[i].colour = PixelColour{static_cast<uint8_t>(_heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[_legend_land_contours[i].height])};
j++; j++;
} }
_legend_land_contours[i].end = true; _legend_land_contours[i].end = true;
@ -340,7 +340,7 @@ void BuildLandLegend()
*/ */
void BuildOwnerLegend() void BuildOwnerLegend()
{ {
_legend_land_owners[1].colour = static_cast<uint8_t>(_heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour); _legend_land_owners[1].colour = PixelColour{static_cast<uint8_t>(_heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour)};
int i = NUM_NO_COMPANY_ENTRIES; int i = NUM_NO_COMPANY_ENTRIES;
for (const Company *c : Company::Iterate()) { for (const Company *c : Company::Iterate()) {
@ -607,7 +607,7 @@ uint32_t GetSmallMapOwnerPixels(TileIndex tile, TileType t, IncludeHeightmap inc
} }
/** Vehicle colours in #SMT_VEHICLES mode. Indexed by #VehicleType. */ /** Vehicle colours in #SMT_VEHICLES mode. Indexed by #VehicleType. */
static const uint8_t _vehicle_type_colours[6] = { static const PixelColour _vehicle_type_colours[6] = {
PC_RED, PC_YELLOW, PC_LIGHT_BLUE, PC_WHITE, PC_BLACK, PC_RED PC_RED, PC_YELLOW, PC_LIGHT_BLUE, PC_WHITE, PC_BLACK, PC_RED
}; };
@ -935,7 +935,7 @@ protected:
uint8_t *val8 = (uint8_t *)&val; uint8_t *val8 = (uint8_t *)&val;
int idx = std::max(0, -start_pos); int idx = std::max(0, -start_pos);
for (int pos = std::max(0, start_pos); pos < end_pos; pos++) { for (int pos = std::max(0, start_pos); pos < end_pos; pos++) {
blitter->SetPixel(dst, idx, 0, val8[idx]); blitter->SetPixel(dst, idx, 0, PixelColour{val8[idx]});
idx++; idx++;
} }
/* Switch to next tile in the column */ /* Switch to next tile in the column */
@ -973,7 +973,7 @@ protected:
} }
/* Calculate pointer to pixel and the colour */ /* Calculate pointer to pixel and the colour */
uint8_t colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE; PixelColour colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
/* And draw either one or two pixels depending on clipping */ /* And draw either one or two pixels depending on clipping */
blitter->SetPixel(dpi->dst_ptr, x, y, colour); blitter->SetPixel(dpi->dst_ptr, x, y, colour);
@ -1348,7 +1348,7 @@ protected:
if (type == _smallmap_industry_highlight) { if (type == _smallmap_industry_highlight) {
if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE); if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE);
} else { } else {
return GetIndustrySpec(type)->map_colour * 0x01010101; return GetIndustrySpec(type)->map_colour.p * 0x01010101;
} }
} }
/* Otherwise make it disappear */ /* Otherwise make it disappear */
@ -1644,7 +1644,7 @@ public:
i = 1; i = 1;
} }
uint8_t legend_colour = tbl->colour; PixelColour legend_colour = tbl->colour;
std::array<StringParameter, 2> params{}; std::array<StringParameter, 2> params{};
switch (this->map_type) { switch (this->map_type) {

View File

@ -7,6 +7,7 @@
/** @file station_cmd.cpp Handling of station tiles. */ /** @file station_cmd.cpp Handling of station tiles. */
#include "core/enum_type.hpp"
#include "stdafx.h" #include "stdafx.h"
#include "core/flatset_type.hpp" #include "core/flatset_type.hpp"
#include "aircraft.h" #include "aircraft.h"
@ -949,125 +950,6 @@ static CommandCost CheckFlatLandRailStation(TileIndex tile_cur, TileIndex north_
return cost; return cost;
} }
/**
* Checks if a road stop can be built at the given tile.
* @param cur_tile Tile to check.
* @param allowed_z Height allowed for the tile. If allowed_z is negative, it will be set to the height of this tile.
* @param flags Operation to perform.
* @param invalid_dirs Prohibited directions (set of DiagDirections).
* @param is_drive_through True if trying to build a drive-through station.
* @param station_type Station type (bus, truck or road waypoint).
* @param axis Axis of a drive-through road stop.
* @param station StationID to be queried and returned if available.
* @param rt Road type to build, may be INVALID_ROADTYPE if an existing road is required.
* @return The cost in case of success, or an error code if it failed.
*/
static CommandCost CheckFlatLandRoadStop(TileIndex cur_tile, int &allowed_z, DoCommandFlags flags, DiagDirections invalid_dirs, bool is_drive_through, StationType station_type, Axis axis, StationID *station, RoadType rt)
{
CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
/* If station is set, then we have special handling to allow building on top of already existing stations.
* Station points to StationID::Invalid() if we can build on any station.
* Or it points to a station if we're only allowed to build on exactly that station. */
if (station != nullptr && IsTileType(cur_tile, MP_STATION)) {
if (!IsAnyRoadStop(cur_tile)) {
return ClearTile_Station(cur_tile, DoCommandFlag::Auto); // Get error message.
} else {
if (station_type != GetStationType(cur_tile) ||
is_drive_through != IsDriveThroughStopTile(cur_tile)) {
return ClearTile_Station(cur_tile, DoCommandFlag::Auto); // Get error message.
}
/* Drive-through station in the wrong direction. */
if (is_drive_through && IsDriveThroughStopTile(cur_tile) && GetDriveThroughStopAxis(cur_tile) != axis) {
return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
}
StationID st = GetStationIndex(cur_tile);
if (*station == StationID::Invalid()) {
*station = st;
} else if (*station != st) {
return CommandCost(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
}
}
} else {
bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
/* Road bits in the wrong direction. */
RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE;
if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) {
/* Someone was pedantic and *NEEDED* three fracking different error messages. */
switch (CountBits(rb)) {
case 1:
return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
case 2:
if (rb == ROAD_X || rb == ROAD_Y) return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
return CommandCost(STR_ERROR_DRIVE_THROUGH_CORNER);
default: // 3 or 4
return CommandCost(STR_ERROR_DRIVE_THROUGH_JUNCTION);
}
}
if (build_over_road) {
/* There is a road, check if we can build road+tram stop over it. */
RoadType road_rt = GetRoadType(cur_tile, RTT_ROAD);
if (road_rt != INVALID_ROADTYPE) {
Owner road_owner = GetRoadOwner(cur_tile, RTT_ROAD);
if (road_owner == OWNER_TOWN) {
if (!_settings_game.construction.road_stop_on_town_road) return CommandCost(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
} else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE) {
ret = CheckOwnership(road_owner);
if (ret.Failed()) return ret;
}
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD));
if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD);
if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE && road_owner != OWNER_TOWN) {
ret = CheckOwnership(road_owner);
if (ret.Failed()) return ret;
}
cost.AddCost(RoadBuildCost(road_rt) * (2 - num_pieces));
} else if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt)) {
cost.AddCost(RoadBuildCost(rt) * 2);
}
/* There is a tram, check if we can build road+tram stop over it. */
RoadType tram_rt = GetRoadType(cur_tile, RTT_TRAM);
if (tram_rt != INVALID_ROADTYPE) {
Owner tram_owner = GetRoadOwner(cur_tile, RTT_TRAM);
if (Company::IsValidID(tram_owner) &&
(!_settings_game.construction.road_stop_on_competitor_road ||
/* Disallow breaking end-of-line of someone else
* so trams can still reverse on this tile. */
HasExactlyOneBit(GetRoadBits(cur_tile, RTT_TRAM)))) {
ret = CheckOwnership(tram_owner);
if (ret.Failed()) return ret;
}
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM));
if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD);
cost.AddCost(RoadBuildCost(tram_rt) * (2 - num_pieces));
} else if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt)) {
cost.AddCost(RoadBuildCost(rt) * 2);
}
} else if (rt == INVALID_ROADTYPE) {
return CommandCost(STR_ERROR_THERE_IS_NO_ROAD);
} else {
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, cur_tile);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
cost.AddCost(RoadBuildCost(rt) * 2);
}
}
return cost;
}
/** /**
* Check whether we can expand the rail part of the given station. * Check whether we can expand the rail part of the given station.
@ -1324,6 +1206,230 @@ void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec)
SetStationTileHaveWires(tile, !flags.Test(StationSpec::TileFlag::NoWires)); SetStationTileHaveWires(tile, !flags.Test(StationSpec::TileFlag::NoWires));
} }
CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, uint8_t layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
BridgeType bridge_type, TransportType bridge_transport_type)
{
if (statspec != nullptr && statspec->internal_flags.Test(StationSpecIntlFlag::BridgeHeightsSet)) {
int height_above = statspec->GetBridgeAboveFlags(layout).height;
if (height_above == 0) return CommandCost(INVALID_STRING_ID);
if (GetTileMaxZ(tile) + height_above > bridge_height) {
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
}
} else if (!statspec) {
/* Default stations/waypoints */
const int height = layout < 4 ? 2 : 5;
if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
} else {
return CommandCost(INVALID_STRING_ID);
}
BridgePiecePillarFlags disallowed_pillar_flags;
if (statspec != nullptr && statspec->internal_flags.Test(StationSpecIntlFlag::BridgeDisallowedPillarsSet)) {
/* Pillar flags set by NewGRF */
disallowed_pillar_flags = statspec->GetBridgeAboveFlags(layout).disallowed_pillars;
} else if (!statspec) {
/* Default stations/waypoints */
if (layout < 8) {
static const BridgePiecePillarFlags st_flags[8] = {
{BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_EDGE_NE}, //0x50,
{BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE}, //0xA0,
{BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_EDGE_NE}, //0x50,
{BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE}, //0xA0,
{BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_EDGE_NE, BridgePiecePillarFlag::BPPF_EDGE_SE, BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_S}, //0x50 | 0x26,
{BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE, BridgePiecePillarFlag::BPPF_EDGE_NE, BridgePiecePillarFlag::BPPF_CORNER_N, BridgePiecePillarFlag::BPPF_CORNER_E}, //0xA0 | 0x1C,
{BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE, BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_CORNER_N, BridgePiecePillarFlag::BPPF_CORNER_W}, //0x50 | 0x89,
{BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE, BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_CORNER_S, BridgePiecePillarFlag::BPPF_CORNER_W} //0xA0 | 0x43
};
disallowed_pillar_flags = st_flags[layout];
} else {
disallowed_pillar_flags = {};
}
} else if (GetStationTileFlags(layout, statspec).Test(StationSpec::TileFlag::Blocked)) {
/* Non-track station tiles */
disallowed_pillar_flags = {};
} else {
/* Tracked station tiles */
const Axis axis = HasBit(layout, 0) ? AXIS_Y : AXIS_X;
disallowed_pillar_flags = axis == AXIS_X ? BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_EDGE_NE}) : BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE}); //0x50, 0xA0
}
if (!(GetBridgeTilePillarFlags(tile, northern_bridge_end, southern_bridge_end, bridge_type, bridge_transport_type) & disallowed_pillar_flags).Any()) return CommandCost(STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION);
return CommandCost();
}
CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, uint8_t layout)
{
if (!IsBridgeAbove(tile)) return CommandCost();
TileIndex southern_bridge_end = GetSouthernBridgeEnd(tile);
TileIndex northern_bridge_end = GetNorthernBridgeEnd(tile);
return IsRailStationBridgeAboveOk(tile, statspec, layout, northern_bridge_end, southern_bridge_end, GetBridgeHeight(southern_bridge_end),
GetBridgeType(southern_bridge_end), GetTunnelBridgeTransportType(southern_bridge_end));
}
CommandCost IsRoadStopBridgeAboveOK(TileIndex tile, const RoadStopSpec *spec, bool drive_through, DiagDirection entrance,
TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
BridgeType bridge_type, TransportType bridge_transport_type)
{
if (spec != nullptr && spec->internal_flags.Test(RoadStopSpecIntlFlag::BridgeHeightsSet)) {
int height = spec->bridge_height[drive_through ? (GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + DiagDirToAxis(entrance)) : entrance];
if (height == 0) return CommandCost(INVALID_STRING_ID);
if (GetTileMaxZ(tile) + height > bridge_height) {
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
}
} else {
return CommandCost(INVALID_STRING_ID);
if (GetTileMaxZ(tile) + (drive_through ? 1 : 2) > bridge_height) {
return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION);
}
}
BridgePiecePillarFlags disallowed_pillar_flags = {};
if (spec != nullptr && spec->internal_flags.Test(RoadStopSpecIntlFlag::BridgeDisallowedPillarsSet)) {
disallowed_pillar_flags = spec->bridge_disallowed_pillars[drive_through ? (GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + DiagDirToAxis(entrance)) : entrance];
} else if (drive_through) {
disallowed_pillar_flags = DiagDirToAxis(entrance) == AXIS_X ? BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_EDGE_SW, BridgePiecePillarFlag::BPPF_EDGE_NE}) : BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_EDGE_NW, BridgePiecePillarFlag::BPPF_EDGE_SE}); //0x50, 0xA0
} else {
disallowed_pillar_flags.Set((BridgePiecePillarFlags) (4 + entrance));
}
if (!(GetBridgeTilePillarFlags(tile, northern_bridge_end, southern_bridge_end, bridge_type, bridge_transport_type) & disallowed_pillar_flags).Any()) return CommandCost(STR_ERROR_BRIDGE_PILLARS_OBSTRUCT_STATION);
return CommandCost();
}
/**
* Checks if a road stop can be built at the given tile.
* @param cur_tile Tile to check.
* @param allowed_z Height allowed for the tile. If allowed_z is negative, it will be set to the height of this tile.
* @param flags Operation to perform.
* @param invalid_dirs Prohibited directions (set of DiagDirections).
* @param is_drive_through True if trying to build a drive-through station.
* @param station_type Station type (bus, truck or road waypoint).
* @param axis Axis of a drive-through road stop.
* @param station StationID to be queried and returned if available.
* @param rt Road type to build, may be INVALID_ROADTYPE if an existing road is required.
* @return The cost in case of success, or an error code if it failed.
*/
static CommandCost CheckFlatLandRoadStop(TileIndex cur_tile, int &allowed_z, const RoadStopSpec *spec, DoCommandFlags flags, DiagDirections invalid_dirs, bool is_drive_through, StationType station_type, Axis axis, StationID *station, RoadType rt)
{
CommandCost cost(EXPENSES_CONSTRUCTION);
bool allow_under_bridge = spec != nullptr && spec->internal_flags.Test(RoadStopSpecIntlFlag::BridgeHeightsSet);
CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through, true);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
if (allow_under_bridge && IsBridgeAbove(cur_tile)) {
TileIndex southern_bridge_end = GetSouthernBridgeEnd(cur_tile);
TileIndex northern_bridge_end = GetNorthernBridgeEnd(cur_tile);
CommandCost bridge_ret = IsRoadStopBridgeAboveOK(cur_tile, spec, is_drive_through, DiagDirection::DIAGDIR_NE /*obviously wrong, but how do you get the "first bit" from invalid_dirs? and how would that be correct?? */,
northern_bridge_end, southern_bridge_end, GetBridgeHeight(southern_bridge_end),
GetBridgeType(southern_bridge_end), GetTunnelBridgeTransportType(southern_bridge_end));
if (bridge_ret.Failed()) return bridge_ret;
}
/* If station is set, then we have special handling to allow building on top of already existing stations.
* Station points to StationID::Invalid() if we can build on any station.
* Or it points to a station if we're only allowed to build on exactly that station. */
if (station != nullptr && IsTileType(cur_tile, MP_STATION)) {
if (!IsAnyRoadStop(cur_tile)) {
return ClearTile_Station(cur_tile, DoCommandFlag::Auto); // Get error message.
} else {
if (station_type != GetStationType(cur_tile) ||
is_drive_through != IsDriveThroughStopTile(cur_tile)) {
return ClearTile_Station(cur_tile, DoCommandFlag::Auto); // Get error message.
}
/* Drive-through station in the wrong direction. */
if (is_drive_through && IsDriveThroughStopTile(cur_tile) && GetDriveThroughStopAxis(cur_tile) != axis) {
return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
}
StationID st = GetStationIndex(cur_tile);
if (*station == StationID::Invalid()) {
*station = st;
} else if (*station != st) {
return CommandCost(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
}
}
} else {
bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
/* Road bits in the wrong direction. */
RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE;
if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) {
/* Someone was pedantic and *NEEDED* three fracking different error messages. */
switch (CountBits(rb)) {
case 1:
return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
case 2:
if (rb == ROAD_X || rb == ROAD_Y) return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION);
return CommandCost(STR_ERROR_DRIVE_THROUGH_CORNER);
default: // 3 or 4
return CommandCost(STR_ERROR_DRIVE_THROUGH_JUNCTION);
}
}
if (build_over_road) {
/* There is a road, check if we can build road+tram stop over it. */
RoadType road_rt = GetRoadType(cur_tile, RTT_ROAD);
if (road_rt != INVALID_ROADTYPE) {
Owner road_owner = GetRoadOwner(cur_tile, RTT_ROAD);
if (road_owner == OWNER_TOWN) {
if (!_settings_game.construction.road_stop_on_town_road) return CommandCost(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
} else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE) {
ret = CheckOwnership(road_owner);
if (ret.Failed()) return ret;
}
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD));
if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD);
if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE && road_owner != OWNER_TOWN) {
ret = CheckOwnership(road_owner);
if (ret.Failed()) return ret;
}
cost.AddCost(RoadBuildCost(road_rt) * (2 - num_pieces));
} else if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt)) {
cost.AddCost(RoadBuildCost(rt) * 2);
}
/* There is a tram, check if we can build road+tram stop over it. */
RoadType tram_rt = GetRoadType(cur_tile, RTT_TRAM);
if (tram_rt != INVALID_ROADTYPE) {
Owner tram_owner = GetRoadOwner(cur_tile, RTT_TRAM);
if (Company::IsValidID(tram_owner) &&
(!_settings_game.construction.road_stop_on_competitor_road ||
/* Disallow breaking end-of-line of someone else
* so trams can still reverse on this tile. */
HasExactlyOneBit(GetRoadBits(cur_tile, RTT_TRAM)))) {
ret = CheckOwnership(tram_owner);
if (ret.Failed()) return ret;
}
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM));
if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD);
cost.AddCost(RoadBuildCost(tram_rt) * (2 - num_pieces));
} else if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt)) {
cost.AddCost(RoadBuildCost(rt) * 2);
}
} else if (rt == INVALID_ROADTYPE) {
return CommandCost(STR_ERROR_THERE_IS_NO_ROAD);
} else {
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, cur_tile);
if (ret.Failed()) return ret;
cost.AddCost(ret.GetCost());
cost.AddCost(RoadBuildCost(rt) * 2);
}
}
return cost;
}
/** /**
* Build rail station * Build rail station
* @param flags operation to perform * @param flags operation to perform
@ -1362,6 +1468,9 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy
w_org = numtracks; w_org = numtracks;
} }
/* Check if the first tile and the last tile are valid */
if (!IsValidTile(tile_org) || TileAddWrap(tile_org, w_org - 1, h_org - 1) == INVALID_TILE) return CMD_ERROR;
bool reuse = (station_to_join != NEW_STATION); bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = StationID::Invalid(); if (!reuse) station_to_join = StationID::Invalid();
bool distant_join = (station_to_join != StationID::Invalid()); bool distant_join = (station_to_join != StationID::Invalid());
@ -1376,6 +1485,7 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy
/* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */ /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
StationID est = StationID::Invalid(); StationID est = StationID::Invalid();
std::vector<Train *> affected_vehicles; std::vector<Train *> affected_vehicles;
/* Add construction and clearing expenses. */ /* Add construction and clearing expenses. */
CommandCost cost = CalculateRailStationCost(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks); CommandCost cost = CalculateRailStationCost(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
if (cost.Failed()) return cost; if (cost.Failed()) return cost;
@ -1423,23 +1533,30 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy
st->cached_anim_triggers.Set(statspec->animation.triggers); st->cached_anim_triggers.Set(statspec->animation.triggers);
} }
TileIndexDiff tile_delta = TileOffsByAxis(axis); // offset to go to the next platform tile
TileIndexDiff track_delta = TileOffsByAxis(OtherAxis(axis)); // offset to go to the next track
Track track = AxisToTrack(axis);
std::vector<uint8_t> layouts(numtracks * plat_len); std::vector<uint8_t> layouts(numtracks * plat_len);
GetStationLayout(layouts.data(), numtracks, plat_len, statspec); GetStationLayout(layouts.data(), numtracks, plat_len, statspec);
TileIndexDiff tile_delta = TileOffsByAxis(axis); // offset to go to the next platform tile
TileIndexDiff track_delta = TileOffsByAxis(OtherAxis(axis)); // offset to go to the next track
Track track = AxisToTrack(axis);
uint8_t numtracks_orig = numtracks; uint8_t numtracks_orig = numtracks;
Company *c = Company::Get(st->owner); Company *c = Company::Get(st->owner);
size_t layout_idx = 0; size_t layout_idx = 0;
TileIndex tile_track = tile_org; TileIndex tile_track = tile_org;
do { do {
TileIndex tile = tile_track; TileIndex tile = tile_track;
int w = plat_len; int w = plat_len;
do { do {
uint8_t layout = layouts[layout_idx++]; uint8_t layout = layouts[layout_idx++];
ret = IsRailStationBridgeAboveOk(tile, statspec, layout);
if (ret.Failed()) {
//return CommandCost::DualErrorMessage(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST, ret.GetErrorMessage()); //FIXME
return ret;
}
if (IsRailStationTile(tile) && HasStationReservation(tile)) { if (IsRailStationTile(tile) && HasStationReservation(tile)) {
/* Check for trains having a reservation for this tile. */ /* Check for trains having a reservation for this tile. */
Train *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile))); Train *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile)));
@ -1913,7 +2030,7 @@ static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID statio
* @param unit_cost The cost to build one road stop of the current type. * @param unit_cost The cost to build one road stop of the current type.
* @return The cost in case of success, or an error code if it failed. * @return The cost in case of success, or an error code if it failed.
*/ */
CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost) CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, const RoadStopSpec *roadstopspec, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost)
{ {
DiagDirections invalid_dirs{}; DiagDirections invalid_dirs{};
if (is_drive_through) { if (is_drive_through) {
@ -1927,7 +2044,7 @@ CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool
int allowed_z = -1; int allowed_z = -1;
CommandCost cost(EXPENSES_CONSTRUCTION); CommandCost cost(EXPENSES_CONSTRUCTION);
for (TileIndex cur_tile : tile_area) { for (TileIndex cur_tile : tile_area) {
CommandCost ret = CheckFlatLandRoadStop(cur_tile, allowed_z, flags, invalid_dirs, is_drive_through, station_type, axis, est, rt); CommandCost ret = CheckFlatLandRoadStop(cur_tile, allowed_z, roadstopspec, flags, invalid_dirs, is_drive_through, station_type, axis, est, rt);
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
bool is_preexisting_roadstop = IsTileType(cur_tile, MP_STATION) && IsAnyRoadStop(cur_tile); bool is_preexisting_roadstop = IsTileType(cur_tile, MP_STATION) && IsAnyRoadStop(cur_tile);
@ -2008,7 +2125,7 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width
unit_cost = _price[is_truck_stop ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]; unit_cost = _price[is_truck_stop ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS];
} }
StationID est = StationID::Invalid(); StationID est = StationID::Invalid();
CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, is_drive_through, is_truck_stop ? StationType::Truck : StationType::Bus, axis, ddir, &est, rt, unit_cost); CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, is_drive_through, is_truck_stop ? StationType::Truck : StationType::Bus, roadstopspec, axis, ddir, &est, rt, unit_cost);
if (cost.Failed()) return cost; if (cost.Failed()) return cost;
Station *st = nullptr; Station *st = nullptr;
@ -3380,6 +3497,7 @@ draw_default_foundation:
} }
DrawRailTileSeq(ti, t, TO_BUILDINGS, total_offset, relocation, palette); DrawRailTileSeq(ti, t, TO_BUILDINGS, total_offset, relocation, palette);
DrawBridgeMiddle(ti);
} }
void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image) void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
@ -5079,7 +5197,7 @@ StationIDStack FlowStatMap::DeleteFlows(StationID via)
FlowStat &s_flows = f_it->second; FlowStat &s_flows = f_it->second;
s_flows.ChangeShare(via, INT_MIN); s_flows.ChangeShare(via, INT_MIN);
if (s_flows.GetShares()->empty()) { if (s_flows.GetShares()->empty()) {
ret.Push(f_it->first.base()); ret.Push(f_it->first);
this->erase(f_it++); this->erase(f_it++);
} else { } else {
++f_it; ++f_it;

View File

@ -225,7 +225,7 @@ static void StationsWndShowStationRating(int left, int right, int y, CargoType c
int padding = ScaleGUITrad(1); int padding = ScaleGUITrad(1);
int width = right - left; int width = right - left;
int colour = cs->rating_colour; PixelColour colour = cs->rating_colour;
TextColour tc = GetContrastColour(colour); TextColour tc = GetContrastColour(colour);
uint w = std::min(amount + 5, units_full) * width / units_full; uint w = std::min(amount + 5, units_full) * width / units_full;

View File

@ -26,7 +26,7 @@ struct RoadStop;
struct StationSpec; struct StationSpec;
struct Waypoint; struct Waypoint;
using StationIDStack = SmallStack<StationID::BaseType, StationID::BaseType, StationID::Invalid().base(), 8, StationID::End().base()>; using StationIDStack = SmallStack<StationID, StationID::BaseType, StationID::Invalid().base(), 8, StationID::End().base()>;
/** Station types */ /** Station types */
enum class StationType : uint8_t { enum class StationType : uint8_t {

View File

@ -740,8 +740,53 @@ static const std::span<const std::span<const PalSpriteID>> _bridge_sprite_table[
* @param nrl description of the rail bridge in query tool * @param nrl description of the rail bridge in query tool
* @param nrd description of the road bridge in query tool * @param nrd description of the road bridge in query tool
*/ */
#define MBR(y, mnl, mxl, p, mxs, spr, plt, dsc, nrl, nrd) \ #define MBR(y, mnl, mxl, p, mxs, spr, plt, dsc, nrl, nrd, pillars) \
{TimerGameCalendar::Year{y}, mnl, mxl, p, mxs, spr, plt, dsc, { nrl, nrd }, {}, 0} {TimerGameCalendar::Year{y}, mnl, mxl, p, mxs, spr, plt, dsc, { nrl, nrd }, {}, 0, BridgeSpecCtrlFlags(), pillars}
static constexpr std::array<BridgePiecePillarFlags, 12> all_pillars = {
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F,
BridgePiecePillarFlag::BPPF_ALL_CORNERS, //0x0F
};
static constexpr std::array<BridgePiecePillarFlags, 12> susp_pillars = {
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_S}), //0x03,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_S, BridgePiecePillarFlag::BPPF_CORNER_E}), //0x06,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_S}), //0x03,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_S, BridgePiecePillarFlag::BPPF_CORNER_E}), //0x06,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_ALL_CORNERS}), //0x0F,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_ALL_CORNERS}), //0x0F,
BridgePiecePillarFlags({BridgePiecePillarFlag()}), //0x00,
BridgePiecePillarFlags({BridgePiecePillarFlag()}), //0x00
};
static constexpr std::array<BridgePiecePillarFlags, 12> cant_pillars = {
BridgePiecePillarFlags({BridgePiecePillarFlag()}), //0x00,
BridgePiecePillarFlags({BridgePiecePillarFlag()}), //0x00,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_E, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x0C,
BridgePiecePillarFlags({BridgePiecePillarFlag::BPPF_CORNER_W, BridgePiecePillarFlag::BPPF_CORNER_N}), //0x09
};
const BridgeSpec _orig_bridge[] = { const BridgeSpec _orig_bridge[] = {
/* /*
@ -755,43 +800,43 @@ const BridgeSpec _orig_bridge[] = {
string with description name on rail name on road string with description name on rail name on road
| | | | */ | | | | */
MBR( 0, 0, 0xFFFF, 80, 32, 0xA24, PAL_NONE, MBR( 0, 0, 0xFFFF, 80, 32, 0xA24, PAL_NONE,
STR_BRIDGE_NAME_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_RAIL_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_ROAD_WOODEN), STR_BRIDGE_NAME_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_RAIL_WOODEN, STR_LAI_BRIDGE_DESCRIPTION_ROAD_WOODEN, all_pillars),
MBR( 0, 0, 2, 112, 48, 0xA26, PALETTE_TO_STRUCT_RED, MBR( 0, 0, 2, 112, 48, 0xA26, PALETTE_TO_STRUCT_RED,
STR_BRIDGE_NAME_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CONCRETE), STR_BRIDGE_NAME_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CONCRETE, all_pillars),
MBR(1930, 0, 5, 144, 64, 0xA25, PAL_NONE, MBR(1930, 0, 5, 144, 64, 0xA25, PAL_NONE,
STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL), STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL, all_pillars),
MBR( 0, 2, 10, 168, 80, 0xA22, PALETTE_TO_STRUCT_CONCRETE, MBR( 0, 2, 10, 168, 80, 0xA22, PALETTE_TO_STRUCT_CONCRETE,
STR_BRIDGE_NAME_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_CONCRETE), STR_BRIDGE_NAME_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_CONCRETE, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_CONCRETE, susp_pillars),
MBR(1930, 3, 0xFFFF, 185, 96, 0xA22, PAL_NONE, MBR(1930, 3, 0xFFFF, 185, 96, 0xA22, PAL_NONE,
STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL), STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL, susp_pillars),
MBR(1930, 3, 0xFFFF, 192, 112, 0xA22, PALETTE_TO_STRUCT_YELLOW, MBR(1930, 3, 0xFFFF, 192, 112, 0xA22, PALETTE_TO_STRUCT_YELLOW,
STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL), STR_BRIDGE_NAME_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_SUSPENSION_STEEL, susp_pillars),
MBR(1930, 3, 7, 224, 160, 0xA23, PAL_NONE, MBR(1930, 3, 7, 224, 160, 0xA23, PAL_NONE,
STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL), STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, cant_pillars),
MBR(1930, 3, 8, 232, 208, 0xA23, PALETTE_TO_STRUCT_BROWN, MBR(1930, 3, 8, 232, 208, 0xA23, PALETTE_TO_STRUCT_BROWN,
STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL), STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, cant_pillars),
MBR(1930, 3, 9, 248, 240, 0xA23, PALETTE_TO_STRUCT_RED, MBR(1930, 3, 9, 248, 240, 0xA23, PALETTE_TO_STRUCT_RED,
STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL), STR_BRIDGE_NAME_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_CANTILEVER_STEEL, cant_pillars),
MBR(1930, 0, 2, 240, 256, 0xA27, PAL_NONE, MBR(1930, 0, 2, 240, 256, 0xA27, PAL_NONE,
STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL), STR_BRIDGE_NAME_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_GIRDER_STEEL, all_pillars),
MBR(1995, 2, 0xFFFF, 255, 320, 0xA28, PAL_NONE, MBR(1995, 2, 0xFFFF, 255, 320, 0xA28, PAL_NONE,
STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL), STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, cant_pillars),
MBR(2005, 2, 0xFFFF, 380, 512, 0xA28, PALETTE_TO_STRUCT_YELLOW, MBR(2005, 2, 0xFFFF, 380, 512, 0xA28, PALETTE_TO_STRUCT_YELLOW,
STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL), STR_BRIDGE_NAME_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, cant_pillars),
MBR(2010, 2, 0xFFFF, 510, 608, 0xA28, PALETTE_TO_STRUCT_CONCRETE, MBR(2010, 2, 0xFFFF, 510, 608, 0xA28, PALETTE_TO_STRUCT_CONCRETE,
STR_BRIDGE_TUBULAR_SILICON, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL) STR_BRIDGE_TUBULAR_SILICON, STR_LAI_BRIDGE_DESCRIPTION_RAIL_TUBULAR_STEEL, STR_LAI_BRIDGE_DESCRIPTION_ROAD_TUBULAR_STEEL, cant_pillars)
}; };
#undef MBR #undef MBR

View File

@ -1134,7 +1134,7 @@ enum IndustryTypes : uint8_t {
{r1, r2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, m, \ {r1, r2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, m, \
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \ {INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
{{im1, 0}, {im2, 0}, {im3, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, \ {{im1, 0}, {im2, 0}, {im3, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, \
pr, clim, bev, col, in, intx, s1, s2, s3, STR_UNDEFINED, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, \ pr, clim, bev, PixelColour{col}, in, intx, s1, s2, s3, STR_UNDEFINED, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, \
IndustryCallbackMasks{}, true, SubstituteGRFFileProps(IT_INVALID), snd, {}, \ IndustryCallbackMasks{}, true, SubstituteGRFFileProps(IT_INVALID), snd, {}, \
{{p1, p2}}, {{a1, a2, a3}}} {{p1, p2}}, {{a1, a2, a3}}}
/* Format: /* Format:

View File

@ -49,7 +49,7 @@
* @param classes Classes of this cargo type. @see CargoClass * @param classes Classes of this cargo type. @see CargoClass
*/ */
#define MK(bt, label, colour, weight, mult, ip, td1, td2, freight, tae, str_plural, str_singular, str_volume, classes) \ #define MK(bt, label, colour, weight, mult, ip, td1, td2, freight, tae, str_plural, str_singular, str_volume, classes) \
{label, bt, colour, colour, weight, mult, classes, ip, {td1, td2}, freight, tae, INVALID_TPE, TOWN_PRODUCTION_DIVISOR, CargoCallbackMasks{}, \ {label, bt, PixelColour{colour}, PixelColour{colour}, weight, mult, classes, ip, {td1, td2}, freight, tae, INVALID_TPE, TOWN_PRODUCTION_DIVISOR, CargoCallbackMasks{}, \
MK_STR_CARGO_PLURAL(str_plural), MK_STR_CARGO_SINGULAR(str_singular), str_volume, MK_STR_QUANTITY(str_plural), MK_STR_ABBREV(str_plural), \ MK_STR_CARGO_PLURAL(str_plural), MK_STR_CARGO_SINGULAR(str_singular), str_volume, MK_STR_QUANTITY(str_plural), MK_STR_ABBREV(str_plural), \
MK_SPRITE(str_plural), nullptr, nullptr, 0} MK_SPRITE(str_plural), nullptr, nullptr, 0}

View File

@ -98,7 +98,7 @@ static const RailTypeInfo _original_railtypes[] = {
RailTypeLabelList(), RailTypeLabelList(),
/* map colour */ /* map colour */
0x0A, PC_GREY,
/* introduction date */ /* introduction date */
CalendarTime::INVALID_DATE, CalendarTime::INVALID_DATE,
@ -200,7 +200,7 @@ static const RailTypeInfo _original_railtypes[] = {
RailTypeLabelList(), RailTypeLabelList(),
/* map colour */ /* map colour */
0x0A, PC_GREY,
/* introduction date */ /* introduction date */
CalendarTime::INVALID_DATE, CalendarTime::INVALID_DATE,
@ -298,7 +298,7 @@ static const RailTypeInfo _original_railtypes[] = {
RailTypeLabelList(), RailTypeLabelList(),
/* map colour */ /* map colour */
0x0A, PC_GREY,
/* introduction date */ /* introduction date */
CalendarTime::INVALID_DATE, CalendarTime::INVALID_DATE,
@ -396,7 +396,7 @@ static const RailTypeInfo _original_railtypes[] = {
RailTypeLabelList(), RailTypeLabelList(),
/* map colour */ /* map colour */
0x0A, PC_GREY,
/* introduction date */ /* introduction date */
CalendarTime::INVALID_DATE, CalendarTime::INVALID_DATE,

View File

@ -81,7 +81,7 @@ static const RoadTypeInfo _original_roadtypes[] = {
RoadTypeLabelList(), RoadTypeLabelList(),
/* map colour */ /* map colour */
0x01, PC_BLACK,
/* introduction date */ /* introduction date */
CalendarTime::MIN_DATE, CalendarTime::MIN_DATE,
@ -162,7 +162,7 @@ static const RoadTypeInfo _original_roadtypes[] = {
RoadTypeLabelList(), RoadTypeLabelList(),
/* map colour */ /* map colour */
0x01, PC_BLACK,
/* introduction date */ /* introduction date */
CalendarTime::INVALID_DATE, CalendarTime::INVALID_DATE,

View File

@ -8,22 +8,22 @@
/** @file string_colours.h The colour translation of GRF's strings. */ /** @file string_colours.h The colour translation of GRF's strings. */
/** Colour mapping for #TextColour. */ /** Colour mapping for #TextColour. */
static const uint8_t _string_colourmap[17] = { static constexpr PixelColour _string_colourmap[17] = {
150, // TC_BLUE PixelColour{150}, // TC_BLUE
12, // TC_SILVER PixelColour{ 12}, // TC_SILVER
189, // TC_GOLD PixelColour{189}, // TC_GOLD
184, // TC_RED PixelColour{184}, // TC_RED
174, // TC_PURPLE PixelColour{174}, // TC_PURPLE
30, // TC_LIGHT_BROWN PixelColour{ 30}, // TC_LIGHT_BROWN
195, // TC_ORANGE PixelColour{195}, // TC_ORANGE
209, // TC_GREEN PixelColour{209}, // TC_GREEN
68, // TC_YELLOW PixelColour{ 68}, // TC_YELLOW
95, // TC_DARK_GREEN PixelColour{ 95}, // TC_DARK_GREEN
79, // TC_CREAM PixelColour{ 79}, // TC_CREAM
116, // TC_BROWN PixelColour{116}, // TC_BROWN
15, // TC_WHITE PixelColour{ 15}, // TC_WHITE
152, // TC_LIGHT_BLUE PixelColour{152}, // TC_LIGHT_BLUE
6, // TC_GREY PixelColour{ 6}, // TC_GREY
133, // TC_DARK_BLUE PixelColour{133}, // TC_DARK_BLUE
1, // TC_BLACK PixelColour{ 1}, // TC_BLACK
}; };

View File

@ -21,8 +21,6 @@ public:
this->height = FontCache::GetDefaultFontHeight(this->fs); this->height = FontCache::GetDefaultFontHeight(this->fs);
} }
void SetUnicodeGlyph(char32_t, SpriteID) override {}
void InitializeUnicodeGlyphMap() override {}
void ClearFontCache() override {} void ClearFontCache() override {}
const Sprite *GetGlyph(GlyphID) override { return nullptr; } const Sprite *GetGlyph(GlyphID) override { return nullptr; }
uint GetGlyphWidth(GlyphID) override { return this->height / 2; } uint GetGlyphWidth(GlyphID) override { return this->height / 2; }

View File

@ -39,10 +39,13 @@
#include "object_base.h" #include "object_base.h"
#include "water.h" #include "water.h"
#include "company_gui.h" #include "company_gui.h"
#include "newgrf_roadstop.h"
#include "station_func.h" #include "station_func.h"
#include "station_map.h"
#include "tunnelbridge_cmd.h" #include "tunnelbridge_cmd.h"
#include "landscape_cmd.h" #include "landscape_cmd.h"
#include "terraform_cmd.h" #include "terraform_cmd.h"
#include "newgrf_station.h"
#include "table/strings.h" #include "table/strings.h"
#include "table/bridge_land.h" #include "table/bridge_land.h"
@ -55,6 +58,12 @@ TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from
/** Z position of the bridge sprites relative to bridge height (downwards) */ /** Z position of the bridge sprites relative to bridge height (downwards) */
static const int BRIDGE_Z_START = 3; static const int BRIDGE_Z_START = 3;
extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, uint8_t layout, TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
BridgeType bridge_type, TransportType bridge_transport_type);
extern CommandCost IsRoadStopBridgeAboveOK(TileIndex tile, const RoadStopSpec *spec, bool drive_through, DiagDirection entrance,
TileIndex northern_bridge_end, TileIndex southern_bridge_end, int bridge_height,
BridgeType bridge_type, TransportType bridge_transport_type);
/** /**
* Mark bridge tiles dirty. * Mark bridge tiles dirty.
@ -391,6 +400,43 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
/* If bridge belonged to bankrupt company, it has a new owner now */ /* If bridge belonged to bankrupt company, it has a new owner now */
is_new_owner = (owner == OWNER_NONE); is_new_owner = (owner == OWNER_NONE);
if (is_new_owner) owner = company; if (is_new_owner) owner = company;
TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
if (!IsTileType(tile, MP_STATION)) continue;
switch (GetStationType(tile)) {
case StationType::Rail:
case StationType::RailWaypoint: {
CommandCost ret = IsRailStationBridgeAboveOk(tile, GetStationSpec(tile), GetStationGfx(tile), tile_start, tile_end, z_start + 1, bridge_type, transport_type);
if (ret.Failed()) {
if (ret.GetErrorMessage() != INVALID_STRING_ID) return ret;
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
if (ret.Failed()) return ret;
}
break;
}
case StationType::Bus:
case StationType::Truck:
case StationType::RoadWaypoint: {
CommandCost ret = IsRoadStopBridgeAboveOK(tile, GetRoadStopSpec(tile), IsDriveThroughStopTile(tile), IsDriveThroughStopTile(tile) ? AxisToDiagDir(GetDriveThroughStopAxis(tile)) : GetBayRoadStopDir(tile),
tile_start, tile_end, z_start + 1, bridge_type, transport_type);
if (ret.Failed()) {
if (ret.GetErrorMessage() != INVALID_STRING_ID) return ret;
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
if (ret.Failed()) return ret;
}
break;
}
case StationType::Buoy:
/* Buoys are always allowed */
break;
default:
break;
}
}
} else { } else {
/* Build a new bridge. */ /* Build a new bridge. */
@ -467,6 +513,45 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
break; break;
} }
case MP_STATION: {
switch (GetStationType(tile)) {
case StationType::Airport:
goto not_valid_below;
case StationType::Rail:
case StationType::RailWaypoint: {
CommandCost ret = IsRailStationBridgeAboveOk(tile, GetStationSpec(tile), GetStationGfx(tile), tile_start, tile_end, z_start + 1, bridge_type, transport_type);
if (ret.Failed()) {
if (ret.GetErrorMessage() != INVALID_STRING_ID) return ret;
goto not_valid_below;
}
break;
}
case StationType::Bus:
case StationType::Truck:
case StationType::RoadWaypoint: {
CommandCost ret = IsRoadStopBridgeAboveOK(tile, GetRoadStopSpec(tile), IsDriveThroughStopTile(tile), IsDriveThroughStopTile(tile) ? AxisToDiagDir(GetDriveThroughStopAxis(tile)) : GetBayRoadStopDir(tile),
tile_start, tile_end, z_start + 1, bridge_type, transport_type);
if (ret.Failed()) {
if (ret.GetErrorMessage() != INVALID_STRING_ID) return ret;
goto not_valid_below;
}
break;
}
case StationType::Buoy:
/* Buoys are always allowed */
break;
default:
//if (!(GetStationType(tile) == StationType::Dock && _settings_game.construction.allow_docks_under_bridges)) goto not_valid_below;
break;
}
break;
}
case MP_CLEAR: case MP_CLEAR:
break; break;
@ -1517,6 +1602,49 @@ static BridgePieces CalcBridgePiece(uint north, uint south)
} }
} }
BridgePiecePillarFlags GetBridgeTilePillarFlags(TileIndex tile, TileIndex northern_bridge_end, TileIndex southern_bridge_end, BridgeType bridge_type, TransportType bridge_transport_type)
{
if (bridge_transport_type == TRANSPORT_WATER) return BridgePiecePillarFlag::BPPF_ALL_CORNERS;
BridgePieces piece = CalcBridgePiece(
GetTunnelBridgeLength(tile, northern_bridge_end) + 1,
GetTunnelBridgeLength(tile, southern_bridge_end) + 1
);
assert(piece < BRIDGE_PIECE_HEAD);
const BridgeSpec *spec = GetBridgeSpec(bridge_type);
const Axis axis = TileX(northern_bridge_end) == TileX(southern_bridge_end) ? AXIS_Y : AXIS_X;
if (!spec->ctrl_flags.Test(BridgeSpecCtrlFlag::BSCF_INVALID_PILLAR_FLAGS)) {
return spec->pillar_flags[piece * 2 + (axis == AXIS_Y ? 1 : 0)];
} else {
uint base_offset;
if (bridge_transport_type == TRANSPORT_RAIL) {
base_offset = GetRailTypeInfo(GetRailType(southern_bridge_end))->bridge_offset;
} else {
base_offset = 8;
}
const PalSpriteID *psid = &GetBridgeSpriteTable(bridge_type, piece)[base_offset];
if (axis == AXIS_Y) psid += 4;
return psid[2].sprite != 0 ? BridgePiecePillarFlag::BPPF_ALL_CORNERS : BridgePiecePillarFlags();
}
}
BridgePieceDebugInfo GetBridgePieceDebugInfo(TileIndex tile)
{
TileIndex rampnorth = GetNorthernBridgeEnd(tile);
TileIndex rampsouth = GetSouthernBridgeEnd(tile);
BridgePieces piece = CalcBridgePiece(
GetTunnelBridgeLength(tile, rampnorth) + 1,
GetTunnelBridgeLength(tile, rampsouth) + 1
);
BridgePiecePillarFlags pillar_flags = GetBridgeTilePillarFlags(tile, rampnorth, rampsouth, GetBridgeType(rampnorth), GetTunnelBridgeTransportType(rampnorth));
const Axis axis = TileX(rampnorth) == TileX(rampsouth) ? AXIS_Y : AXIS_X;
uint pillar_index = piece * 2 + (axis == AXIS_Y ? 1 : 0);
return { piece, pillar_flags, pillar_index };
}
/** /**
* Draw the middle bits of a bridge. * Draw the middle bits of a bridge.
* @param ti Tile information of the tile to draw it on. * @param ti Tile information of the tile to draw it on.

View File

@ -741,7 +741,7 @@ public:
*/ */
inline StationIDStack GetNextStoppingStation() const inline StationIDStack GetNextStoppingStation() const
{ {
return (this->orders == nullptr) ? StationID::Invalid().base() : this->orders->GetNextStoppingStation(this); return (this->orders == nullptr) ? StationID::Invalid() : this->orders->GetNextStoppingStation(this);
} }
void ResetRefitCaps(); void ResetRefitCaps();

View File

@ -697,7 +697,7 @@ static void DrawVehicleRefitWindow(const RefitOptions &refits, const RefitOption
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
uint iconwidth = std::max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width); uint iconwidth = std::max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width);
uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height; uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); PixelColour linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
int iconleft = rtl ? ir.right - iconwidth : ir.left; int iconleft = rtl ? ir.right - iconwidth : ir.left;
int iconcenter = rtl ? ir.right - iconwidth / 2 : ir.left + iconwidth / 2; int iconcenter = rtl ? ir.right - iconwidth / 2 : ir.left + iconwidth / 2;

View File

@ -1732,13 +1732,13 @@ static void ViewportDrawDirtyBlocks()
int right = UnScaleByZoom(dpi->width, dpi->zoom); int right = UnScaleByZoom(dpi->width, dpi->zoom);
int bottom = UnScaleByZoom(dpi->height, dpi->zoom); int bottom = UnScaleByZoom(dpi->height, dpi->zoom);
int colour = _string_colourmap[_dirty_block_colour & 0xF]; PixelColour colour = _string_colourmap[_dirty_block_colour & 0xF];
dst = dpi->dst_ptr; dst = dpi->dst_ptr;
uint8_t bo = UnScaleByZoom(dpi->left + dpi->top, dpi->zoom) & 1; uint8_t bo = UnScaleByZoom(dpi->left + dpi->top, dpi->zoom) & 1;
do { do {
for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, (uint8_t)colour); for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, colour);
dst = blitter->MoveTo(dst, 0, 1); dst = blitter->MoveTo(dst, 0, 1);
} while (--bottom > 0); } while (--bottom > 0);
} }
@ -1761,7 +1761,7 @@ static void ViewportDrawStrings(ZoomLevel zoom, const StringSpriteToDrawVector *
} }
if (ss.flags.Test(ViewportStringFlag::TextColour)) { if (ss.flags.Test(ViewportStringFlag::TextColour)) {
if (ss.colour != INVALID_COLOUR) colour = static_cast<TextColour>(GetColourGradient(ss.colour, SHADE_LIGHTER) | TC_IS_PALETTE_COLOUR); if (ss.colour != INVALID_COLOUR) colour = GetColourGradient(ss.colour, SHADE_LIGHTER).ToTextColour();
} }
int left = x + WidgetDimensions::scaled.fullbevel.left; int left = x + WidgetDimensions::scaled.fullbevel.left;

View File

@ -182,7 +182,9 @@ static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *
extern void GetStationLayout(uint8_t *layout, uint numtracks, uint plat_len, const StationSpec *statspec); extern void GetStationLayout(uint8_t *layout, uint numtracks, uint plat_len, const StationSpec *statspec);
extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road); extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road);
extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta); extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta);
extern CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost); extern CommandCost CalculateRoadStopCost(TileArea tile_area, DoCommandFlags flags, bool is_drive_through, StationType station_type, const RoadStopSpec *roadstopspec, Axis axis, DiagDirection ddir, StationID *est, RoadType rt, Money unit_cost);
extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, uint8_t layout);
extern CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int replacement_spec_index); extern CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int replacement_spec_index);
/** /**
@ -220,6 +222,17 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi
if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR; if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
const StationSpec *spec = StationClass::Get(spec_class)->GetSpec(spec_index);
std::vector<uint8_t> layout_ptr;
layout_ptr.resize(count);
if (spec == nullptr) {
/* The layout must be 0 for the 'normal' waypoints by design. */
//memset(layout_ptr, 0, count); //FIXME
} else {
/* But for NewGRF waypoints we like to have their style. */
GetStationLayout(&layout_ptr[0], count, 1, spec);
}
TileArea new_location(start_tile, width, height); TileArea new_location(start_tile, width, height);
/* only AddCost for non-existing waypoints */ /* only AddCost for non-existing waypoints */
@ -237,6 +250,10 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi
TileIndex tile = start_tile + i * offset; TileIndex tile = start_tile + i * offset;
CommandCost ret = IsValidTileForWaypoint(tile, axis, &est); CommandCost ret = IsValidTileForWaypoint(tile, axis, &est);
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
ret = IsRailStationBridgeAboveOk(tile, spec, layout_ptr[i]);
if (ret.Failed()) {
return ret;
}
} }
Waypoint *wp = nullptr; Waypoint *wp = nullptr;
@ -364,7 +381,7 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi
unit_cost = _price[PR_BUILD_STATION_TRUCK]; unit_cost = _price[PR_BUILD_STATION_TRUCK];
} }
StationID est = StationID::Invalid(); StationID est = StationID::Invalid();
CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, true, StationType::RoadWaypoint, axis, AxisToDiagDir(axis), &est, INVALID_ROADTYPE, unit_cost); CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, true, StationType::RoadWaypoint, roadstopspec, axis, AxisToDiagDir(axis), &est, INVALID_ROADTYPE, unit_cost);
if (cost.Failed()) return cost; if (cost.Failed()) return cost;
Waypoint *wp = nullptr; Waypoint *wp = nullptr;

View File

@ -302,11 +302,11 @@ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, Fra
} else { } else {
assert(colour < COLOUR_END); assert(colour < COLOUR_END);
const uint dark = GetColourGradient(colour, SHADE_DARK); const PixelColour dark = GetColourGradient(colour, SHADE_DARK);
const uint medium_dark = GetColourGradient(colour, SHADE_LIGHT); const PixelColour medium_dark = GetColourGradient(colour, SHADE_LIGHT);
const uint medium_light = GetColourGradient(colour, SHADE_LIGHTER); const PixelColour medium_light = GetColourGradient(colour, SHADE_LIGHTER);
const uint light = GetColourGradient(colour, SHADE_LIGHTEST); const PixelColour light = GetColourGradient(colour, SHADE_LIGHTEST);
uint interior; PixelColour interior;
Rect outer = {left, top, right, bottom}; // Outside rectangle Rect outer = {left, top, right, bottom}; // Outside rectangle
Rect inner = outer.Shrink(WidgetDimensions::scaled.bevel); // Inside rectangle Rect inner = outer.Shrink(WidgetDimensions::scaled.bevel); // Inside rectangle
@ -469,7 +469,7 @@ static inline void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint3
row_height = r.Height() / num_rows; row_height = r.Height() / num_rows;
} }
int col = GetColourGradient(colour, SHADE_LIGHTER); PixelColour col = GetColourGradient(colour, SHADE_LIGHTER);
int x = r.left; int x = r.left;
for (int ctr = num_columns; ctr > 1; ctr--) { for (int ctr = num_columns; ctr > 1; ctr--) {
@ -515,8 +515,8 @@ static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_
DrawImageButtons(r.WithHeight(height, false), NWID_VSCROLLBAR, colour, up_clicked, SPR_ARROW_UP, SA_CENTER); DrawImageButtons(r.WithHeight(height, false), NWID_VSCROLLBAR, colour, up_clicked, SPR_ARROW_UP, SA_CENTER);
DrawImageButtons(r.WithHeight(height, true), NWID_VSCROLLBAR, colour, down_clicked, SPR_ARROW_DOWN, SA_CENTER); DrawImageButtons(r.WithHeight(height, true), NWID_VSCROLLBAR, colour, down_clicked, SPR_ARROW_DOWN, SA_CENTER);
int c1 = GetColourGradient(colour, SHADE_DARK); PixelColour c1 = GetColourGradient(colour, SHADE_DARK);
int c2 = GetColourGradient(colour, SHADE_LIGHTEST); PixelColour c2 = GetColourGradient(colour, SHADE_LIGHTEST);
/* draw "shaded" background */ /* draw "shaded" background */
GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2); GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2);
@ -554,8 +554,8 @@ static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool l
DrawImageButtons(r.WithWidth(width, false), NWID_HSCROLLBAR, colour, left_clicked, SPR_ARROW_LEFT, SA_CENTER); DrawImageButtons(r.WithWidth(width, false), NWID_HSCROLLBAR, colour, left_clicked, SPR_ARROW_LEFT, SA_CENTER);
DrawImageButtons(r.WithWidth(width, true), NWID_HSCROLLBAR, colour, right_clicked, SPR_ARROW_RIGHT, SA_CENTER); DrawImageButtons(r.WithWidth(width, true), NWID_HSCROLLBAR, colour, right_clicked, SPR_ARROW_RIGHT, SA_CENTER);
int c1 = GetColourGradient(colour, SHADE_DARK); PixelColour c1 = GetColourGradient(colour, SHADE_DARK);
int c2 = GetColourGradient(colour, SHADE_LIGHTEST); PixelColour c2 = GetColourGradient(colour, SHADE_LIGHTEST);
/* draw "shaded" background */ /* draw "shaded" background */
GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2); GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2);
@ -593,8 +593,8 @@ static inline void DrawFrame(const Rect &r, Colours colour, TextColour text_colo
if (!str.empty()) x2 = DrawString(r.left + WidgetDimensions::scaled.frametext.left, r.right - WidgetDimensions::scaled.frametext.right, r.top, str, text_colour, align, false, fs); if (!str.empty()) x2 = DrawString(r.left + WidgetDimensions::scaled.frametext.left, r.right - WidgetDimensions::scaled.frametext.right, r.top, str, text_colour, align, false, fs);
int c1 = GetColourGradient(colour, SHADE_DARK); PixelColour c1 = GetColourGradient(colour, SHADE_DARK);
int c2 = GetColourGradient(colour, SHADE_LIGHTEST); PixelColour c2 = GetColourGradient(colour, SHADE_LIGHTEST);
/* If the frame has text, adjust the top bar to fit half-way through */ /* If the frame has text, adjust the top bar to fit half-way through */
Rect inner = r.Shrink(ScaleGUITrad(1)); Rect inner = r.Shrink(ScaleGUITrad(1));
@ -791,7 +791,7 @@ void Window::DrawWidgets() const
Rect outer = widget->GetCurrentRect(); Rect outer = widget->GetCurrentRect();
Rect inner = outer.Shrink(WidgetDimensions::scaled.bevel).Expand(1); Rect inner = outer.Shrink(WidgetDimensions::scaled.bevel).Expand(1);
int colour = _string_colourmap[_window_highlight_colour ? widget->GetHighlightColour() : TC_WHITE]; PixelColour colour = _string_colourmap[_window_highlight_colour ? widget->GetHighlightColour() : TC_WHITE];
GfxFillRect(outer.left, outer.top, inner.left, inner.bottom, colour); GfxFillRect(outer.left, outer.top, inner.left, inner.bottom, colour);
GfxFillRect(inner.left + 1, outer.top, inner.right - 1, inner.top, colour); GfxFillRect(inner.left + 1, outer.top, inner.right - 1, inner.top, colour);