mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-22 06:23:04 +01:00
Add draw to image API
This commit is contained in:
9
distribution/openrct2.d.ts
vendored
9
distribution/openrct2.d.ts
vendored
@@ -2829,7 +2829,9 @@ declare global {
|
||||
setPixelData(id: number, data: PixelData): void;
|
||||
|
||||
/**
|
||||
* Gets a {@link GraphicsContext} for the given image so that you can draw directly to it.
|
||||
* Calls the given function with a {@link GraphicsContext} for the given image, allowing the
|
||||
* ability to draw directly to it.
|
||||
*
|
||||
* Allocates or reallocates the image if not previously allocated or if the size is changed.
|
||||
* The pixels of the image will persist between calls, so you can draw over the top of what
|
||||
* is currently there. The default pixel colour will be 0 (transparent).
|
||||
@@ -2838,10 +2840,11 @@ declare global {
|
||||
* can in images is a good way to improve performance.
|
||||
*
|
||||
* Will error if given an ID of an image not owned by this plugin.
|
||||
* @param id The id of the image to get a {@link GraphicsContext} for.
|
||||
* @param id The id of the image to draw to.
|
||||
* @param size The size the image that should be allocated.
|
||||
* @param callback The function that will draw to the image.
|
||||
*/
|
||||
getGraphicsContext(id: number, size: ScreenSize): GraphicsContext;
|
||||
draw(id: number, size: ScreenSize, callback: (g: GraphicsContext) => void): void;
|
||||
}
|
||||
|
||||
type PixelData = RawPixelData | RlePixelData | PngPixelData;
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
|
||||
# include "CustomImages.h"
|
||||
|
||||
# include "ScGraphicsContext.hpp"
|
||||
|
||||
# include <openrct2/Context.h>
|
||||
# include <openrct2/drawing/Image.h>
|
||||
# include <openrct2/drawing/ImageImporter.h>
|
||||
# include <openrct2/drawing/X8DrawingEngine.h>
|
||||
# include <openrct2/scripting/Plugin.h>
|
||||
|
||||
using namespace OpenRCT2::Drawing;
|
||||
@@ -393,6 +396,7 @@ namespace OpenRCT2::Scripting
|
||||
el.flags |= G1_FLAG_RLE_COMPRESSION;
|
||||
}
|
||||
gfx_set_g1_element(id, &el);
|
||||
drawing_engine_invalidate_image(id);
|
||||
}
|
||||
|
||||
void DukSetPixelData(duk_context* ctx, ImageIndex id, const DukValue& dukPixelData)
|
||||
@@ -409,6 +413,59 @@ namespace OpenRCT2::Scripting
|
||||
}
|
||||
}
|
||||
|
||||
void DukDrawCustomImage(ScriptEngine& scriptEngine, ImageIndex id, ScreenSize size, const DukValue& callback)
|
||||
{
|
||||
auto* ctx = scriptEngine.GetContext();
|
||||
auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
|
||||
|
||||
auto drawingEngine = std::make_unique<X8DrawingEngine>(GetContext()->GetUiContext());
|
||||
rct_drawpixelinfo dpi;
|
||||
dpi.DrawingEngine = drawingEngine.get();
|
||||
dpi.width = size.width;
|
||||
dpi.height = size.height;
|
||||
|
||||
auto createNewImage = false;
|
||||
auto g1 = gfx_get_g1_element(id);
|
||||
if (g1 == nullptr || g1->width != size.width || g1->height != size.height || (g1->flags & G1_FLAG_RLE_COMPRESSION))
|
||||
{
|
||||
createNewImage = true;
|
||||
}
|
||||
|
||||
if (createNewImage)
|
||||
{
|
||||
auto bufferSize = size.width* size.height;
|
||||
dpi.bits = new uint8_t[bufferSize];
|
||||
std::memset(dpi.bits, 0, bufferSize);
|
||||
|
||||
// Draw the original image if we are creating a new one
|
||||
gfx_draw_sprite(&dpi, ImageId(id), { 0, 0 });
|
||||
}
|
||||
else
|
||||
{
|
||||
dpi.bits = g1->offset;
|
||||
}
|
||||
|
||||
auto dukG = GetObjectAsDukValue(ctx, std::make_shared<ScGraphicsContext>(ctx, dpi));
|
||||
scriptEngine.ExecutePluginCall(plugin, callback, { dukG }, false);
|
||||
|
||||
if (createNewImage)
|
||||
{
|
||||
rct_g1_element newg1{};
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
delete[] g1->offset;
|
||||
newg1 = *g1;
|
||||
}
|
||||
newg1.offset = dpi.bits;
|
||||
newg1.width = size.width;
|
||||
newg1.height = size.height;
|
||||
newg1.flags = 0;
|
||||
gfx_set_g1_element(id, &newg1);
|
||||
}
|
||||
|
||||
drawing_engine_invalidate_image(id);
|
||||
}
|
||||
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace OpenRCT2::Scripting
|
||||
DukValue DukGetImageInfo(duk_context* ctx, ImageIndex id);
|
||||
DukValue DukGetImagePixelData(duk_context* ctx, ImageIndex id);
|
||||
void DukSetPixelData(duk_context* ctx, ImageIndex id, const DukValue& dukPixelData);
|
||||
void DukDrawCustomImage(ScriptEngine& scriptEngine, ImageIndex id, ScreenSize size, const DukValue& callback);
|
||||
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace OpenRCT2::Scripting
|
||||
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:
|
||||
@@ -127,6 +128,21 @@ namespace OpenRCT2::Scripting
|
||||
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);
|
||||
|
||||
@@ -89,17 +89,18 @@ void Plugin::Start()
|
||||
throw std::runtime_error("No main function specified.");
|
||||
}
|
||||
|
||||
_hasStarted = true;
|
||||
|
||||
mainFunc.push();
|
||||
auto result = duk_pcall(_context, 0);
|
||||
if (result != DUK_ERR_NONE)
|
||||
{
|
||||
auto val = std::string(duk_safe_to_string(_context, -1));
|
||||
duk_pop(_context);
|
||||
_hasStarted = false;
|
||||
throw std::runtime_error("[" + _metadata.Name + "] " + val);
|
||||
}
|
||||
duk_pop(_context);
|
||||
|
||||
_hasStarted = true;
|
||||
}
|
||||
|
||||
void Plugin::StopBegin()
|
||||
|
||||
Reference in New Issue
Block a user