bezier spline controls
This commit is contained in:
parent
b732d12bed
commit
444fb98125
|
@ -3,16 +3,16 @@
|
|||
Register functions with built-in drawing callbacks to have code execute at particular points in time. Some drawing functions take world coordinates, while others take screen coordinates.
|
||||
|
||||
gui
|
||||
Called before nk_gui. Screen space.
|
||||
Called every frame.
|
||||
|
||||
draw
|
||||
Called every frame. World space.
|
||||
Called every frame.
|
||||
|
||||
debug
|
||||
Called if drawing physics. World space.
|
||||
Called if drawing physics.
|
||||
|
||||
gizmo
|
||||
Called usually for editor purposes. World space.
|
||||
Called on an object if it is selected in the editor.
|
||||
|
||||
# Mum
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
/* test the GC by forcing it before each object allocation */
|
||||
//#define FORCE_GC_AT_MALLOC
|
||||
|
||||
|
||||
#ifdef CONFIG_ATOMICS
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* Removing crud I don't like */
|
||||
/* Functions that lead to bloated error prone javascript */
|
||||
/* It is EMCA6 but without a lot of builtin objects and various functions. There are no:
|
||||
* Promises and so on (Generators, async)
|
||||
* WeakMaps and so on (weakset, weakref)
|
||||
|
@ -10,7 +8,7 @@
|
|||
In addition to the removal of a bunch of stuff as seen here.
|
||||
Access prototypes through __proto__ instead of the long-winded Object.getProtoTypeOf.
|
||||
*/
|
||||
|
||||
/*
|
||||
Object.getPrototypeOf = undefined;
|
||||
Object.setPrototypeOf = undefined;
|
||||
Reflect = undefined;
|
||||
|
@ -22,6 +20,7 @@ WeakMap = undefined;
|
|||
Promise = undefined;
|
||||
Set = undefined;
|
||||
WeakSet = undefined;
|
||||
*/
|
||||
|
||||
var fmt = {};
|
||||
|
||||
|
@ -1127,7 +1126,7 @@ Object.defineProperty(Array.prototype, 'find', {
|
|||
}});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'last', {
|
||||
get: function() { return this[this.length-1]; },
|
||||
value: function() { return this[this.length-1]; },
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'at', {
|
||||
|
|
|
@ -487,7 +487,7 @@ component.polygon2d = Object.copy(collider2d, {
|
|||
|
||||
gizmo() {
|
||||
this.spoints.forEach(function(x) {
|
||||
Debug.point(world2screen(this.gameobject.this2world(x)), 3, Color.green);
|
||||
Shape.point(world2screen(this.gameobject.this2world(x)), 3, Color.green);
|
||||
}, this);
|
||||
|
||||
this.points.forEach(function(x, i) {
|
||||
|
@ -499,7 +499,8 @@ component.polygon2d = Object.copy(collider2d, {
|
|||
if (!Object.hasOwn(this,'points'))
|
||||
this.points = deep_copy(this.__proto__.points);
|
||||
|
||||
var p = Gizmos.pick_gameobject_points(pos, this.gameobject, this.points);
|
||||
var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.points);
|
||||
var p = this.points[i];
|
||||
if (p)
|
||||
return make_point_obj(this, p);
|
||||
|
||||
|
@ -553,6 +554,7 @@ component.edge2d = Object.copy(collider2d, {
|
|||
thickness:0,
|
||||
/* if type === -1, point to point */
|
||||
type: Spline.type.catmull,
|
||||
C: 1, /* when in bezier, continuity required. 0, 1 or 2. */
|
||||
looped: false,
|
||||
angle: 3, /* maximum angle between two segments */
|
||||
|
||||
|
@ -612,30 +614,18 @@ component.edge2d = Object.copy(collider2d, {
|
|||
}
|
||||
|
||||
if (this.type === Spline.type.catmull) {
|
||||
if (this.looped) {
|
||||
spoints.unshift(spoints[spoints.length-1]);
|
||||
spoints.push(spoints[1]);
|
||||
spoints.push(spoints[2]);
|
||||
} else {
|
||||
spoints.unshift(spoints[0].sub(spoints[1]).add(spoints[0]));
|
||||
spoints.push(spoints[spoints.length-1].sub(spoints[spoints.length-2]).add(spoints[spoints.length-1]));
|
||||
}
|
||||
if (this.looped)
|
||||
spoints = Spline.catmull_loop(spoints);
|
||||
else
|
||||
spoints = Spline.catmull_caps(spoints);
|
||||
|
||||
return Spline.sample_angle(this.type, spoints,this.angle);
|
||||
}
|
||||
|
||||
var tp = [];
|
||||
for (var i = 0; i < spoints.length-1; i++)
|
||||
tp.push([spoints[i+1].sub(spoints[i]), spoints[i+1].sub(spoints[i])]);
|
||||
|
||||
spoints = spoints.map((p,i) => p.concat(tp[i]));
|
||||
spoints = spoints.flat();
|
||||
|
||||
return Spline.sample_angle(this.type, spoints, this.angle);
|
||||
},
|
||||
|
||||
boundingbox() {
|
||||
return points2bb(this.points.map(x => x.scale(this.gameobject.scale)));
|
||||
},
|
||||
boundingbox() { return points2bb(this.points.map(x => x.scale(this.gameobject.scale))); },
|
||||
|
||||
hides: ['gameobject', 'id', 'shape'],
|
||||
_enghook: make_edge2d,
|
||||
|
@ -643,27 +633,50 @@ component.edge2d = Object.copy(collider2d, {
|
|||
/* EDITOR */
|
||||
gizmo() {
|
||||
if (this.type === Spline.type.catmull) {
|
||||
this.spoints().forEach(x => Debug.point(this.gameobject.this2world(x), 3, Color.teal));
|
||||
this.cpoints.forEach((x,i) => Debug.numbered_point(this.gameobject.this2world(x), i));
|
||||
this.spoints().forEach(x => Shape.point(this.gameobject.this2screen(x), 3, Color.teal));
|
||||
this.cpoints.forEach((x,i) => Debug.numbered_point(this.gameobject.this2screen(x), i));
|
||||
} else {
|
||||
for (var i = 1; i < this.cpoints.length; i+=2) {
|
||||
Debug.point(this.gameobject.this2world(this.cpoints[i]), 3, Color.green);
|
||||
Debug.line([this.gameobject.this2world(this.cpoints[i-1]), this.gameobject.this2world(this.cpoints[i])], Color.yellow);
|
||||
}
|
||||
// for (var i = 0; i < this.cpoints.length; i+=3)
|
||||
// Debug.numbered_point(this.gameobject.this2world(this.cpoints[
|
||||
}
|
||||
for (var i = 0; i < this.cpoints.length; i += 3)
|
||||
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.teal);
|
||||
|
||||
for (var i = 1; i < this.cpoints.length; i+=3) {
|
||||
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.green);
|
||||
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i+1]), i+1, Color.green);
|
||||
Shape.line([this.gameobject.this2screen(this.cpoints[i-1]), this.gameobject.this2screen(this.cpoints[i])], Color.yellow);
|
||||
Shape.line([this.gameobject.this2screen(this.cpoints[i+1]), this.gameobject.this2screen(this.cpoints[i+2])], Color.yellow);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
finish_center(change) {
|
||||
this.cpoints = this.cpoints.map(function(x) { return x.sub(change); });
|
||||
},
|
||||
finish_center(change) { this.cpoints = this.cpoints.map(function(x) { return x.sub(change); }); },
|
||||
|
||||
pick(pos) {
|
||||
var p = Gizmos.pick_gameobject_points(pos, this.gameobject, this.cpoints);
|
||||
if (p)
|
||||
return make_point_obj(this, p);
|
||||
var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.cpoints);
|
||||
var p = this.cpoints[i];
|
||||
var that = this.gameobject;
|
||||
var me = this;
|
||||
if (p) {
|
||||
var o = {
|
||||
pos: p,
|
||||
sync: me.sync.bind(me)
|
||||
};
|
||||
if (Spline.bezier_is_handle(this.cpoints,i))
|
||||
o.move = function(d) {
|
||||
d = that.dir_world2this(d);
|
||||
p.x += d.x;
|
||||
p.y += d.y;
|
||||
Spline.bezier_cp_mirror(me.cpoints,i);
|
||||
};
|
||||
else
|
||||
o.move = function(d) {
|
||||
d = that.dir_world2this(d);
|
||||
p.x += d.x;
|
||||
p.y += d.y;
|
||||
var pp = Spline.bezier_point_handles(me.cpoints,i);
|
||||
pp.forEach(ph => me.cpoints[ph] = me.cpoints[ph].add(d));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
@ -741,10 +754,25 @@ bucket.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.";
|
||||
|
||||
bucket.inputs['C-c'] = function() { this.type = Spline.type.catmull; };
|
||||
bucket.inputs['C-c'] = function() {
|
||||
switch(this.type) {
|
||||
case Spline.type.bezier:
|
||||
this.cpoints = Spline.bezier2catmull(this.cpoints);
|
||||
break;
|
||||
}
|
||||
this.type = Spline.type.catmull;
|
||||
};
|
||||
|
||||
bucket.inputs['C-c'].doc = "Set type of spline to catmull-rom.";
|
||||
|
||||
bucket.inputs['C-b'] = function() { this.type = Spline.type.bezier; };
|
||||
bucket.inputs['C-b'] = function() {
|
||||
switch(this.type) {
|
||||
case Spline.type.catmull:
|
||||
this.cpoints = Spline.catmull2bezier(Spline.catmull_caps(this.cpoints));
|
||||
break;
|
||||
}
|
||||
this.type = Spline.type.bezier;
|
||||
};
|
||||
|
||||
bucket.inputs['C-o'] = function() { this.type = -1; };
|
||||
bucket.inputs['C-o'].doc = "Set spline to linear.";
|
||||
|
@ -760,10 +788,10 @@ bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.
|
|||
bucket.inputs['C-lm'] = function() {
|
||||
var idx = 0;
|
||||
|
||||
if (this.cpoints.length >= 2) {
|
||||
idx = cmd(59, screen2world(Mouse.pos).sub(this.gameobject.pos), this.cpoints, 1000);
|
||||
if (idx === -1) return;
|
||||
}
|
||||
if (this.cpoints.length >= 2)
|
||||
idx = cmd(59, screen2world(Mouse.pos).sub(this.gameobject.pos), this.cpoints, 400);
|
||||
|
||||
console.say("new point");
|
||||
|
||||
if (idx === this.cpoints.length)
|
||||
this.cpoints.push(this.gameobject.world2this(screen2world(Mouse.pos)));
|
||||
|
@ -836,30 +864,10 @@ component.circle2d.impl = Object.mix({
|
|||
/* ASSETS */
|
||||
|
||||
var Texture = {
|
||||
mipmaps(path, x) {
|
||||
cmd(94, path, x);
|
||||
},
|
||||
mipmaps(path, x) { cmd(94, path, x); },
|
||||
|
||||
sprite(path, x) {
|
||||
cmd(95, path, x);
|
||||
},
|
||||
sprite(path, x) { cmd(95, path, x); },
|
||||
};
|
||||
|
||||
var Resources = {
|
||||
load(path) {
|
||||
if (path in this)
|
||||
return this[path];
|
||||
|
||||
var src = {};
|
||||
this[path] = src;
|
||||
src.path = path;
|
||||
|
||||
if (!IO.exists(`${path}.asset`))
|
||||
return this[path];
|
||||
|
||||
var data = JSON.parse(IO.slurp(`${path}.asset`));
|
||||
Object.assign(src,data);
|
||||
return this[path];
|
||||
|
||||
},
|
||||
};
|
||||
Texture.mipmaps.doc = "Return true if the texture has mipmaps.";
|
||||
Texture.sprite.do = "Return true if the texture is treated as a sprite.";
|
||||
|
|
122
scripts/debug.js
122
scripts/debug.js
|
@ -1,13 +1,35 @@
|
|||
var Gizmos = {
|
||||
pick_gameobject_points(worldpos, gameobject, points) {
|
||||
var idx = Math.grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
if (idx === -1) return undefined;
|
||||
return points[idx];
|
||||
},
|
||||
};
|
||||
|
||||
/* All draw in screen space */
|
||||
var Shape = {
|
||||
circle(pos, radius, color) { cmd(115, pos, radius, color); },
|
||||
|
||||
point(pos,size,color) {
|
||||
color ??= Color.blue;
|
||||
Shape.circle(pos,size,color);
|
||||
},
|
||||
|
||||
arrow(start, end, color, capsize) {
|
||||
color ??= Color.red;
|
||||
capsize ??= 4;
|
||||
cmd(81, start, end, color, capsize);
|
||||
},
|
||||
|
||||
poly(points, color) { cmd_points(0,points,color); },
|
||||
|
||||
box(pos, wh, color) {
|
||||
color ??= Color.white;
|
||||
cmd(53, pos, wh, color);
|
||||
},
|
||||
|
||||
line(points, color, type, thickness) {
|
||||
thickness ??= 1;
|
||||
type ??= 0;
|
||||
color ??= Color.white;
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
cmd(83, points, color, thickness);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var Debug = {
|
||||
|
@ -27,38 +49,17 @@ var Debug = {
|
|||
cmd(47, width, span, color);
|
||||
},
|
||||
|
||||
point(pos, size, color) {
|
||||
color = color ? color : Color.blue;
|
||||
Shape.circle(pos, size, color);
|
||||
// cmd(51, pos, size,color);
|
||||
},
|
||||
|
||||
coordinate(pos, size, color) { GUI.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color); },
|
||||
|
||||
arrow(start, end, color, capsize) {
|
||||
color = color ? color : Color.red;
|
||||
if (!capsize)
|
||||
capsize = 4;
|
||||
cmd(81, start, end, color, capsize);
|
||||
},
|
||||
|
||||
poly(points, color) {
|
||||
cmd_points(0,points,color);
|
||||
},
|
||||
|
||||
boundingbox(bb, color) {
|
||||
color ??= Color.white;
|
||||
cmd_points(0, bb2points(bb), color);
|
||||
},
|
||||
|
||||
box(pos, wh, color) {
|
||||
numbered_point(pos, n, color) {
|
||||
color ??= Color.white;
|
||||
cmd(53, pos, wh, color);
|
||||
},
|
||||
|
||||
numbered_point(pos, n) {
|
||||
Debug.point(pos, 3);
|
||||
GUI.text(n, pos.add([0,4]), 1);
|
||||
Shape.point(pos, 3, color);
|
||||
GUI.text(n, pos.add([0,4]), 1, color);
|
||||
},
|
||||
|
||||
phys_drawing: false,
|
||||
|
@ -75,22 +76,7 @@ var Debug = {
|
|||
Register.debug.register(fn,obj);
|
||||
},
|
||||
|
||||
gameobject(go) {
|
||||
|
||||
},
|
||||
|
||||
line(points, color, type, thickness) {
|
||||
thickness ??= 1;
|
||||
type ??= 0;
|
||||
|
||||
if (!color)
|
||||
color = Color.white;
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
cmd(83, points, color, thickness);
|
||||
}
|
||||
},
|
||||
gameobject(go) { cmd(15, go.body); },
|
||||
|
||||
draw_bb: false,
|
||||
draw_gizmos: false,
|
||||
|
@ -136,8 +122,8 @@ Debug.Options.Color = {
|
|||
var Gizmos = {
|
||||
pick_gameobject_points(worldpos, gameobject, points) {
|
||||
var idx = Math.grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
if (idx === -1) return null;
|
||||
return points[idx];
|
||||
if (idx === -1) return undefined;
|
||||
return idx;
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -146,19 +132,51 @@ var Profile = {
|
|||
ns(ticks) { return cmd(128, ticks); },
|
||||
us(ticks) { return cmd(129, ticks); },
|
||||
ms(ticks) { return cmd(130, ticks); },
|
||||
best_t(ns) {
|
||||
var e = ns;
|
||||
var qq = 'ns';
|
||||
if (e > 1000) {
|
||||
e /= 1000;
|
||||
qq = 'us';
|
||||
if (e > 1000) {
|
||||
e /= 1000;
|
||||
qq = 'ms';
|
||||
}
|
||||
}
|
||||
return {
|
||||
time: e,
|
||||
unit: qq
|
||||
};
|
||||
},
|
||||
cpu(fn, times, q) {
|
||||
times ??= 1;
|
||||
q ??= "ns";
|
||||
q ??= "unnamed";
|
||||
var start = Profile.tick_now();
|
||||
for (var i = 0; i < times; i++)
|
||||
fn();
|
||||
|
||||
var elapsed = Profile.tick_now() - start;
|
||||
Log.say(`Profiled in ${Profile[q](elapsed)/times} avg ${q}.`);
|
||||
var avgt = Profile.best_t(elapsed/times);
|
||||
var totalt = Profile.best_t(elapsed);
|
||||
|
||||
console.say(`Profile [${q}]: ${avgt.time.toFixed(3)} ${avgt.unit} average [${totalt.time.toFixed(3)} ${totalt.unit} for ${times} loops]`);
|
||||
},
|
||||
|
||||
get fps() { return sys_cmd(8); },
|
||||
};
|
||||
|
||||
|
||||
|
||||
Profile.test = {
|
||||
barecall() { profile(0); },
|
||||
unpack_num(n) { profile(1,n); },
|
||||
unpack_array(n) { profile(2,n); },
|
||||
pack_num() { profile(3); },
|
||||
pack_string() { profile(6); },
|
||||
unpack_string(s) { profile(4,s); },
|
||||
unpack_32farr(a) { profile(5,a); },
|
||||
};
|
||||
|
||||
Profile.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`;
|
||||
|
||||
/* These controls are available during editing, and during play of debug builds */
|
||||
|
|
|
@ -270,7 +270,7 @@ var editor = {
|
|||
if (!dif) return;
|
||||
|
||||
if (this.snapshots.length !== 0) {
|
||||
var ddif = ediff(dif, this.snapshots.last);
|
||||
var ddif = ediff(dif, this.snapshots.last());
|
||||
if (!ddif) return;
|
||||
dif = ddif;
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ var editor = {
|
|||
root = root ? root + "." : root;
|
||||
Object.entries(obj.objects).forEach(function(x) {
|
||||
var p = root + x[0];
|
||||
GUI.text(p, world2screen(x[1].worldpos()), 1, editor.color_depths[depth]);
|
||||
GUI.text(p, x[1].screenpos(), 1, editor.color_depths[depth]);
|
||||
editor.draw_objects_names(x[1], p, depth+1);
|
||||
});
|
||||
},
|
||||
|
@ -367,14 +367,14 @@ var editor = {
|
|||
|
||||
color_depths: [],
|
||||
draw() {
|
||||
Debug.point(world2screen(this.cursor), 2, Color.green);
|
||||
Shape.point(world2screen(this.cursor), 2, Color.green);
|
||||
|
||||
this.selectlist.forEach(x => {
|
||||
if ('gizmo' in x && typeof x['gizmo'] === 'function' )
|
||||
x.gizmo();
|
||||
});
|
||||
|
||||
Debug.line(bb2points(cwh2bb([0,0],[Game.native.x,Game.native.y])).wrapped(1), Color.yellow);
|
||||
Shape.line(bb2points(cwh2bb([0,0],[Game.native.x,Game.native.y])).wrapped(1), Color.yellow);
|
||||
|
||||
/* Draw selection box */
|
||||
if (this.sel_start) {
|
||||
|
@ -389,7 +389,7 @@ var editor = {
|
|||
wh[1] = Math.abs(endpos[1] - this.sel_start[1]);
|
||||
var bb = cwh2bb(c,wh);
|
||||
Debug.boundingbox(bb, Color.Editor.select.alpha(0.1));
|
||||
Debug.line(bb2points(bb).wrapped(1), Color.white);
|
||||
Shape.line(bb2points(bb).wrapped(1), Color.white);
|
||||
}
|
||||
|
||||
Debug.coordinate([0,0]);
|
||||
|
@ -405,9 +405,7 @@ var editor = {
|
|||
if (this.comp_info && this.sel_comp)
|
||||
GUI.text(Input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
||||
|
||||
|
||||
// GUI.text(editor.edit_level.worldpos().map(x => Math.round(x)), world2screen(editor.edit_level.worldpos()), 1, Color.red);
|
||||
GUI.text("+", world2screen(editor.edit_level.worldpos()), 1, Color.blue);
|
||||
GUI.text("+", editor.edit_level.screenpos(), 1, Color.blue);
|
||||
|
||||
var thiso = editor.get_this();
|
||||
var clvl = thiso;
|
||||
|
@ -454,21 +452,20 @@ var editor = {
|
|||
x._ed.check_dirty();
|
||||
if (x._ed.dirty) sname += "*";
|
||||
|
||||
GUI.text(sname, world2screen(x.worldpos()).add([0, 32]), 1, Color.editor.ur);
|
||||
GUI.text(x.worldpos().map(function(x) { return Math.round(x); }), world2screen(x.worldpos()), 1, Color.white);
|
||||
// Debug.arrow(world2screen(x.worldpos()), world2screen(x.worldpos().add(x.up().scale(40))), Color.yellow, 1);
|
||||
GUI.text(sname, x.screenpos().add([0, 32]), 1, Color.editor.ur);
|
||||
GUI.text(x.worldpos().map(function(x) { return Math.round(x); }), x.screenpos(), 1, Color.white);
|
||||
});
|
||||
|
||||
Object.entries(thiso.objects).forEach(function(x) {
|
||||
var p = x[1]._ed.namestr();
|
||||
GUI.text(p, world2screen(x[1].worldpos().add([0,16])),1,editor.color_depths[depth]);
|
||||
GUI.text(p, x[1].screenpos().add([0,16]),1,editor.color_depths[depth]);
|
||||
});
|
||||
|
||||
var mg = physics.pos_query(Mouse.worldpos);
|
||||
|
||||
if (mg) {
|
||||
var p = mg.path_from(thiso);
|
||||
GUI.text(p, world2screen(Mouse.worldpos),1,Color.teal);
|
||||
GUI.text(p, Mouse.screenpos(),1,Color.teal);
|
||||
}
|
||||
|
||||
if (this.selectlist.length === 1) {
|
||||
|
@ -476,7 +473,7 @@ var editor = {
|
|||
for (var key in this.selectlist[0].components) {
|
||||
var selected = this.sel_comp === this.selectlist[0].components[key];
|
||||
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
|
||||
GUI.text(str, world2screen(this.selectlist[0].worldpos()).add([0,-16*(i++)]));
|
||||
GUI.text(str, this.selectlist[0].screenpos().add([0,-16*(i++)]));
|
||||
}
|
||||
|
||||
if (this.sel_comp) {
|
||||
|
@ -486,7 +483,7 @@ var editor = {
|
|||
|
||||
editor.edit_level.objects.forEach(function(obj) {
|
||||
if (!obj._ed.selectable)
|
||||
GUI.image("icons/icons8-lock-16.png", world2screen(obj.worldpos()));
|
||||
GUI.image("icons/icons8-lock-16.png", obj.screenpos());
|
||||
});
|
||||
|
||||
Debug.draw_grid(1, editor.grid_size, Color.Editor.grid.alpha(0.3));
|
||||
|
@ -1684,7 +1681,7 @@ var objectexplorer = Object.copy(inputpanel, {
|
|||
}
|
||||
|
||||
if (!this.previous.empty)
|
||||
items.push(Mum.text({str:"prev: " + this.previous.last, action: this.prev_obj}));
|
||||
items.push(Mum.text({str:"prev: " + this.previous.last(), action: this.prev_obj}));
|
||||
|
||||
Object.getOwnPropertyNames(this.obj).forEach(key => {
|
||||
var descriptor = Object.getOwnPropertyDescriptor(this.obj, key);
|
||||
|
|
|
@ -95,12 +95,11 @@ var timer = {
|
|||
load("scripts/animation.js");
|
||||
|
||||
var Render = {
|
||||
normal() {
|
||||
cmd(67);
|
||||
},
|
||||
normal() { cmd(67);},
|
||||
wireframe() { cmd(68); },
|
||||
|
||||
pass() {
|
||||
|
||||
wireframe() {
|
||||
cmd(68);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -125,7 +124,7 @@ function world2screen(worldpos) { return Game.camera.world2view(worldpos); }
|
|||
var Register = {
|
||||
kbm_input(mode, btn, state, ...args) {
|
||||
if (state === 'released') {
|
||||
btn = btn.split('-').last;
|
||||
btn = btn.split('-').last();
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
|
@ -338,6 +337,45 @@ Spline.sample_angle = function(type, points, angle) {
|
|||
return spline_cmd(0, type, points[0].length, points, angle);
|
||||
}
|
||||
|
||||
Spline.bezier2catmull = function(b)
|
||||
{
|
||||
var c = [];
|
||||
for (var i = 0; i < b.length; i += 3)
|
||||
c.push(b[i]);
|
||||
return c;
|
||||
}
|
||||
|
||||
Spline.catmull2bezier = function(c)
|
||||
{
|
||||
var b = [];
|
||||
for (var i = 1; i < c.length-2; i++) {
|
||||
b.push(c[i].slice());
|
||||
b.push(c[i+1].sub(c[i-1]).scale(0.25).add(c[i]));
|
||||
b.push(c[i].sub(c[i+2]).scale(0.25).add(c[i+1]));
|
||||
}
|
||||
b.push(c[c.length-2]);
|
||||
return b;
|
||||
}
|
||||
|
||||
Spline.catmull_loop = function(cp)
|
||||
{
|
||||
cp = cp.slice();
|
||||
cp.unshift(cp.last());
|
||||
cp.push(cp[1]);
|
||||
cp.push(cp[2]);
|
||||
return cp;
|
||||
}
|
||||
|
||||
Spline.catmull_caps = function(cp)
|
||||
{
|
||||
cp = cp.slice();
|
||||
cp.unshift(cp[0].sub(cp[1]).add(cp[0]));
|
||||
cp.push(cp.last().sub(cp.at(-2).add(cp.last())));
|
||||
return cp;
|
||||
}
|
||||
|
||||
Spline.catmull2bezier.doc = "Given a set of control points C for a camtull-rom type curve, return a set of cubic bezier points to give the same curve."
|
||||
|
||||
Spline.type = {
|
||||
catmull: 0,
|
||||
bezier: 1,
|
||||
|
@ -345,6 +383,40 @@ Spline.type = {
|
|||
cubichermite: 3
|
||||
};
|
||||
|
||||
Spline.bezier_tan_partner = function(points, i)
|
||||
{
|
||||
if (i%3 === 0) return undefined;
|
||||
var partner_i = (i%3) === 2 ? i-1 : i+1;
|
||||
return points[i];
|
||||
}
|
||||
|
||||
Spline.bezier_cp_mirror = function(points, i)
|
||||
{
|
||||
if (i%3 === 0) return undefined;
|
||||
var partner_i = (i%3) === 2 ? i+2 : i-2;
|
||||
var node_i = (i%3) === 2 ? i+1 : i-1;
|
||||
if (partner_i >= points.length || node_i >= points.length) return;
|
||||
points[partner_i] = points[node_i].sub(points[i]).add(points[node_i]);
|
||||
}
|
||||
|
||||
Spline.bezier_point_handles = function(points, i)
|
||||
{
|
||||
if (!Spline.bezier_is_node(points,i)) return [];
|
||||
var a = i-1;
|
||||
var b = i+1;
|
||||
var c = []
|
||||
if (a > 0)
|
||||
c.push(a);
|
||||
|
||||
if (b < points.length)
|
||||
c.push(b);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Spline.bezier_is_node = function(points, i) { return i%3 === 0; }
|
||||
Spline.bezier_is_handle = function(points, i) { return !Spline.bezier_is_node(points,i); }
|
||||
|
||||
load("scripts/components.js");
|
||||
|
||||
var Game = {
|
||||
|
|
|
@ -181,6 +181,7 @@ var gameobject = {
|
|||
set_body(2,this.body,x);
|
||||
this.objects.forEach((o,i) => o.set_worldpos(this.this2world(poses[i])));
|
||||
},
|
||||
screenpos() { return world2screen(this.worldpos()); },
|
||||
|
||||
worldangle() { return Math.rad2deg(q_body(2,this.body))%360; },
|
||||
sworldangle(x) { set_body(0,this.body,Math.deg2rad(x)); },
|
||||
|
@ -280,7 +281,8 @@ var gameobject = {
|
|||
shove(vec) { set_body(12,this.body,vec);},
|
||||
shove_at(vec, at) { set_body(14,this.body,vec,at); },
|
||||
world2this(pos) { return cmd(70, this.body, pos); },
|
||||
this2world(pos) { return cmd(71, this.body,pos); },
|
||||
this2world(pos) { return cmd(71, this.body, pos); },
|
||||
this2screen(pos) { return world2screen(this.this2world(pos)); },
|
||||
dir_world2this(dir) { return cmd(160, this.body, dir); },
|
||||
dir_this2world(dir) { return cmd(161, this.body, dir); },
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/*
|
||||
GUI functions take screen space coordinates
|
||||
*/
|
||||
|
||||
var GUI = {
|
||||
text(str, pos, size, color, wrap, anchor, cursor) {
|
||||
size ??= 1;
|
||||
|
@ -271,7 +275,7 @@ GUI.window = function(pos, wh, color)
|
|||
var p = pos.slice();
|
||||
p.x += wh.x/2;
|
||||
p.y += wh.y/2;
|
||||
Debug.box(p,wh,color);
|
||||
Shape.box(p,wh,color);
|
||||
}
|
||||
|
||||
GUI.flush = function() { cmd(141); };
|
||||
|
|
|
@ -4,9 +4,9 @@ var Input = {
|
|||
};
|
||||
|
||||
var Mouse = {
|
||||
get pos() {
|
||||
return cmd(45);
|
||||
},
|
||||
get pos() { return cmd(45); },
|
||||
|
||||
screenpos() { return cmd(45); },
|
||||
|
||||
get worldpos() {
|
||||
return screen2world(cmd(45));
|
||||
|
|
|
@ -69,10 +69,7 @@ JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
|
|||
(byte & 0x02 ? '1' : '0'), \
|
||||
(byte & 0x01 ? '1' : '0')
|
||||
|
||||
void js_setprop_str(JSValue obj, const char *prop, JSValue v)
|
||||
{
|
||||
JS_SetPropertyStr(js, obj, prop, v);
|
||||
}
|
||||
void js_setprop_str(JSValue obj, const char *prop, JSValue v) { JS_SetPropertyStr(js, obj, prop, v); }
|
||||
|
||||
JSValue jstzone()
|
||||
{
|
||||
|
@ -140,18 +137,10 @@ int js2int(JSValue v) {
|
|||
return i;
|
||||
}
|
||||
|
||||
JSValue int2js(int i) {
|
||||
return JS_NewInt64(js, i);
|
||||
}
|
||||
JSValue int2js(int i) { return JS_NewInt64(js, i); }
|
||||
|
||||
JSValue str2js(const char *c) {
|
||||
return JS_NewString(js, c);
|
||||
}
|
||||
|
||||
const char *js2str(JSValue v)
|
||||
{
|
||||
return JS_ToCString(js, v);
|
||||
}
|
||||
JSValue str2js(const char *c) { return JS_NewString(js, c); }
|
||||
const char *js2str(JSValue v) { return JS_ToCString(js, v); }
|
||||
|
||||
JSValue strarr2js(const char **c)
|
||||
{
|
||||
|
@ -197,7 +186,7 @@ struct glrect js2glrect(JSValue v) {
|
|||
return rect;
|
||||
}
|
||||
|
||||
JSValue js_arridx(JSValue v, int idx) { return js_getpropidx( v, idx); }
|
||||
JSValue js_arridx(JSValue v, int idx) { return js_getpropidx(v, idx); }
|
||||
|
||||
int js_arrlen(JSValue v) {
|
||||
int len;
|
||||
|
@ -270,9 +259,23 @@ cpBitmask js2bitmask(JSValue v) {
|
|||
HMM_Vec2 *js2cpvec2arr(JSValue v) {
|
||||
HMM_Vec2 *arr = NULL;
|
||||
int n = js_arrlen(v);
|
||||
for (int i = 0; i < n; i++)
|
||||
arrput(arr, js2vec2(js_getpropidx( v, i)));
|
||||
arrsetlen(arr,n);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
arr[i] = js2vec2(js_getpropidx( v, i));
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
HMM_Vec2 *jsfloat2vec(JSValue v)
|
||||
{
|
||||
size_t s;
|
||||
void *buf = JS_GetArrayBuffer(js, &s, v);
|
||||
HMM_Vec2 *arr = NULL;
|
||||
int n = s/2;
|
||||
n /= sizeof(float);
|
||||
// arrsetcap(arr,n);
|
||||
// memcpy(arr,buf,s);
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -401,6 +404,8 @@ JSValue duk_spline_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
arrfree(points);
|
||||
|
||||
if (!samples)
|
||||
|
@ -573,7 +578,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 15:
|
||||
// music_stop();
|
||||
gameobject_draw_debug(js2gameobject(argv[1]));
|
||||
break;
|
||||
|
||||
case 16:
|
||||
|
@ -1054,7 +1059,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 128:
|
||||
YughWarn("%g",stm_ms(9737310));
|
||||
ret = JS_NewFloat64(js, stm_ns(js2uint64(argv[1])));
|
||||
break;
|
||||
|
||||
|
@ -1842,6 +1846,34 @@ JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst
|
|||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
const char *STRTEST = "TEST STRING";
|
||||
|
||||
JSValue duk_profile(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
{
|
||||
int cmd = js2int(argv[0]);
|
||||
switch(cmd) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
js2number(argv[1]);
|
||||
break;
|
||||
case 2:
|
||||
js2cpvec2arr(argv[1]);
|
||||
break;
|
||||
case 3:
|
||||
return num2js(1.0);
|
||||
case 4:
|
||||
js2str(argv[1]);
|
||||
break;
|
||||
case 5:
|
||||
jsfloat2vec(argv[1]);
|
||||
break;
|
||||
case 6:
|
||||
return JS_NewStringLen(js, STRTEST, sizeof(*STRTEST));
|
||||
}
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
#define DUK_FUNC(NAME, ARGS) JS_SetPropertyStr(js, globalThis, #NAME, JS_NewCFunction(js, duk_##NAME, #NAME, ARGS));
|
||||
|
||||
void ffi_load() {
|
||||
|
@ -1880,6 +1912,8 @@ void ffi_load() {
|
|||
|
||||
DUK_FUNC(inflate_cpv, 3)
|
||||
|
||||
DUK_FUNC(profile, 2)
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
|
||||
JS_NewClassID(&js_ptr_id);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define RESOURCES_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stb_ds.h"
|
||||
#include "string.h"
|
||||
|
||||
extern char *DATA_PATH;
|
||||
|
||||
|
|
Loading…
Reference in a new issue