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();