/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ #pragma once #ifdef ENABLE_SCRIPTING # include # include # include namespace OpenRCT2::Scripting { class ScTileSelection { private: duk_context* _ctx{}; public: ScTileSelection(duk_context* ctx) : _ctx(ctx) { } DukValue range_get() const { if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE) { DukObject range(_ctx); DukObject leftTop(_ctx); leftTop.Set("x", gMapSelectPositionA.x); leftTop.Set("y", gMapSelectPositionA.y); range.Set("leftTop", leftTop.Take()); DukObject rightBottom(_ctx); rightBottom.Set("x", gMapSelectPositionB.x); rightBottom.Set("y", gMapSelectPositionB.y); range.Set("rightBottom", rightBottom.Take()); return range.Take(); } else { duk_push_null(_ctx); return DukValue::take_from_stack(_ctx); } } void range_set(DukValue value) { map_invalidate_selection_rect(); if (value.type() == DukValue::Type::OBJECT) { auto range = GetMapRange(value); if (range) { gMapSelectPositionA.x = range->GetLeft(); gMapSelectPositionA.y = range->GetTop(); gMapSelectPositionB.x = range->GetRight(); gMapSelectPositionB.y = range->GetBottom(); gMapSelectType = MAP_SELECT_TYPE_FULL; gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; } } else { gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE; } map_invalidate_selection_rect(); } DukValue tiles_get() const { duk_push_array(_ctx); if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_CONSTRUCT) { duk_uarridx_t index = 0; for (const auto& tile : gMapSelectionTiles) { duk_push_object(_ctx); duk_push_int(_ctx, tile.x); duk_put_prop_string(_ctx, -2, "x"); duk_push_int(_ctx, tile.y); duk_put_prop_string(_ctx, -2, "y"); duk_put_prop_index(_ctx, -2, index); index++; } } return DukValue::take_from_stack(_ctx); } void tiles_set(DukValue value) { map_invalidate_map_selection_tiles(); gMapSelectionTiles.clear(); if (value.is_array()) { value.push(); auto arrayLen = duk_get_length(_ctx, -1); for (duk_uarridx_t i = 0; i < arrayLen; i++) { if (duk_get_prop_index(_ctx, -1, i)) { auto dukElement = DukValue::take_from_stack(_ctx); auto coords = GetCoordsXY(dukElement); if (coords) { gMapSelectionTiles.push_back(*coords); } } } duk_pop(_ctx); } if (gMapSelectionTiles.empty()) { gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT; gMapSelectFlags &= ~MAP_SELECT_FLAG_GREEN; } else { gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_CONSTRUCT; } map_invalidate_map_selection_tiles(); } static void Register(duk_context* ctx) { dukglue_register_property(ctx, &ScTileSelection::range_get, &ScTileSelection::range_set, "range"); dukglue_register_property(ctx, &ScTileSelection::tiles_get, &ScTileSelection::tiles_set, "tiles"); } private: static std::optional GetCoordsXY(const DukValue& dukCoords) { std::optional result; if (dukCoords.type() == DukValue::Type::OBJECT) { auto dukX = dukCoords["x"]; if (dukX.type() == DukValue::Type::NUMBER) { auto dukY = dukCoords["y"]; if (dukY.type() == DukValue::Type::NUMBER) { result = { dukX.as_int(), dukY.as_int() }; } } } return result; } static std::optional GetMapRange(const DukValue& dukMapRange) { std::optional result; if (dukMapRange.type() == DukValue::Type::OBJECT) { auto leftTop = GetCoordsXY(dukMapRange["leftTop"]); if (leftTop.has_value()) { auto rightBottom = GetCoordsXY(dukMapRange["rightBottom"]); if (rightBottom.has_value()) { result = MapRange(leftTop->x, leftTop->y, rightBottom->x, rightBottom->y); } } } return result; } }; } // namespace OpenRCT2::Scripting #endif