396 lines
14 KiB
C
396 lines
14 KiB
C
// sprite_playdate.c - Cell integration for Playdate Sprite API
|
|
// Wraps pd_api_sprite.h functions for JavaScript access
|
|
|
|
#include "cell.h"
|
|
#include "common.h"
|
|
|
|
// --- Helpers ---
|
|
|
|
static LCDSprite* js2sprite(JSContext *js, JSValueConst val) {
|
|
int64_t ptr;
|
|
if (JS_ToInt64(js, &ptr, val) < 0) return NULL;
|
|
return (LCDSprite*)(intptr_t)ptr;
|
|
}
|
|
|
|
static LCDBitmap* js2bitmap(JSContext *js, JSValueConst val) {
|
|
int64_t ptr;
|
|
if (JS_ToInt64(js, &ptr, val) < 0) return NULL;
|
|
return (LCDBitmap*)(intptr_t)ptr;
|
|
}
|
|
|
|
// --- Sprite Functions ---
|
|
|
|
JSC_CCALL(sprite_setAlwaysRedraw,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
pd_sprite->setAlwaysRedraw(JS_ToBool(js, argv[0]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_drawSprites,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
pd_sprite->drawSprites();
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_updateAndDrawSprites,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
pd_sprite->updateAndDrawSprites();
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_newSprite,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = pd_sprite->newSprite();
|
|
if (!s) return JS_ThrowInternalError(js, "failed to create sprite");
|
|
return JS_NewInt64(js, (int64_t)(intptr_t)s);
|
|
)
|
|
|
|
JSC_CCALL(sprite_freeSprite,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (s) pd_sprite->freeSprite(s);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_copy,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
LCDSprite *copy = pd_sprite->copy(s);
|
|
return copy ? JS_NewInt64(js, (int64_t)(intptr_t)copy) : JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_addSprite,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->addSprite(s);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_removeSprite,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->removeSprite(s);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_removeAllSprites,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
pd_sprite->removeAllSprites();
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getSpriteCount,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
return JS_NewInt32(js, pd_sprite->getSpriteCount());
|
|
)
|
|
|
|
JSC_CCALL(sprite_setBounds,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
PDRect bounds = { (float)js2number(js, argv[1]), (float)js2number(js, argv[2]),
|
|
(float)js2number(js, argv[3]), (float)js2number(js, argv[4]) };
|
|
pd_sprite->setBounds(s, bounds);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getBounds,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
PDRect b = pd_sprite->getBounds(s);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, b.x));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, b.y));
|
|
JS_SetPropertyStr(js, obj, "width", JS_NewFloat64(js, b.width));
|
|
JS_SetPropertyStr(js, obj, "height", JS_NewFloat64(js, b.height));
|
|
return obj;
|
|
)
|
|
|
|
JSC_CCALL(sprite_moveTo,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->moveTo(s, (float)js2number(js, argv[1]), (float)js2number(js, argv[2]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_moveBy,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->moveBy(s, (float)js2number(js, argv[1]), (float)js2number(js, argv[2]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setImage,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
LCDBitmap *img = js2bitmap(js, argv[1]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
LCDBitmapFlip flip = argc > 2 ? (LCDBitmapFlip)(int)js2number(js, argv[2]) : kBitmapUnflipped;
|
|
pd_sprite->setImage(s, img, flip);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getImage,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
LCDBitmap *img = pd_sprite->getImage(s);
|
|
return img ? JS_NewInt64(js, (int64_t)(intptr_t)img) : JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setSize,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setSize(s, (float)js2number(js, argv[1]), (float)js2number(js, argv[2]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setZIndex,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setZIndex(s, (int16_t)js2number(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getZIndex,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewInt32(js, pd_sprite->getZIndex(s));
|
|
)
|
|
|
|
JSC_CCALL(sprite_setDrawMode,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setDrawMode(s, (LCDBitmapDrawMode)(int)js2number(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setImageFlip,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setImageFlip(s, (LCDBitmapFlip)(int)js2number(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getImageFlip,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewInt32(js, pd_sprite->getImageFlip(s));
|
|
)
|
|
|
|
JSC_CCALL(sprite_setVisible,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setVisible(s, JS_ToBool(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_isVisible,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewBool(js, pd_sprite->isVisible(s));
|
|
)
|
|
|
|
JSC_CCALL(sprite_setOpaque,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setOpaque(s, JS_ToBool(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_markDirty,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->markDirty(s);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setTag,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setTag(s, (uint8_t)js2number(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getTag,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewInt32(js, pd_sprite->getTag(s));
|
|
)
|
|
|
|
JSC_CCALL(sprite_setIgnoresDrawOffset,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setIgnoresDrawOffset(s, JS_ToBool(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getPosition,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
float x, y;
|
|
pd_sprite->getPosition(s, &x, &y);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, x));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, y));
|
|
return obj;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setCenter,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setCenter(s, (float)js2number(js, argv[1]), (float)js2number(js, argv[2]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getCenter,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
float x, y;
|
|
pd_sprite->getCenter(s, &x, &y);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, x));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, y));
|
|
return obj;
|
|
)
|
|
|
|
// --- Collision Functions ---
|
|
|
|
JSC_CCALL(sprite_resetCollisionWorld,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
pd_sprite->resetCollisionWorld();
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setCollideRect,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
PDRect rect = { (float)js2number(js, argv[1]), (float)js2number(js, argv[2]),
|
|
(float)js2number(js, argv[3]), (float)js2number(js, argv[4]) };
|
|
pd_sprite->setCollideRect(s, rect);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_getCollideRect,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
PDRect r = pd_sprite->getCollideRect(s);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, r.x));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, r.y));
|
|
JS_SetPropertyStr(js, obj, "width", JS_NewFloat64(js, r.width));
|
|
JS_SetPropertyStr(js, obj, "height", JS_NewFloat64(js, r.height));
|
|
return obj;
|
|
)
|
|
|
|
JSC_CCALL(sprite_clearCollideRect,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->clearCollideRect(s);
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_setCollisionsEnabled,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setCollisionsEnabled(s, JS_ToBool(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_collisionsEnabled,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewBool(js, pd_sprite->collisionsEnabled(s));
|
|
)
|
|
|
|
JSC_CCALL(sprite_setUpdatesEnabled,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
pd_sprite->setUpdatesEnabled(s, JS_ToBool(js, argv[1]));
|
|
return JS_NULL;
|
|
)
|
|
|
|
JSC_CCALL(sprite_updatesEnabled,
|
|
if (!pd_sprite) return JS_ThrowInternalError(js, "sprite not initialized");
|
|
LCDSprite *s = js2sprite(js, argv[0]);
|
|
if (!s) return JS_ThrowTypeError(js, "invalid sprite");
|
|
return JS_NewBool(js, pd_sprite->updatesEnabled(s));
|
|
)
|
|
|
|
static const JSCFunctionListEntry js_sprite_funcs[] = {
|
|
MIST_FUNC_DEF(sprite, setAlwaysRedraw, 1),
|
|
MIST_FUNC_DEF(sprite, drawSprites, 0),
|
|
MIST_FUNC_DEF(sprite, updateAndDrawSprites, 0),
|
|
MIST_FUNC_DEF(sprite, newSprite, 0),
|
|
MIST_FUNC_DEF(sprite, freeSprite, 1),
|
|
MIST_FUNC_DEF(sprite, copy, 1),
|
|
MIST_FUNC_DEF(sprite, addSprite, 1),
|
|
MIST_FUNC_DEF(sprite, removeSprite, 1),
|
|
MIST_FUNC_DEF(sprite, removeAllSprites, 0),
|
|
MIST_FUNC_DEF(sprite, getSpriteCount, 0),
|
|
MIST_FUNC_DEF(sprite, setBounds, 5),
|
|
MIST_FUNC_DEF(sprite, getBounds, 1),
|
|
MIST_FUNC_DEF(sprite, moveTo, 3),
|
|
MIST_FUNC_DEF(sprite, moveBy, 3),
|
|
MIST_FUNC_DEF(sprite, setImage, 3),
|
|
MIST_FUNC_DEF(sprite, getImage, 1),
|
|
MIST_FUNC_DEF(sprite, setSize, 3),
|
|
MIST_FUNC_DEF(sprite, setZIndex, 2),
|
|
MIST_FUNC_DEF(sprite, getZIndex, 1),
|
|
MIST_FUNC_DEF(sprite, setDrawMode, 2),
|
|
MIST_FUNC_DEF(sprite, setImageFlip, 2),
|
|
MIST_FUNC_DEF(sprite, getImageFlip, 1),
|
|
MIST_FUNC_DEF(sprite, setVisible, 2),
|
|
MIST_FUNC_DEF(sprite, isVisible, 1),
|
|
MIST_FUNC_DEF(sprite, setOpaque, 2),
|
|
MIST_FUNC_DEF(sprite, markDirty, 1),
|
|
MIST_FUNC_DEF(sprite, setTag, 2),
|
|
MIST_FUNC_DEF(sprite, getTag, 1),
|
|
MIST_FUNC_DEF(sprite, setIgnoresDrawOffset, 2),
|
|
MIST_FUNC_DEF(sprite, getPosition, 1),
|
|
MIST_FUNC_DEF(sprite, setCenter, 3),
|
|
MIST_FUNC_DEF(sprite, getCenter, 1),
|
|
MIST_FUNC_DEF(sprite, resetCollisionWorld, 0),
|
|
MIST_FUNC_DEF(sprite, setCollideRect, 5),
|
|
MIST_FUNC_DEF(sprite, getCollideRect, 1),
|
|
MIST_FUNC_DEF(sprite, clearCollideRect, 1),
|
|
MIST_FUNC_DEF(sprite, setCollisionsEnabled, 2),
|
|
MIST_FUNC_DEF(sprite, collisionsEnabled, 1),
|
|
MIST_FUNC_DEF(sprite, setUpdatesEnabled, 2),
|
|
MIST_FUNC_DEF(sprite, updatesEnabled, 1),
|
|
};
|
|
|
|
JSValue js_sprite_use(JSContext *js) {
|
|
JSValue mod = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, mod, js_sprite_funcs, countof(js_sprite_funcs));
|
|
return mod;
|
|
}
|