Simplify components in js

This commit is contained in:
John Alanbrook 2024-05-28 13:39:02 -05:00
parent eadfd1dc38
commit 33fdd97bdd
8 changed files with 202 additions and 311 deletions

View file

@ -132,6 +132,7 @@ else
CXXFLAGS += -std=c++11
LDFLAGS += -framework Cocoa -framework QuartzCore -framework AudioToolbox -framework Metal -framework MetalKit
INFO :=$(INFO)_macos
STEAMAPI := steam_api
endif
endif

View file

@ -358,13 +358,6 @@ Object.readonly = function(o, name, msg)
Object.defineProperty(o, name, prop);
}
Object.extend = function(from)
{
var n = {};
Object.mixin(n, from);
return n;
}
Object.mixin = function(target, source)
{
if (typeof source !== 'object') return target;
@ -810,6 +803,13 @@ Object.defineProperty(String.prototype, 'name', {
return this.fromlast('/').tolast('.'); }
});
Object.defineProperty(String.prototype, 'set_name', {
value: function(name) {
var dir = this.dir();
return this.dir() + name + "." + this.ext();
}
});
Object.defineProperty(String.prototype, 'base', {
value: function() { return this.fromlast('/'); }
});
@ -1337,16 +1337,19 @@ Math.snap = function(val, grid) {
}
Math.angledist = function (a1, a2) {
a1 = Math.turn2deg(a1);
a2 = Math.turn2deg(a2);
a1 = a1%1;
a2 = a2%1;
var dist = a2 - a1;
var wrap = dist >= 0 ? dist+360 : dist-360;
wrap %= 360;
if (dist == 0) return dist;
if (Math.abs(dist) < Math.abs(wrap))
return Math.deg2turn(dist);
if (dist > 0) {
if (dist > 0.5) return dist-1;
return dist;
}
return Math.deg2turn(wrap);
if (dist < -0.5) return dist+1;
return dist;
};
Math.angledist.doc = "Find the shortest angle between two angles.";
Math.TAU = Math.PI*2;
@ -1544,8 +1547,8 @@ Math.sortpointsccw = function(points)
var cm = points2cm(points);
var cmpoints = points.map(function(x) { return x.sub(cm); });
var ccw = cmpoints.sort(function(a,b) {
aatan = Math.atan2(a.y, a.x);
batan = Math.atan2(b.y, b.x);
var aatan = Math.atan2(a.y, a.x);
var batan = Math.atan2(b.y, b.x);
return aatan - batan;
});
@ -1604,6 +1607,8 @@ yaml.tojson = function(yaml)
return yaml;
}
Math.sign = function(n) { return n >= 0 ? 1 : -1; }
return {
convert,
time,

View file

@ -1,44 +1,4 @@
var component = {
components: [],
toString() {
if ('gameobject' in this)
return this.name + " on " + this.gameobject;
else
return this.name;
},
name: "component",
component: true,
enabled: true,
enable() { this.enabled = true; },
disable() { this.enabled = false; },
isComponent(c) {
if (typeof c !== 'object') return false;
if (typeof c.toString !== 'function') return false;
if (typeof c.make !== 'function') return false;
return (typeof component[c.toString()] === 'object');
},
make(go) {
var nc = Object.create(this);
nc.gameobject = 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;
},
kill() { console.info("Kill not created for this component yet"); },
sync(){},
post(){},
gui(){},
gizmo(){},
finish_center() {},
extend(spec) { return Object.copy(this, spec); },
};
var component = {};
var make_point_obj = function(o, p)
{
@ -53,41 +13,8 @@ var make_point_obj = function(o, p)
}
}
var assign_impl = function(obj, impl)
{
var tmp = {};
for (var key of Object.keys(impl))
if (typeof obj[key] !== 'undefined' && typeof obj[key] !== 'function')
tmp[key] = obj[key];
Object.mixin(obj, impl);
for (var key in tmp)
obj[key] = tmp[key];
}
function json_from_whitelist(whitelist)
{
return function() {
var o = {};
for (var p of whitelist)
o[p] = this[p];
return o;
}
}
var sprite = {
loop: true,
toJSON:json_from_whitelist([
"path",
"pos",
"scale",
"angle",
"color",
"emissive",
"parallax",
"frame"
]),
anim:{},
playing: 0,
play(str = 0) {
@ -155,7 +82,6 @@ var sprite = {
this.anim_done = undefined;
delete allsprites[this.guid];
},
toString() { return "sprite"; },
move(d) { this.pos = this.pos.add(d); },
grow(x) {
this.scale = this.scale.scale(x);
@ -181,15 +107,6 @@ var sprite = {
height() { return this.dimensions().y; },
};
globalThis.allsprites = {};
sprite.make = function(go)
{
var sp = Object.create(sprite);
sp.go = go;
sp.gameobject = go;
sp.guid = prosperon.guid();
allsprites[sp.guid] = sp;
return sp;
}
sprite.doc = {
path: "Path to the texture.",
@ -225,9 +142,18 @@ sprite.inputs.kp3 = function() { this.setanchor("ur"); }
sprite.inputs.kp2 = function() { this.setanchor("um"); }
sprite.inputs.kp1 = function() { this.setanchor("ul"); }
component.sprite = sprite;
component.sprite = function(obj) {
var sp = Object.create(sprite);
sp.gameobject = obj;
sp.guid = prosperon.guid();
allsprites[sp.guid] = sp;
return sp;
}
sprite.shade = [1,1,1,1];
//Object.seal(sprite);
Object.mixin(os.make_seg2d(), {
sync() { this.set_endpoints(this.points[0], this.points[1]); }
});
/* sprite anim returns a data structure for the given file path
frames: array of frames
@ -364,18 +290,7 @@ SpriteAnim.strip.doc = 'Given a path and number of frames, converts a horizontal
SpriteAnim.aseprite.doc = 'Given an aseprite json metadata, returns an object of animations defined in the aseprite file.';
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, {
impl: {
set sensor(x) { pshape.set_sensor(this.shape,x); },
get sensor() { return pshape.get_sensor(this.shape); },
set enabled(x) { pshape.set_enabled(this.shape,x); },
get enabled() { return pshape.get_enabled(this.shape); }
},
});
Object.hide(collider2d.impl, 'enabled');
var collider2d = {};
collider2d.inputs = {};
collider2d.inputs['M-s'] = function() { this.sensor = !this.sensor; }
collider2d.inputs['M-s'].doc = "Toggle if this collider is a sensor.";
@ -383,27 +298,11 @@ collider2d.inputs['M-s'].doc = "Toggle if this collider is a sensor.";
collider2d.inputs['M-t'] = function() { this.enabled = !this.enabled; }
collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled.";
component.polygon2d = Object.copy(collider2d, {
toJSON:json_from_whitelist([
'points',
'sensor'
]),
toString() { return "polygon2d"; },
flipx: false,
flipy: false,
Object.mix(os.make_poly2d(), {
boundingbox() {
return bbox.frompoints(this.spoints());
},
hides: ['id', 'shape', 'gameobject'],
_enghook: os.make_poly2d,
points:[],
setpoints(points) {
this.points = points;
this.sync();
},
/* EDITOR */
spoints() {
var spoints = this.points.slice();
@ -449,63 +348,71 @@ function pointscaler(x) {
this.points = this.points.map(p => p.mult(x));
}
component.polygon2d.impl = Object.mix(collider2d.impl, {
sync() { poly2d.setverts(this.id,this.spoints()); },
query() { return physics.shape_query(this.shape); },
Object.mixin(os.make_poly2d(), {
sync() {
this.setverts(this.points);
},
grow: pointscaler,
});
var polygon2d = component.polygon2d;
var polyinputs = Object.create(collider2d.inputs);
os.make_poly2d().inputs = polyinputs;
polygon2d.inputs = {};
//polygon2d.inputs.post = function() { this.sync(); };
polygon2d.inputs.f10 = function() {
polyinputs = {};
polyinputs.f10 = function() {
this.points = Math.sortpointsccw(this.points);
};
polygon2d.inputs.f10.doc = "Sort all points to be CCW order.";
polyinputs.f10.doc = "Sort all points to be CCW order.";
polygon2d.inputs['C-lm'] = function() {
polyinputs['C-lm'] = function() {
this.points.push(this.gameobject.world2this(input.mouse.worldpos()));
};
polygon2d.inputs['C-lm'].doc = "Add a point to location of mouse.";
polygon2d.inputs.lm = function(){};
polygon2d.inputs.lm.released = function(){};
polyinputs['C-lm'].doc = "Add a point to location of mouse.";
polyinputs.lm = function(){};
polyinputs.lm.released = function(){};
polygon2d.inputs['C-M-lm'] = function() {
polyinputs['C-M-lm'] = function() {
var idx = Math.grab_from_points(input.mouse.worldpos(), this.points.map(p => this.gameobject.this2world(p)), 25);
if (idx === -1) return;
this.points.splice(idx, 1);
};
polygon2d.inputs['C-M-lm'].doc = "Remove point under mouse.";
polyinputs['C-M-lm'].doc = "Remove point under mouse.";
polygon2d.inputs['C-b'] = function() {
polyinputs['C-b'] = function() {
this.points = this.spoints;
this.flipx = false;
this.flipy = false;
};
polygon2d.inputs['C-b'].doc = "Freeze mirroring in place.";
polyinputs['C-b'].doc = "Freeze mirroring in place.";
component.edge2d = Object.copy(collider2d, {
toJSON:json_from_whitelist([
'sensor',
'thickness',
'points',
'hollow',
'hollowt',
'angle',
]),
var edge2d = {
dimensions:2,
thickness:0,
thickness:1,
/* if type === -1, point to point */
type: Spline.type.catmull,
C: 1, /* when in bezier, continuity required. 0, 1 or 2. */
looped: false,
angle: 0.5, /* smaller for smoother bezier */
elasticity: 0,
friction: 0,
sync() {
var ppp = this.sample();
this.segs ??= [];
var count = ppp.length-1;
this.segs.length = count;
for (var i = 0; i < count; i++) {
this.segs[i] ??= os.make_seg2d(this.body);
this.segs[i].set_endpoints(ppp[i],ppp[i+1]);
this.segs[i].set_neighbors(ppp[i],ppp[i+1]);
this.segs[i].radius = this.thickness;
this.segs[i].elasticity = this.elasticity;
this.segs[i].friction = this.friction;
this.segs[i].collide = this.collide;
}
},
flipx: false,
flipy: false,
points:[],
toString() { return "edge2d"; },
hollow: false,
hollowt: 0,
@ -544,12 +451,10 @@ component.edge2d = Object.copy(collider2d, {
return arr1.concat(arr2.reverse());
}
return spoints;
},
if (this.looped)
spoints = spoints.wrapped(1);
setpoints(points) {
this.points = points;
// this.sync();
return spoints;
},
post() {
@ -582,9 +487,6 @@ component.edge2d = Object.copy(collider2d, {
boundingbox() { return bbox.frompoints(this.points.map(x => x.scale(this.gameobject.scale))); },
hides: ['gameobject', 'id', 'shape'],
_enghook: os.make_edge2d,
/* EDITOR */
gizmo() {
if (this.type === Spline.type.catmull || this.type === -1) {
@ -692,71 +594,64 @@ component.edge2d = Object.copy(collider2d, {
this.points.forEach(x =>picks.push(make_point_obj(this,x)));
return picks;
},
});
};
component.edge2d.impl = Object.mix(collider2d.impl, {
set thickness(x) { edge2d.set_thickness(this.id,x); },
get thickness() { return edge2d.get_thickness(this.id); },
grow: pointscaler,
sync() {
var sensor = this.sensor;
var points = this.sample();
if (!points) return;
edge2d.setverts(this.id,points);
this.sensor = sensor;
},
});
component.edge2d = function(obj) {
if (!obj.body) obj.rigidify();
var edge = Object.create(edge2d);
edge.body = obj.body;
return edge;
}
var bucket = component.edge2d;
bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
bucket.inputs = {};
bucket.inputs.h = function() { this.hollow = !this.hollow; };
bucket.inputs.h.doc = "Toggle hollow.";
edge2d.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
edge2d.inputs = {};
edge2d.inputs.h = function() { this.hollow = !this.hollow; };
edge2d.inputs.h.doc = "Toggle hollow.";
bucket.inputs['C-g'] = function() { if (this.hollowt > 0) this.hollowt--; };
bucket.inputs['C-g'].doc = "Thin the hollow thickness.";
bucket.inputs['C-g'].rep = true;
edge2d.inputs['C-g'] = function() { if (this.hollowt > 0) this.hollowt--; };
edge2d.inputs['C-g'].doc = "Thin the hollow thickness.";
edge2d.inputs['C-g'].rep = true;
bucket.inputs['C-f'] = function() { this.hollowt++; };
bucket.inputs['C-f'].doc = "Increase the hollow thickness.";
bucket.inputs['C-f'].rep = true;
edge2d.inputs['C-f'] = function() { this.hollowt++; };
edge2d.inputs['C-f'].doc = "Increase the hollow thickness.";
edge2d.inputs['C-f'].rep = true;
bucket.inputs['M-v'] = function() { if (this.thickness > 0) this.thickness--; };
bucket.inputs['M-v'].doc = "Decrease spline thickness.";
bucket.inputs['M-v'].rep = true;
edge2d.inputs['M-v'] = function() { if (this.thickness > 0) this.thickness--; };
edge2d.inputs['M-v'].doc = "Decrease spline thickness.";
edge2d.inputs['M-v'].rep = true;
bucket.inputs['C-y'] = function() {
edge2d.inputs['C-y'] = function() {
this.points = this.spoints();
this.flipx = false;
this.flipy = false;
this.hollow = false;
};
bucket.inputs['C-y'].doc = "Freeze mirroring,";
bucket.inputs['M-b'] = function() { this.thickness++; };
bucket.inputs['M-b'].doc = "Increase spline thickness.";
bucket.inputs['M-b'].rep = true;
edge2d.inputs['C-y'].doc = "Freeze mirroring,";
edge2d.inputs['M-b'] = function() { this.thickness++; };
edge2d.inputs['M-b'].doc = "Increase spline thickness.";
edge2d.inputs['M-b'].rep = true;
bucket.inputs.plus = function() {
edge2d.inputs.plus = function() {
if (this.angle <= 1) {
this.angle = 1;
return;
}
this.angle *= 0.9;
};
bucket.inputs.plus.doc = "Increase the number of samples of this spline.";
bucket.inputs.plus.rep = true;
edge2d.inputs.plus.doc = "Increase the number of samples of this spline.";
edge2d.inputs.plus.rep = true;
bucket.inputs.minus = function() { this.angle *= 1.1; };
bucket.inputs.minus.doc = "Decrease the number of samples on this spline.";
bucket.inputs.minus.rep = true;
edge2d.inputs.minus = function() { this.angle *= 1.1; };
edge2d.inputs.minus.doc = "Decrease the number of samples on this spline.";
edge2d.inputs.minus.rep = true;
bucket.inputs['C-r'] = function() { this.points = this.points.reverse(); };
bucket.inputs['C-r'].doc = "Reverse the order of the spline's points.";
edge2d.inputs['C-r'] = function() { this.points = this.points.reverse(); };
edge2d.inputs['C-r'].doc = "Reverse the order of the spline's points.";
bucket.inputs['C-l'] = function() { this.looped = !this.looped};
bucket.inputs['C-l'].doc = "Toggle spline being looped.";
edge2d.inputs['C-l'] = function() { this.looped = !this.looped};
edge2d.inputs['C-l'].doc = "Toggle spline being looped.";
bucket.inputs['C-c'] = function() {
edge2d.inputs['C-c'] = function() {
switch(this.type) {
case Spline.type.bezier:
this.points = Spline.bezier2catmull(this.points);
@ -765,9 +660,9 @@ bucket.inputs['C-c'] = function() {
this.type = Spline.type.catmull;
};
bucket.inputs['C-c'].doc = "Set type of spline to catmull-rom.";
edge2d.inputs['C-c'].doc = "Set type of spline to catmull-rom.";
bucket.inputs['C-b'] = function() {
edge2d.inputs['C-b'] = function() {
switch(this.type) {
case Spline.type.catmull:
this.points = Spline.catmull2bezier(Spline.catmull_caps(this.points));
@ -776,10 +671,10 @@ bucket.inputs['C-b'] = function() {
this.type = Spline.type.bezier;
};
bucket.inputs['C-o'] = function() { this.type = -1; };
bucket.inputs['C-o'].doc = "Set spline to linear.";
edge2d.inputs['C-o'] = function() { this.type = -1; };
edge2d.inputs['C-o'].doc = "Set spline to linear.";
bucket.inputs['C-M-lm'] = function() {
edge2d.inputs['C-M-lm'] = function() {
if (Spline.is_catmull(this.type)) {
var idx = Math.grab_from_points(input.mouse.worldpos(), this.points.map(p => this.gameobject.this2world(p)), 25);
if (idx === -1) return;
@ -789,12 +684,12 @@ bucket.inputs['C-M-lm'] = function() {
this.points = this.points.newfirst(idx);
};
bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.";
edge2d.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.";
bucket.inputs['C-lm'] = function() { this.add_node(input.mouse.worldpos()); }
bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
edge2d.inputs['C-lm'] = function() { this.add_node(input.mouse.worldpos()); }
edge2d.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
bucket.inputs['C-M-lm'] = function() {
edge2d.inputs['C-M-lm'] = function() {
var idx = -1;
if (Spline.is_catmull(this.type))
idx = Math.grab_from_points(input.mouse.worldpos(), this.points.map(p => this.gameobject.this2world(p)), 25);
@ -806,12 +701,12 @@ bucket.inputs['C-M-lm'] = function() {
this.rm_node(idx);
};
bucket.inputs['C-M-lm'].doc = "Remove point from the spline.";
edge2d.inputs['C-M-lm'].doc = "Remove point from the spline.";
bucket.inputs.lm = function(){};
bucket.inputs.lm.released = function(){};
edge2d.inputs.lm = function(){};
edge2d.inputs.lm.released = function(){};
bucket.inputs.lb = function() {
edge2d.inputs.lb = function() {
var np = [];
this.points.forEach(function(c) {
@ -820,10 +715,10 @@ bucket.inputs.lb = function() {
this.points = np;
};
bucket.inputs.lb.doc = "Rotate the points CCW.";
bucket.inputs.lb.rep = true;
edge2d.inputs.lb.doc = "Rotate the points CCW.";
edge2d.inputs.lb.rep = true;
bucket.inputs.rb = function() {
edge2d.inputs.rb = function() {
var np = [];
this.points.forEach(function(c) {
@ -832,37 +727,27 @@ bucket.inputs.rb = function() {
this.points = np;
};
bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true;
edge2d.inputs.rb.doc = "Rotate the points CW.";
edge2d.inputs.rb.rep = true;
component.circle2d = Object.copy(collider2d, {
radius:10,
offset:[0,0],
toString() { return "circle2d"; },
/* CIRCLE */
boundingbox() {
return bbox.fromcwh([0,0], [this.radius,this.radius]);
},
function shape_maker(maker) {
return function(obj) {
if (!obj.body) obj.rigidify();
return maker(obj.body);
}
}
component.circle2d = shape_maker(os.make_circle2d);
component.poly2d = shape_maker(os.make_poly2d);
component.seg2d = shape_maker(os.make_seg2d);
hides: ['gameobject', 'id', 'shape', 'scale'],
_enghook: os.make_circle2d,
});
component.circle2d.impl = Object.mix({
toJSON:json_from_whitelist([
"pos",
"radius",
]),
set radius(x) { circle2d.set_radius(this.id,x); circle2d.sync(this.id); },
get radius() { return circle2d.get_radius(this.id); },
Object.mix(os.make_circle2d(), {
boundingbox() { return bbox.fromcwh(this.offset, [this.radius,this.radius]); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { circle2d.set_offset(this.id,x); circle2d.sync(this.id); },
get offset() { circle2d.get_offset(this.id); },
get pos() { return this.offset; },
set pos(x) { this.offset = x; },
@ -870,7 +755,6 @@ component.circle2d.impl = Object.mix({
if (typeof x === 'number') this.scale *= x;
else if (typeof x === 'object') this.scale *= x[0];
},
}, collider2d.impl);
});
return {component, SpriteAnim};

View file

@ -33,6 +33,11 @@ var entity = {
return undefined;
},
rigidify() {
this.body = os.make_body(this.transform);
},
path_from(o) {
var p = this.toString();
var c = this.master;
@ -178,9 +183,8 @@ var entity = {
for (var [prop, p] of Object.entries(ent)) {
if (!p) continue;
if (typeof p !== 'object') continue;
if (component.isComponent(p)) continue;
if (!p.comp) continue;
ent[prop] = component[p.comp].make(ent);
ent[prop] = component[p.comp](ent);
Object.merge(ent[prop], p);
ent.components[prop] = ent[prop];
};
@ -347,9 +351,8 @@ dup(diff) {
for (var key in this.components) {
this.components[key].kill?.();
this.components[key].gameobject = undefined;
this[key].enabled = false;
this.components[key].enabled = false;
delete this.components[key];
delete this[key];
}
delete this.components;
@ -393,15 +396,14 @@ dup(diff) {
return this.objects[newname];
},
add_component(comp, data, name = comp.toString()) {
if (typeof comp.make !== 'function') return;
name = obj_unique_name(name, this);
this[name] = comp.make(this);
this[name].comp = comp.toString();
this.components[name] = this[name];
if (data)
Object.assign(this[name], data);
return this[name];
add_component(comp, data) {
var name = prosperon.guid();
this.components[name] = comp(this);
if (data) {
Object.assign(this.components[name], data);
this.components[name].sync?.();
}
return this.components[name];
},
};

View file

@ -30,7 +30,7 @@ JSValue arb2js(cpArbiter *arb)
cpShape *shape2;
cpArbiterGetShapes(arb, &shape1, &shape2);
JSValue j = cpShape2js(shape2);
JSValue j = *(JSValue*)cpShapeGetUserData(shape2);
JSValue jg = body2go(body2)->ref;
@ -69,8 +69,8 @@ void register_hit(cpArbiter *arb, gameobject *go, const char *name)
cpShape *s1, *s2;
cpArbiterGetShapes(arb, &s1, &s2);
JSValue j1 = cpShape2js(s1);
JSValue j2 = cpShape2js(s2);
JSValue j1 = *(JSValue*)cpShapeGetUserData(s1);
JSValue j2 = *(JSValue*)cpShapeGetUserData(s2);
cb = JS_GetPropertyStr(js, j1, name);
if (!JS_IsUndefined(cb)) {
JSValue jarb = arb2js(arb);

View file

@ -32,6 +32,7 @@ void gameobject_apply(gameobject *go) { *go->t = go2t(go); }
static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
gameobject *go = body2go(body);
gameobject_apply(go);
cpVect pos = cpBodyGetPosition(body);
HMM_Vec2 g = warp_force((HMM_Vec3){pos.x, pos.y, 0}, go->warp_mask).xy;
if (!go) {
@ -91,9 +92,3 @@ void gameobject_free(gameobject *go) {
cpBodyFree(go->body);
free(go);
}
void gameobject_setpos(gameobject *go, cpVect vec) {
if (!go || !go->body) return;
cpBodySetPosition(go->body, vec);
// phys2d_reindex_body(go->body);
}

View file

@ -1324,17 +1324,6 @@ JSC_CCALL(physics_box_query,
return ret;
)
static void shape_query_fn(cpShape *shape, cpContactPointSet *points, JSValue *cb)
{
JSValue go = JS_DupValue(js,shape2go(shape)->ref);
script_call_sym(*cb, 1, &go);
JS_FreeValue(js, go);
}
JSC_CCALL(physics_shape_query,
//cpSpaceShapeQuery(space, ((struct phys2d_shape*)js2ptr(argv[0]))->shape, shape_query_fn, &argv[1]);
)
static void ray_query_fn(cpShape *shape, float t, cpVect n, float a, JSValue *cb)
{
JSValue argv[3] = {
@ -1429,7 +1418,6 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
MIST_FUNC_DEF(physics, point_query_nearest, 2),
MIST_FUNC_DEF(physics, ray_query, 4),
MIST_FUNC_DEF(physics, box_query, 2),
MIST_FUNC_DEF(physics, shape_query, 1),
MIST_FUNC_DEF(physics, closest_point, 3),
MIST_FUNC_DEF(physics, make_damp, 0),
MIST_FUNC_DEF(physics, make_gravity, 0),
@ -1591,7 +1579,6 @@ JSC_GETSET(gameobject, warp_mask, bitmask)
JSC_CCALL(gameobject_sleeping, return boolean2js(cpBodyIsSleeping(js2gameobject(self)->body)))
JSC_CCALL(gameobject_sleep, cpBodySleep(js2gameobject(self)->body))
JSC_CCALL(gameobject_wake, cpBodyActivate(js2gameobject(self)->body))
JSC_CCALL(gameobject_selfsync, gameobject_apply(js2gameobject(self)))
void body_shape_fn(cpBody *body, cpShape *shape, JSValue *fn) {
JSValue v = *(JSValue*)cpShapeGetUserData(shape);
@ -1600,8 +1587,7 @@ void body_shape_fn(cpBody *body, cpShape *shape, JSValue *fn) {
JSC_CCALL(gameobject_eachshape,
gameobject *g = js2gameobject(self);
JSValue fn = argv[0];
cpBodyEachShape(g->body, body_shape_fn, &fn);
cpBodyEachShape(g->body, body_shape_fn, &argv[0]);
)
void body_constraint_fn(cpBody *body, cpConstraint *c, JSValue *fn) {
@ -1648,7 +1634,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, selfsync, 0),
MIST_FUNC_DEF(gameobject, eachshape, 1),
MIST_FUNC_DEF(gameobject, eachconstraint, 1),
MIST_FUNC_DEF(gameobject, eacharbiter, 1),
@ -2096,7 +2081,7 @@ JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
JSC_CCALL(os_gc, script_gc());
JSC_SSCALL(os_eval, ret = script_eval(str, str2))
JSC_CCALL(os_make_gameobject,
JSC_CCALL(os_make_body,
gameobject *g = MakeGameobject();
g->t = js2transform(argv[0]);
ret = gameobject2js(g);
@ -2146,6 +2131,16 @@ JSC_CCALL(cpShape_body,
return JS_DupValue(js,gameobject2js(go));
)
static void shape_query_fn(cpShape *shape, cpContactPointSet *points, JSValue *cb)
{
JSValue v = *(JSValue*)cpShapeGetUserData(shape);
script_call_sym(*cb, 1, &v);
}
JSC_CCALL(cpShape_query,
cpSpaceShapeQuery(space, js2cpShape(self), shape_query_fn, &argv[0]);
)
static const JSCFunctionListEntry js_cpShape_funcs[] = {
CGETSET_ADD(cpShape, sensor),
CGETSET_ADD(cpShape, friction),
@ -2156,6 +2151,7 @@ static const JSCFunctionListEntry js_cpShape_funcs[] = {
CGETSET_ADD(cpShape, mass),
MIST_FUNC_DEF(cpShape, area, 0),
MIST_FUNC_DEF(cpShape, body, 0),
MIST_FUNC_DEF(cpShape, query, 1),
};
JSValue js_circle2d_set_radius(JSContext *js, JSValue self, JSValue val) {
@ -2203,12 +2199,13 @@ JSC_CCALL(os_make_circle2d,
JSC_CCALL(poly2d_setverts,
cpShape *s = js2cpShape(self);
HMM_Vec2 *v = js2cpvec2arr(argv[0]);
gameobject *go = shape2go(s);
cpTransform t = {0};
t.a = 1;
t.a = go->t->scale.x;
t.b = 0;
t.tx = 0;
t.c = 0;
t.d = 1;
t.d = go->t->scale.y;
t.ty = 0;
cpPolyShapeSetVerts(s, arrlen(v), v, t);
arrfree(v);
@ -2235,9 +2232,8 @@ JSC_CCALL(os_make_poly2d,
)
JSC_CCALL(seg2d_set_endpoints,
HMM_Vec2 a = js2vec2(argv[0]);
HMM_Vec2 b = js2vec2(argv[1]);
cpSegmentShapeSetEndpoints(js2cpShape(self), a.cp, b.cp);
cpSegmentShapeSetEndpoints(js2cpShape(self), js2vec2(argv[0]).cp, js2vec2(argv[1]).cp);
cpSpaceReindexShape(space, js2cpShape(self));
)
JSValue js_seg2d_set_radius(JSContext *js, JSValue self, JSValue val) {
@ -2252,10 +2248,15 @@ JSC_CCALL(seg2d_set_neighbors,
cpSegmentShapeSetNeighbors(js2cpShape(self), prev.cp, next.cp);
)
JSC_CCALL(seg2d_a, return cvec22js(cpSegmentShapeGetA(js2cpShape(self))))
JSC_CCALL(seg2d_b, return cvec22js(cpSegmentShapeGetB(js2cpShape(self))))
static const JSCFunctionListEntry js_seg2d_funcs[] = {
MIST_FUNC_DEF(seg2d, set_endpoints, 2),
CGETSET_ADD(seg2d, radius),
MIST_FUNC_DEF(seg2d, set_neighbors, 2)
MIST_FUNC_DEF(seg2d, set_neighbors, 2),
MIST_FUNC_DEF(seg2d, a, 0),
MIST_FUNC_DEF(seg2d, b, 0),
};
JSC_CCALL(os_make_seg2d,
@ -2496,7 +2497,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, reindex_static, 0),
MIST_FUNC_DEF(os, gc, 0),
MIST_FUNC_DEF(os, eval, 2),
MIST_FUNC_DEF(os, make_gameobject, 1),
MIST_FUNC_DEF(os, make_body, 1),
MIST_FUNC_DEF(os, make_circle2d, 2),
MIST_FUNC_DEF(os, make_poly2d, 2),
MIST_FUNC_DEF(os, make_seg2d, 1),

View file

@ -98,7 +98,10 @@ static JSClassDef js_##TYPE##_class = {\
#TYPE,\
.finalizer = js_##TYPE##_finalizer,\
};\
TYPE *js2##TYPE (JSValue val) { return JS_GetOpaque(val,js_##TYPE##_id); }\
TYPE *js2##TYPE (JSValue val) { \
assert(JS_GetClassID(val) == js_##TYPE##_id); \
return JS_GetOpaque(val,js_##TYPE##_id); \
}\
JSValue TYPE##2js(TYPE *n) { \
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
YughSpam("Created " #TYPE " at %p", n); \