mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
727 lines
21 KiB
C++
727 lines
21 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
|
*
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
|
*
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
|
*****************************************************************************/
|
|
|
|
#include "Window.h"
|
|
|
|
#include "Theme.h"
|
|
|
|
#include <SDL.h>
|
|
#include <algorithm>
|
|
#include <openrct2/Context.h>
|
|
#include <openrct2/Input.h>
|
|
#include <openrct2/OpenRCT2.h>
|
|
#include <openrct2/audio/audio.h>
|
|
#include <openrct2/config/Config.h>
|
|
#include <openrct2/drawing/Drawing.h>
|
|
#include <openrct2/interface/Widget.h>
|
|
#include <openrct2/localisation/StringIds.h>
|
|
#include <openrct2/sprites.h>
|
|
#include <openrct2/ui/UiContext.h>
|
|
#include <openrct2/world/Sprite.h>
|
|
|
|
using namespace OpenRCT2;
|
|
|
|
// The amount of pixels to scroll per wheel click
|
|
constexpr int32_t WindowScrollPixels = 17;
|
|
|
|
static int32_t _previousAbsoluteWheel = 0;
|
|
|
|
static bool WindowFitsBetweenOthers(const ScreenCoordsXY& loc, int32_t width, int32_t height)
|
|
{
|
|
for (auto& w : g_window_list)
|
|
{
|
|
if (w->flags & WF_STICK_TO_BACK)
|
|
continue;
|
|
|
|
if (loc.x + width <= w->windowPos.x)
|
|
continue;
|
|
if (loc.x >= w->windowPos.x + w->width)
|
|
continue;
|
|
if (loc.y + height <= w->windowPos.y)
|
|
continue;
|
|
if (loc.y >= w->windowPos.y + w->height)
|
|
continue;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool WindowFitsWithinSpace(const ScreenCoordsXY& loc, int32_t width, int32_t height)
|
|
{
|
|
if (loc.x < 0)
|
|
return false;
|
|
if (loc.y <= TOP_TOOLBAR_HEIGHT && !(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
|
|
return false;
|
|
if (loc.x + width > context_get_width())
|
|
return false;
|
|
if (loc.y + height > context_get_height())
|
|
return false;
|
|
return WindowFitsBetweenOthers(loc, width, height);
|
|
}
|
|
|
|
static bool WindowFitsOnScreen(const ScreenCoordsXY& loc, int32_t width, int32_t height)
|
|
{
|
|
uint16_t screenWidth = context_get_width();
|
|
uint16_t screenHeight = context_get_height();
|
|
int32_t unk;
|
|
|
|
unk = -(width / 4);
|
|
if (loc.x < unk)
|
|
return false;
|
|
unk = screenWidth + (unk * 2);
|
|
if (loc.x > unk)
|
|
return false;
|
|
if (loc.y <= TOP_TOOLBAR_HEIGHT && !(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
|
|
return false;
|
|
unk = screenHeight - (height / 4);
|
|
if (loc.y > unk)
|
|
return false;
|
|
return WindowFitsBetweenOthers(loc, width, height);
|
|
}
|
|
|
|
static ScreenCoordsXY ClampWindowToScreen(const ScreenCoordsXY& pos, const int32_t screenWidth, const int32_t width)
|
|
{
|
|
auto screenPos = pos;
|
|
if (screenPos.x < 0)
|
|
screenPos.x = 0;
|
|
if (screenPos.x + width > screenWidth)
|
|
screenPos.x = screenWidth - width;
|
|
|
|
return screenPos;
|
|
}
|
|
|
|
static ScreenCoordsXY GetAutoPositionForNewWindow(int32_t width, int32_t height)
|
|
{
|
|
auto uiContext = GetContext()->GetUiContext();
|
|
auto screenWidth = uiContext->GetWidth();
|
|
auto screenHeight = uiContext->GetHeight();
|
|
|
|
// Place window in an empty corner of the screen
|
|
const ScreenCoordsXY cornerPositions[] = {
|
|
{ 0, 30 }, // topLeft
|
|
{ screenWidth - width, 30 }, // topRight
|
|
{ 0, screenHeight - 34 - height }, // bottomLeft
|
|
{ screenWidth - width, screenHeight - 34 - height } // bottomRight
|
|
};
|
|
|
|
for (const auto& cornerPos : cornerPositions)
|
|
{
|
|
if (WindowFitsWithinSpace(cornerPos, width, height))
|
|
{
|
|
return ClampWindowToScreen(cornerPos, screenWidth, width);
|
|
}
|
|
}
|
|
|
|
// Place window next to another
|
|
for (auto& w : g_window_list)
|
|
{
|
|
if (w->flags & WF_STICK_TO_BACK)
|
|
continue;
|
|
|
|
const ScreenCoordsXY offsets[] = { { w->width + 2, 0 },
|
|
{ -w->width - 2, 0 },
|
|
{ 0, w->height + 2 },
|
|
{ 0, -w->height - 2 },
|
|
{ w->width + 2, -w->height - 2 },
|
|
{ -w->width - 2, -w->height - 2 },
|
|
{ w->width + 2, w->height + 2 },
|
|
{ -w->width - 2, w->height + 2 } };
|
|
|
|
for (const auto& offset : offsets)
|
|
{
|
|
auto screenPos = w->windowPos + offset;
|
|
if (WindowFitsWithinSpace(screenPos, width, height))
|
|
{
|
|
return ClampWindowToScreen(screenPos, screenWidth, width);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Overlap
|
|
for (auto& w : g_window_list)
|
|
{
|
|
if (w->flags & WF_STICK_TO_BACK)
|
|
continue;
|
|
|
|
// clang-format off
|
|
const ScreenCoordsXY offsets[] = {
|
|
{ w->width + 2, 0 },
|
|
{ -w->width - 2, 0 },
|
|
{ 0, w->height + 2 },
|
|
{ 0, -w->height - 2 }
|
|
};
|
|
// clang-format on
|
|
|
|
for (const auto& offset : offsets)
|
|
{
|
|
auto screenPos = w->windowPos + offset;
|
|
if (WindowFitsOnScreen(screenPos, width, height))
|
|
{
|
|
return ClampWindowToScreen(screenPos, screenWidth, width);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cascade
|
|
auto screenPos = ScreenCoordsXY{ 0, 30 };
|
|
for (auto& w : g_window_list)
|
|
{
|
|
if (screenPos == w->windowPos)
|
|
{
|
|
screenPos.x += 5;
|
|
screenPos.y += 5;
|
|
}
|
|
}
|
|
|
|
return ClampWindowToScreen(screenPos, screenWidth, width);
|
|
}
|
|
|
|
static ScreenCoordsXY GetCentrePositionForNewWindow(int32_t width, int32_t height)
|
|
{
|
|
auto uiContext = GetContext()->GetUiContext();
|
|
auto screenWidth = uiContext->GetWidth();
|
|
auto screenHeight = uiContext->GetHeight();
|
|
return ScreenCoordsXY{ (screenWidth - width) / 2, std::max(TOP_TOOLBAR_HEIGHT + 1, (screenHeight - height) / 2) };
|
|
}
|
|
|
|
rct_window* WindowCreate(
|
|
std::unique_ptr<rct_window>&& wp, rct_windowclass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags)
|
|
{
|
|
if (flags & WF_AUTO_POSITION)
|
|
{
|
|
if (flags & WF_CENTRE_SCREEN)
|
|
{
|
|
pos = GetCentrePositionForNewWindow(width, height);
|
|
}
|
|
else
|
|
{
|
|
pos = GetAutoPositionForNewWindow(width, height);
|
|
}
|
|
}
|
|
|
|
// Check if there are any window slots left
|
|
// include WINDOW_LIMIT_RESERVED for items such as the main viewport and toolbars to not appear to be counted.
|
|
if (g_window_list.size() >= static_cast<size_t>(gConfigGeneral.window_limit + WINDOW_LIMIT_RESERVED))
|
|
{
|
|
// Close least recently used window
|
|
for (auto& w : g_window_list)
|
|
{
|
|
if (!(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT | WF_NO_AUTO_CLOSE)))
|
|
{
|
|
window_close(w.get());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Find right position to insert new window
|
|
auto itDestPos = g_window_list.end();
|
|
if (flags & WF_STICK_TO_BACK)
|
|
{
|
|
for (auto it = g_window_list.begin(); it != g_window_list.end(); it++)
|
|
{
|
|
if (!((*it)->flags & WF_STICK_TO_BACK))
|
|
{
|
|
itDestPos = it;
|
|
}
|
|
}
|
|
}
|
|
else if (!(flags & WF_STICK_TO_FRONT))
|
|
{
|
|
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
|
|
{
|
|
if (!((*it)->flags & WF_STICK_TO_FRONT))
|
|
{
|
|
itDestPos = it.base();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto itNew = g_window_list.insert(itDestPos, std::move(wp));
|
|
auto w = itNew->get();
|
|
|
|
// Setup window
|
|
w->classification = cls;
|
|
w->flags = flags;
|
|
|
|
// Play sounds and flash the window
|
|
if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)))
|
|
{
|
|
w->flags |= WF_WHITE_BORDER_MASK;
|
|
OpenRCT2::Audio::Play(OpenRCT2::Audio::SoundId::WindowOpen, 0, pos.x + (width / 2));
|
|
}
|
|
|
|
w->windowPos = pos;
|
|
w->width = width;
|
|
w->height = height;
|
|
w->min_width = width;
|
|
w->max_width = width;
|
|
w->min_height = height;
|
|
w->max_height = height;
|
|
|
|
w->viewport_focus_coordinates.var_480 = 0;
|
|
w->viewport_focus_coordinates.x = 0;
|
|
w->viewport_focus_coordinates.y = 0;
|
|
w->viewport_focus_coordinates.z = 0;
|
|
w->viewport_focus_coordinates.rotation = 0;
|
|
w->page = 0;
|
|
w->var_48C = 0;
|
|
w->var_492 = 0;
|
|
|
|
ColourSchemeUpdate(w);
|
|
w->Invalidate();
|
|
w->OnOpen();
|
|
return w;
|
|
}
|
|
|
|
rct_window* WindowCreate(
|
|
const ScreenCoordsXY& pos, int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls,
|
|
uint32_t flags)
|
|
{
|
|
auto w = std::make_unique<rct_window>();
|
|
w->event_handlers = event_handlers;
|
|
return WindowCreate(std::move(w), cls, pos, width, height, flags);
|
|
}
|
|
|
|
rct_window* WindowCreateAutoPos(
|
|
int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, uint32_t flags)
|
|
{
|
|
auto pos = GetAutoPositionForNewWindow(width, height);
|
|
return WindowCreate(pos, width, height, event_handlers, cls, flags);
|
|
}
|
|
|
|
rct_window* WindowCreateCentred(
|
|
int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, uint32_t flags)
|
|
{
|
|
auto pos = GetCentrePositionForNewWindow(width, height);
|
|
return WindowCreate(pos, width, height, event_handlers, cls, flags);
|
|
}
|
|
|
|
static int32_t WindowGetWidgetIndex(rct_window* w, rct_widget* widget)
|
|
{
|
|
int32_t i = 0;
|
|
for (rct_widget* widget2 = w->widgets; widget2->type != WindowWidgetType::Last; widget2++, i++)
|
|
if (widget == widget2)
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
static int32_t WindowGetScrollIndex(rct_window* w, int32_t targetWidgetIndex)
|
|
{
|
|
if (w->widgets[targetWidgetIndex].type != WindowWidgetType::Scroll)
|
|
return -1;
|
|
|
|
int32_t scrollIndex = 0;
|
|
rct_widgetindex widgetIndex = 0;
|
|
for (rct_widget* widget = w->widgets; widget->type != WindowWidgetType::Last; widget++, widgetIndex++)
|
|
{
|
|
if (widgetIndex == targetWidgetIndex)
|
|
break;
|
|
if (widget->type == WindowWidgetType::Scroll)
|
|
scrollIndex++;
|
|
}
|
|
|
|
return scrollIndex;
|
|
}
|
|
|
|
static rct_widget* WindowGetScrollWidget(rct_window* w, int32_t scrollIndex)
|
|
{
|
|
for (rct_widget* widget = w->widgets; widget->type != WindowWidgetType::Last; widget++)
|
|
{
|
|
if (widget->type != WindowWidgetType::Scroll)
|
|
continue;
|
|
|
|
if (scrollIndex == 0)
|
|
return widget;
|
|
scrollIndex--;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006E78E3
|
|
*/
|
|
static void WindowScrollWheelInput(rct_window* w, int32_t scrollIndex, int32_t wheel)
|
|
{
|
|
rct_scroll* scroll = &w->scrolls[scrollIndex];
|
|
rct_widget* widget = WindowGetScrollWidget(w, scrollIndex);
|
|
rct_widgetindex widgetIndex = WindowGetWidgetIndex(w, widget);
|
|
|
|
if (scroll->flags & VSCROLLBAR_VISIBLE)
|
|
{
|
|
int32_t size = widget->height() - 1;
|
|
if (scroll->flags & HSCROLLBAR_VISIBLE)
|
|
size -= 11;
|
|
size = std::max(0, scroll->v_bottom - size);
|
|
scroll->v_top = std::min(std::max(0, scroll->v_top + wheel), size);
|
|
}
|
|
else
|
|
{
|
|
int32_t size = widget->width() - 1;
|
|
if (scroll->flags & VSCROLLBAR_VISIBLE)
|
|
size -= 11;
|
|
size = std::max(0, scroll->h_right - size);
|
|
scroll->h_left = std::min(std::max(0, scroll->h_left + wheel), size);
|
|
}
|
|
|
|
WidgetScrollUpdateThumbs(w, widgetIndex);
|
|
widget_invalidate(w, widgetIndex);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006E793B
|
|
*/
|
|
static int32_t WindowWheelInput(rct_window* w, int32_t wheel)
|
|
{
|
|
int32_t i = 0;
|
|
for (rct_widget* widget = w->widgets; widget->type != WindowWidgetType::Last; widget++)
|
|
{
|
|
if (widget->type != WindowWidgetType::Scroll)
|
|
continue;
|
|
|
|
// Originally always checked first scroll view, bug maybe?
|
|
rct_scroll* scroll = &w->scrolls[i];
|
|
if (scroll->flags & (HSCROLLBAR_VISIBLE | VSCROLLBAR_VISIBLE))
|
|
{
|
|
WindowScrollWheelInput(w, i, wheel);
|
|
return 1;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006E79FB
|
|
*/
|
|
static void WindowViewportWheelInput(rct_window* w, int32_t wheel)
|
|
{
|
|
if (gScreenFlags & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TITLE_DEMO))
|
|
return;
|
|
|
|
if (wheel < 0)
|
|
window_zoom_in(w, true);
|
|
else if (wheel > 0)
|
|
window_zoom_out(w, true);
|
|
}
|
|
|
|
static bool WindowOtherWheelInput(rct_window* w, rct_widgetindex widgetIndex, int32_t wheel)
|
|
{
|
|
// HACK: Until we have a new window system that allows us to add new events like mouse wheel easily,
|
|
// this selective approach will have to do.
|
|
|
|
// Allow mouse wheel scrolling to increment or decrement the land tool size for various windows
|
|
auto widgetType = w->widgets[widgetIndex].type;
|
|
|
|
// Lower widgetIndex once or twice we got a type that matches, to allow scrolling on the increase/decrease buttons too
|
|
int32_t attempts = 0;
|
|
while (widgetType != WindowWidgetType::ImgBtn && widgetType != WindowWidgetType::Spinner && widgetIndex > 0)
|
|
{
|
|
switch (widgetType)
|
|
{
|
|
case WindowWidgetType::TrnBtn: // + and - for preview widget
|
|
case WindowWidgetType::Button: // + and - for spinner widget
|
|
{
|
|
if (attempts > 0)
|
|
{
|
|
// Verify that the previous button was of the same type
|
|
auto previousType = w->widgets[widgetIndex + 1].type;
|
|
if (previousType != widgetType)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
// The widget type is not an increment or decrement button
|
|
return false;
|
|
}
|
|
|
|
attempts++;
|
|
if (attempts > 2)
|
|
{
|
|
// We're 2 buttons up, and no preview or spinner widget was found
|
|
return false;
|
|
}
|
|
|
|
widgetIndex--;
|
|
widgetType = w->widgets[widgetIndex].type;
|
|
}
|
|
|
|
rct_widgetindex buttonWidgetIndex;
|
|
WindowWidgetType expectedType;
|
|
uint32_t expectedContent[2];
|
|
switch (widgetType)
|
|
{
|
|
case WindowWidgetType::ImgBtn:
|
|
buttonWidgetIndex = wheel < 0 ? widgetIndex + 2 : widgetIndex + 1;
|
|
expectedType = WindowWidgetType::TrnBtn;
|
|
expectedContent[0] = IMAGE_TYPE_REMAP | SPR_LAND_TOOL_DECREASE;
|
|
expectedContent[1] = IMAGE_TYPE_REMAP | SPR_LAND_TOOL_INCREASE;
|
|
break;
|
|
case WindowWidgetType::Spinner:
|
|
buttonWidgetIndex = wheel < 0 ? widgetIndex + 1 : widgetIndex + 2;
|
|
expectedType = WindowWidgetType::Button;
|
|
expectedContent[0] = STR_NUMERIC_UP;
|
|
expectedContent[1] = STR_NUMERIC_DOWN;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
if (WidgetIsDisabled(w, buttonWidgetIndex))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
auto button1Type = w->widgets[widgetIndex + 1].type;
|
|
auto button1Image = w->widgets[widgetIndex + 1].image;
|
|
auto button2Type = w->widgets[widgetIndex + 2].type;
|
|
auto button2Image = w->widgets[widgetIndex + 2].image;
|
|
if (button1Type != expectedType || button2Type != expectedType || button1Image != expectedContent[0]
|
|
|| button2Image != expectedContent[1])
|
|
{
|
|
return false;
|
|
}
|
|
|
|
window_event_mouse_down_call(w, buttonWidgetIndex);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006E7868
|
|
*/
|
|
void WindowAllWheelInput()
|
|
{
|
|
// Get wheel value
|
|
auto cursorState = context_get_cursor_state();
|
|
int32_t absolute_wheel = cursorState->wheel;
|
|
int32_t relative_wheel = absolute_wheel - _previousAbsoluteWheel;
|
|
int32_t pixel_scroll = relative_wheel * WindowScrollPixels;
|
|
_previousAbsoluteWheel = absolute_wheel;
|
|
|
|
if (relative_wheel == 0)
|
|
return;
|
|
|
|
// Check window cursor is over
|
|
if (!(input_test_flag(INPUT_FLAG_5)))
|
|
{
|
|
rct_window* w = window_find_from_point(cursorState->position);
|
|
if (w != nullptr)
|
|
{
|
|
// Check if main window
|
|
if (w->classification == WC_MAIN_WINDOW || w->classification == WC_VIEWPORT)
|
|
{
|
|
WindowViewportWheelInput(w, relative_wheel);
|
|
return;
|
|
}
|
|
|
|
// Check scroll view, cursor is over
|
|
rct_widgetindex widgetIndex = window_find_widget_from_point(w, cursorState->position);
|
|
if (widgetIndex != -1)
|
|
{
|
|
rct_widget* widget = &w->widgets[widgetIndex];
|
|
if (widget->type == WindowWidgetType::Scroll)
|
|
{
|
|
int32_t scrollIndex = WindowGetScrollIndex(w, widgetIndex);
|
|
rct_scroll* scroll = &w->scrolls[scrollIndex];
|
|
if (scroll->flags & (HSCROLLBAR_VISIBLE | VSCROLLBAR_VISIBLE))
|
|
{
|
|
WindowScrollWheelInput(w, WindowGetScrollIndex(w, widgetIndex), pixel_scroll);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (WindowOtherWheelInput(w, widgetIndex, pixel_scroll))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check other scroll views on window
|
|
if (WindowWheelInput(w, pixel_scroll))
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ApplyScreenSaverLockSetting()
|
|
{
|
|
gConfigGeneral.disable_screensaver ? SDL_DisableScreenSaver() : SDL_EnableScreenSaver();
|
|
}
|
|
|
|
/**
|
|
* Initialises scroll widgets to their virtual size.
|
|
* rct2: 0x006EAEB8
|
|
*/
|
|
void WindowInitScrollWidgets(rct_window* w)
|
|
{
|
|
rct_widget* widget;
|
|
rct_scroll* scroll;
|
|
int32_t widget_index, scroll_index;
|
|
int32_t width, height;
|
|
|
|
widget_index = 0;
|
|
scroll_index = 0;
|
|
for (widget = w->widgets; widget->type != WindowWidgetType::Last; widget++)
|
|
{
|
|
if (widget->type != WindowWidgetType::Scroll)
|
|
{
|
|
widget_index++;
|
|
continue;
|
|
}
|
|
|
|
scroll = &w->scrolls[scroll_index];
|
|
scroll->flags = 0;
|
|
width = 0;
|
|
height = 0;
|
|
window_get_scroll_size(w, scroll_index, &width, &height);
|
|
scroll->h_left = 0;
|
|
scroll->h_right = width + 1;
|
|
scroll->v_top = 0;
|
|
scroll->v_bottom = height + 1;
|
|
|
|
if (widget->content & SCROLL_HORIZONTAL)
|
|
scroll->flags |= HSCROLLBAR_VISIBLE;
|
|
if (widget->content & SCROLL_VERTICAL)
|
|
scroll->flags |= VSCROLLBAR_VISIBLE;
|
|
|
|
WidgetScrollUpdateThumbs(w, widget_index);
|
|
|
|
widget_index++;
|
|
scroll_index++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006EB15C
|
|
*/
|
|
void WindowDrawWidgets(rct_window* w, rct_drawpixelinfo* dpi)
|
|
{
|
|
rct_widget* widget;
|
|
rct_widgetindex widgetIndex;
|
|
|
|
if ((w->flags & WF_TRANSPARENT) && !(w->flags & WF_NO_BACKGROUND))
|
|
gfx_filter_rect(
|
|
dpi, { w->windowPos, w->windowPos + ScreenCoordsXY{ w->width - 1, w->height - 1 } }, FilterPaletteID::Palette51);
|
|
|
|
// todo: some code missing here? Between 006EB18C and 006EB260
|
|
|
|
widgetIndex = 0;
|
|
for (widget = w->widgets; widget->type != WindowWidgetType::Last; widget++)
|
|
{
|
|
// Check if widget is outside the draw region
|
|
if (w->windowPos.x + widget->left < dpi->x + dpi->width && w->windowPos.x + widget->right >= dpi->x)
|
|
if (w->windowPos.y + widget->top < dpi->y + dpi->height && w->windowPos.y + widget->bottom >= dpi->y)
|
|
WidgetDraw(dpi, w, widgetIndex);
|
|
|
|
widgetIndex++;
|
|
}
|
|
|
|
// todo: something missing here too? Between 006EC32B and 006EC369
|
|
|
|
if (w->flags & WF_WHITE_BORDER_MASK)
|
|
{
|
|
gfx_fill_rect_inset(
|
|
dpi, w->windowPos.x, w->windowPos.y, w->windowPos.x + w->width - 1, w->windowPos.y + w->height - 1, COLOUR_WHITE,
|
|
INSET_RECT_FLAG_FILL_NONE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006EA776
|
|
*/
|
|
static void WindowInvalidatePressedImageButton(rct_window* w)
|
|
{
|
|
rct_widgetindex widgetIndex;
|
|
rct_widget* widget;
|
|
|
|
widgetIndex = 0;
|
|
for (widget = w->widgets; widget->type != WindowWidgetType::Last; widget++, widgetIndex++)
|
|
{
|
|
if (widget->type != WindowWidgetType::ImgBtn)
|
|
continue;
|
|
|
|
if (WidgetIsPressed(w, widgetIndex) || WidgetIsActiveTool(w, widgetIndex))
|
|
gfx_set_dirty_blocks({ w->windowPos, w->windowPos + ScreenCoordsXY{ w->width, w->height } });
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006EA73F
|
|
*/
|
|
void InvalidateAllWindowsAfterInput()
|
|
{
|
|
window_visit_each([](rct_window* w) {
|
|
window_update_scroll_widgets(w);
|
|
WindowInvalidatePressedImageButton(w);
|
|
window_event_resize_call(w);
|
|
});
|
|
}
|
|
|
|
void Window::InvalidateWidget(rct_widgetindex widgetIndex)
|
|
{
|
|
widget_invalidate(this, widgetIndex);
|
|
}
|
|
|
|
bool Window::IsWidgetDisabled(rct_widgetindex widgetIndex) const
|
|
{
|
|
return (disabled_widgets & (1LL << widgetIndex)) != 0;
|
|
}
|
|
|
|
bool Window::IsWidgetPressed(rct_widgetindex widgetIndex) const
|
|
{
|
|
return (pressed_widgets & (1LL << widgetIndex)) != 0;
|
|
}
|
|
|
|
void Window::SetWidgetDisabled(rct_widgetindex widgetIndex, bool value)
|
|
{
|
|
if (value)
|
|
disabled_widgets |= (1ULL << widgetIndex);
|
|
else
|
|
disabled_widgets &= ~(1ULL << widgetIndex);
|
|
}
|
|
|
|
void Window::SetWidgetPressed(rct_widgetindex widgetIndex, bool value)
|
|
{
|
|
if (value)
|
|
pressed_widgets |= (1ULL << widgetIndex);
|
|
else
|
|
pressed_widgets &= ~(1ULL << widgetIndex);
|
|
}
|
|
|
|
void Window::SetCheckboxValue(rct_widgetindex widgetIndex, bool value)
|
|
{
|
|
SetWidgetPressed(widgetIndex, value);
|
|
}
|
|
|
|
void Window::DrawWidgets(rct_drawpixelinfo& dpi)
|
|
{
|
|
WindowDrawWidgets(this, &dpi);
|
|
}
|
|
|
|
void Window::Close()
|
|
{
|
|
window_close(this);
|
|
}
|