Merge pull request #3993 from Rodbourn/develop

Prevent rendering of hidden windows.
This commit is contained in:
Ted John 2016-07-06 18:52:10 +01:00 committed by GitHub
commit ae80ba4888
4 changed files with 80 additions and 2 deletions

View File

@ -365,6 +365,8 @@ public:
_rainDrawer.SetDPI(&_bitsDPI);
_rainDrawer.Restore();
ResetWindowVisbilities();
// Redraw dirty regions before updating the viewports, otherwise
// when viewports get panned, they copy dirty pixels
DrawAllDirtyBlocks();
@ -528,6 +530,16 @@ private:
_dirtyGrid.Blocks = new uint8[_dirtyGrid.BlockColumns * _dirtyGrid.BlockRows];
}
static void ResetWindowVisbilities()
{
// reset window visibilty status to unknown
for (rct_window *w = g_window_list; w < gWindowNextSlot; w++)
{
w->visibility = VC_UNKNOWN;
if (w->viewport != NULL) w->viewport->visibility = VC_UNKNOWN;
}
}
void DrawAllDirtyBlocks()
{
uint32 dirtyBlockColumns = _dirtyGrid.BlockColumns;

View File

@ -1396,6 +1396,23 @@ void get_map_coordinates_from_pos(int screenX, int screenY, int flags, sint16 *x
*/
void viewport_invalidate(rct_viewport *viewport, int left, int top, int right, int bottom)
{
// if unknown viewport visibility, use the containing window to discover the status
if (viewport->visibility == VC_UNKNOWN)
{
for (rct_window *w = g_window_list; w < gWindowNextSlot; w++)
{
if (w->classification != WC_MAIN_WINDOW && w->viewport != NULL && w->viewport == viewport)
{
// note, window_is_visible will update viewport->visibility, so this should have a low hit count
if (!window_is_visible(w)) {
return;
}
}
}
}
if (viewport->visibility == VC_COVERED) return;
int viewportLeft = viewport->view_x;
int viewportTop = viewport->view_y;
int viewportRight = viewport->view_x + viewport->view_width;

View File

@ -146,7 +146,7 @@ void window_dispatch_update_all()
void window_update_all_viewports()
{
for (rct_window *w = g_window_list; w < RCT2_NEW_WINDOW; w++)
if (w->viewport != NULL)
if (w->viewport != NULL && window_is_visible(w))
viewport_update_position(w);
}
@ -1464,6 +1464,8 @@ void window_zoom_out(rct_window *w)
*/
void window_draw(rct_drawpixelinfo *dpi, rct_window *w, int left, int top, int right, int bottom)
{
if (!window_is_visible(w)) return;
// Split window into only the regions that require drawing
if (window_draw_split(dpi, w, left, top, right, bottom))
return;
@ -1479,7 +1481,7 @@ void window_draw(rct_drawpixelinfo *dpi, rct_window *w, int left, int top, int r
// Draw the window in this region
for (rct_window *v = w; v < RCT2_NEW_WINDOW; v++) {
// Don't draw overlapping opaque windows, they won't have changed
if (w == v || (v->flags & WF_TRANSPARENT)) {
if ((w == v || (v->flags & WF_TRANSPARENT)) && window_is_visible(v)) {
window_draw_single(dpi, v, left, top, right, bottom);
}
}
@ -2477,3 +2479,39 @@ void window_update_textbox()
window_event_textinput_call(w, gCurrentTextBox.widget_index, gTextBoxInput);
}
}
bool window_is_visible(rct_window* w)
{
// w->visibility is used to prevent repeat calculations within an iteration by caching the result
if (w->visibility == VC_VISIBLE) return true;
if (w->visibility == VC_COVERED) return false;
// only consider viewports, consider the main window always visible
if (w == NULL || w->viewport == NULL || w->classification == WC_MAIN_WINDOW)
{
// default to previous behaviour
w->visibility = VC_VISIBLE;
return true;
}
// start from the window above the current
for (rct_window *w_other = (w+1); w_other < RCT2_NEW_WINDOW; w_other++)
{
// if covered by a higher window, no rendering needed
if (w_other->x <= w->x
&& w_other->y <= w->y
&& w_other->x + w_other->width >= w->x + w->width
&& w_other->y + w_other->height >= w->y + w->height)
{
w->visibility = VC_COVERED;
w->viewport->visibility = VC_COVERED;
return false;
}
}
// default to previous behaviour
w->visibility = VC_VISIBLE;
w->viewport->visibility = VC_VISIBLE;
return true;
}

View File

@ -85,6 +85,7 @@ typedef struct rct_viewport {
uint8 zoom; // 0x10
uint8 var_11;
uint16 flags; // 0x12
uint8 visibility; // VISIBILITY_CACHE
} rct_viewport;
/**
@ -288,6 +289,7 @@ typedef struct rct_window {
sint8 var_4B8;
sint8 var_4B9;
uint8 colours[6]; // 0x4BA
uint8 visibility; // VISIBILITY_CACHE
} rct_window;
#define RCT_WINDOW_RIGHT(w) (w->x + w->width)
@ -493,6 +495,13 @@ enum {
MODAL_RESULT_OK
};
enum VISIBILITY_CACHE
{
VC_UNKNOWN,
VC_VISIBLE,
VC_COVERED
};
typedef void (*modal_callback)(int result);
typedef void (*scenarioselect_callback)(const utf8 *path);
@ -729,6 +738,8 @@ void window_cancel_textbox();
void window_update_textbox_caret();
void window_update_textbox();
bool window_is_visible(rct_window* w);
bool land_tool_is_active();
//Cheat: in-game land ownership editor