fix: decouple map and foreground rendering (#1781)

Performance:
- Reduced unnecessary foreground redraws when attached widgets have not changed.
- Improved rendering efficiency during map and interface updates.

Bug Fixes:
- Improved coordination between map rendering and foreground interface elements.
- Adjusted rendering behavior while the game is offline to prevent unnecessary draw and preload activity.
- Improved handling of foreground UI rendering during map display.
This commit is contained in:
karlo 2026-07-28 13:39:06 +02:00 committed by GitHub
parent f4825cbd87
commit 5636f95e36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 22 additions and 11 deletions

View file

@ -23,6 +23,7 @@
#include "map.h"
#include "animatedtext.h"
#include "client/const.h"
#include "creatures.h"
#include "game.h"
#include "gameconfig.h"
@ -1249,7 +1250,7 @@ bool Map::removeAttachedWidgetFromObject(const UIWidgetPtr& widget) {
void Map::updateAttachedWidgets(const MapViewPtr& mapView)
{
g_drawPool.select(DrawPoolType::MAP);
bool should_repaint = false;
for (const auto& [widget, object] : m_attachedObjectWidgetMap) {
if (widget->isDestroyed()) {
continue;
@ -1300,9 +1301,16 @@ void Map::updateAttachedWidgets(const MapViewPtr& mapView)
const auto& widgetRect = widget->getRect();
const auto& newWidgetRect = Rect(p, widgetRect.width(), widgetRect.height());
widget->disableUpdateTemporarily();
widget->setRect(newWidgetRect);
if (widgetRect != newWidgetRect) {
widget->disableUpdateTemporarily();
widget->setRect(newWidgetRect);
should_repaint = true;
}
}
// only repaint if some widget changed position on the screen
if (should_repaint)
g_drawPool.repaint(DrawPoolType::FOREGROUND);
}
std::map<std::string, std::tuple<int, int, int, std::string>> Map::findEveryPath(const Position& start, int maxDistance, const std::map<std::string, std::string>& params)

View file

@ -169,7 +169,8 @@ bool GraphicalApplication::canDrawMap() const {
if (!m_drawEvents->canDraw(MAP))
return false;
static constexpr std::array<DrawPoolType, 4> types{ MAP, LIGHT, FOREGROUND_MAP, CREATURE_INFORMATION };
// FOREGROUND is here only because of attached widgets on the map (like tile widgets)
static constexpr std::array<DrawPoolType, 5> types{ MAP, LIGHT, FOREGROUND_MAP, CREATURE_INFORMATION, FOREGROUND };
for (DrawPoolType type : types) {
if (g_drawPool.isDrawing(type))
@ -212,7 +213,7 @@ void GraphicalApplication::run()
continue;
}
{
if (g_game.isOnline()) {
AutoStat s(STATS_RENDER, "DrawPreload");
m_drawEvents->preLoad();
}
@ -222,11 +223,13 @@ void GraphicalApplication::run()
if (!g_game.isOnline() && canDrawForeground) {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
} else if (canDrawMap() && canDrawForeground) {
tasks.emplace_back(g_asyncDispatcher->submit_task([] {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
}));
} else if (canDrawMap()) {
if (canDrawForeground) {
tasks.emplace_back(g_asyncDispatcher->submit_task([] {
AutoStat s(STATS_RENDER, "DrawForegroundUI");
g_ui.render(DrawPoolType::FOREGROUND);
}));
}
static constexpr std::array<DrawPoolType, 2> types{ DrawPoolType::LIGHT, DrawPoolType::FOREGROUND_MAP };
for (const auto type : types) {

View file

@ -524,4 +524,4 @@ std::shared_ptr<CoordsBuffer> DrawPool::getCoordsBuffer() {
delete ptr;
}
});
}
}