mirror of https://github.com/OpenRCT2/OpenRCT2.git
Refactor window drawing
This commit is contained in:
parent
2b51eaeaa1
commit
f51ad862c9
|
@ -772,3 +772,15 @@ std::optional<PaletteMap> GetPaletteMapForColour(colour_t paletteId)
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rct_drawpixelinfo rct_drawpixelinfo::Crop(int32_t newX, int32_t newY, int32_t newWidth, int32_t newHeight)
|
||||||
|
{
|
||||||
|
rct_drawpixelinfo result = *this;
|
||||||
|
result.bits = bits + newX + (((size_t)width + pitch) * newY);
|
||||||
|
result.x = static_cast<int16_t>(newX);
|
||||||
|
result.y = static_cast<int16_t>(newY);
|
||||||
|
result.width = static_cast<int16_t>(newWidth);
|
||||||
|
result.height = static_cast<int16_t>(newHeight);
|
||||||
|
result.pitch = static_cast<int16_t>(width + pitch - newWidth);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -110,6 +110,8 @@ struct rct_drawpixelinfo
|
||||||
ZoomLevel zoom_level{};
|
ZoomLevel zoom_level{};
|
||||||
|
|
||||||
OpenRCT2::Drawing::IDrawingEngine* DrawingEngine{};
|
OpenRCT2::Drawing::IDrawingEngine* DrawingEngine{};
|
||||||
|
|
||||||
|
rct_drawpixelinfo Crop(int32_t newX, int32_t newY, int32_t newWidth, int32_t newHeight);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rct_g1_element_32bit
|
struct rct_g1_element_32bit
|
||||||
|
|
|
@ -84,8 +84,7 @@ namespace WindowCloseFlags
|
||||||
static constexpr uint32_t CloseSingle = (1 << 1);
|
static constexpr uint32_t CloseSingle = (1 << 1);
|
||||||
} // namespace WindowCloseFlags
|
} // namespace WindowCloseFlags
|
||||||
|
|
||||||
static int32_t window_draw_split(
|
static void window_draw_core(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom);
|
||||||
rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom);
|
|
||||||
static void window_draw_single(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom);
|
static void window_draw_single(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom);
|
||||||
|
|
||||||
std::list<std::shared_ptr<rct_window>>::iterator window_get_iterator(const rct_window* w)
|
std::list<std::shared_ptr<rct_window>>::iterator window_get_iterator(const rct_window* w)
|
||||||
|
@ -1088,51 +1087,14 @@ void main_window_zoom(bool zoomIn, bool atCursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a window that is in the specified region.
|
* Splits a drawing of a window into regions that can be seen and are not hidden
|
||||||
* rct2: 0x006E756C
|
* by other opaque overlapping windows.
|
||||||
* left (ax)
|
|
||||||
* top (bx)
|
|
||||||
* right (dx)
|
|
||||||
* bottom (bp)
|
|
||||||
*/
|
*/
|
||||||
void window_draw(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
void window_draw(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
||||||
{
|
{
|
||||||
if (!window_is_visible(w))
|
if (!window_is_visible(w))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Split window into only the regions that require drawing
|
|
||||||
if (window_draw_split(dpi, w, left, top, right, bottom))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Clamp region
|
|
||||||
left = std::max<int32_t>(left, w->windowPos.x);
|
|
||||||
top = std::max<int32_t>(top, w->windowPos.y);
|
|
||||||
right = std::min<int32_t>(right, w->windowPos.x + w->width);
|
|
||||||
bottom = std::min<int32_t>(bottom, w->windowPos.y + w->height);
|
|
||||||
if (left >= right)
|
|
||||||
return;
|
|
||||||
if (top >= bottom)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Draw the window in this region
|
|
||||||
for (auto it = window_get_iterator(w); it != g_window_list.end(); it++)
|
|
||||||
{
|
|
||||||
// Don't draw overlapping opaque windows, they won't have changed
|
|
||||||
auto v = (*it).get();
|
|
||||||
if ((w == v || (v->flags & WF_TRANSPARENT)) && window_is_visible(v))
|
|
||||||
{
|
|
||||||
window_draw_single(dpi, v, left, top, right, bottom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a drawing of a window into regions that can be seen and are not hidden
|
|
||||||
* by other opaque overlapping windows.
|
|
||||||
*/
|
|
||||||
static int32_t window_draw_split(
|
|
||||||
rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
|
||||||
{
|
|
||||||
// Divide the draws up for only the visible regions of the window recursively
|
// Divide the draws up for only the visible regions of the window recursively
|
||||||
auto itPos = window_get_iterator(w);
|
auto itPos = window_get_iterator(w);
|
||||||
for (auto it = std::next(itPos); it != g_window_list.end(); it++)
|
for (auto it = std::next(itPos); it != g_window_list.end(); it++)
|
||||||
|
@ -1150,34 +1112,60 @@ static int32_t window_draw_split(
|
||||||
if (topwindow->windowPos.x > left)
|
if (topwindow->windowPos.x > left)
|
||||||
{
|
{
|
||||||
// Split draw at topwindow.left
|
// Split draw at topwindow.left
|
||||||
window_draw(dpi, w, left, top, topwindow->windowPos.x, bottom);
|
window_draw_core(dpi, w, left, top, topwindow->windowPos.x, bottom);
|
||||||
window_draw(dpi, w, topwindow->windowPos.x, top, right, bottom);
|
window_draw_core(dpi, w, topwindow->windowPos.x, top, right, bottom);
|
||||||
}
|
}
|
||||||
else if (topwindow->windowPos.x + topwindow->width < right)
|
else if (topwindow->windowPos.x + topwindow->width < right)
|
||||||
{
|
{
|
||||||
// Split draw at topwindow.right
|
// Split draw at topwindow.right
|
||||||
window_draw(dpi, w, left, top, topwindow->windowPos.x + topwindow->width, bottom);
|
window_draw_core(dpi, w, left, top, topwindow->windowPos.x + topwindow->width, bottom);
|
||||||
window_draw(dpi, w, topwindow->windowPos.x + topwindow->width, top, right, bottom);
|
window_draw_core(dpi, w, topwindow->windowPos.x + topwindow->width, top, right, bottom);
|
||||||
}
|
}
|
||||||
else if (topwindow->windowPos.y > top)
|
else if (topwindow->windowPos.y > top)
|
||||||
{
|
{
|
||||||
// Split draw at topwindow.top
|
// Split draw at topwindow.top
|
||||||
window_draw(dpi, w, left, top, right, topwindow->windowPos.y);
|
window_draw_core(dpi, w, left, top, right, topwindow->windowPos.y);
|
||||||
window_draw(dpi, w, left, topwindow->windowPos.y, right, bottom);
|
window_draw_core(dpi, w, left, topwindow->windowPos.y, right, bottom);
|
||||||
}
|
}
|
||||||
else if (topwindow->windowPos.y + topwindow->height < bottom)
|
else if (topwindow->windowPos.y + topwindow->height < bottom)
|
||||||
{
|
{
|
||||||
// Split draw at topwindow.bottom
|
// Split draw at topwindow.bottom
|
||||||
window_draw(dpi, w, left, top, right, topwindow->windowPos.y + topwindow->height);
|
window_draw_core(dpi, w, left, top, right, topwindow->windowPos.y + topwindow->height);
|
||||||
window_draw(dpi, w, left, topwindow->windowPos.y + topwindow->height, right, bottom);
|
window_draw_core(dpi, w, left, topwindow->windowPos.y + topwindow->height, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawing for this region should be done now, exit
|
// Drawing for this region should be done now, exit
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No windows overlap
|
// No windows overlap
|
||||||
return 0;
|
window_draw_core(dpi, w, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the given window and any other overlapping transparent windows.
|
||||||
|
*/
|
||||||
|
static void window_draw_core(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
||||||
|
{
|
||||||
|
// Clamp region
|
||||||
|
left = std::max<int32_t>(left, w->windowPos.x);
|
||||||
|
top = std::max<int32_t>(top, w->windowPos.y);
|
||||||
|
right = std::min<int32_t>(right, w->windowPos.x + w->width);
|
||||||
|
bottom = std::min<int32_t>(bottom, w->windowPos.y + w->height);
|
||||||
|
if (left >= right)
|
||||||
|
return;
|
||||||
|
if (top >= bottom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Draw the window and any other overlapping transparent windows
|
||||||
|
for (auto it = window_get_iterator(w); it != g_window_list.end(); it++)
|
||||||
|
{
|
||||||
|
auto v = (*it).get();
|
||||||
|
if ((w == v || (v->flags & WF_TRANSPARENT)) && window_is_visible(v))
|
||||||
|
{
|
||||||
|
window_draw_single(dpi, v, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_draw_single(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
static void window_draw_single(rct_drawpixelinfo* dpi, rct_window* w, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
||||||
|
@ -2018,15 +2006,7 @@ bool window_is_visible(rct_window* w)
|
||||||
*/
|
*/
|
||||||
void window_draw_all(rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom)
|
void window_draw_all(rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom)
|
||||||
{
|
{
|
||||||
rct_drawpixelinfo windowDPI = *dpi;
|
auto windowDPI = dpi->Crop(left, top, right - left, bottom - top);
|
||||||
windowDPI.bits = dpi->bits + left + ((dpi->width + dpi->pitch) * top);
|
|
||||||
windowDPI.x = left;
|
|
||||||
windowDPI.y = top;
|
|
||||||
windowDPI.width = right - left;
|
|
||||||
windowDPI.height = bottom - top;
|
|
||||||
windowDPI.pitch = dpi->width + dpi->pitch + left - right;
|
|
||||||
windowDPI.zoom_level = 0;
|
|
||||||
|
|
||||||
window_visit_each([&windowDPI, left, top, right, bottom](rct_window* w) {
|
window_visit_each([&windowDPI, left, top, right, bottom](rct_window* w) {
|
||||||
if (w->flags & WF_TRANSPARENT)
|
if (w->flags & WF_TRANSPARENT)
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue