2022-11-20 20:03:07 -06:00
|
|
|
/**
|
|
|
|
* Implementation of a simple Oberver Pattern for custom event handling
|
|
|
|
*/
|
|
|
|
function Observer() {
|
2022-11-21 20:19:41 -06:00
|
|
|
this.handlers = new Set();
|
2022-11-20 20:03:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Observer.prototype = {
|
2022-11-21 20:19:41 -06:00
|
|
|
// Adds handler for this message
|
|
|
|
on(callback) {
|
|
|
|
this.handlers.add(callback);
|
|
|
|
return callback;
|
|
|
|
},
|
|
|
|
clear(callback) {
|
|
|
|
return this.handlers.delete(callback);
|
|
|
|
},
|
|
|
|
emit(msg) {
|
|
|
|
this.handlers.forEach(async (handler) => {
|
|
|
|
try {
|
|
|
|
await handler(msg);
|
|
|
|
} catch (e) {
|
|
|
|
console.warn("Observer failed to run handler");
|
2022-11-21 23:16:17 -06:00
|
|
|
console.warn(e);
|
2022-11-21 20:19:41 -06:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates unique id
|
|
|
|
*/
|
|
|
|
const guid = (size = 3) => {
|
|
|
|
const s4 = () => {
|
|
|
|
return Math.floor((1 + Math.random()) * 0x10000)
|
|
|
|
.toString(16)
|
|
|
|
.substring(1);
|
|
|
|
};
|
|
|
|
// returns id of format 'aaaaaaaa'-'aaaa'-'aaaa'-'aaaa'-'aaaaaaaaaaaa'
|
|
|
|
let id = "";
|
|
|
|
for (var i = 0; i < size - 1; i++) id += s4() + "-";
|
|
|
|
id += s4();
|
|
|
|
return id;
|
2022-11-20 20:03:07 -06:00
|
|
|
};
|
2022-11-22 16:24:55 -06:00
|
|
|
|
2022-11-23 22:53:14 -06:00
|
|
|
/**
|
|
|
|
* Default option set
|
|
|
|
*/
|
|
|
|
|
|
|
|
function defaultOpt(options, defaults) {
|
|
|
|
Object.keys(defaults).forEach((key) => {
|
|
|
|
if (options[key] === undefined) options[key] = defaults[key];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-11-22 16:24:55 -06:00
|
|
|
/**
|
|
|
|
* Bounding box Calculation
|
|
|
|
*/
|
|
|
|
function snap(i, scaled = true, gridSize = 64) {
|
|
|
|
// very cheap test proof of concept but it works surprisingly well
|
|
|
|
var scaleOffset = 0;
|
|
|
|
if (scaled) {
|
|
|
|
if (scaleFactor % 2 != 0) {
|
|
|
|
// odd number, snaps to center of cell, oops
|
|
|
|
scaleOffset = gridSize / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var snapOffset = (i % gridSize) - scaleOffset;
|
|
|
|
if (snapOffset == 0) {
|
|
|
|
return snapOffset;
|
|
|
|
}
|
|
|
|
return -snapOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBoundingBox(cx, cy, w, h, gridSnap = null) {
|
|
|
|
const offset = {x: 0, y: 0};
|
|
|
|
const box = {x: 0, y: 0};
|
|
|
|
|
|
|
|
if (gridSnap) {
|
|
|
|
offset.x = snap(cx, true, gridSnap);
|
|
|
|
offset.y = snap(cy, true, gridSnap);
|
|
|
|
}
|
|
|
|
box.x = offset.x + cx;
|
|
|
|
box.y = offset.y + cy;
|
|
|
|
|
|
|
|
return {
|
|
|
|
x: Math.floor(box.x - w / 2),
|
|
|
|
y: Math.floor(box.y - h / 2),
|
|
|
|
w,
|
|
|
|
h,
|
|
|
|
};
|
|
|
|
}
|