Fix window re-rendering when ReInit() called within OnPaint/draw handler
This commit is contained in:
20
src/gfx.cpp
20
src/gfx.cpp
@@ -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
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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()
|
||||||
{
|
{
|
||||||
SetDirtyBlocks(this->left, this->top, this->left + this->width, this->top + this->height);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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();
|
||||||
w->SetDirty();
|
extern bool _gfx_draw_active;
|
||||||
|
if (_gfx_draw_active) {
|
||||||
|
SetWindowDirtyPending(w);
|
||||||
|
} else {
|
||||||
|
w->SetDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user