pull out many files into separate uses
This commit is contained in:
@@ -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(
|
||||
|
||||
628
scripts/base.js
628
scripts/base.js
@@ -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
43
scripts/convert.js
Normal 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
|
||||
@@ -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
97
scripts/diff.js
Normal 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
|
||||
@@ -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 aren’t in source at all
|
||||
for (let key of Object.keys(target)) {
|
||||
if (!(key in source)) {
|
||||
delete target[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Then shallow-copy the source’s 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")
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
35
scripts/io.js
Normal 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
|
||||
@@ -268,4 +268,3 @@ layout.inputs.mouse.left = function()
|
||||
layout.toString = _ => "layout"
|
||||
|
||||
return layout
|
||||
|
||||
|
||||
10
scripts/lodash.js
Normal file
10
scripts/lodash.js
Normal 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
|
||||
@@ -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
63
scripts/pmath.js
Normal 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
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
38
scripts/stats.js
Normal 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
243
scripts/time.js
Normal 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
|
||||
@@ -1,5 +1,6 @@
|
||||
var ret = {
|
||||
get pos() {
|
||||
if (!this.transform) return
|
||||
return this.transform.pos;
|
||||
},
|
||||
set pos(x) {
|
||||
|
||||
@@ -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
41
scripts/vector.js
Normal 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
51
scripts/yaml.js
Normal 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
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++)
|
||||
|
||||
Reference in New Issue
Block a user