From 33d450189cd71172169cbfd829190628b1e26f3f Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 6 Apr 2024 19:41:14 -0500 Subject: [PATCH] Physics callbacks called without registering --- scripts/components.js | 8 +-- scripts/engine.js | 6 -- scripts/entity.js | 12 +--- scripts/input.js | 1 + source/engine/2dphysics.c | 112 +++++++++++++------------------------- source/engine/2dphysics.h | 6 +- source/engine/jsffi.c | 41 ++++++-------- 7 files changed, 62 insertions(+), 124 deletions(-) diff --git a/scripts/components.js b/scripts/components.js index 43f9b5e..9be15be 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -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); }, diff --git a/scripts/engine.js b/scripts/engine.js index 295ca2f..13eacae 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -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)); diff --git a/scripts/entity.js b/scripts/entity.js index 242b98f..8f8714c 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -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.`, diff --git a/scripts/input.js b/scripts/input.js index 2923c8f..acb72d5 100644 --- a/scripts/input.js +++ b/scripts/input.js @@ -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) diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index fe35486..dad95eb 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -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; -} diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 3978039..48a8941 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -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 diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index e20dc0a..87f29d2 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -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), };