mirror of https://github.com/mgba-emu/mgba.git
Scripting: Expose some basic geometric utility types
This commit is contained in:
parent
00246cda74
commit
467768d414
|
|
@ -11,9 +11,12 @@
|
|||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/script/macros.h>
|
||||
#include <mgba-util/geometry.h>
|
||||
#include <mgba-util/image.h>
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mImage)
|
||||
mSCRIPT_DECLARE_STRUCT(mRectangle);
|
||||
mSCRIPT_DECLARE_STRUCT(mSize);
|
||||
|
||||
struct mScriptContext;
|
||||
void mScriptContextAttachImage(struct mScriptContext* context);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,100 @@ mSCRIPT_DEFINE_STRUCT(mScriptCallbackManager)
|
|||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCallbackManager, remove)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
static struct mScriptValue* _mRectangleNew(int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||
struct mRectangle* rect = malloc(sizeof(*rect));
|
||||
rect->x = x;
|
||||
rect->y = y;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mRectangle));
|
||||
result->value.opaque = rect;
|
||||
result->flags = mSCRIPT_VALUE_FLAG_DEINIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mRectangleCopy(const struct mRectangle* old) {
|
||||
struct mRectangle* rect = malloc(sizeof(*rect));
|
||||
memcpy(rect, old, sizeof(*rect));
|
||||
struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mRectangle));
|
||||
result->value.opaque = rect;
|
||||
result->flags = mSCRIPT_VALUE_FLAG_DEINIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mRectangleSize(const struct mRectangle* rect) {
|
||||
struct mSize* size = malloc(sizeof(*size));
|
||||
size->width = rect->width;
|
||||
size->height = rect->height;
|
||||
struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mSize));
|
||||
result->value.opaque = size;
|
||||
result->flags = mSCRIPT_VALUE_FLAG_DEINIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mRectangle, W(mRectangle), copy, _mRectangleCopy, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mRectangle, union, mRectangleUnion, 1, CS(mRectangle), other);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mRectangle, BOOL, intersection, mRectangleIntersection, 1, CS(mRectangle), other);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD(mRectangle, center, mRectangleCenter, 1, S(mRectangle), other);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mRectangle, W(mSize), size, _mRectangleSize, 0);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mRectangle)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A basic axis-aligned rectangle object")
|
||||
mSCRIPT_DEFINE_DOCSTRING("Create a copy of this struct::mRectangle")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mRectangle, copy)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The x coordinate of the top-left corner")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mRectangle, S32, x)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The y coordinate of the top-left corner")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mRectangle, S32, y)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The width of the rectangle")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mRectangle, S32, width)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The height of the rectangle")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mRectangle, S32, height)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Find the bounding box of the union of this and another rectangle")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mRectangle, union)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Find the intersection of this and another rectangle. Returns false if the rectangles don't intersect")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mRectangle, intersection)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Center another rectangle inside this one")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mRectangle, center)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Return the size of this struct::mRectangle as a struct::mSize object")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mRectangle, size)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_BIND_FUNCTION(mRectangleNew_Binding, W(mRectangle), _mRectangleNew, 4, S32, x, S32, y, S32, width, S32, height);
|
||||
|
||||
static struct mScriptValue* _mSizeNew(int32_t width, int32_t height) {
|
||||
struct mSize* size = malloc(sizeof(*size));
|
||||
size->width = width;
|
||||
size->height = height;
|
||||
struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mSize));
|
||||
result->value.opaque = size;
|
||||
result->flags = mSCRIPT_VALUE_FLAG_DEINIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mSizeCopy(const struct mSize* old) {
|
||||
struct mSize* size = malloc(sizeof(*size));
|
||||
memcpy(size, old, sizeof(*size));
|
||||
struct mScriptValue* result = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mSize));
|
||||
result->value.opaque = size;
|
||||
result->flags = mSCRIPT_VALUE_FLAG_DEINIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_C_METHOD(mSize, W(mSize), copy, _mSizeCopy, 0);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mSize)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING("A basic size (width/height) object")
|
||||
mSCRIPT_DEFINE_DOCSTRING("Create a copy of this struct::mSize")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mSize, copy)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The width")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mSize, S32, width)
|
||||
mSCRIPT_DEFINE_DOCSTRING("The height")
|
||||
mSCRIPT_DEFINE_STRUCT_MEMBER(mSize, S32, height)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_BIND_FUNCTION(mSizeNew_Binding, W(mSize), _mSizeNew, 2, S32, width, S32, height);
|
||||
|
||||
void mScriptContextAttachStdlib(struct mScriptContext* context) {
|
||||
struct mScriptValue* lib;
|
||||
|
||||
|
|
@ -177,11 +271,15 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) {
|
|||
mScriptContextExportNamespace(context, "util", (struct mScriptKVPair[]) {
|
||||
mSCRIPT_KV_PAIR(makeBitmask, &mScriptMakeBitmask_Binding),
|
||||
mSCRIPT_KV_PAIR(expandBitmask, &mScriptExpandBitmask_Binding),
|
||||
mSCRIPT_KV_PAIR(newRectangle, &mRectangleNew_Binding),
|
||||
mSCRIPT_KV_PAIR(newSize, &mSizeNew_Binding),
|
||||
mSCRIPT_KV_SENTINEL
|
||||
});
|
||||
mScriptContextSetDocstring(context, "util", "Basic utility library");
|
||||
mScriptContextSetDocstring(context, "util.makeBitmask", "Compile a list of bit indices into a bitmask");
|
||||
mScriptContextSetDocstring(context, "util.expandBitmask", "Expand a bitmask into a list of bit indices");
|
||||
mScriptContextSetDocstring(context, "util.newRectangle", "Create a new mRectangle");
|
||||
mScriptContextSetDocstring(context, "util.newSize", "Create a new mSize");
|
||||
|
||||
struct mScriptValue* systemVersion = mScriptStringCreateFromUTF8(projectVersion);
|
||||
struct mScriptValue* systemProgram = mScriptStringCreateFromUTF8(projectName);
|
||||
|
|
|
|||
|
|
@ -169,10 +169,100 @@ M_TEST_DEFINE(callbackWeakref) {
|
|||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(rectangle) {
|
||||
SETUP_LUA;
|
||||
|
||||
struct mRectangle rect = {
|
||||
.x = 1,
|
||||
.y = 2,
|
||||
.width = 3,
|
||||
.height = 4,
|
||||
};
|
||||
struct mScriptValue rval = mSCRIPT_MAKE_S(mRectangle, &rect);
|
||||
mScriptContextSetGlobal(&context, "testRect", &rval);
|
||||
TEST_PROGRAM("assert(testRect)");
|
||||
TEST_PROGRAM("assert(testRect.x == 1)");
|
||||
TEST_PROGRAM("assert(testRect.y == 2)");
|
||||
TEST_PROGRAM("assert(testRect.width == 3)");
|
||||
TEST_PROGRAM("assert(testRect.height == 4)");
|
||||
TEST_PROGRAM(
|
||||
"testRect.x = 10\n"
|
||||
"testRect.y = 11\n"
|
||||
"testRect.width = 20\n"
|
||||
"testRect.height = 21\n"
|
||||
);
|
||||
assert_int_equal(rect.x, 10);
|
||||
assert_int_equal(rect.y, 11);
|
||||
assert_int_equal(rect.width, 20);
|
||||
assert_int_equal(rect.height, 21);
|
||||
|
||||
TEST_PROGRAM("newRect = util.newRectangle(5, 6, 10, 11)");
|
||||
TEST_PROGRAM("assert(newRect.x == 5)");
|
||||
TEST_PROGRAM("assert(newRect.y == 6)");
|
||||
TEST_PROGRAM("assert(newRect.width == 10)");
|
||||
TEST_PROGRAM("assert(newRect.height == 11)");
|
||||
|
||||
TEST_PROGRAM("testRect2 = testRect:copy()");
|
||||
TEST_PROGRAM("assert(testRect2.x == 10)");
|
||||
TEST_PROGRAM("assert(testRect2.y == 11)");
|
||||
TEST_PROGRAM("assert(testRect2.width == 20)");
|
||||
TEST_PROGRAM("assert(testRect2.height == 21)");
|
||||
|
||||
TEST_PROGRAM("assert(testRect2:intersection(newRect))");
|
||||
TEST_PROGRAM("assert(testRect2.x == 10)");
|
||||
TEST_PROGRAM("assert(testRect2.y == 11)");
|
||||
TEST_PROGRAM("assert(testRect2.width == 5)");
|
||||
TEST_PROGRAM("assert(testRect2.height == 6)");
|
||||
|
||||
TEST_PROGRAM("testRect2:union(testRect)");
|
||||
TEST_PROGRAM("assert(testRect2.x == 10)");
|
||||
TEST_PROGRAM("assert(testRect2.y == 11)");
|
||||
TEST_PROGRAM("assert(testRect2.width == 20)");
|
||||
TEST_PROGRAM("assert(testRect2.height == 21)");
|
||||
|
||||
TEST_PROGRAM("testSize = testRect:size()");
|
||||
TEST_PROGRAM("assert(testRect.width == testSize.width)");
|
||||
TEST_PROGRAM("assert(testRect.height == testSize.height)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(size) {
|
||||
SETUP_LUA;
|
||||
|
||||
struct mSize size = {
|
||||
.width = 1,
|
||||
.height = 2,
|
||||
};
|
||||
struct mScriptValue sval = mSCRIPT_MAKE_S(mSize, &size);
|
||||
mScriptContextSetGlobal(&context, "testSize", &sval);
|
||||
TEST_PROGRAM("assert(testSize)");
|
||||
TEST_PROGRAM("assert(testSize.width == 1)");
|
||||
TEST_PROGRAM("assert(testSize.height == 2)");
|
||||
TEST_PROGRAM(
|
||||
"testSize.width = 3\n"
|
||||
"testSize.height = 4\n"
|
||||
);
|
||||
assert_int_equal(size.width, 3);
|
||||
assert_int_equal(size.height, 4);
|
||||
|
||||
TEST_PROGRAM("newSize = util.newSize(5, 6)");
|
||||
TEST_PROGRAM("assert(newSize.width == 5)");
|
||||
TEST_PROGRAM("assert(newSize.height == 6)");
|
||||
|
||||
TEST_PROGRAM("testSize2 = testSize:copy()");
|
||||
TEST_PROGRAM("assert(testSize2.width == 3)");
|
||||
TEST_PROGRAM("assert(testSize2.height == 4)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptStdlib,
|
||||
cmocka_unit_test(bitMask),
|
||||
cmocka_unit_test(bitUnmask),
|
||||
cmocka_unit_test(callbacks),
|
||||
cmocka_unit_test(oneshot),
|
||||
cmocka_unit_test(callbackWeakref),
|
||||
cmocka_unit_test(rectangle),
|
||||
cmocka_unit_test(size),
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue