Physics callbacks called without registering

This commit is contained in:
John Alanbrook 2024-04-06 19:41:14 -05:00
parent 9106ebcc48
commit 33d450189c
7 changed files with 62 additions and 124 deletions

View file

@ -22,10 +22,11 @@ var component = {
make(go) {
var nc = Object.create(this);
nc.gameobject = go;
Object.mixin(nc, this._enghook(go));
Object.mixin(nc, this._enghook(go, nc));
assign_impl(nc,this.impl);
Object.hide(nc, 'gameobject', 'id');
nc.post();
nc.make = undefined;
return nc;
},
@ -358,11 +359,6 @@ SpriteAnim.find.doc = 'Given a path, find the relevant animation for the file.';
/* For all colliders, "shape" is a pointer to a phys2d_shape, "id" is a pointer to the shape data */
var collider2d = Object.copy(component, {
name: "collider 2d",
sensor: false,
kill() {}, /* No killing is necessary - it is done through the gameobject's kill */
impl: {
set sensor(x) { pshape.set_sensor(this.shape,x); },
get sensor() { return pshape.get_sensor(this.shape); },

View file

@ -213,12 +213,6 @@ global.check_registers = function(obj)
if (typeof obj.physupdate === 'function')
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
if (typeof obj.collide === 'function')
physics.collide_begin(obj.collide.bind(obj), obj);
if (typeof obj.separate === 'function')
physics.collide_separate(obj.separate.bind(obj), obj);
if (typeof obj.draw === 'function')
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));

View file

@ -263,13 +263,13 @@ var gameobject = {
text.forEach(path => use(path,ent));
if (typeof config === 'string')
Object.assign(ent, json.decode(Resources.replstrs(config)));
Object.merge(ent, json.decode(Resources.replstrs(config)));
else if (Array.isArray(config))
config.forEach(function(path) {
if (typeof path === 'string')
Object.assign(ent, json.decode(Resources.replstrs(path)));
Object.merge(ent, json.decode(Resources.replstrs(path)));
else if (typeof path === 'object')
Object.assign(ent,path);
Object.merge(ent,path);
});
ent.reparent(this);
@ -285,10 +285,6 @@ var gameobject = {
};
check_registers(ent);
ent.components.forEach(function(x) {
if (typeof x.collide === 'function')
physics.collide_shape(x.collide.bind(x), ent, x.shape);
});
if (typeof ent.load === 'function') ent.load();
if (sim.playing())
@ -516,7 +512,6 @@ var gameobject = {
this.timers = [];
Event.rm_obj(this);
input.do_uncontrol(this);
physics.collide_rm(this);
if (this.master) {
this.master.remove_obj(this);
@ -627,7 +622,6 @@ gameobject.doc = {
shove_at: 'Apply a force to this body, at a position relative to itself.',
max_velocity: 'The max linear velocity this object can travel.',
max_angularvelocity: 'The max angular velocity this object can rotate.',
in_air: `Return true if the object is in the air.`,
on_ground: `Return true if the object is on the ground.`,
spawn: `Create an instance of a supplied ur-type on this object. Optionally provide a data object to modify the created entity.`,
hide: `Make this object invisible.`,

View file

@ -92,6 +92,7 @@ prosperon.keyup = function(key)
prosperon.keys[key] = false;
if (key == 341 || key == 345)
mod.ctrl = 0;
else if (key == 342 || key == 346)
mod.alt = 0;
else if (key == 343 || key == 347)

View file

@ -28,6 +28,10 @@ struct rgba dynamic_color = {255,70,46,255};
struct rgba kinematic_color = {255, 194, 64, 255};
struct rgba static_color = {73,209,80,255};
static JSValue fns[100];
static JSValue hits[100];
static int cb_idx = 0;
static const unsigned char col_alpha = 40;
static const float sensor_seg = 10;
@ -182,6 +186,7 @@ void constraint_test(cpConstraint *constraint, float *dt)
void phys2d_update(float deltaT) {
cpSpaceStep(space, deltaT);
cpSpaceEachConstraint(space, constraint_test, &deltaT);
cb_idx = 0;
}
void init_phys2dshape(struct phys2d_shape *shape, gameobject *go, void *data) {
@ -538,33 +543,24 @@ int shape_get_sensor(struct phys2d_shape *shape) {
void phys2d_reindex_body(cpBody *body) { cpSpaceReindexShapesForBody(space, body); }
int arb_valid(cpArbiter *arb)
{
cpBody *body1;
cpBody *body2;
cpArbiterGetBodies(arb, &body1, &body2);
gameobject *go2 = cpBodyGetUserData(body2);
return !JS_IsUndefined(go2->ref);
}
JSValue arb2js(cpArbiter *arb)
{
cpBody *body1;
cpBody *body2;
cpArbiterGetBodies(arb, &body1, &body2);
gameobject *go2 = cpBodyGetUserData(body2);
if (JS_IsUndefined(go2->ref)) return JS_UNDEFINED;
cpShape *shape1;
cpShape *shape2;
cpArbiterGetShapes(arb, &shape1, &shape2);
HMM_Vec2 norm;
norm.cp = cpArbiterGetNormal(arb);
struct phys2d_shape *pshape = cpShapeGetUserData(shape2);
gameobject *go2 = cpBodyGetUserData(body2);
JSValue obj = JS_NewObject(js);
JS_SetPropertyStr(js, obj, "normal", vec22js(norm));
JS_SetPropertyStr(js, obj, "normal", vec22js((HMM_Vec2)cpArbiterGetNormal(arb)));
JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,go2->ref));
JS_SetPropertyStr(js, obj, "sensor", JS_NewBool(js, cpShapeGetSensor(shape2)));
JS_SetPropertyStr(js, obj, "shape", JS_DupValue(js, pshape->ref));
JS_SetPropertyStr(js, obj, "point", vec22js((HMM_Vec2)cpArbiterGetPointA(arb, 0)));
HMM_Vec2 srfv;
srfv.cp = cpArbiterGetSurfaceVelocity(arb);
@ -580,73 +576,39 @@ void phys_run_post(cpSpace *space, JSValue *fn, JSValue *hit)
JS_FreeValue(js, *fn);
}
/* TODO: Limitation, cannot handle multiple collision same frame */
int script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go)
void register_hit(cpArbiter *arb, gameobject *go, const char *name)
{
if (!arb_valid(arb)) return 1;
YughSpam("Adding begin callbacks for go %p", go);
if (!JS_IsUndefined(go->cbs.begin) && cpSpaceAddPostStepCallback(space, phys_run_post, &go->cbs.begin, &go->cbs.bhit)) {
YughSpam("Added begin for %p", &go->cbs.begin);
JS_DupValue(js, go->cbs.begin);
go->cbs.bhit = arb2js(arb);
}
cpShape *shape1;
cpShape *shape2;
cpArbiterGetShapes(arb, &shape1, &shape2);
struct phys2d_shape *pshape1 = cpShapeGetUserData(shape1);
for (int i = 0; i < arrlen(go->shape_cbs); i++) {
if (go->shape_cbs[i].shape != pshape1) continue;
if (!JS_IsUndefined(go->shape_cbs[i].cbs.begin) && cpSpaceAddPostStepCallback(space, phys_run_post, &go->shape_cbs[i].cbs.begin, &go->shape_cbs[i].cbs.bhit))
go->shape_cbs[i].cbs.bhit = arb2js(arb);
}
return 1;
}
void script_phys_cb_separate(cpArbiter *arb, cpSpace *space, gameobject *go)
{
if (!arb_valid(arb)) return;
if (JS_IsUndefined(go->cbs.separate)) return;
go->cbs.shit = arb2js(arb);
cpSpaceAddPostStepCallback(space, phys_run_post, &go->cbs.separate, &go->cbs.shit);
}
void phys2d_rm_go_handlers(gameobject *go) {
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, (cpCollisionType)go);
if (!JS_IsUndefined(go->cbs.begin)) {
JS_FreeValue(js,go->cbs.begin);
go->cbs.begin = JS_UNDEFINED;
}
if (JS_IsFunction(js,go->cbs.separate)) {
JS_FreeValue(js,go->cbs.separate);
go->cbs.separate = JS_UNDEFINED;
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++;
}
for (int i = 0; i < arrlen(go->shape_cbs); i++) {
JS_FreeValue(js, go->shape_cbs[i].cbs.begin);
go->shape_cbs[i].cbs.begin = JS_UNDEFINED;
cpShape *s1, *s2;
cpArbiterGetShapes(arb, &s1, &s2);
struct phys2d_shape *pshape1 = cpShapeGetUserData(s1);
if (JS_IsUndefined(pshape1->ref)) return;
cb = JS_GetPropertyStr(js, pshape1->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++;
}
}
void script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "collide"); }
void script_phys_cb_separate(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "separate"); }
void phys2d_setup_handlers(gameobject *go) {
cpCollisionHandler *handler = cpSpaceAddWildcardHandler(space, (cpCollisionType)go);
handler->userData = go;
handler->beginFunc = script_phys_cb_begin;
handler->postSolveFunc = script_phys_cb_begin;
handler->separateFunc = script_phys_cb_separate;
}
static int airborne = 0;
void inair(cpBody *body, cpArbiter *arbiter, void *data) {
airborne = 0;
}
int phys2d_in_air(cpBody *body) {
airborne = 1;
cpBodyEachArbiter(body, inair, NULL);
return airborne;
}

View file

@ -31,6 +31,7 @@ void constraint_free(constraint *constraint);
struct phys2d_shape {
cpShape *shape; /* user data is this phys2d_shape */
JSValue ref;
transform2d t;
gameobject *go;
void *data; /* The specific subtype; phys2d_circle, etc */
@ -113,7 +114,6 @@ struct shape_cb {
void fire_hits();
void phys2d_rm_go_handlers(gameobject *go);
void phys2d_set_gravity(HMM_Vec2 v);
void shape_enabled(struct phys2d_shape *shape, int enabled);
@ -127,10 +127,8 @@ void shape_gui(struct phys2d_shape *shape);
void phys2d_setup_handlers(gameobject *go);
int query_point(HMM_Vec2 pos);
void flush_collide_cbs();
void phys2d_reindex_body(cpBody *body);
extern unsigned int category_masks[32];
void set_cat_mask(int cat, unsigned int mask);
int phys2d_in_air(cpBody *body);
#endif

View file

@ -934,11 +934,6 @@ JSC_CCALL(physics_closest_point,
JSC_CCALL(physics_make_gravity, return warp_gravity2js(warp_gravity_make()))
JSC_CCALL(physics_make_damp, return warp_damp2js(warp_damp_make()))
JSC_CCALL(physics_collide_begin, js2gameobject(argv[1])->cbs.begin = JS_DupValue(js,argv[0]))
JSC_CCALL(physics_collide_rm, phys2d_rm_go_handlers(js2gameobject(argv[0])))
JSC_CCALL(physics_collide_separate, js2gameobject(argv[1])->cbs.separate = JS_DupValue(js,argv[0]))
JSC_CCALL(physics_collide_shape, gameobject_add_shape_collider(js2gameobject(argv[1]), JS_DupValue(js,argv[0]), js2ptr(argv[2])))
void bb_query_fn(cpShape *shape, JSValue *cb)
{
JSValue go = JS_DupValue(js,shape2go(shape)->ref);
@ -1027,10 +1022,6 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
MIST_FUNC_DEF(physics, closest_point, 3),
MIST_FUNC_DEF(physics, make_damp, 0),
MIST_FUNC_DEF(physics, make_gravity, 0),
MIST_FUNC_DEF(physics, collide_begin, 2),
MIST_FUNC_DEF(physics, collide_rm, 1),
MIST_FUNC_DEF(physics, collide_separate, 2),
MIST_FUNC_DEF(physics, collide_shape, 3)
};
static const JSCFunctionListEntry js_emitter_funcs[] = {
@ -1159,7 +1150,6 @@ JSC_GETSET(gameobject, maxangularvelocity, number)
JSC_GETSET(gameobject, warp_filter, bitmask)
JSC_GETSET(gameobject, drawlayer, number)
JSC_CCALL(gameobject_selfsync, gameobject_apply(js2gameobject(this)))
JSC_CCALL(gameobject_in_air, return boolean2js(phys2d_in_air(js2gameobject(this)->body)))
JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0]))))
JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0]))))
JSC_CCALL(gameobject_dir_world2this, return vec22js(mat_t_dir(t_world2go(js2gameobject(this)), js2vec2(argv[0]))))
@ -1188,7 +1178,6 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
MIST_FUNC_DEF(gameobject, impulse, 1),
MIST_FUNC_DEF(gameobject, force, 1),
MIST_FUNC_DEF(gameobject, force_local, 2),
MIST_FUNC_DEF(gameobject, in_air, 0),
MIST_FUNC_DEF(gameobject, world2this, 1),
MIST_FUNC_DEF(gameobject, this2world, 1),
MIST_FUNC_DEF(gameobject, dir_world2this, 1),
@ -1266,9 +1255,9 @@ static const JSCFunctionListEntry js_dspsound_funcs[] = {
};
JSC_CCALL(pshape_set_sensor, shape_set_sensor(js2ptr(argv[0]), js2boolean(argv[1])))
JSC_CCALL(pshape_get_sensor, shape_get_sensor(js2ptr(argv[0])))
JSC_CCALL(pshape_get_sensor, return boolean2js(shape_get_sensor(js2ptr(argv[0]))))
JSC_CCALL(pshape_set_enabled, shape_enabled(js2ptr(argv[0]), js2boolean(argv[1])))
JSC_CCALL(pshape_get_enabled, shape_is_enabled(js2ptr(argv[0])))
JSC_CCALL(pshape_get_enabled, return boolean2js(shape_is_enabled(js2ptr(argv[0]))))
static const JSCFunctionListEntry js_pshape_funcs[] = {
MIST_FUNC_DEF(pshape, set_sensor, 2),
@ -1455,17 +1444,10 @@ JSC_CCALL(os_make_circle2d,
JSValue circleval = JS_NewObject(js);
js_setprop_str(circleval, "id", ptr2js(circle));
js_setprop_str(circleval, "shape", ptr2js(&circle->shape));
circle->shape.ref = argv[1];
return circleval;
)
JSC_CCALL(os_make_model,
gameobject *go = js2gameobject(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
return ret;
)
JSC_CCALL(os_make_poly2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_poly *poly = Make2DPoly(go);
@ -1473,6 +1455,7 @@ JSC_CCALL(os_make_poly2d,
JSValue polyval = JS_NewObject(js);
js_setprop_str(polyval, "id", ptr2js(poly));
js_setprop_str(polyval, "shape", ptr2js(&poly->shape));
poly->shape.ref = argv[1];
return polyval;
)
@ -1486,6 +1469,7 @@ JSC_CCALL(os_make_edge2d,
JSValue edgeval = JS_NewObject(js);
js_setprop_str(edgeval, "id", ptr2js(edge));
js_setprop_str(edgeval, "shape", ptr2js(&edge->shape));
edge->shape.ref = argv[1];
return edgeval;
)
@ -1494,6 +1478,15 @@ JSC_SCALL(os_make_texture,
YughInfo("Made texture with %s", str);
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
)
JSC_CCALL(os_make_model,
gameobject *go = js2gameobject(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
return ret;
)
JSC_SCALL(os_system, system(str); )
static const JSCFunctionListEntry js_os_funcs[] = {
@ -1509,9 +1502,9 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, capture, 5),
MIST_FUNC_DEF(os, eval, 2),
MIST_FUNC_DEF(os, make_gameobject, 0),
MIST_FUNC_DEF(os, make_circle2d, 1),
MIST_FUNC_DEF(os, make_poly2d, 1),
MIST_FUNC_DEF(os, make_edge2d, 1),
MIST_FUNC_DEF(os, make_circle2d, 2),
MIST_FUNC_DEF(os, make_poly2d, 2),
MIST_FUNC_DEF(os, make_edge2d, 2),
MIST_FUNC_DEF(os, make_model, 2),
MIST_FUNC_DEF(os, make_texture, 1),
};