mirror of https://github.com/OpenRCT2/OpenRCT2.git
308 lines
9.3 KiB
C++
308 lines
9.3 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2018 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 "../interface/Window.h"
|
|
|
|
# include <memory>
|
|
# include <openrct2/Context.h>
|
|
# include <openrct2/common.h>
|
|
# include <openrct2/interface/Viewport.h>
|
|
# include <openrct2/scripting/Duktape.hpp>
|
|
# include <openrct2/scripting/ScriptEngine.h>
|
|
# include <openrct2/world/Map.h>
|
|
|
|
namespace OpenRCT2::Scripting
|
|
{
|
|
class ScViewport
|
|
{
|
|
private:
|
|
rct_windowclass _class{};
|
|
rct_windownumber _number{};
|
|
|
|
public:
|
|
ScViewport(rct_windowclass c, rct_windownumber n = 0)
|
|
: _class(c)
|
|
, _number(n)
|
|
{
|
|
}
|
|
|
|
private:
|
|
int32_t left_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->view_x;
|
|
}
|
|
return 0;
|
|
}
|
|
void left_set(int32_t value)
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
SetViewLeftTop(value, viewport->view_y);
|
|
}
|
|
}
|
|
|
|
int32_t top_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->view_y;
|
|
}
|
|
return 0;
|
|
}
|
|
void top_set(int32_t value)
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
SetViewLeftTop(viewport->view_x, value);
|
|
}
|
|
}
|
|
|
|
int32_t right_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->view_x + viewport->view_width;
|
|
}
|
|
return 0;
|
|
}
|
|
void right_set(int32_t value)
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
SetViewLeftTop(value - viewport->view_width, viewport->view_y);
|
|
}
|
|
}
|
|
|
|
int32_t bottom_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->view_y + viewport->view_height;
|
|
}
|
|
return 0;
|
|
}
|
|
void bottom_set(int32_t value)
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
SetViewLeftTop(viewport->view_x, value - viewport->view_height);
|
|
}
|
|
}
|
|
|
|
int32_t rotation_get()
|
|
{
|
|
return get_current_rotation();
|
|
}
|
|
void rotation_set(int32_t value)
|
|
{
|
|
if (value >= 0 && value < 4)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
while (get_current_rotation() != value)
|
|
{
|
|
window_rotate_camera(w, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t zoom_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->zoom;
|
|
}
|
|
return 0;
|
|
}
|
|
void zoom_set(int32_t value)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
window_zoom_set(w, value, false);
|
|
}
|
|
}
|
|
|
|
uint32_t visibilityFlags_get()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
return viewport->flags;
|
|
}
|
|
return 0;
|
|
}
|
|
void visibilityFlags_set(uint32_t value)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
auto viewport = w->viewport;
|
|
if (viewport != nullptr)
|
|
{
|
|
if (viewport->flags != value)
|
|
{
|
|
viewport->flags = value;
|
|
w->Invalidate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DukValue getCentrePosition()
|
|
{
|
|
auto viewport = GetViewport();
|
|
if (viewport != nullptr)
|
|
{
|
|
auto centreX = viewport->view_x + (viewport->view_width / 2);
|
|
auto centreY = viewport->view_y + (viewport->view_height / 2);
|
|
auto coords = viewport_coord_to_map_coord(centreX, centreY, 24);
|
|
|
|
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
|
auto obj = duk_push_object(ctx);
|
|
duk_push_number(ctx, coords.x);
|
|
duk_put_prop_string(ctx, obj, "x");
|
|
duk_push_number(ctx, coords.y);
|
|
duk_put_prop_string(ctx, obj, "y");
|
|
return DukValue::take_from_stack(ctx);
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void moveTo(DukValue position)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
auto viewport = w->viewport;
|
|
if (viewport != nullptr)
|
|
{
|
|
auto coords = GetCoordsFromObject(position);
|
|
if (coords)
|
|
{
|
|
auto screenCoords = translate_3d_to_2d_with_z(get_current_rotation(), *coords);
|
|
auto left = screenCoords.x - (viewport->view_width / 2);
|
|
auto top = screenCoords.y - (viewport->view_height / 2);
|
|
SetViewLeftTop(left, top);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void scrollTo(DukValue position)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
auto coords = GetCoordsFromObject(position);
|
|
if (coords)
|
|
{
|
|
window_scroll_to_location(w, coords->x, coords->y, coords->z);
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
static void Register(duk_context* ctx)
|
|
{
|
|
dukglue_register_property(ctx, &ScViewport::left_get, &ScViewport::left_set, "left");
|
|
dukglue_register_property(ctx, &ScViewport::top_get, &ScViewport::top_set, "top");
|
|
dukglue_register_property(ctx, &ScViewport::right_get, &ScViewport::right_set, "right");
|
|
dukglue_register_property(ctx, &ScViewport::bottom_get, &ScViewport::bottom_set, "bottom");
|
|
dukglue_register_property(ctx, &ScViewport::rotation_get, &ScViewport::rotation_set, "rotation");
|
|
dukglue_register_property(ctx, &ScViewport::zoom_get, &ScViewport::zoom_set, "zoom");
|
|
dukglue_register_property(
|
|
ctx, &ScViewport::visibilityFlags_get, &ScViewport::visibilityFlags_set, "visibilityFlags");
|
|
dukglue_register_method(ctx, &ScViewport::getCentrePosition, "getCentrePosition");
|
|
dukglue_register_method(ctx, &ScViewport::moveTo, "moveTo");
|
|
dukglue_register_method(ctx, &ScViewport::scrollTo, "scrollTo");
|
|
}
|
|
|
|
private:
|
|
rct_window* GetWindow()
|
|
{
|
|
if (_class == WC_MAIN_WINDOW)
|
|
return window_get_main();
|
|
else
|
|
return window_find_by_number(_class, _number);
|
|
}
|
|
|
|
rct_viewport* GetViewport()
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
return w->viewport;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void SetViewLeftTop(int32_t left, int32_t top)
|
|
{
|
|
auto w = GetWindow();
|
|
if (w != nullptr)
|
|
{
|
|
auto viewport = w->viewport;
|
|
if (viewport != nullptr)
|
|
{
|
|
viewport->view_x = left;
|
|
viewport->view_y = top;
|
|
viewport->flags &= ~WF_SCROLLING_TO_LOCATION;
|
|
w->saved_view_x = viewport->view_x;
|
|
w->saved_view_y = viewport->view_y;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::optional<CoordsXYZ> GetCoordsFromObject(DukValue position)
|
|
{
|
|
if (position.type() == DukValue::Type::OBJECT)
|
|
{
|
|
auto dukX = position["x"];
|
|
auto dukY = position["y"];
|
|
auto dukZ = position["z"];
|
|
if (dukX.type() == DukValue::Type::NUMBER && dukY.type() == DukValue::Type::NUMBER)
|
|
{
|
|
auto x = dukX.as_int();
|
|
auto y = dukY.as_int();
|
|
if (dukZ.type() == DukValue::Type::NUMBER)
|
|
{
|
|
return CoordsXYZ(x, y, dukZ.as_int());
|
|
}
|
|
else
|
|
{
|
|
auto z = tile_element_height(CoordsXY(x, y));
|
|
return CoordsXYZ(x, y, z);
|
|
}
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
};
|
|
} // namespace OpenRCT2::Scripting
|
|
|
|
#endif
|