mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-30 10:15:36 +01:00
Get custom buttons working
This commit is contained in:
@@ -361,8 +361,15 @@ static void widget_text_centred(rct_drawpixelinfo* dpi, rct_window* w, rct_widge
|
||||
else
|
||||
t = w->windowPos.y + widget->top;
|
||||
|
||||
auto stringId = widget->text;
|
||||
void * formatArgs = gCommonFormatArgs;
|
||||
if (widget->flags & WIDGET_FLAGS::TEXT_IS_STRING)
|
||||
{
|
||||
stringId = STR_STRING;
|
||||
formatArgs = &widget->string;
|
||||
}
|
||||
gfx_draw_string_centred_clipped(
|
||||
dpi, widget->text, gCommonFormatArgs, colour, (l + r + 1) / 2 - 1, t, widget->right - widget->left - 2);
|
||||
dpi, stringId, formatArgs, colour, (l + r + 1) / 2 - 1, t, widget->right - widget->left - 2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,7 +406,14 @@ static void widget_text(rct_drawpixelinfo* dpi, rct_window* w, rct_widgetindex w
|
||||
else
|
||||
t = w->windowPos.y + widget->top;
|
||||
|
||||
gfx_draw_string_left_clipped(dpi, widget->text, gCommonFormatArgs, colour, l + 1, t, r - l);
|
||||
auto stringId = widget->text;
|
||||
void * formatArgs = gCommonFormatArgs;
|
||||
if (widget->flags & WIDGET_FLAGS::TEXT_IS_STRING)
|
||||
{
|
||||
stringId = STR_STRING;
|
||||
formatArgs = &widget->string;
|
||||
}
|
||||
gfx_draw_string_left_clipped(dpi, stringId, formatArgs, colour, l + 1, t, r - l);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <openrct2/drawing/Drawing.h>
|
||||
#include <openrct2/localisation/Localisation.h>
|
||||
#include <openrct2/localisation/StringIds.h>
|
||||
@@ -29,14 +31,14 @@ namespace OpenRCT2::Ui::Windows
|
||||
WIDX_TITLE,
|
||||
WIDX_CLOSE,
|
||||
WIDX_CONTENT_PANEL,
|
||||
WIDX_CUSTOM_BEGIN,
|
||||
};
|
||||
|
||||
static rct_widget window_custom_widgets[] = {
|
||||
static rct_widget CustomDefaultWidgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 0, 0, 0, 0xFFFFFFFF, STR_NONE }, // panel / background
|
||||
{ WWT_CAPTION, 0, 1, 0, 1, 14, STR_STRING, STR_WINDOW_TITLE_TIP }, // title bar
|
||||
{ WWT_CLOSEBOX, 0, 0, 0, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
|
||||
{ WWT_RESIZE, 1, 0, 0, 14, 0, 0xFFFFFFFF, STR_NONE }, // content panel
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static void window_custom_close(rct_window *w);
|
||||
@@ -79,6 +81,33 @@ namespace OpenRCT2::Ui::Windows
|
||||
nullptr
|
||||
};
|
||||
|
||||
struct CustomWidgetDesc
|
||||
{
|
||||
// Properties
|
||||
std::string Type;
|
||||
sint32 X;
|
||||
sint32 Y;
|
||||
sint32 Width;
|
||||
sint32 Height;
|
||||
std::string Text;
|
||||
|
||||
// Event handlers
|
||||
DukValue OnClick;
|
||||
|
||||
static CustomWidgetDesc FromDukValue(DukValue desc)
|
||||
{
|
||||
CustomWidgetDesc result;
|
||||
result.Type = desc["type"].as_string();
|
||||
result.X = desc["x"].as_int();
|
||||
result.Y = desc["y"].as_int();
|
||||
result.Width = desc["width"].as_int();
|
||||
result.Height = desc["height"].as_int();
|
||||
result.Text = desc["text"].as_string();
|
||||
result.OnClick = desc["onClick"];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct CustomWindowDesc
|
||||
{
|
||||
std::string Classification;
|
||||
@@ -92,6 +121,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
std::optional<sint32> MaxHeight;
|
||||
std::string Title;
|
||||
std::optional<sint32> Id;
|
||||
std::vector<CustomWidgetDesc> Widgets;
|
||||
|
||||
CustomWindowDesc() = default;
|
||||
|
||||
@@ -114,6 +144,14 @@ namespace OpenRCT2::Ui::Windows
|
||||
result.MaxHeight = GetOptionalInt(desc["maxHeight"]);
|
||||
result.Title = desc["title"].as_string();
|
||||
result.Id = GetOptionalInt(desc["id"]);
|
||||
|
||||
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 std::move(result);
|
||||
}
|
||||
|
||||
@@ -134,6 +172,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
public:
|
||||
std::shared_ptr<Plugin> Owner;
|
||||
CustomWindowDesc Desc;
|
||||
std::vector<rct_widget> Widgets;
|
||||
|
||||
CustomWindowInfo(
|
||||
rct_windowclass cls,
|
||||
@@ -154,6 +193,8 @@ namespace OpenRCT2::Ui::Windows
|
||||
|
||||
static CustomWindowInfo& GetInfo(rct_window * w);
|
||||
static rct_windownumber GetNewWindowNumber();
|
||||
static void RefreshWidgets(rct_window * w);
|
||||
static void InvokeEventHandler(std::shared_ptr<Plugin> owner, const DukValue& dukHandler);
|
||||
|
||||
rct_window * window_custom_open(std::shared_ptr<Plugin> owner, DukValue dukDesc)
|
||||
{
|
||||
@@ -189,7 +230,6 @@ namespace OpenRCT2::Ui::Windows
|
||||
|
||||
window->number = GetNewWindowNumber();
|
||||
window->custom_info = new CustomWindowInfo(window->classification, window->number, owner, desc);
|
||||
window->widgets = window_custom_widgets;
|
||||
window->enabled_widgets = (1 << WIDX_CLOSE);
|
||||
window->colours[0] = COLOUR_GREY;
|
||||
window->colours[1] = COLOUR_GREY;
|
||||
@@ -201,7 +241,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
window->max_width = desc.MaxWidth.value_or(std::numeric_limits<uint16>::max());
|
||||
window->max_height = desc.MaxHeight.value_or(std::numeric_limits<uint16>::max());
|
||||
}
|
||||
|
||||
RefreshWidgets(window);
|
||||
window_init_scroll_widgets(window);
|
||||
return window;
|
||||
}
|
||||
@@ -218,6 +258,13 @@ namespace OpenRCT2::Ui::Windows
|
||||
case WIDX_CLOSE:
|
||||
window_close(w);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
const auto& info = GetInfo(w);
|
||||
const auto& widgetDesc = info.Desc.Widgets[widgetIndex - WIDX_CUSTOM_BEGIN];
|
||||
InvokeEventHandler(info.Owner, widgetDesc.OnClick);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,13 +288,13 @@ namespace OpenRCT2::Ui::Windows
|
||||
|
||||
static void window_custom_invalidate(rct_window * w)
|
||||
{
|
||||
window_custom_widgets[WIDX_BACKGROUND].right = w->width - 1;
|
||||
window_custom_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
|
||||
window_custom_widgets[WIDX_TITLE].right = w->width - 2;
|
||||
window_custom_widgets[WIDX_CLOSE].left = w->width - 13;
|
||||
window_custom_widgets[WIDX_CLOSE].right = w->width - 3;
|
||||
window_custom_widgets[WIDX_CONTENT_PANEL].right = w->width - 1;
|
||||
window_custom_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1;
|
||||
w->widgets[WIDX_BACKGROUND].right = w->width - 1;
|
||||
w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
|
||||
w->widgets[WIDX_TITLE].right = w->width - 2;
|
||||
w->widgets[WIDX_CLOSE].left = w->width - 13;
|
||||
w->widgets[WIDX_CLOSE].right = w->width - 3;
|
||||
w->widgets[WIDX_CONTENT_PANEL].right = w->width - 1;
|
||||
w->widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1;
|
||||
|
||||
const auto& desc = GetInfo(w).Desc;
|
||||
set_format_arg(0, void *, desc.Title.c_str());
|
||||
@@ -272,4 +319,55 @@ namespace OpenRCT2::Ui::Windows
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void RefreshWidgets(rct_window * w)
|
||||
{
|
||||
auto& info = GetInfo(w);
|
||||
auto& widgets = info.Widgets;
|
||||
|
||||
widgets.clear();
|
||||
|
||||
// Add default widgets (window shim)
|
||||
widgets.insert(widgets.begin(), std::begin(CustomDefaultWidgets), std::end(CustomDefaultWidgets));
|
||||
w->enabled_widgets = 1ULL << WIDX_CLOSE;
|
||||
|
||||
// Add custom widgets
|
||||
for (const auto& widgetDesc : info.Desc.Widgets)
|
||||
{
|
||||
rct_widget widget{};
|
||||
widget.type = WWT_BUTTON;
|
||||
widget.left = widgetDesc.X;
|
||||
widget.top = widgetDesc.Y;
|
||||
widget.right = widgetDesc.X + widgetDesc.Width;
|
||||
widget.bottom = widgetDesc.Y + widgetDesc.Height;
|
||||
widget.string = (utf8*)widgetDesc.Text.c_str();
|
||||
widget.tooltip = STR_NONE;
|
||||
widget.flags = WIDGET_FLAGS::TEXT_IS_STRING;
|
||||
widgets.push_back(widget);
|
||||
|
||||
auto widgetIndex = widgets.size() - 1;
|
||||
if (widgetIndex < 64)
|
||||
{
|
||||
w->enabled_widgets |= 1ULL << widgetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
widgets.push_back({ WIDGETS_END });
|
||||
w->widgets = widgets.data();
|
||||
}
|
||||
|
||||
static void InvokeEventHandler(std::shared_ptr<Plugin> owner, const DukValue& dukHandler)
|
||||
{
|
||||
if (dukHandler.is_function())
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto& execInfo = scriptEngine.GetExecInfo();
|
||||
{
|
||||
ScriptExecutionInfo::PluginScope scope(execInfo, owner);
|
||||
dukHandler.push();
|
||||
duk_pcall(dukHandler.context(), 0);
|
||||
duk_pop(dukHandler.context());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,12 @@ struct widget_identifier
|
||||
|
||||
extern widget_identifier gCurrentTextBox;
|
||||
|
||||
using WidgetFlags = uint32;
|
||||
namespace WIDGET_FLAGS
|
||||
{
|
||||
const uint32 TEXT_IS_STRING = 1 << 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget structure
|
||||
* size: 0x10
|
||||
@@ -84,6 +90,9 @@ struct rct_widget
|
||||
utf8* string;
|
||||
};
|
||||
rct_string_id tooltip; // 0x0E
|
||||
|
||||
// New properties
|
||||
WidgetFlags flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user