improve spawn callback; more robust deletion of actors

This commit is contained in:
2025-01-23 15:27:40 -06:00
parent 9e6f5e7eb1
commit d174aa88d6
17 changed files with 429 additions and 884 deletions

View File

@@ -1,60 +1,22 @@
Number.roman = { Object.defineProperty(Array.prototype, "dofilter", {
M: 1000, value: function array_dofilter(fn) {
D: 500, for (let i = 0; i < this.length; i++) {
C: 100, if (!fn.call(this, this[i], i, this)) {
L: 50, this.splice(i, 1);
X: 10, i--;
V: 5, }
I: 1, }
}; return this;
},
});
function deep_copy(from) { Object.defineProperty(Array.prototype, "delete", {
return json.decode(json.encode(from)); value: function(item) {
} var idx = this.indexOf(item);
if (idx > -1) this.splice(idx,1)
Object.methods = function (o) { return undefined
var m = [];
Object.keys(o).forEach(function (k) {
if (typeof o[k] === "function") m.push(k);
});
return m;
};
Object.methods.doc = "Retun an array of all functions an object has access to.";
Object.dig = function (obj, path, def = {}) {
var pp = path.split(".");
for (var i = 0; i < pp.length - 1; i++) {
obj = obj[pp[i]] = obj[pp[i]] || {};
} }
obj[pp[pp.length - 1]] = def; });
return def;
};
Object.rkeys = function (o) {
var keys = [];
Object.keys(o).forEach(function (key) {
keys.push(key);
if (Object.isObject(o[key])) keys.push(Object.rkeys(o[key]));
});
return keys;
};
Object.readonly = function (o, name, msg) {
var tmp = {};
var prop = Object.getOwnPropertyDescriptor(o, name);
if (!prop) {
console.error(`Attempted to make property ${name} readonly, but it doesn't exist on ${o}.`);
return;
}
Object.defineProperty(tmp, name, prop);
prop.get = function () {
return tmp[name];
};
prop.set = function () {
console.warn(`Attempted to set readonly property ${name}`);
};
Object.defineProperty(o, name, prop);
};
Object.mixin = function (target, source) { Object.mixin = function (target, source) {
if (typeof source !== "object") return target; if (typeof source !== "object") return target;
@@ -62,155 +24,6 @@ Object.mixin = function (target, source) {
return target; return target;
}; };
Object.mix = function (...objs) {
var n = {};
for (var o of objs) Object.mixin(n, o);
return n;
};
Object.deepmixin = function (target, source) {
var o = source;
while (o !== Object.prototype) {
Object.mixin(target, o);
o = o.__proto__;
}
};
Object.deepfreeze = function (obj) {
for (var key in obj) {
if (typeof obj[key] === "object") Object.deepfreeze(obj[key]);
}
Object.freeze(obj);
};
/* Goes through each key and overwrites if it's present */
Object.dainty_assign = function (target, source) {
Object.keys(source).forEach(function (k) {
if (typeof source[k] === "function") return;
if (!(k in target)) return;
if (Array.isArray(source[k])) target[k] = deep_copy(source[k]);
else if (Object.isObject(source[k])) Object.dainty_assign(target[k], source[k]);
else target[k] = source[k];
});
};
Object.isObject = function (o) {
return o instanceof Object && !(o instanceof Array);
};
Object.setter_assign = function (target, source) {
for (var key in target) if (Object.isAccessor(target, key) && typeof source[key] !== "undefined") target[key] = source[key];
};
Object.containingKey = function (obj, prop) {
if (typeof obj !== "object") return undefined;
if (!(prop in obj)) return undefined;
var o = obj;
while (o.__proto__ && !Object.hasOwn(o, prop)) o = o.__proto__;
return o;
};
Object.access = function (obj, name) {
var dig = name.split(".");
for (var i of dig) {
obj = obj[i];
if (!obj) return undefined;
}
return obj;
};
Object.isAccessor = function (obj, prop) {
var o = Object.containingKey(obj, prop);
if (!o) return false;
var desc = Object.getOwnPropertyDescriptor(o, prop);
if (!desc) return false;
if (desc.get || desc.set) return true;
return false;
};
Object.mergekey = function (o1, o2, k) {
if (!o2) return;
if (typeof o2[k] === "object") {
if (Array.isArray(o2[k])) o1[k] = deep_copy(o2[k]);
else {
if (!o1[k]) o1[k] = {};
if (typeof o1[k] === "object") Object.merge(o1[k], o2[k]);
else o1[k] = o2[k];
}
} else o1[k] = o2[k];
};
/* Same as merge from Ruby */
/* Adds objs key by key to target */
Object.merge = function (target, ...objs) {
for (var obj of objs) for (var key of Object.keys(obj)) Object.mergekey(target, obj, key);
return target;
};
Object.totalmerge = function (target, ...objs) {
for (var obj of objs) for (var key in obj) Object.mergekey(target, obj, key);
return target;
};
/* Returns a new object with undefined, null, and empty values removed. */
Object.compact = function (obj) {};
Object.totalassign = function (to, from) {
for (var key in from) to[key] = from[key];
};
/* Prototypes out an object and assigns values */
Object.copy = function (proto, ...objs) {
var c = Object.create(proto);
for (var obj of objs) Object.mixin(c, obj);
return c;
};
/* OBJECT DEFININTIONS */
Object.defHidden = function (obj, prop) {
Object.defineProperty(obj, prop, { enumerable: false, writable: true });
};
Object.hide = function hide(obj, ...props) {
for (var prop of props) {
var p = Object.getOwnPropertyDescriptor(obj, prop);
if (p && p.enumerable)
Object.defineProperty(obj, prop, {...p, enumerable:false});
}
};
Object.enumerable = function (obj, val, ...props) {
for (var prop of props) {
p = Object.getOwnPropertyDescriptor(obj, prop);
if (!p) continue;
p.enumerable = val;
Object.defineProperty(obj, prop, p);
}
};
Object.unhide = function (obj, ...props) {
for (var prop of props) {
var p = Object.getOwnPropertyDescriptor(obj, prop);
if (!p) continue;
p.enumerable = true;
Object.defineProperty(obj, prop, p);
}
};
Object.defineProperty(Object.prototype, "obscure", {
value: function (name) {
Object.defineProperty(this, name, { enumerable: false });
},
});
Object.defineProperty(Object.prototype, "mixin", { Object.defineProperty(Object.prototype, "mixin", {
value: function mixin(obj) { value: function mixin(obj) {
if (typeof obj === "string") obj = use(obj); if (typeof obj === "string") obj = use(obj);
@@ -219,108 +32,27 @@ Object.defineProperty(Object.prototype, "mixin", {
}, },
}); });
Object.defineProperty(Object.prototype, "hasOwn", {
value: function (x) {
return this.hasOwnProperty(x);
},
});
Object.defineProperty(Object.prototype, "defn", {
value: function (name, val) {
Object.defineProperty(this, name, {
value: val,
writable: true,
configurable: true,
});
},
});
Object.defineProperty(Object.prototype, "nulldef", {
value: function (name, val) {
if (!this.hasOwnProperty(name)) this[name] = val;
},
});
Object.defineProperty(Object.prototype, "prop_obj", {
value: function () {
return JSON.parse(JSON.stringify(this));
},
});
/* defc 'define constant'. Defines a value that is not writable. */
Object.defineProperty(Object.prototype, "defc", {
value: function (name, val) {
Object.defineProperty(this, name, {
value: val,
writable: false,
enumerable: true,
configurable: false,
});
},
});
Object.defineProperty(Object.prototype, "stick", {
value: function (prop) {
Object.defineProperty(this, prop, { writable: false });
},
});
Object.defineProperty(Object.prototype, "harden", {
value: function (prop) {
Object.defineProperty(this, prop, {
writable: false,
configurable: false,
enumerable: false,
});
},
});
Object.defineProperty(Object.prototype, "deflock", {
value: function (prop) {
Object.defineProperty(this, prop, { configurable: false });
},
});
Object.defineProperty(Object.prototype, "forEach", {
value: function (fn) {
Object.values(this).forEach(fn);
},
});
Object.empty = function empty(obj) {
return Object.keys(obj).length === 0;
};
Object.defineProperty(Object.prototype, "nth", {
value: function (x) {
if (this.empty || x >= Object.keys(this).length) return null;
return this[Object.keys(this)[x]];
},
});
Object.defineProperty(Object.prototype, "filter", {
value: function (fn) {
return Object.values(this).filter(fn);
},
});
Object.defineProperty(Object.prototype, "push", {
value: function (val) {
var str = val.toString();
str = str.replaceAll(".", "_");
var n = 1;
var t = str;
while (Object.hasOwn(this, t)) {
t = str + n;
n++;
}
this[t] = val;
return t;
},
});
/* STRING DEFS */ /* STRING DEFS */
Object.defineProperty(String.prototype, "rm", {
value: function (index, endidx = index + 1) {
return this.slice(0, index) + this.slice(endidx);
},
});
Object.defineProperty(String.prototype, "tolast", {
value: function (val) {
var idx = this.lastIndexOf(val);
if (idx === -1) return this.slice();
return this.slice(0, idx);
},
});
Object.defineProperty(String.prototype, "dir", {
value: function () {
if (!this.includes("/")) return "";
return this.tolast("/");
},
});
Object.defineProperty(String.prototype, "next", { Object.defineProperty(String.prototype, "next", {
value: function (char, from) { value: function (char, from) {
@@ -346,12 +78,10 @@ Object.defineProperty(String.prototype, "next", {
}); });
Object.defineProperty(String.prototype, "prev", { Object.defineProperty(String.prototype, "prev", {
value: function (char, from, count) { value: function (char, from, count = 0) {
if (from > this.length - 1) return -1; if (from > this.length - 1) return -1;
else if (!from) from = this.length - 1; else if (!from) from = this.length - 1;
if (!count) count = 0;
var find = this.slice(0, from).lastIndexOf(char); var find = this.slice(0, from).lastIndexOf(char);
while (count > 1) { while (count > 1) {
@@ -364,16 +94,6 @@ Object.defineProperty(String.prototype, "prev", {
}, },
}); });
Object.defineProperty(String.prototype, "shift", {
value: function (n) {
if (n === 0) return this.slice();
if (n > 0) return this.slice(n);
if (n < 0) return this.slice(0, this.length + n);
},
});
Object.defineProperty(String.prototype, "strip_ext", { Object.defineProperty(String.prototype, "strip_ext", {
value: function () { value: function () {
return this.tolast("."); return this.tolast(".");
@@ -386,26 +106,6 @@ Object.defineProperty(String.prototype, "ext", {
}, },
}); });
Object.defineProperty(String.prototype, 'has_ext', {
value: function() {
var lastdot = this.lastIndexOf('.');
return lastdot > 0 && lastdot < this.length-1;
}
});
Object.defineProperty(String.prototype, "set_ext", {
value: function (val) {
return this.strip_ext() + val;
},
});
Object.defineProperty(String.prototype, "folder_same_name", {
value: function () {
var dirs = this.dir().split("/");
return dirs.last() === this.name();
},
});
Object.defineProperty(String.prototype, "up_path", { Object.defineProperty(String.prototype, "up_path", {
value: function () { value: function () {
var base = this.base(); var base = this.base();
@@ -460,18 +160,6 @@ Object.defineProperty(String.prototype, "base", {
}, },
}); });
Object.defineProperty(String.prototype, "splice", {
value: function (index, str) {
return this.slice(0, index) + str + this.slice(index);
},
});
Object.defineProperty(String.prototype, "sub", {
value: function (index, str) {
return this.slice(0, index) + str + this.slice(index + str.length);
},
});
Object.defineProperty(String.prototype, "updir", { Object.defineProperty(String.prototype, "updir", {
value: function () { value: function () {
if (this.lastIndexOf("/") === this.length - 1) return this.slice(0, this.length - 1); if (this.lastIndexOf("/") === this.length - 1) return this.slice(0, this.length - 1);
@@ -481,17 +169,6 @@ Object.defineProperty(String.prototype, "updir", {
}, },
}); });
Object.defineProperty(String.prototype, "uc", {
value: function () {
return this.toUpperCase();
},
});
Object.defineProperty(String.prototype, "lc", {
value: function () {
return this.toLowerCase();
},
});
/* ARRAY DEFS */ /* ARRAY DEFS */
Object.defineProperty(Array.prototype, "copy", { Object.defineProperty(Array.prototype, "copy", {
value: function () { value: function () {
@@ -505,42 +182,6 @@ Object.defineProperty(Array.prototype, "copy", {
}, },
}); });
Object.defineProperty(Array.prototype, "forFrom", {
value: function (n, fn) {
for (var i = n; i < this.length; i++) fn(this[i]);
},
});
Object.defineProperty(Array.prototype, "forTo", {
value: function (n, fn) {
for (var i = 0; i < n; i++) fn(this[i]);
},
});
Object.defineProperty(Array.prototype, "dofilter", {
value: function array_dofilter(fn) {
for (let i = 0; i < this.length; i++) {
if (!fn.call(this, this[i], i, this)) {
this.splice(i, 1);
i--;
}
}
return this;
},
});
Object.defineProperty(Array.prototype, "reversed", {
value: function array_reversed() {
var c = this.slice();
return c.reverse();
},
});
Array.random = function random(arr) {
if (!Array.isArray(arr)) return;
return arr[Math.floor(Math.random()*arr.length)];
}
function make_swizz() { function make_swizz() {
function setelem(n) { function setelem(n) {
return { return {
@@ -673,62 +314,12 @@ function make_swizz() {
} }
make_swizz(); make_swizz();
Object.defineProperty(Array.prototype, "newfirst", {
value: function (i) {
var c = this.slice();
if (i >= c.length) return c;
do {
c.push(c.shift());
i--;
} while (i > 0);
return c;
},
});
Object.defineProperty(Array.prototype, "doubleup", {
value: function (n) {
var c = [];
this.forEach(function (x) {
for (var i = 0; i < n; i++) c.push(x);
});
return c;
},
});
Object.defineProperty(Array.prototype, "mult", {
value: function (arr) {
var c = [];
for (var i = 0; i < this.length; i++) {
c[i] = this[i] * arr[i];
}
return c;
},
});
Object.defineProperty(Array.prototype, "apply", {
value: function fnapply(fn) {
this.forEach(function (x) {
x[fn].apply(x);
});
},
});
Object.defineProperty(Array.prototype, "sorted", {
value: function sorted() {
return this.toSorted();
},
});
Object.defineProperty(Array.prototype, "equal", { Object.defineProperty(Array.prototype, "equal", {
value: function equal(b) { value: function equal(b) {
if (this.length !== b.length) return false; if (this.length !== b.length) return false;
if (b == null) return false; if (b == null) return false;
if (this === b) return true; if (this === b) return true;
return JSON.stringify(this) === JSON.stringify(b)
return JSON.stringify(this.sorted()) === JSON.stringify(b.sorted());
for (var i = 0; i < this.length; i++) { for (var i = 0; i < this.length; i++) {
if (!this[i] === b[i]) return false; if (!this[i] === b[i]) return false;
@@ -738,122 +329,6 @@ Object.defineProperty(Array.prototype, "equal", {
}, },
}); });
Object.defineProperty(Array.prototype, "mapc", {
value: function (fn) {
return this.map(x => fn(x));
},
});
Object.defineProperty(Array.prototype, "mapvec", {
value: function (fn, b) {
return this.map((x, i) => fn(x, b[i]));
},
});
Object.defineProperty(Array.prototype, "remove", {
value: function remove(b) {
var idx = this.indexOf(b);
if (idx === -1) return false;
this.splice(idx, 1);
return true;
},
});
Object.defineProperty(Array.prototype, "delete", {
value: function remove(b) {
var idx = this.indexOf(b);
if (idx === -1) return false;
this.splice(idx, 1);
return true;
},
});
Object.defineProperty(Array.prototype, "set", {
value: function set(b) {
if (this.length !== b.length) return;
b.forEach(function (val, i) {
this[i] = val;
}, this);
},
});
Object.defineProperty(Array.prototype, "flat", {
value: function flat() {
return [].concat.apply([], this);
},
});
/* Return true if array contains x */
Object.defineProperty(Array.prototype, "empty", {
get: function empty() {
return this.length === 0;
},
});
Object.defineProperty(Array.prototype, "push_unique", {
value: function (x) {
var inc = !this.includes(x);
if (inc) this.push(x);
return inc;
},
});
Object.defineProperty(Array.prototype, "unique", {
value: function () {
var c = [];
this.forEach(function (x) {
c.push_unique(x);
});
return c;
},
});
Object.defineProperty(Array.prototype, "unduped", {
value: function () {
return [...new Set(this)];
},
});
Object.defineProperty(Array.prototype, "findIndex", {
value: function (fn) {
var idx = -1;
this.every(function (x, i) {
if (fn(x)) {
idx = i;
return false;
}
return true;
});
return idx;
},
});
Object.defineProperty(Array.prototype, "find", {
value: function (fn) {
var ret;
this.every(function (x) {
if (fn(x)) {
ret = x;
return false;
}
return true;
});
return ret;
},
});
Object.defineProperty(Array.prototype, "search", { Object.defineProperty(Array.prototype, "search", {
value: function (val) { value: function (val) {
for (var i = 0; i < this.length; i++) if (this[i] === val) return i; for (var i = 0; i < this.length; i++) if (this[i] === val) return i;
@@ -903,44 +378,3 @@ Object.defineProperty(Array.prototype, "mirrored", {
return c; return c;
}, },
}); });
Object.defineProperty(Array.prototype, "forEachRight", {
value: function(fn) {
for (var i = this.length-1; i >= 0; i--)
fn(this[i], i);
}
});
Number.hex = function (n) {
var s = Math.floor(n).toString(16);
if (s.length === 1) s = "0" + s;
return s.uc();
};
Object.defineProperty(Object.prototype, "lerp", {
value: function (to, t) {
var self = this;
var obj = {};
Object.keys(self).forEach(function (key) {
obj[key] = self[key].lerp(to[key], t);
});
return obj;
},
});
/* POINT ASSISTANCE */
function points2cm(points) {
var x = 0;
var y = 0;
var n = points.length;
points.forEach(function (p) {
x = x + p[0];
y = y + p[1];
});
return [x / n, y / n];
}
return {}

View File

@@ -1,3 +1,9 @@
function tohex(n) {
var s = Math.floor(n).toString(16);
if (s.length === 1) s = "0" + s;
return s.toUpperCase();
};
var Color = { var Color = {
white: [255, 255, 255], white: [255, 255, 255],
black: [0, 0, 0], black: [0, 0, 0],
@@ -17,7 +23,7 @@ Color.editor.ur = Color.green;
Color.tohtml = function (v) { Color.tohtml = function (v) {
var html = v.map(function (n) { var html = v.map(function (n) {
return Number.hex(n * 255); return tohex(n * 255);
}); });
return "#" + html.join(""); return "#" + html.join("");
}; };

View File

@@ -35,6 +35,16 @@ convert.deromanize = function (str) {
return num; return num;
}; };
convert.roman = {
M: 1000,
D: 500,
C: 100,
L: 50,
X: 10,
V: 5,
I: 1,
}
convert.buf2hex = function (buffer) { convert.buf2hex = function (buffer) {
// buffer is an ArrayBuffer // buffer is an ArrayBuffer
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join(" "); return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join(" ");

View File

@@ -1,5 +1,6 @@
var render = use('render') var render = use('render')
var debug = os.use('debug') var debug = os.use('debug')
var util = use('util')
debug.build = function (fn) { debug.build = function (fn) {
if (!debug.show) return; if (!debug.show) return;
@@ -192,7 +193,7 @@ debug.api.print_doc = function (name) {
obj = eval(name); obj = eval(name);
if (!Object.isObject(obj)) { if (!util.isObject(obj)) {
console.warn("Cannot print the API of something that isn't an object."); console.warn("Cannot print the API of something that isn't an object.");
return undefined; return undefined;
} }

View File

@@ -1,3 +1,4 @@
var util = use('util')
var diff = {} var diff = {}
function deep_copy(from) { function deep_copy(from) {
@@ -41,14 +42,14 @@ diff.ediff = function ediff(from, to) {
} }
var diff = ediff(from[key], to[key]); var diff = ediff(from[key], to[key]);
if (diff && !Object.empty(diff)) ret[key] = Object.values(ediff(v, [])); if (diff && !util.isEmpty(diff)) ret[key] = Object.values(ediff(v, []));
return; return;
} }
if (typeof v === "object" && v !== null) { if (typeof v === "object" && v !== null) {
var diff = ediff(v, to[key]); var diff = ediff(v, to[key]);
if (diff && !Object.empty(diff)) ret[key] = diff; if (diff && !util.isEmpty(diff)) ret[key] = diff;
return; return;
} }
@@ -60,7 +61,7 @@ diff.ediff = function ediff(from, to) {
if (!to || v !== to[key]) ret[key] = v; if (!to || v !== to[key]) ret[key] = v;
}); });
if (Object.empty(ret)) return undefined; if (util.isEmpty(ret)) return undefined;
return ret; return ret;
} }
@@ -75,7 +76,7 @@ diff.samediff = function samediff(from, to) {
return same; return same;
} }
Object.keys(from).forEach(function (k) { Object.keys(from).forEach(function (k) {
if (Object.isObject(from[k])) { if (util.isObject(from[k])) {
samediff(from[k], to[k]); samediff(from[k], to[k]);
return; return;
} }

85
scripts/draw2d.js Normal file
View File

@@ -0,0 +1,85 @@
var render = use('render')
var vector = use('vector')
var draw = {}
draw.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) {
var mesh = os.make_line_prim(points,thickness, 0,0,color);
render.current_queue.push({
type: 'geometry',
mesh,
pipeline,
first_index:0,
num_indices:mesh.num_indices
});
};
draw.cross = function render_cross(pos, size, color = Color.red, thickness = 1, pipe = sprite_pipeline) {
var a = [pos.add([0, size]), pos.add([0, -size])];
var b = [pos.add([size, 0]), pos.add([-size, 0])];
draw.line(a, color, thickness);
draw.line(b, color, thickness);
};
draw.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10, pipe = sprite_pipeline) {
var dir = vector.norm(end.sub(start))
var wing1 = [vector.rotate(dir, wingangle).scale(wingspan).add(end), end];
var wing2 = [vector.rotate(dir, -wingangle).scale(wingspan).add(end), end];
render.line([start, end], color);
render.line(wing1, color);
render.line(wing2, color);
};
draw.rectangle = function render_rectangle(rect, color = Color.white, pipeline = rect_pipeline) {
var T = os.make_transform();
T.rect(rect);
render.current_queue.push({
type:'sprite',
transform:T,
color,
pipeline
});
};
var tile_def = {repeat_x:true, repeat_y:true};
draw.tile = function(image, rect, color = Color.white, tile = tile_def, pipeline = sprite_pipeline)
{
if (!image) throw Error ('Need an image to render.')
if (typeof image === "string")
image = graphics.texture(image);
var mesh = render._main.tile(image.texture, {x:0,y:0,width:image.texture.width,height:image.texture.height}, rect, tile);
current_queue.push({
type:'geometry',
mesh,
image,
pipeline,
first_index:0,
num_indices:mesh.num_indices
});
}
// slice is given in pixels
var slice9_info = {
tile_top:true,
tile_bottom:true,
tile_left:true,
tile_right:true,
tile_center_x:true,
tile_center_right:true
};
draw.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.white, info = slice9_info, pipeline = sprite_pipeline) {
if (!image) throw Error ('Need an image to render.')
if (typeof image === "string")
image = graphics.texture(image);
var mesh = render._main.slice9(image.texture, rect, gizmo.normalizeSpacing(slice), info);
current_queue.push({
type: 'geometry',
mesh,
image,
pipeline,
first_index:0,
num_indices:mesh.num_indices
});
};

View File

@@ -1,47 +1,11 @@
globalThis.console = os.use('console') globalThis.console = os.use('console')
globalThis.prosperon = os.use('prosperon') globalThis.prosperon = os.use('prosperon')
globalThis.game = os.use('game')
var io = os.use('io') var io = os.use('io')
Object.defineProperty(Object.prototype, "object_id", {
value: function() {
return os.value_id(this);
}
});
os.mem_limit.doc = "Set the memory limit of the runtime in bytes."; os.mem_limit.doc = "Set the memory limit of the runtime in bytes.";
os.gc_threshold.doc = "Set the threshold before a GC pass is triggered in bytes. This is set to malloc_size + malloc_size>>1 after a GC pass."; os.gc_threshold.doc = "Set the threshold before a GC pass is triggered in bytes. This is set to malloc_size + malloc_size>>1 after a GC pass.";
os.max_stacksize.doc = "Set the max stack size in bytes."; os.max_stacksize.doc = "Set the max stack size in bytes.";
Object.defineProperty(String.prototype, "rm", {
value: function (index, endidx = index + 1) {
return this.slice(0, index) + this.slice(endidx);
},
});
Object.defineProperty(String.prototype, "tolast", {
value: function (val) {
var idx = this.lastIndexOf(val);
if (idx === -1) return this.slice();
return this.slice(0, idx);
},
});
Object.defineProperty(String.prototype, "dir", {
value: function () {
if (!this.includes("/")) return "";
return this.tolast("/");
},
});
Object.defineProperty(String.prototype, "folder", {
value: function () {
var dir = this.dir();
if (!dir) return "";
else return dir + "/";
},
});
globalThis.Resources = {}; globalThis.Resources = {};
Resources.rm_fn = function rm_fn(fn, text) { Resources.rm_fn = function rm_fn(fn, text) {
@@ -241,12 +205,11 @@ io.slurpbytes = function(path)
var ignore = io.slurp('.prosperonignore').split('\n'); var ignore = io.slurp('.prosperonignore').split('\n');
var allpaths; var allpaths;
var tmpglob = io.glob;
io.glob = function glob(pat) { io.glob = function glob(pat) {
if (!allpaths) if (!allpaths)
allpaths = io.globfs(ignore); allpaths = io.globfs(ignore);
return allpaths.filter(str => game.glob(pat,str)).sort(); return allpaths.filter(str => io.match(pat,str)).sort();
} }
io.invalidate = function() io.invalidate = function()
@@ -352,69 +315,10 @@ console.doc = {
clear: "Clear console.", clear: "Clear console.",
}; };
globalThis.global = globalThis;
var script = io.slurp("core/scripts/base.js") var script = io.slurp("core/scripts/base.js")
var fnname = "base" var fnname = "base"
script = `(function ${fnname}() { ${script}; })` script = `(function ${fnname}() { ${script}; })`
Object.assign(globalThis,os.eval("core/scripts/base.js",script)()) os.eval('core/scripts/base.js', script)()
function splitPath(path) {
return path.split('/').filter(part => part.length > 0);
}
function splitPattern(pattern) {
return pattern.split('/').filter(part => part.length > 0);
}
function matchPath(pathParts, patternParts) {
let pathIndex = 0;
let patternIndex = 0;
let starPatternIndex = -1;
let starPathIndex = -1;
while (pathIndex < pathParts.length) {
if (patternIndex < patternParts.length) {
if (patternParts[patternIndex] === '**') {
// Record the position of '**' in the pattern
starPatternIndex = patternIndex;
// Record the current position in the path
starPathIndex = pathIndex;
// Move to the next pattern component
patternIndex++;
continue;
} else if (
patternParts[patternIndex] === '*' ||
patternParts[patternIndex] === pathParts[pathIndex]
) {
// If the pattern is '*' or exact match, move to the next component
patternIndex++;
pathIndex++;
continue;
}
}
if (starPatternIndex !== -1) {
// If there was a previous '**', backtrack
patternIndex = starPatternIndex + 1;
starPathIndex++;
pathIndex = starPathIndex;
continue;
}
// No match and no '**' to backtrack to
return false;
}
// Check for remaining '**' in the pattern
while (patternIndex < patternParts.length && patternParts[patternIndex] === '**') {
patternIndex++;
}
return patternIndex === patternParts.length;
}
prosperon.SIGABRT = function() prosperon.SIGABRT = function()
{ {
@@ -433,6 +337,7 @@ function add_timer(obj, fn, seconds)
var timers = obj.timers; var timers = obj.timers;
var stop = function () { var stop = function () {
if (!timer) return
timers.delete(stop); timers.delete(stop);
timer.fn = undefined; timer.fn = undefined;
timer = undefined; timer = undefined;
@@ -548,7 +453,7 @@ var script_fn = function script_fn(path) {
var module_name = file.name() var module_name = file.name()
if (parsed.module) { if (parsed.module) {
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; ${parsed.module}})`; var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports:exports}; var define = undefined; ${parsed.module}})`;
var module_fn = os.eval(file, mod_script) var module_fn = os.eval(file, mod_script)
var module_ret = module_fn.call(); var module_ret = module_fn.call();
if (module_ret === undefined || module_ret === null) if (module_ret === undefined || module_ret === null)
@@ -688,7 +593,7 @@ var Register = {
fns.splice(left, 0, dofn); fns.splice(left, 0, dofn);
return function () { return function () {
fns.remove(dofn); fns.delete(dofn)
}; };
}; };
@@ -764,19 +669,24 @@ Register.add_cb("imgui");
Register.add_cb("app"); Register.add_cb("app");
Register.add_cb("prerender"); Register.add_cb("prerender");
function cant_kill()
{
throw Error("Can't kill an object in its spawning code. Move the kill command to awake.");
}
actor.toString = function() { return this.__file } actor.toString = function() { return this.__file }
actor.spawn = function spawn(script, config, callback) { actor.spawn = function spawn(script, config, callback) {
if (this.__dead__) throw Error("Attempting to spawn on a dead actor")
var prog var prog
if (!script) { if (!script) {
prog = Object.create(actor) prog = {}
if (callback) callback(prog) prog.module_ret = {}
return prog prog.prog_fn = function() {}
} else {
prog = script_fn(script);
if (!prog.prog_fn) throw new Error(`Script ${script} is not an actor script or has no actor component`)
} }
prog = script_fn(script);
if (!prog.prog_fn) throw new Error(`Script ${script} is not an actor script or has no actor component`)
var underling; var underling;
prog.module_ret.__proto__ = actor; prog.module_ret.__proto__ = actor;
underling = Object.create(prog.module_ret); underling = Object.create(prog.module_ret);
@@ -786,10 +696,16 @@ actor.spawn = function spawn(script, config, callback) {
underling.timers = [] underling.timers = []
underling.underlings = new Set() underling.underlings = new Set()
if (callback) callback(underling) if (callback) callback(underling, {
message:"created"
})
try{ try{
prog.prog_fn.call(underling) prog.prog_fn.call(underling)
} catch(e) {throw e} } catch(e) {throw e}
if (underling.__dead__)
return undefined
if (typeof config === 'object') Object.assign(underling,config); if (typeof config === 'object') Object.assign(underling,config);
if (!underling.__reggies) if (!underling.__reggies)
@@ -803,6 +719,12 @@ try{
if (underling.tag) if (underling.tag)
search.tag_add(underling.tag, underling) search.tag_add(underling.tag, underling)
Object.defineProperty(underling, 'garbage', {
configurable: false,
writable: false,
value: underling.garbage
})
return underling; return underling;
}; };
@@ -821,7 +743,7 @@ var input = use('input')
actor.kill = function kill() { actor.kill = function kill() {
if (this.__dead__) return; if (this.__dead__) return;
this.__dead__ = true; this.__dead__ = true;
this.timers.forEachRight(t => t()) this.timers.slice().forEach(t => t()) // slice in case something is removed from timers while running
delete this.timers delete this.timers
input.do_uncontrol(this); input.do_uncontrol(this);
Event.rm_obj(this); Event.rm_obj(this);
@@ -853,29 +775,9 @@ actor.interval = function interval(fn, seconds) {
return stop; return stop;
}; };
actor.underlings = new Set()
globalThis.app = actor.spawn()
app.garbage = function () {
os.exit(0);
};
globalThis.world = app;
var search = use('search') var search = use('search')
/* MATH EXTENSIONS */ actor.underlings = new Set()
Object.defineProperty(Number.prototype, "lerp", {
value: function (to, t) {
return Math.lerp(this, to, t);
},
});
Object.defineProperty(Number.prototype, "clamp", { globalThis.mixin("color");
value: function (from, to) { globalThis.mixin("std")
return Math.clamp(this, from, to);
},
});
global.mixin("color");
global.mixin("std")

View File

@@ -159,6 +159,24 @@ function make_spritesheet(paths, width, height)
sheet.load_gpu(); sheet.load_gpu();
} }
var fontcache = {};
var datas= [];
graphics.get_font = function get_font(path,size)
{
var parts = path.split('.');
if (!isNaN(parts[1])) {
path = parts[0];
size = Number(parts[1]);
}
path = Resources.find_font(path);
var fontstr = `${path}.${size}`;
if (fontcache[fontstr]) return fontcache[fontstr];
var data = io.slurpbytes(path);
fontcache[fontstr] = os.make_font(data,size);
fontcache[fontstr].texture = prosperon.gpu.load_texture(fontcache[fontstr].surface);
return fontcache[fontstr];
}
graphics.semver = {}; graphics.semver = {};
graphics.semver.valid = function (v, range) { graphics.semver.valid = function (v, range) {

View File

@@ -1,4 +1,5 @@
var input = os.use('input') var input = os.use('input')
var util = use('util')
var downkeys = {}; var downkeys = {};
@@ -110,7 +111,7 @@ input.mouse.normal.doc = "Set the mouse to show again after hiding.";
input.keyboard = {}; input.keyboard = {};
input.keyboard.down = function (code) { input.keyboard.down = function (code) {
if (typeof code === "number") return downkeys[code]; if (typeof code === "number") return downkeys[code];
if (typeof code === "string") return downkeys[code.uc().charCodeAt()] || downkeys[code.lc().charCodeAt()]; if (typeof code === "string") return downkeys[code.toUpperCase().charCodeAt()] || downkeys[code.toLowerCase().charCodeAt()];
return undefined; return undefined;
}; };
@@ -176,9 +177,7 @@ input.action = {
input.tabcomplete = function tabcomplete(val, list) { input.tabcomplete = function tabcomplete(val, list) {
if (!val) return val; if (!val) return val;
list.dofilter(function (x) { list = filter(x => x.startsWith(val))
return x.startsWith(val);
});
if (list.length === 1) { if (list.length === 1) {
return list[0]; return list[0];
@@ -186,7 +185,7 @@ input.tabcomplete = function tabcomplete(val, list) {
var ret = undefined; var ret = undefined;
var i = val.length; var i = val.length;
while (!ret && !Object.empty(list)) { while (!ret && list.length !== 0) {
var char = list[0][i]; var char = list[0][i];
if ( if (
!list.every(function (x) { !list.every(function (x) {
@@ -196,9 +195,7 @@ input.tabcomplete = function tabcomplete(val, list) {
ret = list[0].slice(0, i); ret = list[0].slice(0, i);
else { else {
i++; i++;
list.dofilter(function (x) { list = list.filter(x => x.length-1 > i)
return x.length - 1 > i;
});
} }
} }
@@ -218,7 +215,7 @@ var Player = {
}, },
mouse_input(type, ...args) { mouse_input(type, ...args) {
for (var pawn of this.pawns.reversed()) { for (var pawn of [...this.pawns].reverse()) {
if (typeof pawn.inputs?.mouse?.[type] === "function") { if (typeof pawn.inputs?.mouse?.[type] === "function") {
pawn.inputs.mouse[type].call(pawn, ...args); pawn.inputs.mouse[type].call(pawn, ...args);
pawn.inputs.post?.call(pawn); pawn.inputs.post?.call(pawn);
@@ -228,7 +225,7 @@ var Player = {
}, },
char_input(c) { char_input(c) {
for (var pawn of this.pawns.reversed()) { for (var pawn of [...this.pawns].reverse()) {
if (typeof pawn.inputs?.char === "function") { if (typeof pawn.inputs?.char === "function") {
pawn.inputs.char.call(pawn, c); pawn.inputs.char.call(pawn, c);
pawn.inputs.post?.call(pawn); pawn.inputs.post?.call(pawn);
@@ -238,7 +235,7 @@ var Player = {
}, },
joy_input(name, joystick) { joy_input(name, joystick) {
for (var pawn of this.pawns.reversed()) { for (var pawn of [...this.pawns].reverse()) {
if (!pawn.inputs) return; if (!pawn.inputs) return;
if (!pawn.inputs.joystick) return; if (!pawn.inputs.joystick) return;
if (!pawn.inputs.joystick[name]) return; if (!pawn.inputs.joystick[name]) return;
@@ -255,8 +252,7 @@ var Player = {
}, },
raw_input(cmd, state, ...args) { raw_input(cmd, state, ...args) {
this.pawns = this.pawns.filter(x => x.inputs); for (var pawn of [...this.pawns].reverse()) {
for (var pawn of this.pawns.reversed()) {
var inputs = pawn.inputs; var inputs = pawn.inputs;
if (!inputs[cmd]) { if (!inputs[cmd]) {
@@ -294,27 +290,25 @@ var Player = {
obj_controlled(obj) { obj_controlled(obj) {
for (var p in Player.players) { for (var p in Player.players) {
if (p.pawns.contains(obj)) return true; if (p.pawns.has(obj)) return true;
} }
return false; return false;
}, },
print_pawns() { print_pawns() {
for (var pawn of this.pawns.reversed()) console.log(pawn.toString()); [...this.pawns].reverse().forEach(x => console.log(x))
}, },
create() { create() {
var n = Object.create(this); var n = Object.create(this);
n.pawns = []; n.pawns = new Set()
n.gamepads = []; n.gamepads = [];
this.players.push(n); this.players.push(n);
this[this.players.length - 1] = n; this[this.players.length - 1] = n;
return n; return n;
}, },
pawns: [],
control(pawn) { control(pawn) {
if (!pawn) if (!pawn)
return return
@@ -322,18 +316,18 @@ var Player = {
if (!pawn.inputs) if (!pawn.inputs)
throw new Error("attempted to control a pawn without any input object."); throw new Error("attempted to control a pawn without any input object.");
this.pawns.push_unique(pawn); this.pawns.add(pawn);
}, },
uncontrol(pawn) { uncontrol(pawn) {
this.pawns = this.pawns.filter(x => x !== pawn); this.pawns.delete(pawn)
}, },
}; };
input.do_uncontrol = function input_do_uncontrol(pawn) { input.do_uncontrol = function input_do_uncontrol(pawn) {
// if (!pawn.inputs) return; if (!pawn.inputs) return;
Player.players.forEach(function (p) { Player.players.forEach(function (p) {
p.pawns = p.pawns.filter(x => x !== pawn) p.pawns.delete(pawn)
}); });
}; };

View File

@@ -1,10 +0,0 @@
var lodash = {};
lodash.get = function (obj, path, defValue) {
if (!path) return undefined;
// Check if path is string or array. Regex : ensure that we do not have '.' and brackets.
var pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
var result = pathArray.reduce((prevObj, key) => prevObj && prevObj[key], obj);
return result === undefined ? defValue : result;
}
return lodash

22
scripts/path.js Normal file
View File

@@ -0,0 +1,22 @@
var path = {}
path.name = function name(str)
{
var idx = str.indexOf("/");
if (idx === -1) return str.tolast(".");
return str.fromlast("/").tolast(".");
}
path.dir = function (str) {
if (!str.includes("/")) return "";
var idx = str.lastIndexOf(s
return str.tolast("/");
}
path.folder = function(str) {
var dir = this.dir();
if (!dir) return "";
else return dir + "/";
}
return path

View File

@@ -60,4 +60,17 @@ pmath.sign = function (n) {
return n >= 0 ? 1 : -1; return n >= 0 ? 1 : -1;
}; };
pmath.points2cm = function(points)
{
var x = 0;
var y = 0;
var n = points.length;
points.forEach(function (p) {
x = x + p[0];
y = y + p[1];
});
return [x / n, y / n];
}
return pmath return pmath

View File

@@ -5,9 +5,7 @@ var gizmo = use('gizmos')
var vector = use('vector') var vector = use('vector')
var search = use('search') var search = use('search')
game.timescale = 1 prosperon.window = os.engine_start(config);
prosperon.window = game.engine_start(config);
var driver = "vulkan" var driver = "vulkan"
switch(os.sys()) { switch(os.sys()) {
@@ -831,16 +829,6 @@ render.line = function render_line(points, color = Color.white, thickness = 1, p
}); });
}; };
render.dbg_line = function(points, color = Color.white)
{
}
render.dbg_point = function(points, color = Color.white)
{
}
/* All draw in screen space */ /* All draw in screen space */
render.point = function (pos, size, color = Color.blue) { render.point = function (pos, size, color = Color.blue) {
render._main.point(pos,color); render._main.point(pos,color);
@@ -896,9 +884,11 @@ render.particles = function render_particles(emitter, pipeline = sprite_pipeline
}); });
} }
render.text = function text(text, rect, font = prosperon.font, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) { var sysfont = graphics.get_font('fonts/c64.ttf', 8);
render.text = function text(text, rect, font = sysfont, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) {
if (typeof font === 'string') if (typeof font === 'string')
font = render.get_font(font) font = graphics.get_font(font)
var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font); var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font);
// full_upload(mesh) // full_upload(mesh)
@@ -915,7 +905,7 @@ render.text = function text(text, rect, font = prosperon.font, size = 0, color =
return; return;
if (typeof font === 'string') if (typeof font === 'string')
font = render.get_font(font); font = graphics.get_font(font);
if (!font) return; if (!font) return;
var pos = [rect.x,rect.y]; var pos = [rect.x,rect.y];
@@ -928,7 +918,7 @@ render.text = function text(text, rect, font = prosperon.font, size = 0, color =
render.text_size = function(str, font, ...args) render.text_size = function(str, font, ...args)
{ {
if (typeof font === 'string') if (typeof font === 'string')
font = render.get_font(font); font = graphics.get_font(font);
return font.text_size(str, ...args); return font.text_size(str, ...args);
} }
@@ -996,32 +986,6 @@ render.mask = function mask(image, pos, scale, rotation = 0, ref = 1)
render.draw(shape.quad); render.draw(shape.quad);
} }
function calc_image_size(img)
{
return [img.texture.width*img.rect.width, img.texture.height*img.rect.height];
}
function tile(image, rect = [0,0], color = Color.white, repeat = {})
{
if (!image) throw Error ('Need an image to render.')
if (typeof image === "string")
image = graphics.texture(image);
render._main.tile(image, rect, undefined, 1);
return;
var tex = image.texture;
if (!tex) return;
var image_size = calc_image_size(image); //image.size;
var size = [rect.width ? rect.width : image_size.x, rect.height ? rect.height : image_size.y];
render._main.tile(image.texture, rect, image.rect, 1);
return;
}
var std_sprite_cmd = { var std_sprite_cmd = {
type: 'sprite', type: 'sprite',
pipeline: sprite_pipeline, pipeline: sprite_pipeline,
@@ -1130,34 +1094,11 @@ render.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.wh
var textssbos = []; var textssbos = [];
var tdraw = 0; var tdraw = 0;
var fontcache = {};
var datas= [];
render.get_font = function get_font(path,size)
{
var parts = path.split('.');
if (!isNaN(parts[1])) {
path = parts[0];
size = Number(parts[1]);
}
path = Resources.find_font(path);
var fontstr = `${path}.${size}`;
if (fontcache[fontstr]) return fontcache[fontstr];
var data = io.slurpbytes(path);
fontcache[fontstr] = os.make_font(data,size);
fontcache[fontstr].texture = render._main.load_texture(fontcache[fontstr].surface);
return fontcache[fontstr];
}
render.doc = "Draw shapes in screen space."; render.doc = "Draw shapes in screen space.";
render.cross.doc = "Draw a cross centered at pos, with arm length size."; render.cross.doc = "Draw a cross centered at pos, with arm length size.";
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle."; render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright."; render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
render.draw = function render_draw(mesh, material, pipeline) {
};
render.viewport = function(rect) render.viewport = function(rect)
{ {
render._main.viewport(rect); render._main.viewport(rect);
@@ -1217,7 +1158,8 @@ function screen2hud(pos)
*/ */
prosperon.make_camera = function make_camera() { prosperon.make_camera = function make_camera() {
var cam = world.spawn(); return;
/* var cam = world.spawn();
cam.near = 1; cam.near = 1;
cam.far = -1000; cam.far = -1000;
cam.ortho = true; // True if this is a 2d camera cam.ortho = true; // True if this is a 2d camera
@@ -1228,7 +1170,7 @@ prosperon.make_camera = function make_camera() {
cam.screen2cam = screen2cam; cam.screen2cam = screen2cam;
cam.screen2hud = screen2hud; cam.screen2hud = screen2hud;
cam.zoom = 1; // the "scale factor" this camera demonstrates cam.zoom = 1; // the "scale factor" this camera demonstrates
return cam; return cam;*/
}; };
var screencolor; var screencolor;
@@ -1367,6 +1309,7 @@ var last_frame_time = 0;
var frame_t = 0; var frame_t = 0;
// Ran once per frame // Ran once per frame
var fpses = []; var fpses = [];
var timescale = 1
render.process = function process() { render.process = function process() {
var now = profile.now(); var now = profile.now();
var dt = now - last_frame_time; var dt = now - last_frame_time;
@@ -1379,7 +1322,7 @@ render.process = function process() {
frame_t = last_frame_time; frame_t = last_frame_time;
game.engine_input(e => { os.engine_input(e => {
prosperon[e.type]?.(e); prosperon[e.type]?.(e);
}); });
@@ -1388,9 +1331,9 @@ render.process = function process() {
prosperon.appupdate(dt) prosperon.appupdate(dt)
input.procdown() input.procdown()
emitters.update(dt * game.timescale) emitters.update(dt * timescale)
os.update_timers(dt * game.timescale) os.update_timers(dt * timescale)
prosperon.update(dt*game.timescale) prosperon.update(dt*timescale)
if (sim.mode === "step") sim.pause(); if (sim.mode === "step") sim.pause();
if (sim.mode === "play" || sim.mode === "step") { if (sim.mode === "play" || sim.mode === "step") {
@@ -1399,8 +1342,8 @@ render.process = function process() {
while (physlag > physics.delta) { while (physlag > physics.delta) {
physlag -= physics.delta; physlag -= physics.delta;
prosperon.phys2d_step(physics.delta * game.timescale); prosperon.phys2d_step(physics.delta * timescale);
prosperon.physupdate(physics.delta * game.timescale); prosperon.physupdate(physics.delta * timescale);
} }
*/ */
} }
@@ -1419,7 +1362,7 @@ render.process = function process() {
// Some initialization // Some initialization
shader_type = render._main.shader_format()[0]; shader_type = render._main.shader_format()[0];
prosperon.font = render.get_font('fonts/c64.ttf', 8);
std_sampler = render._main.make_sampler({ std_sampler = render._main.make_sampler({
min_filter: "nearest", min_filter: "nearest",

View File

@@ -5,6 +5,7 @@ else os.user = os.env("USER");
var sim = use('sim') var sim = use('sim')
var io = use('io') var io = use('io')
var util = use('util')
/*var ignore; /*var ignore;
if (ignore = io.slurp('.prosperonignore')) { if (ignore = io.slurp('.prosperonignore')) {
@@ -212,8 +213,20 @@ Cmdline.register_order(
function (argv) { function (argv) {
if (argv[0]) io.chdir(argv[0]); if (argv[0]) io.chdir(argv[0]);
if (io.exists("main.js")) app.spawn("main.js") var app
else app.spawn("nogame.js"); if (io.exists("main.js"))
app = actor.spawn("main.js", {}, function(underling, msg) {
if (msg.message !== "created") return;
Object.defineProperty(underling, 'then', {
configurable:false,
writable:false,
value:function() {
os.exit(0);
}
});
})
else
app = actor.spawn("nogame.js");
var ren = use('render') var ren = use('render')
@@ -355,7 +368,7 @@ Cmdline.register_order(
var obj = json.decode(io.slurp(file)); var obj = json.decode(io.slurp(file));
var nn = nota.encode(obj); var nn = nota.encode(obj);
io.slurpwrite(file.set_ext(".nota"), nn); io.slurpwrite(file.strip_ext() + ".nota", nn);
} }
}, },
"Create a nota file from a json.", "Create a nota file from a json.",
@@ -372,7 +385,7 @@ Cmdline.register_order(
say(file.ext()); say(file.ext());
var obj = nota.decode(io.slurp(file)); var obj = nota.decode(io.slurp(file));
var nn = json.encode(obj); var nn = json.encode(obj);
io.slurpwrite(file.set_ext(".json", nn)); io.slurpwrite(file.strip_ext() + ".json", nn);
} }
}, },
"Create a JSON from a nota.", "Create a JSON from a nota.",
@@ -435,7 +448,7 @@ Cmdline.print_order = function (fn) {
Cmdline.register_order( Cmdline.register_order(
"help", "help",
function (order) { function (order) {
if (!Object.empty(order)) { if (!util.isEmpty(order)) {
var orfn = Cmdline.orders[order]; var orfn = Cmdline.orders[order];
if (!orfn) { if (!orfn) {

View File

@@ -1,4 +1,5 @@
var profile = use('profile') var profile = use('profile')
var util = use('util')
/* Take numbers from 0 to 1 and remap them to easing functions */ /* Take numbers from 0 to 1 and remap them to easing functions */
var Ease = { var Ease = {
@@ -127,7 +128,7 @@ var tween = function (from, to, time, fn, cb) {
var update = function tween_update(dt) { var update = function tween_update(dt) {
var elapsed = profile.now() - start; var elapsed = profile.now() - start;
fn(from.lerp(to, elapsed / time)); fn(util.obj_lerp(from,to,elapsed/time));
if (elapsed >= time) { if (elapsed >= time) {
fn(to) fn(to)
cb?.() cb?.()

102
scripts/util.js Normal file
View File

@@ -0,0 +1,102 @@
var util = {}
util.deepfreeze = function (obj) {
for (var key in obj) {
if (typeof obj[key] === "object") Object.deepfreeze(obj[key]);
}
Object.freeze(obj);
};
util.dainty_assign = function (target, source) {
Object.keys(source).forEach(function (k) {
if (typeof source[k] === "function") return;
if (!(k in target)) return;
if (Array.isArray(source[k])) target[k] = deep_copy(source[k]);
else if (Object.isObject(source[k])) Object.dainty_assign(target[k], source[k]);
else target[k] = source[k];
});
};
util.get = function (obj, path, defValue) {
if (!path) return undefined;
// Check if path is string or array. Regex : ensure that we do not have '.' and brackets.
var pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
var result = pathArray.reduce((prevObj, key) => prevObj && prevObj[key], obj);
return result === undefined ? defValue : result;
}
util.isObject = function (o) {
return o instanceof Object && !(o instanceof Array);
};
util.isEmpty = function(o) {
return Object.keys(obj).length === 0;
}
util.dig = function (obj, path, def = {}) {
var pp = path.split(".");
for (var i = 0; i < pp.length - 1; i++) {
obj = obj[pp[i]] = obj[pp[i]] || {};
}
obj[pp[pp.length - 1]] = def;
return def;
};
util.access = function (obj, name) {
var dig = name.split(".");
for (var i of dig) {
obj = obj[i];
if (!obj) return undefined;
}
return obj;
};
function deep_copy(from) {
return json.decode(json.encode(from));
}
util.mergekey = function (o1, o2, k) {
if (!o2) return;
if (typeof o2[k] === "object") {
if (Array.isArray(o2[k])) o1[k] = deep_copy(o2[k]);
else {
if (!o1[k]) o1[k] = {};
if (typeof o1[k] === "object") util.merge(o1[k], o2[k]);
else o1[k] = o2[k];
}
} else o1[k] = o2[k];
};
/* Same as merge from Ruby */
/* Adds objs key by key to target */
util.merge = function (target, ...objs) {
for (var obj of objs) for (var key of Object.keys(obj)) util.mergekey(target, obj, key);
return target;
};
util.copy = function (proto, ...objs) {
var c = Object.create(proto);
for (var obj of objs) Object.mixin(c, obj);
return c;
};
util.obj_lerp = function(a,b,t)
{
if (a.lerp)
return a.lerp(b,t);
var obj = {};
Object.keys(a).forEach(function (key) {
obj[key] = a[key].lerp(b[key], t);
});
return obj;
}
return util

View File

@@ -29,6 +29,8 @@
#include "cgltf.h" #include "cgltf.h"
#include "physfs.h" #include "physfs.h"
#include "wildmatch.h"
#include "freelist.h" #include "freelist.h"
#include "sprite.h" #include "sprite.h"
@@ -261,13 +263,6 @@ int JS_GETBOOL(JSContext *js, JSValue v, const char *prop)
return r; return r;
} }
JSValue js_getpropertystr(JSContext *js, JSValue v, const char *str)
{
JSValue ret = JS_GetPropertyStr(js, v, str);
JS_FreeValue(js,ret);
return ret;
}
JSValue js_getproperty(JSContext *js, JSValue v, JSAtom atom) JSValue js_getproperty(JSContext *js, JSValue v, JSAtom atom)
{ {
JSValue ret = JS_GetProperty(js, v, atom); JSValue ret = JS_GetProperty(js, v, atom);
@@ -2226,6 +2221,17 @@ static const JSCFunctionListEntry js_array_funcs[] = {
PROTO_FUNC_DEF(array, lerp, 2) PROTO_FUNC_DEF(array, lerp, 2)
}; };
JSC_CCALL(number_lerp,
double a = js2number(js,self);
double b = js2number(js,argv[0]);
double t = js2number(js,argv[1]);
return number2js(js, (b-a)*t+a);
)
static const JSCFunctionListEntry js_number_funcs[] = {
PROTO_FUNC_DEF(number, lerp, 2),
};
#define JS_SDL_PROP(JS, VAL, SDLPROP, PROP) \ #define JS_SDL_PROP(JS, VAL, SDLPROP, PROP) \
{ \ { \
JSValue v = JS_GetPropertyStr(JS,VAL,#PROP); \ JSValue v = JS_GetPropertyStr(JS,VAL,#PROP); \
@@ -2235,7 +2241,7 @@ JS_FreeCString(JS,str); \
JS_FreeValue(js,v); \ JS_FreeValue(js,v); \
} \ } \
JSC_SCALL(game_engine_start, JSC_SCALL(os_engine_start,
JSValue p = argv[0]; JSValue p = argv[0];
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_NAME_STRING, name) JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_NAME_STRING, name)
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_VERSION_STRING, version) JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_VERSION_STRING, version)
@@ -2629,7 +2635,7 @@ static JSValue event2js(JSContext *js, SDL_Event event)
void gui_input(SDL_Event *e); void gui_input(SDL_Event *e);
// Polls and handles all input events // Polls and handles all input events
JSC_CCALL(game_engine_input, JSC_CCALL(os_engine_input,
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
#ifndef NEDITOR #ifndef NEDITOR
@@ -2640,19 +2646,6 @@ JSC_CCALL(game_engine_input,
uncaught_exception(js,ret); uncaught_exception(js,ret);
} }
) )
#include "wildmatch.h"
JSC_SSCALL(game_glob,
if (wildmatch(str, str2, WM_PATHNAME | WM_PERIOD | WM_WILDSTAR) == WM_MATCH)
ret = JS_NewBool(js,1);
else
ret = JS_NewBool(js, 0);
)
static const JSCFunctionListEntry js_game_funcs[] = {
MIST_FUNC_DEF(game, engine_start, 1),
MIST_FUNC_DEF(game, engine_input,1),
MIST_FUNC_DEF(game, glob, 2),
};
JSC_CCALL(camera_list, JSC_CCALL(camera_list,
int num; int num;
@@ -5694,6 +5687,14 @@ int globfs_cb(struct globdata *data, char *dir, char *file)
return 1; return 1;
} }
JSC_SSCALL(io_match,
if (wildmatch(str, str2, WM_PATHNAME | WM_PERIOD | WM_WILDSTAR) == WM_MATCH)
ret = JS_NewBool(js,1);
else
ret = JS_NewBool(js, 0);
)
JSC_CCALL(io_globfs, JSC_CCALL(io_globfs,
ret = JS_NewArray(js); ret = JS_NewArray(js);
struct globdata data; struct globdata data;
@@ -5730,6 +5731,7 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, mkdir, 1), MIST_FUNC_DEF(io, mkdir, 1),
MIST_FUNC_DEF(io,stat,1), MIST_FUNC_DEF(io,stat,1),
MIST_FUNC_DEF(io, globfs, 1), MIST_FUNC_DEF(io, globfs, 1),
MIST_FUNC_DEF(io, match, 2),
MIST_FUNC_DEF(io, exists, 1), MIST_FUNC_DEF(io, exists, 1),
MIST_FUNC_DEF(io, mount, 1), MIST_FUNC_DEF(io, mount, 1),
MIST_FUNC_DEF(io,unmount,1), MIST_FUNC_DEF(io,unmount,1),
@@ -7190,7 +7192,6 @@ typedef struct {
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) } #define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
static ModuleEntry module_registry[] = { static ModuleEntry module_registry[] = {
MISTLINE(game),
MISTLINE(io), MISTLINE(io),
MISTLINE(input), MISTLINE(input),
MISTLINE(prosperon), MISTLINE(prosperon),
@@ -7207,8 +7208,6 @@ static ModuleEntry module_registry[] = {
JSC_SCALL(os_use, JSC_SCALL(os_use,
SDL_SharedObject *ptr; SDL_SharedObject *ptr;
printf("str %s found? %d\n", str, access(str,F_OK));
printf("obj? %p\n", SDL_LoadObject(str));
if (access(str, F_OK) != 0 || !(ptr = SDL_LoadObject(str))) { if (access(str, F_OK) != 0 || !(ptr = SDL_LoadObject(str))) {
for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) { for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) {
if (strcmp(str,module_registry[i].name) == 0) { if (strcmp(str,module_registry[i].name) == 0) {
@@ -7232,7 +7231,8 @@ JSC_SCALL(os_use,
) )
JSC_SSCALL(os_trimchr, JSC_SSCALL(os_trimchr,
int len = js2number(js,js_getpropertystr(js,argv[0], "length")); int len;
JS_GETPROP(js,len,argv[0],length,number)
const char *start = str; const char *start = str;
while (*start == *str2) while (*start == *str2)
@@ -7246,6 +7246,8 @@ JSC_SSCALL(os_trimchr,
) )
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, engine_start, 1),
MIST_FUNC_DEF(os, engine_input, 1),
MIST_FUNC_DEF(os, turbulence, 4), MIST_FUNC_DEF(os, turbulence, 4),
MIST_FUNC_DEF(os, model_buffer, 1), MIST_FUNC_DEF(os, model_buffer, 1),
MIST_FUNC_DEF(os, clean_transforms, 0), MIST_FUNC_DEF(os, clean_transforms, 0),
@@ -7634,9 +7636,17 @@ void ffi_load(JSContext *js) {
QJSGLOBALCLASS(os); QJSGLOBALCLASS(os);
JSValue array_proto = js_getpropertystr(js,globalThis, "Array"); JSValue jsarray = JS_GetPropertyStr(js,globalThis, "Array");
array_proto = js_getpropertystr(js,array_proto, "prototype"); JSValue array_proto = JS_GetPropertyStr(js,jsarray, "prototype");
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, countof(js_array_funcs)); JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, countof(js_array_funcs));
JS_FreeValue(js,jsarray);
JS_FreeValue(js,array_proto);
JSValue jsnumber = JS_GetPropertyStr(js,globalThis, "Number");
JSValue number_proto = JS_GetPropertyStr(js,jsnumber, "prototype");
JS_SetPropertyFunctionList(js, number_proto, js_number_funcs, countof(js_number_funcs));
JS_FreeValue(js,jsnumber);
JS_FreeValue(js,number_proto);
JS_SetPropertyStr(js, globalThis, "layout", js_layout_use(js)); JS_SetPropertyStr(js, globalThis, "layout", js_layout_use(js));
JS_SetPropertyStr(js, globalThis, "soloud", js_soloud_use(js)); JS_SetPropertyStr(js, globalThis, "soloud", js_soloud_use(js));