Files
cell/scripts/base.js

947 lines
20 KiB
JavaScript

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