From 5e689ce25e574a3d220d45b22a4d81413224a0f5 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 24 Apr 2024 21:26:07 +0100 Subject: [PATCH] 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. --- src/gfx.cpp | 40 +++++++++++++++++++++------------------- src/gfx_type.h | 11 ++++++++--- src/vehicle_gui.cpp | 14 ++++---------- src/video/opengl.cpp | 29 +++++++++++------------------ src/video/opengl.h | 4 +--- 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 36f62a129d..0292dff16a 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -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(); } diff --git a/src/gfx_type.h b/src/gfx_type.h index c71819c7ad..c6866f46e2 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -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 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 diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 3849518303..93efd79c4e 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -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; } } diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 5b49f34126..13920cb543 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -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(); diff --git a/src/video/opengl.h b/src/video/opengl.h index b143039b40..0fd706ffb2 100644 --- a/src/video/opengl.h +++ b/src/video/opengl.h @@ -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 cursor_sprites; ///< Sprites comprising cursor OpenGLBackend(); ~OpenGLBackend();