mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-19 04:53:12 +01:00
Implement tile selection API
This commit is contained in:
94
distribution/openrct2.d.ts
vendored
94
distribution/openrct2.d.ts
vendored
@@ -71,6 +71,14 @@ declare global {
|
||||
z: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A rectangular area specified using two coordinates.
|
||||
*/
|
||||
interface MapRange {
|
||||
leftTop: Coord2;
|
||||
rightBottom: Coord2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents information about the plugin such as type, name, author and version.
|
||||
* It also includes the entry point.
|
||||
@@ -710,6 +718,7 @@ declare global {
|
||||
readonly height: number;
|
||||
readonly windows: number;
|
||||
readonly mainViewport: Viewport;
|
||||
readonly tileSelection: TileSelection;
|
||||
|
||||
getWindow(id: number): Window;
|
||||
getWindow(classification: string): Window;
|
||||
@@ -717,9 +726,94 @@ declare global {
|
||||
closeWindows(classification: string, id?: number): void;
|
||||
closeAllWindows(): void;
|
||||
|
||||
/**
|
||||
* Begins a new tool session. The cursor will change to the style specified by the
|
||||
* given tool descriptor and cursor events will be provided.
|
||||
* @param tool The properties and event handlers for the tool.
|
||||
*/
|
||||
activateTool(tool: ToolDesc): void;
|
||||
|
||||
registerMenuItem(text: string, callback: () => void): void;
|
||||
}
|
||||
|
||||
interface TileSelection {
|
||||
range: MapRange;
|
||||
tiles: Coord2[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of tool.
|
||||
* Raw will provide only the screen coordinates of where the cursor is.
|
||||
* Tile will provide a coordinates of the tile the cursor is over.
|
||||
* Interact will provide information about the ride or entity the cursor is over.
|
||||
*/
|
||||
type ToolType = "raw" | "tile" | "interact";
|
||||
|
||||
type InteractionType =
|
||||
"none" |
|
||||
"surface" |
|
||||
"sprite" |
|
||||
"ride" |
|
||||
"water" |
|
||||
"scenery" |
|
||||
"footpath" |
|
||||
"footpath_addition" |
|
||||
"park" |
|
||||
"wall" |
|
||||
"large_scenery" |
|
||||
"label" |
|
||||
"banner";
|
||||
|
||||
interface ToolEventArgs {
|
||||
kind: InteractionType;
|
||||
screenCoords: Coord2;
|
||||
mapCoords?: Coord3;
|
||||
tileElementIndex?: number;
|
||||
entity?: Entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the properties and event handlers for a custom tool.
|
||||
*/
|
||||
interface ToolDesc {
|
||||
type: ToolType;
|
||||
cursor: CursorType;
|
||||
|
||||
onDown: (e: ToolEventArgs) => void;
|
||||
onMove: (e: ToolEventArgs) => void;
|
||||
onUp: (e: ToolEventArgs) => void;
|
||||
onFinish: () => void;
|
||||
}
|
||||
|
||||
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" |
|
||||
"fence_down" |
|
||||
"flower_down" |
|
||||
"path_down" |
|
||||
"dig_down" |
|
||||
"water_down" |
|
||||
"house_down" |
|
||||
"volcano_down" |
|
||||
"walk_down" |
|
||||
"paint_down" |
|
||||
"entrance_down" |
|
||||
"hand_open" |
|
||||
"hand_closed";
|
||||
|
||||
/**
|
||||
* Represents the type of a widget, e.g. button or label.
|
||||
*/
|
||||
|
||||
179
src/openrct2-ui/scripting/ScTileSelection.hpp
Normal file
179
src/openrct2-ui/scripting/ScTileSelection.hpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/*****************************************************************************
|
||||
* 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 <openrct2/common.h>
|
||||
# include <openrct2/scripting/Duktape.hpp>
|
||||
# include <openrct2/world/Map.h>
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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<CoordsXY> GetCoordsXY(const DukValue& dukCoords)
|
||||
{
|
||||
std::optional<CoordsXY> 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)
|
||||
{
|
||||
CoordsXY coords;
|
||||
coords.x = dukX.as_int();
|
||||
coords.y = dukY.as_int();
|
||||
result = coords;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::optional<MapRange> GetMapRange(const DukValue& dukMapRange)
|
||||
{
|
||||
std::optional<MapRange> 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
|
||||
@@ -12,6 +12,7 @@
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
# include "CustomMenu.h"
|
||||
# include "ScTileSelection.hpp"
|
||||
# include "ScViewport.hpp"
|
||||
# include "ScWindow.hpp"
|
||||
|
||||
@@ -64,6 +65,11 @@ namespace OpenRCT2::Scripting
|
||||
return std::make_shared<ScViewport>(WC_MAIN_WINDOW);
|
||||
}
|
||||
|
||||
std::shared_ptr<ScTileSelection> tileSelection_get() const
|
||||
{
|
||||
return std::make_shared<ScTileSelection>(_scriptEngine.GetContext());
|
||||
}
|
||||
|
||||
std::shared_ptr<ScWindow> openWindow(DukValue desc)
|
||||
{
|
||||
using namespace OpenRCT2::Ui::Windows;
|
||||
@@ -142,6 +148,7 @@ namespace OpenRCT2::Scripting
|
||||
dukglue_register_property(ctx, &ScUi::width_get, nullptr, "width");
|
||||
dukglue_register_property(ctx, &ScUi::windows_get, nullptr, "windows");
|
||||
dukglue_register_property(ctx, &ScUi::mainViewport_get, nullptr, "mainViewport");
|
||||
dukglue_register_property(ctx, &ScUi::tileSelection_get, nullptr, "tileSelection");
|
||||
dukglue_register_method(ctx, &ScUi::openWindow, "openWindow");
|
||||
dukglue_register_method(ctx, &ScUi::closeWindows, "closeWindows");
|
||||
dukglue_register_method(ctx, &ScUi::closeAllWindows, "closeAllWindows");
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# include "UiExtensions.h"
|
||||
|
||||
# include "CustomMenu.h"
|
||||
# include "ScTileSelection.hpp"
|
||||
# include "ScUi.hpp"
|
||||
# include "ScWidget.hpp"
|
||||
# include "ScWindow.hpp"
|
||||
@@ -26,6 +27,7 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine)
|
||||
|
||||
dukglue_register_global(ctx, std::make_shared<ScUi>(scriptEngine), "ui");
|
||||
|
||||
ScTileSelection::Register(ctx);
|
||||
ScUi::Register(ctx);
|
||||
ScViewport::Register(ctx);
|
||||
ScWidget::Register(ctx);
|
||||
|
||||
Reference in New Issue
Block a user