mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-02-02 19:56:13 +01:00
Implement plugin ownership of images
This commit is contained in:
@@ -11,7 +11,11 @@
|
||||
|
||||
# include "CustomImages.h"
|
||||
|
||||
# include <openrct2/Context.h>
|
||||
# include <openrct2/drawing/Image.h>
|
||||
# include <openrct2/drawing/ImageImporter.h>
|
||||
# include <openrct2/scripting/Plugin.h>
|
||||
|
||||
using namespace OpenRCT2::Drawing;
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
@@ -43,6 +47,97 @@ namespace OpenRCT2::Scripting
|
||||
DukValue Data;
|
||||
};
|
||||
|
||||
struct AllocatedImageList
|
||||
{
|
||||
std::shared_ptr<Plugin> Owner;
|
||||
ImageList Range;
|
||||
};
|
||||
|
||||
static std::vector<AllocatedImageList> _allocatedImages;
|
||||
|
||||
static void FreeImages(ImageList range)
|
||||
{
|
||||
for (ImageIndex i = 0; i < range.Count; i++)
|
||||
{
|
||||
auto index = range.BaseId + i;
|
||||
auto g1 = gfx_get_g1_element(index);
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
// Free pixel data
|
||||
delete[] g1->offset;
|
||||
|
||||
// Replace slot with empty element
|
||||
rct_g1_element empty{};
|
||||
gfx_set_g1_element(index, &empty);
|
||||
}
|
||||
}
|
||||
gfx_object_free_images(range.BaseId, range.Count);
|
||||
}
|
||||
|
||||
std::optional<ImageList> AllocateCustomImages(const std::shared_ptr<Plugin>& plugin, uint32_t count)
|
||||
{
|
||||
std::vector<rct_g1_element> images;
|
||||
images.resize(count);
|
||||
|
||||
auto base = gfx_object_allocate_images(images.data(), count);
|
||||
if (base == ImageIndexUndefined)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
auto range = ImageList(base, count);
|
||||
|
||||
AllocatedImageList item;
|
||||
item.Owner = plugin;
|
||||
item.Range = range;
|
||||
_allocatedImages.push_back(std::move(item));
|
||||
return range;
|
||||
}
|
||||
|
||||
bool FreeCustomImages(const std::shared_ptr<Plugin>& plugin, ImageList range)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
_allocatedImages.begin(), _allocatedImages.end(),
|
||||
[&plugin, range](const AllocatedImageList& item) { return item.Owner == plugin && item.Range == range; });
|
||||
if (it == _allocatedImages.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeImages(it->Range);
|
||||
_allocatedImages.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DoesPluginOwnImage(const std::shared_ptr<Plugin>& plugin, ImageIndex index)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
_allocatedImages.begin(), _allocatedImages.end(),
|
||||
[&plugin, index](const AllocatedImageList& item) { return item.Owner == plugin && item.Range.Contains(index); });
|
||||
return it != _allocatedImages.end();
|
||||
}
|
||||
|
||||
static void FreeCustomImages(const std::shared_ptr<Plugin>& plugin)
|
||||
{
|
||||
auto it = _allocatedImages.begin();
|
||||
while (it != _allocatedImages.end())
|
||||
{
|
||||
if (it->Owner == plugin)
|
||||
{
|
||||
FreeImages(it->Range);
|
||||
it = _allocatedImages.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitialiseCustomImages(ScriptEngine& scriptEngine)
|
||||
{
|
||||
scriptEngine.SubscribeToPluginStoppedEvent([](std::shared_ptr<Plugin> plugin) -> void { FreeCustomImages(plugin); });
|
||||
}
|
||||
|
||||
DukValue DukGetImageInfo(duk_context* ctx, ImageIndex id)
|
||||
{
|
||||
auto* g1 = gfx_get_g1_element(id);
|
||||
|
||||
@@ -11,11 +11,17 @@
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
# include <openrct2/drawing/Image.h>
|
||||
# include <openrct2/drawing/ImageId.hpp>
|
||||
# include <openrct2/scripting/Duktape.hpp>
|
||||
# include <openrct2/scripting/ScriptEngine.h>
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
void InitialiseCustomImages(ScriptEngine& scriptEngine);
|
||||
std::optional<ImageList> AllocateCustomImages(const std::shared_ptr<Plugin>& plugin, uint32_t count);
|
||||
bool FreeCustomImages(const std::shared_ptr<Plugin>& plugin, ImageList range);
|
||||
bool DoesPluginOwnImage(const std::shared_ptr<Plugin>& plugin, ImageIndex index);
|
||||
DukValue DukGetImageInfo(duk_context* ctx, ImageIndex id);
|
||||
DukValue DukGetImagePixelData(duk_context* ctx, ImageIndex id);
|
||||
void DukSetPixelData(duk_context* ctx, ImageIndex id, const DukValue& dukPixelData);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
# include "CustomImages.h"
|
||||
|
||||
# include <openrct2/Context.h>
|
||||
# include <openrct2/drawing/Image.h>
|
||||
# include <openrct2/scripting/Duktape.hpp>
|
||||
# include <openrct2/sprites.h>
|
||||
@@ -83,22 +84,25 @@ namespace OpenRCT2::Scripting
|
||||
|
||||
DukValue allocate(int32_t count)
|
||||
{
|
||||
std::vector<rct_g1_element> images;
|
||||
images.resize(count);
|
||||
|
||||
auto base = gfx_object_allocate_images(images.data(), count);
|
||||
if (base == ImageIndexUndefined)
|
||||
{
|
||||
return ToDuk(_ctx, nullptr);
|
||||
}
|
||||
return CreateImageIndexRange(base, count);
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
|
||||
auto range = AllocateCustomImages(plugin, count);
|
||||
return range ? CreateImageIndexRange(range->BaseId, range->Count) : ToDuk(_ctx, nullptr);
|
||||
}
|
||||
|
||||
void free(const DukValue& range)
|
||||
void free(const DukValue& dukRange)
|
||||
{
|
||||
auto start = range["start"].as_int();
|
||||
auto count = range["count"].as_int();
|
||||
gfx_object_free_images(start, count);
|
||||
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)
|
||||
@@ -113,6 +117,13 @@ namespace OpenRCT2::Scripting
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
# include "UiExtensions.h"
|
||||
|
||||
# include "CustomImages.h"
|
||||
# include "CustomMenu.h"
|
||||
# include "ScGraphicsContext.hpp"
|
||||
# include "ScImageManager.hpp"
|
||||
@@ -55,6 +56,7 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine)
|
||||
ScTitleSequencePark::Register(ctx);
|
||||
ScWindow::Register(ctx);
|
||||
|
||||
InitialiseCustomImages(scriptEngine);
|
||||
InitialiseCustomMenuItems(scriptEngine);
|
||||
scriptEngine.SubscribeToPluginStoppedEvent(
|
||||
[](std::shared_ptr<Plugin> plugin) -> void { CloseWindowsOwnedByPlugin(plugin); });
|
||||
|
||||
@@ -12,15 +12,48 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <openrct2/drawing/ImageId.hpp>
|
||||
|
||||
struct rct_g1_element;
|
||||
|
||||
struct ImageList
|
||||
{
|
||||
uint32_t BaseId;
|
||||
uint32_t Count;
|
||||
ImageIndex BaseId{};
|
||||
ImageIndex Count{};
|
||||
|
||||
ImageList() = default;
|
||||
ImageList(ImageIndex baseId, ImageIndex count)
|
||||
: BaseId(baseId)
|
||||
, Count(count)
|
||||
{
|
||||
}
|
||||
|
||||
bool Contains(ImageIndex index) const
|
||||
{
|
||||
return index >= BaseId && index < GetEnd();
|
||||
}
|
||||
|
||||
ImageIndex GetEnd() const
|
||||
{
|
||||
return BaseId + Count;
|
||||
}
|
||||
|
||||
static ImageList FromBeginEnd(ImageIndex begin, ImageIndex end)
|
||||
{
|
||||
return ImageList(begin, end - begin);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator==(const ImageList& lhs, const ImageList& rhs)
|
||||
{
|
||||
return lhs.BaseId == rhs.BaseId && lhs.Count == rhs.Count;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const ImageList& lhs, const ImageList& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
uint32_t gfx_object_allocate_images(const rct_g1_element* images, uint32_t count);
|
||||
void gfx_object_free_images(uint32_t baseImageId, uint32_t count);
|
||||
void gfx_object_check_all_images_freed();
|
||||
|
||||
Reference in New Issue
Block a user