clang-format UI root

This commit is contained in:
clang-format 2018-06-22 23:22:29 +02:00 committed by Hielke Morsink
parent e558660860
commit 9c022606f1
16 changed files with 1021 additions and 1009 deletions

View File

@ -7,9 +7,10 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2/interface/Cursors.h>
#include "CursorRepository.h"
#include <openrct2/interface/Cursors.h>
// clang-format off
namespace OpenRCT2::Ui
{

View File

@ -7,15 +7,14 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <cmath>
#include "CursorRepository.h"
#include <cmath>
#include <openrct2/common.h>
#include <openrct2/config/Config.h>
#include <openrct2/core/Guard.hpp>
#include <openrct2/interface/Cursors.h>
#include "CursorRepository.h"
using namespace OpenRCT2::Ui;
CursorRepository::~CursorRepository()
@ -40,25 +39,25 @@ void CursorRepository::SetCurrentCursor(CURSOR_ID cursorId)
{
if (_currentCursor != cursorId)
{
SDL_Cursor * cursor = _scaledCursors.at(_currentCursorScale).getScaledCursor(cursorId);
SDL_Cursor* cursor = _scaledCursors.at(_currentCursorScale).getScaledCursor(cursorId);
SDL_SetCursor(cursor);
_currentCursor = cursorId;
}
}
static bool getBit(const uint8_t * data, size_t x, size_t y, size_t width)
static bool getBit(const uint8_t* data, size_t x, size_t y, size_t width)
{
size_t position = y * width + x;
return (data[position / 8] & (1 << (7 - (x % 8)))) != 0;
}
static void setBit(uint8_t * data, size_t x, size_t y, size_t width)
static void setBit(uint8_t* data, size_t x, size_t y, size_t width)
{
size_t position = y * width + x;
data[position / 8] |= (1 << (7 - (position % 8)));
}
static void drawRect(uint8_t * data, size_t x, size_t y, size_t width, size_t scale)
static void drawRect(uint8_t* data, size_t x, size_t y, size_t width, size_t scale)
{
for (size_t outY = (y * scale); outY < ((1 + y) * scale); outY++)
{
@ -69,17 +68,18 @@ static void drawRect(uint8_t * data, size_t x, size_t y, size_t width, size_t sc
}
}
static uint8_t * scaleDataArray(const uint8_t data[], size_t width, size_t height, size_t scale)
static uint8_t* scaleDataArray(const uint8_t data[], size_t width, size_t height, size_t scale)
{
size_t length = width * height;
auto * ret = static_cast<uint8_t *>(calloc(sizeof(uint8_t), length * scale * scale));
auto* ret = static_cast<uint8_t*>(calloc(sizeof(uint8_t), length * scale * scale));
for (size_t y = 0; y < height * 8; y++)
{
for (size_t x = 0; x < width; x++)
{
bool value = getBit(data, x, y, width);
if (!value) continue;
if (!value)
continue;
drawRect(ret, x, y, width, scale);
}
@ -88,27 +88,26 @@ static uint8_t * scaleDataArray(const uint8_t data[], size_t width, size_t heigh
return ret;
}
SDL_Cursor * CursorRepository::Create(const CursorData * cursorInfo, uint8_t scale)
SDL_Cursor* CursorRepository::Create(const CursorData* cursorInfo, uint8_t scale)
{
SDL_Cursor * cursor;
SDL_Cursor* cursor;
auto integer_scale = (int) round(scale);
auto integer_scale = (int)round(scale);
auto data = scaleDataArray(cursorInfo->Data, CURSOR_BIT_WIDTH, CURSOR_HEIGHT, static_cast<size_t>(integer_scale));
auto mask = scaleDataArray(cursorInfo->Mask, CURSOR_BIT_WIDTH, CURSOR_HEIGHT, static_cast<size_t>(integer_scale));
cursor = SDL_CreateCursor(
data,
mask,
BASE_CURSOR_WIDTH * integer_scale,
BASE_CURSOR_HEIGHT * integer_scale,
cursorInfo->HotSpot.X * integer_scale,
cursorInfo->HotSpot.Y * integer_scale);
data,
mask,
BASE_CURSOR_WIDTH * integer_scale,
BASE_CURSOR_HEIGHT * integer_scale,
cursorInfo->HotSpot.X * integer_scale,
cursorInfo->HotSpot.Y * integer_scale);
free(data);
free(mask);
return cursor;
}
@ -125,8 +124,7 @@ void CursorRepository::GenerateScaledCursorSetHolder(uint8_t scale)
{
if (_scaledCursors.find(scale) == _scaledCursors.end())
{
std::function<SDL_Cursor *(CURSOR_ID)> cursorGenerator = [this, scale](CURSOR_ID cursorId)
{
std::function<SDL_Cursor*(CURSOR_ID)> cursorGenerator = [this, scale](CURSOR_ID cursorId) {
switch (cursorId)
{
// We can't scale the system cursors, but they should be appropriately scaled anyway

View File

@ -9,11 +9,9 @@
#pragma once
#include <map>
#include <functional>
#include <SDL2/SDL.h>
#include <functional>
#include <map>
#include <openrct2/interface/Cursors.h>
struct SDL_Cursor;
@ -26,9 +24,10 @@ namespace OpenRCT2::Ui
class CursorSetHolder
{
private:
SDL_Cursor * _cursors[CURSOR_COUNT] = {nullptr};
SDL_Cursor* _cursors[CURSOR_COUNT] = { nullptr };
public:
CursorSetHolder(const std::function<SDL_Cursor *(CURSOR_ID)> & getCursor)
CursorSetHolder(const std::function<SDL_Cursor*(CURSOR_ID)>& getCursor)
{
for (size_t i = 0; i < CURSOR_COUNT; i++)
{
@ -44,16 +43,16 @@ namespace OpenRCT2::Ui
}
}
SDL_Cursor * getScaledCursor(CURSOR_ID cursorId)
SDL_Cursor* getScaledCursor(CURSOR_ID cursorId)
{
return _cursors[cursorId];
}
};
constexpr static int32_t BASE_CURSOR_WIDTH = 32;
constexpr static int32_t BASE_CURSOR_WIDTH = 32;
constexpr static int32_t BASE_CURSOR_HEIGHT = 32;
CURSOR_ID _currentCursor = CURSOR_UNDEFINED;
CURSOR_ID _currentCursor = CURSOR_UNDEFINED;
uint8_t _currentCursorScale = 1;
std::map<uint8_t, CursorSetHolder> _scaledCursors;
@ -66,8 +65,8 @@ namespace OpenRCT2::Ui
void SetCursorScale(uint8_t cursorScale);
private:
SDL_Cursor * Create(const CursorData * cursorInfo, uint8_t scale);
SDL_Cursor* Create(const CursorData* cursorInfo, uint8_t scale);
void GenerateScaledCursorSetHolder(uint8_t scale);
static const CursorData * GetCursorData(CURSOR_ID cursorId);
static const CursorData* GetCursorData(CURSOR_ID cursorId);
};
}
} // namespace OpenRCT2::Ui

View File

@ -25,7 +25,7 @@ public:
SDL_GetError();
}
explicit SDLException(const char * message)
explicit SDLException(const char* message)
: runtime_error(message)
{
}
@ -34,7 +34,7 @@ public:
* Throws an SDL exception with a message containing the given call information
* and the message given by SDL_GetError.
*/
static void Throw(const char * call)
static void Throw(const char* call)
{
std::string message = std::string(call) + ": " + std::string(SDL_GetError());
throw SDLException(message);

View File

@ -7,24 +7,25 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2/common.h>
#include "TextComposition.h"
#include "UiContext.h"
#include "interface/InGameConsole.h"
#include <SDL2/SDL.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/common.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/String.hpp>
#include "TextComposition.h"
#include <openrct2/interface/InteractiveConsole.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/localisation/Localisation.h>
#include "interface/InGameConsole.h"
#include "UiContext.h"
#ifdef __MACOSX__
// macOS uses COMMAND rather than CTRL for many keyboard shortcuts
#define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI
// macOS uses COMMAND rather than CTRL for many keyboard shortcuts
#define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI
#else
#define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL
#define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL
#endif
using namespace OpenRCT2;
@ -35,7 +36,7 @@ bool TextComposition::IsActive()
return SDL_IsTextInputActive() && _session.Buffer != nullptr;
}
TextInputSession * TextComposition::Start(utf8 * buffer, size_t bufferSize)
TextInputSession* TextComposition::Start(utf8* buffer, size_t bufferSize)
{
Guard::ArgumentNotNull(buffer);
@ -62,126 +63,129 @@ void TextComposition::Stop()
_imeActive = false;
}
void TextComposition::HandleMessage(const SDL_Event * e)
void TextComposition::HandleMessage(const SDL_Event* e)
{
auto& console = GetInGameConsole();
switch (e->type) {
case SDL_TEXTEDITING:
// When inputting Korean characters, `edit.length` is always zero
String::Set(_imeBuffer, sizeof(_imeBuffer), e->edit.text);
_imeStart = e->edit.start;
_imeLength = e->edit.length;
_imeActive = ((e->edit.length != 0 || String::SizeOf(e->edit.text) != 0) && _imeBuffer[0] != '\0');
break;
case SDL_TEXTINPUT:
// will receive an `SDL_TEXTINPUT` event when a composition is committed
_imeActive = false;
_imeBuffer[0] = '\0';
if (_session.Buffer != nullptr)
{
// HACK ` will close console, so don't input any text
if (e->text.text[0] == '`' && console.IsOpen()) {
break;
}
utf8 * newText = String::Duplicate(e->text.text);
utf8_remove_formatting(newText, false);
Insert(newText);
Memory::Free(newText);
console.RefreshCaret();
window_update_textbox();
}
break;
case SDL_KEYDOWN:
switch (e->type)
{
if (_imeActive)
{
case SDL_TEXTEDITING:
// When inputting Korean characters, `edit.length` is always zero
String::Set(_imeBuffer, sizeof(_imeBuffer), e->edit.text);
_imeStart = e->edit.start;
_imeLength = e->edit.length;
_imeActive = ((e->edit.length != 0 || String::SizeOf(e->edit.text) != 0) && _imeBuffer[0] != '\0');
break;
}
uint16_t modifier = e->key.keysym.mod;
SDL_Keycode key = e->key.keysym.sym;
if (key == SDLK_KP_ENTER)
{
// Map Keypad enter to regular enter.
key = SDLK_RETURN;
}
GetContext()->GetUiContext()->SetKeysPressed(key, e->key.keysym.scancode);
// Text input
if (_session.Buffer == nullptr)
{
break;
}
// Clear the input on <CTRL>Backspace (Windows/Linux) or <MOD>Backspace (macOS)
if (key == SDLK_BACKSPACE && (modifier & KEYBOARD_PRIMARY_MODIFIER))
{
Clear();
console.RefreshCaret();
window_update_textbox();
}
switch (key) {
case SDLK_BACKSPACE:
// If backspace and we have input text with a cursor position nonzero
if (_session.SelectionStart > 0)
case SDL_TEXTINPUT:
// will receive an `SDL_TEXTINPUT` event when a composition is committed
_imeActive = false;
_imeBuffer[0] = '\0';
if (_session.Buffer != nullptr)
{
size_t endOffset = _session.SelectionStart;
CursorLeft();
_session.SelectionSize = endOffset - _session.SelectionStart;
Delete();
// HACK ` will close console, so don't input any text
if (e->text.text[0] == '`' && console.IsOpen())
{
break;
}
utf8* newText = String::Duplicate(e->text.text);
utf8_remove_formatting(newText, false);
Insert(newText);
Memory::Free(newText);
console.RefreshCaret();
window_update_textbox();
}
break;
case SDLK_HOME:
CursorHome();
console.RefreshCaret();
break;
case SDLK_END:
CursorEnd();
console.RefreshCaret();
break;
case SDLK_DELETE:
case SDL_KEYDOWN:
{
size_t startOffset = _session.SelectionStart;
CursorRight();
_session.SelectionSize = _session.SelectionStart - startOffset;
_session.SelectionStart = startOffset;
Delete();
console.RefreshCaret();
window_update_textbox();
break;
}
case SDLK_RETURN:
window_cancel_textbox();
break;
case SDLK_LEFT:
CursorLeft();
console.RefreshCaret();
break;
case SDLK_RIGHT:
CursorRight();
console.RefreshCaret();
break;
case SDLK_v:
if ((modifier & KEYBOARD_PRIMARY_MODIFIER) && SDL_HasClipboardText())
if (_imeActive)
{
utf8 * text = SDL_GetClipboardText();
utf8_remove_formatting(text, false);
Insert(text);
SDL_free(text);
break;
}
uint16_t modifier = e->key.keysym.mod;
SDL_Keycode key = e->key.keysym.sym;
if (key == SDLK_KP_ENTER)
{
// Map Keypad enter to regular enter.
key = SDLK_RETURN;
}
GetContext()->GetUiContext()->SetKeysPressed(key, e->key.keysym.scancode);
// Text input
if (_session.Buffer == nullptr)
{
break;
}
// Clear the input on <CTRL>Backspace (Windows/Linux) or <MOD>Backspace (macOS)
if (key == SDLK_BACKSPACE && (modifier & KEYBOARD_PRIMARY_MODIFIER))
{
Clear();
console.RefreshCaret();
window_update_textbox();
}
break;
switch (key)
{
case SDLK_BACKSPACE:
// If backspace and we have input text with a cursor position nonzero
if (_session.SelectionStart > 0)
{
size_t endOffset = _session.SelectionStart;
CursorLeft();
_session.SelectionSize = endOffset - _session.SelectionStart;
Delete();
console.RefreshCaret();
window_update_textbox();
}
break;
case SDLK_HOME:
CursorHome();
console.RefreshCaret();
break;
case SDLK_END:
CursorEnd();
console.RefreshCaret();
break;
case SDLK_DELETE:
{
size_t startOffset = _session.SelectionStart;
CursorRight();
_session.SelectionSize = _session.SelectionStart - startOffset;
_session.SelectionStart = startOffset;
Delete();
console.RefreshCaret();
window_update_textbox();
break;
}
case SDLK_RETURN:
window_cancel_textbox();
break;
case SDLK_LEFT:
CursorLeft();
console.RefreshCaret();
break;
case SDLK_RIGHT:
CursorRight();
console.RefreshCaret();
break;
case SDLK_v:
if ((modifier & KEYBOARD_PRIMARY_MODIFIER) && SDL_HasClipboardText())
{
utf8* text = SDL_GetClipboardText();
utf8_remove_formatting(text, false);
Insert(text);
SDL_free(text);
window_update_textbox();
}
break;
}
}
}
}
}
void TextComposition::CursorHome()
@ -192,7 +196,7 @@ void TextComposition::CursorHome()
void TextComposition::CursorEnd()
{
size_t selectionOffset = _session.Size;
const utf8 * ch = _session.Buffer + _session.SelectionStart;
const utf8* ch = _session.Buffer + _session.SelectionStart;
while (!utf8_is_codepoint_start(ch) && selectionOffset > 0)
{
ch--;
@ -207,13 +211,12 @@ void TextComposition::CursorLeft()
size_t selectionOffset = _session.SelectionStart;
if (selectionOffset > 0)
{
const utf8 * ch = _session.Buffer + selectionOffset;
const utf8* ch = _session.Buffer + selectionOffset;
do
{
ch--;
selectionOffset--;
}
while (!utf8_is_codepoint_start(ch) && selectionOffset > 0);
} while (!utf8_is_codepoint_start(ch) && selectionOffset > 0);
_session.SelectionStart = selectionOffset;
}
@ -225,22 +228,21 @@ void TextComposition::CursorRight()
size_t selectionMaxOffset = _session.Size;
if (selectionOffset < selectionMaxOffset)
{
const utf8 * ch = _session.Buffer + _session.SelectionStart;
const utf8* ch = _session.Buffer + _session.SelectionStart;
do
{
ch++;
selectionOffset++;
}
while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset);
} while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset);
_session.SelectionSize = std::max<size_t>(0, _session.SelectionSize - (selectionOffset - _session.SelectionStart));
_session.SelectionStart = selectionOffset;
}
}
void TextComposition::Insert(const utf8 * text)
void TextComposition::Insert(const utf8* text)
{
const utf8 * ch = text;
const utf8* ch = text;
uint32_t codepoint;
while ((codepoint = utf8_get_next(ch, &ch)) != 0)
{
@ -254,12 +256,12 @@ void TextComposition::InsertCodepoint(codepoint_t codepoint)
size_t remainingSize = _session.BufferSize - _session.Size;
if (codepointLength <= remainingSize)
{
utf8 * buffer = _session.Buffer;
utf8 * insertPtr = buffer + _session.SelectionStart;
utf8* buffer = _session.Buffer;
utf8* insertPtr = buffer + _session.SelectionStart;
if (_session.SelectionStart < _session.Size)
{
// Shift bytes (including null terminator) right to make room for new codepoint
utf8 * targetShiftPtr = insertPtr + codepointLength;
utf8* targetShiftPtr = insertPtr + codepointLength;
size_t shiftSize = _session.Size - _session.SelectionStart + 1;
memmove(targetShiftPtr, insertPtr, shiftSize);
}
@ -278,7 +280,7 @@ void TextComposition::InsertCodepoint(codepoint_t codepoint)
void TextComposition::Clear()
{
utf8 * buffer = _session.Buffer;
utf8* buffer = _session.Buffer;
buffer[0] = 0;
_session.Size = 0;
_session.Length = 0;
@ -292,21 +294,21 @@ void TextComposition::Delete()
size_t selectionMaxOffset = _session.Size;
// Find out how many bytes to delete.
const utf8 * ch = _session.Buffer + _session.SelectionStart;
const utf8* ch = _session.Buffer + _session.SelectionStart;
do
{
ch++;
selectionOffset++;
}
while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset);
} while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset);
utf8 * buffer = _session.Buffer;
utf8 * targetShiftPtr = buffer + _session.SelectionStart;
utf8 * sourceShiftPtr = targetShiftPtr + _session.SelectionSize;
utf8* buffer = _session.Buffer;
utf8* targetShiftPtr = buffer + _session.SelectionStart;
utf8* sourceShiftPtr = targetShiftPtr + _session.SelectionSize;
size_t bytesToSkip = selectionOffset - _session.SelectionStart;
// std::min() is used to ensure that shiftSize doesn't underflow; it should be between 0 and _session.Size
size_t shiftSize = _session.Size - std::min(_session.Size, (_session.SelectionStart - _session.SelectionSize + bytesToSkip));
size_t shiftSize
= _session.Size - std::min(_session.Size, (_session.SelectionStart - _session.SelectionSize + bytesToSkip));
memmove(targetShiftPtr, sourceShiftPtr, shiftSize);
_session.SelectionSize = 0;
RecalculateLength();

View File

@ -9,8 +9,8 @@
#pragma once
#include <openrct2/common.h>
#include <openrct2/Context.h>
#include <openrct2/common.h>
#include <openrct2/ui/UiContext.h>
union SDL_Event;
@ -25,26 +25,26 @@ namespace OpenRCT2::Ui
private:
TextInputSession _session = {};
bool _imeActive = false;
int32_t _imeStart = 0;
int32_t _imeLength = 0;
utf8 _imeBuffer[32] = {};
bool _imeActive = false;
int32_t _imeStart = 0;
int32_t _imeLength = 0;
utf8 _imeBuffer[32] = {};
public:
bool IsActive();
TextInputSession * Start(utf8 * buffer, size_t bufferSize);
TextInputSession* Start(utf8* buffer, size_t bufferSize);
void Stop();
void HandleMessage(const SDL_Event * e);
void HandleMessage(const SDL_Event* e);
private:
void CursorHome();
void CursorEnd();
void CursorLeft();
void CursorRight();
void Insert(const utf8 * text);
void Insert(const utf8* text);
void InsertCodepoint(codepoint_t codepoint);
void Clear();
void Delete();
void RecalculateLength();
};
}
} // namespace OpenRCT2::Ui

View File

@ -7,24 +7,24 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2/audio/AudioContext.h>
#include "Ui.h"
#include "UiContext.h"
#include "audio/AudioContext.h"
#include "drawing/BitmapReader.h"
#include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/PlatformEnvironment.h>
#include <openrct2/ui/UiContext.h>
#include "audio/AudioContext.h"
#include "drawing/BitmapReader.h"
#include "Ui.h"
#include "UiContext.h"
#include <openrct2/audio/AudioContext.h>
#include <openrct2/platform/platform.h>
#include <openrct2/ui/UiContext.h>
using namespace OpenRCT2;
using namespace OpenRCT2::Audio;
using namespace OpenRCT2::Ui;
template<typename T>
static std::shared_ptr<T> to_shared(std::unique_ptr<T>&& src)
template<typename T> static std::shared_ptr<T> to_shared(std::unique_ptr<T>&& src)
{
return std::shared_ptr<T>(std::move(src));
}
@ -33,9 +33,9 @@ static std::shared_ptr<T> to_shared(std::unique_ptr<T>&& src)
* Main entry point for non-Windows systems. Windows instead uses its own DLL proxy.
*/
#if defined(_MSC_VER) && !defined(__DISABLE_DLL_PROXY__)
int NormalisedMain(int argc, const char * * argv)
int NormalisedMain(int argc, const char** argv)
#else
int main(int argc, const char * * argv)
int main(int argc, const char** argv)
#endif
{
int runGame = cmdline_run(argv, argc);
@ -63,10 +63,9 @@ int main(int argc, const char * * argv)
return gExitCode;
}
#ifdef __ANDROID__
extern "C" {
int SDL_main(int argc, const char *argv[])
int SDL_main(int argc, const char* argv[])
{
return main(argc, argv);
}

View File

@ -8,5 +8,5 @@
*****************************************************************************/
#ifdef _MSC_VER
int NormalisedMain(int argc, const char * * argv);
int NormalisedMain(int argc, const char** argv);
#endif

View File

@ -9,29 +9,27 @@
#ifdef __ANDROID__
#include <dlfcn.h>
#include <sstream>
#include <stdexcept>
#include <openrct2/common.h>
#include <openrct2/core/String.hpp>
#include <openrct2/ui/UiContext.h>
#include "UiContext.h"
#include <SDL.h>
#include <dlfcn.h>
#include <openrct2/common.h>
#include <openrct2/core/String.hpp>
#include <openrct2/ui/UiContext.h>
#include <sstream>
#include <stdexcept>
namespace OpenRCT2::Ui
{
class AndroidContext final : public IPlatformUiContext
{
private:
public:
AndroidContext()
{
}
void SetWindowIcon(SDL_Window * window) override
void SetWindowIcon(SDL_Window* window) override
{
}
@ -40,21 +38,21 @@ namespace OpenRCT2::Ui
return false;
}
void ShowMessageBox(SDL_Window * window, const std::string &message) override
void ShowMessageBox(SDL_Window* window, const std::string& message) override
{
log_verbose(message.c_str());
STUB();
}
std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc &desc) override
std::string ShowFileDialog(SDL_Window* window, const FileDialogDesc& desc) override
{
STUB();
return nullptr;
}
std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) override
std::string ShowDirectoryDialog(SDL_Window* window, const std::string& title) override
{
log_info(title.c_str());
STUB();
@ -63,10 +61,10 @@ namespace OpenRCT2::Ui
}
};
IPlatformUiContext * CreatePlatformUiContext()
IPlatformUiContext* CreatePlatformUiContext()
{
return new AndroidContext();
}
}
} // namespace OpenRCT2::Ui
#endif // __ANDROID__

View File

@ -9,18 +9,17 @@
#if (defined(__linux__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__)) && !defined(__ANDROID__)
#include "UiContext.h"
#include <SDL.h>
#include <dlfcn.h>
#include <sstream>
#include <stdexcept>
#include <openrct2/common.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/ui/UiContext.h>
#include "UiContext.h"
#include <SDL.h>
#include <sstream>
#include <stdexcept>
namespace OpenRCT2::Ui
{
@ -34,13 +33,12 @@ namespace OpenRCT2::Ui
class LinuxContext final : public IPlatformUiContext
{
private:
public:
LinuxContext()
{
}
void SetWindowIcon(SDL_Window * window) override
void SetWindowIcon(SDL_Window* window) override
{
}
@ -50,25 +48,25 @@ namespace OpenRCT2::Ui
// See http://syprog.blogspot.ru/2011/12/listing-loaded-shared-objects-in-linux.html
struct lmap
{
void * base_address;
char * path;
void * unused;
lmap * next;
lmap * prev;
void* base_address;
char* path;
void* unused;
lmap* next;
lmap* prev;
};
struct dummy
{
void * pointers[3];
dummy * ptr;
void* pointers[3];
dummy* ptr;
};
bool result = false;
void * processHandle = dlopen(nullptr, RTLD_NOW);
void* processHandle = dlopen(nullptr, RTLD_NOW);
if (processHandle != nullptr)
{
dummy * p = ((dummy *)processHandle)->ptr;
lmap * pl = (lmap *)p->ptr;
dummy* p = ((dummy*)processHandle)->ptr;
lmap* pl = (lmap*)p->ptr;
while (pl != nullptr)
{
if (strstr(pl->path, "gameoverlayrenderer.so") != nullptr)
@ -86,115 +84,121 @@ namespace OpenRCT2::Ui
#endif
}
void ShowMessageBox(SDL_Window * window, const std::string &message) override
void ShowMessageBox(SDL_Window* window, const std::string& message) override
{
log_verbose(message.c_str());
std::string executablePath;
DIALOG_TYPE dtype = GetDialogApp(&executablePath);
switch (dtype) {
case DIALOG_TYPE::KDIALOG:
switch (dtype)
{
std::string cmd = String::Format("%s --title \"OpenRCT2\" --msgbox \"%s\"", executablePath.c_str(), message.c_str());
Execute(cmd);
break;
}
case DIALOG_TYPE::ZENITY:
{
std::string cmd = String::Format("%s --title=\"OpenRCT2\" --info --text=\"%s\"", executablePath.c_str(), message.c_str());
Execute(cmd);
break;
}
default:
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "OpenRCT2", message.c_str(), window);
break;
case DIALOG_TYPE::KDIALOG:
{
std::string cmd
= String::Format("%s --title \"OpenRCT2\" --msgbox \"%s\"", executablePath.c_str(), message.c_str());
Execute(cmd);
break;
}
case DIALOG_TYPE::ZENITY:
{
std::string cmd = String::Format(
"%s --title=\"OpenRCT2\" --info --text=\"%s\"", executablePath.c_str(), message.c_str());
Execute(cmd);
break;
}
default:
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "OpenRCT2", message.c_str(), window);
break;
}
}
std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc &desc) override
std::string ShowFileDialog(SDL_Window* window, const FileDialogDesc& desc) override
{
std::string result;
std::string executablePath;
DIALOG_TYPE dtype = GetDialogApp(&executablePath);
switch (dtype) {
case DIALOG_TYPE::KDIALOG:
switch (dtype)
{
std::string action =
(desc.Type == FILE_DIALOG_TYPE::OPEN) ? "--getopenfilename" :
"--getsavefilename";
std::string filter = GetKDialogFilterString(desc.Filters);
std::string cmd = String::StdFormat("%s --title '%s' %s '%s' '%s'",
executablePath.c_str(),
desc.Title.c_str(),
action.c_str(),
desc.InitialDirectory.c_str(),
filter.c_str());
std::string output;
if (Execute(cmd, &output) == 0)
case DIALOG_TYPE::KDIALOG:
{
result = output;
std::string action = (desc.Type == FILE_DIALOG_TYPE::OPEN) ? "--getopenfilename" : "--getsavefilename";
std::string filter = GetKDialogFilterString(desc.Filters);
std::string cmd = String::StdFormat(
"%s --title '%s' %s '%s' '%s'",
executablePath.c_str(),
desc.Title.c_str(),
action.c_str(),
desc.InitialDirectory.c_str(),
filter.c_str());
std::string output;
if (Execute(cmd, &output) == 0)
{
result = output;
}
break;
}
break;
}
case DIALOG_TYPE::ZENITY:
{
std::string action = "--file-selection";
std::string flags;
if (desc.Type == FILE_DIALOG_TYPE::SAVE)
{
flags = "--confirm-overwrite --save";
}
std::string filters = GetZenityFilterString(desc.Filters);
std::string cmd = String::StdFormat("%s %s --filename='%s/' %s --title='%s' / %s",
executablePath.c_str(),
action.c_str(),
desc.InitialDirectory.c_str(),
flags.c_str(),
desc.Title.c_str(),
filters.c_str());
std::string output;
if (Execute(cmd, &output) == 0)
case DIALOG_TYPE::ZENITY:
{
std::string action = "--file-selection";
std::string flags;
if (desc.Type == FILE_DIALOG_TYPE::SAVE)
{
// The default file extension is taken from the **first** available filter, since
// we cannot obtain it from zenity's output. This means that the FileDialogDesc::Filters
// array must be carefully populated, at least the first element.
std::string pattern = desc.Filters[0].Pattern;
std::string defaultExtension = pattern.substr(pattern.find_last_of('.'));
const utf8 * filename = Path::GetFileName(output.c_str());
// If there is no extension, append the pattern
const utf8 * extension = Path::GetExtension(filename);
result = output;
if (extension[0] == '\0' && !defaultExtension.empty())
flags = "--confirm-overwrite --save";
}
std::string filters = GetZenityFilterString(desc.Filters);
std::string cmd = String::StdFormat(
"%s %s --filename='%s/' %s --title='%s' / %s",
executablePath.c_str(),
action.c_str(),
desc.InitialDirectory.c_str(),
flags.c_str(),
desc.Title.c_str(),
filters.c_str());
std::string output;
if (Execute(cmd, &output) == 0)
{
if (desc.Type == FILE_DIALOG_TYPE::SAVE)
{
result = output.append(defaultExtension);
// The default file extension is taken from the **first** available filter, since
// we cannot obtain it from zenity's output. This means that the FileDialogDesc::Filters
// array must be carefully populated, at least the first element.
std::string pattern = desc.Filters[0].Pattern;
std::string defaultExtension = pattern.substr(pattern.find_last_of('.'));
const utf8* filename = Path::GetFileName(output.c_str());
// If there is no extension, append the pattern
const utf8* extension = Path::GetExtension(filename);
result = output;
if (extension[0] == '\0' && !defaultExtension.empty())
{
result = output.append(defaultExtension);
}
}
else
{
result = output;
}
}
else
{
result = output;
}
break;
}
break;
}
default:
ThrowMissingDialogApp();
break;
default:
ThrowMissingDialogApp();
break;
}
if (!result.empty())
{
if (desc.Type == FILE_DIALOG_TYPE::OPEN && access(result.c_str(), F_OK) == -1)
{
std::string msg = String::StdFormat("\"%s\" not found: %s, please choose another file\n", result.c_str(), strerror(errno));
std::string msg = String::StdFormat(
"\"%s\" not found: %s, please choose another file\n", result.c_str(), strerror(errno));
ShowMessageBox(window, msg);
return ShowFileDialog(window, desc);
}
else if (desc.Type == FILE_DIALOG_TYPE::SAVE && access(result.c_str(), F_OK) != -1 && dtype == DIALOG_TYPE::KDIALOG)
else if (
desc.Type == FILE_DIALOG_TYPE::SAVE && access(result.c_str(), F_OK) != -1 && dtype == DIALOG_TYPE::KDIALOG)
{
std::string cmd = String::StdFormat("%s --yesno \"Overwrite %s?\"", executablePath.c_str(), result.c_str());
if (Execute(cmd) != 0)
@ -206,41 +210,44 @@ namespace OpenRCT2::Ui
return result;
}
std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) override
std::string ShowDirectoryDialog(SDL_Window* window, const std::string& title) override
{
std::string result;
std::string executablePath;
DIALOG_TYPE dtype = GetDialogApp(&executablePath);
switch (dtype) {
case DIALOG_TYPE::KDIALOG:
switch (dtype)
{
std::string output;
std::string cmd = String::Format("%s --title '%s' --getexistingdirectory /", executablePath.c_str(), title.c_str());
if (Execute(cmd, &output) == 0)
case DIALOG_TYPE::KDIALOG:
{
result = output;
std::string output;
std::string cmd
= String::Format("%s --title '%s' --getexistingdirectory /", executablePath.c_str(), title.c_str());
if (Execute(cmd, &output) == 0)
{
result = output;
}
break;
}
break;
}
case DIALOG_TYPE::ZENITY:
{
std::string output;
std::string cmd = String::Format("%s --title='%s' --file-selection --directory /", executablePath.c_str(), title.c_str());
if (Execute(cmd, &output) == 0)
case DIALOG_TYPE::ZENITY:
{
result = output;
std::string output;
std::string cmd = String::Format(
"%s --title='%s' --file-selection --directory /", executablePath.c_str(), title.c_str());
if (Execute(cmd, &output) == 0)
{
result = output;
}
break;
}
break;
}
default:
ThrowMissingDialogApp();
break;
default:
ThrowMissingDialogApp();
break;
}
return result;
}
private:
static DIALOG_TYPE GetDialogApp(std::string * executablePath)
static DIALOG_TYPE GetDialogApp(std::string* executablePath)
{
// Prefer zenity as it offers more required features, e.g., overwrite
// confirmation and selecting only existing files.
@ -258,11 +265,11 @@ namespace OpenRCT2::Ui
return DIALOG_TYPE::NONE;
}
static int32_t Execute(const std::string &command, std::string * output = nullptr)
static int32_t Execute(const std::string& command, std::string* output = nullptr)
{
#ifndef __EMSCRIPTEN__
log_verbose("executing \"%s\"...\n", command.c_str());
FILE * fpipe = popen(command.c_str(), "r");
FILE* fpipe = popen(command.c_str(), "r");
if (fpipe == nullptr)
{
return -1;
@ -313,7 +320,7 @@ namespace OpenRCT2::Ui
{
std::stringstream filtersb;
bool first = true;
for (const auto &filter : filters)
for (const auto& filter : filters)
{
// KDialog wants filters space-delimited and we don't expect ';' anywhere else
std::string pattern = filter.Pattern;
@ -342,7 +349,7 @@ namespace OpenRCT2::Ui
{
// Zenity seems to be case sensitive, while KDialog isn't
std::stringstream filtersb;
for (const auto &filter : filters)
for (const auto& filter : filters)
{
filtersb << " --file-filter='" << filter.Name << " | ";
for (char c : filter.Pattern)
@ -353,10 +360,7 @@ namespace OpenRCT2::Ui
}
else if (isalpha(c))
{
filtersb << '['
<< (char)tolower(c)
<< (char)toupper(c)
<< ']';
filtersb << '[' << (char)tolower(c) << (char)toupper(c) << ']';
}
else
{
@ -377,7 +381,7 @@ namespace OpenRCT2::Ui
}
};
IPlatformUiContext * CreatePlatformUiContext()
IPlatformUiContext* CreatePlatformUiContext()
{
return new LinuxContext();
}

View File

@ -20,17 +20,17 @@
#undef CreateWindow
// Then the rest
#include "UiContext.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <openrct2/common.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/ui/UiContext.h>
#include "UiContext.h"
#include <sstream>
#include <shlobj.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <sstream>
// Native resource IDs
#include "../../resources/resource.h"
@ -63,7 +63,7 @@ namespace OpenRCT2::Ui
_win32module = GetModuleHandleA(nullptr);
}
void SetWindowIcon(SDL_Window * window) override
void SetWindowIcon(SDL_Window* window) override
{
if (_win32module != nullptr)
{
@ -84,14 +84,14 @@ namespace OpenRCT2::Ui
return (GetModuleHandleA("GameOverlayRenderer.dll") != nullptr);
}
void ShowMessageBox(SDL_Window * window, const std::string &message) override
void ShowMessageBox(SDL_Window* window, const std::string& message) override
{
HWND hwnd = GetHWND(window);
std::wstring messageW = String::ToUtf16(message);
MessageBoxW(hwnd, messageW.c_str(), L"OpenRCT2", MB_OK);
}
std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc &desc) override
std::string ShowFileDialog(SDL_Window* window, const FileDialogDesc& desc) override
{
std::wstring wcFilename = String::ToUtf16(desc.DefaultFilename);
wcFilename.resize(std::max<size_t>(wcFilename.size(), MAX_PATH));
@ -149,14 +149,13 @@ namespace OpenRCT2::Ui
return resultFilename;
}
std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) override
std::string ShowDirectoryDialog(SDL_Window* window, const std::string& title) override
{
std::string result;
// Initialize COM and get a pointer to the shell memory allocator
LPMALLOC lpMalloc;
if (SUCCEEDED(CoInitializeEx(0, COINIT_APARTMENTTHREADED)) &&
SUCCEEDED(SHGetMalloc(&lpMalloc)))
if (SUCCEEDED(CoInitializeEx(0, COINIT_APARTMENTTHREADED)) && SUCCEEDED(SHGetMalloc(&lpMalloc)))
{
std::wstring titleW = String::ToUtf16(title);
BROWSEINFOW bi = {};
@ -184,7 +183,7 @@ namespace OpenRCT2::Ui
}
private:
HWND GetHWND(SDL_Window * window)
HWND GetHWND(SDL_Window* window)
{
HWND result = nullptr;
if (window != nullptr)
@ -207,16 +206,13 @@ namespace OpenRCT2::Ui
std::wstringstream filtersb;
for (auto filter : filters)
{
filtersb << String::ToUtf16(filter.Name)
<< '\0'
<< String::ToUtf16(filter.Pattern)
<< '\0';
filtersb << String::ToUtf16(filter.Name) << '\0' << String::ToUtf16(filter.Pattern) << '\0';
}
return filtersb.str();
}
};
IPlatformUiContext * CreatePlatformUiContext()
IPlatformUiContext* CreatePlatformUiContext()
{
return new Win32Context();
}

View File

@ -7,42 +7,42 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "UiContext.h"
#include "CursorRepository.h"
#include "SDLException.h"
#include "TextComposition.h"
#include "WindowManager.h"
#include "drawing/engines/DrawingEngineFactory.hpp"
#include "input/KeyboardShortcuts.h"
#include "interface/InGameConsole.h"
#include "interface/Theme.h"
#include "title/TitleSequencePlayer.h"
#include <SDL2/SDL.h>
#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <cmath>
#include <cstdlib>
#include <memory>
#include <vector>
#include <SDL2/SDL.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Context.h>
#include <openrct2/Input.h>
#include <openrct2/Version.h>
#include <openrct2/audio/AudioMixer.h>
#include <openrct2/config/Config.h>
#include <openrct2/Context.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/localisation/StringIds.h>
#include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/interface/Chat.h>
#include <openrct2/interface/InteractiveConsole.h>
#include <openrct2/localisation/StringIds.h>
#include <openrct2/platform/Platform2.h>
#include <openrct2/title/TitleSequencePlayer.h>
#include <openrct2/ui/UiContext.h>
#include <openrct2/ui/WindowManager.h>
#include <openrct2/Version.h>
#include "CursorRepository.h"
#include "drawing/engines/DrawingEngineFactory.hpp"
#include "input/KeyboardShortcuts.h"
#include "interface/Theme.h"
#include "SDLException.h"
#include "TextComposition.h"
#include "UiContext.h"
#include "WindowManager.h"
#include <openrct2/Input.h>
#include <openrct2/interface/InteractiveConsole.h>
#include <openrct2-ui/interface/Window.h>
#include "interface/InGameConsole.h"
#include "title/TitleSequencePlayer.h"
#include <vector>
using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;
@ -50,10 +50,10 @@ using namespace OpenRCT2::Input;
using namespace OpenRCT2::Ui;
#ifdef __MACOSX__
// macOS uses COMMAND rather than CTRL for many keyboard shortcuts
#define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI
// macOS uses COMMAND rather than CTRL for many keyboard shortcuts
#define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI
#else
#define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL
#define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL
#endif
class UiContext final : public IUiContext
@ -61,40 +61,43 @@ class UiContext final : public IUiContext
private:
constexpr static uint32_t TOUCH_DOUBLE_TIMEOUT = 300;
IPlatformUiContext * const _platformUiContext;
IWindowManager * const _windowManager;
IPlatformUiContext* const _platformUiContext;
IWindowManager* const _windowManager;
CursorRepository _cursorRepository;
SDL_Window * _window = nullptr;
int32_t _width = 0;
int32_t _height = 0;
int32_t _scaleQuality = 0;
SDL_Window* _window = nullptr;
int32_t _width = 0;
int32_t _height = 0;
int32_t _scaleQuality = 0;
std::vector<Resolution> _fsResolutions;
bool _steamOverlayActive = false;
// Input
KeyboardShortcuts _keyboardShortcuts;
TextComposition _textComposition;
CursorState _cursorState = {};
uint32_t _lastKeyPressed = 0;
const uint8_t * _keysState = nullptr;
uint8_t _keysPressed[256] = {};
uint32_t _lastGestureTimestamp = 0;
float _gestureRadius = 0;
KeyboardShortcuts _keyboardShortcuts;
TextComposition _textComposition;
CursorState _cursorState = {};
uint32_t _lastKeyPressed = 0;
const uint8_t* _keysState = nullptr;
uint8_t _keysPressed[256] = {};
uint32_t _lastGestureTimestamp = 0;
float _gestureRadius = 0;
InGameConsole _inGameConsole;
InGameConsole _inGameConsole;
std::unique_ptr<ITitleSequencePlayer> _titleSequencePlayer;
public:
InGameConsole& GetInGameConsole() { return _inGameConsole; }
InGameConsole& GetInGameConsole()
{
return _inGameConsole;
}
explicit UiContext(const std::shared_ptr<IPlatformEnvironment>& env)
: _platformUiContext(CreatePlatformUiContext()),
_windowManager(CreateWindowManager()),
_keyboardShortcuts(env)
: _platformUiContext(CreatePlatformUiContext())
, _windowManager(CreateWindowManager())
, _keyboardShortcuts(env)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
@ -118,7 +121,7 @@ public:
_inGameConsole.Update();
}
void Draw(rct_drawpixelinfo * dpi) override
void Draw(rct_drawpixelinfo* dpi) override
{
auto bgColour = theme_get_colour(WC_CHAT, 0);
chat_draw(dpi, bgColour);
@ -126,7 +129,7 @@ public:
}
// Window
void * GetWindow() override
void* GetWindow() override
{
return _window;
}
@ -193,8 +196,7 @@ public:
bool IsMinimised() override
{
uint32_t windowFlags = GetWindowFlags();
return (windowFlags & SDL_WINDOW_MINIMIZED) ||
(windowFlags & SDL_WINDOW_HIDDEN);
return (windowFlags & SDL_WINDOW_MINIMIZED) || (windowFlags & SDL_WINDOW_HIDDEN);
}
bool IsSteamOverlayActive() override
@ -203,17 +205,17 @@ public:
}
// Input
const CursorState * GetCursorState() override
const CursorState* GetCursorState() override
{
return &_cursorState;
}
const uint8_t * GetKeysState() override
const uint8_t* GetKeysState() override
{
return _keysState;
}
const uint8_t * GetKeysPressed() override
const uint8_t* GetKeysPressed() override
{
return _keysPressed;
}
@ -238,7 +240,7 @@ public:
SDL_ShowCursor(value ? SDL_ENABLE : SDL_DISABLE);
}
void GetCursorPosition(int32_t * x, int32_t * y) override
void GetCursorPosition(int32_t* x, int32_t* y) override
{
SDL_GetMouseState(x, y);
}
@ -284,7 +286,7 @@ public:
return _textComposition.IsActive();
}
TextInputSession * StartTextInput(utf8 * buffer, size_t bufferSize) override
TextInputSession* StartTextInput(utf8* buffer, size_t bufferSize) override
{
return _textComposition.Start(buffer, bufferSize);
}
@ -306,197 +308,203 @@ public:
SDL_Event e;
while (SDL_PollEvent(&e))
{
switch (e.type) {
case SDL_QUIT:
context_quit();
break;
case SDL_WINDOWEVENT:
// HACK: Fix #2158, OpenRCT2 does not draw if it does not think that the window is
// visible - due a bug in SDL 2.0.3 this hack is required if the
// window is maximised, minimised and then restored again.
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
if (SDL_GetWindowFlags(_window) & SDL_WINDOW_MAXIMIZED)
{
SDL_RestoreWindow(_window);
SDL_MaximizeWindow(_window);
}
if ((SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
SDL_RestoreWindow(_window);
SDL_SetWindowFullscreen(_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
OnResize(e.window.data1, e.window.data2);
}
switch (e.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED:
case SDL_WINDOWEVENT_MOVED:
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_RESTORED:
{
// Update default display index
int32_t displayIndex = SDL_GetWindowDisplayIndex(_window);
if (displayIndex != gConfigGeneral.default_display)
{
gConfigGeneral.default_display = displayIndex;
config_save_default();
}
switch (e.type)
{
case SDL_QUIT:
context_quit();
break;
}
}
if (gConfigSound.audio_focus && gConfigSound.sound_enabled)
{
case SDL_WINDOWEVENT:
// HACK: Fix #2158, OpenRCT2 does not draw if it does not think that the window is
// visible - due a bug in SDL 2.0.3 this hack is required if the
// window is maximised, minimised and then restored again.
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
Mixer_SetVolume(1);
if (SDL_GetWindowFlags(_window) & SDL_WINDOW_MAXIMIZED)
{
SDL_RestoreWindow(_window);
SDL_MaximizeWindow(_window);
}
if ((SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
SDL_RestoreWindow(_window);
SDL_SetWindowFullscreen(_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
if (e.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
Mixer_SetVolume(0);
OnResize(e.window.data1, e.window.data2);
}
}
break;
case SDL_MOUSEMOTION:
_cursorState.x = (int32_t)(e.motion.x / gConfigGeneral.window_scale);
_cursorState.y = (int32_t)(e.motion.y / gConfigGeneral.window_scale);
break;
case SDL_MOUSEWHEEL:
if (_inGameConsole.IsOpen())
switch (e.window.event)
{
case SDL_WINDOWEVENT_SIZE_CHANGED:
case SDL_WINDOWEVENT_MOVED:
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_RESTORED:
{
// Update default display index
int32_t displayIndex = SDL_GetWindowDisplayIndex(_window);
if (displayIndex != gConfigGeneral.default_display)
{
gConfigGeneral.default_display = displayIndex;
config_save_default();
}
break;
}
}
if (gConfigSound.audio_focus && gConfigSound.sound_enabled)
{
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
Mixer_SetVolume(1);
}
if (e.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
{
Mixer_SetVolume(0);
}
}
break;
case SDL_MOUSEMOTION:
_cursorState.x = (int32_t)(e.motion.x / gConfigGeneral.window_scale);
_cursorState.y = (int32_t)(e.motion.y / gConfigGeneral.window_scale);
break;
case SDL_MOUSEWHEEL:
if (_inGameConsole.IsOpen())
{
_inGameConsole.Scroll(e.wheel.y * 3); // Scroll 3 lines at a time
break;
}
_cursorState.wheel -= e.wheel.y;
break;
case SDL_MOUSEBUTTONDOWN:
{
_inGameConsole.Scroll(e.wheel.y * 3); // Scroll 3 lines at a time
int32_t x = (int32_t)(e.button.x / gConfigGeneral.window_scale);
int32_t y = (int32_t)(e.button.y / gConfigGeneral.window_scale);
switch (e.button.button)
{
case SDL_BUTTON_LEFT:
store_mouse_input(MOUSE_STATE_LEFT_PRESS, x, y);
_cursorState.left = CURSOR_PRESSED;
_cursorState.old = 1;
break;
case SDL_BUTTON_MIDDLE:
_cursorState.middle = CURSOR_PRESSED;
break;
case SDL_BUTTON_RIGHT:
store_mouse_input(MOUSE_STATE_RIGHT_PRESS, x, y);
_cursorState.right = CURSOR_PRESSED;
_cursorState.old = 2;
break;
}
break;
}
_cursorState.wheel -= e.wheel.y;
break;
case SDL_MOUSEBUTTONDOWN:
{
int32_t x = (int32_t)(e.button.x / gConfigGeneral.window_scale);
int32_t y = (int32_t)(e.button.y / gConfigGeneral.window_scale);
switch (e.button.button) {
case SDL_BUTTON_LEFT:
store_mouse_input(MOUSE_STATE_LEFT_PRESS, x, y);
_cursorState.left = CURSOR_PRESSED;
_cursorState.old = 1;
break;
case SDL_BUTTON_MIDDLE:
_cursorState.middle = CURSOR_PRESSED;
break;
case SDL_BUTTON_RIGHT:
store_mouse_input(MOUSE_STATE_RIGHT_PRESS, x, y);
_cursorState.right = CURSOR_PRESSED;
_cursorState.old = 2;
case SDL_MOUSEBUTTONUP:
{
int32_t x = (int32_t)(e.button.x / gConfigGeneral.window_scale);
int32_t y = (int32_t)(e.button.y / gConfigGeneral.window_scale);
switch (e.button.button)
{
case SDL_BUTTON_LEFT:
store_mouse_input(MOUSE_STATE_LEFT_RELEASE, x, y);
_cursorState.left = CURSOR_RELEASED;
_cursorState.old = 3;
break;
case SDL_BUTTON_MIDDLE:
_cursorState.middle = CURSOR_RELEASED;
break;
case SDL_BUTTON_RIGHT:
store_mouse_input(MOUSE_STATE_RIGHT_RELEASE, x, y);
_cursorState.right = CURSOR_RELEASED;
_cursorState.old = 4;
break;
}
break;
}
break;
}
case SDL_MOUSEBUTTONUP:
{
int32_t x = (int32_t)(e.button.x / gConfigGeneral.window_scale);
int32_t y = (int32_t)(e.button.y / gConfigGeneral.window_scale);
switch (e.button.button) {
case SDL_BUTTON_LEFT:
store_mouse_input(MOUSE_STATE_LEFT_RELEASE, x, y);
_cursorState.left = CURSOR_RELEASED;
_cursorState.old = 3;
break;
case SDL_BUTTON_MIDDLE:
_cursorState.middle = CURSOR_RELEASED;
break;
case SDL_BUTTON_RIGHT:
store_mouse_input(MOUSE_STATE_RIGHT_RELEASE, x, y);
_cursorState.right = CURSOR_RELEASED;
_cursorState.old = 4;
break;
}
break;
}
// Apple sends touchscreen events for trackpads, so ignore these events on macOS
// Apple sends touchscreen events for trackpads, so ignore these events on macOS
#ifndef __MACOSX__
case SDL_FINGERMOTION:
_cursorState.x = (int32_t)(e.tfinger.x * _width);
_cursorState.y = (int32_t)(e.tfinger.y * _height);
break;
case SDL_FINGERDOWN:
{
int32_t x = (int32_t)(e.tfinger.x * _width);
int32_t y = (int32_t)(e.tfinger.y * _height);
_cursorState.touchIsDouble = (!_cursorState.touchIsDouble &&
e.tfinger.timestamp - _cursorState.touchDownTimestamp < TOUCH_DOUBLE_TIMEOUT);
if (_cursorState.touchIsDouble)
case SDL_FINGERMOTION:
_cursorState.x = (int32_t)(e.tfinger.x * _width);
_cursorState.y = (int32_t)(e.tfinger.y * _height);
break;
case SDL_FINGERDOWN:
{
store_mouse_input(MOUSE_STATE_RIGHT_PRESS, x, y);
_cursorState.right = CURSOR_PRESSED;
_cursorState.old = 2;
}
else
{
store_mouse_input(MOUSE_STATE_LEFT_PRESS, x, y);
_cursorState.left = CURSOR_PRESSED;
_cursorState.old = 1;
}
_cursorState.touch = true;
_cursorState.touchDownTimestamp = e.tfinger.timestamp;
break;
}
case SDL_FINGERUP:
{
int32_t x = (int32_t)(e.tfinger.x * _width);
int32_t y = (int32_t)(e.tfinger.y * _height);
int32_t x = (int32_t)(e.tfinger.x * _width);
int32_t y = (int32_t)(e.tfinger.y * _height);
if (_cursorState.touchIsDouble)
_cursorState.touchIsDouble
= (!_cursorState.touchIsDouble
&& e.tfinger.timestamp - _cursorState.touchDownTimestamp < TOUCH_DOUBLE_TIMEOUT);
if (_cursorState.touchIsDouble)
{
store_mouse_input(MOUSE_STATE_RIGHT_PRESS, x, y);
_cursorState.right = CURSOR_PRESSED;
_cursorState.old = 2;
}
else
{
store_mouse_input(MOUSE_STATE_LEFT_PRESS, x, y);
_cursorState.left = CURSOR_PRESSED;
_cursorState.old = 1;
}
_cursorState.touch = true;
_cursorState.touchDownTimestamp = e.tfinger.timestamp;
break;
}
case SDL_FINGERUP:
{
store_mouse_input(MOUSE_STATE_RIGHT_RELEASE, x, y);
_cursorState.right = CURSOR_RELEASED;
_cursorState.old = 4;
int32_t x = (int32_t)(e.tfinger.x * _width);
int32_t y = (int32_t)(e.tfinger.y * _height);
if (_cursorState.touchIsDouble)
{
store_mouse_input(MOUSE_STATE_RIGHT_RELEASE, x, y);
_cursorState.right = CURSOR_RELEASED;
_cursorState.old = 4;
}
else
{
store_mouse_input(MOUSE_STATE_LEFT_RELEASE, x, y);
_cursorState.left = CURSOR_RELEASED;
_cursorState.old = 3;
}
_cursorState.touch = true;
break;
}
else {
store_mouse_input(MOUSE_STATE_LEFT_RELEASE, x, y);
_cursorState.left = CURSOR_RELEASED;
_cursorState.old = 3;
}
_cursorState.touch = true;
break;
}
#endif
case SDL_KEYDOWN:
_textComposition.HandleMessage(&e);
break;
case SDL_MULTIGESTURE:
if (e.mgesture.numFingers == 2)
{
if (e.mgesture.timestamp > _lastGestureTimestamp + 1000)
case SDL_KEYDOWN:
_textComposition.HandleMessage(&e);
break;
case SDL_MULTIGESTURE:
if (e.mgesture.numFingers == 2)
{
_gestureRadius = 0;
}
_lastGestureTimestamp = e.mgesture.timestamp;
_gestureRadius += e.mgesture.dDist;
if (e.mgesture.timestamp > _lastGestureTimestamp + 1000)
{
_gestureRadius = 0;
}
_lastGestureTimestamp = e.mgesture.timestamp;
_gestureRadius += e.mgesture.dDist;
// Zoom gesture
constexpr int32_t tolerance = 128;
int32_t gesturePixels = (int32_t)(_gestureRadius * _width);
if (abs(gesturePixels) > tolerance)
{
_gestureRadius = 0;
main_window_zoom(gesturePixels > 0, true);
// Zoom gesture
constexpr int32_t tolerance = 128;
int32_t gesturePixels = (int32_t)(_gestureRadius * _width);
if (abs(gesturePixels) > tolerance)
{
_gestureRadius = 0;
main_window_zoom(gesturePixels > 0, true);
}
}
}
break;
case SDL_TEXTEDITING:
_textComposition.HandleMessage(&e);
break;
case SDL_TEXTINPUT:
_textComposition.HandleMessage(&e);
break;
default:
break;
break;
case SDL_TEXTEDITING:
_textComposition.HandleMessage(&e);
break;
case SDL_TEXTINPUT:
_textComposition.HandleMessage(&e);
break;
default:
break;
}
}
@ -569,22 +577,22 @@ public:
CreateWindow(x, y);
}
void ShowMessageBox(const std::string &message) override
void ShowMessageBox(const std::string& message) override
{
_platformUiContext->ShowMessageBox(_window, message);
}
std::string ShowFileDialog(const FileDialogDesc &desc) override
std::string ShowFileDialog(const FileDialogDesc& desc) override
{
return _platformUiContext->ShowFileDialog(_window, desc);
}
std::string ShowDirectoryDialog(const std::string &title) override
std::string ShowDirectoryDialog(const std::string& title) override
{
return _platformUiContext->ShowDirectoryDialog(_window, title);
}
IWindowManager * GetWindowManager() override
IWindowManager* GetWindowManager() override
{
return _windowManager;
}
@ -594,7 +602,7 @@ public:
return (SDL_SetClipboardText(target) == 0);
}
ITitleSequencePlayer * GetTitleSequencePlayer() override
ITitleSequencePlayer* GetTitleSequencePlayer() override
{
if (_titleSequencePlayer == nullptr)
{
@ -612,8 +620,10 @@ private:
// Get saved window size
int32_t width = gConfigGeneral.window_width;
int32_t height = gConfigGeneral.window_height;
if (width <= 0) width = 640;
if (height <= 0) height = 480;
if (width <= 0)
width = 640;
if (height <= 0)
height = 480;
// Create window in window first rather than fullscreen so we have the display the window is on first
uint32_t flags = SDL_WINDOW_RESIZABLE;
@ -664,9 +674,7 @@ private:
#ifndef __MACOSX__
SDL_WINDOW_MAXIMIZED |
#endif
SDL_WINDOW_MINIMIZED |
SDL_WINDOW_FULLSCREEN |
SDL_WINDOW_FULLSCREEN_DESKTOP;
SDL_WINDOW_MINIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP;
if (!(flags & nonWindowFlags))
{
@ -706,20 +714,16 @@ private:
}
// Sort by area
std::sort(resolutions.begin(), resolutions.end(),
[](const Resolution &a, const Resolution &b) -> bool
{
int32_t areaA = a.Width * a.Height;
int32_t areaB = b.Width * b.Height;
return areaA < areaB;
});
std::sort(resolutions.begin(), resolutions.end(), [](const Resolution& a, const Resolution& b) -> bool {
int32_t areaA = a.Width * a.Height;
int32_t areaB = b.Width * b.Height;
return areaA < areaB;
});
// Remove duplicates
auto last = std::unique(resolutions.begin(), resolutions.end(),
[](const Resolution &a, const Resolution &b) -> bool
{
return (a.Width == b.Width && a.Height == b.Height);
});
auto last = std::unique(resolutions.begin(), resolutions.end(), [](const Resolution& a, const Resolution& b) -> bool {
return (a.Width == b.Width && a.Height == b.Height);
});
resolutions.erase(last, resolutions.end());
// Update config fullscreen resolution if not set
@ -737,7 +741,7 @@ private:
Resolution result = { 640, 480 };
int32_t closestAreaDiff = -1;
int32_t destinationArea = inWidth * inHeight;
for (const Resolution &resolution : _fsResolutions)
for (const Resolution& resolution : _fsResolutions)
{
// Check if exact match
if (resolution.Width == inWidth && resolution.Height == inHeight)
@ -763,16 +767,16 @@ private:
}
static void DrawRainWindow(
IRainDrawer * rainDrawer,
rct_window * original_w,
IRainDrawer* rainDrawer,
rct_window* original_w,
int16_t left,
int16_t right,
int16_t top,
int16_t bottom,
DrawRainFunc drawFunc)
{
rct_window * w{};
for (auto i = window_get_index(original_w) + 1; ; i++)
rct_window* w{};
for (auto i = window_get_index(original_w) + 1;; i++)
{
if (i >= g_window_list.size())
{
@ -818,7 +822,8 @@ private:
}
int16_t w_right = RCT_WINDOW_RIGHT(w);
if (right > w_right) {
if (right > w_right)
{
DrawRainWindow(rainDrawer, original_w, left, w_right, top, bottom, drawFunc);
left = w_right;
@ -826,7 +831,8 @@ private:
return;
}
if (top < w->y) {
if (top < w->y)
{
DrawRainWindow(rainDrawer, original_w, left, right, top, w->y, drawFunc);
top = w->y;

View File

@ -10,8 +10,8 @@
#pragma once
#include <memory>
#include <string>
#include <openrct2/common.h>
#include <string>
struct SDL_Window;
@ -22,9 +22,9 @@ namespace OpenRCT2
namespace Ui
{
struct FileDialogDesc;
class InGameConsole;
interface IUiContext;
struct FileDialogDesc;
class InGameConsole;
interface IUiContext;
interface IPlatformUiContext
{
@ -32,13 +32,13 @@ namespace OpenRCT2
virtual void SetWindowIcon(SDL_Window * window) abstract;
virtual bool IsSteamOverlayAttached() abstract;
virtual void ShowMessageBox(SDL_Window * window, const std::string &message) abstract;
virtual std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc &desc) abstract;
virtual std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) abstract;
virtual void ShowMessageBox(SDL_Window * window, const std::string& message) abstract;
virtual std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc& desc) abstract;
virtual std::string ShowDirectoryDialog(SDL_Window * window, const std::string& title) abstract;
};
std::unique_ptr<IUiContext> CreateUiContext(const std::shared_ptr<IPlatformEnvironment>& env);
IPlatformUiContext * CreatePlatformUiContext();
IPlatformUiContext* CreatePlatformUiContext();
InGameConsole& GetInGameConsole();
} // namespace Ui

View File

@ -28,18 +28,18 @@ namespace OpenRCT2::Ui
class macOSContext final : public IPlatformUiContext
{
private:
public:
macOSContext()
{
@autoreleasepool {
if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) {
if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)])
{
[NSWindow setAllowsAutomaticWindowTabbing:NO];
}
}
}
void SetWindowIcon(SDL_Window * window) override
void SetWindowIcon(SDL_Window* window) override
{
}
@ -49,49 +49,51 @@ namespace OpenRCT2::Ui
return false;
}
void ShowMessageBox(SDL_Window * window, const std::string &message) override
void ShowMessageBox(SDL_Window* window, const std::string& message) override
{
@autoreleasepool
{
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
@autoreleasepool {
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
[alert addButtonWithTitle:@"OK"];
alert.messageText = [NSString stringWithUTF8String:message.c_str()];
[alert runModal];
}
}
std::string ShowFileDialog(SDL_Window * window, const FileDialogDesc &desc) override
std::string ShowFileDialog(SDL_Window* window, const FileDialogDesc& desc) override
{
@autoreleasepool
{
NSMutableArray *extensions = [NSMutableArray new];
for (const OpenRCT2::Ui::FileDialogDesc::Filter &filter: desc.Filters) {
if (filter.Pattern != "") {
NSString *fp = [NSString stringWithUTF8String:filter.Pattern.c_str()];
@autoreleasepool {
NSMutableArray* extensions = [NSMutableArray new];
for (const OpenRCT2::Ui::FileDialogDesc::Filter& filter : desc.Filters)
{
if (filter.Pattern != "")
{
NSString* fp = [NSString stringWithUTF8String:filter.Pattern.c_str()];
fp = [fp stringByReplacingOccurrencesOfString:@"*." withString:@""];
[extensions addObjectsFromArray:[fp componentsSeparatedByString:@";"]];
}
}
NSString *directory;
NSSavePanel *panel;
NSString* directory;
NSSavePanel* panel;
if (desc.Type == FILE_DIALOG_TYPE::SAVE)
{
NSString *filePath = [NSString stringWithUTF8String:desc.DefaultFilename.c_str()];
NSString* filePath = [NSString stringWithUTF8String:desc.DefaultFilename.c_str()];
directory = filePath.stringByDeletingLastPathComponent;
NSString *basename = filePath.lastPathComponent;
NSString* basename = filePath.lastPathComponent;
panel = [NSSavePanel savePanel];
panel.nameFieldStringValue = [NSString stringWithFormat:@"%@.%@", basename, extensions.firstObject];
}
else if (desc.Type == FILE_DIALOG_TYPE::OPEN)
{
directory = [NSString stringWithUTF8String:desc.InitialDirectory.c_str()];
NSOpenPanel *open = [NSOpenPanel openPanel];
NSOpenPanel* open = [NSOpenPanel openPanel];
open.canChooseDirectories = false;
open.canChooseFiles = true;
open.allowsMultipleSelection = false;
panel = open;
} else {
}
else
{
return std::string();
}
@ -101,36 +103,39 @@ namespace OpenRCT2::Ui
if ([panel runModal] == NSModalResponseCancel)
{
return std::string();
} else {
}
else
{
return panel.URL.path.UTF8String;
}
}
}
std::string ShowDirectoryDialog(SDL_Window * window, const std::string &title) override
std::string ShowDirectoryDialog(SDL_Window* window, const std::string& title) override
{
@autoreleasepool
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
@autoreleasepool {
NSOpenPanel* panel = [NSOpenPanel openPanel];
panel.canChooseFiles = false;
panel.canChooseDirectories = true;
panel.allowsMultipleSelection = false;
if ([panel runModal] == NSModalResponseOK)
{
NSString *selectedPath = panel.URL.path;
const char *path = selectedPath.UTF8String;
NSString* selectedPath = panel.URL.path;
const char* path = selectedPath.UTF8String;
return path;
} else {
}
else
{
return "";
}
}
}
private:
static int32_t Execute(const std::string &command, std::string * output = nullptr)
static int32_t Execute(const std::string& command, std::string* output = nullptr)
{
log_verbose("executing \"%s\"...\n", command.c_str());
FILE * fpipe = popen(command.c_str(), "r");
FILE* fpipe = popen(command.c_str(), "r");
if (fpipe == nullptr)
{
return -1;
@ -174,7 +179,7 @@ namespace OpenRCT2::Ui
}
};
IPlatformUiContext * CreatePlatformUiContext()
IPlatformUiContext* CreatePlatformUiContext()
{
return new macOSContext();
}

View File

@ -7,19 +7,21 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2/ui/WindowManager.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/core/Console.hpp>
#include <openrct2/config/Config.h>
#include <openrct2/interface/Viewport.h>
#include <openrct2/Input.h>
#include <openrct2/world/Sprite.h>
#include "WindowManager.h"
#include "input/Input.h"
#include "input/KeyboardShortcuts.h"
#include "interface/Theme.h"
#include "WindowManager.h"
#include "windows/Window.h"
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Input.h>
#include <openrct2/config/Config.h>
#include <openrct2/core/Console.hpp>
#include <openrct2/interface/Viewport.h>
#include <openrct2/ui/WindowManager.h>
#include <openrct2/world/Sprite.h>
using namespace OpenRCT2::Ui;
class WindowManager final : public IWindowManager
@ -32,405 +34,407 @@ public:
window_new_ride_init_vars();
}
rct_window * OpenWindow(rct_windowclass wc) override
rct_window* OpenWindow(rct_windowclass wc) override
{
switch (wc)
{
case WC_ABOUT:
return window_about_open();
case WC_BOTTOM_TOOLBAR:
return window_game_bottom_toolbar_open();
case WC_CHANGELOG:
return window_changelog_open();
case WC_CHEATS:
return window_cheats_open();
case WC_CLEAR_SCENERY:
return window_clear_scenery_open();
case WC_CUSTOM_CURRENCY_CONFIG:
return custom_currency_window_open();
case WC_DEBUG_PAINT:
return window_debug_paint_open();
case WC_EDITOR_INVENTION_LIST:
return window_editor_inventions_list_open();
case WC_EDITOR_OBJECT_SELECTION:
return window_editor_object_selection_open();
case WC_EDTIOR_OBJECTIVE_OPTIONS:
return window_editor_objective_options_open();
case WC_EDITOR_SCENARIO_OPTIONS:
return window_editor_scenario_options_open();
case WC_FINANCES:
return window_finances_open();
case WC_FOOTPATH:
return window_footpath_open();
case WC_GUEST_LIST:
return window_guest_list_open();
case WC_LAND:
return window_land_open();
case WC_LAND_RIGHTS:
return window_land_rights_open();
case WC_MAIN_WINDOW:
return window_main_open();
case WC_MAP:
return window_map_open();
case WC_MAPGEN:
return window_mapgen_open();
case WC_MULTIPLAYER:
return window_multiplayer_open();
case WC_MUSIC_CREDITS:
return window_music_credits_open();
case WC_CONSTRUCT_RIDE:
return window_new_ride_open();
case WC_PARK_INFORMATION:
return window_park_entrance_open();
case WC_RECENT_NEWS:
return window_news_open();
case WC_RIDE_CONSTRUCTION:
return window_ride_construction_open();
case WC_RESEARCH:
return window_research_open();
case WC_RIDE_LIST:
return window_ride_list_open();
case WC_NOTIFICATION_OPTIONS:
return window_news_options_open();
case WC_OPTIONS:
return window_options_open();
case WC_SAVE_PROMPT:
return window_save_prompt_open();
case WC_SCENERY:
return window_scenery_open();
case WC_SERVER_LIST:
return window_server_list_open();
case WC_SERVER_START:
return window_server_start_open();
case WC_KEYBOARD_SHORTCUT_LIST:
return window_shortcut_keys_open();
case WC_STAFF_LIST:
return window_staff_list_open();
case WC_THEMES:
return window_themes_open();
case WC_TILE_INSPECTOR:
return window_tile_inspector_open();
case WC_TITLE_EXIT:
return window_title_exit_open();
case WC_TITLE_LOGO:
return window_title_logo_open();
case WC_TITLE_MENU:
return window_title_menu_open();
case WC_TITLE_OPTIONS:
return window_title_options_open();
case WC_TOP_TOOLBAR:
return window_top_toolbar_open();
case WC_VIEW_CLIPPING:
return window_view_clipping_open();
case WC_VIEWPORT:
return window_viewport_open();
case WC_WATER:
return window_water_open();
default:
Console::Error::WriteLine("Unhandled window class (%d)", wc);
return nullptr;
case WC_ABOUT:
return window_about_open();
case WC_BOTTOM_TOOLBAR:
return window_game_bottom_toolbar_open();
case WC_CHANGELOG:
return window_changelog_open();
case WC_CHEATS:
return window_cheats_open();
case WC_CLEAR_SCENERY:
return window_clear_scenery_open();
case WC_CUSTOM_CURRENCY_CONFIG:
return custom_currency_window_open();
case WC_DEBUG_PAINT:
return window_debug_paint_open();
case WC_EDITOR_INVENTION_LIST:
return window_editor_inventions_list_open();
case WC_EDITOR_OBJECT_SELECTION:
return window_editor_object_selection_open();
case WC_EDTIOR_OBJECTIVE_OPTIONS:
return window_editor_objective_options_open();
case WC_EDITOR_SCENARIO_OPTIONS:
return window_editor_scenario_options_open();
case WC_FINANCES:
return window_finances_open();
case WC_FOOTPATH:
return window_footpath_open();
case WC_GUEST_LIST:
return window_guest_list_open();
case WC_LAND:
return window_land_open();
case WC_LAND_RIGHTS:
return window_land_rights_open();
case WC_MAIN_WINDOW:
return window_main_open();
case WC_MAP:
return window_map_open();
case WC_MAPGEN:
return window_mapgen_open();
case WC_MULTIPLAYER:
return window_multiplayer_open();
case WC_MUSIC_CREDITS:
return window_music_credits_open();
case WC_CONSTRUCT_RIDE:
return window_new_ride_open();
case WC_PARK_INFORMATION:
return window_park_entrance_open();
case WC_RECENT_NEWS:
return window_news_open();
case WC_RIDE_CONSTRUCTION:
return window_ride_construction_open();
case WC_RESEARCH:
return window_research_open();
case WC_RIDE_LIST:
return window_ride_list_open();
case WC_NOTIFICATION_OPTIONS:
return window_news_options_open();
case WC_OPTIONS:
return window_options_open();
case WC_SAVE_PROMPT:
return window_save_prompt_open();
case WC_SCENERY:
return window_scenery_open();
case WC_SERVER_LIST:
return window_server_list_open();
case WC_SERVER_START:
return window_server_start_open();
case WC_KEYBOARD_SHORTCUT_LIST:
return window_shortcut_keys_open();
case WC_STAFF_LIST:
return window_staff_list_open();
case WC_THEMES:
return window_themes_open();
case WC_TILE_INSPECTOR:
return window_tile_inspector_open();
case WC_TITLE_EXIT:
return window_title_exit_open();
case WC_TITLE_LOGO:
return window_title_logo_open();
case WC_TITLE_MENU:
return window_title_menu_open();
case WC_TITLE_OPTIONS:
return window_title_options_open();
case WC_TOP_TOOLBAR:
return window_top_toolbar_open();
case WC_VIEW_CLIPPING:
return window_view_clipping_open();
case WC_VIEWPORT:
return window_viewport_open();
case WC_WATER:
return window_water_open();
default:
Console::Error::WriteLine("Unhandled window class (%d)", wc);
return nullptr;
}
}
rct_window * OpenView(uint8_t view) override
rct_window* OpenView(uint8_t view) override
{
switch (view)
{
case WV_PARK_AWARDS:
return window_park_awards_open();
case WV_PARK_RATING:
return window_park_rating_open();
case WV_PARK_OBJECTIVE:
return window_park_objective_open();
case WV_PARK_GUESTS:
return window_park_guests_open();
case WV_FINANCES_RESEARCH:
return window_finances_research_open();
case WV_RIDE_RESEARCH:
if (gConfigInterface.toolbar_show_research)
{
return this->OpenWindow(WC_RESEARCH);
}
else
{
return window_new_ride_open_research();
}
case WV_MAZE_CONSTRUCTION:
return window_maze_construction_open();
case WV_NETWORK_PASSWORD:
return window_network_status_open_password();
case WV_EDITOR_BOTTOM_TOOLBAR:
return window_editor_bottom_toolbar_open();
case WV_EDITOR_MAIN:
return window_editor_main_open();
default:
return nullptr;
case WV_PARK_AWARDS:
return window_park_awards_open();
case WV_PARK_RATING:
return window_park_rating_open();
case WV_PARK_OBJECTIVE:
return window_park_objective_open();
case WV_PARK_GUESTS:
return window_park_guests_open();
case WV_FINANCES_RESEARCH:
return window_finances_research_open();
case WV_RIDE_RESEARCH:
if (gConfigInterface.toolbar_show_research)
{
return this->OpenWindow(WC_RESEARCH);
}
else
{
return window_new_ride_open_research();
}
case WV_MAZE_CONSTRUCTION:
return window_maze_construction_open();
case WV_NETWORK_PASSWORD:
return window_network_status_open_password();
case WV_EDITOR_BOTTOM_TOOLBAR:
return window_editor_bottom_toolbar_open();
case WV_EDITOR_MAIN:
return window_editor_main_open();
default:
return nullptr;
}
}
rct_window * OpenDetails(uint8_t type, int32_t id) override
rct_window* OpenDetails(uint8_t type, int32_t id) override
{
switch (type)
{
case WD_BANNER:
return window_banner_open(id);
case WD_DEMOLISH_RIDE:
return window_ride_demolish_prompt_open(id);
case WD_REFURBISH_RIDE:
return window_ride_refurbish_prompt_open(id);
case WD_NEW_CAMPAIGN:
return window_new_campaign_open(id);
case WD_SIGN:
return window_sign_open(id);
case WD_SIGN_SMALL:
return window_sign_small_open(id);
case WD_BANNER:
return window_banner_open(id);
case WD_DEMOLISH_RIDE:
return window_ride_demolish_prompt_open(id);
case WD_REFURBISH_RIDE:
return window_ride_refurbish_prompt_open(id);
case WD_NEW_CAMPAIGN:
return window_new_campaign_open(id);
case WD_SIGN:
return window_sign_open(id);
case WD_SIGN_SMALL:
return window_sign_small_open(id);
case WD_PLAYER:
return window_player_open(id);
case WD_PLAYER:
return window_player_open(id);
default:
return nullptr;
default:
return nullptr;
}
}
rct_window * ShowError(rct_string_id title, rct_string_id message) override
rct_window* ShowError(rct_string_id title, rct_string_id message) override
{
return window_error_open(title, message);
}
rct_window * OpenIntent(Intent * intent) override
rct_window* OpenIntent(Intent* intent) override
{
switch (intent->GetWindowClass())
{
case WC_PEEP:
return window_guest_open((rct_peep*)intent->GetPointerExtra(INTENT_EXTRA_PEEP));
case WC_FIRE_PROMPT:
return window_staff_fire_prompt_open((rct_peep*)intent->GetPointerExtra(INTENT_EXTRA_PEEP));
case WC_INSTALL_TRACK:
return window_install_track_open(intent->GetStringExtra(INTENT_EXTRA_PATH).c_str());
case WC_GUEST_LIST:
return window_guest_list_open_with_filter(intent->GetSIntExtra(INTENT_EXTRA_GUEST_LIST_FILTER), intent->GetSIntExtra(INTENT_EXTRA_RIDE_ID));
case WC_LOADSAVE:
{
uint32_t type = intent->GetUIntExtra(INTENT_EXTRA_LOADSAVE_TYPE);
std::string defaultName = intent->GetStringExtra(INTENT_EXTRA_PATH);
loadsave_callback callback = (loadsave_callback) intent->GetPointerExtra(INTENT_EXTRA_CALLBACK);
rct_window *w = window_loadsave_open(type, defaultName.c_str());
window_loadsave_set_loadsave_callback(callback);
case WC_PEEP:
return window_guest_open((rct_peep*)intent->GetPointerExtra(INTENT_EXTRA_PEEP));
case WC_FIRE_PROMPT:
return window_staff_fire_prompt_open((rct_peep*)intent->GetPointerExtra(INTENT_EXTRA_PEEP));
case WC_INSTALL_TRACK:
return window_install_track_open(intent->GetStringExtra(INTENT_EXTRA_PATH).c_str());
case WC_GUEST_LIST:
return window_guest_list_open_with_filter(
intent->GetSIntExtra(INTENT_EXTRA_GUEST_LIST_FILTER), intent->GetSIntExtra(INTENT_EXTRA_RIDE_ID));
case WC_LOADSAVE:
{
uint32_t type = intent->GetUIntExtra(INTENT_EXTRA_LOADSAVE_TYPE);
std::string defaultName = intent->GetStringExtra(INTENT_EXTRA_PATH);
loadsave_callback callback = (loadsave_callback)intent->GetPointerExtra(INTENT_EXTRA_CALLBACK);
rct_window* w = window_loadsave_open(type, defaultName.c_str());
window_loadsave_set_loadsave_callback(callback);
return w;
}
case WC_MANAGE_TRACK_DESIGN:
return window_track_manage_open((track_design_file_ref *) intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN));
case WC_NETWORK_STATUS:
{
std::string message = intent->GetStringExtra(INTENT_EXTRA_MESSAGE);
close_callback callback = intent->GetCloseCallbackExtra(INTENT_EXTRA_CALLBACK);
return window_network_status_open(message.c_str(), callback);
}
case WC_OBJECT_LOAD_ERROR:
{
std::string path = intent->GetStringExtra(INTENT_EXTRA_PATH);
const rct_object_entry * objects = (rct_object_entry *) intent->GetPointerExtra(INTENT_EXTRA_LIST);
size_t count = intent->GetUIntExtra(INTENT_EXTRA_LIST_COUNT);
window_object_load_error_open(const_cast<utf8 *>(path.c_str()), count, objects);
return w;
}
case WC_MANAGE_TRACK_DESIGN:
return window_track_manage_open((track_design_file_ref*)intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN));
case WC_NETWORK_STATUS:
{
std::string message = intent->GetStringExtra(INTENT_EXTRA_MESSAGE);
close_callback callback = intent->GetCloseCallbackExtra(INTENT_EXTRA_CALLBACK);
return window_network_status_open(message.c_str(), callback);
}
case WC_OBJECT_LOAD_ERROR:
{
std::string path = intent->GetStringExtra(INTENT_EXTRA_PATH);
const rct_object_entry* objects = (rct_object_entry*)intent->GetPointerExtra(INTENT_EXTRA_LIST);
size_t count = intent->GetUIntExtra(INTENT_EXTRA_LIST_COUNT);
window_object_load_error_open(const_cast<utf8*>(path.c_str()), count, objects);
return nullptr;
}
case WC_RIDE:
return window_ride_main_open(intent->GetSIntExtra(INTENT_EXTRA_RIDE_ID));
case WC_TRACK_DESIGN_PLACE:
return window_track_place_open((track_design_file_ref *) intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN));
case WC_TRACK_DESIGN_LIST:
{
ride_list_item rideItem;
rideItem.type = intent->GetUIntExtra(INTENT_EXTRA_RIDE_TYPE);
rideItem.entry_index = intent->GetUIntExtra(INTENT_EXTRA_RIDE_ENTRY_INDEX);
return window_track_list_open(rideItem);
}
case WC_SCENARIO_SELECT:
return window_scenarioselect_open((scenarioselect_callback) intent->GetPointerExtra(INTENT_EXTRA_CALLBACK), false);
case WD_VEHICLE:
return window_ride_open_vehicle((rct_vehicle *) intent->GetPointerExtra(INTENT_EXTRA_VEHICLE));
case WD_TRACK:
return window_ride_open_track((rct_tile_element *) intent->GetPointerExtra(INTENT_EXTRA_TILE_ELEMENT));
case INTENT_ACTION_NEW_RIDE_OF_TYPE:
{
// Open ride list window
auto w = window_new_ride_open();
return nullptr;
}
case WC_RIDE:
return window_ride_main_open(intent->GetSIntExtra(INTENT_EXTRA_RIDE_ID));
case WC_TRACK_DESIGN_PLACE:
return window_track_place_open((track_design_file_ref*)intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN));
case WC_TRACK_DESIGN_LIST:
{
ride_list_item rideItem;
rideItem.type = intent->GetUIntExtra(INTENT_EXTRA_RIDE_TYPE);
rideItem.entry_index = intent->GetUIntExtra(INTENT_EXTRA_RIDE_ENTRY_INDEX);
return window_track_list_open(rideItem);
}
case WC_SCENARIO_SELECT:
return window_scenarioselect_open(
(scenarioselect_callback)intent->GetPointerExtra(INTENT_EXTRA_CALLBACK), false);
case WD_VEHICLE:
return window_ride_open_vehicle((rct_vehicle*)intent->GetPointerExtra(INTENT_EXTRA_VEHICLE));
case WD_TRACK:
return window_ride_open_track((rct_tile_element*)intent->GetPointerExtra(INTENT_EXTRA_TILE_ELEMENT));
case INTENT_ACTION_NEW_RIDE_OF_TYPE:
{
// Open ride list window
auto w = window_new_ride_open();
// Switch to right tab and scroll to ride location
ride_list_item rideItem;
rideItem.type = intent->GetUIntExtra(INTENT_EXTRA_RIDE_TYPE);
rideItem.entry_index = intent->GetUIntExtra(INTENT_EXTRA_RIDE_ENTRY_INDEX);
window_new_ride_focus(rideItem);
// Switch to right tab and scroll to ride location
ride_list_item rideItem;
rideItem.type = intent->GetUIntExtra(INTENT_EXTRA_RIDE_TYPE);
rideItem.entry_index = intent->GetUIntExtra(INTENT_EXTRA_RIDE_ENTRY_INDEX);
window_new_ride_focus(rideItem);
return w;
}
default:
Console::Error::WriteLine("Unhandled window class for intent (%d)", intent->GetWindowClass());
return nullptr;
return w;
}
default:
Console::Error::WriteLine("Unhandled window class for intent (%d)", intent->GetWindowClass());
return nullptr;
}
}
void BroadcastIntent(const Intent &intent) override
void BroadcastIntent(const Intent& intent) override
{
switch (intent.GetWindowClass())
{
case INTENT_ACTION_MAP:
window_map_reset();
break;
case INTENT_ACTION_MAP:
window_map_reset();
break;
case INTENT_ACTION_REFRESH_NEW_RIDES:
window_new_ride_init_vars();
break;
case INTENT_ACTION_REFRESH_NEW_RIDES:
window_new_ride_init_vars();
break;
case INTENT_ACTION_REFRESH_RIDE_LIST:
{
auto window = window_find_by_class(WC_RIDE_LIST);
if (window != nullptr)
case INTENT_ACTION_REFRESH_RIDE_LIST:
{
window_ride_list_refresh_list(window);
}
break;
}
case INTENT_ACTION_UPDATE_MAZE_CONSTRUCTION:
window_maze_construction_update_pressed_widgets();
break;
case INTENT_ACTION_RIDE_CONSTRUCTION_FOCUS:
{
auto rideIndex = intent.GetUIntExtra(INTENT_EXTRA_RIDE_ID);
auto w = window_find_by_class(WC_RIDE_CONSTRUCTION);
if (w == nullptr || w->number != rideIndex)
{
window_close_construction_windows();
_currentRideIndex = rideIndex;
w = OpenWindow(WC_RIDE_CONSTRUCTION);
}
else
{
ride_construction_invalidate_current_track();
_currentRideIndex = rideIndex;
}
break;
}
case INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_PIECES:
window_ride_construction_update_enabled_track_pieces();
break;
case INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_ACTIVE_ELEMENTS:
window_ride_construction_update_active_elements_impl();
break;
case INTENT_ACTION_INIT_SCENERY:
window_scenery_init();
break;
case INTENT_ACTION_SET_DEFAULT_SCENERY_CONFIG:
window_scenery_set_default_placement_configuration();
break;
case INTENT_ACTION_REFRESH_SCENERY:
window_scenery_reset_selected_scenery_items();
break;
case INTENT_ACTION_INVALIDATE_TICKER_NEWS:
window_game_bottom_toolbar_invalidate_news_item();
break;
case INTENT_ACTION_REFRESH_GUEST_LIST:
window_guest_list_refresh_list();
break;
case INTENT_ACTION_REFRESH_STAFF_LIST:
{
auto w = window_find_by_class(WC_STAFF_LIST);
if (w != nullptr)
{
w->no_list_items = 0;
}
break;
}
case INTENT_ACTION_CLEAR_TILE_INSPECTOR_CLIPBOARD:
window_tile_inspector_clear_clipboard();
break;
case INTENT_ACTION_INVALIDATE_VEHICLE_WINDOW:
{
rct_vehicle * vehicle = static_cast<rct_vehicle *>(intent.GetPointerExtra(INTENT_EXTRA_VEHICLE));
int32_t viewVehicleIndex;
Ride * ride;
rct_window * w;
w = window_find_by_number(WC_RIDE, vehicle->ride);
if (w == nullptr)
return;
ride = get_ride(vehicle->ride);
viewVehicleIndex = w->ride.view - 1;
if (viewVehicleIndex < 0 || viewVehicleIndex >= ride->num_vehicles)
return;
if (vehicle->sprite_index != ride->vehicles[viewVehicleIndex])
return;
window_invalidate(w);
break;
}
case INTENT_ACTION_RIDE_PAINT_RESET_VEHICLE:
{
auto rideIndex = intent.GetUIntExtra(INTENT_EXTRA_RIDE_ID);
auto w = window_find_by_number(WC_RIDE, rideIndex);
if (w != nullptr)
{
if (w->page == 4) // WINDOW_RIDE_PAGE_COLOUR
{
w->vehicleIndex = 0;
auto window = window_find_by_class(WC_RIDE_LIST);
if (window != nullptr)
{
window_ride_list_refresh_list(window);
}
window_invalidate(w);
break;
}
}
case INTENT_ACTION_UPDATE_CLIMATE:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_CLIMATE;
window_invalidate_by_class(WC_GUEST_LIST);
break;
case INTENT_ACTION_UPDATE_MAZE_CONSTRUCTION:
window_maze_construction_update_pressed_widgets();
break;
case INTENT_ACTION_UPDATE_PARK_RATING:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_PARK_RATING;
window_invalidate_by_class(WC_PARK_INFORMATION);
break;
case INTENT_ACTION_UPDATE_DATE:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_DATE;
break;
case INTENT_ACTION_UPDATE_CASH:
window_invalidate_by_class(WC_FINANCES);
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_MONEY;
break;
case INTENT_ACTION_UPDATE_BANNER:
{
uint8_t bannerIndex = static_cast<uint8_t>(intent.GetUIntExtra(INTENT_EXTRA_BANNER_INDEX));
rct_window * w = window_find_by_number(WC_BANNER, bannerIndex);
if (w != nullptr)
case INTENT_ACTION_RIDE_CONSTRUCTION_FOCUS:
{
window_invalidate(w);
auto rideIndex = intent.GetUIntExtra(INTENT_EXTRA_RIDE_ID);
auto w = window_find_by_class(WC_RIDE_CONSTRUCTION);
if (w == nullptr || w->number != rideIndex)
{
window_close_construction_windows();
_currentRideIndex = rideIndex;
w = OpenWindow(WC_RIDE_CONSTRUCTION);
}
else
{
ride_construction_invalidate_current_track();
_currentRideIndex = rideIndex;
}
break;
}
break;
}
case INTENT_ACTION_UPDATE_RESEARCH:
window_invalidate_by_class(WC_FINANCES);
window_invalidate_by_class(WC_RESEARCH);
break;
case INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_PIECES:
window_ride_construction_update_enabled_track_pieces();
break;
case INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_ACTIVE_ELEMENTS:
window_ride_construction_update_active_elements_impl();
break;
case INTENT_ACTION_INIT_SCENERY:
window_scenery_init();
break;
case INTENT_ACTION_SET_DEFAULT_SCENERY_CONFIG:
window_scenery_set_default_placement_configuration();
break;
case INTENT_ACTION_REFRESH_SCENERY:
window_scenery_reset_selected_scenery_items();
break;
case INTENT_ACTION_INVALIDATE_TICKER_NEWS:
window_game_bottom_toolbar_invalidate_news_item();
break;
case INTENT_ACTION_REFRESH_GUEST_LIST:
window_guest_list_refresh_list();
break;
case INTENT_ACTION_REFRESH_STAFF_LIST:
{
auto w = window_find_by_class(WC_STAFF_LIST);
if (w != nullptr)
{
w->no_list_items = 0;
}
break;
}
case INTENT_ACTION_CLEAR_TILE_INSPECTOR_CLIPBOARD:
window_tile_inspector_clear_clipboard();
break;
case INTENT_ACTION_INVALIDATE_VEHICLE_WINDOW:
{
rct_vehicle* vehicle = static_cast<rct_vehicle*>(intent.GetPointerExtra(INTENT_EXTRA_VEHICLE));
int32_t viewVehicleIndex;
Ride* ride;
rct_window* w;
w = window_find_by_number(WC_RIDE, vehicle->ride);
if (w == nullptr)
return;
ride = get_ride(vehicle->ride);
viewVehicleIndex = w->ride.view - 1;
if (viewVehicleIndex < 0 || viewVehicleIndex >= ride->num_vehicles)
return;
if (vehicle->sprite_index != ride->vehicles[viewVehicleIndex])
return;
window_invalidate(w);
break;
}
case INTENT_ACTION_RIDE_PAINT_RESET_VEHICLE:
{
auto rideIndex = intent.GetUIntExtra(INTENT_EXTRA_RIDE_ID);
auto w = window_find_by_number(WC_RIDE, rideIndex);
if (w != nullptr)
{
if (w->page == 4) // WINDOW_RIDE_PAGE_COLOUR
{
w->vehicleIndex = 0;
}
window_invalidate(w);
}
}
case INTENT_ACTION_UPDATE_CLIMATE:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_CLIMATE;
window_invalidate_by_class(WC_GUEST_LIST);
break;
case INTENT_ACTION_UPDATE_PARK_RATING:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_PARK_RATING;
window_invalidate_by_class(WC_PARK_INFORMATION);
break;
case INTENT_ACTION_UPDATE_DATE:
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_DATE;
break;
case INTENT_ACTION_UPDATE_CASH:
window_invalidate_by_class(WC_FINANCES);
gToolbarDirtyFlags |= BTM_TB_DIRTY_FLAG_MONEY;
break;
case INTENT_ACTION_UPDATE_BANNER:
{
uint8_t bannerIndex = static_cast<uint8_t>(intent.GetUIntExtra(INTENT_EXTRA_BANNER_INDEX));
rct_window* w = window_find_by_number(WC_BANNER, bannerIndex);
if (w != nullptr)
{
window_invalidate(w);
}
break;
}
case INTENT_ACTION_UPDATE_RESEARCH:
window_invalidate_by_class(WC_FINANCES);
window_invalidate_by_class(WC_RESEARCH);
break;
}
}
@ -438,12 +442,12 @@ public:
{
switch (windowClass)
{
case WC_NETWORK_STATUS:
window_network_status_close();
break;
case WC_NETWORK_STATUS:
window_network_status_close();
break;
default:
break;
default:
break;
}
}
@ -516,7 +520,7 @@ public:
}
};
IWindowManager * OpenRCT2::Ui::CreateWindowManager()
IWindowManager* OpenRCT2::Ui::CreateWindowManager()
{
return new WindowManager();
}

View File

@ -13,5 +13,5 @@ namespace OpenRCT2::Ui
{
interface IWindowManager;
IWindowManager * CreateWindowManager();
}
IWindowManager* CreateWindowManager();
} // namespace OpenRCT2::Ui