11#include "common/config.h"
13#include "medialoader/image/EXRHandler.h"
14#include "medialoader/image/PNGHandler.h"
15#include "medialoader/image/STBHandler.h"
17#include "medialoader/image/ASTCHandler.h"
18#include "medialoader/image/KTXHandler.h"
19#include "medialoader/image/PKMHandler.h"
20#include "medialoader/image/PVRHandler.h"
21#include "medialoader/image/ddsHandler.h"
23#include <simplesquirrel/simplesquirrel.hpp>
36 new PNGHandler,
new WebPHandler,
new STBHandler,
new EXRHandler,
new DDSHandler,
37 new PVRHandler,
new KTXHandler,
new PKMHandler,
new ASTCHandler,
72 if (
handler->canParseCompressed((
const char*)data->getData(), data->getSize()))
return true;
93 std::vector<eve::script::Owned<ImageData>> faces;
98 if (totalW % 3 == 0 && totalH % 4 == 0 && totalW / 3 == totalH / 4) {
107 faces.emplace_back(newPastedImageData(src, 1 *
w, 1 *
h,
w,
h));
108 faces.emplace_back(newPastedImageData(src, 1 *
w, 3 *
h,
w,
h));
109 faces.emplace_back(newPastedImageData(src, 1 *
w, 0 *
h,
w,
h));
110 faces.emplace_back(newPastedImageData(src, 1 *
w, 2 *
h,
w,
h));
111 faces.emplace_back(newPastedImageData(src, 0 *
w, 1 *
h,
w,
h));
112 faces.emplace_back(newPastedImageData(src, 2 *
w, 1 *
h,
w,
h));
113 }
else if (totalW % 4 == 0 && totalH % 3 == 0 && totalW / 4 == totalH / 3) {
121 faces.emplace_back(newPastedImageData(src, 2 *
w, 1 *
h,
w,
h));
122 faces.emplace_back(newPastedImageData(src, 0 *
w, 1 *
h,
w,
h));
123 faces.emplace_back(newPastedImageData(src, 1 *
w, 0 *
h,
w,
h));
124 faces.emplace_back(newPastedImageData(src, 1 *
w, 2 *
h,
w,
h));
125 faces.emplace_back(newPastedImageData(src, 1 *
w, 1 *
h,
w,
h));
126 faces.emplace_back(newPastedImageData(src, 3 *
w, 1 *
h,
w,
h));
127 }
else if (totalH % 6 == 0 && totalW == totalH / 6) {
138 for (
int i = 0; i < 6; i++) faces.emplace_back(newPastedImageData(src, 0, i *
h,
w,
h));
139 }
else if (totalW % 6 == 0 && totalW / 6 == totalH) {
145 for (
int i = 0; i < 6; i++) faces.emplace_back(newPastedImageData(src, i *
w, 0,
w,
h));
153 std::vector<eve::script::Owned<ImageData>> layers;
158 if (totalW % totalH == 0) {
159 for (
int i = 0; i < totalW / totalH; i++)
160 layers.emplace_back(newPastedImageData(src, i * totalH, 0, totalH, totalH));
161 }
else if (totalH % totalW == 0) {
162 for (
int i = 0; i < totalH / totalW; i++)
163 layers.emplace_back(newPastedImageData(src, 0, i * totalW, totalW, totalW));
165 throw eve::Exception(
"Cannot extract volume layers from source ImageData.");
170void Image::expose(ssq::Table& table) {
171 auto cls = table.addClass(
name, Image::create,
false);
177 "ImageData", std::function<image::ImageData*()>([]() ->
image::ImageData* {
return nullptr; }),
true);
189 if (!self)
return 0.f;
192 img.addFunc(
"getPixelG", [](image::ImageData* self,
int x,
int y) ->
float {
193 if (!self)
return 0.f;
194 return self->getPixel(
x,
y).
g;
196 img.addFunc(
"getPixelB", [](image::ImageData* self,
int x,
int y) ->
float {
197 if (!self)
return 0.f;
198 return self->getPixel(
x,
y).
b;
200 img.addFunc(
"getPixelA", [](image::ImageData* self,
int x,
int y) ->
float {
201 if (!self)
return 0.f;
202 return self->getPixel(
x,
y).
a;
204 img.addFunc(
"setPixel", [](image::ImageData* self,
int x,
int y,
float r,
float g,
float b,
float a) {
208 img.addFunc(
"paintCircleUv", [](image::ImageData* self,
float u,
float v,
float radius,
float r,
float g,
float b,
209 float a,
bool wrapU,
bool wrapV) {
210 if (!self)
throw eve::Exception(
"ImageData.paintCircleUv: null image");
212 if (!painted.ok())
throw eve::Exception(
"%s", painted.status().describe().c_str());
213 return std::move(painted).takeValue().changedPixelCount;
216 auto paint =
table.addClass<UvPaintSession>(
217 "UvPaintSession", std::function<UvPaintSession*()>([]() -> UvPaintSession* {
return nullptr; }),
true);
218 paint.addFunc(
"initialize", [
vm = paint.getHandle()](UvPaintSession* self, ImageData*
pixels) {
220 return eve::script::projectResult(vm, Result<void>::failure(Diagnostic::error(
221 DiagnosticCode::InvalidArgument,
"initialize requires ImageData",
222 "image", {},
"image.uvPaintSession.script")));
225 paint.addFunc(
"paintCircle", [
vm = paint.getHandle()](UvPaintSession* self,
float u,
float v,
float radius,
float r,
226 float g,
float b,
float a,
bool wrapU,
bool wrapV) {
228 vm, self->paintCircleResult(
u,
v,
radius,
r,
g,
b,
a, wrapU, wrapV),
229 [](
const UvPaintReceipt& receipt) { return eve::Value(receipt.changedPixelCount); });
231 paint.addFunc(
"undo", [
vm = paint.getHandle()](UvPaintSession* self) {
234 paint.addFunc(
"restore", [
vm = paint.getHandle()](UvPaintSession* self) {
237 paint.addFunc(
"bake", [
vm = paint.getHandle()](UvPaintSession* self) {
240 paint.addFunc(
"currentImageResult", [
vm = paint.getHandle()](UvPaintSession* self) {
241 auto result = self->currentImageResult();
243 auto instance = eve::script::makeOwnedSquirrelInstance<ImageData>(
vm, std::move(result).takeValue());
247 paint.addFunc(
"copyCurrentTo", [
vm = paint.getHandle()](UvPaintSession* self,
ImageData* destination) {
251 "copyCurrentTo requires ImageData",
"destination", {},
252 "image.uvPaintSession.script")));
255 paint.addFunc(
"getRevision", [](UvPaintSession* self) {
return self->revision(); });
256 paint.addFunc(
"getUndoCount", [](UvPaintSession* self) {
return self->undoCount(); });
257 paint.addFunc(
"isInitialized", [](UvPaintSession* self) {
return self->isInitialized(); });
259 auto region =
table.addClass<UvPaintRegion>(
260 "UvPaintRegion", std::function<UvPaintRegion*()>([]() -> UvPaintRegion* {
return nullptr; }),
true);
261 region.addFunc(
"getCenterX", [](UvPaintRegion* self) {
return self->centerX; });
262 region.addFunc(
"getCenterY", [](UvPaintRegion* self) {
return self->centerY; });
263 region.addFunc(
"getX", [](UvPaintRegion* self) {
return self->minX; });
264 region.addFunc(
"getY", [](UvPaintRegion* self) {
return self->minY; });
265 region.addFunc(
"getWidth", [](UvPaintRegion* self) {
return self->width(); });
266 region.addFunc(
"getHeight", [](UvPaintRegion* self) {
return self->height(); });
267 region.addFunc(
"getR", [](UvPaintRegion* self) {
return self->r; });
268 region.addFunc(
"getG", [](UvPaintRegion* self) {
return self->g; });
269 region.addFunc(
"getB", [](UvPaintRegion* self) {
return self->b; });
270 region.addFunc(
"getA", [](UvPaintRegion* self) {
return self->a; });
271 region.addFunc(
"prepare", [
vm = region.getHandle()](UvPaintRegion* self,
int width,
int height,
float u,
float v,
272 float radiusU,
float radiusV,
float r,
float g,
float b,
273 float a,
bool flipV) {
274 return eve::script::projectResult(
275 vm, self->prepareResult(width, height, u, v, radiusU, radiusV, r, g, b, a, flipV));
279void Image::expose(ssq::Class&
cls) {
280 cls.addFunc(
"getName", &Image::getName);
282 cls.addFunc(
"newImageDataFromFile", &Image::newImageDataFromFile);
283 cls.addFunc(
"newEmptyImageData", [](Image* self,
int width,
int height,
const std::string& format) -> ImageData* {
284 if (!self)
return nullptr;
287 cls.addFunc(
"newUvPaintSession", [](Image*) {
return new UvPaintSession(); });
288 cls.addFunc(
"newUvPaintRegion", [](Image*) {
return new UvPaintRegion(); });
289 cls.addFunc(
"isCompressed", &Image::isCompressed);
#define Module_IMPL(ModuleName, newExpr)
The single Squirrel projection for common Result, Status and Value.
Explicit Value/Owned/Borrowed semantics at the Squirrel boundary.
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
EVENGINE_API_FOUNDATION public API.
Resource * get(std::string key)
Get the cached resource for key; on a miss, load it through the registered IAssetReloader providers a...
static ResourceManager & getInstance()
Returns the instance.
Resource is a game object that is managed by the ResourceManager. It can be loaded from a file or gen...
static Result failure(Status status)
Construct a failed result from a structured status.
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Represents raw pixel data.
ImageData * clone() const
bool inside(int x, int y) const
Checks whether a position is inside this ImageData. Useful for checking bounds.
void getPixel(int x, int y, Colorf &c) const
Gets the pixel at location (x,y).
medialoader::Colorf Colorf
void paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, int sh)
Paste part of one ImageData onto another. The subregion defined by the top-left corner (sx,...
ImageData * rotate(float radians, std::string filter="nearest", bool expand=true) const
Rotate pixels around the image center and return a new ImageData.
size_t getPixelSize() const
std::string getFormat() const
This module is responsible for decoding files such as PNG, GIF, JPEG into raw pixel data,...
ImageData * newImageDataFromFile(std::string path)
Loads an image from a VFS path through the unified resource cache. Repeated loads of one path share a...
medialoader::FormatHandler FormatHandler
std::vector< script::Owned< ImageData > > newVolumeLayers(ImageData *src)
Creates a volume layers. @ownership Caller deletes unless documented otherwise.
bool isCompressed(Data *data)
Creates new CompressedImageData from FileData.
std::vector< script::Owned< ImageData > > newCubeFaces(ImageData *src)
Creates a cube faces. @ownership Caller deletes unless documented otherwise.
const std::list< FormatHandler * > & getFormatHandlers() const
Returns the format handlers.
ImageData * newImageData(Data *data)
Creates new ImageData from FileData.
Internal decoder adapter; each call owns its output and borrows input synchronously.
std::unordered_map< std::string, SkillDefinition > & table()
ssq::Table projectStatusResult(HSQUIRRELVM vm, const Status &status)
Project a checked native status that carries no payload.
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.
Build metadata (engine git commit, build time, third-party version).