diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 0bf6d9dfa0..dc490f3b4b 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -737,6 +737,11 @@ declare global { } interface ButtonWidget extends Widget { + /** + * Whether the button has a 3D border. + * By default, text buttons have borders and image buttons do not but it can be overridden. + */ + border?: boolean; image: number; text: string; onClick: () => void; @@ -745,18 +750,18 @@ declare global { interface CheckboxWidget extends Widget { text: string; isChecked: boolean; - onChanged: (isChecked: boolean) => void; + onChange: (isChecked: boolean) => void; } interface DropdownWidget extends Widget { items: string[]; selectedIndex: number; - onChanged: (index: number) => void; + onChange: (index: number) => void; } interface LabelWidget extends Widget { text: string; - onChanged: (index: number) => void; + onChange: (index: number) => void; } interface SpinnerWidget extends Widget { @@ -776,10 +781,15 @@ declare global { y: number; width: number; height: number; + minWidth: number; + maxWidth: number; + minHeight: number; + maxHeight: number; isSticky: boolean; colours: number[]; title: string; widgets: Widget[]; + tabIndex: number; close(): void; bringToFront(): void; @@ -796,10 +806,28 @@ declare global { id?: number; minWidth?: number; minHeight?: number; + maxWidth?: number; + maxHeight?: number; widgets?: Widget[]; colours?: number[]; + tabs: WindowTabDesc[]; onClose?: () => void; + onUpdate?: () => void; + tabChange?: () => void; + } + + interface ImageAnimation { + frameBase: number; + frameCount?: number; + frameDuration?: number; + offsetX?: number; + offsetY?: number; + } + + interface WindowTabDesc { + image: number | ImageAnimation; + widgets?: Widget[]; } interface Viewport { diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index deafa94571..9e3fcd214d 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -146,6 +146,10 @@ rct_window* window_create( w->windowPos = screenCoords; w->width = width; w->height = height; + w->min_width = width; + w->max_width = width; + w->min_height = height; + w->max_height = height; w->viewport = nullptr; w->event_handlers = event_handlers; w->enabled_widgets = 0; diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 82e43334a3..40960278ff 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -21,6 +21,7 @@ # include # include # include +# include # include # include # include @@ -37,6 +38,7 @@ namespace OpenRCT2::Ui::Windows WIDX_TITLE, WIDX_CLOSE, WIDX_CONTENT_PANEL, + WIDX_TAB_0, WIDX_CUSTOM_BEGIN, }; @@ -52,6 +54,7 @@ namespace OpenRCT2::Ui::Windows static void window_custom_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget); static void window_custom_resize(rct_window* w); static void window_custom_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex); + static void window_custom_update(rct_window* w); static void window_custom_invalidate(rct_window* w); static void window_custom_paint(rct_window* w, rct_drawpixelinfo* dpi); static void window_custom_update_viewport(rct_window* w); @@ -62,7 +65,7 @@ namespace OpenRCT2::Ui::Windows window_custom_mousedown, window_custom_dropdown, nullptr, - nullptr, + window_custom_update, nullptr, nullptr, nullptr, @@ -100,6 +103,7 @@ namespace OpenRCT2::Ui::Windows int32_t SelectedIndex{}; bool IsChecked{}; bool IsDisabled{}; + bool HasBorder{}; // Event handlers DukValue OnClick; @@ -135,10 +139,12 @@ namespace OpenRCT2::Ui::Windows { auto img = dukImage.as_uint(); result.Image = ImageId::FromUInt32(img); + result.HasBorder = false; } else { result.Text = ProcessString(desc["text"]); + result.HasBorder = true; } result.OnClick = desc["onClick"]; } @@ -172,6 +178,46 @@ namespace OpenRCT2::Ui::Windows result.OnIncrement = desc["onIncrement"]; result.OnDecrement = desc["onDecrement"]; } + if (desc["border"].type() == DukValue::Type::BOOLEAN) + { + result.HasBorder = desc["border"].as_bool(); + } + return result; + } + }; + + struct CustomTabDesc + { + ImageId imageFrameBase; + uint32_t imageFrameCount; + uint32_t imageFrameDuration; + int32_t offsetX; + int32_t offsetY; + std::vector Widgets; + + static CustomTabDesc FromDukValue(const DukValue& desc) + { + CustomTabDesc result; + auto dukImage = desc["image"]; + if (dukImage.type() == DukValue::Type::NUMBER) + { + result.imageFrameBase = ImageId::FromUInt32(static_cast(dukImage.as_int())); + } + else if (dukImage.type() == DukValue::Type::OBJECT) + { + result.imageFrameBase = ImageId::FromUInt32(static_cast(dukImage["frameBase"].as_int())); + result.imageFrameCount = AsOrDefault(dukImage["frameCount"], 0); + result.imageFrameDuration = AsOrDefault(dukImage["frameDuration"], 0); + result.offsetX = AsOrDefault(dukImage["offsetX"], 0); + result.offsetY = AsOrDefault(dukImage["offsetY"], 0); + } + if (desc["widgets"].is_array()) + { + auto dukWidgets = desc["widgets"].as_array(); + std::transform(dukWidgets.begin(), dukWidgets.end(), std::back_inserter(result.Widgets), [](const DukValue& w) { + return CustomWidgetDesc::FromDukValue(w); + }); + } return result; } }; @@ -191,9 +237,12 @@ namespace OpenRCT2::Ui::Windows std::optional Id; std::vector Widgets; std::vector Colours; + std::vector Tabs; // Event handlers DukValue OnClose; + DukValue OnUpdate; + DukValue OnTabChange; CustomWindowDesc() = default; @@ -225,6 +274,14 @@ namespace OpenRCT2::Ui::Windows }); } + if (desc["tabs"].is_array()) + { + auto dukTabs = desc["tabs"].as_array(); + std::transform(dukTabs.begin(), dukTabs.end(), std::back_inserter(result.Tabs), [](const DukValue& w) { + return CustomTabDesc::FromDukValue(w); + }); + } + if (desc["colours"].is_array()) { auto dukColours = desc["colours"].as_array(); @@ -239,6 +296,8 @@ namespace OpenRCT2::Ui::Windows } result.OnClose = desc["onClose"]; + result.OnUpdate = desc["onUpdate"]; + result.OnTabChange = desc["onTabChange"]; return result; } @@ -265,7 +324,7 @@ namespace OpenRCT2::Ui::Windows CustomWindowInfo(const CustomWindowInfo&) = delete; - const CustomWidgetDesc* GetCustomWidgetDesc(size_t widgetIndex) const + const CustomWidgetDesc* GetCustomWidgetDesc(rct_window* w, size_t widgetIndex) const { if (widgetIndex < WidgetIndexMap.size()) { @@ -274,13 +333,26 @@ namespace OpenRCT2::Ui::Windows { return &Desc.Widgets[widgetDescIndex]; } + else + { + auto page = w->page; + if (Desc.Tabs.size() > page) + { + auto& widgets = Desc.Tabs[page].Widgets; + auto tabWidgetIndex = widgetDescIndex - Desc.Widgets.size(); + if (tabWidgetIndex < widgets.size()) + { + return &widgets[widgetDescIndex]; + } + } + } } return nullptr; } - CustomWidgetDesc* GetCustomWidgetDesc(size_t widgetIndex) + CustomWidgetDesc* GetCustomWidgetDesc(rct_window* w, size_t widgetIndex) { - return const_cast(std::as_const(*this).GetCustomWidgetDesc(widgetIndex)); + return const_cast(std::as_const(*this).GetCustomWidgetDesc(w, widgetIndex)); } }; @@ -297,11 +369,7 @@ namespace OpenRCT2::Ui::Windows { auto desc = CustomWindowDesc::FromDukValue(dukDesc); - uint16_t windowFlags = 0; - if (desc.IsResizable()) - { - windowFlags |= WF_RESIZABLE; - } + uint16_t windowFlags = WF_RESIZABLE; rct_window* window{}; if (desc.X && desc.Y) @@ -352,6 +420,23 @@ namespace OpenRCT2::Ui::Windows } } + static void window_custom_change_tab(rct_window* w, size_t tabIndex) + { + const auto& info = GetInfo(w); + + w->page = static_cast(tabIndex); + w->frame_no = 0; + RefreshWidgets(w); + + w->Invalidate(); + window_event_resize_call(w); + window_event_invalidate_call(w); + window_init_scroll_widgets(w); + w->Invalidate(); + + InvokeEventHandler(info.Owner, info.Desc.OnTabChange); + } + static void window_custom_mouseup(rct_window* w, rct_widgetindex widgetIndex) { switch (widgetIndex) @@ -362,7 +447,13 @@ namespace OpenRCT2::Ui::Windows default: { const auto& info = GetInfo(w); - const auto widgetDesc = info.GetCustomWidgetDesc(widgetIndex); + if (widgetIndex >= WIDX_TAB_0 && widgetIndex < WIDX_TAB_0 + info.Desc.Tabs.size()) + { + window_custom_change_tab(w, widgetIndex - WIDX_TAB_0); + break; + } + + const auto widgetDesc = info.GetCustomWidgetDesc(w, widgetIndex); if (widgetDesc != nullptr) { if (widgetDesc->Type == "button") @@ -391,19 +482,15 @@ namespace OpenRCT2::Ui::Windows static void window_custom_resize(rct_window* w) { - const auto& desc = GetInfo(w).Desc; - if (desc.IsResizable()) + if (w->width < w->min_width) { - if (w->width < w->min_width) - { - w->Invalidate(); - w->width = w->min_width; - } - if (w->height < w->min_height) - { - w->Invalidate(); - w->height = w->min_height; - } + w->Invalidate(); + w->width = w->min_width; + } + if (w->height < w->min_height) + { + w->Invalidate(); + w->height = w->min_height; } window_custom_update_viewport(w); } @@ -411,7 +498,7 @@ namespace OpenRCT2::Ui::Windows static void window_custom_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) { const auto& info = GetInfo(w); - const auto widgetDesc = info.GetCustomWidgetDesc(widgetIndex); + const auto widgetDesc = info.GetCustomWidgetDesc(w, widgetIndex); if (widgetDesc != nullptr) { if (widgetDesc->Type == "dropdown") @@ -451,7 +538,7 @@ namespace OpenRCT2::Ui::Windows return; auto& info = GetInfo(w); - auto widgetDesc = info.GetCustomWidgetDesc(widgetIndex); + auto widgetDesc = info.GetCustomWidgetDesc(w, widgetIndex); if (widgetDesc != nullptr) { if (widgetDesc->Type == "dropdown") @@ -473,6 +560,36 @@ namespace OpenRCT2::Ui::Windows } } + static void window_custom_update(rct_window* w) + { + const auto& info = GetInfo(w); + if (info.Desc.Tabs.size() > w->page) + { + const auto& tab = info.Desc.Tabs[w->page]; + if (tab.imageFrameCount != 0) + { + w->frame_no++; + if (w->frame_no >= tab.imageFrameCount * tab.imageFrameDuration) + { + w->frame_no = 0; + } + widget_invalidate(w, WIDX_TAB_0 + w->page); + } + InvokeEventHandler(info.Owner, info.Desc.OnUpdate); + } + } + + static void window_custom_set_pressed_tab(rct_window* w) + { + const auto& info = GetInfo(w); + auto numTabs = info.Desc.Tabs.size(); + for (size_t i = 0; i < numTabs; i++) + { + w->pressed_widgets &= ~(1 << (WIDX_TAB_0 + i)); + } + w->pressed_widgets |= 1LL << (WIDX_TAB_0 + w->page); + } + static void window_custom_invalidate(rct_window* w) { w->widgets[WIDX_BACKGROUND].right = w->width - 1; @@ -483,13 +600,42 @@ namespace OpenRCT2::Ui::Windows w->widgets[WIDX_CONTENT_PANEL].right = w->width - 1; w->widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; + window_custom_set_pressed_tab(w); + const auto& desc = GetInfo(w).Desc; set_format_arg(0, void*, desc.Title.c_str()); } + static void window_custom_draw_tab_images(rct_window* w, rct_drawpixelinfo* dpi) + { + const auto& customInfo = GetInfo(w); + const auto& tabs = customInfo.Desc.Tabs; + size_t tabIndex = 0; + for (auto tab : tabs) + { + auto widgetIndex = static_cast(WIDX_TAB_0 + tabIndex); + auto widget = &w->widgets[widgetIndex]; + if (widget_is_enabled(w, widgetIndex)) + { + auto l = w->windowPos.x + widget->left + tab.offsetX; + auto t = w->windowPos.y + widget->top + tab.offsetY; + auto image = tab.imageFrameBase; + if (w->page == tabIndex && tab.imageFrameDuration != 0 && tab.imageFrameCount != 0) + { + auto frame = w->frame_no / tab.imageFrameDuration; + auto imageOffset = frame % tab.imageFrameCount; + image = image.WithIndex(image.GetIndex() + imageOffset); + } + gfx_draw_sprite(dpi, image.ToUInt32(), l, t, image.GetTertiary()); + } + tabIndex++; + } + } + static void window_custom_paint(rct_window* w, rct_drawpixelinfo* dpi) { window_draw_widgets(w, dpi); + window_custom_draw_tab_images(w, dpi); if (w->viewport != nullptr) { window_draw_viewport(dpi, w); @@ -517,7 +663,7 @@ namespace OpenRCT2::Ui::Windows { auto viewportWidget = &w->widgets[*viewportWidgetIndex]; auto& customInfo = GetInfo(w); - auto widgetInfo = customInfo.GetCustomWidgetDesc(*viewportWidgetIndex); + auto widgetInfo = customInfo.GetCustomWidgetDesc(w, *viewportWidgetIndex); if (widgetInfo != nullptr) { if (w->viewport == nullptr) @@ -560,8 +706,8 @@ namespace OpenRCT2::Ui::Windows widget.colour = 1; widget.left = desc.X; widget.top = desc.Y; - widget.right = desc.X + desc.Width; - widget.bottom = desc.Y + desc.Height; + widget.right = desc.X + desc.Width - 1; + widget.bottom = desc.Y + desc.Height - 1; widget.content = std::numeric_limits::max(); widget.tooltip = STR_NONE; widget.flags = WIDGET_FLAGS::IS_ENABLED; @@ -572,7 +718,7 @@ namespace OpenRCT2::Ui::Windows { if (desc.Image.HasValue()) { - widget.type = WWT_FLATBTN; + widget.type = desc.HasBorder ? WWT_IMGBTN : WWT_FLATBTN; widget.image = desc.Image.ToUInt32(); } else @@ -608,10 +754,10 @@ namespace OpenRCT2::Ui::Windows widget = {}; widget.type = WWT_BUTTON; widget.colour = 1; - widget.left = desc.X + desc.Width - 11; - widget.right = desc.X + desc.Width - 1; + widget.left = desc.X + desc.Width - 12; + widget.right = desc.X + desc.Width - 2; widget.top = desc.Y + 1; - widget.bottom = desc.Y + desc.Height - 1; + widget.bottom = desc.Y + desc.Height - 2; widget.text = STR_DROPDOWN_GLYPH; widget.tooltip = STR_NONE; widget.flags |= WIDGET_FLAGS::IS_ENABLED; @@ -642,17 +788,17 @@ namespace OpenRCT2::Ui::Windows widget = {}; widget.type = WWT_BUTTON; widget.colour = 1; - widget.left = desc.X + desc.Width - 25; + widget.left = desc.X + desc.Width - 26; widget.right = widget.left + 12; widget.top = desc.Y + 1; - widget.bottom = desc.Y + desc.Height - 1; + widget.bottom = desc.Y + desc.Height - 2; widget.text = STR_NUMERIC_DOWN; widget.tooltip = STR_NONE; widget.flags |= WIDGET_FLAGS::IS_ENABLED; widgetList.push_back(widget); // Add the increment button - widget.left = desc.X + desc.Width - 12; + widget.left = desc.X + desc.Width - 13; widget.right = widget.left + 11; widget.text = STR_NUMERIC_UP; widgetList.push_back(widget); @@ -667,10 +813,15 @@ namespace OpenRCT2::Ui::Windows static void RefreshWidgets(rct_window* w) { + w->enabled_widgets = 0; + w->pressed_widgets = 0; + w->disabled_widgets = 0; + auto& info = GetInfo(w); auto& widgets = info.Widgets; widgets.clear(); + info.WidgetIndexMap.clear(); // Add default widgets (window shim) widgets.insert(widgets.begin(), std::begin(CustomDefaultWidgets), std::end(CustomDefaultWidgets)); @@ -678,11 +829,41 @@ namespace OpenRCT2::Ui::Windows { info.WidgetIndexMap.push_back(std::numeric_limits::max()); } + w->enabled_widgets = 1ULL << WIDX_CLOSE; + + // Add window tabs + if (info.Desc.Tabs.size() != 0) + { + widgets[WIDX_CONTENT_PANEL].top = 43; + } + for (size_t tabDescIndex = 0; tabDescIndex < info.Desc.Tabs.size(); tabDescIndex++) + { + rct_widget widget{}; + widget.type = WWT_TAB; + widget.colour = 1; + widget.left = static_cast(3 + (tabDescIndex * 31)); + widget.right = widget.left + 30; + widget.top = 17; + widget.bottom = 43; + widget.image = IMAGE_TYPE_REMAP | SPR_TAB; + widget.tooltip = STR_NONE; + widgets.push_back(widget); + info.WidgetIndexMap.push_back(std::numeric_limits::max()); + w->enabled_widgets |= 1ULL << (widgets.size() - 1); + } // Add custom widgets - for (size_t widgetDescIndex = 0; widgetDescIndex < info.Desc.Widgets.size(); widgetDescIndex++) + auto totalWidgets = info.Desc.Widgets.size(); + auto tabWidgetsOffset = totalWidgets; + if (info.Desc.Tabs.size() != 0) { - const auto& widgetDesc = info.Desc.Widgets[widgetDescIndex]; + totalWidgets += info.Desc.Tabs[w->page].Widgets.size(); + } + for (size_t widgetDescIndex = 0; widgetDescIndex < totalWidgets; widgetDescIndex++) + { + const auto& widgetDesc = widgetDescIndex < info.Desc.Widgets.size() + ? info.Desc.Widgets[widgetDescIndex] + : info.Desc.Tabs[w->page].Widgets[widgetDescIndex - tabWidgetsOffset]; auto preWidgetSize = widgets.size(); CreateWidget(widgets, widgetDesc); auto numWidetsAdded = widgets.size() - preWidgetSize; @@ -690,17 +871,10 @@ namespace OpenRCT2::Ui::Windows { info.WidgetIndexMap.push_back(widgetDescIndex); } - } - widgets.push_back({ WIDGETS_END }); - w->widgets = widgets.data(); - - // Enable widgets - w->enabled_widgets = 1ULL << WIDX_CLOSE; - for (size_t i = 0; i < std::min(widgets.size(), 64); i++) - { - auto mask = 1ULL << i; - auto flags = widgets[i].flags; + auto widgetIndex = widgets.size() - 1; + auto mask = 1ULL << widgetIndex; + auto flags = widgets[widgetIndex].flags; if (flags & WIDGET_FLAGS::IS_ENABLED) { w->enabled_widgets |= mask; @@ -714,6 +888,9 @@ namespace OpenRCT2::Ui::Windows w->disabled_widgets |= mask; } } + + widgets.push_back({ WIDGETS_END }); + w->widgets = widgets.data(); } static void InvokeEventHandler(const std::shared_ptr& owner, const DukValue& dukHandler) @@ -753,7 +930,7 @@ namespace OpenRCT2::Ui::Windows if (w->custom_info != nullptr) { auto& customInfo = GetInfo(w); - auto customWidgetInfo = customInfo.GetCustomWidgetDesc(widgetIndex); + auto customWidgetInfo = customInfo.GetCustomWidgetDesc(w, widgetIndex); if (customWidgetInfo != nullptr) { customWidgetInfo->Text = language_convert_string(value); @@ -786,7 +963,7 @@ namespace OpenRCT2::Ui::Windows auto& customInfo = GetInfo(w); for (size_t i = 0; i < customInfo.Widgets.size(); i++) { - auto customWidgetInfo = customInfo.GetCustomWidgetDesc(i); + auto customWidgetInfo = customInfo.GetCustomWidgetDesc(w, i); if (customWidgetInfo != nullptr) { if (customWidgetInfo->Name == name) diff --git a/src/openrct2-ui/scripting/ScWidget.hpp b/src/openrct2-ui/scripting/ScWidget.hpp index 2a6efecc57..ee112cfbed 100644 --- a/src/openrct2-ui/scripting/ScWidget.hpp +++ b/src/openrct2-ui/scripting/ScWidget.hpp @@ -101,6 +101,7 @@ namespace OpenRCT2::Scripting if (widget != nullptr) { Invalidate(); + widget->right = value + widget->right - widget->left; widget->left = value; Invalidate(); } @@ -121,6 +122,7 @@ namespace OpenRCT2::Scripting if (widget != nullptr) { Invalidate(); + widget->bottom = value + widget->bottom - widget->top; widget->top = value; Invalidate(); } diff --git a/src/openrct2-ui/scripting/ScWindow.hpp b/src/openrct2-ui/scripting/ScWindow.hpp index 1dfd629bb1..1efab2166c 100644 --- a/src/openrct2-ui/scripting/ScWindow.hpp +++ b/src/openrct2-ui/scripting/ScWindow.hpp @@ -71,11 +71,105 @@ namespace OpenRCT2::Scripting } int32_t width_get() const { - return GetWindow()->width; + auto w = GetWindow(); + if (w != nullptr) + { + return w->width; + } + return 0; + } + void width_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_resize(w, value - w->width, 0); + } } int32_t height_get() const { - return GetWindow()->height; + auto w = GetWindow(); + if (w != nullptr) + { + return w->height; + } + return 0; + } + void height_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_resize(w, 0, value - w->height); + } + } + int32_t minWidth_get() const + { + auto w = GetWindow(); + if (w != nullptr) + { + return w->min_width; + } + return 0; + } + void minWidth_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_set_resize(w, value, w->min_height, w->max_width, w->max_height); + } + } + int32_t maxWidth_get() const + { + auto w = GetWindow(); + if (w != nullptr) + { + return w->max_width; + } + return 0; + } + void maxWidth_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_set_resize(w, w->min_width, w->min_height, value, w->max_height); + } + } + int32_t minHeight_get() const + { + auto w = GetWindow(); + if (w != nullptr) + { + return w->min_height; + } + return 0; + } + void minHeight_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_set_resize(w, w->min_width, value, w->max_width, w->max_height); + } + } + int32_t maxHeight_get() const + { + auto w = GetWindow(); + if (w != nullptr) + { + return w->max_height; + } + return 0; + } + void maxHeight_set(int32_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + window_set_resize(w, w->min_width, w->min_height, w->max_width, value); + } } bool isSticky_get() const { @@ -144,6 +238,16 @@ namespace OpenRCT2::Scripting } } + int32_t tabIndex_get() const + { + auto w = GetWindow(); + if (w != nullptr && w->classification == WC_CUSTOM) + { + return w->page; + } + return 0; + } + void close() { auto w = GetWindow(); @@ -183,12 +287,17 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScWindow::number_get, nullptr, "number"); dukglue_register_property(ctx, &ScWindow::x_get, &ScWindow::x_set, "x"); dukglue_register_property(ctx, &ScWindow::y_get, &ScWindow::y_set, "y"); - dukglue_register_property(ctx, &ScWindow::width_get, nullptr, "width"); - dukglue_register_property(ctx, &ScWindow::height_get, nullptr, "height"); + dukglue_register_property(ctx, &ScWindow::width_get, &ScWindow::width_set, "width"); + dukglue_register_property(ctx, &ScWindow::height_get, &ScWindow::height_set, "height"); + dukglue_register_property(ctx, &ScWindow::minWidth_get, &ScWindow::minWidth_set, "minWidth"); + dukglue_register_property(ctx, &ScWindow::maxWidth_get, &ScWindow::maxWidth_set, "maxWidth"); + dukglue_register_property(ctx, &ScWindow::minHeight_get, &ScWindow::minHeight_set, "minHeight"); + dukglue_register_property(ctx, &ScWindow::maxHeight_get, &ScWindow::maxHeight_set, "maxHeight"); dukglue_register_property(ctx, &ScWindow::isSticky_get, nullptr, "isSticky"); dukglue_register_property(ctx, &ScWindow::widgets_get, nullptr, "widgets"); dukglue_register_property(ctx, &ScWindow::colours_get, &ScWindow::colours_set, "colours"); dukglue_register_property(ctx, &ScWindow::title_get, &ScWindow::title_set, "title"); + dukglue_register_property(ctx, &ScWindow::tabIndex_get, nullptr, "tabIndex"); dukglue_register_method(ctx, &ScWindow::close, "close"); dukglue_register_method(ctx, &ScWindow::findWidget, "findWidget"); diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 4cb29bd83e..9381113bd2 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1317,8 +1317,8 @@ void window_set_resize(rct_window* w, int32_t minWidth, int32_t minHeight, int32 w->max_height = maxHeight; // Clamp width and height to minimum and maximum - int32_t width = std::clamp(w->width, minWidth, maxWidth); - int32_t height = std::clamp(w->height, minHeight, maxHeight); + int32_t width = std::clamp(w->width, std::min(minWidth, maxWidth), std::max(minWidth, maxWidth)); + int32_t height = std::clamp(w->height, std::min(minHeight, maxHeight), std::max(minHeight, maxHeight)); // Resize window if size has changed if (w->width != width || w->height != height) diff --git a/src/openrct2/localisation/Language.cpp b/src/openrct2/localisation/Language.cpp index 9fa7b04f09..c8be0188e4 100644 --- a/src/openrct2/localisation/Language.cpp +++ b/src/openrct2/localisation/Language.cpp @@ -208,7 +208,7 @@ std::string language_convert_string(const std::string_view& s) state = PARSE_STATE::TOKEN; break; default: - if (c >= 32) + if (static_cast(c) >= 32) { result.push_back(c); }