Codechange: Store cursor sprites in vector. (#12564)

Combine two separate fixed length arrays to allow simpler iteration.

No need to check that arrays are all the same length.
No need to separately store the number of sprites to draw.
Removes the upper limit of the number of sprites that can be drawn.

Removes lengthof and array indices.
This commit is contained in:
Peter Nelson 2024-04-24 21:26:07 +01:00 committed by GitHub
parent 9121770582
commit 5e689ce25e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 53 deletions

View File

@ -1363,8 +1363,8 @@ void DrawMouseCursor()
/* Draw cursor on screen */ /* Draw cursor on screen */
_cur_dpi = &_screen; _cur_dpi = &_screen;
for (uint i = 0; i < _cursor.sprite_count; ++i) { for (const auto &cs : _cursor.sprites) {
DrawSprite(_cursor.sprite_seq[i].sprite, _cursor.sprite_seq[i].pal, _cursor.pos.x + _cursor.sprite_pos[i].x, _cursor.pos.y + _cursor.sprite_pos[i].y); DrawSprite(cs.image.sprite, cs.image.pal, _cursor.pos.x + cs.pos.x, _cursor.pos.y + cs.pos.y);
} }
VideoDriver::GetInstance()->MakeDirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); VideoDriver::GetInstance()->MakeDirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y);
@ -1615,20 +1615,22 @@ void UpdateCursorSize()
/* Ignore setting any cursor before the sprites are loaded. */ /* Ignore setting any cursor before the sprites are loaded. */
if (GetMaxSpriteID() == 0) return; if (GetMaxSpriteID() == 0) return;
static_assert(lengthof(_cursor.sprite_seq) == lengthof(_cursor.sprite_pos)); bool first = true;
assert(_cursor.sprite_count <= lengthof(_cursor.sprite_seq)); for (const auto &cs : _cursor.sprites) {
for (uint i = 0; i < _cursor.sprite_count; ++i) { const Sprite *p = GetSprite(GB(cs.image.sprite, 0, SPRITE_WIDTH), SpriteType::Normal);
const Sprite *p = GetSprite(GB(_cursor.sprite_seq[i].sprite, 0, SPRITE_WIDTH), SpriteType::Normal);
Point offs, size; Point offs, size;
offs.x = UnScaleGUI(p->x_offs) + _cursor.sprite_pos[i].x; offs.x = UnScaleGUI(p->x_offs) + cs.pos.x;
offs.y = UnScaleGUI(p->y_offs) + _cursor.sprite_pos[i].y; offs.y = UnScaleGUI(p->y_offs) + cs.pos.y;
size.x = UnScaleGUI(p->width); size.x = UnScaleGUI(p->width);
size.y = UnScaleGUI(p->height); size.y = UnScaleGUI(p->height);
if (i == 0) { if (first) {
/* First sprite sets the total. */
_cursor.total_offs = offs; _cursor.total_offs = offs;
_cursor.total_size = size; _cursor.total_size = size;
first = false;
} else { } else {
/* Additional sprites expand the total. */
int right = std::max(_cursor.total_offs.x + _cursor.total_size.x, offs.x + size.x); int right = std::max(_cursor.total_offs.x + _cursor.total_size.x, offs.x + size.x);
int bottom = std::max(_cursor.total_offs.y + _cursor.total_size.y, offs.y + size.y); int bottom = std::max(_cursor.total_offs.y + _cursor.total_size.y, offs.y + size.y);
if (offs.x < _cursor.total_offs.x) _cursor.total_offs.x = offs.x; if (offs.x < _cursor.total_offs.x) _cursor.total_offs.x = offs.x;
@ -1648,13 +1650,10 @@ void UpdateCursorSize()
*/ */
static void SetCursorSprite(CursorID cursor, PaletteID pal) static void SetCursorSprite(CursorID cursor, PaletteID pal)
{ {
if (_cursor.sprite_count == 1 && _cursor.sprite_seq[0].sprite == cursor && _cursor.sprite_seq[0].pal == pal) return; if (_cursor.sprites.size() == 1 && _cursor.sprites[0].image.sprite == cursor && _cursor.sprites[0].image.pal == pal) return;
_cursor.sprite_count = 1; _cursor.sprites.clear();
_cursor.sprite_seq[0].sprite = cursor; _cursor.sprites.emplace_back(cursor, pal, 0, 0);
_cursor.sprite_seq[0].pal = pal;
_cursor.sprite_pos[0].x = 0;
_cursor.sprite_pos[0].y = 0;
UpdateCursorSize(); UpdateCursorSize();
} }
@ -1665,7 +1664,8 @@ static void SwitchAnimatedCursor()
if (cur == nullptr || cur->sprite == AnimCursor::LAST) cur = _cursor.animate_list; if (cur == nullptr || cur->sprite == AnimCursor::LAST) cur = _cursor.animate_list;
SetCursorSprite(cur->sprite, _cursor.sprite_seq[0].pal); assert(!_cursor.sprites.empty());
SetCursorSprite(cur->sprite, _cursor.sprites[0].image.pal);
_cursor.animate_timeout = cur->display_time; _cursor.animate_timeout = cur->display_time;
_cursor.animate_cur = cur + 1; _cursor.animate_cur = cur + 1;
@ -1684,10 +1684,11 @@ void CursorTick()
*/ */
void SetMouseCursorBusy(bool busy) void SetMouseCursorBusy(bool busy)
{ {
assert(!_cursor.sprites.empty());
if (busy) { if (busy) {
if (_cursor.sprite_seq[0].sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE); if (_cursor.sprites[0].image.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE);
} else { } else {
if (_cursor.sprite_seq[0].sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); if (_cursor.sprites[0].image.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
} }
} }
@ -1712,9 +1713,10 @@ void SetMouseCursor(CursorID sprite, PaletteID pal)
*/ */
void SetAnimatedMouseCursor(const AnimCursor *table) void SetAnimatedMouseCursor(const AnimCursor *table)
{ {
assert(!_cursor.sprites.empty());
_cursor.animate_list = table; _cursor.animate_list = table;
_cursor.animate_cur = nullptr; _cursor.animate_cur = nullptr;
_cursor.sprite_seq[0].pal = PAL_NONE; _cursor.sprites[0].image.pal = PAL_NONE;
SwitchAnimatedCursor(); SwitchAnimatedCursor();
} }

View File

@ -112,6 +112,13 @@ struct AnimCursor {
uint8_t display_time; ///< Amount of ticks this sprite will be shown uint8_t display_time; ///< Amount of ticks this sprite will be shown
}; };
struct CursorSprite {
PalSpriteID image; ///< Image.
Point pos; ///< Relative position.
constexpr CursorSprite(SpriteID spr, PaletteID pal, int x, int y) : image({spr, pal}), pos({x, y}) {}
};
/** Collection of variables for cursor-display and -animation */ /** Collection of variables for cursor-display and -animation */
struct CursorVars { struct CursorVars {
/* Logical mouse position */ /* Logical mouse position */
@ -126,9 +133,7 @@ struct CursorVars {
int h_wheel; int h_wheel;
/* Mouse appearance */ /* Mouse appearance */
PalSpriteID sprite_seq[16]; ///< current image of cursor std::vector<CursorSprite> sprites; ///< Sprites comprising cursor.
Point sprite_pos[16]; ///< relative position of individual sprites
uint sprite_count; ///< number of sprites to draw
Point total_offs, total_size; ///< union of sprite properties Point total_offs, total_size; ///< union of sprite properties
Point draw_pos, draw_size; ///< position and size bounding-box for drawing Point draw_pos, draw_size; ///< position and size bounding-box for drawing

View File

@ -3537,7 +3537,7 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
{ {
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
_cursor.sprite_count = 0; _cursor.sprites.clear();
int total_width = 0; int total_width = 0;
int y_offset = 0; int y_offset = 0;
bool rotor_seq = false; // Whether to draw the rotor of the vehicle in this step. bool rotor_seq = false; // Whether to draw the rotor of the vehicle in this step.
@ -3557,18 +3557,12 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq); v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
} }
if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
int x_offs = 0; int x_offs = 0;
if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset(); if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset();
for (uint i = 0; i < seq.count; ++i) { for (uint i = 0; i < seq.count; ++i) {
PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal; PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
_cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite; _cursor.sprites.emplace_back(seq.seq[i].sprite, pal2, rtl ? (-total_width + x_offs) : (total_width + x_offs), y_offset);
_cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? (-total_width + x_offs) : (total_width + x_offs);
_cursor.sprite_pos[_cursor.sprite_count].y = y_offset;
_cursor.sprite_count++;
} }
if (v->type == VEH_AIRCRAFT && v->subtype == AIR_HELICOPTER && !rotor_seq) { if (v->type == VEH_AIRCRAFT && v->subtype == AIR_HELICOPTER && !rotor_seq) {
@ -3584,8 +3578,8 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
/* Center trains and road vehicles on the front vehicle */ /* Center trains and road vehicles on the front vehicle */
int offs = (ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2; int offs = (ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2;
if (rtl) offs = -offs; if (rtl) offs = -offs;
for (uint i = 0; i < _cursor.sprite_count; ++i) { for (auto &cs : _cursor.sprites) {
_cursor.sprite_pos[i].x += offs; cs.pos.x += offs;
} }
} }

View File

@ -1074,16 +1074,14 @@ void OpenGLBackend::DrawMouseCursor()
/* Draw cursor on screen */ /* Draw cursor on screen */
_cur_dpi = &_screen; _cur_dpi = &_screen;
for (uint i = 0; i < this->cursor_sprite_count; ++i) { for (const auto &cs : this->cursor_sprites) {
SpriteID sprite = this->cursor_sprite_seq[i].sprite;
/* Sprites are cached by PopulateCursorCache(). */ /* Sprites are cached by PopulateCursorCache(). */
if (this->cursor_cache.Contains(sprite)) { if (this->cursor_cache.Contains(cs.image.sprite)) {
Sprite *spr = this->cursor_cache.Get(sprite); Sprite *spr = this->cursor_cache.Get(cs.image.sprite);
this->RenderOglSprite((OpenGLSprite *)spr->data, this->cursor_sprite_seq[i].pal, this->RenderOglSprite((OpenGLSprite *)spr->data, cs.image.pal,
this->cursor_pos.x + this->cursor_sprite_pos[i].x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI), this->cursor_pos.x + cs.pos.x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI),
this->cursor_pos.y + this->cursor_sprite_pos[i].y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI), this->cursor_pos.y + cs.pos.y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI),
ZOOM_LVL_GUI); ZOOM_LVL_GUI);
} }
} }
@ -1091,9 +1089,6 @@ void OpenGLBackend::DrawMouseCursor()
void OpenGLBackend::PopulateCursorCache() void OpenGLBackend::PopulateCursorCache()
{ {
static_assert(lengthof(_cursor.sprite_seq) == lengthof(this->cursor_sprite_seq));
static_assert(lengthof(_cursor.sprite_pos) == lengthof(this->cursor_sprite_pos));
if (this->clear_cursor_cache) { if (this->clear_cursor_cache) {
/* We have a pending cursor cache clear to do first. */ /* We have a pending cursor cache clear to do first. */
this->clear_cursor_cache = false; this->clear_cursor_cache = false;
@ -1103,16 +1098,14 @@ void OpenGLBackend::PopulateCursorCache()
} }
this->cursor_pos = _cursor.pos; this->cursor_pos = _cursor.pos;
this->cursor_sprite_count = _cursor.sprite_count;
this->cursor_in_window = _cursor.in_window; this->cursor_in_window = _cursor.in_window;
for (uint i = 0; i < _cursor.sprite_count; ++i) { this->cursor_sprites.clear();
this->cursor_sprite_seq[i] = _cursor.sprite_seq[i]; for (const auto &sc : _cursor.sprites) {
this->cursor_sprite_pos[i] = _cursor.sprite_pos[i]; this->cursor_sprites.emplace_back(sc);
SpriteID sprite = _cursor.sprite_seq[i].sprite;
if (!this->cursor_cache.Contains(sprite)) { if (!this->cursor_cache.Contains(sc.image.sprite)) {
Sprite *old = this->cursor_cache.Insert(sprite, (Sprite *)GetRawSprite(sprite, SpriteType::Normal, &SimpleSpriteAlloc, this)); Sprite *old = this->cursor_cache.Insert(sc.image.sprite, (Sprite *)GetRawSprite(sc.image.sprite, SpriteType::Normal, &SimpleSpriteAlloc, this));
if (old != nullptr) { if (old != nullptr) {
OpenGLSprite *gl_sprite = (OpenGLSprite *)old->data; OpenGLSprite *gl_sprite = (OpenGLSprite *)old->data;
gl_sprite->~OpenGLSprite(); gl_sprite->~OpenGLSprite();

View File

@ -65,9 +65,7 @@ private:
Point cursor_pos; ///< Cursor position Point cursor_pos; ///< Cursor position
bool cursor_in_window; ///< Cursor inside this window bool cursor_in_window; ///< Cursor inside this window
PalSpriteID cursor_sprite_seq[16]; ///< Current image of cursor std::vector<CursorSprite> cursor_sprites; ///< Sprites comprising cursor
Point cursor_sprite_pos[16]; ///< Relative position of individual cursor sprites
uint cursor_sprite_count; ///< Number of cursor sprites to draw
OpenGLBackend(); OpenGLBackend();
~OpenGLBackend(); ~OpenGLBackend();