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 */
_cur_dpi = &_screen;
for (uint i = 0; i < _cursor.sprite_count; ++i) {
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);
for (const auto &cs : _cursor.sprites) {
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);
@ -1615,20 +1615,22 @@ void UpdateCursorSize()
/* Ignore setting any cursor before the sprites are loaded. */
if (GetMaxSpriteID() == 0) return;
static_assert(lengthof(_cursor.sprite_seq) == lengthof(_cursor.sprite_pos));
assert(_cursor.sprite_count <= lengthof(_cursor.sprite_seq));
for (uint i = 0; i < _cursor.sprite_count; ++i) {
const Sprite *p = GetSprite(GB(_cursor.sprite_seq[i].sprite, 0, SPRITE_WIDTH), SpriteType::Normal);
bool first = true;
for (const auto &cs : _cursor.sprites) {
const Sprite *p = GetSprite(GB(cs.image.sprite, 0, SPRITE_WIDTH), SpriteType::Normal);
Point offs, size;
offs.x = UnScaleGUI(p->x_offs) + _cursor.sprite_pos[i].x;
offs.y = UnScaleGUI(p->y_offs) + _cursor.sprite_pos[i].y;
offs.x = UnScaleGUI(p->x_offs) + cs.pos.x;
offs.y = UnScaleGUI(p->y_offs) + cs.pos.y;
size.x = UnScaleGUI(p->width);
size.y = UnScaleGUI(p->height);
if (i == 0) {
if (first) {
/* First sprite sets the total. */
_cursor.total_offs = offs;
_cursor.total_size = size;
first = false;
} else {
/* Additional sprites expand the total. */
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);
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)
{
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.sprite_seq[0].sprite = cursor;
_cursor.sprite_seq[0].pal = pal;
_cursor.sprite_pos[0].x = 0;
_cursor.sprite_pos[0].y = 0;
_cursor.sprites.clear();
_cursor.sprites.emplace_back(cursor, pal, 0, 0);
UpdateCursorSize();
}
@ -1665,7 +1664,8 @@ static void SwitchAnimatedCursor()
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_cur = cur + 1;
@ -1684,10 +1684,11 @@ void CursorTick()
*/
void SetMouseCursorBusy(bool busy)
{
assert(!_cursor.sprites.empty());
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 {
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)
{
assert(!_cursor.sprites.empty());
_cursor.animate_list = table;
_cursor.animate_cur = nullptr;
_cursor.sprite_seq[0].pal = PAL_NONE;
_cursor.sprites[0].image.pal = PAL_NONE;
SwitchAnimatedCursor();
}

View File

@ -112,6 +112,13 @@ struct AnimCursor {
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 */
struct CursorVars {
/* Logical mouse position */
@ -126,9 +133,7 @@ struct CursorVars {
int h_wheel;
/* Mouse appearance */
PalSpriteID sprite_seq[16]; ///< current image of cursor
Point sprite_pos[16]; ///< relative position of individual sprites
uint sprite_count; ///< number of sprites to draw
std::vector<CursorSprite> sprites; ///< Sprites comprising cursor.
Point total_offs, total_size; ///< union of sprite properties
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;
_cursor.sprite_count = 0;
_cursor.sprites.clear();
int total_width = 0;
int y_offset = 0;
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);
}
if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
int x_offs = 0;
if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset();
for (uint i = 0; i < seq.count; ++i) {
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.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++;
_cursor.sprites.emplace_back(seq.seq[i].sprite, pal2, rtl ? (-total_width + x_offs) : (total_width + x_offs), y_offset);
}
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 */
int offs = (ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2;
if (rtl) offs = -offs;
for (uint i = 0; i < _cursor.sprite_count; ++i) {
_cursor.sprite_pos[i].x += offs;
for (auto &cs : _cursor.sprites) {
cs.pos.x += offs;
}
}

View File

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

View File

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