pull out many files into separate uses

This commit is contained in:
2025-01-22 17:49:15 -06:00
parent 3d7ea7d358
commit 9e6f5e7eb1
27 changed files with 903 additions and 804 deletions

View File

@@ -108,7 +108,8 @@ if get_option('editor')
foreach imgui : imsrc
sources += tp / 'imgui' / imgui
endforeach
deps += dependency('qjs-dmon')
sub_dmon = subproject('qjs-dmon')
dmon_dep = sub_dmon.get_variable('qjs_dmon_dep')
endif
includers = []
@@ -131,7 +132,9 @@ prosperon = executable('prosperon', sources,
dependencies: deps,
include_directories: includers,
link_args: link,
build_rpath: '$ORIGIN'
build_rpath: '$ORIGIN',
install:true,
install_dir:'bin'
)
prosperon_dep = declare_dependency(

View File

@@ -8,289 +8,9 @@ Number.roman = {
I: 1,
};
var convert = {};
convert.romanize = function (num) {
if (!+num) return false;
var digits = String(+num).split("");
var key = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
var roman = "",
i = 3;
while (i--) roman = (key[+digits.pop() + i * 10] || "") + roman;
return Array(+digits.join("") + 1).join("M") + roman;
};
convert.deromanize = function (str) {
var str = str.toUpperCase();
var validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/;
var token = /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g;
var key = {
M: 1000,
CM: 900,
D: 500,
CD: 400,
C: 100,
XC: 90,
L: 50,
XL: 40,
X: 10,
IX: 9,
V: 5,
IV: 4,
I: 1,
};
var num = 0,
m;
if (!(str && validator.test(str))) return false;
while ((m = token.exec(str))) num += key[m[0]];
return num;
};
convert.buf2hex = function (buffer) {
// buffer is an ArrayBuffer
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join(" ");
};
var time = os.use('time')
/* Time values are always expressed in terms of real earth-seconds */
Object.assign(time, {
hour2minute() {
return this.hour / this.minute;
},
day2hour() {
return this.day / this.hour;
},
minute2second() {
return this.minute / this.second;
},
week2day() {
return this.week / this.day;
},
});
time.strparse = {
yyyy: "year",
mm: "month",
m: "month",
eee: "yday",
dd: "day",
d: "day",
v: "weekday",
hh: "hour",
h: "hour",
nn: "minute",
n: "minute",
ss: "second",
s: "second",
};
time.doc = {
doc: "Functions for manipulating time.",
second: "Earth-seconds in a second.",
minute: "Seconds in a minute.",
hour: "Seconds in an hour.",
day: "Seconds in a day.",
week: "Seconds in a week.",
weekdays: "Names of the days of the week.",
monthstr: "Full names of the months of the year.",
epoch: "Times are expressed in terms of day 0 at hms 0 of this year.",
now: "Get the time now.",
computer_zone: "Get the time zone of the running computer.",
computer_dst: "Return true if the computer is in daylight savings.",
yearsize: "Given a year, return the number of days in that year.",
monthdays: "Number of days in each month.",
fmt: "Default format for time.",
record: "Given a time, return an object with time fields.",
number: "Return the number representation of a given time.",
text: "Return a text formatted time.",
};
time.second = 1;
time.minute = 60;
time.hour = 3_600;
time.day = 86_400;
time.week = 604_800;
time.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
time.monthstr = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
time.epoch = 1970;
time.isleap = function (year) {
return this.yearsize(year) === 366;
};
time.isleap.doc = "Return true if the given year is a leapyear.";
time.yearsize = function (y) {
if (y % 4 === 0 && (y % 100 != 0 || y % 400 === 0)) return 366;
return 365;
};
time.timecode = function (t, fps = 24) {
var s = Math.trunc(t);
t -= s;
return `${s}:${Math.trunc(fps * s)}`;
};
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
time.zones = {};
time.zones["-12"] = "IDLW";
time.record = function (num, zone = this.computer_zone()) {
if (typeof num === "object") return num;
else if (typeof num === "number") {
var monthdays = this.monthdays.slice();
var rec = {
second: 0,
minute: 0,
hour: 0,
yday: 0,
year: 0,
zone: 0,
};
rec.zone = zone;
num += zone * this.hour;
var hms = num % this.day;
var day = parseInt(num / this.day);
if (hms < 0) {
hms += this.day;
day--;
}
rec.second = hms % this.minute;
var d1 = Math.floor(hms / this.minute);
rec.minute = d1 % this.minute;
rec.hour = Math.floor(d1 / this.minute);
/* addend%7 is 4 */
rec.weekday = (day + 4503599627370496 + 2) % 7;
var d1 = this.epoch;
if (day >= 0) for (d1 = this.epoch; day >= this.yearsize(d1); d1++) day -= this.yearsize(d1);
else for (d1 = this.epoch; day < 0; d1--) day += this.yearsize(d1 - 1);
rec.year = d1;
if (rec.year <= 0) rec.ce = "BC";
else rec.ce = "AD";
rec.yday = day;
if (this.yearsize(d1) === 366) monthdays[1] = 29;
var d0 = day;
for (d1 = 0; d0 >= monthdays[d1]; d1++) d0 -= monthdays[d1];
monthdays[1] = 28;
rec.day = d0 + 1;
rec.month = d1;
return rec;
}
};
time.number = function (rec) {
if (typeof rec === "number") return rec;
else if (typeof rec === "object") {
var c = 0;
var year = rec.year ? rec.year : 0;
var hour = rec.hour ? rec.hour : 0;
var minute = rec.minute ? rec.minute : 0;
var second = rec.second ? rec.second : 0;
var zone = rec.zone ? rec.zone : 0;
if (year > this.epoch) for (var i = this.epoch; i < year; i++) c += this.day * this.yearsize(i);
else if (year < this.epoch) {
for (var i = this.epoch - 1; i > year; i--) c += this.day * this.yearsize(i);
c += (this.yearsize(year) - yday - 1) * this.day;
c += (this.day2hour() - hour - 1) * this.hour;
c += (this.hour2minute() - minute - 1) * this.minute;
c += this.minute2second() - second;
c += zone * this.hour;
c *= -1;
return c;
}
c += second;
c += minute * this.minute;
c += hour * this.hour;
c += yday * this.day;
c -= zone * this.hour;
return c;
}
};
/* Time formatting
yyyy - year in a 4 digit field
y - as many digits as necessary
mm - month (1-12)
mB - month name
mb - abbreviated month name
dd - day (1-31)
d
c - if the year is <= 0, BC. Otherwise, AD.
hh - hour
h
nn - minutes
n
ss - seconds
s
v - day of the week (0-6)
vB - weekday name
vb - abbreviated weekday name
a - am/pm
z - zone, -12 to +11
*/
time.fmt = "vB mB d h:nn:ss TZz a y c";
/* If num is a number, converts to a rec first. */
time.text = function (num, fmt = this.fmt, zone) {
var rec = num;
if (typeof rec === "number") rec = time.record(num, zone);
zone = rec.zone;
if (fmt.match("a")) {
if (rec.hour >= 13) {
rec.hour -= 12;
fmt = fmt.replaceAll("a", "PM");
} else if (rec.hour === 12) fmt = fmt.replaceAll("a", "PM");
else if (rec.hour === 0) {
rec.hour = 12;
fmt = fmt.replaceAll("a", "AM");
} else fmt = fmt.replaceAll("a", "AM");
}
var year = rec.year > 0 ? rec.year : rec.year - 1;
if (fmt.match("c")) {
if (year < 0) {
year = Math.abs(year);
fmt = fmt.replaceAll("c", "BC");
} else fmt = fmt.replaceAll("c", "AD");
}
fmt = fmt.replaceAll("yyyy", year.toString().padStart(4, "0"));
fmt = fmt.replaceAll("y", year);
fmt = fmt.replaceAll("eee", rec.yday + 1);
fmt = fmt.replaceAll("dd", rec.day.toString().padStart(2, "0"));
fmt = fmt.replaceAll("d", rec.day);
fmt = fmt.replaceAll("hh", rec.hour.toString().padStart(2, "0"));
fmt = fmt.replaceAll("h", rec.hour);
fmt = fmt.replaceAll("nn", rec.minute.toString().padStart(2, "0"));
fmt = fmt.replaceAll("n", rec.minute);
fmt = fmt.replaceAll("ss", rec.second.toString().padStart(2, "0"));
fmt = fmt.replaceAll("s", rec.second);
fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone);
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/m[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/v[^bB]/g, rec.weekday);
fmt = fmt.replaceAll("mb", this.monthstr[rec.month].slice(0, 3));
fmt = fmt.replaceAll("mB", this.monthstr[rec.month]);
fmt = fmt.replaceAll("vB", this.weekdays[rec.weekday]);
fmt = fmt.replaceAll("vb", this.weekdays[rec.weekday].slice(0, 3));
return fmt;
};
function deep_copy(from) {
return json.decode(json.encode(from));
}
Object.methods = function (o) {
var m = [];
@@ -761,12 +481,6 @@ Object.defineProperty(String.prototype, "updir", {
},
});
Object.defineProperty(String.prototype, "trimchr", {
value: function (chars) {
return vector.trimchr(this, chars);
},
});
Object.defineProperty(String.prototype, "uc", {
value: function () {
return this.toUpperCase();
@@ -822,12 +536,6 @@ Object.defineProperty(Array.prototype, "reversed", {
},
});
Object.defineProperty(Array.prototype, "rotate", {
value: function array_rotate(a) {
return Vector.rotate(this, a);
},
});
Array.random = function random(arr) {
if (!Array.isArray(arr)) return;
return arr[Math.floor(Math.random()*arr.length)];
@@ -965,12 +673,6 @@ function make_swizz() {
}
make_swizz();
Object.defineProperty(Array.prototype, "normalized", {
value: function () {
return vector.norm(this);
},
});
Object.defineProperty(Array.prototype, "newfirst", {
value: function (i) {
var c = this.slice();
@@ -1209,53 +911,6 @@ Object.defineProperty(Array.prototype, "forEachRight", {
}
});
var vector = os.use('vector')
Math.lerp = vector.lerp;
Math.gcd = vector.gcd;
Math.lcm = vector.lcm;
Math.sum = vector.sum;
Math.mean = vector.mean;
Math.sigma = vector.sigma;
Math.median = vector.median;
vector.v2one = [1,1];
vector.v3one = [1,1,1];
vector.v2zero = [0,0];
vector.v3zero = [0,0,0];
Math.variance = function (series) {
var mean = Math.mean(series);
var vnce = 0;
for (var i = 0; i < series.length; i++) vnce += Math.pow(series[i] - mean, 2);
return vnce / series.length;
};
Math.ci = function (series) {
return (3 * Math.sigma(series)) / Math.sqrt(series.length);
};
Math.grab_from_points = function (pos, points, slop) {
var shortest = slop;
var idx = -1;
points.forEach(function (x, i) {
if (Vector.length(pos.sub(x)) < shortest) {
shortest = Vector.length(pos.sub(x));
idx = i;
}
});
return idx;
};
Math.nearest = function (n, incr) {
return Math.round(n / incr) * incr;
};
Math.places = function (n, digits) {
var div = Math.pow(10, digits);
return Math.round(n * div) / div;
};
Number.hex = function (n) {
var s = Math.floor(n).toString(16);
if (s.length === 1) s = "0" + s;
@@ -1275,104 +930,7 @@ Object.defineProperty(Object.prototype, "lerp", {
},
});
/* MATH EXTENSIONS */
Object.defineProperty(Number.prototype, "lerp", {
value: function (to, t) {
return Math.lerp(this, to, t);
},
});
Object.defineProperty(Number.prototype, "clamp", {
value: function (from, to) {
return Math.clamp(this, from, to);
},
});
Math.clamp = vector.clamp;
Math.random_range = vector.random_range;
Math.rand_int = function (max = 9007199254740991) {
return Math.floor(Math.random() * max);
};
Math.snap = function (val, grid) {
if (!grid || grid === 1) return Math.round(val);
var rem = val % grid;
var d = val - rem;
var i = Math.round(rem / grid) * grid;
return d + i;
};
Math.angledist = vector.angledist;
Math.angledist.doc = "Find the shortest angle between two angles.";
Math.TAU = Math.PI * 2;
Math.deg2rad = function (deg) {
return deg * 0.0174533;
};
Math.rad2deg = function (rad) {
return rad / 0.0174533;
};
Math.turn2rad = function (x) {
return x * Math.TAU;
};
Math.rad2turn = function (x) {
return x / Math.TAU;
};
Math.turn2deg = function (x) {
return x * 360;
};
Math.deg2turn = function (x) {
return x / 360;
};
Math.randomint = function (max) {
return Math.clamp(Math.floor(Math.random() * max), 0, max - 1);
};
Math.variate = vector.variate;
/* VECTORS */
var Vector = {};
Vector.length = vector.length;
Vector.norm = vector.norm;
Vector.project = vector.project;
Vector.dot = vector.dot;
Vector.random = function () {
var vec = [Math.random() - 0.5, Math.random() - 0.5];
return Vector.norm(vec);
};
Vector.angle_between = vector.angle_between;
Vector.rotate = vector.rotate;
vector.direction = function (from, to) {
return vector.norm(to.sub(from));
};
Vector.equal = function (v1, v2, tol) {
if (!tol) return v1.equal(v2);
var eql = true;
var c = v1.sub(v2);
c.forEach(function (x) {
if (!eql) return;
if (Math.abs(x) > tol) eql = false;
});
return eql;
};
Vector.reflect = function (vec, plane) {
var p = Vector.norm(plane);
return vec.sub(p.scale(2 * Vector.dot(vec, p)));
};
Vector.reflect_point = function (vec, point) {
return point.add(vec.sub(point).scale(-1));
};
/* POINT ASSISTANCE */
function points2cm(points) {
var x = 0;
var y = 0;
@@ -1385,182 +943,4 @@ function points2cm(points) {
return [x / n, y / n];
}
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) {
var aatan = Math.atan2(a.y, a.x);
var batan = Math.atan2(b.y, b.x);
return aatan - batan;
});
return ccw.map(function (x) {
return x.add(cm);
});
};
var yaml = {};
yaml.tojson = function (yaml) {
// Replace key value pairs that are strings with quotation marks around them
yaml = yaml.replace(/(\w+):/g, '"$1":');
yaml = yaml.replace(/: ([\w\.\/]+)/g, ': "$1"'); // TODO: make this more general
yaml = yaml.split("\n");
var cont = {};
var cur = 0;
for (var i = 0; i < yaml.length; i++) {
var line = yaml[i];
var indent = line.search(/\S/);
if (indent > cur) {
if (line[indent] == "-") {
cont[indent] = "array";
yaml[i] = line.sub(indent, "[");
} else {
cont[indent] = "obj";
yaml[i] = line.sub(indent - 1, "{");
}
}
if (indent < cur) {
while (cur > indent) {
if (cont[cur] === "obj") yaml[i - 1] = yaml[i - 1] + "}";
else if (cont[cur] === "array") yaml[i - 1] = yaml[i - 1] + "]";
delete cont[cur];
cur--;
}
}
if (indent === cur) {
if (yaml[i][indent] === "-") yaml[i] = yaml[i].sub(indent, ",");
else yaml[i - 1] = yaml[i - 1] + ",";
}
cur = indent;
}
yaml = "{" + yaml.join("\n") + "}";
yaml = yaml.replace(/\s/g, "");
yaml = yaml.replace(/,}/g, "}");
yaml = yaml.replace(/,]/g, "]");
yaml = yaml.replace(/,"[^"]+"\:,/g, ",");
yaml = yaml.replace(/,"[^"]+"\:}/g, "}");
return yaml;
};
Math.sign = function (n) {
return n >= 0 ? 1 : -1;
};
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;
};
function deep_copy(from) {
return json.decode(json.encode(from));
}
function valdiff(from, to) {
if (typeof from !== typeof to) return from;
if (typeof from === "function") return undefined;
if (typeof from === "undefined") return undefined;
if (typeof from === "number") {
return to;
return undefined;
}
if (typeof from === "object") return ediff(from, to);
if (from !== to) return to;
return undefined;
}
function ediff(from, to) {
var ret = {};
if (!to)
// return ediff(from, {});
return deep_copy(from);
Object.entries(from).forEach(function ([key, v]) {
if (typeof v === "function") return;
if (typeof v === "undefined") return;
if (Array.isArray(v)) {
if (!Array.isArray(to[key]) || v.length !== to[key].length) {
var r = ediff(v, []);
if (r) ret[key] = Object.values(r);
return;
}
var diff = ediff(from[key], to[key]);
if (diff && !Object.empty(diff)) ret[key] = Object.values(ediff(v, []));
return;
}
if (typeof v === "object" && v !== null) {
var diff = ediff(v, to[key]);
if (diff && !Object.empty(diff)) ret[key] = diff;
return;
}
if (typeof v === "number" || v === null) {
if (!isFinite(v)) v = null; // Squash infinity to null
if (v !== to[key]) ret[key] = v;
return;
}
if (!to || v !== to[key]) ret[key] = v;
});
if (Object.empty(ret)) return undefined;
return ret;
}
ediff.doc = "Given a from and to object, returns an object that, if applied to from, will make it the same as to. Does not include deletion; it is only additive. If one element in an array is different, the entire array is copied. Squashes infinite numbers to null for use in JSON.";
function samediff(from, to) {
var same = [];
if (!to) return same;
if (typeof to !== "object") {
console.warn("'To' must be an object. Got " + to);
return same;
}
Object.keys(from).forEach(function (k) {
if (Object.isObject(from[k])) {
samediff(from[k], to[k]);
return;
}
// if (Array.isArray(from[k])) {
// var d = valdiff(from[k], to[k]);
// if (!d)
// }
var d = valdiff(from[k], to[k]);
if (!d) delete from[k];
});
return same;
}
samediff.doc = "Given a from and to object, returns an array of keys that are the same on from as on to.";
return {
convert,
time,
Vector,
yaml,
lodash,
};
return {}

43
scripts/convert.js Normal file
View File

@@ -0,0 +1,43 @@
var convert = {};
convert.romanize = function (num) {
if (!+num) return false;
var digits = String(+num).split("");
var key = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
var roman = "",
i = 3;
while (i--) roman = (key[+digits.pop() + i * 10] || "") + roman;
return Array(+digits.join("") + 1).join("M") + roman;
};
convert.deromanize = function (str) {
var str = str.toUpperCase();
var validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/;
var token = /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g;
var key = {
M: 1000,
CM: 900,
D: 500,
CD: 400,
C: 100,
XC: 90,
L: 50,
XL: 40,
X: 10,
IX: 9,
V: 5,
IV: 4,
I: 1,
};
var num = 0,
m;
if (!(str && validator.test(str))) return false;
while ((m = token.exec(str))) num += key[m[0]];
return num;
};
convert.buf2hex = function (buffer) {
// buffer is an ArrayBuffer
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join(" ");
};
return convert

View File

@@ -251,14 +251,5 @@ debug.break_var = function(obj,vars)
});
}
debug.try = function(fn)
{
try {
fn();
} catch(e) {
console.error(e)
}
}
return {debug}
return debug

97
scripts/diff.js Normal file
View File

@@ -0,0 +1,97 @@
var diff = {}
function deep_copy(from) {
return json.decode(json.encode(from));
}
diff.valdiff = function valdiff(from, to) {
if (typeof from !== typeof to) return from;
if (typeof from === "function") return undefined;
if (typeof from === "undefined") return undefined;
if (typeof from === "number") {
return to;
return undefined;
}
if (typeof from === "object") return ediff(from, to);
if (from !== to) return to;
return undefined;
}
diff.ediff = function ediff(from, to) {
var ret = {};
if (!to)
// return ediff(from, {});
return deep_copy(from);
Object.entries(from).forEach(function ([key, v]) {
if (typeof v === "function") return;
if (typeof v === "undefined") return;
if (Array.isArray(v)) {
if (!Array.isArray(to[key]) || v.length !== to[key].length) {
var r = ediff(v, []);
if (r) ret[key] = Object.values(r);
return;
}
var diff = ediff(from[key], to[key]);
if (diff && !Object.empty(diff)) ret[key] = Object.values(ediff(v, []));
return;
}
if (typeof v === "object" && v !== null) {
var diff = ediff(v, to[key]);
if (diff && !Object.empty(diff)) ret[key] = diff;
return;
}
if (typeof v === "number" || v === null) {
if (!isFinite(v)) v = null; // Squash infinity to null
if (v !== to[key]) ret[key] = v;
return;
}
if (!to || v !== to[key]) ret[key] = v;
});
if (Object.empty(ret)) return undefined;
return ret;
}
ediff.doc = "Given a from and to object, returns an object that, if applied to from, will make it the same as to. Does not include deletion; it is only additive. If one element in an array is different, the entire array is copied. Squashes infinite numbers to null for use in JSON.";
diff.samediff = function samediff(from, to) {
var same = [];
if (!to) return same;
if (typeof to !== "object") {
console.warn("'To' must be an object. Got " + to);
return same;
}
Object.keys(from).forEach(function (k) {
if (Object.isObject(from[k])) {
samediff(from[k], to[k]);
return;
}
// if (Array.isArray(from[k])) {
// var d = valdiff(from[k], to[k]);
// if (!d)
// }
var d = valdiff(from[k], to[k]);
if (!d) delete from[k];
});
return same;
}
samediff.doc = "Given a from and to object, returns an array of keys that are the same on from as on to.";
return diff

View File

@@ -1,3 +1,8 @@
globalThis.console = os.use('console')
globalThis.prosperon = os.use('prosperon')
globalThis.game = os.use('game')
var io = os.use('io')
Object.defineProperty(Object.prototype, "object_id", {
value: function() {
return os.value_id(this);
@@ -93,7 +98,7 @@ Resources.replstrs = function replstrs(path) {
}
*/
script = script.replace(regexp, function (str) {
var newstr = Resources.replpath(str.trimchr('"'), path);
var newstr = Resources.replpath(os.trimchr(str,'"'), path);
return `"${newstr}"`;
});
@@ -218,7 +223,37 @@ Resources.find_font = function(file, root = "") {
return find_ext(file, Resources.fonts, root);
}.hashify();
globalThis.console = os.use('console')
var tmpslurp = io.slurp;
io.slurp = function slurp(path)
{
var findpath = Resources.replpath(path);
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
return ret;
}
io.slurpbytes = function(path)
{
path = Resources.replpath(path);
var ret = tmpslurp(path);// || core_db.slurp(path);
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
return ret;
}
var ignore = io.slurp('.prosperonignore').split('\n');
var allpaths;
var tmpglob = io.glob;
io.glob = function glob(pat) {
if (!allpaths)
allpaths = io.globfs(ignore);
return allpaths.filter(str => game.glob(pat,str)).sort();
}
io.invalidate = function()
{
allpaths = undefined;
}
console.transcript = "";
console.say = function (msg) {
@@ -227,19 +262,18 @@ console.say = function (msg) {
console.transcript += msg;
};
globalThis.say = console.say;
globalThis.print = console.print;
console.rec = function(category, priority, line, file, msg)
{
return `${file}:${line}: [${category} ${priority}]: ${msg}` + "\n";
}
var io = os.use('io')
var logfile = io.open('.prosperon/log.txt')
//logfile.buffer(1024*1024) // 1MB buffer
console.stdout_lvl = 0;
function pprint(msg, lvl = 0) {
if (lvl < console.stdout_lvl && !logfile) return;
@@ -258,7 +292,7 @@ function pprint(msg, lvl = 0) {
if (m) line = m;
}
var fmt = console.rec("script", lvl, line,file, msg);
if (lvl >= console.stdout_lvl)
console.print(fmt)
@@ -295,7 +329,7 @@ ${e.stack}`, 4)
};
console.panic = function (e) {
console.pprint(msg, 5)
console.pprint(e , 5)
os.quit();
};
@@ -305,8 +339,6 @@ console.assert = function (op, str = `assertion failed [value '${op}']`) {
os.on('uncaught_exception', function(e) { console.error(e); });
console.stdout_lvl = 1;
console.doc = {
log: "Output directly to in game console.",
level: "Set level to output logging to console.",
@@ -322,55 +354,10 @@ console.doc = {
globalThis.global = globalThis;
var tmpslurp = io.slurp;
io.slurp = function slurp(path)
{
var findpath = Resources.replpath(path);
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
return ret;
}
io.slurpbytes = function(path)
{
path = Resources.replpath(path);
var ret = tmpslurp(path);// || core_db.slurp(path);
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
return ret;
}
function bare_use(file) {
try {
var script = io.slurp(file);
if (!script) return;
var fnname = file.replace(/[^a-zA-Z0-9_$]/g, "_");
script = `(function ${fnname}() { var self = this; ${script}; })`;
Object.assign(globalThis, os.eval(file, script)());
} catch(e) {
console.log(file)
console.error(e);
throw e
}
}
bare_use("core/scripts/base.js");
var game = os.use('game')
var ignore = io.slurp('.prosperonignore').split('\n');
var allpaths;
var tmpglob = io.glob;
io.glob = function glob(pat) {
if (!allpaths)
allpaths = io.globfs(ignore);
return allpaths.filter(str => game.glob(pat,str)).sort();
}
io.invalidate = function()
{
allpaths = undefined;
}
var script = io.slurp("core/scripts/base.js")
var fnname = "base"
script = `(function ${fnname}() { ${script}; })`
Object.assign(globalThis,os.eval("core/scripts/base.js",script)())
function splitPath(path) {
return path.split('/').filter(part => part.length > 0);
@@ -427,7 +414,7 @@ function matchPath(pathParts, patternParts) {
return patternIndex === patternParts.length;
}
globalThis.prosperon = os.use('prosperon')
prosperon.SIGABRT = function()
{
@@ -474,21 +461,84 @@ function add_timer(obj, fn, seconds)
var actor = {};
var use = function use(file) {
var so_ext;
switch(os.sys()) {
case 'Windows':
so_ext = '.dll';
break;
default:
so_ext = '.so';
break;
}
var use_cache = {}
function load_mod(file)
{
try {
var par = script_fn(file)
if (par?.module_ret)
if (par?.module_ret) {
use_cache[file] = par.module_
return par.module_ret
}
} catch(e) {
console.error(e)
}
try {
return os.use('./lib' + file + '.so')
} catch(e) { console.error(e)}
return os.use('./lib' + file + so_ext)
} catch(e) { console.error(e) }
return os.use(file)
}.hashify()
}
var use = function use(file) {
if (use_cache[file]) return use_cache[file];
use_cache[file] = load_mod(file)
return use_cache[file]
}
use.hotreload = function(file)
{
console.log(`hot reloading ${file}`)
var oldval = use_cache[file]
var newval = load_mod(file)
if (!oldval) {
use_cache[file] = newval;
return newval;
}
if (typeof oldval !== 'object' || typeof newval !== 'object' || !oldval || !newval) {
use_cache[file] = newval;
return newval;
}
use_patch(oldval, newval);
return oldval;
}
function use_patch(target, source)
{
// First remove properties that arent in source at all
for (let key of Object.keys(target)) {
if (!(key in source)) {
delete target[key];
}
}
// Then shallow-copy the sources own properties
for (let key of Object.keys(source)) {
target[key] = source[key];
}
// Update the prototype if needed so that new or changed methods come along
let oldProto = Object.getPrototypeOf(target);
let newProto = Object.getPrototypeOf(source);
if (oldProto !== newProto) {
Object.setPrototypeOf(target, newProto);
}
}
var script_fn = function script_fn(path) {
var file = Resources.find_script(path)
@@ -714,6 +764,7 @@ Register.add_cb("imgui");
Register.add_cb("app");
Register.add_cb("prerender");
actor.toString = function() { return this.__file }
actor.spawn = function spawn(script, config, callback) {
var prog
if (!script) {
@@ -730,6 +781,7 @@ actor.spawn = function spawn(script, config, callback) {
prog.module_ret.__proto__ = actor;
underling = Object.create(prog.module_ret);
underling.overling = this;
underling.__file = script
underling.timers = []
underling.underlings = new Set()
@@ -737,7 +789,7 @@ actor.spawn = function spawn(script, config, callback) {
if (callback) callback(underling)
try{
prog.prog_fn.call(underling)
} catch(e) { console.error(e); throw e}
} catch(e) {throw e}
if (typeof config === 'object') Object.assign(underling,config);
if (!underling.__reggies)
@@ -758,7 +810,9 @@ actor.spawn.doc = `Create a new actor, using this actor as the overling, initial
actor.clear = function actor_clear()
{
this.underlings.forEach(p => p.kill())
this.underlings.forEach(p => {
p.kill();
})
this.underlings.clear()
}
@@ -773,11 +827,13 @@ actor.kill = function kill() {
Event.rm_obj(this);
this.clear()
this.overling.underlings.delete(this)
delete this.underlings
this.__dead__ = true;
if (typeof this.garbage === "function") this.garbage();
if (typeof this.then === "function") this.then();
search.tag_clear_guid(this)
};
actor.kill.doc = `Remove this actor and all its underlings from existence.`;
@@ -808,6 +864,18 @@ globalThis.world = app;
var search = use('search')
/* MATH EXTENSIONS */
Object.defineProperty(Number.prototype, "lerp", {
value: function (to, t) {
return Math.lerp(this, to, t);
},
});
Object.defineProperty(Number.prototype, "clamp", {
value: function (from, to) {
return Math.clamp(this, from, to);
},
});
global.mixin("color");
global.mixin("std")

View File

@@ -1,4 +1,5 @@
var geometry = os.use('geometry')
var vector = use('vector')
var shape = {};
shape.box = {};
@@ -55,7 +56,7 @@ shape.arc = function (radius, angle, n, start = 0) {
angle = Math.deg2rad(angle);
var arclen = angle / n;
for (var i = 0; i < n; i++) points.push(Vector.rotate([radius, 0], start + arclen * i));
for (var i = 0; i < n; i++) points.push(vector.rotate([radius, 0], start + arclen * i));
return points;
};

View File

@@ -120,15 +120,24 @@ graphics.texture.total_vram = function()
return vram;
}
function merge_objects(ov,nv,arr)
{
arr.forEach(x => ov[x] = nv[x])
}
graphics.tex_hotreload = function tex_hotreload(file) {
console.log(`hot reloading ${file}`)
if (!(file in graphics.texture.cache)) return;
console.log('really doing it')
var img = create_image(file);
var oldimg = graphics.texture.cache[file];
console.log(json.encode(img))
console.log(`new image:${json.encode(img)}`)
console.log(`old image: ${json.encode(oldimg)}`)
merge_objects(oldimg,img, ['surface', 'texture', 'loop', 'time']);
graphics.texture.cache[file] = img;
// graphics.texture.cache[file] = img;
};
function make_spritesheet(paths, width, height)

View File

@@ -301,7 +301,7 @@ var Player = {
},
print_pawns() {
for (var pawn of this.pawns.reversed()) say(pawn.toString());
for (var pawn of this.pawns.reversed()) console.log(pawn.toString());
},
create() {
@@ -316,11 +316,12 @@ var Player = {
pawns: [],
control(pawn) {
if (!pawn) return
if (!pawn.inputs) {
console.warn(`attempted to control a pawn without any input object.`);
return;
}
if (!pawn)
return
if (!pawn.inputs)
throw new Error("attempted to control a pawn without any input object.");
this.pawns.push_unique(pawn);
},
@@ -330,14 +331,14 @@ var Player = {
};
input.do_uncontrol = function input_do_uncontrol(pawn) {
if (!pawn.inputs) return;
// if (!pawn.inputs) return;
Player.players.forEach(function (p) {
p.pawns = p.pawns.filter(x => x !== pawn);
p.pawns = p.pawns.filter(x => x !== pawn)
});
};
for (var i = 0; i < 4; i++)
Player.create();
//for (var i = 0; i < 4; i++)
Player.create();
Player.control.doc = "Control a provided object, if the object has an 'inputs' object.";
Player.uncontrol.doc = "Uncontrol a previously controlled object.";

35
scripts/io.js Normal file
View File

@@ -0,0 +1,35 @@
var io = os.use('io')
var tmpslurp = io.slurp;
io.slurp = function slurp(path)
{
var findpath = Resources.replpath(path);
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
return ret;
}
io.slurpbytes = function(path)
{
path = Resources.replpath(path);
var ret = tmpslurp(path);// || core_db.slurp(path);
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
return ret;
}
var ignore = io.slurp('.prosperonignore').split('\n');
var allpaths;
var tmpglob = io.glob;
io.glob = function glob(pat) {
if (!allpaths)
allpaths = io.globfs(ignore);
return allpaths.filter(str => game.glob(pat,str)).sort();
}
io.invalidate = function()
{
allpaths = undefined;
}
return io

View File

@@ -268,4 +268,3 @@ layout.inputs.mouse.left = function()
layout.toString = _ => "layout"
return layout

10
scripts/lodash.js Normal file
View File

@@ -0,0 +1,10 @@
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

View File

@@ -9,6 +9,8 @@ var HIT = {
};
*/
var vector = use('vector')
var phys = {};
phys.pos_query = function pos_query(pos, start = world, give = 10) {
@@ -18,7 +20,7 @@ phys.pos_query = function pos_query(pos, start = world, give = 10) {
if (ret) return ret.entity;
return game.all_objects(function (o) {
var dist = Vector.length(o.pos.sub(pos));
var dist = vector.length(o.pos.sub(pos));
if (dist <= give) return o;
});
};

63
scripts/pmath.js Normal file
View File

@@ -0,0 +1,63 @@
var pmath = {}
var vector = use('vector')
pmath.rand_int = function (max = 9007199254740991) {
return Math.floor(Math.random() * max);
};
pmath.snap = function (val, grid) {
if (!grid || grid === 1) return Math.round(val);
var rem = val % grid;
var d = val - rem;
var i = Math.round(rem / grid) * grid;
return d + i;
};
pmath.TAU = Math.PI * 2;
pmath.deg2rad = function (deg) {
return deg * 0.0174533;
};
pmath.rad2deg = function (rad) {
return rad / 0.0174533;
};
pmath.turn2rad = function (x) {
return x * Math.TAU;
};
pmath.rad2turn = function (x) {
return x / Math.TAU;
};
pmath.turn2deg = function (x) {
return x * 360;
};
pmath.deg2turn = function (x) {
return x / 360;
};
pmath.randomint = function (max) {
return Math.clamp(Math.floor(Math.random() * max), 0, max - 1);
};
pmath.variate = vector.variate;
pmath.sortpointsccw = function (points) {
var cm = points2cm(points);
var cmpoints = points.map(function (x) {
return x.sub(cm);
});
var ccw = cmpoints.sort(function (a, b) {
var aatan = Math.atan2(a.y, a.x);
var batan = Math.atan2(b.y, b.x);
return aatan - batan;
});
return ccw.map(function (x) {
return x.add(cm);
});
};
pmath.sign = function (n) {
return n >= 0 ? 1 : -1;
};
return pmath

View File

@@ -1,5 +1,7 @@
var profile = os.use('profile')
var pmath = use('pmath')
/*
TYPES OF PROFILING
report - can see specific events that happened. Includes inclusive vs noninclusive times. When used on top of each other, also generates a callstack.
@@ -117,12 +119,12 @@ profile.start_cpu_gather_fn = function()
profile.cpu_start = profile.now();
var st = profile.cpu_start;
profile.gather(Math.variate(hittar,hitpct), function() {
profile.gather(pmath.variate(hittar,hitpct), function() {
var time = profile.now() - st;
var err = new Error();
add_callgraph_from_stack(err, time);
st = profile.now();
profile.gather_rate(Math.variate(hittar,hitpct));
profile.gather_rate(pmath.variate(hittar,hitpct));
});
}
@@ -142,7 +144,7 @@ profile.start_cpu_gather = function (gathertime = 5) {
st = profile.now();
if (profile.secs(st - profile.cpu_start) < gathertime)
profile.gather_rate(Math.variate(hittar, hitpct));
profile.gather_rate(pmath.variate(hittar, hitpct));
else
profile.stop_cpu_measure();
});

View File

@@ -1,8 +1,9 @@
var render = {}
var profile = use('profile')
var game = os.use('game')
var config = use('config.js')
var gizmo = use('gizmos')
var vector = use('vector')
var search = use('search')
game.timescale = 1
@@ -500,7 +501,6 @@ var main_depth = {
function render_camera(cmds, camera)
{
var pass;
try{
delete camera.target // TODO: HORRIBLE
if (!camera.target) {
main_color.width = main_depth.width = camera.size.x;
@@ -611,14 +611,12 @@ try{
pass.draw_indexed(group.num_indices, 1, group.first_index, 0, 0);
}
cmds.pop_debug_group();
} catch(e) {console.error(e); }
finally{
pass?.end();
render_queue = [];
hud_queue = [];
}
}
function mode_rect(src,dst,mode = "stretch")
{
@@ -722,11 +720,9 @@ function gpupresent()
{
os.clean_transforms();
prosperon.prerender();
try{
var cmds = render._main.acquire_cmd_buffer();
render_queue = sprites_to_queue().concat(render_queue);
render_camera(cmds, prosperon.camera);
} catch(e) { console.error(e); } finally {
var swapchain_tex = cmds.acquire_swapchain();
if (!swapchain_tex)
cmds.cancel();
@@ -752,7 +748,6 @@ function gpupresent()
}
cmds.submit()
}
}
}
var pipeline_model;
@@ -859,9 +854,9 @@ render.cross = function render_cross(pos, size, color = Color.red, thickness = 1
};
render.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10, pipe = sprite_pipeline) {
var dir = end.sub(start).normalized();
var wing1 = [Vector.rotate(dir, wingangle).scale(wingspan).add(end), end];
var wing2 = [Vector.rotate(dir, -wingangle).scale(wingspan).add(end), end];
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);
@@ -1204,7 +1199,7 @@ function screen2cam(pos) {
screen2cam.doc = "Convert a screen space position in pixels to a normalized viewport position in a camera.";
prosperon.gizmos = function gizmos() {
game.all_objects(o => {
search.all_objects(o => {
if (o.gizmo) render.image(graphics.texture(o.gizmo), o.pos);
});
};
@@ -1259,6 +1254,8 @@ var imdebug = function imdebug() {
var observed_tex = undefined;
var debug = {}
debug.console = false
var imgui_fn = function imgui_fn() {
imgui.newframe();
if (debug.console)
@@ -1341,21 +1338,25 @@ var imgui_fn = function imgui_fn() {
// imgui.endframe(render._main);
};
var dmon = use('dmon')
var dmon
try {
dmon = use('dmon')
} catch (e) {
console.log(`could not use dmon`)
console.error(e)
}
if (dmon) dmon.watch('.');
function dmon_cb(e)
{
try {
io.invalidate();
if (e.file.startsWith('.')) return;
// if (e.file.endsWith('.js'))
// actor.hotreload(e.file);
if (e.file.endsWith('.js'))
use.hotreload(e.file);
if (e.file.endsWith('.hlsl'))
shader_hotreload(e.file);
else if (Resources.is_image(e.file))
game.tex_hotreload(e.file);
} catch(e) { console.error(e); }
graphics.tex_hotreload(e.file);
}
var sim = use('sim')
@@ -1377,21 +1378,19 @@ render.process = function process() {
var dt = last_frame_time - frame_t;
frame_t = last_frame_time;
try {
game.engine_input(e => {
prosperon[e.type]?.(e);
});
} catch(e) { console.error(e); }
layout.newframe();
try { prosperon.appupdate(dt); } catch(e) { console.error(e) }
input.procdown();
try {
emitters.update(dt * game.timescale);
os.update_timers(dt * game.timescale);
prosperon.update(dt*game.timescale);
} catch(e) { console.error(e) }
prosperon.appupdate(dt)
input.procdown()
emitters.update(dt * game.timescale)
os.update_timers(dt * game.timescale)
prosperon.update(dt*game.timescale)
if (sim.mode === "step") sim.pause();
if (sim.mode === "play" || sim.mode === "step") {
@@ -1407,13 +1406,12 @@ try {
}
current_queue = render_queue;
try { prosperon.draw(); } catch(e) { console.error(e) }
prosperon.draw()
for (var e of emitters.all())
render.particles(e);
current_queue = hud_queue;
try { prosperon.hud(); } catch(e) { console.error(e) }
try { imgui_fn(); } catch(e) { console.error(e) }
prosperon.hud()
imgui_fn()
render._main.present();
tracy.end_frame();

View File

@@ -1,4 +1,5 @@
var Spline = {};
var vector = use('vector')
Spline.sample_angle = function (type, points, angle) {
if (type === 0) return spline.catmull(points, angle);
else if (type === 1) return spline.bezier(points, angle);
@@ -6,8 +7,8 @@ Spline.sample_angle = function (type, points, angle) {
};
Spline.bezier_loop = function (cp) {
cp.push(Vector.reflect_point(cp.at(-2), cp.at(-1)));
cp.push(Vector.reflect_point(cp[1], cp[0]));
cp.push(vector.reflect_point(cp.at(-2), cp.at(-1)));
cp.push(vector.reflect_point(cp[1], cp[0]));
cp.push(cp[0].slice());
return cp;
};
@@ -118,4 +119,4 @@ Spline.bezier_is_handle = function (points, i) {
return !Spline.bezier_is_node(points, i);
};
return { Spline };
return Spline

View File

@@ -106,8 +106,9 @@ var sprite = {
this.transform.parent = undefined
for (var t of this.transform.children())
t.parent = undefined
delete this.transform
delete this.transform.sprite
delete this._sprite
// console.log("CLEARED SPRITE")
},
anchor: [0, 0],
set layer(v) { this._sprite.layer = v; },
@@ -187,7 +188,7 @@ var tree = os.make_rtree()
sprite.tree = tree;
sprite.t_hook = function() {
var msp = this.sprite;
var msp = this.sprite._sprite;
if (this.__in)
tree.delete(msp);
msp.rect = this.torect()
@@ -212,5 +213,5 @@ this.transform.change_hook = $.t_hook;
var msp = os.make_sprite();
this._sprite = msp;
msp.color = Color.white;
this.transform.sprite = msp
this.transform.sprite = this

38
scripts/stats.js Normal file
View File

@@ -0,0 +1,38 @@
var stats = {}
var vector = use('vector')
/*
Math.variance = function (series) {
var mean = Math.mean(series);
var vnce = 0;
for (var i = 0; i < series.length; i++) vnce += Math.pow(series[i] - mean, 2);
return vnce / series.length;
};
Math.ci = function (series) {
return (3 * Math.sigma(series)) / Math.sqrt(series.length);
};
Math.grab_from_points = function (pos, points, slop) {
var shortest = slop;
var idx = -1;
points.forEach(function (x, i) {
if (vector.length(pos.sub(x)) < shortest) {
shortest = vector.length(pos.sub(x));
idx = i;
}
});
return idx;
};
Math.nearest = function (n, incr) {
return Math.round(n / incr) * incr;
};
Math.places = function (n, digits) {
var div = Math.pow(10, digits);
return Math.round(n * div) / div;
};
*/
return stats

243
scripts/time.js Normal file
View File

@@ -0,0 +1,243 @@
var time = os.use('time')
/* Time values are always expressed in terms of real earth-seconds */
Object.assign(time, {
hour2minute() {
return this.hour / this.minute;
},
day2hour() {
return this.day / this.hour;
},
minute2second() {
return this.minute / this.second;
},
week2day() {
return this.week / this.day;
},
});
time.strparse = {
yyyy: "year",
mm: "month",
m: "month",
eee: "yday",
dd: "day",
d: "day",
v: "weekday",
hh: "hour",
h: "hour",
nn: "minute",
n: "minute",
ss: "second",
s: "second",
};
time.doc = {
doc: "Functions for manipulating time.",
second: "Earth-seconds in a second.",
minute: "Seconds in a minute.",
hour: "Seconds in an hour.",
day: "Seconds in a day.",
week: "Seconds in a week.",
weekdays: "Names of the days of the week.",
monthstr: "Full names of the months of the year.",
epoch: "Times are expressed in terms of day 0 at hms 0 of this year.",
now: "Get the time now.",
computer_zone: "Get the time zone of the running computer.",
computer_dst: "Return true if the computer is in daylight savings.",
yearsize: "Given a year, return the number of days in that year.",
monthdays: "Number of days in each month.",
fmt: "Default format for time.",
record: "Given a time, return an object with time fields.",
number: "Return the number representation of a given time.",
text: "Return a text formatted time.",
};
time.second = 1;
time.minute = 60;
time.hour = 3_600;
time.day = 86_400;
time.week = 604_800;
time.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
time.monthstr = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
time.epoch = 1970;
time.isleap = function (year) {
return this.yearsize(year) === 366;
};
time.isleap.doc = "Return true if the given year is a leapyear.";
time.yearsize = function (y) {
if (y % 4 === 0 && (y % 100 != 0 || y % 400 === 0)) return 366;
return 365;
};
time.timecode = function (t, fps = 24) {
var s = Math.trunc(t);
t -= s;
return `${s}:${Math.trunc(fps * s)}`;
};
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
time.zones = {};
time.zones["-12"] = "IDLW";
time.record = function (num, zone = this.computer_zone()) {
if (typeof num === "object") return num;
else if (typeof num === "number") {
var monthdays = this.monthdays.slice();
var rec = {
second: 0,
minute: 0,
hour: 0,
yday: 0,
year: 0,
zone: 0,
};
rec.zone = zone;
num += zone * this.hour;
var hms = num % this.day;
var day = parseInt(num / this.day);
if (hms < 0) {
hms += this.day;
day--;
}
rec.second = hms % this.minute;
var d1 = Math.floor(hms / this.minute);
rec.minute = d1 % this.minute;
rec.hour = Math.floor(d1 / this.minute);
/* addend%7 is 4 */
rec.weekday = (day + 4503599627370496 + 2) % 7;
var d1 = this.epoch;
if (day >= 0) for (d1 = this.epoch; day >= this.yearsize(d1); d1++) day -= this.yearsize(d1);
else for (d1 = this.epoch; day < 0; d1--) day += this.yearsize(d1 - 1);
rec.year = d1;
if (rec.year <= 0) rec.ce = "BC";
else rec.ce = "AD";
rec.yday = day;
if (this.yearsize(d1) === 366) monthdays[1] = 29;
var d0 = day;
for (d1 = 0; d0 >= monthdays[d1]; d1++) d0 -= monthdays[d1];
monthdays[1] = 28;
rec.day = d0 + 1;
rec.month = d1;
return rec;
}
};
time.number = function (rec) {
if (typeof rec === "number") return rec;
else if (typeof rec === "object") {
var c = 0;
var year = rec.year ? rec.year : 0;
var hour = rec.hour ? rec.hour : 0;
var minute = rec.minute ? rec.minute : 0;
var second = rec.second ? rec.second : 0;
var zone = rec.zone ? rec.zone : 0;
if (year > this.epoch) for (var i = this.epoch; i < year; i++) c += this.day * this.yearsize(i);
else if (year < this.epoch) {
for (var i = this.epoch - 1; i > year; i--) c += this.day * this.yearsize(i);
c += (this.yearsize(year) - yday - 1) * this.day;
c += (this.day2hour() - hour - 1) * this.hour;
c += (this.hour2minute() - minute - 1) * this.minute;
c += this.minute2second() - second;
c += zone * this.hour;
c *= -1;
return c;
}
c += second;
c += minute * this.minute;
c += hour * this.hour;
c += yday * this.day;
c -= zone * this.hour;
return c;
}
};
/* Time formatting
yyyy - year in a 4 digit field
y - as many digits as necessary
mm - month (1-12)
mB - month name
mb - abbreviated month name
dd - day (1-31)
d
c - if the year is <= 0, BC. Otherwise, AD.
hh - hour
h
nn - minutes
n
ss - seconds
s
v - day of the week (0-6)
vB - weekday name
vb - abbreviated weekday name
a - am/pm
z - zone, -12 to +11
*/
time.fmt = "vB mB d h:nn:ss TZz a y c";
/* If num is a number, converts to a rec first. */
time.text = function (num, fmt = this.fmt, zone) {
var rec = num;
if (typeof rec === "number") rec = time.record(num, zone);
zone = rec.zone;
if (fmt.match("a")) {
if (rec.hour >= 13) {
rec.hour -= 12;
fmt = fmt.replaceAll("a", "PM");
} else if (rec.hour === 12) fmt = fmt.replaceAll("a", "PM");
else if (rec.hour === 0) {
rec.hour = 12;
fmt = fmt.replaceAll("a", "AM");
} else fmt = fmt.replaceAll("a", "AM");
}
var year = rec.year > 0 ? rec.year : rec.year - 1;
if (fmt.match("c")) {
if (year < 0) {
year = Math.abs(year);
fmt = fmt.replaceAll("c", "BC");
} else fmt = fmt.replaceAll("c", "AD");
}
fmt = fmt.replaceAll("yyyy", year.toString().padStart(4, "0"));
fmt = fmt.replaceAll("y", year);
fmt = fmt.replaceAll("eee", rec.yday + 1);
fmt = fmt.replaceAll("dd", rec.day.toString().padStart(2, "0"));
fmt = fmt.replaceAll("d", rec.day);
fmt = fmt.replaceAll("hh", rec.hour.toString().padStart(2, "0"));
fmt = fmt.replaceAll("h", rec.hour);
fmt = fmt.replaceAll("nn", rec.minute.toString().padStart(2, "0"));
fmt = fmt.replaceAll("n", rec.minute);
fmt = fmt.replaceAll("ss", rec.second.toString().padStart(2, "0"));
fmt = fmt.replaceAll("s", rec.second);
fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone);
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/m[^bB]/g, rec.month + 1);
fmt = fmt.replaceAll(/v[^bB]/g, rec.weekday);
fmt = fmt.replaceAll("mb", this.monthstr[rec.month].slice(0, 3));
fmt = fmt.replaceAll("mB", this.monthstr[rec.month]);
fmt = fmt.replaceAll("vB", this.weekdays[rec.weekday]);
fmt = fmt.replaceAll("vb", this.weekdays[rec.weekday].slice(0, 3));
return fmt;
};
return time

View File

@@ -1,5 +1,6 @@
var ret = {
get pos() {
if (!this.transform) return
return this.transform.pos;
},
set pos(x) {

View File

@@ -117,17 +117,25 @@ Ease.elastic.c5 = (2 * Math.PI) / 4.5;
var tween = function (from, to, time, fn, cb) {
var start = profile.now()
function cleanup() {
stop()
fn = undefined
stop = undefined
cb = undefined
update = undefined
}
var update = function tween_update(dt) {
var elapsed = profile.now() - start;
fn(from.lerp(to, elapsed / time));
if (elapsed >= time) {
fn(to);
stop();
cb?.();
fn(to)
cb?.()
cleanup()
}
};
var stop = Register.update.register(update);
return stop;
return cleanup
};
var Tween = {

41
scripts/vector.js Normal file
View File

@@ -0,0 +1,41 @@
/* VECTORS */
var vector = os.use('vector')
vector.random = function () {
var vec = [Math.random() - 0.5, Math.random() - 0.5];
return vector.norm(vec);
};
vector.direction = function (from, to) {
return vector.norm(to.sub(from));
};
vector.equal = function (v1, v2, tol) {
if (!tol) return v1.equal(v2);
var eql = true;
var c = v1.sub(v2);
c.forEach(function (x) {
if (!eql) return;
if (Math.abs(x) > tol) eql = false;
});
return eql;
};
vector.reflect = function (vec, plane) {
var p = vector.norm(plane);
return vec.sub(p.scale(2 * vector.dot(vec, p)));
};
vector.reflect_point = function (vec, point) {
return point.add(vec.sub(point).scale(-1));
};
vector.v2one = [1,1];
vector.v3one = [1,1,1];
vector.v2zero = [0,0];
vector.v3zero = [0,0,0];
return vector

51
scripts/yaml.js Normal file
View File

@@ -0,0 +1,51 @@
var yaml = {};
yaml.tojson = function (yaml) {
// Replace key value pairs that are strings with quotation marks around them
yaml = yaml.replace(/(\w+):/g, '"$1":');
yaml = yaml.replace(/: ([\w\.\/]+)/g, ': "$1"'); // TODO: make this more general
yaml = yaml.split("\n");
var cont = {};
var cur = 0;
for (var i = 0; i < yaml.length; i++) {
var line = yaml[i];
var indent = line.search(/\S/);
if (indent > cur) {
if (line[indent] == "-") {
cont[indent] = "array";
yaml[i] = line.sub(indent, "[");
} else {
cont[indent] = "obj";
yaml[i] = line.sub(indent - 1, "{");
}
}
if (indent < cur) {
while (cur > indent) {
if (cont[cur] === "obj") yaml[i - 1] = yaml[i - 1] + "}";
else if (cont[cur] === "array") yaml[i - 1] = yaml[i - 1] + "]";
delete cont[cur];
cur--;
}
}
if (indent === cur) {
if (yaml[i][indent] === "-") yaml[i] = yaml[i].sub(indent, ",");
else yaml[i - 1] = yaml[i - 1] + ",";
}
cur = indent;
}
yaml = "{" + yaml.join("\n") + "}";
yaml = yaml.replace(/\s/g, "");
yaml = yaml.replace(/,}/g, "}");
yaml = yaml.replace(/,]/g, "]");
yaml = yaml.replace(/,"[^"]+"\:,/g, ",");
yaml = yaml.replace(/,"[^"]+"\:}/g, "}");
return yaml;
};
return yaml

View File

@@ -1116,7 +1116,7 @@ static void js_transform_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark
transform *t = JS_GetOpaque(val, js_transform_id);
if (!t) return;
// Mark the JSValue references stored in your struct
JS_MarkValue(rt, t->self, mark_func);
// JS_MarkValue(rt, t->self, mark_func);
JS_MarkValue(rt, t->change_hook, mark_func);
JS_MarkValue(rt, t->jsparent, mark_func);
// Mark the array elements
@@ -1944,20 +1944,6 @@ JSC_CCALL(vector_clamp,
return number2js(js,x > h ? h : x < l ? l : x);
)
JSC_SSCALL(vector_trimchr,
int len = js2number(js,js_getpropertystr(js,argv[0], "length"));
const char *start = str;
while (*start == *str2)
start++;
const char *end = str + len-1;
while(*end == *str2)
end--;
ret = JS_NewStringLen(js, start, end-start+1);
)
JSC_CCALL(vector_angledist,
double a1 = js2number(js,argv[0]);
double a2 = js2number(js,argv[1]);
@@ -2125,7 +2111,6 @@ static const JSCFunctionListEntry js_vector_funcs[] = {
MIST_FUNC_DEF(vector, gcd, 2),
MIST_FUNC_DEF(vector, lcm, 2),
MIST_FUNC_DEF(vector, clamp, 3),
MIST_FUNC_DEF(vector, trimchr, 2),
MIST_FUNC_DEF(vector, angledist, 2),
MIST_FUNC_DEF(vector, variate, 2),
MIST_FUNC_DEF(vector, random_range, 2),
@@ -2652,7 +2637,7 @@ JSC_CCALL(game_engine_input,
#endif
JSValue e = event2js(js,event);
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
JS_FreeValue(js,ret);
uncaught_exception(js,ret);
}
)
#include "wildmatch.h"
@@ -5914,32 +5899,39 @@ static JSValue js_transform_set_parent(JSContext *js, JSValueConst self, JSValue
return JS_ThrowReferenceError(js,"Parent must be another transform.");
transform *t = js2transform(js,self);
if (t->parent) {
JS_FreeValue(js,t->jsparent);
for (int i = 0; i < arrlen(p->children); i++) {
if (p->children[i] == t) {
arrdelswap(p->children,i);
if (t == p)
return JS_ThrowReferenceError(js, "A transform cannot be its own parent.");
if (t->parent) {
transform *cur_parent = t->parent;
JS_FreeValue(js,t->jsparent);
t->jsparent = JS_UNDEFINED;
for (int i = 0; i < arrlen(cur_parent->children); i++) {
if (cur_parent->children[i] == t) {
arrdelswap(cur_parent->children,i);
break;
}
}
for (int i = 0; i < arrlen(p->jschildren); i++) {
if (JS_SameValue(js,p->jschildren[i],self)) {
JS_FreeValue(js,p->jschildren[i]);
arrdelswap(p->jschildren,i);
for (int i = 0; i < arrlen(cur_parent->jschildren); i++) {
if (JS_SameValue(js,cur_parent->jschildren[i],self)) {
JS_FreeValue(js,cur_parent->jschildren[i]);
arrdelswap(cur_parent->jschildren,i);
break;
}
}
}
if (!p) return JS_UNDEFINED;
t->parent = p;
t->jsparent = JS_DupValue(js,v);
arrput(p->children, t);
JSValue child = JS_DupValue(js,self);
arrput(p->jschildren,child);
if (p) {
arrput(p->children, t);
JSValue child = JS_DupValue(js,self);
arrput(p->jschildren,child);
}
transform_apply(t);
@@ -6038,10 +6030,9 @@ JSC_CCALL(performance_unpack_string, JS_ToCString(js, argv[0]))
JSC_CCALL(performance_call_fn_n,
for (int i = 0; i < js2number(js,argv[1]); i++) {
JSValue r = JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
if (JS_IsException(r)) return r;
JS_FreeValue(js,r);
uncaught_exception(js,r);
}
ret = JS_Call(js,argv[2], JS_UNDEFINED, 0, NULL);
uncaught_exception(js,JS_Call(js,argv[2], JS_UNDEFINED, 0, NULL));
)
static const JSCFunctionListEntry js_performance_funcs[] = {
@@ -6518,7 +6509,8 @@ JSC_CCALL(os_make_font,
JSC_CCALL(os_make_transform,
transform *t = make_transform();
ret = transform2js(js,t);
t->self = JS_DupValue(js,ret);
// t->self = JS_DupValue(js,ret);
t->self = ret;
)
JSC_CCALL(os_make_sprite, return sprite2js(js,make_sprite()))
@@ -6922,9 +6914,9 @@ static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
s[0] = SDL_Surface2js(ds->js,surf);
JSValue cb = JS_DupValue(ds->js,ds->callback);
JSValue ret = JS_Call(ds->js, cb, JS_UNDEFINED, 1, s);
JS_FreeValue(ds->js,ret);
JS_FreeValue(ds->js,cb);
free(rgb);
uncaught_exception(ds->js,ret);
}
JSC_CCALL(os_make_video,
@@ -7214,8 +7206,10 @@ static ModuleEntry module_registry[] = {
};
JSC_SCALL(os_use,
SDL_SharedObject *ptr = SDL_LoadObject(str);
if (!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))) {
for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) {
if (strcmp(str,module_registry[i].name) == 0) {
JSValue mod = JS_NewObject(js);
@@ -7228,6 +7222,7 @@ JSC_SCALL(os_use,
JSValue (*js_use)(JSContext*);
js_use = (JSValue (*)(JSContext*))SDL_LoadFunction(ptr, "use");
if (!js_use)
ret = JS_ThrowReferenceError(js, "Shared library %s has no use function", str);
else
@@ -7236,6 +7231,20 @@ JSC_SCALL(os_use,
SDL_UnloadObject(ptr);
)
JSC_SSCALL(os_trimchr,
int len = js2number(js,js_getpropertystr(js,argv[0], "length"));
const char *start = str;
while (*start == *str2)
start++;
const char *end = str + len-1;
while(*end == *str2)
end--;
ret = JS_NewStringLen(js, start, end-start+1);
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, turbulence, 4),
MIST_FUNC_DEF(os, model_buffer, 1),
@@ -7305,6 +7314,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, rects_to_sprites,2),
MIST_FUNC_DEF(os, on, 2),
MIST_FUNC_DEF(os, use, 1),
MIST_FUNC_DEF(os, trimchr, 2),
};
JSC_CCALL(qtree_insert,

View File

@@ -96,7 +96,10 @@ void script_stop()
void uncaught_exception(JSContext *js, JSValue v)
{
if (!JS_IsException(v)) return;
if (!JS_IsException(v)) {
JS_FreeValue(js,v);
return;
}
if (!JS_IsUndefined(on_exception)) {
JSValue ex = JS_GetException(js);

View File

@@ -25,7 +25,7 @@ transform *make_transform()
}
void transform_free(JSRuntime *rt, transform *t) {
JS_FreeValueRT(rt,t->self);
// JS_FreeValueRT(rt,t->self);
JS_FreeValueRT(rt,t->change_hook);
JS_FreeValueRT(rt,t->jsparent);
for (int i = 0; i < arrlen(t->jschildren); i++)