1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Move Widget, Window, Intent, MouseInput into OpenRCT2 namespace (#23642)

This commit is contained in:
Aaron van Geffen
2025-01-18 14:29:41 +01:00
committed by GitHub
parent b9f6b6f754
commit e1fa0b539d
21 changed files with 6070 additions and 6009 deletions

View File

@@ -41,80 +41,81 @@
#include <openrct2/world/Scenery.h>
#include <optional>
using namespace OpenRCT2;
using namespace OpenRCT2::Ui;
using namespace OpenRCT2::Ui::Windows;
struct RCTMouseData
namespace OpenRCT2
{
using namespace OpenRCT2::Ui;
using namespace OpenRCT2::Ui::Windows;
struct RCTMouseData
{
uint32_t x;
uint32_t y;
MouseState state;
};
};
static RCTMouseData _mouseInputQueue[64];
static uint8_t _mouseInputQueueReadIndex = 0;
static uint8_t _mouseInputQueueWriteIndex = 0;
static RCTMouseData _mouseInputQueue[64];
static uint8_t _mouseInputQueueReadIndex = 0;
static uint8_t _mouseInputQueueWriteIndex = 0;
static std::optional<uint32_t> _ticksSinceDragStart;
static WidgetRef _dragWidget;
static uint8_t _dragScrollIndex;
static int32_t _originalWindowWidth;
static int32_t _originalWindowHeight;
static std::optional<uint32_t> _ticksSinceDragStart;
static WidgetRef _dragWidget;
static uint8_t _dragScrollIndex;
static int32_t _originalWindowWidth;
static int32_t _originalWindowHeight;
static uint8_t _currentScrollIndex;
static uint8_t _currentScrollArea;
static uint8_t _currentScrollIndex;
static uint8_t _currentScrollArea;
ScreenCoordsXY gInputDragLast;
ScreenCoordsXY gInputDragLast;
uint32_t gTooltipCloseTimeout;
WidgetRef gTooltipWidget;
ScreenCoordsXY gTooltipCursor;
uint32_t gTooltipCloseTimeout;
WidgetRef gTooltipWidget;
ScreenCoordsXY gTooltipCursor;
static std::optional<uint32_t> _clickRepeatTicks;
static std::optional<uint32_t> _clickRepeatTicks;
static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords);
static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex);
static void InputWidgetOverChangeCheck(WindowClass windowClass, rct_windownumber windowNumber, WidgetIndex widgetIndex);
static void InputWidgetOverFlatbuttonInvalidate();
void ProcessMouseOver(const ScreenCoordsXY& screenCoords);
void ProcessMouseTool(const ScreenCoordsXY& screenCoords);
void InvalidateScroll();
static RCTMouseData* GetMouseInput();
void TileElementRightClick(int32_t type, TileElement* tileElement, const ScreenCoordsXY& screenCoords);
static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState state);
static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex);
void InputStateWidgetPressed(
static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords);
static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex);
static void InputWidgetOverChangeCheck(WindowClass windowClass, rct_windownumber windowNumber, WidgetIndex widgetIndex);
static void InputWidgetOverFlatbuttonInvalidate();
void ProcessMouseOver(const ScreenCoordsXY& screenCoords);
void ProcessMouseTool(const ScreenCoordsXY& screenCoords);
void InvalidateScroll();
static RCTMouseData* GetMouseInput();
void TileElementRightClick(int32_t type, TileElement* tileElement, const ScreenCoordsXY& screenCoords);
static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState state);
static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex);
void InputStateWidgetPressed(
const ScreenCoordsXY& screenCoords, MouseState state, WidgetIndex widgetIndex, WindowBase* w, Widget* widget);
void SetCursor(CursorID cursor_id);
static void InputWindowPositionContinue(
void SetCursor(CursorID cursor_id);
static void InputWindowPositionContinue(
WindowBase& w, const ScreenCoordsXY& lastScreenCoords, const ScreenCoordsXY& newScreenCoords);
static void InputWindowPositionEnd(WindowBase& w, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeContinue(WindowBase& w, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeEnd();
static void InputViewportDragBegin(WindowBase& w);
static void InputViewportDragContinue();
static void InputViewportDragEnd();
static void InputScrollBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputScrollContinue(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputScrollEnd();
static void InputScrollPartUpdateHThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t x, int32_t scroll_id);
static void InputScrollPartUpdateHLeft(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateHRight(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateVThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t y, int32_t scroll_id);
static void InputScrollPartUpdateVTop(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateVBottom(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputUpdateTooltip(WindowBase* w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputWindowPositionEnd(WindowBase& w, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeContinue(WindowBase& w, const ScreenCoordsXY& screenCoords);
static void InputWindowResizeEnd();
static void InputViewportDragBegin(WindowBase& w);
static void InputViewportDragContinue();
static void InputViewportDragEnd();
static void InputScrollBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputScrollContinue(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
static void InputScrollEnd();
static void InputScrollPartUpdateHThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t x, int32_t scroll_id);
static void InputScrollPartUpdateHLeft(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateHRight(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateVThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t y, int32_t scroll_id);
static void InputScrollPartUpdateVTop(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputScrollPartUpdateVBottom(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id);
static void InputUpdateTooltip(WindowBase* w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
#pragma region Mouse input
/**
/**
*
* rct2: 0x006EA627
*/
void GameHandleInput()
{
void GameHandleInput()
{
InvalidateAllWindowsAfterInput();
MouseState state;
@@ -139,14 +140,14 @@ void GameHandleInput()
ProcessMouseOver(screenCoords);
ProcessMouseTool(screenCoords);
}
}
}
/**
/**
*
* rct2: 0x006E83C7
*/
static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords)
{
static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords)
{
RCTMouseData* input = GetMouseInput();
if (input == nullptr)
{
@@ -158,14 +159,14 @@ static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords)
screenCoords.x = input->x;
screenCoords.y = input->y;
return input->state;
}
}
/**
/**
*
* rct2: 0x00407074
*/
static RCTMouseData* GetMouseInput()
{
static RCTMouseData* GetMouseInput()
{
// Check if that location has been written to yet
if (_mouseInputQueueReadIndex == _mouseInputQueueWriteIndex)
{
@@ -175,14 +176,14 @@ static RCTMouseData* GetMouseInput()
RCTMouseData* result = &_mouseInputQueue[_mouseInputQueueReadIndex];
_mouseInputQueueReadIndex = (_mouseInputQueueReadIndex + 1) % std::size(_mouseInputQueue);
return result;
}
}
/**
/**
*
* rct2: 0x006E957F
*/
static void InputScrollDragBegin(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
static void InputScrollDragBegin(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
_inputState = InputState::ScrollRight;
gInputDragLast = screenCoords;
_dragWidget.window_classification = w->classification;
@@ -192,14 +193,14 @@ static void InputScrollDragBegin(const ScreenCoordsXY& screenCoords, WindowBase*
_dragScrollIndex = WindowGetScrollDataIndex(*w, widgetIndex);
ContextHideCursor();
}
}
/**
/**
* Based on (heavily changed)
* rct2: 0x006E9E0E, 0x006E9ED0
*/
static void InputScrollDragContinue(const ScreenCoordsXY& screenCoords, WindowBase* w)
{
static void InputScrollDragContinue(const ScreenCoordsXY& screenCoords, WindowBase* w)
{
WidgetIndex widgetIndex = _dragWidget.widget_index;
uint8_t scrollIndex = _dragScrollIndex;
@@ -237,14 +238,14 @@ static void InputScrollDragContinue(const ScreenCoordsXY& screenCoords, WindowBa
};
ContextSetCursorPosition(fixedCursorPosition);
}
}
/**
/**
*
* rct2: 0x006E8ACB
*/
static void InputScrollRight(const ScreenCoordsXY& screenCoords, MouseState state)
{
static void InputScrollRight(const ScreenCoordsXY& screenCoords, MouseState state)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByNumber(_dragWidget.window_classification, _dragWidget.window_number);
if (w == nullptr)
@@ -273,14 +274,14 @@ static void InputScrollRight(const ScreenCoordsXY& screenCoords, MouseState stat
// Function only handles right button, so it's the only one relevant
break;
}
}
}
/**
/**
*
* rct2: 0x006E8655
*/
static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState state)
{
static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState state)
{
WindowBase* w;
Widget* widget;
WidgetIndex widgetIndex;
@@ -472,38 +473,38 @@ static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState
InputScrollRight(screenCoords, state);
break;
}
}
}
#pragma region Window positioning / resizing
void InputWindowPositionBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
void InputWindowPositionBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
_inputState = InputState::PositioningWindow;
gInputDragLast = screenCoords - w.windowPos;
_dragWidget.window_classification = w.classification;
_dragWidget.window_number = w.number;
_dragWidget.widget_index = widgetIndex;
}
}
static void InputWindowPositionContinue(
static void InputWindowPositionContinue(
WindowBase& w, const ScreenCoordsXY& lastScreenCoords, const ScreenCoordsXY& newScreenCoords)
{
{
int32_t snapProximity;
snapProximity = (w.flags & WF_NO_SNAPPING) ? 0 : Config::Get().general.WindowSnapProximity;
WindowMoveAndSnap(w, newScreenCoords - lastScreenCoords, snapProximity);
}
}
static void InputWindowPositionEnd(WindowBase& w, const ScreenCoordsXY& screenCoords)
{
static void InputWindowPositionEnd(WindowBase& w, const ScreenCoordsXY& screenCoords)
{
_inputState = InputState::Normal;
gTooltipCloseTimeout = 0;
gTooltipWidget = _dragWidget;
w.OnMoved(screenCoords);
}
}
static void InputWindowResizeBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
static void InputWindowResizeBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
_inputState = InputState::Resizing;
gInputDragLast = screenCoords;
_dragWidget.window_classification = w.classification;
@@ -511,10 +512,10 @@ static void InputWindowResizeBegin(WindowBase& w, WidgetIndex widgetIndex, const
_dragWidget.widget_index = widgetIndex;
_originalWindowWidth = w.width;
_originalWindowHeight = w.height;
}
}
static void InputWindowResizeContinue(WindowBase& w, const ScreenCoordsXY& screenCoords)
{
static void InputWindowResizeContinue(WindowBase& w, const ScreenCoordsXY& screenCoords)
{
if (screenCoords.y < static_cast<int32_t>(ContextGetHeight()) - 2)
{
auto differentialCoords = screenCoords - gInputDragLast;
@@ -523,21 +524,21 @@ static void InputWindowResizeContinue(WindowBase& w, const ScreenCoordsXY& scree
WindowResize(w, targetWidth, targetHeight);
}
}
}
static void InputWindowResizeEnd()
{
static void InputWindowResizeEnd()
{
_inputState = InputState::Normal;
gTooltipCloseTimeout = 0;
gTooltipWidget = _dragWidget;
}
}
#pragma endregion
#pragma region Viewport dragging
static void InputViewportDragBegin(WindowBase& w)
{
static void InputViewportDragBegin(WindowBase& w)
{
w.flags &= ~WF_SCROLLING_TO_LOCATION;
_inputState = InputState::ViewportRight;
_dragWidget.window_classification = w.classification;
@@ -552,10 +553,10 @@ static void InputViewportDragBegin(WindowBase& w)
WindowUnfollowSprite(w);
// gInputFlags |= INPUT_FLAG_5;
}
}
static void InputViewportDragContinue()
{
static void InputViewportDragContinue()
{
WindowBase* w;
Viewport* viewport;
@@ -592,7 +593,8 @@ static void InputViewportDragContinue()
// As the user moved the mouse, don't interpret it as right click in any case.
_ticksSinceDragStart = std::nullopt;
// applying the zoom only with negative values avoids a "deadzone" effect where small positive value round to zero.
// applying the zoom only with negative values avoids a "deadzone" effect where small positive value round to
// zero.
const bool posX = differentialCoords.x > 0;
const bool posY = differentialCoords.y > 0;
differentialCoords.x = (viewport->zoom + 1).ApplyTo(-std::abs(differentialCoords.x));
@@ -620,20 +622,20 @@ static void InputViewportDragContinue()
{
ContextSetCursorPosition(gInputDragLast);
}
}
}
static void InputViewportDragEnd()
{
static void InputViewportDragEnd()
{
_inputState = InputState::Reset;
ContextShowCursor();
}
}
#pragma endregion
#pragma region Scroll bars
static void InputScrollBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
static void InputScrollBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
const auto& widget = w.widgets[widgetIndex];
_inputState = InputState::ScrollLeft;
@@ -700,10 +702,10 @@ static void InputScrollBegin(WindowBase& w, WidgetIndex widgetIndex, const Scree
}
WidgetScrollUpdateThumbs(w, widgetIndex);
WindowInvalidateByNumber(w.classification, w.number);
}
}
static void InputScrollContinue(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
static void InputScrollContinue(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
int32_t scroll_part, scroll_id;
const auto& widget = w.widgets[widgetIndex];
@@ -757,20 +759,20 @@ static void InputScrollContinue(WindowBase& w, WidgetIndex widgetIndex, const Sc
InputScrollPartUpdateVBottom(w, widgetIndex, scroll_id);
break;
}
}
}
static void InputScrollEnd()
{
static void InputScrollEnd()
{
_inputState = InputState::Reset;
InvalidateScroll();
}
}
/**
/**
*
* rct2: 0x006E98F2
*/
static void InputScrollPartUpdateHThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t x, int32_t scroll_id)
{
static void InputScrollPartUpdateHThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t x, int32_t scroll_id)
{
const auto& widget = w.widgets[widgetIndex];
auto& scroll = w.scrolls[scroll_id];
@@ -803,14 +805,14 @@ static void InputScrollPartUpdateHThumb(WindowBase& w, WidgetIndex widgetIndex,
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
/**
/**
*
* rct2: 0x006E99A9
*/
static void InputScrollPartUpdateVThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t y, int32_t scroll_id)
{
static void InputScrollPartUpdateVThumb(WindowBase& w, WidgetIndex widgetIndex, int32_t y, int32_t scroll_id)
{
const auto& widget = w.widgets[widgetIndex];
auto& scroll = w.scrolls[scroll_id];
@@ -843,14 +845,14 @@ static void InputScrollPartUpdateVThumb(WindowBase& w, WidgetIndex widgetIndex,
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
/**
/**
*
* rct2: 0x006E9A60
*/
static void InputScrollPartUpdateHLeft(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
static void InputScrollPartUpdateHLeft(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
if (windowMgr->FindByNumber(w.classification, w.number) != nullptr)
{
@@ -861,14 +863,14 @@ static void InputScrollPartUpdateHLeft(WindowBase& w, WidgetIndex widgetIndex, i
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
/**
/**
*
* rct2: 0x006E9ABF
*/
static void InputScrollPartUpdateHRight(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
static void InputScrollPartUpdateHRight(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
const auto& widget = w.widgets[widgetIndex];
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
@@ -889,14 +891,14 @@ static void InputScrollPartUpdateHRight(WindowBase& w, WidgetIndex widgetIndex,
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
/**
/**
*
* rct2: 0x006E9C37
*/
static void InputScrollPartUpdateVTop(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
static void InputScrollPartUpdateVTop(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
if (windowMgr->FindByNumber(w.classification, w.number) != nullptr)
{
@@ -907,14 +909,14 @@ static void InputScrollPartUpdateVTop(WindowBase& w, WidgetIndex widgetIndex, in
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
/**
/**
*
* rct2: 0x006E9C96
*/
static void InputScrollPartUpdateVBottom(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
static void InputScrollPartUpdateVBottom(WindowBase& w, WidgetIndex widgetIndex, int32_t scroll_id)
{
const auto& widget = w.widgets[widgetIndex];
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
@@ -935,18 +937,18 @@ static void InputScrollPartUpdateVBottom(WindowBase& w, WidgetIndex widgetIndex,
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidateByNumber(w.classification, w.number, widgetIndex);
}
}
}
#pragma endregion
#pragma region Widgets
/**
/**
*
* rct2: 0x006E9253
*/
static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
WindowClass windowClass = WindowClass::Null;
rct_windownumber windowNumber = 0;
Widget* widget = nullptr;
@@ -978,14 +980,14 @@ static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, W
{
InputUpdateTooltip(w, widgetIndex, screenCoords);
}
}
}
/**
/**
*
* rct2: 0x006E9269
*/
static void InputWidgetOverChangeCheck(WindowClass windowClass, rct_windownumber windowNumber, WidgetIndex widgetIndex)
{
static void InputWidgetOverChangeCheck(WindowClass windowClass, rct_windownumber windowNumber, WidgetIndex widgetIndex)
{
// Prevents invalid widgets being clicked source of bug is elsewhere
if (widgetIndex == kWidgetIndexNull)
return;
@@ -1006,14 +1008,14 @@ static void InputWidgetOverChangeCheck(WindowClass windowClass, rct_windownumber
if (windowClass != WindowClass::Null)
InputWidgetOverFlatbuttonInvalidate();
}
}
}
/**
* Used to invalidate flat button widgets when the mouse leaves and enters them. This should be generalised so that all widgets
* can use this in the future.
/**
* Used to invalidate flat button widgets when the mouse leaves and enters them. This should be generalised so that all
* widgets can use this in the future.
*/
static void InputWidgetOverFlatbuttonInvalidate()
{
static void InputWidgetOverFlatbuttonInvalidate()
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByNumber(gHoverWidget.window_classification, gHoverWidget.window_number);
if (w != nullptr)
@@ -1021,17 +1023,18 @@ static void InputWidgetOverFlatbuttonInvalidate()
w->OnPrepareDraw();
if (w->widgets[gHoverWidget.widget_index].type == WindowWidgetType::FlatBtn)
{
WidgetInvalidateByNumber(gHoverWidget.window_classification, gHoverWidget.window_number, gHoverWidget.widget_index);
WidgetInvalidateByNumber(
gHoverWidget.window_classification, gHoverWidget.window_number, gHoverWidget.widget_index);
}
}
}
}
/**
/**
*
* rct2: 0x006E95F9
*/
static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex)
{
WindowClass windowClass = WindowClass::Null;
rct_windownumber windowNumber = 0;
@@ -1129,14 +1132,14 @@ static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, W
}
break;
}
}
}
/**
/**
*
* rct2: 0x006ED833
*/
void ProcessMouseOver(const ScreenCoordsXY& screenCoords)
{
void ProcessMouseOver(const ScreenCoordsXY& screenCoords)
{
CursorID cursorId = CursorID::Arrow;
auto ft = Formatter();
ft.Add<StringId>(STR_NONE);
@@ -1210,14 +1213,14 @@ void ProcessMouseOver(const ScreenCoordsXY& screenCoords)
ViewportInteractionRightOver(screenCoords);
SetCursor(cursorId);
}
}
/**
/**
*
* rct2: 0x006ED801
*/
void ProcessMouseTool(const ScreenCoordsXY& screenCoords)
{
void ProcessMouseTool(const ScreenCoordsXY& screenCoords)
{
if (_inputFlags & INPUT_FLAG_TOOL_ACTIVE)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
@@ -1228,9 +1231,9 @@ void ProcessMouseTool(const ScreenCoordsXY& screenCoords)
else if (InputGetState() != InputState::ViewportRight)
w->OnToolUpdate(gCurrentToolWidget.widget_index, screenCoords);
}
}
}
const std::map<colour_t, StringId> kColourToTip = {
const std::map<colour_t, StringId> kColourToTip = {
{ COLOUR_BLACK, STR_COLOUR_BLACK_TIP },
{ COLOUR_GREY, STR_COLOUR_GREY_TIP },
{ COLOUR_WHITE, STR_COLOUR_WHITE_TIP },
@@ -1287,15 +1290,15 @@ const std::map<colour_t, StringId> kColourToTip = {
{ COLOUR_DULL_BROWN_LIGHT, STR_COLOUR_DULL_BROWN_LIGHT_TIP },
{ COLOUR_INVISIBLE, STR_COLOUR_INVISIBLE_TIP },
{ COLOUR_VOID, STR_COLOUR_VOID_TIP },
};
};
/**
/**
*
* rct2: 0x006E8DA7
*/
void InputStateWidgetPressed(
void InputStateWidgetPressed(
const ScreenCoordsXY& screenCoords, MouseState state, WidgetIndex widgetIndex, WindowBase* w, Widget* widget)
{
{
WindowClass cursor_w_class;
rct_windownumber cursor_w_number;
cursor_w_class = gPressedWidget.window_classification;
@@ -1524,7 +1527,8 @@ void InputStateWidgetPressed(
gDropdownLastColourHover = dropdown_index;
WindowTooltipClose();
WindowTooltipShow(OpenRCT2String{ kColourToTip.at(ColourDropDownIndexToColour(dropdown_index)), {} }, screenCoords);
WindowTooltipShow(
OpenRCT2String{ kColourToTip.at(ColourDropDownIndexToColour(dropdown_index)), {} }, screenCoords);
}
if (dropdown_index < Dropdown::ItemsMaxSize && Dropdown::IsDisabled(dropdown_index))
@@ -1545,10 +1549,10 @@ void InputStateWidgetPressed(
gDropdownLastColourHover = -1;
WindowTooltipClose();
}
}
}
static void InputUpdateTooltip(WindowBase* w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
static void InputUpdateTooltip(WindowBase* w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords)
{
if (gTooltipWidget.window_classification == WindowClass::Null)
{
if (gTooltipCursor == screenCoords)
@@ -1584,30 +1588,30 @@ static void InputUpdateTooltip(WindowBase* w, WidgetIndex widgetIndex, const Scr
WindowCloseByClass(WindowClass::Tooltip);
}
}
}
}
#pragma endregion
/**
/**
*
* rct2: 0x006ED990
*/
void SetCursor(CursorID cursor_id)
{
void SetCursor(CursorID cursor_id)
{
assert(cursor_id != CursorID::Undefined);
if (_inputState == InputState::Resizing)
{
cursor_id = CursorID::DiagonalArrows;
}
ContextSetCurrentCursor(cursor_id);
}
}
/**
/**
*
* rct2: 0x006E876D
*/
void InvalidateScroll()
{
void InvalidateScroll()
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByNumber(gPressedWidget.window_classification, gPressedWidget.window_number);
if (w != nullptr)
@@ -1616,13 +1620,13 @@ void InvalidateScroll()
w->scrolls[_currentScrollIndex].flags &= 0xFF11;
WindowInvalidateByNumber(gPressedWidget.window_classification, gPressedWidget.window_number);
}
}
}
/**
/**
* rct2: 0x00406C96
*/
void StoreMouseInput(MouseState state, const ScreenCoordsXY& screenCoords)
{
void StoreMouseInput(MouseState state, const ScreenCoordsXY& screenCoords)
{
uint32_t writeIndex = _mouseInputQueueWriteIndex;
uint32_t nextWriteIndex = (writeIndex + 1) % std::size(_mouseInputQueue);
@@ -1636,10 +1640,10 @@ void StoreMouseInput(MouseState state, const ScreenCoordsXY& screenCoords)
_mouseInputQueueWriteIndex = nextWriteIndex;
}
}
}
void GameHandleEdgeScroll()
{
void GameHandleEdgeScroll()
{
WindowBase* mainWindow;
int32_t scrollX, scrollY;
@@ -1670,10 +1674,10 @@ void GameHandleEdgeScroll()
scrollY = 1;
InputScrollViewport(ScreenCoordsXY(scrollX, scrollY));
}
}
void InputScrollViewport(const ScreenCoordsXY& scrollScreenCoords)
{
void InputScrollViewport(const ScreenCoordsXY& scrollScreenCoords)
{
WindowBase* mainWindow = WindowGetMain();
if (mainWindow == nullptr)
return;
@@ -1737,4 +1741,5 @@ void InputScrollViewport(const ScreenCoordsXY& scrollScreenCoords)
mainWindow->savedViewPos.y += dy;
_inputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
}
}
} // namespace OpenRCT2

View File

@@ -11,21 +11,24 @@
#include <openrct2/interface/Window.h>
enum class MouseState : uint32_t
namespace OpenRCT2
{
enum class MouseState : uint32_t
{
Released,
LeftPress,
LeftRelease,
RightPress,
RightRelease
};
};
extern ScreenCoordsXY gInputDragLast;
extern ScreenCoordsXY gInputDragLast;
void InputWindowPositionBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
void GameHandleInput();
void GameHandleEdgeScroll();
void InputWindowPositionBegin(WindowBase& w, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords);
void GameHandleInput();
void GameHandleEdgeScroll();
void StoreMouseInput(MouseState state, const ScreenCoordsXY& screenCoords);
void StoreMouseInput(MouseState state, const ScreenCoordsXY& screenCoords);
void InputScrollViewport(const ScreenCoordsXY& screenCoords);
void InputScrollViewport(const ScreenCoordsXY& screenCoords);
} // namespace OpenRCT2

View File

@@ -10,6 +10,7 @@
#pragma once
#include <openrct2-ui/interface/Window.h>
#include <openrct2/object/ObjectTypes.h>
constexpr uint16_t kLandToolMinimumSize = 1;
constexpr uint16_t kLandToolMaximumSize = 64;

View File

@@ -32,16 +32,17 @@
#include <openrct2/ui/WindowManager.h>
#include <openrct2/world/Location.hpp>
using namespace OpenRCT2;
using namespace OpenRCT2::Ui;
// 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)
namespace OpenRCT2
{
using namespace OpenRCT2::Ui;
// 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_DEAD)
@@ -61,10 +62,10 @@ static bool WindowFitsBetweenOthers(const ScreenCoordsXY& loc, int32_t width, in
}
return true;
}
}
static bool WindowFitsWithinSpace(const ScreenCoordsXY& loc, int32_t width, int32_t height)
{
static bool WindowFitsWithinSpace(const ScreenCoordsXY& loc, int32_t width, int32_t height)
{
if (loc.x < 0)
return false;
if (loc.y <= kTopToolbarHeight && !(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
@@ -74,10 +75,10 @@ static bool WindowFitsWithinSpace(const ScreenCoordsXY& loc, int32_t width, int3
if (loc.y + height > ContextGetHeight())
return false;
return WindowFitsBetweenOthers(loc, width, height);
}
}
static bool WindowFitsOnScreen(const ScreenCoordsXY& loc, int32_t width, int32_t height)
{
static bool WindowFitsOnScreen(const ScreenCoordsXY& loc, int32_t width, int32_t height)
{
uint16_t screenWidth = ContextGetWidth();
uint16_t screenHeight = ContextGetHeight();
int32_t unk;
@@ -94,11 +95,12 @@ static bool WindowFitsOnScreen(const ScreenCoordsXY& loc, int32_t width, int32_t
if (loc.y > unk)
return false;
return WindowFitsBetweenOthers(loc, width, height);
}
}
static ScreenCoordsXY ClampWindowToScreen(
const ScreenCoordsXY& pos, const int32_t screenWidth, const int32_t screenHeight, const int32_t width, const int32_t height)
{
static ScreenCoordsXY ClampWindowToScreen(
const ScreenCoordsXY& pos, const int32_t screenWidth, const int32_t screenHeight, const int32_t width,
const int32_t height)
{
auto screenPos = pos;
if (width > screenWidth || screenPos.x < 0)
screenPos.x = 0;
@@ -112,10 +114,10 @@ static ScreenCoordsXY ClampWindowToScreen(
screenPos.y = screenHeight + toolbarAllowance - height;
return screenPos;
}
}
static ScreenCoordsXY GetAutoPositionForNewWindow(int32_t width, int32_t height)
{
static ScreenCoordsXY GetAutoPositionForNewWindow(int32_t width, int32_t height)
{
auto uiContext = GetContext()->GetUiContext();
auto screenWidth = uiContext->GetWidth();
auto screenHeight = uiContext->GetHeight();
@@ -202,26 +204,27 @@ static ScreenCoordsXY GetAutoPositionForNewWindow(int32_t width, int32_t height)
}
return ClampWindowToScreen(screenPos, screenWidth, screenHeight, width, height);
}
}
static ScreenCoordsXY GetCentrePositionForNewWindow(int32_t width, int32_t height)
{
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(kTopToolbarHeight + 1, (screenHeight - height) / 2) };
}
}
static int32_t WindowGetWidgetIndex(const WindowBase& w, Widget* widget)
{
const auto it = std::find_if(w.widgets.begin(), w.widgets.end(), [&](auto& otherWidget) { return &otherWidget == widget; });
static int32_t WindowGetWidgetIndex(const WindowBase& w, Widget* widget)
{
const auto it = std::find_if(
w.widgets.begin(), w.widgets.end(), [&](auto& otherWidget) { return &otherWidget == widget; });
if (it == w.widgets.end())
return -1;
return std::distance(w.widgets.begin(), it);
}
}
static int32_t WindowGetScrollIndex(const WindowBase& w, int32_t targetWidgetIndex)
{
static int32_t WindowGetScrollIndex(const WindowBase& w, int32_t targetWidgetIndex)
{
if (w.widgets[targetWidgetIndex].type != WindowWidgetType::Scroll)
return -1;
@@ -236,10 +239,10 @@ static int32_t WindowGetScrollIndex(const WindowBase& w, int32_t targetWidgetInd
}
return scrollIndex;
}
}
static Widget* WindowGetScrollWidget(const WindowBase& w, int32_t scrollIndex)
{
static Widget* WindowGetScrollWidget(const WindowBase& w, int32_t scrollIndex)
{
for (WidgetIndex widgetIndex = 0; widgetIndex < w.widgets.size(); widgetIndex++)
{
auto& widget = w.widgets[widgetIndex];
@@ -252,14 +255,14 @@ static Widget* WindowGetScrollWidget(const WindowBase& w, int32_t scrollIndex)
}
return nullptr;
}
}
/**
/**
*
* rct2: 0x006E78E3
*/
static void WindowScrollWheelInput(WindowBase& w, int32_t scrollIndex, int32_t wheel)
{
static void WindowScrollWheelInput(WindowBase& w, int32_t scrollIndex, int32_t wheel)
{
auto& scroll = w.scrolls[scrollIndex];
Widget* widget = WindowGetScrollWidget(w, scrollIndex);
WidgetIndex widgetIndex = WindowGetWidgetIndex(w, widget);
@@ -283,14 +286,14 @@ static void WindowScrollWheelInput(WindowBase& w, int32_t scrollIndex, int32_t w
WidgetScrollUpdateThumbs(w, widgetIndex);
WidgetInvalidate(w, widgetIndex);
}
}
/**
/**
*
* rct2: 0x006E793B
*/
static int32_t WindowWheelInput(WindowBase& w, int32_t wheel)
{
static int32_t WindowWheelInput(WindowBase& w, int32_t wheel)
{
int32_t scrollIndex = 0;
for (WidgetIndex widgetIndex = 0; widgetIndex < w.widgets.size(); widgetIndex++)
{
@@ -309,14 +312,14 @@ static int32_t WindowWheelInput(WindowBase& w, int32_t wheel)
}
return 0;
}
}
/**
/**
*
* rct2: 0x006E79FB
*/
static void WindowViewportWheelInput(WindowBase& w, int32_t wheel)
{
static void WindowViewportWheelInput(WindowBase& w, int32_t wheel)
{
if (gScreenFlags & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TITLE_DEMO))
return;
@@ -324,10 +327,10 @@ static void WindowViewportWheelInput(WindowBase& w, int32_t wheel)
Windows::WindowZoomIn(w, true);
else if (wheel > 0)
Windows::WindowZoomOut(w, true);
}
}
static bool isSpinnerGroup(WindowBase& w, WidgetIndex index, WindowWidgetType buttonType)
{
static bool isSpinnerGroup(WindowBase& w, WidgetIndex index, WindowWidgetType buttonType)
{
const auto& widgets = w.widgets;
if (widgets[index].type != WindowWidgetType::Spinner && widgets[index].type != WindowWidgetType::ImgBtn)
@@ -340,10 +343,10 @@ static bool isSpinnerGroup(WindowBase& w, WidgetIndex index, WindowWidgetType bu
return false;
return true;
}
}
static std::optional<WidgetIndex> getSpinnerGroupWidgetIndex(WindowBase& w, WidgetIndex startIndex)
{
static std::optional<WidgetIndex> getSpinnerGroupWidgetIndex(WindowBase& w, WidgetIndex startIndex)
{
// We only iterate 3 times as we might be at the spinner or one of its buttons.
for (WidgetIndex index = 0; index < 3; index++)
{
@@ -365,11 +368,11 @@ static std::optional<WidgetIndex> getSpinnerGroupWidgetIndex(WindowBase& w, Widg
}
return std::nullopt;
}
}
// Allow mouse wheel scrolling to manipulate spinner widgets and tool sizes
static bool WindowOtherWheelInput(WindowBase& w, WidgetIndex widgetIndex, int32_t wheel)
{
// Allow mouse wheel scrolling to manipulate spinner widgets and tool sizes
static bool WindowOtherWheelInput(WindowBase& w, 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.
@@ -417,14 +420,14 @@ static bool WindowOtherWheelInput(WindowBase& w, WidgetIndex widgetIndex, int32_
w.OnMouseDown(targetWidgetIndex);
return true;
}
}
/**
/**
*
* rct2: 0x006E7868
*/
void WindowAllWheelInput()
{
void WindowAllWheelInput()
{
// Get wheel value
auto cursorState = ContextGetCursorState();
int32_t absolute_wheel = cursorState->wheel;
@@ -478,19 +481,19 @@ void WindowAllWheelInput()
}
}
}
}
}
void ApplyScreenSaverLockSetting()
{
void ApplyScreenSaverLockSetting()
{
Config::Get().general.DisableScreensaver ? SDL_DisableScreenSaver() : SDL_EnableScreenSaver();
}
}
/**
/**
*
* rct2: 0x006EA776
*/
static void WindowInvalidatePressedImageButton(const WindowBase& w)
{
static void WindowInvalidatePressedImageButton(const WindowBase& w)
{
for (WidgetIndex widgetIndex = 0; widgetIndex < w.widgets.size(); widgetIndex++)
{
auto& widget = w.widgets[widgetIndex];
@@ -500,10 +503,10 @@ static void WindowInvalidatePressedImageButton(const WindowBase& w)
if (WidgetIsPressed(w, widgetIndex) || isToolActive(w, widgetIndex))
GfxSetDirtyBlocks({ w.windowPos, w.windowPos + ScreenCoordsXY{ w.width, w.height } });
}
}
}
void Window::ScrollToViewport()
{
void Window::ScrollToViewport()
{
if (viewport == nullptr || !focus.has_value())
return;
@@ -512,75 +515,75 @@ void Window::ScrollToViewport()
auto mainWindow = WindowGetMain();
if (mainWindow != nullptr)
WindowScrollToLocation(*mainWindow, newCoords);
}
}
void Window::OnDraw(DrawPixelInfo& dpi)
{
void Window::OnDraw(DrawPixelInfo& dpi)
{
Windows::WindowDrawWidgets(*this, dpi);
}
}
void Window::OnDrawWidget(WidgetIndex widgetIndex, DrawPixelInfo& dpi)
{
void Window::OnDrawWidget(WidgetIndex widgetIndex, DrawPixelInfo& dpi)
{
WidgetDraw(dpi, *this, widgetIndex);
}
}
void Window::InitScrollWidgets()
{
void Window::InitScrollWidgets()
{
Windows::WindowInitScrollWidgets(*this);
}
}
void Window::InvalidateWidget(WidgetIndex widgetIndex)
{
void Window::InvalidateWidget(WidgetIndex widgetIndex)
{
WidgetInvalidate(*this, widgetIndex);
}
}
bool Window::IsWidgetDisabled(WidgetIndex widgetIndex) const
{
bool Window::IsWidgetDisabled(WidgetIndex widgetIndex) const
{
return WidgetIsDisabled(*this, widgetIndex);
}
}
bool Window::IsWidgetPressed(WidgetIndex widgetIndex) const
{
bool Window::IsWidgetPressed(WidgetIndex widgetIndex) const
{
return WidgetIsPressed(*this, widgetIndex);
}
}
void Window::SetWidgetEnabled(WidgetIndex widgetIndex, bool value)
{
void Window::SetWidgetEnabled(WidgetIndex widgetIndex, bool value)
{
WidgetSetEnabled(*this, widgetIndex, value);
}
}
void Window::SetWidgetDisabled(WidgetIndex widgetIndex, bool value)
{
void Window::SetWidgetDisabled(WidgetIndex widgetIndex, bool value)
{
WidgetSetDisabled(*this, widgetIndex, value);
}
}
void Window::SetWidgetDisabledAndInvalidate(WidgetIndex widgetIndex, bool value)
{
void Window::SetWidgetDisabledAndInvalidate(WidgetIndex widgetIndex, bool value)
{
bool oldState = IsWidgetDisabled(widgetIndex);
if (oldState != value)
{
WidgetSetDisabled(*this, widgetIndex, value);
InvalidateWidget(widgetIndex);
}
}
}
void Window::SetWidgetPressed(WidgetIndex widgetIndex, bool value)
{
void Window::SetWidgetPressed(WidgetIndex widgetIndex, bool value)
{
WidgetSetPressed(*this, widgetIndex, value);
}
}
void Window::SetCheckboxValue(WidgetIndex widgetIndex, bool value)
{
void Window::SetCheckboxValue(WidgetIndex widgetIndex, bool value)
{
SetWidgetPressed(widgetIndex, value);
}
}
void Window::DrawWidgets(DrawPixelInfo& dpi)
{
void Window::DrawWidgets(DrawPixelInfo& dpi)
{
Windows::WindowDrawWidgets(*this, dpi);
}
}
void Window::Close()
{
void Window::Close()
{
CloseWindowModifier modifier = GetCloseModifier();
if (modifier == CloseWindowModifier::Shift)
@@ -595,20 +598,20 @@ void Window::Close()
{
WindowClose(*this);
}
}
}
void Window::CloseOthers()
{
void Window::CloseOthers()
{
WindowCloseAllExceptNumberAndClass(number, classification);
}
}
void Window::CloseOthersOfThisClass()
{
void Window::CloseOthersOfThisClass()
{
WindowCloseByClass(classification);
}
}
CloseWindowModifier Window::GetCloseModifier()
{
CloseWindowModifier Window::GetCloseModifier()
{
CloseWindowModifier lastModifier = CloseWindowModifier::None;
if (gLastCloseModifier.window.number == number && gLastCloseModifier.window.classification == classification)
@@ -619,18 +622,18 @@ CloseWindowModifier Window::GetCloseModifier()
gLastCloseModifier.modifier = CloseWindowModifier::None;
return lastModifier;
}
}
void Window::TextInputOpen(
void Window::TextInputOpen(
WidgetIndex callWidget, StringId title, StringId description, const Formatter& descriptionArgs, StringId existingText,
uintptr_t existingArgs, int32_t maxLength)
{
{
OpenRCT2::Ui::Windows::WindowTextInputOpen(
this, callWidget, title, description, descriptionArgs, existingText, existingArgs, maxLength);
}
}
void Window::ResizeFrame()
{
void Window::ResizeFrame()
{
// Frame
widgets[0].right = width - 1;
widgets[0].bottom = height - 1;
@@ -647,18 +650,18 @@ void Window::ResizeFrame()
widgets[2].left = width - 3 - kCloseButtonWidth;
widgets[2].right = width - 3;
}
}
}
void Window::ResizeFrameWithPage()
{
void Window::ResizeFrameWithPage()
{
ResizeFrame();
// Page background
widgets[3].right = width - 1;
widgets[3].bottom = height - 1;
}
}
void Window::ResizeSpinner(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size)
{
void Window::ResizeSpinner(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size)
{
auto right = origin.x + size.width - 1;
auto bottom = origin.y + size.height - 1;
widgets[widgetIndex].left = origin.x;
@@ -675,10 +678,10 @@ void Window::ResizeSpinner(WidgetIndex widgetIndex, const ScreenCoordsXY& origin
widgets[widgetIndex + 2].top = origin.y + 1;
widgets[widgetIndex + 2].right = right - size.height - 1;
widgets[widgetIndex + 2].bottom = bottom - 1;
}
}
void Window::ResizeDropdown(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size)
{
void Window::ResizeDropdown(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size)
{
auto right = origin.x + size.width - 1;
auto bottom = origin.y + size.height - 1;
widgets[widgetIndex].left = origin.x;
@@ -690,10 +693,10 @@ void Window::ResizeDropdown(WidgetIndex widgetIndex, const ScreenCoordsXY& origi
widgets[widgetIndex + 1].top = origin.y + 1;
widgets[widgetIndex + 1].right = right - 1;
widgets[widgetIndex + 1].bottom = bottom - 1;
}
}
void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_tab_id)
{
void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_tab_id)
{
int32_t i, x = w->widgets[start_tab_id].left;
int32_t tab_width = w->widgets[start_tab_id].width();
@@ -714,13 +717,14 @@ void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_ta
widget.right = 0;
}
}
}
}
ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w)
{
ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w)
{
const uint8_t buttonOffset = (Config::Get().interface.WindowButtonsOnTheLeft) ? kCloseButtonWidth + 2 : 0;
return w.windowPos + ScreenCoordsXY{ 2 + buttonOffset, 2 };
}
}
} // namespace OpenRCT2
namespace OpenRCT2::Ui::Windows
{

View File

@@ -14,10 +14,12 @@
struct TextInputSession;
struct Window : WindowBase
namespace OpenRCT2
{
virtual void OnDraw(DrawPixelInfo& dpi) override;
virtual void OnDrawWidget(WidgetIndex widgetIndex, DrawPixelInfo& dpi) override;
struct Window : WindowBase
{
void OnDraw(DrawPixelInfo& dpi) override;
void OnDrawWidget(WidgetIndex widgetIndex, DrawPixelInfo& dpi) override;
void ScrollToViewport();
void InitScrollWidgets();
@@ -35,20 +37,21 @@ struct Window : WindowBase
void CloseOthersOfThisClass();
CloseWindowModifier GetCloseModifier();
void TextInputOpen(
WidgetIndex callWidget, StringId title, StringId description, const Formatter& descriptionArgs, StringId existingText,
uintptr_t existingArgs, int32_t maxLength);
WidgetIndex callWidget, StringId title, StringId description, const Formatter& descriptionArgs,
StringId existingText, uintptr_t existingArgs, int32_t maxLength);
void ResizeFrame();
void ResizeFrameWithPage();
void ResizeSpinner(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size);
void ResizeDropdown(WidgetIndex widgetIndex, const ScreenCoordsXY& origin, const ScreenSize& size);
};
};
void WindowAllWheelInput();
void ApplyScreenSaverLockSetting();
void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_tab_id);
ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w);
void WindowAllWheelInput();
void ApplyScreenSaverLockSetting();
void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_tab_id);
ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w);
} // namespace OpenRCT2
namespace OpenRCT2::Ui::Windows
{

View File

@@ -830,7 +830,7 @@ std::optional<RowColumn> CustomListView::GetItemIndexAt(const ScreenCoordsXY& po
return result;
}
Widget* CustomListView::GetWidget() const
OpenRCT2::Widget* CustomListView::GetWidget() const
{
size_t scrollIndex = 0;
for (WidgetIndex widgetIndex = 0; widgetIndex < ParentWindow->widgets.size(); widgetIndex++)

View File

@@ -11,6 +11,7 @@
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Identifiers.h>
#include <openrct2/world/ScenerySelection.h>
#include <string_view>
struct ObjectEntryDescriptor;

View File

@@ -25,12 +25,13 @@ enum class CursorID : uint8_t;
namespace OpenRCT2
{
struct IStream;
}
class Intent;
struct WindowBase;
} // namespace OpenRCT2
struct ITrackDesignRepository;
struct IGameStateSnapshots;
class Intent;
struct WindowBase;
struct NewVersionInfo;
struct TTFFontDescriptor;
@@ -221,12 +222,12 @@ int32_t ContextGetWidth();
int32_t ContextGetHeight();
bool ContextHasFocus();
void ContextSetCursorTrap(bool value);
WindowBase* ContextOpenWindow(WindowClass wc);
WindowBase* ContextOpenDetailWindow(uint8_t type, int32_t id);
WindowBase* ContextOpenWindowView(uint8_t view);
WindowBase* ContextShowError(StringId title, StringId message, const class Formatter& args, bool autoClose = false);
WindowBase* ContextOpenIntent(Intent* intent);
void ContextBroadcastIntent(Intent* intent);
OpenRCT2::WindowBase* ContextOpenWindow(WindowClass wc);
OpenRCT2::WindowBase* ContextOpenDetailWindow(uint8_t type, int32_t id);
OpenRCT2::WindowBase* ContextOpenWindowView(uint8_t view);
OpenRCT2::WindowBase* ContextShowError(StringId title, StringId message, const class Formatter& args, bool autoClose = false);
OpenRCT2::WindowBase* ContextOpenIntent(OpenRCT2::Intent* intent);
void ContextBroadcastIntent(OpenRCT2::Intent* intent);
void ContextForceCloseWindowByClass(WindowClass wc);
void ContextHandleInput();
void ContextInputHandleKeyboard(bool isTitle);

View File

@@ -13,7 +13,11 @@
#include <memory>
class Intent;
namespace OpenRCT2
{
class Intent;
}
struct ParkLoadResult;
enum class GameCommand : int32_t
@@ -165,7 +169,7 @@ void PauseToggle();
bool GameIsPaused();
bool GameIsNotPaused();
void SaveGame();
std::unique_ptr<Intent> CreateSaveGameAsIntent();
std::unique_ptr<OpenRCT2::Intent> CreateSaveGameAsIntent();
void SaveGameAs();
void SaveGameCmd(u8string_view name = {});
void SaveGameWithName(u8string_view name);

View File

@@ -12,34 +12,36 @@
#include "Context.h"
#include "Game.h"
InputState _inputState;
uint8_t _inputFlags;
namespace OpenRCT2
{
InputState _inputState;
uint8_t _inputFlags;
WidgetRef gHoverWidget;
WidgetRef gPressedWidget;
WidgetRef gHoverWidget;
WidgetRef gPressedWidget;
uint32_t _tooltipNotShownTimeout;
uint32_t _tooltipNotShownTimeout;
/**
/**
*
* rct2: 0x006E3B43
*/
void TitleHandleKeyboardInput()
{
void TitleHandleKeyboardInput()
{
ContextInputHandleKeyboard(true);
}
}
/**
/**
*
* rct2: 0x006E3B43
*/
void GameHandleKeyboardInput()
{
void GameHandleKeyboardInput()
{
ContextInputHandleKeyboard(false);
}
}
void InputSetFlag(INPUT_FLAGS flag, bool on)
{
void InputSetFlag(INPUT_FLAGS flag, bool on)
{
if (on)
{
_inputFlags |= flag;
@@ -48,29 +50,30 @@ void InputSetFlag(INPUT_FLAGS flag, bool on)
{
_inputFlags &= ~flag;
}
}
}
bool InputTestFlag(INPUT_FLAGS flag)
{
bool InputTestFlag(INPUT_FLAGS flag)
{
return _inputFlags & flag;
}
}
void InputResetFlags()
{
void InputResetFlags()
{
_inputFlags = 0;
}
}
void InputSetState(InputState state)
{
void InputSetState(InputState state)
{
_inputState = state;
}
}
InputState InputGetState()
{
InputState InputGetState()
{
return _inputState;
}
}
void ResetTooltipNotShown()
{
void ResetTooltipNotShown()
{
_tooltipNotShownTimeout = gCurrentRealTimeTicks + 50;
}
}
} // namespace OpenRCT2

View File

@@ -11,8 +11,10 @@
#include "interface/Window.h"
enum INPUT_FLAGS
namespace OpenRCT2
{
enum INPUT_FLAGS
{
INPUT_FLAG_WIDGET_PRESSED = (1 << 0),
// The dropdown can stay open if the mouse is released, set on flag Dropdown::Flag::StayOpen
@@ -34,10 +36,10 @@ enum INPUT_FLAGS
INPUT_FLAG_6 = (1 << 6),
INPUT_FLAG_VIEWPORT_SCROLLING = (1 << 7)
};
};
enum class InputState
{
enum class InputState
{
Reset,
Normal,
WidgetPressed,
@@ -48,28 +50,29 @@ enum class InputState
ScrollLeft,
Resizing,
ScrollRight
};
};
extern WidgetRef gHoverWidget;
extern WidgetRef gPressedWidget;
extern WidgetRef gHoverWidget;
extern WidgetRef gPressedWidget;
extern uint32_t gTooltipCloseTimeout;
extern WidgetRef gTooltipWidget;
extern ScreenCoordsXY gTooltipCursor;
extern uint32_t gTooltipCloseTimeout;
extern WidgetRef gTooltipWidget;
extern ScreenCoordsXY gTooltipCursor;
// TODO: Move to openrct2-ui and make static again
extern InputState _inputState;
extern uint8_t _inputFlags;
extern uint32_t _tooltipNotShownTimeout;
// TODO: Move to openrct2-ui and make static again
extern InputState _inputState;
extern uint8_t _inputFlags;
extern uint32_t _tooltipNotShownTimeout;
void TitleHandleKeyboardInput();
void GameHandleKeyboardInput();
void TitleHandleKeyboardInput();
void GameHandleKeyboardInput();
void InputSetFlag(INPUT_FLAGS flag, bool on);
bool InputTestFlag(INPUT_FLAGS flag);
void InputResetFlags();
void InputSetFlag(INPUT_FLAGS flag, bool on);
bool InputTestFlag(INPUT_FLAGS flag);
void InputResetFlags();
void InputSetState(InputState state);
InputState InputGetState();
void InputSetState(InputState state);
InputState InputGetState();
void ResetTooltipNotShown();
void ResetTooltipNotShown();
} // namespace OpenRCT2

File diff suppressed because it is too large Load Diff

View File

@@ -20,16 +20,19 @@ struct PaintSession;
struct PaintStruct;
struct DrawPixelInfo;
struct TileElement;
struct WindowBase;
struct EntityBase;
struct Guest;
struct Staff;
struct PaintEntry;
// Flags must currenly retain their values to avoid breaking plugins.
// Values can be changed when plugins move to using named constants.
enum : uint32_t
namespace OpenRCT2
{
struct WindowBase;
// Flags must currenly retain their values to avoid breaking plugins.
// Values can be changed when plugins move to using named constants.
enum : uint32_t
{
VIEWPORT_FLAG_NONE = 0u,
VIEWPORT_FLAG_GRIDLINES = (1u << 7),
@@ -67,7 +70,8 @@ enum : uint32_t
VIEWPORT_FLAG_INDEPEDENT_ROTATION = (1u << 30),
VIEWPORT_FLAG_RENDERING_INHIBITED = (1u << 31),
};
};
} // namespace OpenRCT2
enum class VisibilityKind
{
@@ -103,75 +107,78 @@ enum class ViewportVisibility : uint8_t
UndergroundViewGhostOff = 5,
};
constexpr uint16_t ViewportInteractionItemAll = std::numeric_limits<uint16_t>::max();
struct InteractionInfo
namespace OpenRCT2
{
constexpr uint16_t ViewportInteractionItemAll = std::numeric_limits<uint16_t>::max();
struct InteractionInfo
{
InteractionInfo() = default;
InteractionInfo(const PaintStruct* ps);
CoordsXY Loc;
TileElement* Element{};
EntityBase* Entity{};
ViewportInteractionItem interactionType = ViewportInteractionItem::None;
};
};
constexpr int32_t kMaxViewportCount = kWindowLimitMax;
constexpr int32_t kMaxViewportCount = kWindowLimitMax;
/**
/**
* A reference counter for whether something is forcing the grid lines to show. When the counter
* is decremented to 0, the grid lines are hidden.
*/
extern uint8_t gShowGridLinesRefCount;
extern uint8_t gShowLandRightsRefCount;
extern uint8_t gShowConstructionRightsRefCount;
extern uint8_t gShowGridLinesRefCount;
extern uint8_t gShowLandRightsRefCount;
extern uint8_t gShowConstructionRightsRefCount;
// rct2: 0x014234BC
extern Viewport* g_music_tracking_viewport;
// rct2: 0x014234BC
extern Viewport* g_music_tracking_viewport;
void ViewportInitAll();
std::optional<ScreenCoordsXY> centre_2d_coordinates(const CoordsXYZ& loc, Viewport* viewport);
void ViewportCreate(WindowBase* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus);
void ViewportRemove(Viewport* viewport);
void ViewportInitAll();
std::optional<ScreenCoordsXY> centre_2d_coordinates(const CoordsXYZ& loc, Viewport* viewport);
void ViewportCreate(WindowBase* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus);
void ViewportRemove(Viewport* viewport);
void ViewportsInvalidate(int32_t x, int32_t y, int32_t z0, int32_t z1, ZoomLevel maxZoom);
void ViewportsInvalidate(const CoordsXYZ& pos, int32_t width, int32_t minHeight, int32_t maxHeight, ZoomLevel maxZoom);
void ViewportsInvalidate(const ScreenRect& screenRect, ZoomLevel maxZoom = ZoomLevel{ -1 });
void ViewportUpdatePosition(WindowBase* window);
void ViewportUpdateSmartFollowGuest(WindowBase* window, const Guest& peep);
void ViewportRotateSingle(WindowBase* window, int32_t direction);
void ViewportRotateAll(int32_t direction);
void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport);
void ViewportsInvalidate(int32_t x, int32_t y, int32_t z0, int32_t z1, ZoomLevel maxZoom);
void ViewportsInvalidate(const CoordsXYZ& pos, int32_t width, int32_t minHeight, int32_t maxHeight, ZoomLevel maxZoom);
void ViewportsInvalidate(const ScreenRect& screenRect, ZoomLevel maxZoom = ZoomLevel{ -1 });
void ViewportUpdatePosition(WindowBase* window);
void ViewportUpdateSmartFollowGuest(WindowBase* window, const Guest& peep);
void ViewportRotateSingle(WindowBase* window, int32_t direction);
void ViewportRotateAll(int32_t direction);
void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport);
CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t rotation);
CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t rotation);
CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z, uint8_t rotation);
std::optional<CoordsXY> ScreenPosToMapPos(const ScreenCoordsXY& screenCoords, int32_t* direction);
CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z, uint8_t rotation);
std::optional<CoordsXY> ScreenPosToMapPos(const ScreenCoordsXY& screenCoords, int32_t* direction);
void ShowGridlines();
void HideGridlines();
void ShowLandRights();
void HideLandRights();
void ShowConstructionRights();
void HideConstructionRights();
void ViewportSetVisibility(ViewportVisibility mode);
void ShowGridlines();
void HideGridlines();
void ShowLandRights();
void HideLandRights();
void ShowConstructionRights();
void HideConstructionRights();
void ViewportSetVisibility(ViewportVisibility mode);
InteractionInfo GetMapCoordinatesFromPos(const ScreenCoordsXY& screenCoords, int32_t flags);
InteractionInfo GetMapCoordinatesFromPosWindow(WindowBase* window, const ScreenCoordsXY& screenCoords, int32_t flags);
InteractionInfo GetMapCoordinatesFromPos(const ScreenCoordsXY& screenCoords, int32_t flags);
InteractionInfo GetMapCoordinatesFromPosWindow(WindowBase* window, const ScreenCoordsXY& screenCoords, int32_t flags);
InteractionInfo SetInteractionInfoFromPaintSession(PaintSession* session, uint32_t viewFlags, uint16_t filter);
InteractionInfo SetInteractionInfoFromPaintSession(PaintSession* session, uint32_t viewFlags, uint16_t filter);
std::optional<CoordsXY> ScreenGetMapXY(const ScreenCoordsXY& screenCoords, Viewport** viewport);
std::optional<CoordsXY> ScreenGetMapXYWithZ(const ScreenCoordsXY& screenCoords, int32_t z);
std::optional<CoordsXY> ScreenGetMapXYQuadrant(const ScreenCoordsXY& screenCoords, uint8_t* quadrant);
std::optional<CoordsXY> ScreenGetMapXYQuadrantWithZ(const ScreenCoordsXY& screenCoords, int32_t z, uint8_t* quadrant);
std::optional<CoordsXY> ScreenGetMapXYSide(const ScreenCoordsXY& screenCoords, uint8_t* side);
std::optional<CoordsXY> ScreenGetMapXYSideWithZ(const ScreenCoordsXY& screenCoords, int32_t z, uint8_t* side);
std::optional<CoordsXY> ScreenGetMapXY(const ScreenCoordsXY& screenCoords, Viewport** viewport);
std::optional<CoordsXY> ScreenGetMapXYWithZ(const ScreenCoordsXY& screenCoords, int32_t z);
std::optional<CoordsXY> ScreenGetMapXYQuadrant(const ScreenCoordsXY& screenCoords, uint8_t* quadrant);
std::optional<CoordsXY> ScreenGetMapXYQuadrantWithZ(const ScreenCoordsXY& screenCoords, int32_t z, uint8_t* quadrant);
std::optional<CoordsXY> ScreenGetMapXYSide(const ScreenCoordsXY& screenCoords, uint8_t* side);
std::optional<CoordsXY> ScreenGetMapXYSideWithZ(const ScreenCoordsXY& screenCoords, int32_t z, uint8_t* side);
ScreenCoordsXY Translate3DTo2DWithZ(int32_t rotation, const CoordsXYZ& pos);
ScreenCoordsXY Translate3DTo2DWithZ(int32_t rotation, const CoordsXYZ& pos);
uint8_t GetCurrentRotation();
int32_t GetHeightMarkerOffset();
uint8_t GetCurrentRotation();
int32_t GetHeightMarkerOffset();
void ViewportSetSavedView();
void ViewportSetSavedView();
VisibilityKind GetPaintStructVisibility(const PaintStruct* ps, uint32_t viewFlags);
VisibilityKind GetPaintStructVisibility(const PaintStruct* ps, uint32_t viewFlags);
} // namespace OpenRCT2

View File

@@ -9,16 +9,20 @@
#pragma once
#include "../core/StringTypes.h"
#include "../drawing/ImageId.hpp"
#include "../localisation/StringIdType.h"
#include "../world/Location.hpp"
#include <cstdint>
struct WindowBase;
using WidgetIndex = uint16_t;
constexpr WidgetIndex kWidgetIndexNull = 0xFFFF;
enum class WindowWidgetType : uint8_t
namespace OpenRCT2
{
using WidgetIndex = uint16_t;
constexpr WidgetIndex kWidgetIndexNull = 0xFFFF;
enum class WindowWidgetType : uint8_t
{
Empty = 0,
Frame = 1,
Resize = 2,
@@ -43,23 +47,118 @@ enum class WindowWidgetType : uint8_t
ProgressBar = 29,
Custom = 28,
TextBox = 27,
};
};
constexpr uint8_t kCloseButtonWidth = 10;
using WidgetFlags = uint32_t;
namespace WIDGET_FLAGS
{
const WidgetFlags TEXT_IS_STRING = 1 << 0;
const WidgetFlags IS_PRESSED = 1 << 2;
const WidgetFlags IS_DISABLED = 1 << 3;
const WidgetFlags TOOLTIP_IS_STRING = 1 << 4;
const WidgetFlags IS_HIDDEN = 1 << 5;
const WidgetFlags IS_HOLDABLE = 1 << 6;
} // namespace WIDGET_FLAGS
constexpr int32_t kScrollableRowHeight = 12;
constexpr uint8_t kListRowHeight = 12;
constexpr uint8_t kTableCellHeight = 12;
constexpr uint8_t kButtonFaceHeight = 12;
constexpr uint8_t kSpinnerHeight = 12;
constexpr uint8_t kDropdownHeight = 12;
constexpr uint16_t kTextInputSize = 1024;
constexpr uint16_t kTopToolbarHeight = 27;
enum
{
enum
{
SCROLL_HORIZONTAL = (1 << 0),
SCROLL_VERTICAL = (1 << 1),
SCROLL_BOTH = SCROLL_HORIZONTAL | SCROLL_VERTICAL
};
};
struct Widget
{
WindowWidgetType type{};
uint8_t colour{};
int16_t left{};
int16_t right{};
int16_t top{};
int16_t bottom{};
union
{
uint32_t content;
ImageId image{};
StringId text;
utf8* string;
};
StringId tooltip{ STR_NONE };
// New properties
WidgetFlags flags{};
utf8* sztooltip{};
int16_t width() const
{
return right - left;
}
int16_t height() const
{
return bottom - top;
}
int16_t midX() const
{
return (left + right) / 2;
}
int16_t midY() const
{
return (top + bottom) / 2;
}
int16_t textTop() const
{
if (height() >= 10)
return std::max<int32_t>(top, top + (height() / 2) - 5);
return top - 1;
}
void moveRight(int32_t amount)
{
left += amount;
right += amount;
}
void moveDown(int32_t amount)
{
top += amount;
bottom += amount;
}
void moveTo(ScreenCoordsXY coords)
{
moveRight(coords.x - left);
moveDown(coords.y - top);
}
void moveToX(int16_t x)
{
moveRight(x - left);
}
void moveToY(int16_t y)
{
moveDown(y - top);
}
bool IsVisible() const
{
return !(flags & OpenRCT2::WIDGET_FLAGS::IS_HIDDEN);
}
};
constexpr uint8_t kCloseButtonWidth = 10;
constexpr int32_t kScrollableRowHeight = 12;
constexpr uint8_t kListRowHeight = 12;
constexpr uint8_t kTableCellHeight = 12;
constexpr uint8_t kButtonFaceHeight = 12;
constexpr uint8_t kSpinnerHeight = 12;
constexpr uint8_t kDropdownHeight = 12;
constexpr uint16_t kTextInputSize = 1024;
constexpr uint16_t kTopToolbarHeight = 27;
} // namespace OpenRCT2

View File

@@ -39,22 +39,23 @@
#include <iterator>
#include <list>
using namespace OpenRCT2;
namespace OpenRCT2
{
std::list<std::shared_ptr<WindowBase>> g_window_list;
WindowBase* gWindowAudioExclusive;
std::list<std::shared_ptr<WindowBase>> g_window_list;
WindowBase* gWindowAudioExclusive;
WindowCloseModifier gLastCloseModifier = { { WindowClass::Null, 0 }, CloseWindowModifier::None };
WindowCloseModifier gLastCloseModifier = { { WindowClass::Null, 0 }, CloseWindowModifier::None };
uint32_t gWindowUpdateTicks;
colour_t gCurrentWindowColours[3];
uint32_t gWindowUpdateTicks;
colour_t gCurrentWindowColours[3];
Tool gCurrentToolId;
WidgetRef gCurrentToolWidget;
Tool gCurrentToolId;
WidgetRef gCurrentToolWidget;
// converted from uint16_t values at 0x009A41EC - 0x009A4230
// these are percentage coordinates of the viewport to centre to, if a window is obscuring a location, the next is tried
// clang-format off
// converted from uint16_t values at 0x009A41EC - 0x009A4230
// these are percentage coordinates of the viewport to centre to, if a window is obscuring a location, the next is tried
// clang-format off
static constexpr float window_scroll_locations[][2] = {
{ 0.5f, 0.5f },
{ 0.75f, 0.5f },
@@ -74,36 +75,36 @@ static constexpr float window_scroll_locations[][2] = {
{ 0.125f, 0.875f },
{ 0.125f, 0.125f },
};
// clang-format on
// clang-format on
namespace OpenRCT2::WindowCloseFlags
{
namespace WindowCloseFlags
{
static constexpr uint32_t None = 0;
static constexpr uint32_t CloseSingle = (1 << 0);
} // namespace OpenRCT2::WindowCloseFlags
} // namespace WindowCloseFlags
static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
std::list<std::shared_ptr<WindowBase>>::iterator WindowGetIterator(const WindowBase* w)
{
std::list<std::shared_ptr<WindowBase>>::iterator WindowGetIterator(const WindowBase* w)
{
return std::find_if(g_window_list.begin(), g_window_list.end(), [w](const std::shared_ptr<WindowBase>& w2) -> bool {
return w == w2.get();
});
}
}
void WindowVisitEach(std::function<void(WindowBase*)> func)
{
void WindowVisitEach(std::function<void(WindowBase*)> func)
{
for (auto& w : g_window_list)
{
if (w->flags & WF_DEAD)
continue;
func(w.get());
}
}
}
void WindowSetFlagForAllViewports(uint32_t viewportFlag, bool enabled)
{
void WindowSetFlagForAllViewports(uint32_t viewportFlag, bool enabled)
{
WindowVisitEach([&](WindowBase* w) {
if (w->viewport != nullptr)
{
@@ -113,34 +114,34 @@ void WindowSetFlagForAllViewports(uint32_t viewportFlag, bool enabled)
w->viewport->flags &= ~viewportFlag;
}
});
}
}
/**
/**
*
* rct2: 0x006ED7B0
*/
void WindowDispatchUpdateAll()
{
void WindowDispatchUpdateAll()
{
// gTooltipNotShownTicks++;
WindowVisitEach([&](WindowBase* w) { w->OnUpdate(); });
}
}
void WindowUpdateAllViewports()
{
void WindowUpdateAllViewports()
{
WindowVisitEach([&](WindowBase* w) {
if (w->viewport != nullptr && WindowIsVisible(*w))
{
ViewportUpdatePosition(w);
}
});
}
}
/**
/**
*
* rct2: 0x006E77A1
*/
void WindowUpdateAll()
{
void WindowUpdateAll()
{
// Remove all windows in g_window_list that have the WF_DEAD flag
g_window_list.remove_if([](auto&& w) -> bool { return w->flags & WF_DEAD; });
@@ -166,15 +167,15 @@ void WindowUpdateAll()
auto windowManager = GetContext()->GetUiContext()->GetWindowManager();
windowManager->UpdateMouseWheel();
}
}
void WindowNotifyLanguageChange()
{
void WindowNotifyLanguageChange()
{
WindowVisitEach([&](WindowBase* w) { w->OnLanguageChange(); });
}
}
static void WindowCloseSurplus(int32_t cap, WindowClass avoid_classification)
{
static void WindowCloseSurplus(int32_t cap, WindowClass avoid_classification)
{
// find the amount of windows that are currently open
auto count = static_cast<int32_t>(g_window_list.size());
// difference between amount open and cap = amount to close
@@ -194,19 +195,20 @@ static void WindowCloseSurplus(int32_t cap, WindowClass avoid_classification)
}
}
// skip window if window matches specified WindowClass (as user may be modifying via options)
if (avoid_classification != WindowClass::Null && foundW != nullptr && foundW->classification == avoid_classification)
if (avoid_classification != WindowClass::Null && foundW != nullptr
&& foundW->classification == avoid_classification)
{
continue;
}
WindowClose(*foundW);
}
}
}
/*
/*
* Changes the maximum amount of windows allowed
*/
void WindowSetWindowLimit(int32_t value)
{
void WindowSetWindowLimit(int32_t value)
{
int32_t prev = Config::Get().general.WindowLimit;
int32_t val = std::clamp<int32_t>(value, kWindowLimitMin, kWindowLimitMax);
Config::Get().general.WindowLimit = val;
@@ -217,16 +219,16 @@ void WindowSetWindowLimit(int32_t value)
{
WindowCloseSurplus(val, WindowClass::Options);
}
}
}
/**
/**
* Closes the specified window.
* rct2: 0x006ECD4C
*
* @param window The window to close (esi).
*/
void WindowClose(WindowBase& w)
{
void WindowClose(WindowBase& w)
{
w.OnClose();
// Remove viewport
@@ -236,11 +238,11 @@ void WindowClose(WindowBase& w)
w.Invalidate();
w.flags |= WF_DEAD;
}
}
template<typename TPred>
static void WindowCloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None)
{
template<typename TPred>
static void WindowCloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None)
{
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); ++it)
{
auto& wnd = *(*it);
@@ -256,42 +258,43 @@ static void WindowCloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags
}
}
}
}
}
/**
/**
* Closes all windows with the specified window class.
* rct2: 0x006ECCF4
* @param cls (cl) with bit 15 set
*/
void WindowCloseByClass(WindowClass cls)
{
void WindowCloseByClass(WindowClass cls)
{
WindowCloseByCondition([&](WindowBase* w) -> bool { return w->classification == cls; });
}
}
/**
/**
* Closes all windows with specified window class and number.
* rct2: 0x006ECCF4
* @param cls (cl) without bit 15 set
* @param number (dx)
*/
void WindowCloseByNumber(WindowClass cls, rct_windownumber number)
{
WindowCloseByCondition([cls, number](WindowBase* w) -> bool { return w->classification == cls && w->number == number; });
}
void WindowCloseByNumber(WindowClass cls, rct_windownumber number)
{
WindowCloseByCondition(
[cls, number](WindowBase* w) -> bool { return w->classification == cls && w->number == number; });
}
// TODO: Refactor this to use variant once the new window class is done.
void WindowCloseByNumber(WindowClass cls, EntityId number)
{
// TODO: Refactor this to use variant once the new window class is done.
void WindowCloseByNumber(WindowClass cls, EntityId number)
{
WindowCloseByNumber(cls, static_cast<rct_windownumber>(number.ToUnderlying()));
}
}
/**
/**
* Closes the top-most window
*
* rct2: 0x006E403C
*/
void WindowCloseTop()
{
void WindowCloseTop()
{
WindowCloseByClass(WindowClass::Dropdown);
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR)
@@ -302,105 +305,105 @@ void WindowCloseTop()
auto pred = [](WindowBase* w) -> bool { return !(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)); };
WindowCloseByCondition(pred, WindowCloseFlags::CloseSingle);
}
}
/**
/**
* Closes all open windows
*
* rct2: 0x006EE927
*/
void WindowCloseAll()
{
void WindowCloseAll()
{
WindowCloseByClass(WindowClass::Dropdown);
WindowCloseByCondition([](WindowBase* w) -> bool { return !(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)); });
}
}
void WindowCloseAllExceptClass(WindowClass cls)
{
void WindowCloseAllExceptClass(WindowClass cls)
{
WindowCloseByClass(WindowClass::Dropdown);
WindowCloseByCondition([cls](WindowBase* w) -> bool {
return w->classification != cls && !(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT));
});
}
}
/**
/**
* Closes all windows, save for those having any of the passed flags.
*/
void WindowCloseAllExceptFlags(uint16_t flags)
{
void WindowCloseAllExceptFlags(uint16_t flags)
{
WindowCloseByCondition([flags](WindowBase* w) -> bool { return !(w->flags & flags); });
}
}
/**
/**
* Closes all windows except the specified window number and class.
* @param number (dx)
* @param cls (cl) without bit 15 set
*/
void WindowCloseAllExceptNumberAndClass(rct_windownumber number, WindowClass cls)
{
void WindowCloseAllExceptNumberAndClass(rct_windownumber number, WindowClass cls)
{
WindowCloseByClass(WindowClass::Dropdown);
WindowCloseByCondition([cls, number](WindowBase* w) -> bool {
return (!(w->number == number && w->classification == cls) && !(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)));
});
}
}
/**
/**
* Invalidates the specified window.
* rct2: 0x006EB13A
*
* @param window The window to invalidate (esi).
*/
template<typename TPred>
static void WindowInvalidateByCondition(TPred pred)
{
template<typename TPred>
static void WindowInvalidateByCondition(TPred pred)
{
WindowVisitEach([pred](WindowBase* w) {
if (pred(w))
{
w->Invalidate();
}
});
}
}
/**
/**
* Invalidates all windows with the specified window class.
* rct2: 0x006EC3AC
* @param cls (al) with bit 14 set
*/
void WindowInvalidateByClass(WindowClass cls)
{
void WindowInvalidateByClass(WindowClass cls)
{
WindowInvalidateByCondition([cls](WindowBase* w) -> bool { return w->classification == cls; });
}
}
/**
/**
* Invalidates all windows with the specified window class and number.
* rct2: 0x006EC3AC
*/
void WindowInvalidateByNumber(WindowClass cls, rct_windownumber number)
{
void WindowInvalidateByNumber(WindowClass cls, rct_windownumber number)
{
WindowInvalidateByCondition(
[cls, number](WindowBase* w) -> bool { return w->classification == cls && w->number == number; });
}
}
// TODO: Use variant for this once the window framework is done.
void WindowInvalidateByNumber(WindowClass cls, EntityId id)
{
// TODO: Use variant for this once the window framework is done.
void WindowInvalidateByNumber(WindowClass cls, EntityId id)
{
WindowInvalidateByNumber(cls, static_cast<rct_windownumber>(id.ToUnderlying()));
}
}
/**
/**
* Invalidates all windows.
*/
void WindowInvalidateAll()
{
void WindowInvalidateAll()
{
WindowVisitEach([](WindowBase* w) { w->Invalidate(); });
}
}
/**
/**
* Invalidates the specified widget of a window.
* rct2: 0x006EC402
*/
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex)
{
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex)
{
if (w.widgets.empty())
{
// This might be called before the window is fully created.
@@ -415,48 +418,48 @@ void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex)
GfxSetDirtyBlocks({ { w.windowPos + ScreenCoordsXY{ widget.left, widget.top } },
{ w.windowPos + ScreenCoordsXY{ widget.right + 1, widget.bottom + 1 } } });
}
}
template<typename TPred>
static void widget_invalidate_by_condition(TPred pred)
{
template<typename TPred>
static void widget_invalidate_by_condition(TPred pred)
{
WindowVisitEach([pred](WindowBase* w) {
if (pred(w))
{
w->Invalidate();
}
});
}
}
/**
/**
* Invalidates the specified widget of all windows that match the specified window class.
*/
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex)
{
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex)
{
WindowVisitEach([cls, widgetIndex](WindowBase* w) {
if (w->classification == cls)
{
WidgetInvalidate(*w, widgetIndex);
}
});
}
}
/**
/**
* Invalidates the specified widget of all windows that match the specified window class and number.
* rct2: 0x006EC3AC
*/
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex)
{
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex)
{
WindowVisitEach([cls, number, widgetIndex](WindowBase* w) {
if (w->classification == cls && w->number == number)
{
WidgetInvalidate(*w, widgetIndex);
}
});
}
}
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index)
{
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index)
{
int32_t i, result;
result = 0;
@@ -467,14 +470,14 @@ int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index)
result++;
}
return result;
}
}
/**
/**
*
* rct2: 0x006ECDA4
*/
WindowBase* WindowBringToFront(WindowBase& w)
{
WindowBase* WindowBringToFront(WindowBase& w)
{
if (!(w.flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)))
{
auto itSourcePos = WindowGetIterator(&w);
@@ -506,10 +509,10 @@ WindowBase* WindowBringToFront(WindowBase& w)
}
}
return &w;
}
}
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags)
{
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByClass(cls);
if (w != nullptr)
@@ -520,21 +523,21 @@ WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags)
}
return w;
}
}
WindowBase* WindowBringToFrontByClass(WindowClass cls)
{
WindowBase* WindowBringToFrontByClass(WindowClass cls)
{
return WindowBringToFrontByClassWithFlags(cls, WF_WHITE_BORDER_MASK);
}
}
/**
/**
*
* rct2: 0x006ED78A
* cls (cl)
* number (dx)
*/
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number)
{
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number)
{
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByNumber(cls, number);
if (w != nullptr)
@@ -545,14 +548,14 @@ WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number)
}
return w;
}
}
/**
/**
*
* rct2: 0x006EE65A
*/
void WindowPushOthersRight(WindowBase& window)
{
void WindowPushOthersRight(WindowBase& window)
{
WindowVisitEach([&window](WindowBase* w) {
if (w == &window)
return;
@@ -576,14 +579,14 @@ void WindowPushOthersRight(WindowBase& window)
if (w->viewport != nullptr)
w->viewport->pos.x += push_amount;
});
}
}
/**
/**
*
* rct2: 0x006EE6EA
*/
void WindowPushOthersBelow(WindowBase& w1)
{
void WindowPushOthersBelow(WindowBase& w1)
{
// Enumerate through all other windows
WindowVisitEach([&w1](WindowBase* w2) {
if (&w1 == w2)
@@ -614,14 +617,14 @@ void WindowPushOthersBelow(WindowBase& w1)
if (w2->viewport != nullptr)
w2->viewport->pos.y += push_amount;
});
}
}
/**
/**
*
* rct2: 0x006EE2E4
*/
WindowBase* WindowGetMain()
{
WindowBase* WindowGetMain()
{
for (auto& w : g_window_list)
{
if (w->flags & WF_DEAD)
@@ -632,9 +635,9 @@ WindowBase* WindowGetMain()
}
}
return nullptr;
}
}
/**
/**
*
* rct2: 0x006E7C9C
* @param w (esi)
@@ -642,8 +645,8 @@ WindowBase* WindowGetMain()
* @param y (ecx)
* @param z (edx)
*/
void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords)
{
void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords)
{
WindowUnfollowSprite(w);
if (w.viewport != nullptr)
{
@@ -716,11 +719,11 @@ void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords)
}
}
}
}
}
void WindowViewportGetMapCoordsByCursor(
void WindowViewportGetMapCoordsByCursor(
const WindowBase& w, int32_t* map_x, int32_t* map_y, int32_t* offset_x, int32_t* offset_y)
{
{
// Get mouse position to offset against.
auto mouseCoords = ContextGetCursorPositionScaled();
@@ -748,10 +751,10 @@ void WindowViewportGetMapCoordsByCursor(
// Compute cursor offset relative to tile.
*offset_x = w.viewport->zoom.ApplyTo(w.savedViewPos.x - (centreLoc->x + rebased_x));
*offset_y = w.viewport->zoom.ApplyTo(w.savedViewPos.y - (centreLoc->y + rebased_y));
}
}
void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t map_y, int32_t offset_x, int32_t offset_y)
{
void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t map_y, int32_t offset_x, int32_t offset_y)
{
// Get viewport coordinates centring around the tile.
int32_t z = TileElementHeight({ map_x, map_y });
auto centreLoc = centre_2d_coordinates({ map_x, map_y, z }, w.viewport);
@@ -772,23 +775,23 @@ void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t
// Apply offset to the viewport.
w.savedViewPos = { centreLoc->x + rebased_x + w.viewport->zoom.ApplyInversedTo(offset_x),
centreLoc->y + rebased_y + w.viewport->zoom.ApplyInversedTo(offset_y) };
}
}
/**
/**
* For all windows with viewports, ensure they do not have a zoom level less than the minimum.
*/
void WindowCheckAllValidZoom()
{
void WindowCheckAllValidZoom()
{
WindowVisitEach([](WindowBase* w) {
if (w->viewport != nullptr && w->viewport->zoom < ZoomLevel::min())
{
WindowZoomSet(*w, ZoomLevel::min(), false);
}
});
}
}
void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor)
{
void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor)
{
Viewport* v = w.viewport;
if (v == nullptr)
return;
@@ -833,14 +836,14 @@ void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor)
// a window on top of the viewport.
WindowBringToFront(w);
w.Invalidate();
}
}
/**
/**
* Splits a drawing of a window into regions that can be seen and are not hidden
* by other opaque overlapping windows.
*/
void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
if (!WindowIsVisible(w))
return;
@@ -889,13 +892,13 @@ void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, in
// No windows overlap
WindowDrawCore(dpi, w, left, top, right, bottom);
}
}
/**
/**
* Draws the given window and any other overlapping transparent windows.
*/
static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& 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);
@@ -917,10 +920,10 @@ static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int3
WindowDrawSingle(dpi, *v, left, top, right, bottom);
}
}
}
}
static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
assert(dpi.zoom_level == ZoomLevel{ 0 });
// Copy dpi so we can crop it
DrawPixelInfo copy = dpi;
@@ -977,34 +980,34 @@ static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, in
gCurrentWindowColours[2] = w.colours[2].colour;
w.OnDraw(copy);
}
}
bool isToolActive(WindowClass cls)
{
bool isToolActive(WindowClass cls)
{
return InputTestFlag(INPUT_FLAG_TOOL_ACTIVE) && gCurrentToolWidget.window_classification == cls;
}
}
bool isToolActive(WindowClass cls, rct_windownumber number)
{
bool isToolActive(WindowClass cls, rct_windownumber number)
{
return isToolActive(cls) && gCurrentToolWidget.window_number == number;
}
}
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex)
{
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex)
{
return isToolActive(cls) && gCurrentToolWidget.widget_index == widgetIndex;
}
}
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex, rct_windownumber number)
{
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex, rct_windownumber number)
{
return isToolActive(cls, widgetIndex) && gCurrentToolWidget.window_number == number;
}
}
bool isToolActive(const WindowBase& w, WidgetIndex widgetIndex)
{
bool isToolActive(const WindowBase& w, WidgetIndex widgetIndex)
{
return isToolActive(w.classification, widgetIndex, w.number);
}
}
/**
/**
*
* rct2: 0x006EE212
*
@@ -1012,8 +1015,8 @@ bool isToolActive(const WindowBase& w, WidgetIndex widgetIndex)
* @param widgetIndex (dx)
* @param w (esi)
*/
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool)
{
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool)
{
if (InputTestFlag(INPUT_FLAG_TOOL_ACTIVE))
{
if (w.classification == gCurrentToolWidget.window_classification && w.number == gCurrentToolWidget.window_number
@@ -1034,14 +1037,14 @@ bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool)
gCurrentToolWidget.window_number = w.number;
gCurrentToolWidget.widget_index = widgetIndex;
return false;
}
}
/**
/**
*
* rct2: 0x006EE281
*/
void ToolCancel()
{
void ToolCancel()
{
if (InputTestFlag(INPUT_FLAG_TOOL_ACTIVE))
{
InputSetFlag(INPUT_FLAG_TOOL_ACTIVE, false);
@@ -1056,22 +1059,24 @@ void ToolCancel()
{
// Invalidate tool widget
WidgetInvalidateByNumber(
gCurrentToolWidget.window_classification, gCurrentToolWidget.window_number, gCurrentToolWidget.widget_index);
gCurrentToolWidget.window_classification, gCurrentToolWidget.window_number,
gCurrentToolWidget.widget_index);
// Abort tool event
auto* windowMgr = GetContext()->GetUiContext()->GetWindowManager();
WindowBase* w = windowMgr->FindByNumber(gCurrentToolWidget.window_classification, gCurrentToolWidget.window_number);
WindowBase* w = windowMgr->FindByNumber(
gCurrentToolWidget.window_classification, gCurrentToolWidget.window_number);
if (w != nullptr)
w->OnToolAbort(gCurrentToolWidget.widget_index);
}
}
}
}
/**
/**
* rct2: 0x0066B905
*/
void WindowResizeGui(int32_t width, int32_t height)
{
void WindowResizeGui(int32_t width, int32_t height)
{
WindowResizeGuiScenarioEditor(width, height);
if (gScreenFlags & SCREEN_FLAGS_EDITOR)
return;
@@ -1118,13 +1123,13 @@ void WindowResizeGui(int32_t width, int32_t height)
}
GfxInvalidateScreen();
}
}
/**
/**
* rct2: 0x0066F0DD
*/
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height)
{
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height)
{
auto* mainWind = WindowGetMain();
if (mainWind != nullptr)
{
@@ -1154,26 +1159,26 @@ void WindowResizeGuiScenarioEditor(int32_t width, int32_t height)
bottomWind->windowPos.y = height - 32;
bottomWind->width = std::max(640, width);
}
}
}
/**
/**
*
* rct2: 0x006CBCC3
*/
void WindowCloseConstructionWindows()
{
void WindowCloseConstructionWindows()
{
WindowCloseByClass(WindowClass::RideConstruction);
WindowCloseByClass(WindowClass::Footpath);
WindowCloseByClass(WindowClass::TrackDesignList);
WindowCloseByClass(WindowClass::TrackDesignPlace);
}
}
/**
/**
* Update zoom based volume attenuation for ride music and clear music list.
* rct2: 0x006BC348
*/
void WindowUpdateViewportRideMusic()
{
void WindowUpdateViewportRideMusic()
{
RideAudio::ClearAllViewportInstances();
g_music_tracking_viewport = nullptr;
@@ -1195,19 +1200,19 @@ void WindowUpdateViewportRideMusic()
Audio::gVolumeAdjustZoom = 60;
break;
}
}
}
/**
/**
*
* rct2: 0x006EE3C3
*/
void TextinputCancel()
{
void TextinputCancel()
{
WindowCloseByClass(WindowClass::Textinput);
}
}
bool WindowIsVisible(WindowBase& w)
{
bool WindowIsVisible(WindowBase& w)
{
// w->visibility is used to prevent repeat calculations within an iteration by caching the result
if (w.visibility == VisibilityCache::Visible)
@@ -1246,9 +1251,9 @@ bool WindowIsVisible(WindowBase& w)
w.visibility = VisibilityCache::Visible;
w.viewport->visibility = VisibilityCache::Visible;
return true;
}
}
/**
/**
*
* rct2: 0x006E7499
* left (ax)
@@ -1256,8 +1261,8 @@ bool WindowIsVisible(WindowBase& w)
* right (dx)
* bottom (bp)
*/
void WindowDrawAll(DrawPixelInfo& dpi, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
void WindowDrawAll(DrawPixelInfo& dpi, int32_t left, int32_t top, int32_t right, int32_t bottom)
{
auto windowDPI = dpi.Crop({ left, top }, { right - left, bottom - top });
WindowVisitEach([&windowDPI, left, top, right, bottom](WindowBase* w) {
if (w->flags & WF_TRANSPARENT)
@@ -1268,10 +1273,10 @@ void WindowDrawAll(DrawPixelInfo& dpi, int32_t left, int32_t top, int32_t right,
return;
WindowDraw(windowDPI, *w, left, top, right, bottom);
});
}
}
Viewport* WindowGetPreviousViewport(Viewport* current)
{
Viewport* WindowGetPreviousViewport(Viewport* current)
{
bool foundPrevious = (current == nullptr);
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
{
@@ -1291,10 +1296,10 @@ Viewport* WindowGetPreviousViewport(Viewport* current)
}
}
return nullptr;
}
}
void WindowResetVisibilities()
{
void WindowResetVisibilities()
{
// reset window visibility status to unknown
WindowVisitEach([](WindowBase* w) {
w->visibility = VisibilityCache::Unknown;
@@ -1303,33 +1308,34 @@ void WindowResetVisibilities()
w->viewport->visibility = VisibilityCache::Unknown;
}
});
}
}
void WindowInitAll()
{
void WindowInitAll()
{
WindowCloseAllExceptFlags(0);
}
}
void WindowFollowSprite(WindowBase& w, EntityId spriteIndex)
{
void WindowFollowSprite(WindowBase& w, EntityId spriteIndex)
{
if (spriteIndex.ToUnderlying() < MAX_ENTITIES || spriteIndex.IsNull())
{
w.viewport_smart_follow_sprite = spriteIndex;
}
}
}
void WindowUnfollowSprite(WindowBase& w)
{
void WindowUnfollowSprite(WindowBase& w)
{
w.viewport_smart_follow_sprite = EntityId::GetNull();
w.viewport_target_sprite = EntityId::GetNull();
}
}
Viewport* WindowGetViewport(WindowBase* w)
{
Viewport* WindowGetViewport(WindowBase* w)
{
if (w == nullptr)
{
return nullptr;
}
return w->viewport;
}
}
} // namespace OpenRCT2

View File

@@ -11,156 +11,54 @@
#include "../Identifiers.h"
#include "../core/EnumUtils.hpp"
#include "../drawing/ImageId.hpp"
#include "../localisation/Formatter.h"
#include "../ride/RideTypes.h"
#include "../windows/TileInspectorGlobals.h"
#include "../world/Location.hpp"
#include "../world/ScenerySelection.h"
#include "Colour.h"
#include "Widget.h"
#include "WindowClasses.h"
#include "ZoomLevel.h"
#include <functional>
#include <limits>
#include <list>
#include <memory>
#include <utility>
#include <variant>
struct DrawPixelInfo;
struct WindowBase;
struct TrackDesignFileRef;
struct ScenarioIndexEntry;
struct WindowCloseModifier;
enum class VisibilityCache : uint8_t;
enum class CursorID : uint8_t;
enum class CloseWindowModifier : uint8_t;
using rct_windownumber = int16_t;
namespace OpenRCT2
{
enum class RideConstructionState : uint8_t;
}
using rct_windownumber = int16_t;
struct WindowIdentifier
{
struct WindowBase;
struct WindowCloseModifier;
enum class RideConstructionState : uint8_t;
struct WindowIdentifier
{
WindowClass classification;
rct_windownumber number;
};
};
struct WidgetIdentifier
{
struct WidgetIdentifier
{
WindowIdentifier window;
WidgetIndex widget_index;
};
extern WindowCloseModifier gLastCloseModifier;
using WidgetFlags = uint32_t;
namespace OpenRCT2::WIDGET_FLAGS
{
const WidgetFlags TEXT_IS_STRING = 1 << 0;
const WidgetFlags IS_PRESSED = 1 << 2;
const WidgetFlags IS_DISABLED = 1 << 3;
const WidgetFlags TOOLTIP_IS_STRING = 1 << 4;
const WidgetFlags IS_HIDDEN = 1 << 5;
const WidgetFlags IS_HOLDABLE = 1 << 6;
} // namespace OpenRCT2::WIDGET_FLAGS
enum class WindowWidgetType : uint8_t;
struct Widget
{
WindowWidgetType type{};
uint8_t colour{};
int16_t left{};
int16_t right{};
int16_t top{};
int16_t bottom{};
union
{
uint32_t content;
ImageId image{};
StringId text;
utf8* string;
};
StringId tooltip{ STR_NONE };
// New properties
WidgetFlags flags{};
utf8* sztooltip{};
extern WindowCloseModifier gLastCloseModifier;
int16_t width() const
{
return right - left;
}
int16_t height() const
{
return bottom - top;
}
int16_t midX() const
{
return (left + right) / 2;
}
int16_t midY() const
{
return (top + bottom) / 2;
}
int16_t textTop() const
{
if (height() >= 10)
return std::max<int32_t>(top, top + (height() / 2) - 5);
return top - 1;
}
void moveRight(int32_t amount)
{
left += amount;
right += amount;
}
void moveDown(int32_t amount)
{
top += amount;
bottom += amount;
}
void moveTo(ScreenCoordsXY coords)
{
moveRight(coords.x - left);
moveDown(coords.y - top);
}
void moveToX(int16_t x)
{
moveRight(x - left);
}
void moveToY(int16_t y)
{
moveDown(y - top);
}
bool IsVisible() const
{
return !(flags & OpenRCT2::WIDGET_FLAGS::IS_HIDDEN);
}
};
/**
/**
* Viewport structure
*/
struct Viewport
{
struct Viewport
{
int32_t width{};
int32_t height{};
ScreenCoordsXY pos{};
@@ -198,10 +96,10 @@ struct Viewport
[[nodiscard]] ScreenCoordsXY ScreenToViewportCoord(const ScreenCoordsXY& screenCoord) const;
void Invalidate() const;
};
};
struct Focus
{
struct Focus
{
using CoordinateFocus = CoordsXYZ;
using EntityFocus = EntityId;
@@ -229,21 +127,21 @@ struct Focus
{
return !(*this == other);
}
};
};
struct WindowCloseModifier
{
struct WindowCloseModifier
{
WindowIdentifier window;
CloseWindowModifier modifier;
};
};
struct WindowBase;
struct WindowBase;
#define RCT_WINDOW_RIGHT(w) ((w)->windowPos.x + (w)->width)
#define RCT_WINDOW_BOTTOM(w) ((w)->windowPos.y + (w)->height)
enum WINDOW_FLAGS
{
enum WINDOW_FLAGS
{
/*
WF_TIMEOUT_SHL = 0,
WF_TIMEOUT_MASK = 7,
@@ -273,10 +171,10 @@ enum WINDOW_FLAGS
// Create only flags
WF_AUTO_POSITION = (1 << 16),
WF_CENTRE_SCREEN = (1 << 17),
};
};
enum
{
enum
{
WV_PARK_AWARDS,
WV_PARK_RATING,
WV_PARK_OBJECTIVE,
@@ -290,10 +188,10 @@ enum
WV_NEW_VERSION_INFO,
WV_FINANCE_MARKETING,
WV_CONTRIBUTORS,
};
};
enum WindowDetail
{
enum WindowDetail
{
WD_BANNER,
WD_NEW_CAMPAIGN,
WD_DEMOLISH_RIDE,
@@ -307,7 +205,8 @@ enum WindowDetail
WD_TRACK,
WD_NULL = 255,
};
};
} // namespace OpenRCT2
#define validate_global_widx(wc, widx) \
static_assert(widx == wc##__##widx, "Global WIDX of " #widx " doesn't match actual value.")
@@ -444,105 +343,109 @@ enum class Tool
Bulldozer = 27,
};
struct WidgetRef
namespace OpenRCT2
{
struct WidgetRef
{
WindowClass window_classification;
rct_windownumber window_number;
WidgetIndex widget_index;
};
};
extern Tool gCurrentToolId;
extern WidgetRef gCurrentToolWidget;
extern Tool gCurrentToolId;
extern WidgetRef gCurrentToolWidget;
using modal_callback = void (*)(int32_t result);
using CloseCallback = void (*)();
using modal_callback = void (*)(int32_t result);
using CloseCallback = void (*)();
constexpr int8_t kWindowLimitMin = 4;
constexpr int8_t kWindowLimitMax = 64;
constexpr int8_t kWindowLimitReserved = 4; // Used to reserve room for the main viewport, toolbars, etc.
constexpr int8_t kWindowLimitMin = 4;
constexpr int8_t kWindowLimitMax = 64;
constexpr int8_t kWindowLimitReserved = 4; // Used to reserve room for the main viewport, toolbars, etc.
extern WindowBase* gWindowAudioExclusive;
extern WindowBase* gWindowAudioExclusive;
extern uint32_t gWindowUpdateTicks;
extern uint32_t gWindowUpdateTicks;
extern colour_t gCurrentWindowColours[3];
extern colour_t gCurrentWindowColours[3];
std::list<std::shared_ptr<WindowBase>>::iterator WindowGetIterator(const WindowBase* w);
void WindowVisitEach(std::function<void(WindowBase*)> func);
std::list<std::shared_ptr<WindowBase>>::iterator WindowGetIterator(const WindowBase* w);
void WindowVisitEach(std::function<void(WindowBase*)> func);
void WindowSetFlagForAllViewports(uint32_t viewportFlag, bool enabled);
void WindowSetFlagForAllViewports(uint32_t viewportFlag, bool enabled);
void WindowDispatchUpdateAll();
void WindowUpdateAllViewports();
void WindowUpdateAll();
void WindowNotifyLanguageChange();
void WindowDispatchUpdateAll();
void WindowUpdateAllViewports();
void WindowUpdateAll();
void WindowNotifyLanguageChange();
void WindowSetWindowLimit(int32_t value);
void WindowSetWindowLimit(int32_t value);
WindowBase* WindowBringToFront(WindowBase& w);
WindowBase* WindowBringToFrontByClass(WindowClass cls);
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags);
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number);
WindowBase* WindowBringToFront(WindowBase& w);
WindowBase* WindowBringToFrontByClass(WindowClass cls);
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags);
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number);
void WindowClose(WindowBase& window);
void WindowCloseByClass(WindowClass cls);
void WindowCloseByNumber(WindowClass cls, rct_windownumber number);
void WindowCloseByNumber(WindowClass cls, EntityId number);
void WindowCloseTop();
void WindowCloseAll();
void WindowCloseAllExceptClass(WindowClass cls);
void WindowCloseAllExceptFlags(uint16_t flags);
void WindowCloseAllExceptNumberAndClass(rct_windownumber number, WindowClass cls);
void WindowInvalidateByClass(WindowClass cls);
void WindowInvalidateByNumber(WindowClass cls, rct_windownumber number);
void WindowInvalidateByNumber(WindowClass cls, EntityId id);
void WindowInvalidateAll();
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex);
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex);
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex);
void WindowClose(WindowBase& window);
void WindowCloseByClass(WindowClass cls);
void WindowCloseByNumber(WindowClass cls, rct_windownumber number);
void WindowCloseByNumber(WindowClass cls, EntityId number);
void WindowCloseTop();
void WindowCloseAll();
void WindowCloseAllExceptClass(WindowClass cls);
void WindowCloseAllExceptFlags(uint16_t flags);
void WindowCloseAllExceptNumberAndClass(rct_windownumber number, WindowClass cls);
void WindowInvalidateByClass(WindowClass cls);
void WindowInvalidateByNumber(WindowClass cls, rct_windownumber number);
void WindowInvalidateByNumber(WindowClass cls, EntityId id);
void WindowInvalidateAll();
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex);
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex);
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex);
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index);
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index);
void WindowPushOthersRight(WindowBase& w);
void WindowPushOthersBelow(WindowBase& w1);
void WindowPushOthersRight(WindowBase& w);
void WindowPushOthersBelow(WindowBase& w1);
WindowBase* WindowGetMain();
WindowBase* WindowGetMain();
void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords);
void WindowViewportGetMapCoordsByCursor(
void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords);
void WindowViewportGetMapCoordsByCursor(
const WindowBase& w, int32_t* map_x, int32_t* map_y, int32_t* offset_x, int32_t* offset_y);
void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t map_y, int32_t offset_x, int32_t offset_y);
void WindowCheckAllValidZoom();
void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor);
void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t map_y, int32_t offset_x, int32_t offset_y);
void WindowCheckAllValidZoom();
void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor);
void WindowDrawAll(DrawPixelInfo& dpi, int32_t left, int32_t top, int32_t right, int32_t bottom);
void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
void WindowDrawAll(DrawPixelInfo& dpi, int32_t left, int32_t top, int32_t right, int32_t bottom);
void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom);
bool isToolActive(WindowClass cls);
bool isToolActive(WindowClass cls, rct_windownumber number);
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex);
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex, rct_windownumber number);
bool isToolActive(const WindowBase& w, WidgetIndex widgetIndex);
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool);
void ToolCancel();
bool isToolActive(WindowClass cls);
bool isToolActive(WindowClass cls, rct_windownumber number);
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex);
bool isToolActive(WindowClass cls, WidgetIndex widgetIndex, rct_windownumber number);
bool isToolActive(const WindowBase& w, WidgetIndex widgetIndex);
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool);
void ToolCancel();
void WindowCloseConstructionWindows();
void WindowCloseConstructionWindows();
void WindowUpdateViewportRideMusic();
void WindowUpdateViewportRideMusic();
Viewport* WindowGetViewport(WindowBase* window);
Viewport* WindowGetViewport(WindowBase* window);
// Open window functions
void WindowResizeGui(int32_t width, int32_t height);
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height);
// Open window functions
void WindowResizeGui(int32_t width, int32_t height);
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height);
void TextinputCancel();
void TextinputCancel();
bool WindowIsVisible(WindowBase& w);
bool WindowIsVisible(WindowBase& w);
Viewport* WindowGetPreviousViewport(Viewport* current);
void WindowResetVisibilities();
void WindowInitAll();
Viewport* WindowGetPreviousViewport(Viewport* current);
void WindowResetVisibilities();
void WindowInitAll();
void WindowFollowSprite(WindowBase& w, EntityId spriteIndex);
void WindowUnfollowSprite(WindowBase& w);
void WindowFollowSprite(WindowBase& w, EntityId spriteIndex);
void WindowUnfollowSprite(WindowBase& w);
} // namespace OpenRCT2

View File

@@ -5,33 +5,36 @@
#include "Cursors.h"
#include "Viewport.h"
void WindowBase::SetLocation(const CoordsXYZ& coords)
namespace OpenRCT2
{
void WindowBase::SetLocation(const CoordsXYZ& coords)
{
WindowScrollToLocation(*this, coords);
flags &= ~WF_SCROLLING_TO_LOCATION;
}
}
void WindowBase::Invalidate()
{
void WindowBase::Invalidate()
{
GfxSetDirtyBlocks({ windowPos, windowPos + ScreenCoordsXY{ width, height } });
}
}
void WindowBase::RemoveViewport()
{
void WindowBase::RemoveViewport()
{
if (viewport == nullptr)
return;
ViewportRemove(viewport);
viewport = nullptr;
}
}
void WindowBase::SetWidgets(const std::span<const Widget> newWidgets)
{
void WindowBase::SetWidgets(const std::span<const Widget> newWidgets)
{
widgets.clear();
widgets.insert(widgets.end(), newWidgets.begin(), newWidgets.end());
}
}
CursorID WindowBase::OnCursor(WidgetIndex, const ScreenCoordsXY&, CursorID)
{
CursorID WindowBase::OnCursor(WidgetIndex, const ScreenCoordsXY&, CursorID)
{
return CursorID::Arrow;
}
}
} // namespace OpenRCT2

View File

@@ -9,12 +9,14 @@
#pragma once
#include "../localisation/Formatter.h"
#include "Colour.h"
#include "ScrollArea.h"
#include "Window.h"
#include <list>
#include <memory>
#include <span>
#include <vector>
enum class TileInspectorPage : int16_t;
@@ -28,12 +30,14 @@ struct RCTObjectEntry;
#pragma GCC diagnostic ignored "-Wsuggest-final-types"
#endif
/**
namespace OpenRCT2
{
/**
* Window structure
* size: 0x4C0
*/
struct WindowBase
{
struct WindowBase
{
Viewport* viewport{};
uint64_t disabled_widgets{};
uint64_t pressed_widgets{};
@@ -172,11 +176,12 @@ struct WindowBase
virtual void OnLanguageChange()
{
}
};
};
#ifdef __WARN_SUGGEST_FINAL_METHODS__
#pragma GCC diagnostic pop
#endif
// rct2: 0x01420078
extern std::list<std::shared_ptr<WindowBase>> g_window_list;
// rct2: 0x01420078
extern std::list<std::shared_ptr<WindowBase>> g_window_list;
} // namespace OpenRCT2

View File

@@ -39,13 +39,13 @@ void NetworkPlayer::Write(NetworkPacket& packet)
void NetworkPlayer::IncrementNumCommands()
{
CommandsRan++;
WindowInvalidateByNumber(WindowClass::Player, Id);
OpenRCT2::WindowInvalidateByNumber(WindowClass::Player, Id);
}
void NetworkPlayer::AddMoneySpent(money64 cost)
{
MoneySpent += cost;
WindowInvalidateByNumber(WindowClass::Player, Id);
OpenRCT2::WindowInvalidateByNumber(WindowClass::Player, Id);
}
#endif

View File

@@ -32,6 +32,7 @@
#include <cassert>
using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;
/**

View File

@@ -17,8 +17,10 @@
#include <string>
#include <variant>
enum IntentAction
namespace OpenRCT2
{
enum IntentAction
{
INTENT_ACTION_MAP,
INTENT_ACTION_NEW_RIDE_OF_TYPE,
INTENT_ACTION_REFRESH_CAMPAIGN_RIDE_LIST,
@@ -57,23 +59,23 @@ enum IntentAction
INTENT_ACTION_REMOVE_PROVISIONAL_TRACK_PIECE,
INTENT_ACTION_NULL = 255,
};
};
// The maximum amount of data the Intent can hold, 8 should be sufficient, raise this if needed.
static constexpr size_t kIntentMaxDataSlots = 8;
// The maximum amount of data the Intent can hold, 8 should be sufficient, raise this if needed.
static constexpr size_t kIntentMaxDataSlots = 8;
using IntentData = std::variant<int64_t, std::string, CloseCallback, void*>;
using IntentDataEntry = std::pair<uint32_t, IntentData>;
using IntentDataStorage = sfl::static_vector<IntentDataEntry, kIntentMaxDataSlots>;
using IntentData = std::variant<int64_t, std::string, CloseCallback, void*>;
using IntentDataEntry = std::pair<uint32_t, IntentData>;
using IntentDataStorage = sfl::static_vector<IntentDataEntry, kIntentMaxDataSlots>;
class Intent
{
class Intent
{
WindowClass _Class{ WindowClass::Null };
WindowDetail _WindowDetail{ WD_NULL };
IntentAction _Action{ INTENT_ACTION_NULL };
IntentDataStorage _Data;
public:
public:
explicit Intent(WindowClass windowClass);
explicit Intent(WindowDetail windowDetail);
explicit Intent(IntentAction windowclass);
@@ -100,10 +102,10 @@ public:
const auto val = value.ToUnderlying();
return PutExtra(key, static_cast<uint32_t>(val));
}
};
};
enum
{
enum
{
INTENT_EXTRA_GUEST_LIST_FILTER,
INTENT_EXTRA_RIDE_ID,
INTENT_EXTRA_PATH,
@@ -125,4 +127,5 @@ enum
INTENT_EXTRA_PROGRESS_OFFSET,
INTENT_EXTRA_PROGRESS_TOTAL,
INTENT_EXTRA_STRING_ID,
};
};
} // namespace OpenRCT2