From 030713e126abc76bbf10e507d0ae1dd06d670e10 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 2 Dec 2020 00:21:33 +0000 Subject: [PATCH] Fix #13078: [Plugin] Add colour picker widget --- distribution/changelog.txt | 1 + distribution/openrct2.d.ts | 7 ++- src/openrct2-ui/interface/Widget.cpp | 5 ++ src/openrct2-ui/interface/Widget.h | 2 + src/openrct2-ui/scripting/CustomWindow.cpp | 69 +++++++++++++++++++++- src/openrct2-ui/scripting/CustomWindow.h | 2 + src/openrct2-ui/scripting/ScWidget.hpp | 40 ++++++++++++- src/openrct2-ui/scripting/UiExtensions.cpp | 1 + 8 files changed, 123 insertions(+), 4 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 0822110772..df096a268a 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,6 +1,7 @@ 0.3.2+ (in development) ------------------------------------------------------------------------ - Feature: [#13057] Make GameAction flags accessible by plugins. +- Feature: [#13078] [Plugin] Add colour picker widget. - Feature: [#13376] Open custom window at specified tab. - Feature: [#13398] Add pause button to the Track Designer. - Feature: [#13495] [Plugin] Add properties for park value, guests and company value. diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 11de1d5cdd..d21f2e8b2b 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -1784,7 +1784,7 @@ declare global { * Represents the type of a widget, e.g. button or label. */ type WidgetType = - "button" | "checkbox" | "dropdown" | "groupbox" | "label" | "listview" | "spinner" | "viewport"; + "button" | "checkbox" | "colourpicker" | "dropdown" | "groupbox" | "label" | "listview" | "spinner" | "viewport"; interface Widget { type: WidgetType; @@ -1815,6 +1815,11 @@ declare global { onChange: (isChecked: boolean) => void; } + interface ColourPickerWidget extends Widget { + colour: number; + onChange: (colour: number) => void; + } + interface DropdownWidget extends Widget { items: string[]; selectedIndex: number; diff --git a/src/openrct2-ui/interface/Widget.cpp b/src/openrct2-ui/interface/Widget.cpp index 9dffee73f8..4c7edf6563 100644 --- a/src/openrct2-ui/interface/Widget.cpp +++ b/src/openrct2-ui/interface/Widget.cpp @@ -1105,3 +1105,8 @@ static void WidgetTextBoxDraw(rct_drawpixelinfo* dpi, rct_window* w, rct_widgeti gfx_fill_rect(dpi, { { cur_x, y }, { cur_x + width, y } }, colour + 5); } } + +uint32_t GetColourButtonImage(colour_t colour) +{ + return SPRITE_ID_PALETTE_COLOUR_1(colour) | IMAGE_TYPE_TRANSPARENT | SPR_PALETTE_BTN; +} diff --git a/src/openrct2-ui/interface/Widget.h b/src/openrct2-ui/interface/Widget.h index e28f1acd4f..6c6de4eac2 100644 --- a/src/openrct2-ui/interface/Widget.h +++ b/src/openrct2-ui/interface/Widget.h @@ -10,3 +10,5 @@ #pragma once #include + +uint32_t GetColourButtonImage(colour_t colour); diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 4ee5097111..4fd60372b0 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -91,6 +91,7 @@ namespace OpenRCT2::Ui::Windows std::string Name; ImageId Image; std::string Text; + colour_t Colour; std::string Tooltip; std::vector Items; std::vector ListViewItems; @@ -147,6 +148,15 @@ namespace OpenRCT2::Ui::Windows result.IsChecked = AsOrDefault(desc["isChecked"], false); result.OnChange = desc["onChange"]; } + else if (result.Type == "colourpicker") + { + auto colour = AsOrDefault(desc["colour"], 0); + if (colour < COLOUR_COUNT) + { + result.Colour = colour; + } + result.OnChange = desc["onChange"]; + } else if (result.Type == "dropdown") { auto dukItems = desc["items"].as_array(); @@ -510,7 +520,11 @@ namespace OpenRCT2::Ui::Windows const auto widgetDesc = info.GetCustomWidgetDesc(w, widgetIndex); if (widgetDesc != nullptr) { - if (widgetDesc->Type == "dropdown") + if (widgetDesc->Type == "colourpicker") + { + WindowDropdownShowColour(w, widget, w->colours[widget->colour], widgetDesc->Colour); + } + else if (widgetDesc->Type == "dropdown") { widget--; auto selectedIndex = widgetDesc->SelectedIndex; @@ -550,7 +564,11 @@ namespace OpenRCT2::Ui::Windows auto widgetDesc = info.GetCustomWidgetDesc(w, widgetIndex); if (widgetDesc != nullptr) { - if (widgetDesc->Type == "dropdown") + if (widgetDesc->Type == "colourpicker") + { + UpdateWidgetColour(w, widgetIndex, dropdownIndex); + } + else if (widgetDesc->Type == "dropdown") { UpdateWidgetSelectedIndex(w, widgetIndex - 1, dropdownIndex); } @@ -846,6 +864,12 @@ namespace OpenRCT2::Ui::Windows } widgetList.push_back(widget); } + else if (desc.Type == "colourpicker") + { + widget.type = WindowWidgetType::ColourBtn; + widget.image = GetColourButtonImage(desc.Colour); + widgetList.push_back(widget); + } else if (desc.Type == "dropdown") { widget.type = WindowWidgetType::DropdownMenu; @@ -1102,6 +1126,33 @@ namespace OpenRCT2::Ui::Windows } } + void UpdateWidgetColour(rct_window* w, rct_widgetindex widgetIndex, colour_t colour) + { + if (w->custom_info != nullptr) + { + auto& customInfo = GetInfo(w); + auto customWidgetInfo = customInfo.GetCustomWidgetDesc(w, widgetIndex); + if (customWidgetInfo != nullptr) + { + auto& widget = w->widgets[widgetIndex]; + + auto lastColour = customWidgetInfo->Colour; + if (lastColour != colour && colour < COLOUR_COUNT) + { + customWidgetInfo->Colour = colour; + widget.image = GetColourButtonImage(colour); + widget_invalidate(w, widgetIndex); + + std::vector args; + auto ctx = customWidgetInfo->OnChange.context(); + duk_push_int(ctx, colour); + args.push_back(DukValue::take_from_stack(ctx)); + InvokeEventHandler(customInfo.Owner, customWidgetInfo->OnChange, args); + } + } + } + } + void UpdateWidgetSelectedIndex(rct_window* w, rct_widgetindex widgetIndex, int32_t selectedIndex) { if (w->custom_info != nullptr) @@ -1163,6 +1214,20 @@ namespace OpenRCT2::Ui::Windows return {}; } + colour_t GetWidgetColour(rct_window* w, rct_widgetindex widgetIndex) + { + if (w->custom_info != nullptr) + { + auto& customInfo = GetInfo(w); + auto customWidgetInfo = customInfo.GetCustomWidgetDesc(w, widgetIndex); + if (customWidgetInfo != nullptr) + { + return customWidgetInfo->Colour; + } + } + return COLOUR_BLACK; + } + int32_t GetWidgetSelectedIndex(rct_window* w, rct_widgetindex widgetIndex) { if (w->custom_info != nullptr) diff --git a/src/openrct2-ui/scripting/CustomWindow.h b/src/openrct2-ui/scripting/CustomWindow.h index faa8974704..2c9c975c6f 100644 --- a/src/openrct2-ui/scripting/CustomWindow.h +++ b/src/openrct2-ui/scripting/CustomWindow.h @@ -24,8 +24,10 @@ namespace OpenRCT2::Ui::Windows void UpdateWindowTitle(rct_window* w, const std::string_view& value); void UpdateWidgetText(rct_window* w, rct_widgetindex widget, const std::string_view& string_view); void UpdateWidgetItems(rct_window* w, rct_widgetindex widgetIndex, const std::vector& items); + void UpdateWidgetColour(rct_window* w, rct_widgetindex widgetIndex, colour_t colour); void UpdateWidgetSelectedIndex(rct_window* w, rct_widgetindex widgetIndex, int32_t selectedIndex); std::vector GetWidgetItems(rct_window* w, rct_widgetindex widgetIndex); + colour_t GetWidgetColour(rct_window* w, rct_widgetindex widgetIndex); int32_t GetWidgetSelectedIndex(rct_window* w, rct_widgetindex widgetIndex); rct_window* FindCustomWindowByClassification(const std::string_view& classification); std::optional FindWidgetIndexByName(rct_window* w, const std::string_view& name); diff --git a/src/openrct2-ui/scripting/ScWidget.hpp b/src/openrct2-ui/scripting/ScWidget.hpp index c151f6798e..c06ff93695 100644 --- a/src/openrct2-ui/scripting/ScWidget.hpp +++ b/src/openrct2-ui/scripting/ScWidget.hpp @@ -74,12 +74,13 @@ namespace OpenRCT2::Scripting case WindowWidgetType::Resize: return "resize"; case WindowWidgetType::ImgBtn: - case WindowWidgetType::ColourBtn: case WindowWidgetType::TrnBtn: case WindowWidgetType::FlatBtn: case WindowWidgetType::Button: case WindowWidgetType::CloseBox: return "button"; + case WindowWidgetType::ColourBtn: + return "colourpicker"; case WindowWidgetType::Tab: return "tab"; case WindowWidgetType::LabelCentred: @@ -517,6 +518,41 @@ namespace OpenRCT2::Scripting } }; + class ScColourPickerWidget : public ScWidget + { + public: + ScColourPickerWidget(rct_windowclass c, rct_windownumber n, rct_widgetindex widgetIndex) + : ScWidget(c, n, widgetIndex) + { + } + + static void Register(duk_context* ctx) + { + dukglue_set_base_class(ctx); + dukglue_register_property(ctx, &ScColourPickerWidget::colour_get, &ScColourPickerWidget::colour_set, "colour"); + } + + private: + colour_t colour_get() const + { + auto w = GetWindow(); + if (w != nullptr) + { + return GetWidgetColour(w, _widgetIndex); + } + return COLOUR_BLACK; + } + void colour_set(colour_t value) + { + auto w = GetWindow(); + if (w != nullptr) + { + UpdateWidgetColour(w, _widgetIndex, value); + Invalidate(); + } + } + }; + class ScDropdownWidget : public ScWidget { public: @@ -776,6 +812,8 @@ namespace OpenRCT2::Scripting return GetObjectAsDukValue(ctx, std::make_shared(c, n, widgetIndex)); case WindowWidgetType::Checkbox: return GetObjectAsDukValue(ctx, std::make_shared(c, n, widgetIndex)); + case WindowWidgetType::ColourBtn: + return GetObjectAsDukValue(ctx, std::make_shared(c, n, widgetIndex)); case WindowWidgetType::DropdownMenu: return GetObjectAsDukValue(ctx, std::make_shared(c, n, widgetIndex)); case WindowWidgetType::Scroll: diff --git a/src/openrct2-ui/scripting/UiExtensions.cpp b/src/openrct2-ui/scripting/UiExtensions.cpp index fed8810bc7..3cf4404550 100644 --- a/src/openrct2-ui/scripting/UiExtensions.cpp +++ b/src/openrct2-ui/scripting/UiExtensions.cpp @@ -33,6 +33,7 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine) ScViewport::Register(ctx); ScWidget::Register(ctx); ScButtonWidget::Register(ctx); + ScColourPickerWidget::Register(ctx); ScCheckBoxWidget::Register(ctx); ScDropdownWidget::Register(ctx); ScListViewWidget::Register(ctx);