Fix window re-rendering when ReInit() called within OnPaint/draw handler

This commit is contained in:
Jonathan G Rennison
2020-03-23 00:22:46 +00:00
parent ba65a79d09
commit c227d30801
3 changed files with 38 additions and 2 deletions

View File

@@ -80,8 +80,10 @@ static const uint DIRTY_BLOCK_WIDTH = 64;
extern uint _dirty_block_colour; extern uint _dirty_block_colour;
static bool _whole_screen_dirty = false; static bool _whole_screen_dirty = false;
bool _gfx_draw_active = false;
static std::vector<Rect> _dirty_blocks; static std::vector<Rect> _dirty_blocks;
static std::vector<Rect> _pending_dirty_blocks;
/** /**
* Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen. * Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
@@ -1511,6 +1513,8 @@ void DrawDirtyBlocks()
extern void ViewportPrepareVehicleRoute(); extern void ViewportPrepareVehicleRoute();
ViewportPrepareVehicleRoute(); ViewportPrepareVehicleRoute();
_gfx_draw_active = true;
if (_whole_screen_dirty) { if (_whole_screen_dirty) {
RedrawScreenRect(0, 0, _screen.width, _screen.height); RedrawScreenRect(0, 0, _screen.width, _screen.height);
Window *w; Window *w;
@@ -1677,6 +1681,17 @@ void DrawDirtyBlocks()
} }
_dirty_blocks.clear(); _dirty_blocks.clear();
while (!_pending_dirty_blocks.empty()) {
for (const Rect &r : _pending_dirty_blocks) {
SetDirtyBlocks(r.left, r.top, r.right, r.bottom);
}
_pending_dirty_blocks.clear();
for (const Rect &r : _dirty_blocks) {
RedrawScreenRect(r.left, r.top, r.right, r.bottom);
}
_dirty_blocks.clear();
}
_gfx_draw_active = false;
++_dirty_block_colour; ++_dirty_block_colour;
extern void ClearViewPortCaches(); extern void ClearViewPortCaches();
@@ -1816,6 +1831,11 @@ void SetDirtyBlocks(int left, int top, int right, int bottom)
AddDirtyBlocks(0, left, top, right, bottom); AddDirtyBlocks(0, left, top, right, bottom);
} }
void SetPendingDirtyBlocks(int left, int top, int right, int bottom)
{
_pending_dirty_blocks.push_back({ left, top, right, bottom });
}
/** /**
* This function mark the whole screen as dirty. This results in repainting * This function mark the whole screen as dirty. This results in repainting
* the whole screen. Use this with care as this function will break the * the whole screen. Use this with care as this function will break the

View File

@@ -133,6 +133,7 @@ const char *GetCharAtPosition(const char *str, int x, FontSize start_fontsize =
void DrawDirtyBlocks(); void DrawDirtyBlocks();
void SetDirtyBlocks(int left, int top, int right, int bottom); void SetDirtyBlocks(int left, int top, int right, int bottom);
void SetPendingDirtyBlocks(int left, int top, int right, int bottom);
void UnsetDirtyBlocks(int left, int top, int right, int bottom); void UnsetDirtyBlocks(int left, int top, int right, int bottom);
void MarkWholeScreenDirty(); void MarkWholeScreenDirty();

View File

@@ -974,6 +974,11 @@ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
_cur_dpi = old_dpi; _cur_dpi = old_dpi;
} }
static void SetWindowDirtyPending(Window *w)
{
SetPendingDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height);
}
/** /**
* Mark entire window as dirty (in need of re-paint) * Mark entire window as dirty (in need of re-paint)
* @ingroup dirty * @ingroup dirty
@@ -989,7 +994,12 @@ void Window::SetDirty()
*/ */
void Window::SetDirtyAsBlocks() void Window::SetDirtyAsBlocks()
{ {
extern bool _gfx_draw_active;
if (_gfx_draw_active) {
SetWindowDirtyPending(this);
} else {
SetDirtyBlocks(this->left, this->top, this->left + this->width, this->top + this->height); SetDirtyBlocks(this->left, this->top, this->left + this->width, this->top + this->height);
}
} }
/** /**
@@ -2180,7 +2190,12 @@ void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen)
/* Always call OnResize to make sure everything is initialised correctly if it needs to be. */ /* Always call OnResize to make sure everything is initialised correctly if it needs to be. */
w->OnResize(); w->OnResize();
extern bool _gfx_draw_active;
if (_gfx_draw_active) {
SetWindowDirtyPending(w);
} else {
w->SetDirty(); w->SetDirty();
}
} }
/** /**