2020-04-07 21:44:46 +02:00
|
|
|
class VTUtils {
|
|
|
|
static random(min, max) {
|
|
|
|
let rand = Math.random();
|
|
|
|
if (typeof min === 'undefined') {
|
|
|
|
return rand;
|
|
|
|
} else if (typeof max === 'undefined') {
|
|
|
|
if (min instanceof Array) {
|
|
|
|
return min[Math.floor(rand * min.length)];
|
|
|
|
} else {
|
|
|
|
return rand * min;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (min > max) {
|
|
|
|
let tmp = min;
|
|
|
|
min = max;
|
|
|
|
max = tmp;
|
|
|
|
}
|
|
|
|
return rand * (max - min) + min;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static randomInt(min, max) {
|
|
|
|
return Math.floor(VTUtils.random(min, max));
|
|
|
|
}
|
|
|
|
|
|
|
|
static normalize(val, max, min) {
|
|
|
|
return (val - min) / (max - min);
|
|
|
|
};
|
|
|
|
|
|
|
|
static distance(x, y, x2, y2) {
|
|
|
|
let a = x - x2;
|
|
|
|
let b = y - y2;
|
|
|
|
|
|
|
|
return Math.sqrt(a * a + b * b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static map(n, start1, stop1, start2, stop2, withinBounds) {
|
|
|
|
let newVal = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
|
|
|
|
if (!withinBounds) {
|
|
|
|
return newVal;
|
|
|
|
}
|
|
|
|
if (start2 < stop2) {
|
|
|
|
return this.constrain(newVal, start2, stop2);
|
|
|
|
} else {
|
|
|
|
return this.constrain(newVal, stop2, start2);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static constrain(n, low, high) {
|
|
|
|
return Math.max(Math.min(n, high), low);
|
|
|
|
}
|
|
|
|
|
|
|
|
static hsvToRgb(h, s, v) {
|
2020-08-05 11:24:59 +02:00
|
|
|
let r, g, b,
|
|
|
|
i = Math.floor(h * 6),
|
|
|
|
f = h * 6 - i,
|
|
|
|
p = v * (1 - s),
|
|
|
|
q = v * (1 - f * s),
|
|
|
|
t = v * (1 - (1 - f) * s);
|
2020-04-07 21:44:46 +02:00
|
|
|
|
|
|
|
switch (i % 6) {
|
|
|
|
case 0:
|
|
|
|
r = v, g = t, b = p;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
r = q, g = v, b = p;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r = p, g = v, b = t;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
r = p, g = q, b = v;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r = t, g = p, b = v;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
r = v, g = p, b = q;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {r: r, g: g, b: b};
|
|
|
|
}
|
|
|
|
|
|
|
|
static peakRGB(peak) {
|
|
|
|
return {
|
|
|
|
r: peak,
|
|
|
|
g: 1 - peak,
|
|
|
|
b: 0
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class VTVector {
|
|
|
|
constructor(x, y, z) {
|
|
|
|
this.x = x || 0;
|
|
|
|
this.y = y || 0;
|
|
|
|
this.z = z || 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//helper
|
|
|
|
static createRandom(x, y, z) {
|
|
|
|
x = x || 1;
|
|
|
|
y = y || 1;
|
|
|
|
z = z || 0;
|
|
|
|
return new VTVector(VTUtils.random(-x, x), VTUtils.random(-y, y), VTUtils.random(-z, z));
|
|
|
|
}
|
|
|
|
|
|
|
|
mult(times) {
|
|
|
|
this.x *= times;
|
|
|
|
this.y *= times;
|
|
|
|
this.z *= times;
|
|
|
|
}
|
|
|
|
|
|
|
|
set(vector) {
|
|
|
|
this.x = vector.x;
|
|
|
|
this.y = vector.y;
|
|
|
|
this.z = vector.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
add(vector) {
|
|
|
|
this.x = this.x + vector.x;
|
|
|
|
this.y = this.y + vector.y;
|
|
|
|
this.z = this.z + vector.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
addXYZ(x, y, z) {
|
|
|
|
this.x += x;
|
|
|
|
this.y += y;
|
|
|
|
this.z += z;
|
|
|
|
}
|
|
|
|
|
|
|
|
setXYZ(x, y, z) {
|
|
|
|
this.x = x || 0;
|
|
|
|
this.y = y || 0;
|
|
|
|
this.z = z || 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
clone() {
|
|
|
|
return new VTVector(this.x, this.y, this.z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function $(sel, s) {
|
2020-08-05 11:24:59 +02:00
|
|
|
s = s || document;
|
|
|
|
return s.querySelector(sel);
|
2020-04-07 21:44:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function $$(sel, s) {
|
|
|
|
s = s || document;
|
|
|
|
return s.querySelectorAll(sel);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
|
|
|
this.addEventListener(type, (event) => {
|
|
|
|
let target = event.target;
|
|
|
|
if (target.matches(aim)) {
|
|
|
|
cb(event, target);
|
|
|
|
} else {
|
|
|
|
let parent = target.closest(aim);
|
|
|
|
if (parent) {
|
|
|
|
cb(event, parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2020-08-01 21:51:54 +02:00
|
|
|
Node.prototype.hasClass = function (className) {
|
2020-08-05 11:24:59 +02:00
|
|
|
let items = className.split(','),
|
|
|
|
has = null;
|
|
|
|
for (let item of items) {
|
|
|
|
if (has === false) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
has = this.classList.contains(item.trim());
|
|
|
|
}
|
|
|
|
return has === true;
|
2020-08-01 21:51:54 +02:00
|
|
|
}
|
|
|
|
Node.prototype.addClass = function (className) {
|
2020-08-05 11:24:59 +02:00
|
|
|
let items = className.split(',');
|
|
|
|
for (let item of items) {
|
|
|
|
this.classList.add(item.trim());
|
|
|
|
}
|
|
|
|
return this;
|
2020-08-01 21:51:54 +02:00
|
|
|
}
|
|
|
|
Node.prototype.removeClass = function (className) {
|
2020-08-05 11:24:59 +02:00
|
|
|
let items = className.split(',');
|
|
|
|
for (let item of items) {
|
|
|
|
this.classList.remove(item.trim());
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
Node.prototype.toggleClass = function (className, force) {
|
|
|
|
let items = className.split(',');
|
|
|
|
for (let item of items) {
|
|
|
|
this.classList.toggle(item.trim(), force);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Node.prototype.switchClass = function (clOne, clTwo, twoOne) {
|
|
|
|
let cl = this.classList;
|
|
|
|
if (twoOne) {
|
|
|
|
cl.remove(clOne);
|
|
|
|
cl.add(clTwo)
|
|
|
|
} else {
|
|
|
|
cl.remove(clTwo)
|
|
|
|
cl.add(clOne)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Node.prototype.toggleCheck = function (className, force) {
|
|
|
|
let cl = this.classList;
|
|
|
|
let items = className.split(',');
|
|
|
|
for (let item of items) {
|
|
|
|
let clOne = item.trim();
|
|
|
|
if (force) {
|
|
|
|
cl.add(clOne);
|
|
|
|
} else {
|
|
|
|
cl.remove(clOne)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
File.prototype.toBase64 = function (cb) {
|
|
|
|
const reader = new FileReader();
|
|
|
|
reader.onloadend = cb;
|
|
|
|
reader.readAsDataURL(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
function b64toBlob(b64Data, type) {
|
|
|
|
const byteCharacters = atob(b64Data);
|
|
|
|
const byteNumbers = new Array(byteCharacters.length);
|
|
|
|
for (let i = 0; i < byteCharacters.length; i++) {
|
|
|
|
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
|
|
}
|
|
|
|
const byteArray = new Uint8Array(byteNumbers);
|
|
|
|
return new Blob([byteArray], {type: type});
|
2020-08-01 21:51:54 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 21:44:46 +02:00
|
|
|
function create(name, content) {
|
|
|
|
let d = document.createElement(name);
|
|
|
|
if (content) {
|
|
|
|
d.innerHTML = content;
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
function append(to, array) {
|
2020-08-05 11:24:59 +02:00
|
|
|
for (let item of array) {
|
|
|
|
to.appendChild(item);
|
2020-04-07 21:44:46 +02:00
|
|
|
}
|
2020-08-05 11:24:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function loadFromJSONToVisualData(useKeys) {
|
|
|
|
fetch('/audio-vis/out/showCase.json').then((res) => {
|
|
|
|
return res.json()
|
|
|
|
}).then(e => {
|
|
|
|
let floatArray;
|
|
|
|
if (useKeys) {
|
|
|
|
let keys = Object.keys(e);
|
|
|
|
floatArray = new Float32Array(keys.length);
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
|
|
floatArray[i] = e[keys[i]];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
floatArray = new Float32Array(e.length);
|
|
|
|
for (let i = 0; i < e.length; i++) {
|
|
|
|
floatArray[i] = e[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visual.visuals[visual.c].data = floatArray;
|
|
|
|
})
|
2020-04-07 21:44:46 +02:00
|
|
|
}
|