OpenRCT2/src/openrct2-ui/scripting/ScImageManager.hpp

157 lines
5.4 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2024 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 "CustomImages.h"
# include <openrct2/Context.h>
# include <openrct2/drawing/Image.h>
# include <openrct2/scripting/Duktape.hpp>
# include <openrct2/sprites.h>
namespace OpenRCT2::Scripting
{
class ScImageManager
{
private:
duk_context* _ctx{};
public:
ScImageManager(duk_context* ctx)
: _ctx(ctx)
{
}
static void Register(duk_context* ctx)
{
dukglue_register_method(ctx, &ScImageManager::getPredefinedRange, "getPredefinedRange");
dukglue_register_method(ctx, &ScImageManager::getAvailableAllocationRanges, "getAvailableAllocationRanges");
dukglue_register_method(ctx, &ScImageManager::allocate, "allocate");
dukglue_register_method(ctx, &ScImageManager::free, "free");
dukglue_register_method(ctx, &ScImageManager::getImageInfo, "getImageInfo");
dukglue_register_method(ctx, &ScImageManager::getPixelData, "getPixelData");
dukglue_register_method(ctx, &ScImageManager::setPixelData, "setPixelData");
dukglue_register_method(ctx, &ScImageManager::draw, "draw");
}
private:
DukValue getPredefinedRange(const std::string& name) const
{
if (name == "g1")
{
return CreateImageIndexRange(0, SPR_G1_END);
}
else if (name == "g2")
{
return CreateImageIndexRange(SPR_G2_BEGIN, SPR_G2_END - SPR_G2_BEGIN);
}
else if (name == "csg")
{
return CreateImageIndexRange(SPR_CSG_BEGIN, SPR_CSG_END - SPR_CSG_BEGIN);
}
else if (name == "allocated")
{
return CreateImageIndexRange(SPR_IMAGE_LIST_BEGIN, SPR_IMAGE_LIST_END - SPR_IMAGE_LIST_BEGIN);
}
else
{
return ToDuk(_ctx, nullptr);
}
}
DukValue getAvailableAllocationRanges() const
{
auto ranges = GetAvailableAllocationRanges();
duk_push_array(_ctx);
duk_uarridx_t index = 0;
for (const auto& range : ranges)
{
auto value = CreateImageIndexRange(range.BaseId, range.Count);
value.push();
duk_put_prop_index(_ctx, /* duk stack index */ -2, index);
index++;
}
return DukValue::take_from_stack(_ctx);
}
DukValue allocate(int32_t count)
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
auto range = AllocateCustomImages(plugin, count);
return range ? CreateImageIndexRange(range->BaseId, range->Count) : ToDuk(_ctx, undefined);
}
void free(const DukValue& dukRange)
{
auto start = dukRange["start"].as_int();
auto count = dukRange["count"].as_int();
ImageList range(start, count);
auto& scriptEngine = GetContext()->GetScriptEngine();
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
if (!FreeCustomImages(plugin, range))
{
duk_error(_ctx, DUK_ERR_ERROR, "This plugin did not allocate the specified image range.");
}
}
DukValue getImageInfo(int32_t id)
{
return DukGetImageInfo(_ctx, id);
}
DukValue getPixelData(int32_t id)
{
return DukGetImagePixelData(_ctx, id);
}
void setPixelData(int32_t id, const DukValue& pixelData)
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
if (!DoesPluginOwnImage(plugin, id))
{
duk_error(_ctx, DUK_ERR_ERROR, "This plugin did not allocate the specified image.");
}
DukSetPixelData(_ctx, id, pixelData);
}
void draw(int32_t id, const DukValue& dukSize, const DukValue& callback)
{
auto width = dukSize["width"].as_int();
auto height = dukSize["height"].as_int();
auto& scriptEngine = GetContext()->GetScriptEngine();
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
if (!DoesPluginOwnImage(plugin, id))
{
duk_error(_ctx, DUK_ERR_ERROR, "This plugin did not allocate the specified image.");
}
DukDrawCustomImage(scriptEngine, id, { width, height }, callback);
}
DukValue CreateImageIndexRange(size_t start, size_t count) const
{
DukObject obj(_ctx);
obj.Set("start", static_cast<uint32_t>(start));
obj.Set("count", static_cast<uint32_t>(count));
return obj.Take();
}
};
} // namespace OpenRCT2::Scripting
#endif