2021-11-30 21:29:18 -06:00
|
|
|
#include "2dphysics.h"
|
|
|
|
|
|
|
|
#include "gameobject.h"
|
2022-12-20 08:16:26 -06:00
|
|
|
#include "stb_ds.h"
|
2023-11-03 22:01:30 -05:00
|
|
|
#include "jsffi.h"
|
2022-08-17 00:01:51 -05:00
|
|
|
|
2021-11-30 21:29:18 -06:00
|
|
|
cpSpace *space = NULL;
|
|
|
|
|
2024-04-06 19:41:14 -05:00
|
|
|
static JSValue fns[100];
|
|
|
|
static JSValue hits[100];
|
|
|
|
static int cb_idx = 0;
|
|
|
|
|
2023-05-24 20:45:50 -05:00
|
|
|
void phys2d_init()
|
|
|
|
{
|
2023-05-12 13:22:05 -05:00
|
|
|
space = cpSpaceNew();
|
2022-12-22 03:50:40 -06:00
|
|
|
}
|
|
|
|
|
2024-01-14 10:24:31 -06:00
|
|
|
constraint *constraint_make(cpConstraint *c)
|
|
|
|
{
|
|
|
|
constraint *cp = malloc(sizeof(*cp));
|
|
|
|
cp->c = c;
|
|
|
|
cp->break_cb = JS_UNDEFINED;
|
|
|
|
cp->remove_cb = JS_UNDEFINED;
|
|
|
|
cpSpaceAddConstraint(space,c);
|
|
|
|
cpConstraintSetUserData(c, cp);
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void constraint_break(constraint *constraint)
|
|
|
|
{
|
|
|
|
if (!constraint->c) return;
|
|
|
|
cpSpaceRemoveConstraint(space, constraint->c);
|
|
|
|
cpConstraintFree(constraint->c);
|
|
|
|
constraint->c = NULL;
|
2024-03-15 10:51:04 -05:00
|
|
|
script_call_sym(constraint->break_cb,0,NULL);
|
2024-01-14 10:24:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void constraint_free(constraint *constraint)
|
|
|
|
{
|
|
|
|
constraint_break(constraint);
|
|
|
|
free(constraint);
|
|
|
|
}
|
|
|
|
|
|
|
|
void constraint_test(cpConstraint *constraint, float *dt)
|
|
|
|
{
|
|
|
|
float max = cpConstraintGetMaxForce(constraint);
|
|
|
|
if (!isfinite(max)) return;
|
|
|
|
float force = cpConstraintGetImpulse(constraint)/ *dt;
|
|
|
|
if (force > max)
|
|
|
|
constraint_break(cpConstraintGetUserData(constraint));
|
|
|
|
}
|
|
|
|
|
|
|
|
void phys2d_update(float deltaT) {
|
|
|
|
cpSpaceStep(space, deltaT);
|
|
|
|
cpSpaceEachConstraint(space, constraint_test, &deltaT);
|
2024-04-06 19:41:14 -05:00
|
|
|
cb_idx = 0;
|
2024-01-14 10:24:31 -06:00
|
|
|
}
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2024-01-03 17:19:13 -06:00
|
|
|
JSValue arb2js(cpArbiter *arb)
|
|
|
|
{
|
|
|
|
cpBody *body1;
|
|
|
|
cpBody *body2;
|
|
|
|
cpArbiterGetBodies(arb, &body1, &body2);
|
2024-04-06 19:41:14 -05:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
cpShape *shape1;
|
|
|
|
cpShape *shape2;
|
|
|
|
cpArbiterGetShapes(arb, &shape1, &shape2);
|
|
|
|
|
2024-05-17 12:39:04 -05:00
|
|
|
JSValue *j = cpShapeGetUserData(shape2);
|
|
|
|
|
|
|
|
JSValue jg = body2go(body2)->ref;
|
|
|
|
|
|
|
|
HMM_Vec2 srfv;
|
|
|
|
srfv.cp = cpArbiterGetSurfaceVelocity(arb);
|
2024-04-06 19:41:14 -05:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
JSValue obj = JS_NewObject(js);
|
2024-04-06 19:41:14 -05:00
|
|
|
JS_SetPropertyStr(js, obj, "normal", vec22js((HMM_Vec2)cpArbiterGetNormal(arb)));
|
2024-05-17 12:39:04 -05:00
|
|
|
JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,jg));
|
|
|
|
JS_SetPropertyStr(js, obj, "shape", JS_DupValue(js, *j));
|
|
|
|
JS_SetPropertyStr(js, obj, "point", vec22js((HMM_Vec2)cpArbiterGetPointA(arb, 0)));
|
2024-03-13 03:51:44 -05:00
|
|
|
JS_SetPropertyStr(js, obj, "velocity", vec22js(srfv));
|
2023-05-27 10:13:20 -05:00
|
|
|
|
2024-01-03 17:19:13 -06:00
|
|
|
return obj;
|
2023-02-17 01:16:52 -06:00
|
|
|
}
|
|
|
|
|
2024-01-03 17:19:13 -06:00
|
|
|
void phys_run_post(cpSpace *space, JSValue *fn, JSValue *hit)
|
|
|
|
{
|
2024-04-03 00:44:08 -05:00
|
|
|
script_call_sym(*fn, 1, hit);
|
|
|
|
JS_FreeValue(js, *hit);
|
|
|
|
JS_FreeValue(js, *fn);
|
2024-01-03 17:19:13 -06:00
|
|
|
}
|
|
|
|
|
2024-04-06 19:41:14 -05:00
|
|
|
void register_hit(cpArbiter *arb, gameobject *go, const char *name)
|
2024-01-03 17:19:13 -06:00
|
|
|
{
|
2024-04-11 17:17:49 -05:00
|
|
|
if (JS_IsUndefined(go->ref)) return;
|
2024-04-06 19:41:14 -05:00
|
|
|
JSValue cb = JS_GetPropertyStr(js, go->ref, name);
|
|
|
|
if (!JS_IsUndefined(cb)) {
|
|
|
|
JSValue jarb = arb2js(arb);
|
|
|
|
fns[cb_idx] = JS_DupValue(js, cb);
|
|
|
|
hits[cb_idx] = jarb;
|
|
|
|
cpSpaceAddPostStepCallback(space, phys_run_post, &fns[cb_idx], &hits[cb_idx]);
|
|
|
|
cb_idx++;
|
2024-03-22 09:02:10 -05:00
|
|
|
}
|
2024-01-03 17:19:13 -06:00
|
|
|
|
2024-04-06 19:41:14 -05:00
|
|
|
cpShape *s1, *s2;
|
2024-05-17 12:39:04 -05:00
|
|
|
cpArbiterGetShapes(arb, &s1, &s2);
|
|
|
|
JSValue *j1 = cpShapeGetUserData(s1);
|
|
|
|
JSValue *j2 = cpShapeGetUserData(s2);
|
|
|
|
cb = JS_GetPropertyStr(js, *j1, name);
|
2024-04-06 19:41:14 -05:00
|
|
|
if (!JS_IsUndefined(cb)) {
|
|
|
|
JSValue jarb = arb2js(arb);
|
|
|
|
fns[cb_idx] = JS_DupValue(js,cb);
|
|
|
|
hits[cb_idx] = jarb;
|
|
|
|
cpSpaceAddPostStepCallback(space, phys_run_post, &fns[cb_idx], &hits[cb_idx]);
|
|
|
|
cb_idx++;
|
2024-01-03 17:19:13 -06:00
|
|
|
}
|
2023-02-24 12:11:36 -06:00
|
|
|
}
|
|
|
|
|
2024-04-12 13:53:00 -05:00
|
|
|
int script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "collide"); return 1; }
|
2024-04-06 19:41:14 -05:00
|
|
|
void script_phys_cb_separate(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "separate"); }
|
|
|
|
|
2023-12-11 08:36:45 -06:00
|
|
|
void phys2d_setup_handlers(gameobject *go) {
|
2023-12-21 17:21:01 -06:00
|
|
|
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, (cpCollisionType)go);
|
2023-12-11 08:36:45 -06:00
|
|
|
handler->userData = go;
|
2024-04-11 17:17:49 -05:00
|
|
|
handler->beginFunc = script_phys_cb_begin;
|
2023-03-17 10:25:35 -05:00
|
|
|
handler->separateFunc = script_phys_cb_separate;
|
2023-03-10 13:13:48 -06:00
|
|
|
}
|