mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Move Ui window functions into Ui library (#22426)
* Move scroll widget functions * Move window move functions * De-snake * Move further functions to ui * Move widget function to widget file * Move window create to ui
This commit is contained in:
@@ -802,7 +802,7 @@ private:
|
|||||||
if ((flags & SDL_WINDOW_MINIMIZED) == 0)
|
if ((flags & SDL_WINDOW_MINIMIZED) == 0)
|
||||||
{
|
{
|
||||||
WindowResizeGui(_width, _height);
|
WindowResizeGui(_width, _height);
|
||||||
WindowRelocateWindows(_width, _height);
|
Windows::WindowRelocateWindows(_width, _height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GfxInvalidateScreen();
|
GfxInvalidateScreen();
|
||||||
|
|||||||
@@ -1242,4 +1242,72 @@ namespace OpenRCT2::Ui
|
|||||||
widget.content &= ~0xFF;
|
widget.content &= ~0xFF;
|
||||||
widget.content |= newPercentage;
|
widget.content |= newPercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006EAF26
|
||||||
|
*/
|
||||||
|
void WidgetScrollUpdateThumbs(WindowBase& w, WidgetIndex widget_index)
|
||||||
|
{
|
||||||
|
const auto& widget = w.widgets[widget_index];
|
||||||
|
auto& scroll = w.scrolls[WindowGetScrollDataIndex(w, widget_index)];
|
||||||
|
|
||||||
|
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
||||||
|
{
|
||||||
|
int32_t view_size = widget.width() - 21;
|
||||||
|
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
||||||
|
view_size -= 11;
|
||||||
|
int32_t x = scroll.h_left * view_size;
|
||||||
|
if (scroll.h_right != 0)
|
||||||
|
x /= scroll.h_right;
|
||||||
|
scroll.h_thumb_left = x + 11;
|
||||||
|
|
||||||
|
x = widget.width() - 2;
|
||||||
|
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
||||||
|
x -= 11;
|
||||||
|
x += scroll.h_left;
|
||||||
|
if (scroll.h_right != 0)
|
||||||
|
x = (x * view_size) / scroll.h_right;
|
||||||
|
x += 11;
|
||||||
|
view_size += 10;
|
||||||
|
scroll.h_thumb_right = std::min(x, view_size);
|
||||||
|
|
||||||
|
if (scroll.h_thumb_right - scroll.h_thumb_left < 20)
|
||||||
|
{
|
||||||
|
double barPosition = (scroll.h_thumb_right * 1.0) / view_size;
|
||||||
|
|
||||||
|
scroll.h_thumb_left = static_cast<int32_t>(std::lround(scroll.h_thumb_left - (20 * barPosition)));
|
||||||
|
scroll.h_thumb_right = static_cast<int32_t>(std::lround(scroll.h_thumb_right + (20 * (1 - barPosition))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
||||||
|
{
|
||||||
|
int32_t view_size = widget.height() - 21;
|
||||||
|
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
||||||
|
view_size -= 11;
|
||||||
|
int32_t y = scroll.v_top * view_size;
|
||||||
|
if (scroll.v_bottom != 0)
|
||||||
|
y /= scroll.v_bottom;
|
||||||
|
scroll.v_thumb_top = y + 11;
|
||||||
|
|
||||||
|
y = widget.height() - 2;
|
||||||
|
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
||||||
|
y -= 11;
|
||||||
|
y += scroll.v_top;
|
||||||
|
if (scroll.v_bottom != 0)
|
||||||
|
y = (y * view_size) / scroll.v_bottom;
|
||||||
|
y += 11;
|
||||||
|
view_size += 10;
|
||||||
|
scroll.v_thumb_bottom = std::min(y, view_size);
|
||||||
|
|
||||||
|
if (scroll.v_thumb_bottom - scroll.v_thumb_top < 20)
|
||||||
|
{
|
||||||
|
double barPosition = (scroll.v_thumb_bottom * 1.0) / view_size;
|
||||||
|
|
||||||
|
scroll.v_thumb_top = static_cast<int32_t>(std::lround(scroll.v_thumb_top - (20 * barPosition)));
|
||||||
|
scroll.v_thumb_bottom = static_cast<int32_t>(std::lround(scroll.v_thumb_bottom + (20 * (1 - barPosition))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace OpenRCT2::Ui
|
} // namespace OpenRCT2::Ui
|
||||||
|
|||||||
@@ -190,4 +190,6 @@ namespace OpenRCT2::Ui
|
|||||||
void WidgetSetCheckboxValue(WindowBase& w, WidgetIndex widgetIndex, bool value);
|
void WidgetSetCheckboxValue(WindowBase& w, WidgetIndex widgetIndex, bool value);
|
||||||
|
|
||||||
void WidgetProgressBarSetNewPercentage(Widget& widget, uint8_t newPercentage);
|
void WidgetProgressBarSetNewPercentage(Widget& widget, uint8_t newPercentage);
|
||||||
|
|
||||||
|
void WidgetScrollUpdateThumbs(WindowBase& w, WidgetIndex widget_index);
|
||||||
} // namespace OpenRCT2::Ui
|
} // namespace OpenRCT2::Ui
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <openrct2-ui/windows/Window.h>
|
#include <openrct2-ui/windows/Window.h>
|
||||||
#include <openrct2/Context.h>
|
#include <openrct2/Context.h>
|
||||||
#include <openrct2/Input.h>
|
#include <openrct2/Input.h>
|
||||||
@@ -209,96 +210,6 @@ static ScreenCoordsXY GetCentrePositionForNewWindow(int32_t width, int32_t heigh
|
|||||||
return ScreenCoordsXY{ (screenWidth - width) / 2, std::max(kTopToolbarHeight + 1, (screenHeight - height) / 2) };
|
return ScreenCoordsXY{ (screenWidth - width) / 2, std::max(kTopToolbarHeight + 1, (screenHeight - height) / 2) };
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowBase* WindowCreate(
|
|
||||||
std::unique_ptr<WindowBase>&& wp, WindowClass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags)
|
|
||||||
{
|
|
||||||
if (flags & WF_AUTO_POSITION)
|
|
||||||
{
|
|
||||||
if (flags & WF_CENTRE_SCREEN)
|
|
||||||
{
|
|
||||||
pos = GetCentrePositionForNewWindow(width, height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pos = GetAutoPositionForNewWindow(width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are any window slots left
|
|
||||||
// include kWindowLimitReserved for items such as the main viewport and toolbars to not appear to be counted.
|
|
||||||
if (g_window_list.size() >= static_cast<size_t>(Config::Get().general.WindowLimit + kWindowLimitReserved))
|
|
||||||
{
|
|
||||||
// Close least recently used window
|
|
||||||
for (auto& w : g_window_list)
|
|
||||||
{
|
|
||||||
if (w->flags & WF_DEAD)
|
|
||||||
continue;
|
|
||||||
if (!(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT | WF_NO_AUTO_CLOSE)))
|
|
||||||
{
|
|
||||||
WindowClose(*w.get());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find right position to insert new window
|
|
||||||
auto itDestPos = g_window_list.end();
|
|
||||||
if (flags & WF_STICK_TO_BACK)
|
|
||||||
{
|
|
||||||
for (auto it = g_window_list.begin(); it != g_window_list.end(); it++)
|
|
||||||
{
|
|
||||||
if ((*it)->flags & WF_DEAD)
|
|
||||||
continue;
|
|
||||||
if (!((*it)->flags & WF_STICK_TO_BACK))
|
|
||||||
{
|
|
||||||
itDestPos = it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!(flags & WF_STICK_TO_FRONT))
|
|
||||||
{
|
|
||||||
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
|
|
||||||
{
|
|
||||||
if ((*it)->flags & WF_DEAD)
|
|
||||||
continue;
|
|
||||||
if (!((*it)->flags & WF_STICK_TO_FRONT))
|
|
||||||
{
|
|
||||||
itDestPos = it.base();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto itNew = g_window_list.insert(itDestPos, std::move(wp));
|
|
||||||
auto w = itNew->get();
|
|
||||||
|
|
||||||
// Setup window
|
|
||||||
w->classification = cls;
|
|
||||||
w->flags = flags;
|
|
||||||
|
|
||||||
// Play sounds and flash the window
|
|
||||||
if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)))
|
|
||||||
{
|
|
||||||
w->flags |= WF_WHITE_BORDER_MASK;
|
|
||||||
OpenRCT2::Audio::Play(OpenRCT2::Audio::SoundId::WindowOpen, 0, pos.x + (width / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
w->windowPos = pos;
|
|
||||||
w->width = width;
|
|
||||||
w->height = height;
|
|
||||||
w->min_width = width;
|
|
||||||
w->max_width = width;
|
|
||||||
w->min_height = height;
|
|
||||||
w->max_height = height;
|
|
||||||
|
|
||||||
w->focus = std::nullopt;
|
|
||||||
|
|
||||||
ColourSchemeUpdate(w);
|
|
||||||
w->Invalidate();
|
|
||||||
w->OnOpen();
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t WindowGetWidgetIndex(const WindowBase& w, Widget* widget)
|
static int32_t WindowGetWidgetIndex(const WindowBase& w, Widget* widget)
|
||||||
{
|
{
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
@@ -570,45 +481,6 @@ void ApplyScreenSaverLockSetting()
|
|||||||
Config::Get().general.DisableScreensaver ? SDL_DisableScreenSaver() : SDL_EnableScreenSaver();
|
Config::Get().general.DisableScreensaver ? SDL_DisableScreenSaver() : SDL_EnableScreenSaver();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialises scroll widgets to their virtual size.
|
|
||||||
* rct2: 0x006EAEB8
|
|
||||||
*/
|
|
||||||
void WindowInitScrollWidgets(WindowBase& w)
|
|
||||||
{
|
|
||||||
Widget* widget;
|
|
||||||
int32_t widget_index, scroll_index;
|
|
||||||
|
|
||||||
widget_index = 0;
|
|
||||||
scroll_index = 0;
|
|
||||||
for (widget = w.widgets; widget->type != WindowWidgetType::Last; widget++)
|
|
||||||
{
|
|
||||||
if (widget->type != WindowWidgetType::Scroll)
|
|
||||||
{
|
|
||||||
widget_index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& scroll = w.scrolls[scroll_index];
|
|
||||||
scroll.flags = 0;
|
|
||||||
ScreenSize scrollSize = w.OnScrollGetSize(scroll_index);
|
|
||||||
scroll.h_left = 0;
|
|
||||||
scroll.h_right = scrollSize.width + 1;
|
|
||||||
scroll.v_top = 0;
|
|
||||||
scroll.v_bottom = scrollSize.height + 1;
|
|
||||||
|
|
||||||
if (widget->content & SCROLL_HORIZONTAL)
|
|
||||||
scroll.flags |= HSCROLLBAR_VISIBLE;
|
|
||||||
if (widget->content & SCROLL_VERTICAL)
|
|
||||||
scroll.flags |= VSCROLLBAR_VISIBLE;
|
|
||||||
|
|
||||||
WidgetScrollUpdateThumbs(w, widget_index);
|
|
||||||
|
|
||||||
widget_index++;
|
|
||||||
scroll_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006EB15C
|
* rct2: 0x006EB15C
|
||||||
@@ -671,19 +543,6 @@ static void WindowInvalidatePressedImageButton(const WindowBase& w)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006EA73F
|
|
||||||
*/
|
|
||||||
void InvalidateAllWindowsAfterInput()
|
|
||||||
{
|
|
||||||
WindowVisitEach([](WindowBase* w) {
|
|
||||||
WindowUpdateScrollWidgets(*w);
|
|
||||||
WindowInvalidatePressedImageButton(*w);
|
|
||||||
w->OnResize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::OnDraw(DrawPixelInfo& dpi)
|
void Window::OnDraw(DrawPixelInfo& dpi)
|
||||||
{
|
{
|
||||||
WindowDrawWidgets(*this, dpi);
|
WindowDrawWidgets(*this, dpi);
|
||||||
@@ -696,7 +555,7 @@ void Window::OnDrawWidget(WidgetIndex widgetIndex, DrawPixelInfo& dpi)
|
|||||||
|
|
||||||
void Window::InitScrollWidgets()
|
void Window::InitScrollWidgets()
|
||||||
{
|
{
|
||||||
WindowInitScrollWidgets(*this);
|
Windows::WindowInitScrollWidgets(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::InvalidateWidget(WidgetIndex widgetIndex)
|
void Window::InvalidateWidget(WidgetIndex widgetIndex)
|
||||||
@@ -837,6 +696,96 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
static TextInputSession* _textInput;
|
static TextInputSession* _textInput;
|
||||||
static WidgetIdentifier _currentTextBox = { { WindowClass::Null, 0 }, 0 };
|
static WidgetIdentifier _currentTextBox = { { WindowClass::Null, 0 }, 0 };
|
||||||
|
|
||||||
|
WindowBase* WindowCreate(
|
||||||
|
std::unique_ptr<WindowBase>&& wp, WindowClass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags)
|
||||||
|
{
|
||||||
|
if (flags & WF_AUTO_POSITION)
|
||||||
|
{
|
||||||
|
if (flags & WF_CENTRE_SCREEN)
|
||||||
|
{
|
||||||
|
pos = GetCentrePositionForNewWindow(width, height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos = GetAutoPositionForNewWindow(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any window slots left
|
||||||
|
// include kWindowLimitReserved for items such as the main viewport and toolbars to not appear to be counted.
|
||||||
|
if (g_window_list.size() >= static_cast<size_t>(Config::Get().general.WindowLimit + kWindowLimitReserved))
|
||||||
|
{
|
||||||
|
// Close least recently used window
|
||||||
|
for (auto& w : g_window_list)
|
||||||
|
{
|
||||||
|
if (w->flags & WF_DEAD)
|
||||||
|
continue;
|
||||||
|
if (!(w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT | WF_NO_AUTO_CLOSE)))
|
||||||
|
{
|
||||||
|
WindowClose(*w.get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find right position to insert new window
|
||||||
|
auto itDestPos = g_window_list.end();
|
||||||
|
if (flags & WF_STICK_TO_BACK)
|
||||||
|
{
|
||||||
|
for (auto it = g_window_list.begin(); it != g_window_list.end(); it++)
|
||||||
|
{
|
||||||
|
if ((*it)->flags & WF_DEAD)
|
||||||
|
continue;
|
||||||
|
if (!((*it)->flags & WF_STICK_TO_BACK))
|
||||||
|
{
|
||||||
|
itDestPos = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(flags & WF_STICK_TO_FRONT))
|
||||||
|
{
|
||||||
|
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
|
||||||
|
{
|
||||||
|
if ((*it)->flags & WF_DEAD)
|
||||||
|
continue;
|
||||||
|
if (!((*it)->flags & WF_STICK_TO_FRONT))
|
||||||
|
{
|
||||||
|
itDestPos = it.base();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto itNew = g_window_list.insert(itDestPos, std::move(wp));
|
||||||
|
auto w = itNew->get();
|
||||||
|
|
||||||
|
// Setup window
|
||||||
|
w->classification = cls;
|
||||||
|
w->flags = flags;
|
||||||
|
|
||||||
|
// Play sounds and flash the window
|
||||||
|
if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)))
|
||||||
|
{
|
||||||
|
w->flags |= WF_WHITE_BORDER_MASK;
|
||||||
|
OpenRCT2::Audio::Play(OpenRCT2::Audio::SoundId::WindowOpen, 0, pos.x + (width / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
w->windowPos = pos;
|
||||||
|
w->width = width;
|
||||||
|
w->height = height;
|
||||||
|
w->min_width = width;
|
||||||
|
w->max_width = width;
|
||||||
|
w->min_height = height;
|
||||||
|
w->max_height = height;
|
||||||
|
|
||||||
|
w->focus = std::nullopt;
|
||||||
|
|
||||||
|
ColourSchemeUpdate(w);
|
||||||
|
w->Invalidate();
|
||||||
|
w->OnOpen();
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
WindowBase* WindowGetListening()
|
WindowBase* WindowGetListening()
|
||||||
{
|
{
|
||||||
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
|
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)
|
||||||
@@ -934,4 +883,376 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
{
|
{
|
||||||
return _currentTextBox;
|
return _currentTextBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowResize(WindowBase& w, int32_t dw, int32_t dh)
|
||||||
|
{
|
||||||
|
if (dw == 0 && dh == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Invalidate old region
|
||||||
|
w.Invalidate();
|
||||||
|
|
||||||
|
// Clamp new size to minimum and maximum
|
||||||
|
w.width = std::clamp<int32_t>(w.width + dw, w.min_width, w.max_width);
|
||||||
|
w.height = std::clamp<int32_t>(w.height + dh, w.min_height, w.max_height);
|
||||||
|
|
||||||
|
w.OnResize();
|
||||||
|
w.OnPrepareDraw();
|
||||||
|
|
||||||
|
// Update scroll widgets
|
||||||
|
for (auto& scroll : w.scrolls)
|
||||||
|
{
|
||||||
|
scroll.h_right = WINDOW_SCROLL_UNDEFINED;
|
||||||
|
scroll.v_bottom = WINDOW_SCROLL_UNDEFINED;
|
||||||
|
}
|
||||||
|
WindowUpdateScrollWidgets(w);
|
||||||
|
|
||||||
|
// Invalidate new region
|
||||||
|
w.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006EAE4E
|
||||||
|
*
|
||||||
|
* @param w The window (esi).
|
||||||
|
*/
|
||||||
|
void WindowUpdateScrollWidgets(WindowBase& w)
|
||||||
|
{
|
||||||
|
int32_t scrollIndex, width, height, scrollPositionChanged;
|
||||||
|
WidgetIndex widgetIndex;
|
||||||
|
Widget* widget;
|
||||||
|
|
||||||
|
widgetIndex = 0;
|
||||||
|
scrollIndex = 0;
|
||||||
|
for (widget = w.widgets; widget->type != WindowWidgetType::Last; widget++, widgetIndex++)
|
||||||
|
{
|
||||||
|
if (widget->type != WindowWidgetType::Scroll)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto& scroll = w.scrolls[scrollIndex];
|
||||||
|
ScreenSize scrollSize = w.OnScrollGetSize(scrollIndex);
|
||||||
|
width = scrollSize.width;
|
||||||
|
height = scrollSize.height;
|
||||||
|
|
||||||
|
if (height == 0)
|
||||||
|
{
|
||||||
|
scroll.v_top = 0;
|
||||||
|
}
|
||||||
|
else if (width == 0)
|
||||||
|
{
|
||||||
|
scroll.h_left = 0;
|
||||||
|
}
|
||||||
|
width++;
|
||||||
|
height++;
|
||||||
|
|
||||||
|
scrollPositionChanged = 0;
|
||||||
|
if ((widget->content & SCROLL_HORIZONTAL) && width != scroll.h_right)
|
||||||
|
{
|
||||||
|
scrollPositionChanged = 1;
|
||||||
|
scroll.h_right = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((widget->content & SCROLL_VERTICAL) && height != scroll.v_bottom)
|
||||||
|
{
|
||||||
|
scrollPositionChanged = 1;
|
||||||
|
scroll.v_bottom = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollPositionChanged)
|
||||||
|
{
|
||||||
|
WidgetScrollUpdateThumbs(w, widgetIndex);
|
||||||
|
w.Invalidate();
|
||||||
|
}
|
||||||
|
scrollIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialises scroll widgets to their virtual size.
|
||||||
|
* rct2: 0x006EAEB8
|
||||||
|
*/
|
||||||
|
void WindowInitScrollWidgets(WindowBase& w)
|
||||||
|
{
|
||||||
|
Widget* widget;
|
||||||
|
int32_t widget_index, scroll_index;
|
||||||
|
|
||||||
|
widget_index = 0;
|
||||||
|
scroll_index = 0;
|
||||||
|
for (widget = w.widgets; widget->type != WindowWidgetType::Last; widget++)
|
||||||
|
{
|
||||||
|
if (widget->type != WindowWidgetType::Scroll)
|
||||||
|
{
|
||||||
|
widget_index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& scroll = w.scrolls[scroll_index];
|
||||||
|
scroll.flags = 0;
|
||||||
|
ScreenSize scrollSize = w.OnScrollGetSize(scroll_index);
|
||||||
|
scroll.h_left = 0;
|
||||||
|
scroll.h_right = scrollSize.width + 1;
|
||||||
|
scroll.v_top = 0;
|
||||||
|
scroll.v_bottom = scrollSize.height + 1;
|
||||||
|
|
||||||
|
if (widget->content & SCROLL_HORIZONTAL)
|
||||||
|
scroll.flags |= HSCROLLBAR_VISIBLE;
|
||||||
|
if (widget->content & SCROLL_VERTICAL)
|
||||||
|
scroll.flags |= VSCROLLBAR_VISIBLE;
|
||||||
|
|
||||||
|
WidgetScrollUpdateThumbs(w, widget_index);
|
||||||
|
|
||||||
|
widget_index++;
|
||||||
|
scroll_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SnapLeft(WindowBase& w, int32_t proximity)
|
||||||
|
{
|
||||||
|
const auto* mainWindow = WindowGetMain();
|
||||||
|
auto wBottom = w.windowPos.y + w.height;
|
||||||
|
auto wLeftProximity = w.windowPos.x - (proximity * 2);
|
||||||
|
auto wRightProximity = w.windowPos.x + (proximity * 2);
|
||||||
|
auto rightMost = INT32_MIN;
|
||||||
|
|
||||||
|
WindowVisitEach([&](WindowBase* w2) {
|
||||||
|
if (w2 == &w || w2 == mainWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto right = w2->windowPos.x + w2->width;
|
||||||
|
|
||||||
|
if (wBottom < w2->windowPos.y || w.windowPos.y > w2->windowPos.y + w2->height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (right < wLeftProximity || right > wRightProximity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rightMost = std::max(rightMost, right);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (0 >= wLeftProximity && 0 <= wRightProximity)
|
||||||
|
rightMost = std::max(rightMost, 0);
|
||||||
|
|
||||||
|
if (rightMost != INT32_MIN)
|
||||||
|
w.windowPos.x = rightMost;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SnapTop(WindowBase& w, int32_t proximity)
|
||||||
|
{
|
||||||
|
const auto* mainWindow = WindowGetMain();
|
||||||
|
auto wRight = w.windowPos.x + w.width;
|
||||||
|
auto wTopProximity = w.windowPos.y - (proximity * 2);
|
||||||
|
auto wBottomProximity = w.windowPos.y + (proximity * 2);
|
||||||
|
auto bottomMost = INT32_MIN;
|
||||||
|
|
||||||
|
WindowVisitEach([&](WindowBase* w2) {
|
||||||
|
if (w2 == &w || w2 == mainWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto bottom = w2->windowPos.y + w2->height;
|
||||||
|
|
||||||
|
if (wRight < w2->windowPos.x || w.windowPos.x > w2->windowPos.x + w2->width)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bottom < wTopProximity || bottom > wBottomProximity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bottomMost = std::max(bottomMost, bottom);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (0 >= wTopProximity && 0 <= wBottomProximity)
|
||||||
|
bottomMost = std::max(bottomMost, 0);
|
||||||
|
|
||||||
|
if (bottomMost != INT32_MIN)
|
||||||
|
w.windowPos.y = bottomMost;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SnapRight(WindowBase& w, int32_t proximity)
|
||||||
|
{
|
||||||
|
const auto* mainWindow = WindowGetMain();
|
||||||
|
auto wRight = w.windowPos.x + w.width;
|
||||||
|
auto wBottom = w.windowPos.y + w.height;
|
||||||
|
auto wLeftProximity = wRight - (proximity * 2);
|
||||||
|
auto wRightProximity = wRight + (proximity * 2);
|
||||||
|
auto leftMost = INT32_MAX;
|
||||||
|
|
||||||
|
WindowVisitEach([&](WindowBase* w2) {
|
||||||
|
if (w2 == &w || w2 == mainWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wBottom < w2->windowPos.y || w.windowPos.y > w2->windowPos.y + w2->height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (w2->windowPos.x < wLeftProximity || w2->windowPos.x > wRightProximity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
leftMost = std::min<int32_t>(leftMost, w2->windowPos.x);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto screenWidth = ContextGetWidth();
|
||||||
|
if (screenWidth >= wLeftProximity && screenWidth <= wRightProximity)
|
||||||
|
leftMost = std::min(leftMost, screenWidth);
|
||||||
|
|
||||||
|
if (leftMost != INT32_MAX)
|
||||||
|
w.windowPos.x = leftMost - w.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SnapBottom(WindowBase& w, int32_t proximity)
|
||||||
|
{
|
||||||
|
const auto* mainWindow = WindowGetMain();
|
||||||
|
auto wRight = w.windowPos.x + w.width;
|
||||||
|
auto wBottom = w.windowPos.y + w.height;
|
||||||
|
auto wTopProximity = wBottom - (proximity * 2);
|
||||||
|
auto wBottomProximity = wBottom + (proximity * 2);
|
||||||
|
auto topMost = INT32_MAX;
|
||||||
|
|
||||||
|
WindowVisitEach([&](WindowBase* w2) {
|
||||||
|
if (w2 == &w || w2 == mainWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wRight < w2->windowPos.x || w.windowPos.x > w2->windowPos.x + w2->width)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (w2->windowPos.y < wTopProximity || w2->windowPos.y > wBottomProximity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
topMost = std::min<int32_t>(topMost, w2->windowPos.y);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto screenHeight = ContextGetHeight();
|
||||||
|
if (screenHeight >= wTopProximity && screenHeight <= wBottomProximity)
|
||||||
|
topMost = std::min(topMost, screenHeight);
|
||||||
|
|
||||||
|
if (topMost != INT32_MAX)
|
||||||
|
w.windowPos.y = topMost - w.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowMoveAndSnap(WindowBase& w, ScreenCoordsXY newWindowCoords, int32_t snapProximity)
|
||||||
|
{
|
||||||
|
auto originalPos = w.windowPos;
|
||||||
|
int32_t minY = (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) ? 1 : kTopToolbarHeight + 2;
|
||||||
|
|
||||||
|
newWindowCoords.y = std::clamp(newWindowCoords.y, minY, ContextGetHeight() - 34);
|
||||||
|
|
||||||
|
if (snapProximity > 0)
|
||||||
|
{
|
||||||
|
w.windowPos = newWindowCoords;
|
||||||
|
|
||||||
|
SnapRight(w, snapProximity);
|
||||||
|
SnapBottom(w, snapProximity);
|
||||||
|
SnapLeft(w, snapProximity);
|
||||||
|
SnapTop(w, snapProximity);
|
||||||
|
|
||||||
|
if (w.windowPos == originalPos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
newWindowCoords = w.windowPos;
|
||||||
|
w.windowPos = originalPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowSetPosition(w, newWindowCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowMovePosition(WindowBase& w, const ScreenCoordsXY& deltaCoords)
|
||||||
|
{
|
||||||
|
if (deltaCoords.x == 0 && deltaCoords.y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Invalidate old region
|
||||||
|
w.Invalidate();
|
||||||
|
|
||||||
|
// Translate window and viewport
|
||||||
|
w.windowPos += deltaCoords;
|
||||||
|
if (w.viewport != nullptr)
|
||||||
|
{
|
||||||
|
w.viewport->pos += deltaCoords;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate new region
|
||||||
|
w.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowSetPosition(WindowBase& w, const ScreenCoordsXY& screenCoords)
|
||||||
|
{
|
||||||
|
WindowMovePosition(w, screenCoords - w.windowPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006ED710
|
||||||
|
* Called after a window resize to move windows if they
|
||||||
|
* are going to be out of sight.
|
||||||
|
*/
|
||||||
|
void WindowRelocateWindows(int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
int32_t new_location = 8;
|
||||||
|
WindowVisitEach([width, height, &new_location](WindowBase* w) {
|
||||||
|
// Work out if the window requires moving
|
||||||
|
if (w->windowPos.x + 10 < width)
|
||||||
|
{
|
||||||
|
if (w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT))
|
||||||
|
{
|
||||||
|
if (w->windowPos.y - 22 < height)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (w->windowPos.y + 10 < height)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the new locations
|
||||||
|
auto newWinPos = w->windowPos;
|
||||||
|
w->windowPos = { new_location, new_location + kTopToolbarHeight + 1 };
|
||||||
|
|
||||||
|
// Move the next new location so windows are not directly on top
|
||||||
|
new_location += 8;
|
||||||
|
|
||||||
|
// Adjust the viewport if required.
|
||||||
|
if (w->viewport != nullptr)
|
||||||
|
{
|
||||||
|
w->viewport->pos -= newWinPos - w->windowPos;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowSetResize(WindowBase& w, int32_t minWidth, int32_t minHeight, int32_t maxWidth, int32_t maxHeight)
|
||||||
|
{
|
||||||
|
w.min_width = minWidth;
|
||||||
|
w.min_height = minHeight;
|
||||||
|
w.max_width = maxWidth;
|
||||||
|
w.max_height = maxHeight;
|
||||||
|
|
||||||
|
// Clamp width and height to minimum and maximum
|
||||||
|
int32_t width = std::clamp<int32_t>(w.width, std::min(minWidth, maxWidth), std::max(minWidth, maxWidth));
|
||||||
|
int32_t height = std::clamp<int32_t>(w.height, std::min(minHeight, maxHeight), std::max(minHeight, maxHeight));
|
||||||
|
|
||||||
|
// Resize window if size has changed
|
||||||
|
if (w.width != width || w.height != height)
|
||||||
|
{
|
||||||
|
w.Invalidate();
|
||||||
|
w.width = width;
|
||||||
|
w.height = height;
|
||||||
|
w.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowCanResize(const WindowBase& w)
|
||||||
|
{
|
||||||
|
return (w.flags & WF_RESIZABLE) && (w.min_width != w.max_width || w.min_height != w.max_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* rct2: 0x006EA73F
|
||||||
|
*/
|
||||||
|
void InvalidateAllWindowsAfterInput()
|
||||||
|
{
|
||||||
|
WindowVisitEach([](WindowBase* w) {
|
||||||
|
Windows::WindowUpdateScrollWidgets(*w);
|
||||||
|
WindowInvalidatePressedImageButton(*w);
|
||||||
|
w->OnResize();
|
||||||
|
});
|
||||||
|
}
|
||||||
} // namespace OpenRCT2::Ui::Windows
|
} // namespace OpenRCT2::Ui::Windows
|
||||||
|
|||||||
@@ -45,6 +45,42 @@ ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w);
|
|||||||
|
|
||||||
namespace OpenRCT2::Ui::Windows
|
namespace OpenRCT2::Ui::Windows
|
||||||
{
|
{
|
||||||
|
WindowBase* WindowCreate(
|
||||||
|
std::unique_ptr<WindowBase>&& w, WindowClass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags);
|
||||||
|
template<typename T, typename... TArgs, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
||||||
|
T* WindowCreate(
|
||||||
|
WindowClass cls, const ScreenCoordsXY& pos = {}, int32_t width = 0, int32_t height = 0, uint32_t flags = 0,
|
||||||
|
TArgs&&... args)
|
||||||
|
{
|
||||||
|
return static_cast<T*>(WindowCreate(std::make_unique<T>(std::forward<TArgs>(args)...), cls, pos, width, height, flags));
|
||||||
|
}
|
||||||
|
template<typename T, typename... TArgs, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
||||||
|
T* WindowCreate(WindowClass cls, int32_t width, int32_t height, uint32_t flags, TArgs&&... args)
|
||||||
|
{
|
||||||
|
return static_cast<T*>(
|
||||||
|
WindowCreate(std::make_unique<T>(std::forward<TArgs>(args)...), cls, {}, width, height, flags | WF_AUTO_POSITION));
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
||||||
|
T* WindowFocusOrCreate(WindowClass cls, const ScreenCoordsXY& pos, int32_t width, int32_t height, uint32_t flags = 0)
|
||||||
|
{
|
||||||
|
auto* w = WindowBringToFrontByClass(cls);
|
||||||
|
if (w == nullptr)
|
||||||
|
{
|
||||||
|
w = WindowCreate<T>(cls, pos, width, height, flags);
|
||||||
|
}
|
||||||
|
return static_cast<T*>(w);
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
||||||
|
T* WindowFocusOrCreate(WindowClass cls, int32_t width, int32_t height, uint32_t flags = 0)
|
||||||
|
{
|
||||||
|
auto* w = WindowBringToFrontByClass(cls);
|
||||||
|
if (w == nullptr)
|
||||||
|
{
|
||||||
|
w = WindowCreate<T>(cls, width, height, flags);
|
||||||
|
}
|
||||||
|
return static_cast<T*>(w);
|
||||||
|
}
|
||||||
|
|
||||||
void RideConstructionToolupdateEntranceExit(const ScreenCoordsXY& screenCoords);
|
void RideConstructionToolupdateEntranceExit(const ScreenCoordsXY& screenCoords);
|
||||||
void RideConstructionToolupdateConstruct(const ScreenCoordsXY& screenCoords);
|
void RideConstructionToolupdateConstruct(const ScreenCoordsXY& screenCoords);
|
||||||
void RideConstructionTooldownConstruct(const ScreenCoordsXY& screenCoords);
|
void RideConstructionTooldownConstruct(const ScreenCoordsXY& screenCoords);
|
||||||
@@ -86,4 +122,18 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
bool IsUsingWidgetTextBox();
|
bool IsUsingWidgetTextBox();
|
||||||
bool TextBoxCaretIsFlashed();
|
bool TextBoxCaretIsFlashed();
|
||||||
const WidgetIdentifier& GetCurrentTextBox();
|
const WidgetIdentifier& GetCurrentTextBox();
|
||||||
|
|
||||||
|
void WindowResize(WindowBase& w, int32_t dw, int32_t dh);
|
||||||
|
void WindowInitScrollWidgets(WindowBase& w);
|
||||||
|
void WindowUpdateScrollWidgets(WindowBase& w);
|
||||||
|
|
||||||
|
void WindowMovePosition(WindowBase& w, const ScreenCoordsXY& screenCoords);
|
||||||
|
void WindowSetPosition(WindowBase& w, const ScreenCoordsXY& screenCoords);
|
||||||
|
void WindowMoveAndSnap(WindowBase& w, ScreenCoordsXY newWindowCoords, int32_t snapProximity);
|
||||||
|
void WindowRelocateWindows(int32_t width, int32_t height);
|
||||||
|
|
||||||
|
void WindowSetResize(WindowBase& w, int32_t minWidth, int32_t minHeight, int32_t maxWidth, int32_t maxHeight);
|
||||||
|
bool WindowCanResize(const WindowBase& w);
|
||||||
|
|
||||||
|
void InvalidateAllWindowsAfterInput();
|
||||||
} // namespace OpenRCT2::Ui::Windows
|
} // namespace OpenRCT2::Ui::Windows
|
||||||
|
|||||||
@@ -62,5 +62,3 @@ enum
|
|||||||
SCROLL_VERTICAL = (1 << 1),
|
SCROLL_VERTICAL = (1 << 1),
|
||||||
SCROLL_BOTH = SCROLL_HORIZONTAL | SCROLL_VERTICAL
|
SCROLL_BOTH = SCROLL_HORIZONTAL | SCROLL_VERTICAL
|
||||||
};
|
};
|
||||||
|
|
||||||
void WidgetScrollUpdateThumbs(WindowBase& w, WidgetIndex widget_index);
|
|
||||||
|
|||||||
@@ -576,63 +576,6 @@ void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIn
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006EAE4E
|
|
||||||
*
|
|
||||||
* @param w The window (esi).
|
|
||||||
*/
|
|
||||||
void WindowUpdateScrollWidgets(WindowBase& w)
|
|
||||||
{
|
|
||||||
int32_t scrollIndex, width, height, scrollPositionChanged;
|
|
||||||
WidgetIndex widgetIndex;
|
|
||||||
Widget* widget;
|
|
||||||
|
|
||||||
widgetIndex = 0;
|
|
||||||
scrollIndex = 0;
|
|
||||||
for (widget = w.widgets; widget->type != WindowWidgetType::Last; widget++, widgetIndex++)
|
|
||||||
{
|
|
||||||
if (widget->type != WindowWidgetType::Scroll)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto& scroll = w.scrolls[scrollIndex];
|
|
||||||
ScreenSize scrollSize = w.OnScrollGetSize(scrollIndex);
|
|
||||||
width = scrollSize.width;
|
|
||||||
height = scrollSize.height;
|
|
||||||
|
|
||||||
if (height == 0)
|
|
||||||
{
|
|
||||||
scroll.v_top = 0;
|
|
||||||
}
|
|
||||||
else if (width == 0)
|
|
||||||
{
|
|
||||||
scroll.h_left = 0;
|
|
||||||
}
|
|
||||||
width++;
|
|
||||||
height++;
|
|
||||||
|
|
||||||
scrollPositionChanged = 0;
|
|
||||||
if ((widget->content & SCROLL_HORIZONTAL) && width != scroll.h_right)
|
|
||||||
{
|
|
||||||
scrollPositionChanged = 1;
|
|
||||||
scroll.h_right = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((widget->content & SCROLL_VERTICAL) && height != scroll.v_bottom)
|
|
||||||
{
|
|
||||||
scrollPositionChanged = 1;
|
|
||||||
scroll.v_bottom = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollPositionChanged)
|
|
||||||
{
|
|
||||||
WidgetScrollUpdateThumbs(w, widgetIndex);
|
|
||||||
w.Invalidate();
|
|
||||||
}
|
|
||||||
scrollIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index)
|
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index)
|
||||||
{
|
{
|
||||||
int32_t i, result;
|
int32_t i, result;
|
||||||
@@ -1211,78 +1154,6 @@ void WindowDrawViewport(DrawPixelInfo& dpi, WindowBase& w)
|
|||||||
ViewportRender(dpi, w.viewport, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } });
|
ViewportRender(dpi, w.viewport, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } });
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowSetPosition(WindowBase& w, const ScreenCoordsXY& screenCoords)
|
|
||||||
{
|
|
||||||
WindowMovePosition(w, screenCoords - w.windowPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowMovePosition(WindowBase& w, const ScreenCoordsXY& deltaCoords)
|
|
||||||
{
|
|
||||||
if (deltaCoords.x == 0 && deltaCoords.y == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Invalidate old region
|
|
||||||
w.Invalidate();
|
|
||||||
|
|
||||||
// Translate window and viewport
|
|
||||||
w.windowPos += deltaCoords;
|
|
||||||
if (w.viewport != nullptr)
|
|
||||||
{
|
|
||||||
w.viewport->pos += deltaCoords;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalidate new region
|
|
||||||
w.Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowResize(WindowBase& w, int32_t dw, int32_t dh)
|
|
||||||
{
|
|
||||||
if (dw == 0 && dh == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Invalidate old region
|
|
||||||
w.Invalidate();
|
|
||||||
|
|
||||||
// Clamp new size to minimum and maximum
|
|
||||||
w.width = std::clamp<int32_t>(w.width + dw, w.min_width, w.max_width);
|
|
||||||
w.height = std::clamp<int32_t>(w.height + dh, w.min_height, w.max_height);
|
|
||||||
|
|
||||||
w.OnResize();
|
|
||||||
w.OnPrepareDraw();
|
|
||||||
|
|
||||||
// Update scroll widgets
|
|
||||||
for (auto& scroll : w.scrolls)
|
|
||||||
{
|
|
||||||
scroll.h_right = WINDOW_SCROLL_UNDEFINED;
|
|
||||||
scroll.v_bottom = WINDOW_SCROLL_UNDEFINED;
|
|
||||||
}
|
|
||||||
WindowUpdateScrollWidgets(w);
|
|
||||||
|
|
||||||
// Invalidate new region
|
|
||||||
w.Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowSetResize(WindowBase& w, int32_t minWidth, int32_t minHeight, int32_t maxWidth, int32_t maxHeight)
|
|
||||||
{
|
|
||||||
w.min_width = minWidth;
|
|
||||||
w.min_height = minHeight;
|
|
||||||
w.max_width = maxWidth;
|
|
||||||
w.max_height = maxHeight;
|
|
||||||
|
|
||||||
// Clamp width and height to minimum and maximum
|
|
||||||
int32_t width = std::clamp<int32_t>(w.width, std::min(minWidth, maxWidth), std::max(minWidth, maxWidth));
|
|
||||||
int32_t height = std::clamp<int32_t>(w.height, std::min(minHeight, maxHeight), std::max(minHeight, maxHeight));
|
|
||||||
|
|
||||||
// Resize window if size has changed
|
|
||||||
if (w.width != width || w.height != height)
|
|
||||||
{
|
|
||||||
w.Invalidate();
|
|
||||||
w.width = width;
|
|
||||||
w.height = height;
|
|
||||||
w.Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006EE212
|
* rct2: 0x006EE212
|
||||||
@@ -1345,47 +1216,6 @@ void ToolCancel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006ED710
|
|
||||||
* Called after a window resize to move windows if they
|
|
||||||
* are going to be out of sight.
|
|
||||||
*/
|
|
||||||
void WindowRelocateWindows(int32_t width, int32_t height)
|
|
||||||
{
|
|
||||||
int32_t new_location = 8;
|
|
||||||
WindowVisitEach([width, height, &new_location](WindowBase* w) {
|
|
||||||
// Work out if the window requires moving
|
|
||||||
if (w->windowPos.x + 10 < width)
|
|
||||||
{
|
|
||||||
if (w->flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT))
|
|
||||||
{
|
|
||||||
if (w->windowPos.y - 22 < height)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (w->windowPos.y + 10 < height)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the new locations
|
|
||||||
auto newWinPos = w->windowPos;
|
|
||||||
w->windowPos = { new_location, new_location + kTopToolbarHeight + 1 };
|
|
||||||
|
|
||||||
// Move the next new location so windows are not directly on top
|
|
||||||
new_location += 8;
|
|
||||||
|
|
||||||
// Adjust the viewport if required.
|
|
||||||
if (w->viewport != nullptr)
|
|
||||||
{
|
|
||||||
w->viewport->pos -= newWinPos - w->windowPos;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rct2: 0x0066B905
|
* rct2: 0x0066B905
|
||||||
*/
|
*/
|
||||||
@@ -1515,157 +1345,6 @@ void WindowUpdateViewportRideMusic()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void window_snap_left(WindowBase& w, int32_t proximity)
|
|
||||||
{
|
|
||||||
const auto* mainWindow = WindowGetMain();
|
|
||||||
auto wBottom = w.windowPos.y + w.height;
|
|
||||||
auto wLeftProximity = w.windowPos.x - (proximity * 2);
|
|
||||||
auto wRightProximity = w.windowPos.x + (proximity * 2);
|
|
||||||
auto rightMost = INT32_MIN;
|
|
||||||
|
|
||||||
WindowVisitEach([&](WindowBase* w2) {
|
|
||||||
if (w2 == &w || w2 == mainWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto right = w2->windowPos.x + w2->width;
|
|
||||||
|
|
||||||
if (wBottom < w2->windowPos.y || w.windowPos.y > w2->windowPos.y + w2->height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (right < wLeftProximity || right > wRightProximity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rightMost = std::max(rightMost, right);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 >= wLeftProximity && 0 <= wRightProximity)
|
|
||||||
rightMost = std::max(rightMost, 0);
|
|
||||||
|
|
||||||
if (rightMost != INT32_MIN)
|
|
||||||
w.windowPos.x = rightMost;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void window_snap_top(WindowBase& w, int32_t proximity)
|
|
||||||
{
|
|
||||||
const auto* mainWindow = WindowGetMain();
|
|
||||||
auto wRight = w.windowPos.x + w.width;
|
|
||||||
auto wTopProximity = w.windowPos.y - (proximity * 2);
|
|
||||||
auto wBottomProximity = w.windowPos.y + (proximity * 2);
|
|
||||||
auto bottomMost = INT32_MIN;
|
|
||||||
|
|
||||||
WindowVisitEach([&](WindowBase* w2) {
|
|
||||||
if (w2 == &w || w2 == mainWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto bottom = w2->windowPos.y + w2->height;
|
|
||||||
|
|
||||||
if (wRight < w2->windowPos.x || w.windowPos.x > w2->windowPos.x + w2->width)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (bottom < wTopProximity || bottom > wBottomProximity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bottomMost = std::max(bottomMost, bottom);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 >= wTopProximity && 0 <= wBottomProximity)
|
|
||||||
bottomMost = std::max(bottomMost, 0);
|
|
||||||
|
|
||||||
if (bottomMost != INT32_MIN)
|
|
||||||
w.windowPos.y = bottomMost;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void window_snap_right(WindowBase& w, int32_t proximity)
|
|
||||||
{
|
|
||||||
const auto* mainWindow = WindowGetMain();
|
|
||||||
auto wRight = w.windowPos.x + w.width;
|
|
||||||
auto wBottom = w.windowPos.y + w.height;
|
|
||||||
auto wLeftProximity = wRight - (proximity * 2);
|
|
||||||
auto wRightProximity = wRight + (proximity * 2);
|
|
||||||
auto leftMost = INT32_MAX;
|
|
||||||
|
|
||||||
WindowVisitEach([&](WindowBase* w2) {
|
|
||||||
if (w2 == &w || w2 == mainWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (wBottom < w2->windowPos.y || w.windowPos.y > w2->windowPos.y + w2->height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (w2->windowPos.x < wLeftProximity || w2->windowPos.x > wRightProximity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
leftMost = std::min<int32_t>(leftMost, w2->windowPos.x);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto screenWidth = ContextGetWidth();
|
|
||||||
if (screenWidth >= wLeftProximity && screenWidth <= wRightProximity)
|
|
||||||
leftMost = std::min(leftMost, screenWidth);
|
|
||||||
|
|
||||||
if (leftMost != INT32_MAX)
|
|
||||||
w.windowPos.x = leftMost - w.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void window_snap_bottom(WindowBase& w, int32_t proximity)
|
|
||||||
{
|
|
||||||
const auto* mainWindow = WindowGetMain();
|
|
||||||
auto wRight = w.windowPos.x + w.width;
|
|
||||||
auto wBottom = w.windowPos.y + w.height;
|
|
||||||
auto wTopProximity = wBottom - (proximity * 2);
|
|
||||||
auto wBottomProximity = wBottom + (proximity * 2);
|
|
||||||
auto topMost = INT32_MAX;
|
|
||||||
|
|
||||||
WindowVisitEach([&](WindowBase* w2) {
|
|
||||||
if (w2 == &w || w2 == mainWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (wRight < w2->windowPos.x || w.windowPos.x > w2->windowPos.x + w2->width)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (w2->windowPos.y < wTopProximity || w2->windowPos.y > wBottomProximity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
topMost = std::min<int32_t>(topMost, w2->windowPos.y);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto screenHeight = ContextGetHeight();
|
|
||||||
if (screenHeight >= wTopProximity && screenHeight <= wBottomProximity)
|
|
||||||
topMost = std::min(topMost, screenHeight);
|
|
||||||
|
|
||||||
if (topMost != INT32_MAX)
|
|
||||||
w.windowPos.y = topMost - w.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowMoveAndSnap(WindowBase& w, ScreenCoordsXY newWindowCoords, int32_t snapProximity)
|
|
||||||
{
|
|
||||||
auto originalPos = w.windowPos;
|
|
||||||
int32_t minY = (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) ? 1 : kTopToolbarHeight + 2;
|
|
||||||
|
|
||||||
newWindowCoords.y = std::clamp(newWindowCoords.y, minY, ContextGetHeight() - 34);
|
|
||||||
|
|
||||||
if (snapProximity > 0)
|
|
||||||
{
|
|
||||||
w.windowPos = newWindowCoords;
|
|
||||||
|
|
||||||
window_snap_right(w, snapProximity);
|
|
||||||
window_snap_bottom(w, snapProximity);
|
|
||||||
window_snap_left(w, snapProximity);
|
|
||||||
window_snap_top(w, snapProximity);
|
|
||||||
|
|
||||||
if (w.windowPos == originalPos)
|
|
||||||
return;
|
|
||||||
|
|
||||||
newWindowCoords = w.windowPos;
|
|
||||||
w.windowPos = originalPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowSetPosition(w, newWindowCoords);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t WindowCanResize(const WindowBase& w)
|
|
||||||
{
|
|
||||||
return (w.flags & WF_RESIZABLE) && (w.min_width != w.max_width || w.min_height != w.max_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006EE3C3
|
* rct2: 0x006EE3C3
|
||||||
@@ -1803,74 +1482,6 @@ Viewport* WindowGetViewport(WindowBase* w)
|
|||||||
return w->viewport;
|
return w->viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* rct2: 0x006EAF26
|
|
||||||
*/
|
|
||||||
void WidgetScrollUpdateThumbs(WindowBase& w, WidgetIndex widget_index)
|
|
||||||
{
|
|
||||||
const auto& widget = w.widgets[widget_index];
|
|
||||||
auto& scroll = w.scrolls[WindowGetScrollDataIndex(w, widget_index)];
|
|
||||||
|
|
||||||
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
|
||||||
{
|
|
||||||
int32_t view_size = widget.width() - 21;
|
|
||||||
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
|
||||||
view_size -= 11;
|
|
||||||
int32_t x = scroll.h_left * view_size;
|
|
||||||
if (scroll.h_right != 0)
|
|
||||||
x /= scroll.h_right;
|
|
||||||
scroll.h_thumb_left = x + 11;
|
|
||||||
|
|
||||||
x = widget.width() - 2;
|
|
||||||
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
|
||||||
x -= 11;
|
|
||||||
x += scroll.h_left;
|
|
||||||
if (scroll.h_right != 0)
|
|
||||||
x = (x * view_size) / scroll.h_right;
|
|
||||||
x += 11;
|
|
||||||
view_size += 10;
|
|
||||||
scroll.h_thumb_right = std::min(x, view_size);
|
|
||||||
|
|
||||||
if (scroll.h_thumb_right - scroll.h_thumb_left < 20)
|
|
||||||
{
|
|
||||||
double barPosition = (scroll.h_thumb_right * 1.0) / view_size;
|
|
||||||
|
|
||||||
scroll.h_thumb_left = static_cast<int32_t>(std::lround(scroll.h_thumb_left - (20 * barPosition)));
|
|
||||||
scroll.h_thumb_right = static_cast<int32_t>(std::lround(scroll.h_thumb_right + (20 * (1 - barPosition))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scroll.flags & VSCROLLBAR_VISIBLE)
|
|
||||||
{
|
|
||||||
int32_t view_size = widget.height() - 21;
|
|
||||||
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
|
||||||
view_size -= 11;
|
|
||||||
int32_t y = scroll.v_top * view_size;
|
|
||||||
if (scroll.v_bottom != 0)
|
|
||||||
y /= scroll.v_bottom;
|
|
||||||
scroll.v_thumb_top = y + 11;
|
|
||||||
|
|
||||||
y = widget.height() - 2;
|
|
||||||
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
|
||||||
y -= 11;
|
|
||||||
y += scroll.v_top;
|
|
||||||
if (scroll.v_bottom != 0)
|
|
||||||
y = (y * view_size) / scroll.v_bottom;
|
|
||||||
y += 11;
|
|
||||||
view_size += 10;
|
|
||||||
scroll.v_thumb_bottom = std::min(y, view_size);
|
|
||||||
|
|
||||||
if (scroll.v_thumb_bottom - scroll.v_thumb_top < 20)
|
|
||||||
{
|
|
||||||
double barPosition = (scroll.v_thumb_bottom * 1.0) / view_size;
|
|
||||||
|
|
||||||
scroll.v_thumb_top = static_cast<int32_t>(std::lround(scroll.v_thumb_top - (20 * barPosition)));
|
|
||||||
scroll.v_thumb_bottom = static_cast<int32_t>(std::lround(scroll.v_thumb_bottom + (20 * (1 - barPosition))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowBase::ResizeFrame()
|
void WindowBase::ResizeFrame()
|
||||||
{
|
{
|
||||||
// Frame
|
// Frame
|
||||||
|
|||||||
@@ -509,41 +509,6 @@ WindowBase* WindowBringToFrontByClass(WindowClass cls);
|
|||||||
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags);
|
WindowBase* WindowBringToFrontByClassWithFlags(WindowClass cls, uint16_t flags);
|
||||||
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number);
|
WindowBase* WindowBringToFrontByNumber(WindowClass cls, rct_windownumber number);
|
||||||
|
|
||||||
WindowBase* WindowCreate(
|
|
||||||
std::unique_ptr<WindowBase>&& w, WindowClass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags);
|
|
||||||
template<typename T, typename... TArgs, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
|
||||||
T* WindowCreate(
|
|
||||||
WindowClass cls, const ScreenCoordsXY& pos = {}, int32_t width = 0, int32_t height = 0, uint32_t flags = 0, TArgs&&... args)
|
|
||||||
{
|
|
||||||
return static_cast<T*>(WindowCreate(std::make_unique<T>(std::forward<TArgs>(args)...), cls, pos, width, height, flags));
|
|
||||||
}
|
|
||||||
template<typename T, typename... TArgs, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
|
||||||
T* WindowCreate(WindowClass cls, int32_t width, int32_t height, uint32_t flags, TArgs&&... args)
|
|
||||||
{
|
|
||||||
return static_cast<T*>(
|
|
||||||
WindowCreate(std::make_unique<T>(std::forward<TArgs>(args)...), cls, {}, width, height, flags | WF_AUTO_POSITION));
|
|
||||||
}
|
|
||||||
template<typename T, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
|
||||||
T* WindowFocusOrCreate(WindowClass cls, const ScreenCoordsXY& pos, int32_t width, int32_t height, uint32_t flags = 0)
|
|
||||||
{
|
|
||||||
auto* w = WindowBringToFrontByClass(cls);
|
|
||||||
if (w == nullptr)
|
|
||||||
{
|
|
||||||
w = WindowCreate<T>(cls, pos, width, height, flags);
|
|
||||||
}
|
|
||||||
return static_cast<T*>(w);
|
|
||||||
}
|
|
||||||
template<typename T, typename std::enable_if<std::is_base_of<WindowBase, T>::value>::type* = nullptr>
|
|
||||||
T* WindowFocusOrCreate(WindowClass cls, int32_t width, int32_t height, uint32_t flags = 0)
|
|
||||||
{
|
|
||||||
auto* w = WindowBringToFrontByClass(cls);
|
|
||||||
if (w == nullptr)
|
|
||||||
{
|
|
||||||
w = WindowCreate<T>(cls, width, height, flags);
|
|
||||||
}
|
|
||||||
return static_cast<T*>(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowClose(WindowBase& window);
|
void WindowClose(WindowBase& window);
|
||||||
void WindowFlushDead();
|
void WindowFlushDead();
|
||||||
void WindowCloseByClass(WindowClass cls);
|
void WindowCloseByClass(WindowClass cls);
|
||||||
@@ -566,8 +531,7 @@ void WindowInvalidateAll();
|
|||||||
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex);
|
void WidgetInvalidate(WindowBase& w, WidgetIndex widgetIndex);
|
||||||
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex);
|
void WidgetInvalidateByClass(WindowClass cls, WidgetIndex widgetIndex);
|
||||||
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex);
|
void WidgetInvalidateByNumber(WindowClass cls, rct_windownumber number, WidgetIndex widgetIndex);
|
||||||
void WindowInitScrollWidgets(WindowBase& w);
|
|
||||||
void WindowUpdateScrollWidgets(WindowBase& w);
|
|
||||||
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index);
|
int32_t WindowGetScrollDataIndex(const WindowBase& w, WidgetIndex widget_index);
|
||||||
|
|
||||||
void WindowPushOthersRight(WindowBase& w);
|
void WindowPushOthersRight(WindowBase& w);
|
||||||
@@ -590,11 +554,6 @@ void WindowDraw(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, in
|
|||||||
void WindowDrawWidgets(WindowBase& w, DrawPixelInfo& dpi);
|
void WindowDrawWidgets(WindowBase& w, DrawPixelInfo& dpi);
|
||||||
void WindowDrawViewport(DrawPixelInfo& dpi, WindowBase& w);
|
void WindowDrawViewport(DrawPixelInfo& dpi, WindowBase& w);
|
||||||
|
|
||||||
void WindowSetPosition(WindowBase& w, const ScreenCoordsXY& screenCoords);
|
|
||||||
void WindowMovePosition(WindowBase& w, const ScreenCoordsXY& screenCoords);
|
|
||||||
void WindowResize(WindowBase& w, int32_t dw, int32_t dh);
|
|
||||||
void WindowSetResize(WindowBase& w, int32_t minWidth, int32_t minHeight, int32_t maxWidth, int32_t maxHeight);
|
|
||||||
|
|
||||||
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool);
|
bool ToolSet(const WindowBase& w, WidgetIndex widgetIndex, Tool tool);
|
||||||
void ToolCancel();
|
void ToolCancel();
|
||||||
|
|
||||||
@@ -605,16 +564,11 @@ void WindowUpdateViewportRideMusic();
|
|||||||
Viewport* WindowGetViewport(WindowBase* window);
|
Viewport* WindowGetViewport(WindowBase* window);
|
||||||
|
|
||||||
// Open window functions
|
// Open window functions
|
||||||
void WindowRelocateWindows(int32_t width, int32_t height);
|
|
||||||
void WindowResizeGui(int32_t width, int32_t height);
|
void WindowResizeGui(int32_t width, int32_t height);
|
||||||
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height);
|
void WindowResizeGuiScenarioEditor(int32_t width, int32_t height);
|
||||||
|
|
||||||
void InvalidateAllWindowsAfterInput();
|
|
||||||
void TextinputCancel();
|
void TextinputCancel();
|
||||||
|
|
||||||
void WindowMoveAndSnap(WindowBase& w, ScreenCoordsXY newWindowCoords, int32_t snapProximity);
|
|
||||||
int32_t WindowCanResize(const WindowBase& w);
|
|
||||||
|
|
||||||
bool WindowIsVisible(WindowBase& w);
|
bool WindowIsVisible(WindowBase& w);
|
||||||
|
|
||||||
bool SceneryToolIsActive();
|
bool SceneryToolIsActive();
|
||||||
|
|||||||
Reference in New Issue
Block a user