Some checks failed
Build and Deploy / build-linux (push) Failing after 39s
Build and Deploy / build-windows (CLANG64) (push) Failing after 8m19s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
1279 lines
48 KiB
C
1279 lines
48 KiB
C
// qjs_chipmunk.c
|
|
|
|
#include <chipmunk/chipmunk.h>
|
|
#include <chipmunk/chipmunk_unsafe.h>
|
|
#include <quickjs.h>
|
|
#include <assert.h>
|
|
|
|
/*
|
|
Items are automatically reclaimed when they go out of scope in your quickjs program.
|
|
Each chipmunk type's userdata is a pointer to the underlying JSValue it's associated with.
|
|
Constraints and shapes are create and forget. They can't be changed between bodies. Just delete and make anew.
|
|
Memory for the underlying C types are only freed when the object is out of scope in javascript.
|
|
If a body is freed, all of its shapes and constraints are invalid and issue a warning if you try to use them.
|
|
*/
|
|
|
|
#define countof(x) (sizeof(x)/sizeof((x)[0]))
|
|
|
|
// Forward declarations of the prototypes we'll store globally
|
|
static JSValue circle_proto;
|
|
static JSValue segment_proto;
|
|
static JSValue poly_proto;
|
|
|
|
// For constraints
|
|
static JSValue js_gear;
|
|
static JSValue js_pin;
|
|
static JSValue js_pivot;
|
|
static JSValue js_rotary;
|
|
static JSValue js_motor;
|
|
static JSValue js_damped_spring;
|
|
static JSValue js_damped_rotary;
|
|
static JSValue js_groove;
|
|
static JSValue js_slide;
|
|
static JSValue js_ratchet;
|
|
|
|
static JSClassID js_cpSpace_class_id;
|
|
static JSClassID js_cpBody_class_id;
|
|
static JSClassID js_cpShape_class_id;
|
|
static JSClassID js_cpConstraint_class_id;
|
|
|
|
static void BodyFreeWrap(cpSpace *space, cpBody *body, void *unused) {
|
|
cpSpaceRemoveBody(space, body);
|
|
}
|
|
|
|
static void PostBodyFree(cpBody *body, cpSpace *space) {
|
|
cpSpaceAddPostStepCallback(space, BodyFreeWrap, body, NULL);
|
|
}
|
|
|
|
static void ShapeFreeWrap(cpSpace *space, cpShape *shape, void *unused) {
|
|
printf("Removing shape %p from space\n", shape);
|
|
cpSpace *myspace = cpShapeGetSpace(shape);
|
|
printf("i'm currently in %p, removing out of %p\n", myspace, space);
|
|
cpSpaceRemoveShape(space, shape);
|
|
}
|
|
|
|
static void PostShapeFree(cpShape *shape, cpSpace *space) {
|
|
cpSpaceAddPostStepCallback(space, ShapeFreeWrap, shape, NULL);
|
|
}
|
|
|
|
static void ConstraintFreeWrap(cpSpace *space, cpConstraint *constraint, void *unused) {
|
|
cpSpaceRemoveConstraint(space, constraint);
|
|
}
|
|
|
|
static void PostConstraintFree(cpConstraint *constraint, cpSpace *space) {
|
|
cpSpaceAddPostStepCallback(space, ConstraintFreeWrap, constraint, NULL);
|
|
}
|
|
|
|
static void js_cpSpace_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
printf("freeing space\n");
|
|
cpSpace *space = JS_GetOpaque(val, js_cpSpace_class_id);
|
|
cpSpaceEachShape(space, PostShapeFree, space);
|
|
cpSpaceEachConstraint(space, PostConstraintFree, space);
|
|
cpSpaceEachBody(space, PostBodyFree, space);
|
|
|
|
JSValue *cb = (JSValue*)cpShapeGetUserData(space);
|
|
JS_FreeValueRT(rt, *cb);
|
|
free(cb);
|
|
cpShapeSetUserData(space, NULL); // required to not crash on space free
|
|
cpSpaceFree(space);
|
|
}
|
|
|
|
static void body_rm_shape(cpBody *body, cpShape *shape, cpSpace *space)
|
|
{
|
|
cpSpaceRemoveShape(space, shape);
|
|
}
|
|
|
|
static void body_rm_constraint(cpBody *body, cpConstraint *constraint, cpSpace *space)
|
|
{
|
|
cpSpaceRemoveConstraint(space, constraint);
|
|
}
|
|
|
|
static void js_cpBody_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
printf("freeing body\n");
|
|
cpBody *body = JS_GetOpaque(val, js_cpBody_class_id);
|
|
|
|
cpSpace *space = cpBodyGetSpace(body);
|
|
|
|
if (space) {
|
|
cpBodyEachShape(body, body_rm_shape, space);
|
|
cpBodyEachConstraint(body, PostConstraintFree, space);
|
|
cpSpaceRemoveBody(space,body);
|
|
}
|
|
|
|
JSValue *cb = (JSValue *)cpBodyGetUserData(body);
|
|
JS_FreeValueRT(rt, *cb);
|
|
free(cb);
|
|
|
|
cpBodyFree(body);
|
|
}
|
|
|
|
static void js_cpShape_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
printf("freeing shape\n");
|
|
cpShape *shape = JS_GetOpaque(val, js_cpShape_class_id);
|
|
|
|
cpSpace *space = cpShapeGetSpace(shape);
|
|
if (space)
|
|
cpSpaceRemoveShape(space, shape);
|
|
|
|
JSValue *cb = (JSValue*)cpShapeGetUserData(shape);
|
|
JS_FreeValueRT(rt, *cb);
|
|
free(cb);
|
|
|
|
cpShapeFree(shape);
|
|
}
|
|
|
|
static void js_cpConstraint_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
printf("freeing constraint\n");
|
|
cpConstraint *joint = JS_GetOpaque(val, js_cpConstraint_class_id);
|
|
|
|
cpSpace *space = cpConstraintGetSpace(joint);
|
|
if (space)
|
|
cpSpaceRemoveConstraint(space,joint);
|
|
|
|
JSValue *cb = (JSValue*)cpConstraintGetUserData(joint);
|
|
JS_FreeValueRT(rt, *cb);
|
|
free(cb);
|
|
|
|
cpConstraintFree(joint);
|
|
}
|
|
|
|
#define CPCLASS(TYPE) \
|
|
static inline TYPE *js2##TYPE(JSContext *js, JSValue v) { \
|
|
return JS_GetOpaque(v, js_##TYPE##_class_id); \
|
|
} \
|
|
static inline JSValue TYPE##2js(JSContext *js, TYPE *cp) { \
|
|
return JS_DupValue(js, *(JSValue*)TYPE##GetUserData(cp)); \
|
|
} \
|
|
static inline void js_##TYPE##_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { \
|
|
TYPE *cp = JS_GetOpaque(val, js_##TYPE##_class_id); \
|
|
JS_MarkValue(rt, *(JSValue*)TYPE##GetUserData(cp), mark_func); \
|
|
} \
|
|
static JSClassDef js_##TYPE##_class = { \
|
|
#TYPE, \
|
|
.finalizer = js_##TYPE##_finalizer, \
|
|
.gc_mark = js_##TYPE##_mark, \
|
|
}; \
|
|
|
|
CPCLASS(cpShape)
|
|
CPCLASS(cpSpace)
|
|
CPCLASS(cpBody)
|
|
CPCLASS(cpConstraint)
|
|
|
|
static inline cpVect js2cpvect(JSContext *js, JSValue v) {
|
|
cpVect ret;
|
|
JSValue x = JS_GetPropertyStr(js, v, "x");
|
|
JSValue y = JS_GetPropertyStr(js, v, "y");
|
|
#if CP_USE_DOUBLES
|
|
JS_ToFloat64(js, &ret.x, x);
|
|
JS_ToFloat64(js, &ret.y, y);
|
|
#else
|
|
double fx, fy;
|
|
JS_ToFloat64(js, &fx, x);
|
|
JS_ToFloat64(js, &fy, y);
|
|
ret.x = (cpFloat)fx;
|
|
ret.y = (cpFloat)fy;
|
|
#endif
|
|
JS_FreeValue(js, x);
|
|
JS_FreeValue(js, y);
|
|
return ret;
|
|
}
|
|
|
|
static inline JSValue cpvect2js(JSContext *js, cpVect v) {
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, v.x));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, v.y));
|
|
return obj;
|
|
}
|
|
|
|
static inline JSValue angle2js(JSContext *js, double angle) {
|
|
return JS_NewFloat64(js, angle);
|
|
}
|
|
|
|
static inline double js2angle(JSContext *js, JSValue v) {
|
|
double angle;
|
|
JS_ToFloat64(js, &angle, v);
|
|
return angle;
|
|
}
|
|
|
|
static inline JSValue number2js(JSContext *js, double number) {
|
|
return JS_NewFloat64(js, number);
|
|
}
|
|
|
|
static inline double js2number(JSContext *js, JSValue v) {
|
|
double num;
|
|
JS_ToFloat64(js, &num, v);
|
|
return num;
|
|
}
|
|
|
|
// CP Space GETSET macros
|
|
|
|
#define CP_GETSET(CP, ENTRY, TYPE) \
|
|
static JSValue js_##CP##_set_##ENTRY (JSContext *js, JSValueConst this_val, JSValue val) { \
|
|
CP *cp = js2##CP(js, this_val); \
|
|
if (!cp) return JS_EXCEPTION; \
|
|
CP##Set##ENTRY(cp, js2##TYPE(js, val)); \
|
|
return JS_UNDEFINED; \
|
|
} \
|
|
static JSValue js_##CP##_get_##ENTRY (JSContext *js, JSValueConst this_val) { \
|
|
CP *cp = js2##CP(js, this_val); \
|
|
if (!cp) return JS_EXCEPTION; \
|
|
return TYPE##2js(js, CP##Get##ENTRY(cp)); \
|
|
}
|
|
|
|
static JSValue js_make_cpSpace(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpSpace *space = cpSpaceNew();
|
|
JSValue obj = JS_NewObjectClass(js, js_cpSpace_class_id);
|
|
JS_SetOpaque(obj, space);
|
|
|
|
JSValue *cb = malloc(sizeof(*cb));
|
|
*cb = obj;//JS_DupValue(js,obj);
|
|
cpSpaceSetUserData(space, cb);
|
|
|
|
printf("new space is %p\n", space);
|
|
|
|
return obj;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_chipmunk2d_funcs[] = {
|
|
JS_CFUNC_DEF("make_space", 0, js_make_cpSpace),
|
|
};
|
|
|
|
// CP Space properties
|
|
CP_GETSET(cpSpace, Gravity, cpvect)
|
|
CP_GETSET(cpSpace, Iterations, number)
|
|
CP_GETSET(cpSpace, IdleSpeedThreshold, number)
|
|
CP_GETSET(cpSpace, SleepTimeThreshold, number)
|
|
CP_GETSET(cpSpace, CollisionSlop, number)
|
|
CP_GETSET(cpSpace, CollisionBias, number)
|
|
CP_GETSET(cpSpace, CollisionPersistence, number)
|
|
|
|
// Helpers for eachBody/eachShape/eachConstraint
|
|
struct contextfn {
|
|
JSContext *js;
|
|
JSValue fn;
|
|
};
|
|
|
|
typedef struct contextfn ctxfn;
|
|
|
|
static void each_body_callback(cpBody *body, void *data) {
|
|
ctxfn *pass = (ctxfn*)data;
|
|
JSValue arg = cpBody2js(pass->js, body);
|
|
JS_Call(pass->js, pass->fn, JS_UNDEFINED, 1, &arg);
|
|
JS_FreeValue(pass->js, arg);
|
|
}
|
|
|
|
static JSValue js_space_each_body(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if (!space) return JS_EXCEPTION;
|
|
if (!JS_IsFunction(js, argv[0])) {
|
|
return JS_ThrowTypeError(js, "Expected a function");
|
|
}
|
|
ctxfn pass;
|
|
pass.js = js;
|
|
pass.fn = JS_DupValue(js, argv[0]);
|
|
cpSpaceEachBody(space, each_body_callback, &pass);
|
|
JS_FreeValue(js, pass.fn);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static void each_shape_callback(cpShape *shape, void *data) {
|
|
ctxfn *pass = (ctxfn *)data;
|
|
JSValue arg = cpShape2js(pass->js, shape);
|
|
JS_Call(pass->js, pass->fn, JS_UNDEFINED, 1, &arg);
|
|
JS_FreeValue(pass->js, arg);
|
|
}
|
|
|
|
static JSValue js_space_each_shape(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if (!space) return JS_EXCEPTION;
|
|
if (!JS_IsFunction(js, argv[0])) {
|
|
return JS_ThrowTypeError(js, "Expected a function");
|
|
}
|
|
ctxfn pass;
|
|
pass.js = js;
|
|
pass.fn = JS_DupValue(js, argv[0]);
|
|
cpSpaceEachShape(space, each_shape_callback, &pass);
|
|
JS_FreeValue(js, pass.fn);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static void each_constraint_callback(cpConstraint *constraint, void *data) {
|
|
ctxfn *pass = (ctxfn*)data;
|
|
JSValue arg = cpConstraint2js(pass->js, constraint);
|
|
JS_Call(pass->js, pass->fn, JS_UNDEFINED, 1, &arg);
|
|
JS_FreeValue(pass->js, arg);
|
|
}
|
|
|
|
static JSValue js_space_each_constraint(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if (!space) return JS_EXCEPTION;
|
|
if (!JS_IsFunction(js, argv[0])) {
|
|
return JS_ThrowTypeError(js, "Expected a function");
|
|
}
|
|
ctxfn pass;
|
|
pass.js = js;
|
|
pass.fn = JS_DupValue(js, argv[0]);
|
|
cpSpaceEachConstraint(space, each_constraint_callback, &pass);
|
|
JS_FreeValue(js, pass.fn);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_space_step (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if (!space) return JS_EXCEPTION;
|
|
cpSpaceStep(space, js2number(js, argv[0]));
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_cpSpace_add_body (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if (!space) return JS_ThrowReferenceError(js, "Not a space.");
|
|
|
|
cpBody *body = cpBodyNew(1,1);
|
|
cpBodySetType(body, CP_BODY_TYPE_DYNAMIC);
|
|
|
|
JSValue obj = JS_NewObjectClass(js, js_cpBody_class_id);
|
|
JS_SetOpaque(obj, body);
|
|
|
|
JSValue *cb = malloc(sizeof(*cb));
|
|
*cb = obj;//JS_DupValue(js,obj);
|
|
cpBodySetUserData(body, cb);
|
|
printf("adding body to space %p\n", space);
|
|
cpSpaceAddBody(space, body);
|
|
printf("finished adding body at %p\n", body);
|
|
return obj;
|
|
}
|
|
|
|
// CP Body GET/SET
|
|
#define JS_GETSET_BODY(NAME, TYPE) \
|
|
static JSValue js_body_set_##NAME (JSContext *js, JSValueConst this_val, JSValue val) { \
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION; \
|
|
cpBodySet##NAME(body, js2##TYPE(js, val)); \
|
|
return JS_UNDEFINED; \
|
|
} \
|
|
static JSValue js_body_get_##NAME (JSContext *js, JSValueConst this_val) { \
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION; \
|
|
return TYPE##2js(js, cpBodyGet##NAME(body)); \
|
|
}
|
|
|
|
// Body properties
|
|
JS_GETSET_BODY(Position, cpvect)
|
|
JS_GETSET_BODY(Angle, angle)
|
|
JS_GETSET_BODY(Velocity, cpvect)
|
|
JS_GETSET_BODY(AngularVelocity, angle)
|
|
JS_GETSET_BODY(Moment, number)
|
|
JS_GETSET_BODY(Torque, number)
|
|
JS_GETSET_BODY(Mass, number)
|
|
JS_GETSET_BODY(CenterOfGravity, cpvect)
|
|
JS_GETSET_BODY(Force, cpvect)
|
|
JS_GETSET_BODY(Type, number)
|
|
|
|
// Body methods
|
|
static JSValue js_body_apply_force_at_world_point(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpVect force = js2cpvect(js, argv[0]);
|
|
cpVect point = js2cpvect(js, argv[1]);
|
|
cpBodyApplyForceAtWorldPoint(body, force, point);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_apply_force_at_local_point(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpVect force = js2cpvect(js, argv[0]);
|
|
cpVect point = js2cpvect(js, argv[1]);
|
|
cpBodyApplyForceAtLocalPoint(body, force, point);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_apply_impulse_at_world_point(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpVect impulse = js2cpvect(js, argv[0]);
|
|
cpVect point = js2cpvect(js, argv[1]);
|
|
cpBodyApplyImpulseAtWorldPoint(body, impulse, point);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_apply_impulse_at_local_point(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpVect impulse = js2cpvect(js, argv[0]);
|
|
cpVect point = js2cpvect(js, argv[1]);
|
|
cpBodyApplyImpulseAtLocalPoint(body, impulse, point);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_is_sleeping(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
return JS_NewBool(js, cpBodyIsSleeping(body));
|
|
}
|
|
|
|
static JSValue js_body_activate(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpBodyActivate(body);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_sleep(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpBodySleep(body);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_activate_static(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpShape *filter = JS_IsUndefined(argv[0]) ? NULL : JS_GetOpaque(argv[0], js_cpShape_class_id);
|
|
cpBodyActivateStatic(body, filter);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_sleep_with_group(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpBody *group = js2cpBody(js, argv[0]); if (!group) return JS_EXCEPTION;
|
|
cpBodySleepWithGroup(body, group);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
// Iteration over shapes, constraints, arbiters
|
|
static void body_shape_fn(cpBody *body, cpShape *shape, void *data) {
|
|
ctxfn *pass = data;
|
|
JSValue v = cpShape2js(pass->js, shape);
|
|
JS_Call(pass->js, pass->fn, JS_UNDEFINED, 1, &v);
|
|
JS_FreeValue(pass->js, v);
|
|
}
|
|
|
|
static JSValue js_body_each_shape(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
if (!JS_IsFunction(js, argv[0])) return JS_ThrowTypeError(js, "Expected a function");
|
|
ctxfn pass;
|
|
pass.js = js;
|
|
pass.fn = JS_DupValue(js, argv[0]);
|
|
cpBodyEachShape(body, body_shape_fn, &pass);
|
|
JS_FreeValue(js, pass.fn);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static void body_constraint_fn(cpBody *body, cpConstraint *constraint, void *data) {
|
|
ctxfn *pass = data;
|
|
JSValue v = cpConstraint2js(pass->js, constraint);
|
|
JS_Call(pass->js, pass->fn, JS_UNDEFINED, 1, &v);
|
|
JS_FreeValue(pass->js, v);
|
|
}
|
|
|
|
static JSValue js_body_each_constraint(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
if (!JS_IsFunction(js, argv[0])) return JS_ThrowTypeError(js, "Expected a function");
|
|
ctxfn pass;
|
|
pass.js = js;
|
|
pass.fn = JS_DupValue(js, argv[0]);
|
|
cpBodyEachConstraint(body, body_constraint_fn, &pass);
|
|
JS_FreeValue(js, pass.fn);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static void body_arbiter_fn(cpBody *body, cpArbiter *arbiter, ctxfn *pass) {
|
|
// Not fully implemented
|
|
}
|
|
|
|
static JSValue js_body_each_arbiter(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
// Not fully implemented
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_body_add_circle_shape(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val);
|
|
if (!body) return JS_ThrowReferenceError(js, "Shape must be added to a body.");
|
|
|
|
cpSpace *space = cpBodyGetSpace(body);
|
|
printf("adding circle shape to space %p\n", space);
|
|
|
|
double radius = 10;
|
|
cpVect offset = {0,0};
|
|
if (argc > 0 && JS_IsObject(argv[0])) {
|
|
JSValue r = JS_GetPropertyStr(js, argv[0], "radius");
|
|
if (!JS_IsUndefined(r)) radius = js2number(js, r);
|
|
JS_FreeValue(js, r);
|
|
|
|
printf("RADIUS IS %g\n", radius);
|
|
|
|
JSValue o = JS_GetPropertyStr(js, argv[0], "offset");
|
|
if (!JS_IsUndefined(o)) offset = js2cpvect(js, o);
|
|
JS_FreeValue(js, o);
|
|
}
|
|
|
|
cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, offset));
|
|
|
|
JSValue obj = JS_NewObjectClass(js, js_cpShape_class_id);
|
|
JS_SetOpaque(obj, shape);
|
|
JS_SetPrototype(js, obj, circle_proto);
|
|
|
|
JSValue *cb = malloc(sizeof(*cb));
|
|
*cb = obj;//JS_DupValue(js,obj);
|
|
cpShapeSetUserData(shape, cb);
|
|
|
|
printf("MADE CIRCLE SHAPE\n");
|
|
|
|
return obj;
|
|
}
|
|
|
|
static JSValue js_body_add_segment_shape(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
cpVect a = js2cpvect(js, argv[0]);
|
|
cpVect b = js2cpvect(js, argv[1]);
|
|
double radius = js2number(js, argv[2]);
|
|
cpShape *shape = cpSegmentShapeNew(body, a, b, (cpFloat)radius);
|
|
|
|
JSValue obj = JS_NewObjectClass(js, js_cpShape_class_id);
|
|
JS_SetOpaque(obj, shape);
|
|
JS_SetPrototype(js, obj, segment_proto);
|
|
|
|
JSValue *cb = malloc(sizeof(*cb));
|
|
*cb = obj;//JS_DupValue(js,obj);
|
|
cpShapeSetUserData(shape, cb);
|
|
|
|
return obj;
|
|
}
|
|
|
|
static JSValue js_body_add_poly_shape(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpBody *body = js2cpBody(js, this_val); if (!body) return JS_EXCEPTION;
|
|
int count = (int)js2number(js, argv[0]);
|
|
// The actual verts array is not fully handled here. Just a placeholder for demonstration.
|
|
cpVect verts[1] = {{0,0}};
|
|
cpTransform T = cpTransformIdentity;
|
|
|
|
cpShape *shape = cpPolyShapeNew(body, count, verts, T, 0.0);
|
|
JSValue obj = JS_NewObjectClass(js, js_cpShape_class_id);
|
|
JS_SetOpaque(obj, shape);
|
|
JS_SetPrototype(js, obj, poly_proto);
|
|
|
|
JSValue *cb = malloc(sizeof(*cb));
|
|
*cb = JS_DupValue(js,obj);
|
|
cpShapeSetUserData(shape, cb);
|
|
|
|
return obj;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cpBody_funcs[] = {
|
|
JS_CGETSET_DEF("position", js_body_get_Position, js_body_set_Position),
|
|
JS_CGETSET_DEF("angle", js_body_get_Angle, js_body_set_Angle),
|
|
JS_CGETSET_DEF("velocity", js_body_get_Velocity, js_body_set_Velocity),
|
|
JS_CGETSET_DEF("angularVelocity", js_body_get_AngularVelocity, js_body_set_AngularVelocity),
|
|
JS_CGETSET_DEF("moment", js_body_get_Moment, js_body_set_Moment),
|
|
JS_CGETSET_DEF("torque", js_body_get_Torque, js_body_set_Torque),
|
|
JS_CGETSET_DEF("mass", js_body_get_Mass, js_body_set_Mass),
|
|
JS_CGETSET_DEF("centerOfGravity", js_body_get_CenterOfGravity, js_body_set_CenterOfGravity),
|
|
JS_CGETSET_DEF("force", js_body_get_Force, js_body_set_Force),
|
|
JS_CGETSET_DEF("type", js_body_get_Type, js_body_set_Type),
|
|
JS_CFUNC_DEF("isSleeping", 0, js_body_is_sleeping),
|
|
JS_CFUNC_DEF("activate", 0, js_body_activate),
|
|
JS_CFUNC_DEF("sleep", 0, js_body_sleep),
|
|
JS_CFUNC_DEF("activateStatic", 1, js_body_activate_static),
|
|
JS_CFUNC_DEF("sleepWithGroup", 1, js_body_sleep_with_group),
|
|
JS_CFUNC_DEF("applyForceAtWorldPoint", 2, js_body_apply_force_at_world_point),
|
|
JS_CFUNC_DEF("applyForceAtLocalPoint", 2, js_body_apply_force_at_local_point),
|
|
JS_CFUNC_DEF("applyImpulseAtWorldPoint", 2, js_body_apply_impulse_at_world_point),
|
|
JS_CFUNC_DEF("applyImpulseAtLocalPoint", 2, js_body_apply_impulse_at_local_point),
|
|
JS_CFUNC_DEF("eachShape", 1, js_body_each_shape),
|
|
JS_CFUNC_DEF("eachConstraint", 1, js_body_each_constraint),
|
|
JS_CFUNC_DEF("eachArbiter", 1, js_body_each_arbiter),
|
|
JS_CFUNC_DEF("circle", 1, js_body_add_circle_shape),
|
|
JS_CFUNC_DEF("segment", 1, js_body_add_segment_shape),
|
|
JS_CFUNC_DEF("poly", 1, js_body_add_poly_shape),
|
|
};
|
|
|
|
// Shape-specific get/set
|
|
|
|
#define SHAPE_GETSET(SHAPE, ENTRY, TYPE) \
|
|
static JSValue js_##SHAPE##_set_##ENTRY (JSContext *js, JSValueConst this_val, JSValue val) { \
|
|
cpShape *shape = js2cpShape(js, this_val); \
|
|
if (!shape) return JS_EXCEPTION; \
|
|
SHAPE##Set##ENTRY(shape, js2##TYPE(js, val)); \
|
|
return JS_UNDEFINED; \
|
|
} \
|
|
static JSValue js_##SHAPE##_get_##ENTRY (JSContext *js, JSValueConst this_val) { \
|
|
cpShape *shape = js2cpShape(js, this_val); \
|
|
if (!shape) return JS_EXCEPTION; \
|
|
return TYPE##2js(js, SHAPE##Get##ENTRY(shape)); \
|
|
}
|
|
|
|
// Circle
|
|
SHAPE_GETSET(cpCircleShape, Radius, number)
|
|
SHAPE_GETSET(cpCircleShape, Offset, cpvect)
|
|
|
|
static const JSCFunctionListEntry js_cpCircleShape_funcs[] = {
|
|
JS_CGETSET_DEF("radius", js_cpCircleShape_get_Radius, js_cpCircleShape_set_Radius),
|
|
JS_CGETSET_DEF("offset", js_cpCircleShape_get_Offset, js_cpCircleShape_set_Offset),
|
|
};
|
|
|
|
// Segment
|
|
SHAPE_GETSET(cpSegmentShape, Radius, number)
|
|
|
|
static JSValue js_cpSegmentShape_set_endpoints(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpShape *shape = js2cpShape(js, this_val);
|
|
if (!shape) return JS_EXCEPTION;
|
|
cpSegmentShapeSetEndpoints(shape, js2cpvect(js, argv[0]), js2cpvect(js, argv[1]));
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cpSegmentShape_funcs[] = {
|
|
JS_CFUNC_DEF("setEndpoints", 2, js_cpSegmentShape_set_endpoints),
|
|
JS_CGETSET_DEF("radius", js_cpSegmentShape_get_Radius, js_cpSegmentShape_set_Radius),
|
|
};
|
|
|
|
// Poly
|
|
SHAPE_GETSET(cpPolyShape, Radius, number)
|
|
|
|
static JSValue js_cpPolyShape_set_verts(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpShape *shape = js2cpShape(js, this_val);
|
|
if (!shape) return JS_EXCEPTION;
|
|
int count = (int)js2number(js, argv[0]);
|
|
// Not fully implemented
|
|
cpVect verts[1] = {{0,0}};
|
|
cpPolyShapeSetVerts(shape, count, verts, cpTransformIdentity);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cpPolyShape_funcs[] = {
|
|
JS_CFUNC_DEF("setVerts", 2, js_cpPolyShape_set_verts),
|
|
JS_CGETSET_DEF("radius", js_cpPolyShape_get_Radius, js_cpPolyShape_set_Radius),
|
|
};
|
|
|
|
// Generic shape fields
|
|
static JSValue js_shape_set_filter(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpShapeFilter filter;
|
|
JSValue categories = JS_GetPropertyStr(js, val, "categories");
|
|
JSValue mask = JS_GetPropertyStr(js, val, "mask");
|
|
JSValue group = JS_GetPropertyStr(js, val, "group");
|
|
filter.categories = (uint32_t)js2number(js, categories);
|
|
filter.mask = (uint32_t)js2number(js, mask);
|
|
filter.group = (uint32_t)js2number(js, group);
|
|
JS_FreeValue(js, categories);
|
|
JS_FreeValue(js, mask);
|
|
JS_FreeValue(js, group);
|
|
cpShapeSetFilter(shape, filter);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_set_sensor(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpShapeSetSensor(shape, JS_ToBool(js, val));
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_get_sensor(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
return JS_NewBool(js, cpShapeGetSensor(shape));
|
|
}
|
|
|
|
static JSValue js_shape_set_elasticity(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpShapeSetElasticity(shape, js2number(js, val));
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_get_elasticity(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
return number2js(js, cpShapeGetElasticity(shape));
|
|
}
|
|
|
|
static JSValue js_shape_set_friction(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpShapeSetFriction(shape, js2number(js, val));
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_get_friction(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
return number2js(js, cpShapeGetFriction(shape));
|
|
}
|
|
|
|
static JSValue js_shape_set_surface_velocity(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpVect velocity = js2cpvect(js, val);
|
|
cpShapeSetSurfaceVelocity(shape, velocity);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_get_surface_velocity(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
return cpvect2js(js, cpShapeGetSurfaceVelocity(shape));
|
|
}
|
|
|
|
static JSValue js_shape_get_collision_type(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
return JS_NewInt32(js, cpShapeGetCollisionType(shape));
|
|
}
|
|
|
|
static JSValue js_shape_set_collision_type(JSContext *js, JSValueConst this_val, JSValue val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
int32_t collision_type;
|
|
if (JS_ToInt32(js, &collision_type, val)) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
cpShapeSetCollisionType(shape, collision_type);
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_shape_get_bb(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpBB bb = cpShapeGetBB(shape);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "x", JS_NewFloat64(js, bb.l));
|
|
JS_SetPropertyStr(js, obj, "y", JS_NewFloat64(js, bb.b));
|
|
JS_SetPropertyStr(js, obj, "width", JS_NewFloat64(js, bb.r - bb.l));
|
|
JS_SetPropertyStr(js, obj, "height", JS_NewFloat64(js, bb.t - bb.b));
|
|
return obj;
|
|
}
|
|
|
|
static JSValue js_shape_get_filter(JSContext *js, JSValueConst this_val) {
|
|
cpShape *shape = js2cpShape(js, this_val); if (!shape) return JS_EXCEPTION;
|
|
cpShapeFilter filter = cpShapeGetFilter(shape);
|
|
JSValue obj = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, obj, "categories", JS_NewUint32(js, filter.categories));
|
|
JS_SetPropertyStr(js, obj, "mask", JS_NewUint32(js, filter.mask));
|
|
JS_SetPropertyStr(js, obj, "group", JS_NewUint32(js, filter.group));
|
|
return obj;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cpShape_funcs[] = {
|
|
JS_CGETSET_DEF("collisionType", js_shape_get_collision_type, js_shape_set_collision_type),
|
|
JS_CFUNC_DEF("getBB", 0, js_shape_get_bb),
|
|
JS_CGETSET_DEF("sensor", js_shape_get_sensor, js_shape_set_sensor),
|
|
JS_CGETSET_DEF("elasticity", js_shape_get_elasticity, js_shape_set_elasticity),
|
|
JS_CGETSET_DEF("friction", js_shape_get_friction, js_shape_set_friction),
|
|
JS_CGETSET_DEF("surfaceVelocity", js_shape_get_surface_velocity, js_shape_set_surface_velocity),
|
|
JS_CGETSET_DEF("filter", js_shape_get_filter, js_shape_set_filter)
|
|
};
|
|
|
|
// Constraints
|
|
|
|
#define CC_GETSET(CPTYPE, ENTRY, TYPE) \
|
|
static JSValue js_##CPTYPE##_get_##ENTRY (JSContext *js, JSValueConst this_val) { \
|
|
return TYPE##2js(js, CPTYPE##Get##ENTRY(js2cpConstraint(js, this_val))); \
|
|
} \
|
|
static JSValue js_##CPTYPE##_set_##ENTRY (JSContext *js, JSValueConst this_val, JSValue val) { \
|
|
CPTYPE##Set##ENTRY(js2cpConstraint(js, this_val), js2##TYPE(js, val)); \
|
|
return JS_UNDEFINED; \
|
|
}
|
|
|
|
CC_GETSET(cpConstraint, MaxForce, number)
|
|
CC_GETSET(cpConstraint, MaxBias, number)
|
|
CC_GETSET(cpConstraint, ErrorBias, number)
|
|
CC_GETSET(cpConstraint, CollideBodies, number)
|
|
|
|
static JSValue js_cpConstraint_broken (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
// We'll just return whether the constraint is still in the space or not
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if(!space) return JS_EXCEPTION;
|
|
cpConstraint *constraint = js2cpConstraint(js, argv[0]);
|
|
if(!constraint) return JS_FALSE;
|
|
cpBool inSpace = cpSpaceContainsConstraint(space, constraint);
|
|
return JS_NewBool(js, inSpace);
|
|
}
|
|
|
|
static JSValue js_cpConstraint_break (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
cpSpace *space = js2cpSpace(js, this_val);
|
|
if(!space) return JS_EXCEPTION;
|
|
cpConstraint *constraint = js2cpConstraint(js, argv[0]);
|
|
if(!constraint) return JS_UNDEFINED;
|
|
if(cpSpaceContainsConstraint(space, constraint)) {
|
|
cpSpaceRemoveConstraint(space, constraint);
|
|
}
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue js_cpConstraint_bodyA (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
cpBody *b = cpConstraintGetBodyA(js2cpConstraint(js, this_val));
|
|
return cpBody2js(js, b);
|
|
}
|
|
|
|
static JSValue js_cpConstraint_bodyB (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
cpBody *b = cpConstraintGetBodyB(js2cpConstraint(js, this_val));
|
|
return cpBody2js(js, b);
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cpConstraint_funcs[] = {
|
|
JS_CFUNC_DEF("bodyA", 0, js_cpConstraint_bodyA),
|
|
JS_CFUNC_DEF("bodyB", 0, js_cpConstraint_bodyB),
|
|
JS_CGETSET_DEF("max_force", js_cpConstraint_get_MaxForce, js_cpConstraint_set_MaxForce),
|
|
JS_CGETSET_DEF("max_bias", js_cpConstraint_get_MaxBias, js_cpConstraint_set_MaxBias),
|
|
JS_CGETSET_DEF("error_bias", js_cpConstraint_get_ErrorBias, js_cpConstraint_set_ErrorBias),
|
|
JS_CGETSET_DEF("collide_bodies", js_cpConstraint_get_CollideBodies, js_cpConstraint_set_CollideBodies),
|
|
JS_CFUNC_DEF("broken", 0, js_cpConstraint_broken),
|
|
JS_CFUNC_DEF("break", 0, js_cpConstraint_break),
|
|
};
|
|
|
|
static JSValue prep_constraint(JSContext *js, cpConstraint *c)
|
|
{
|
|
// Create a brand-new JS object of the cpConstraint class
|
|
JSValue ret = JS_NewObjectClass(js, js_cpConstraint_class_id);
|
|
// Attach the actual cpConstraint pointer
|
|
JS_SetOpaque(ret, c);
|
|
|
|
// Allocate space for the back-reference
|
|
JSValue *cb = malloc(sizeof(JSValue));
|
|
*cb = JS_DupValue(js,ret);
|
|
cpConstraintSetUserData(c, cb);
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Pin joint
|
|
CC_GETSET(cpPinJoint, Dist, number)
|
|
CC_GETSET(cpPinJoint, AnchorA, cpvect)
|
|
CC_GETSET(cpPinJoint, AnchorB, cpvect)
|
|
|
|
static const JSCFunctionListEntry js_pin_funcs[] = {
|
|
JS_CGETSET_DEF("distance", js_cpPinJoint_get_Dist, js_cpPinJoint_set_Dist),
|
|
JS_CGETSET_DEF("anchor_a", js_cpPinJoint_get_AnchorA, js_cpPinJoint_set_AnchorA),
|
|
JS_CGETSET_DEF("anchor_b", js_cpPinJoint_get_AnchorB, js_cpPinJoint_set_AnchorB)
|
|
};
|
|
|
|
static JSValue js_joint_pin (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
// If called with no arguments, return the prototype object
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_pin);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
cpConstraint *c = cpPinJointNew(bA, bB, cpvzero, cpvzero);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue pin = prep_constraint(js, c);
|
|
JS_SetPrototype(js, pin, js_pin);
|
|
return pin;
|
|
}
|
|
|
|
// Pivot joint
|
|
CC_GETSET(cpPivotJoint, AnchorA, cpvect)
|
|
CC_GETSET(cpPivotJoint, AnchorB, cpvect)
|
|
|
|
static const JSCFunctionListEntry js_pivot_funcs[] = {
|
|
JS_CGETSET_DEF("anchor_a", js_cpPivotJoint_get_AnchorA, js_cpPivotJoint_set_AnchorA),
|
|
JS_CGETSET_DEF("anchor_b", js_cpPivotJoint_get_AnchorB, js_cpPivotJoint_set_AnchorB)
|
|
};
|
|
|
|
static JSValue js_joint_pivot (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_pivot);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
cpVect pivotPoint = js2cpvect(js, argv[2]);
|
|
cpConstraint *c = cpPivotJointNew(bA, bB, pivotPoint);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue pivot = prep_constraint(js, c);
|
|
JS_SetPrototype(js, pivot, js_pivot);
|
|
return pivot;
|
|
}
|
|
|
|
// Gear joint
|
|
CC_GETSET(cpGearJoint, Phase, number)
|
|
CC_GETSET(cpGearJoint, Ratio, number)
|
|
|
|
static const JSCFunctionListEntry js_gear_funcs[] = {
|
|
JS_CGETSET_DEF("phase", js_cpGearJoint_get_Phase, js_cpGearJoint_set_Phase),
|
|
JS_CGETSET_DEF("ratio", js_cpGearJoint_get_Ratio, js_cpGearJoint_set_Ratio),
|
|
};
|
|
|
|
static JSValue js_joint_gear (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_gear);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
double phase = js2number(js, argv[2]);
|
|
double ratio = js2number(js, argv[3]);
|
|
cpConstraint *c = cpGearJointNew(bA, bB, (cpFloat)phase, (cpFloat)ratio);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue gear = prep_constraint(js, c);
|
|
JS_SetPrototype(js, gear, js_gear);
|
|
return gear;
|
|
}
|
|
|
|
// Rotary limit joint
|
|
CC_GETSET(cpRotaryLimitJoint, Min, number)
|
|
CC_GETSET(cpRotaryLimitJoint, Max, number)
|
|
|
|
static const JSCFunctionListEntry js_rotary_funcs[] = {
|
|
JS_CGETSET_DEF("min", js_cpRotaryLimitJoint_get_Min, js_cpRotaryLimitJoint_set_Min),
|
|
JS_CGETSET_DEF("max", js_cpRotaryLimitJoint_get_Max, js_cpRotaryLimitJoint_set_Max),
|
|
};
|
|
|
|
static JSValue js_joint_rotary (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_rotary);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
double min_ = js2number(js, argv[2]);
|
|
double max_ = js2number(js, argv[3]);
|
|
cpConstraint *c = cpRotaryLimitJointNew(bA, bB, (cpFloat)min_, (cpFloat)max_);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue rotary = prep_constraint(js, c);
|
|
JS_SetPrototype(js, rotary, js_rotary);
|
|
return rotary;
|
|
}
|
|
|
|
// Damped Rotary Spring
|
|
CC_GETSET(cpDampedRotarySpring, RestAngle, number)
|
|
CC_GETSET(cpDampedRotarySpring, Stiffness, number)
|
|
CC_GETSET(cpDampedRotarySpring, Damping, number)
|
|
|
|
static const JSCFunctionListEntry js_damped_rotary_funcs[] = {
|
|
JS_CGETSET_DEF("rest_angle", js_cpDampedRotarySpring_get_RestAngle, js_cpDampedRotarySpring_set_RestAngle),
|
|
JS_CGETSET_DEF("stiffness", js_cpDampedRotarySpring_get_Stiffness, js_cpDampedRotarySpring_set_Stiffness),
|
|
JS_CGETSET_DEF("damping", js_cpDampedRotarySpring_get_Damping, js_cpDampedRotarySpring_set_Damping),
|
|
};
|
|
|
|
static JSValue js_joint_damped_rotary (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_damped_rotary);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
double rest = js2number(js, argv[2]);
|
|
double stiffness = js2number(js, argv[3]);
|
|
double damping = js2number(js, argv[4]);
|
|
cpConstraint *c = cpDampedRotarySpringNew(bA, bB, (cpFloat)rest, (cpFloat)stiffness, (cpFloat)damping);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue dr = prep_constraint(js, c);
|
|
JS_SetPrototype(js, dr, js_damped_rotary);
|
|
return dr;
|
|
}
|
|
|
|
// Damped Spring
|
|
CC_GETSET(cpDampedSpring, AnchorA, cpvect)
|
|
CC_GETSET(cpDampedSpring, AnchorB, cpvect)
|
|
CC_GETSET(cpDampedSpring, RestLength, number)
|
|
CC_GETSET(cpDampedSpring, Stiffness, number)
|
|
CC_GETSET(cpDampedSpring, Damping, number)
|
|
|
|
static const JSCFunctionListEntry js_damped_spring_funcs[] = {
|
|
JS_CGETSET_DEF("anchor_a", js_cpDampedSpring_get_AnchorA, js_cpDampedSpring_set_AnchorA),
|
|
JS_CGETSET_DEF("anchor_b", js_cpDampedSpring_get_AnchorB, js_cpDampedSpring_set_AnchorB),
|
|
JS_CGETSET_DEF("rest_length",js_cpDampedSpring_get_RestLength,js_cpDampedSpring_set_RestLength),
|
|
JS_CGETSET_DEF("stiffness", js_cpDampedSpring_get_Stiffness, js_cpDampedSpring_set_Stiffness),
|
|
JS_CGETSET_DEF("damping", js_cpDampedSpring_get_Damping, js_cpDampedSpring_set_Damping),
|
|
};
|
|
|
|
static JSValue js_joint_damped_spring (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_damped_spring);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
cpVect aA = js2cpvect(js, argv[2]);
|
|
cpVect aB = js2cpvect(js, argv[3]);
|
|
double restLength = js2number(js, argv[4]);
|
|
double stiffness = js2number(js, argv[5]);
|
|
double damping = js2number(js, argv[6]);
|
|
cpConstraint *c = cpDampedSpringNew(bA, bB, aA, aB, (cpFloat)restLength, (cpFloat)stiffness, (cpFloat)damping);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue ds = prep_constraint(js, c);
|
|
JS_SetPrototype(js, ds, js_damped_spring);
|
|
return ds;
|
|
}
|
|
|
|
// Groove joint
|
|
CC_GETSET(cpGrooveJoint, GrooveA, cpvect)
|
|
CC_GETSET(cpGrooveJoint, GrooveB, cpvect)
|
|
CC_GETSET(cpGrooveJoint, AnchorB, cpvect)
|
|
|
|
static const JSCFunctionListEntry js_groove_funcs[] = {
|
|
JS_CGETSET_DEF("groove_a", js_cpGrooveJoint_get_GrooveA, js_cpGrooveJoint_set_GrooveA),
|
|
JS_CGETSET_DEF("groove_b", js_cpGrooveJoint_get_GrooveB, js_cpGrooveJoint_set_GrooveB),
|
|
JS_CGETSET_DEF("anchor_b", js_cpGrooveJoint_get_AnchorB, js_cpGrooveJoint_set_AnchorB),
|
|
};
|
|
|
|
static JSValue js_joint_groove (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_groove);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
cpVect ga = js2cpvect(js, argv[2]);
|
|
cpVect gb = js2cpvect(js, argv[3]);
|
|
cpVect ab = js2cpvect(js, argv[4]);
|
|
cpConstraint *c = cpGrooveJointNew(bA, bB, ga, gb, ab);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue gz = prep_constraint(js, c);
|
|
JS_SetPrototype(js, gz, js_groove);
|
|
return gz;
|
|
}
|
|
|
|
// Slide joint
|
|
CC_GETSET(cpSlideJoint, AnchorA, cpvect)
|
|
CC_GETSET(cpSlideJoint, AnchorB, cpvect)
|
|
CC_GETSET(cpSlideJoint, Min, number)
|
|
CC_GETSET(cpSlideJoint, Max, number)
|
|
|
|
static const JSCFunctionListEntry js_slide_funcs[] = {
|
|
JS_CGETSET_DEF("anchor_a", js_cpSlideJoint_get_AnchorA, js_cpSlideJoint_set_AnchorA),
|
|
JS_CGETSET_DEF("anchor_b", js_cpSlideJoint_get_AnchorB, js_cpSlideJoint_set_AnchorB),
|
|
JS_CGETSET_DEF("min", js_cpSlideJoint_get_Min, js_cpSlideJoint_set_Min),
|
|
JS_CGETSET_DEF("max", js_cpSlideJoint_get_Max, js_cpSlideJoint_set_Max),
|
|
};
|
|
|
|
static JSValue js_joint_slide (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_slide);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
cpVect aA = js2cpvect(js, argv[2]);
|
|
cpVect aB = js2cpvect(js, argv[3]);
|
|
double min_ = js2number(js, argv[4]);
|
|
double max_ = js2number(js, argv[5]);
|
|
cpConstraint *c = cpSlideJointNew(bA, bB, aA, aB, (cpFloat)min_, (cpFloat)max_);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue sld = prep_constraint(js, c);
|
|
JS_SetPrototype(js, sld, js_slide);
|
|
return sld;
|
|
}
|
|
|
|
// Ratchet joint
|
|
CC_GETSET(cpRatchetJoint, Angle, number)
|
|
CC_GETSET(cpRatchetJoint, Phase, number)
|
|
CC_GETSET(cpRatchetJoint, Ratchet, number)
|
|
|
|
static const JSCFunctionListEntry js_ratchet_funcs[] = {
|
|
JS_CGETSET_DEF("angle", js_cpRatchetJoint_get_Angle, js_cpRatchetJoint_set_Angle),
|
|
JS_CGETSET_DEF("phase", js_cpRatchetJoint_get_Phase, js_cpRatchetJoint_set_Phase),
|
|
JS_CGETSET_DEF("ratchet", js_cpRatchetJoint_get_Ratchet, js_cpRatchetJoint_set_Ratchet),
|
|
};
|
|
|
|
static JSValue js_joint_ratchet (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_ratchet);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
double phase = js2number(js, argv[2]);
|
|
double rat = js2number(js, argv[3]);
|
|
cpConstraint *c = cpRatchetJointNew(bA, bB, (cpFloat)phase, (cpFloat)rat);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue r = prep_constraint(js, c);
|
|
JS_SetPrototype(js, r, js_ratchet);
|
|
return r;
|
|
}
|
|
|
|
// Simple motor
|
|
CC_GETSET(cpSimpleMotor, Rate, number)
|
|
|
|
static const JSCFunctionListEntry js_motor_funcs[] = {
|
|
JS_CGETSET_DEF("rate", js_cpSimpleMotor_get_Rate, js_cpSimpleMotor_set_Rate),
|
|
};
|
|
|
|
static JSValue js_joint_motor (JSContext *js, JSValueConst this_val, int argc, JSValue *argv) {
|
|
if (JS_IsUndefined(argv[0])) {
|
|
return JS_DupValue(js, js_motor);
|
|
}
|
|
cpBody *bA = js2cpBody(js, argv[0]);
|
|
cpBody *bB = js2cpBody(js, argv[1]);
|
|
double rate = js2number(js, argv[2]);
|
|
cpConstraint *c = cpSimpleMotorNew(bA, bB, (cpFloat)rate);
|
|
cpSpaceAddConstraint(js2cpSpace(js, this_val), c);
|
|
|
|
JSValue m = prep_constraint(js, c);
|
|
JS_SetPrototype(js, m, js_motor);
|
|
return m;
|
|
}
|
|
|
|
// Space methods
|
|
static const JSCFunctionListEntry js_cpSpace_funcs[] = {
|
|
JS_CFUNC_DEF("body", 0, js_cpSpace_add_body),
|
|
JS_CFUNC_DEF("step", 1, js_space_step),
|
|
JS_CGETSET_DEF("gravity", js_cpSpace_get_Gravity, js_cpSpace_set_Gravity),
|
|
JS_CGETSET_DEF("iterations", js_cpSpace_get_Iterations, js_cpSpace_set_Iterations),
|
|
JS_CFUNC_DEF("eachBody", 1, js_space_each_body),
|
|
JS_CFUNC_DEF("eachShape", 1, js_space_each_shape),
|
|
JS_CFUNC_DEF("eachConstraint", 1, js_space_each_constraint),
|
|
JS_CGETSET_DEF("idle_speed", js_cpSpace_get_IdleSpeedThreshold, js_cpSpace_set_IdleSpeedThreshold),
|
|
JS_CGETSET_DEF("sleep_time", js_cpSpace_get_SleepTimeThreshold, js_cpSpace_set_SleepTimeThreshold),
|
|
JS_CGETSET_DEF("collision_slop", js_cpSpace_get_CollisionSlop, js_cpSpace_set_CollisionSlop),
|
|
JS_CGETSET_DEF("collision_bias", js_cpSpace_get_CollisionBias, js_cpSpace_set_CollisionBias),
|
|
JS_CGETSET_DEF("collision_persistence", js_cpSpace_get_CollisionPersistence, js_cpSpace_set_CollisionPersistence),
|
|
// Joint creation
|
|
JS_CFUNC_DEF("pin", 2, js_joint_pin),
|
|
JS_CFUNC_DEF("pivot", 3, js_joint_pivot),
|
|
JS_CFUNC_DEF("gear", 4, js_joint_gear),
|
|
JS_CFUNC_DEF("rotary", 4, js_joint_rotary),
|
|
JS_CFUNC_DEF("damped_rotary", 5, js_joint_damped_rotary),
|
|
JS_CFUNC_DEF("damped_spring", 7, js_joint_damped_spring),
|
|
JS_CFUNC_DEF("groove", 5, js_joint_groove),
|
|
JS_CFUNC_DEF("slide", 6, js_joint_slide),
|
|
JS_CFUNC_DEF("ratchet", 4, js_joint_ratchet),
|
|
JS_CFUNC_DEF("motor", 3, js_joint_motor),
|
|
};
|
|
|
|
// qjs_chipmunk.c - updated
|
|
JSValue js_chipmunk2d_use(JSContext *js) {
|
|
// Register cpSpace class
|
|
JS_NewClassID(&js_cpSpace_class_id);
|
|
JS_NewClass(JS_GetRuntime(js), js_cpSpace_class_id, &js_cpSpace_class);
|
|
JSValue space_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, space_proto, js_cpSpace_funcs, countof(js_cpSpace_funcs));
|
|
JS_SetClassProto(js, js_cpSpace_class_id, space_proto);
|
|
|
|
// Register cpBody class
|
|
JS_NewClassID(&js_cpBody_class_id);
|
|
JS_NewClass(JS_GetRuntime(js), js_cpBody_class_id, &js_cpBody_class);
|
|
JSValue body_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, body_proto, js_cpBody_funcs, countof(js_cpBody_funcs));
|
|
JS_SetClassProto(js, js_cpBody_class_id, body_proto);
|
|
|
|
// Register cpShape class
|
|
JS_NewClassID(&js_cpShape_class_id);
|
|
JS_NewClass(JS_GetRuntime(js), js_cpShape_class_id, &js_cpShape_class);
|
|
JSValue shape_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, shape_proto, js_cpShape_funcs, countof(js_cpShape_funcs));
|
|
JS_SetClassProto(js, js_cpShape_class_id, shape_proto);
|
|
|
|
// Register cpConstraint class
|
|
JS_NewClassID(&js_cpConstraint_class_id);
|
|
JS_NewClass(JS_GetRuntime(js), js_cpConstraint_class_id, &js_cpConstraint_class);
|
|
JSValue constraint_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, constraint_proto, js_cpConstraint_funcs, countof(js_cpConstraint_funcs));
|
|
JS_SetClassProto(js, js_cpConstraint_class_id, constraint_proto);
|
|
|
|
// --- Shape Subtype Prototypes ---
|
|
JSValue circle_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, circle_proto_local, js_cpCircleShape_funcs, countof(js_cpCircleShape_funcs));
|
|
JS_SetPrototype(js, circle_proto_local, shape_proto);
|
|
|
|
JSValue segment_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, segment_proto_local, js_cpSegmentShape_funcs, countof(js_cpSegmentShape_funcs));
|
|
JS_SetPrototype(js, segment_proto_local, shape_proto);
|
|
|
|
JSValue poly_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, poly_proto_local, js_cpPolyShape_funcs, countof(js_cpPolyShape_funcs));
|
|
JS_SetPrototype(js, poly_proto_local, shape_proto);
|
|
|
|
// Store shape subtypes globally
|
|
circle_proto = JS_DupValue(js, circle_proto_local);
|
|
segment_proto = JS_DupValue(js, segment_proto_local);
|
|
poly_proto = JS_DupValue(js, poly_proto_local);
|
|
|
|
// --- Constraint Subtype Prototypes ---
|
|
JSValue pin_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, pin_proto, js_pin_funcs, countof(js_pin_funcs));
|
|
JS_SetPrototype(js, pin_proto, constraint_proto);
|
|
|
|
JSValue pivot_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, pivot_proto, js_pivot_funcs, countof(js_pivot_funcs));
|
|
JS_SetPrototype(js, pivot_proto, constraint_proto);
|
|
|
|
JSValue gear_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, gear_proto_local, js_gear_funcs, countof(js_gear_funcs));
|
|
JS_SetPrototype(js, gear_proto_local, constraint_proto);
|
|
|
|
JSValue rotary_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, rotary_proto, js_rotary_funcs, countof(js_rotary_funcs));
|
|
JS_SetPrototype(js, rotary_proto, constraint_proto);
|
|
|
|
JSValue motor_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, motor_proto, js_motor_funcs, countof(js_motor_funcs));
|
|
JS_SetPrototype(js, motor_proto, constraint_proto);
|
|
|
|
JSValue damped_rotary_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, damped_rotary_proto, js_damped_rotary_funcs, countof(js_damped_rotary_funcs));
|
|
JS_SetPrototype(js, damped_rotary_proto, constraint_proto);
|
|
|
|
JSValue damped_spring_proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, damped_spring_proto, js_damped_spring_funcs, countof(js_damped_spring_funcs));
|
|
JS_SetPrototype(js, damped_spring_proto, constraint_proto);
|
|
|
|
JSValue groove_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, groove_proto_local, js_groove_funcs, countof(js_groove_funcs));
|
|
JS_SetPrototype(js, groove_proto_local, constraint_proto);
|
|
|
|
JSValue slide_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, slide_proto_local, js_slide_funcs, countof(js_slide_funcs));
|
|
JS_SetPrototype(js, slide_proto_local, constraint_proto);
|
|
|
|
JSValue ratchet_proto_local = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, ratchet_proto_local, js_ratchet_funcs, countof(js_ratchet_funcs));
|
|
JS_SetPrototype(js, ratchet_proto_local, constraint_proto);
|
|
|
|
// Store constraint subtypes globally
|
|
js_pin = JS_DupValue(js, pin_proto);
|
|
js_pivot = JS_DupValue(js, pivot_proto);
|
|
js_gear = JS_DupValue(js, gear_proto_local);
|
|
js_rotary = JS_DupValue(js, rotary_proto);
|
|
js_motor = JS_DupValue(js, motor_proto);
|
|
js_damped_rotary = JS_DupValue(js, damped_rotary_proto);
|
|
js_damped_spring = JS_DupValue(js, damped_spring_proto);
|
|
js_groove = JS_DupValue(js, groove_proto_local);
|
|
js_slide = JS_DupValue(js, slide_proto_local);
|
|
js_ratchet = JS_DupValue(js, ratchet_proto_local);
|
|
|
|
// Store references in prosperon.c_types
|
|
JSValue global = JS_GetGlobalObject(js);
|
|
JSValue prosp = JS_GetPropertyStr(js, global, "prosperon");
|
|
JSValue c_types = JS_GetPropertyStr(js, prosp, "c_types");
|
|
|
|
// Store base types
|
|
JS_SetPropertyStr(js, c_types, "cpSpace", JS_DupValue(js, space_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpBody", JS_DupValue(js, body_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpShape", JS_DupValue(js, shape_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpConstraint", JS_DupValue(js, constraint_proto));
|
|
|
|
// Store shape subtypes
|
|
JS_SetPropertyStr(js, c_types, "cpCircleShape", JS_DupValue(js, circle_proto_local));
|
|
JS_SetPropertyStr(js, c_types, "cpSegmentShape", JS_DupValue(js, segment_proto_local));
|
|
JS_SetPropertyStr(js, c_types, "cpPolyShape", JS_DupValue(js, poly_proto_local));
|
|
|
|
// Store constraint subtypes
|
|
JS_SetPropertyStr(js, c_types, "cpPinJoint", JS_DupValue(js, pin_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpPivotJoint", JS_DupValue(js, pivot_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpGearJoint", JS_DupValue(js, gear_proto_local));
|
|
JS_SetPropertyStr(js, c_types, "cpRotaryLimitJoint", JS_DupValue(js, rotary_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpSimpleMotor", JS_DupValue(js, motor_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpDampedRotarySpring", JS_DupValue(js, damped_rotary_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpDampedSpring", JS_DupValue(js, damped_spring_proto));
|
|
JS_SetPropertyStr(js, c_types, "cpGrooveJoint", JS_DupValue(js, groove_proto_local));
|
|
JS_SetPropertyStr(js, c_types, "cpSlideJoint", JS_DupValue(js, slide_proto_local));
|
|
JS_SetPropertyStr(js, c_types, "cpRatchetJoint", JS_DupValue(js, ratchet_proto_local));
|
|
|
|
// Clean up
|
|
JS_FreeValue(js, c_types);
|
|
JS_FreeValue(js, prosp);
|
|
JS_FreeValue(js, global);
|
|
|
|
// Create the export object with the top-level function(s)
|
|
JSValue export_obj = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, export_obj, js_chipmunk2d_funcs, countof(js_chipmunk2d_funcs));
|
|
|
|
return export_obj;
|
|
}
|
|
|
|
static int js_chipmunk2d_init(JSContext *js, JSModuleDef *m) {
|
|
return JS_SetModuleExport(js, m, "default", js_chipmunk2d_use(js));
|
|
}
|
|
|
|
#ifdef JS_SHARED_LIBRARY
|
|
#define JS_INIT_MODULE js_init_module
|
|
#else
|
|
#define JS_INIT_MODULE js_init_module_chipmunk
|
|
#endif
|
|
|
|
JSModuleDef *JS_INIT_MODULE(JSContext *js, const char *name) {
|
|
JSModuleDef *m = JS_NewCModule(js, name, js_chipmunk2d_init);
|
|
if (!m)
|
|
return NULL;
|
|
JS_AddModuleExport(js, m, "Space");
|
|
return m;
|
|
}
|