diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 05e0c936ad..3a83276a6d 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -762,8 +762,7 @@ declare global { */ interface ToolDesc { id: string; - type: ToolType; - cursor: CursorType; + cursor?: CursorType; onStart: () => void; onDown: (e: ToolEventArgs) => void; @@ -774,32 +773,32 @@ declare global { type CursorType = "arrow" | - "blank" | - "up_arrow" | - "up_down_arrow" | - "hand_point" | - "zzz" | - "diagonal_arrows" | - "picker" | - "tree_down" | - "fountain_down" | - "statue_down" | "bench_down" | - "cross_hair" | "bin_down" | - "lamppost_down" | + "blank" | + "cross_hair" | + "diagonal_arrows" | + "dig_down" | + "entrance_down" | "fence_down" | "flower_down" | - "path_down" | - "dig_down" | - "water_down" | + "fountain_down" | + "hand_closed" | + "hand_open" | + "hand_point" | "house_down" | + "lamppost_down" | + "paint_down" | + "path_down" | + "picker" | + "statue_down" | + "tree_down" | + "up_arrow" | + "up_down_arrow" | "volcano_down" | "walk_down" | - "paint_down" | - "entrance_down" | - "hand_open" | - "hand_closed"; + "water_down" | + "zzz"; /** * Represents the type of a widget, e.g. button or label. diff --git a/src/openrct2-ui/scripting/CustomMenu.cpp b/src/openrct2-ui/scripting/CustomMenu.cpp index 37a0322357..34333ad903 100644 --- a/src/openrct2-ui/scripting/CustomMenu.cpp +++ b/src/openrct2-ui/scripting/CustomMenu.cpp @@ -20,6 +20,53 @@ namespace OpenRCT2::Scripting std::optional ActiveCustomTool; std::vector CustomMenuItems; + static constexpr std::array CursorNames = { + "arrow", "blank", "up_arrow", "up_down_arrow", "hand_point", "zzz", "diagonal_arrows", + "picker", "tree_down", "fountain_down", "statue_down", "bench_down", "cross_hair", "bin_down", + "lamppost_down", "fence_down", "flower_down", "path_down", "dig_down", "water_down", "house_down", + "volcano_down", "walk_down", "paint_down", "entrance_down", "hand_open", "hand_closed", + }; + + template<> DukValue ToDuk(duk_context* ctx, const CURSOR_ID& value) + { + if (value >= 0 && static_cast(value) < std::size(CursorNames)) + { + auto str = CursorNames[value]; + duk_push_lstring(ctx, str.data(), str.size()); + DukValue::take_from_stack(ctx); + } + return {}; + } + + template<> CURSOR_ID FromDuk(const DukValue& s) + { + if (s.type() == DukValue::Type::STRING) + { + auto it = std::find(std::begin(CursorNames), std::end(CursorNames), s.as_c_string()); + if (it != std::end(CursorNames)) + { + return static_cast(std::distance(std::begin(CursorNames), it)); + } + } + return CURSOR_UNDEFINED; + } + + template<> DukValue ToDuk(duk_context* ctx, const CoordsXY& coords) + { + DukObject dukCoords(ctx); + dukCoords.Set("x", coords.x); + dukCoords.Set("y", coords.y); + return dukCoords.Take(); + } + + template<> DukValue ToDuk(duk_context* ctx, const ScreenCoordsXY& coords) + { + DukObject dukCoords(ctx); + dukCoords.Set("x", coords.x); + dukCoords.Set("y", coords.y); + return dukCoords.Take(); + } + static void RemoveMenuItemsAndTool(std::shared_ptr owner) { if (ActiveCustomTool) @@ -83,22 +130,6 @@ namespace OpenRCT2::Scripting scriptEngine.ExecutePluginCall(Owner, onFinish, {}, false); } - static DukValue CoordsXYToDuk(duk_context* ctx, const CoordsXY& coords) - { - DukObject dukCoords(ctx); - dukCoords.Set("x", coords.x); - dukCoords.Set("y", coords.y); - return dukCoords.Take(); - } - - static DukValue CoordsXYToDuk(duk_context* ctx, const ScreenCoordsXY& coords) - { - DukObject dukCoords(ctx); - dukCoords.Set("x", coords.x); - dukCoords.Set("y", coords.y); - return dukCoords.Take(); - } - void CustomTool::InvokeEventHandler(const DukValue& dukHandler, const ScreenCoordsXY& screenCoords) { if (dukHandler.is_function()) @@ -113,8 +144,8 @@ namespace OpenRCT2::Scripting DukObject obj(dukHandler.context()); obj.Set("isDown", MouseDown); - obj.Set("screenCoords", CoordsXYToDuk(ctx, screenCoords)); - obj.Set("mapCoords", CoordsXYToDuk(ctx, mapCoords)); + obj.Set("screenCoords", ToDuk(ctx, screenCoords)); + obj.Set("mapCoords", ToDuk(ctx, mapCoords)); if (interactionType == VIEWPORT_INTERACTION_ITEM_SPRITE && tileElement != nullptr) { @@ -157,7 +188,11 @@ namespace OpenRCT2::Scripting CustomTool customTool; customTool.Owner = scriptEngine.GetExecInfo().GetCurrentPlugin(); customTool.Id = dukValue["id"].as_string(); - customTool.Cursor = StringToCursor(dukValue["cursor"].as_string()); + customTool.Cursor = FromDuk(dukValue["cursor"]); + if (customTool.Cursor == CURSOR_UNDEFINED) + { + customTool.Cursor = CURSOR_ARROW; + } customTool.onStart = dukValue["onStart"]; customTool.onDown = dukValue["onDown"]; customTool.onMove = dukValue["onMove"]; @@ -183,32 +218,6 @@ namespace OpenRCT2::Scripting } } - static constexpr const char* CursorNames[] = { - "arrow", "blank", "up_arrow", "up_down_arrow", "hand_point", "zzz", "diagonal_arrows", - "picker", "tree_down", "fountain_down", "statue_down", "bench_down", "cross_hair", "bin_down", - "lamppost_down", "fence_down", "flower_down", "path_down", "dig_down", "water_down", "house_down", - "volcano_down", "walk_down", "paint_down", "entrance_down", "hand_open", "hand_closed", - }; - - std::string CursorToString(int32_t cursor) - { - if (cursor >= 0 && static_cast(cursor) < std::size(CursorNames)) - { - return CursorNames[cursor]; - } - return {}; - } - - CURSOR_ID StringToCursor(const std::string_view& cursor) - { - auto it = std::find(std::begin(CursorNames), std::end(CursorNames), cursor); - if (it != std::end(CursorNames)) - { - return static_cast(std::distance(std::begin(CursorNames), it)); - } - return CURSOR_UNDEFINED; - } - } // namespace OpenRCT2::Scripting #endif diff --git a/src/openrct2-ui/scripting/CustomMenu.h b/src/openrct2-ui/scripting/CustomMenu.h index 71f4894d64..743fa111f0 100644 --- a/src/openrct2-ui/scripting/CustomMenu.h +++ b/src/openrct2-ui/scripting/CustomMenu.h @@ -72,8 +72,9 @@ namespace OpenRCT2::Scripting void InitialiseCustomMenuItems(ScriptEngine& scriptEngine); void InitialiseCustomTool(ScriptEngine& scriptEngine, const DukValue& dukValue); - std::string CursorToString(int32_t cursor); - CURSOR_ID StringToCursor(const std::string_view& cursor); + + template<> DukValue ToDuk(duk_context* ctx, const CURSOR_ID& value); + template<> CURSOR_ID FromDuk(const DukValue& s); } // namespace OpenRCT2::Scripting diff --git a/src/openrct2-ui/scripting/ScTileSelection.hpp b/src/openrct2-ui/scripting/ScTileSelection.hpp index 4f982cac55..850d180378 100644 --- a/src/openrct2-ui/scripting/ScTileSelection.hpp +++ b/src/openrct2-ui/scripting/ScTileSelection.hpp @@ -148,10 +148,7 @@ namespace OpenRCT2::Scripting auto dukY = dukCoords["y"]; if (dukY.type() == DukValue::Type::NUMBER) { - CoordsXY coords; - coords.x = dukX.as_int(); - coords.y = dukY.as_int(); - result = coords; + result = { dukX.as_int(), dukY.as_int() }; } } } diff --git a/src/openrct2-ui/scripting/ScUi.hpp b/src/openrct2-ui/scripting/ScUi.hpp index cf6020a59c..b4e527a738 100644 --- a/src/openrct2-ui/scripting/ScUi.hpp +++ b/src/openrct2-ui/scripting/ScUi.hpp @@ -39,7 +39,15 @@ namespace OpenRCT2::Scripting { class ScTool { + private: + duk_context* _ctx{}; + public: + ScTool(duk_context* ctx) + : _ctx(ctx) + { + } + static void Register(duk_context* ctx) { dukglue_register_property(ctx, &ScTool::id_get, nullptr, "id"); @@ -53,9 +61,9 @@ namespace OpenRCT2::Scripting return ActiveCustomTool ? ActiveCustomTool->Id : ""; } - std::string cursor_get() const + DukValue cursor_get() const { - return CursorToString(gCurrentToolId); + return ToDuk(_ctx, static_cast(gCurrentToolId)); } void cancel() @@ -103,7 +111,7 @@ namespace OpenRCT2::Scripting { if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) { - return std::make_shared(); + return std::make_shared(_scriptEngine.GetContext()); } return {}; } diff --git a/src/openrct2/scripting/Duktape.hpp b/src/openrct2/scripting/Duktape.hpp index 71ac11ab14..fe47adf8d1 100644 --- a/src/openrct2/scripting/Duktape.hpp +++ b/src/openrct2/scripting/Duktape.hpp @@ -189,6 +189,10 @@ namespace OpenRCT2::Scripting return std::nullopt; } } + + template DukValue ToDuk(duk_context* ctx, const T& value) = delete; + template T FromDuk(const DukValue& s) = delete; + } // namespace OpenRCT2::Scripting #endif