@tomorrowevening/hermes
Version:
An extendable set of Web Tools controlled via a separate window for non-intereference with content.
284 lines (283 loc) • 9.2 kB
JavaScript
import { getProject as _ } from "@tomorrowevening/theatre-core";
import $ from "./BaseRemote.js";
import { noop as g } from "../types.js";
function w(a) {
return a != null && a.r !== void 0 && a.g !== void 0 && a.b !== void 0;
}
function k(a, e, t, i, h) {
const s = 1 - a;
return s * s * s * e + 3 * s * s * a * t + 3 * s * a * a * i + a * a * a * h;
}
function P(a, e, t) {
if (a.type !== "bezier" || a.handles.length !== 4)
throw new Error("Invalid keyframe data for Bézier interpolation.");
const [i, h] = a.handles, s = (t - a.position) / (e.position - a.position);
return k(
s,
a.value,
a.value + i,
e.value + h,
e.value
);
}
class B extends $ {
project;
sheets = /* @__PURE__ */ new Map();
sheetObjects = /* @__PURE__ */ new Map();
sheetObjectCBs = /* @__PURE__ */ new Map();
sheetObjectUnsubscribe = /* @__PURE__ */ new Map();
activeSheet;
studio = void 0;
constructor(e = !1, t = !1) {
super("RemoteTheatre", e, t);
}
dispose() {
this.project = void 0, this.sheets = /* @__PURE__ */ new Map(), this.sheetObjects = /* @__PURE__ */ new Map(), this.sheetObjectCBs = /* @__PURE__ */ new Map(), this.sheetObjectUnsubscribe = /* @__PURE__ */ new Map();
}
loadProject(e, t) {
return this.project = _(e, { state: t }), new Promise((i, h) => {
this.project?.ready.then(() => {
if (t) {
const s = t.sheetsById;
for (const n in s) this.sheet(n);
}
i();
}).catch(() => h());
});
}
getSheetInstance(e, t) {
return t !== void 0 ? `${e}-${t}` : e;
}
sheet(e, t) {
if (this.project === void 0) {
console.error("Theatre Project hasn't been created yet.");
return;
}
const i = this.getSheetInstance(e, t);
let h = this.sheets.get(i);
return h !== void 0 || (h = this.project?.sheet(e, t), this.sheets.set(i, h), this.send({
event: "createSheet",
target: "editor",
data: {
sheet: e,
instance: t
}
})), h;
}
playSheet(e, t, i) {
return new Promise((h) => {
this.sheet(e, i)?.sequence.play(t).then((s) => h(s)), this.send({
event: "playSheet",
target: "editor",
data: {
sheet: e,
instance: i,
value: t
}
});
});
}
pauseSheet(e, t) {
this.sheet(e, t)?.sequence.pause(), this.send({
event: "pauseSheet",
target: "editor",
data: {
sheet: e,
instance: t
}
});
}
clearSheetObjects(e) {
this.sheetObjects.forEach((t, i) => {
i.search(`${e}_`) > -1 && this.unsubscribe(t);
});
}
sheetObject(e, t, i, h, s) {
if (this.project === void 0) {
console.error("Theatre Project hasn't been created yet.");
return;
}
const n = this.sheet(e, s);
if (n === void 0) return;
const u = `${this.getSheetInstance(e, s)}_${t}`;
let b = this.sheetObjects.get(u), j = i;
b !== void 0 && (j = { ...i, ...b.value }), b = n.object(t, j, { reconfigure: !0 }), this.sheetObjects.set(u, b), this.sheetObjectCBs.set(u, h !== void 0 ? h : g);
function v(d, p, o) {
if (typeof o == "object")
if (w(o))
d[p] = {
r: o.r,
g: o.g,
b: o.b,
a: o.a
};
else
for (const r in o) {
const l = o[r];
typeof l == "object" && v(o, r, l);
}
}
const c = b.onValuesChange((d) => {
const p = this.sheetObjectCBs.get(u);
if (this.editor) {
for (const o in d) {
const r = d[o];
typeof r == "object" && v(d, o, r);
}
this.send({
event: "updateSheetObject",
target: "app",
data: {
sheet: e,
sheetObject: u,
values: d
}
}), p && p(d);
} else
p && p(d);
});
return this.sheetObjectUnsubscribe.set(u, c), this.send({
event: "createSheetObject",
target: "editor",
data: {
sheet: e,
instance: s,
key: t,
props: JSON.stringify(i)
}
}), b;
}
getSheetObjectKeyframes(e, t, i) {
const h = this.sheet(e);
if (h === void 0) return [];
const s = `${e}_${t}`, n = this.sheetObjects.get(s);
return n === void 0 ? [] : h.sequence.__experimental_getKeyframes(n.props[i]);
}
getSheetObjectVectors(e, t) {
const i = this.sheet(e);
if (i === void 0) return [];
const h = `${e}_${t}`, s = this.sheetObjects.get(h);
if (s === void 0) return [];
const n = [], f = i.sequence.__experimental_getKeyframes(s.props.x), u = i.sequence.__experimental_getKeyframes(s.props.y), b = i.sequence.__experimental_getKeyframes(s.props.z), j = /* @__PURE__ */ new Set();
return f.forEach((c) => j.add(c.position)), u.forEach((c) => j.add(c.position)), b.forEach((c) => j.add(c.position)), Array.from(j).sort((c, d) => c - d).forEach((c) => {
const d = (p, o) => {
const r = p.find((S, y) => S.position <= o && (p[y + 1]?.position || 1 / 0) > o), l = p.find((S) => S.position > o);
if (!r) return l?.value || 0;
if (!l || r.position === o) return r.value;
if (r.type === "bezier")
return P(r, l, o);
const O = (o - r.position) / (l.position - r.position);
return r.value + O * (l.value - r.value);
};
n.push({
position: c,
x: d(f, c),
y: d(u, c),
z: d(b, c)
});
}), n;
}
update(e) {
}
unsubscribe(e) {
if (this.project === void 0) {
console.error("Theatre Project hasn't been created yet.");
return;
}
const t = e.address.sheetId, i = e.address.objectKey;
this.sheets.get(t)?.detachObject(i);
const s = `${t}_${i}`, n = this.sheetObjectUnsubscribe.get(s);
n !== void 0 && (this.sheetObjects.delete(s), this.sheetObjectCBs.delete(s), this.sheetObjectUnsubscribe.delete(s), n());
}
handleApp(e) {
let t;
switch (e.event) {
case "setSheet":
t = this.sheets.get(e.data.sheet), t !== void 0 ? this.studio?.setSelection([t]) : console.log(`Hermes - Can't set Sheet: ${e.data.sheet}`, t);
break;
case "setSheetObject":
t = this.sheetObjects.get(`${e.data.sheet}_${e.data.key}`), t !== void 0 ? this.studio?.setSelection([t]) : console.log(`Hermes - Can't set Sheet Object: ${e.data.sheet}, ${e.data.key}: ${e.data.sheet}_${e.data.key}`, t);
break;
case "updateSheetObject":
t = this.sheets.get(e.data.sheet), t !== void 0 && t.sequence.pause(), t = this.sheetObjectCBs.get(e.data.sheetObject), t !== void 0 ? t(e.data.values) : console.log(`Hermes - Can't update Sheet Object: ${e.data.sheetObject}, ${e.data.sheet}`, t);
break;
case "updateTimeline":
t = this.sheets.get(e.data.sheet), t !== void 0 ? t.sequence.position = e.data.position : console.log(`Hermes - Can't update sheet position: ${e.data.sheet}, ${e.data.position}`);
break;
}
}
handleEditor(e) {
switch (e.event) {
case "createSheet":
this.sheet(e.data.sheet, e.data.instance);
break;
case "playSheet":
this.sheet(e.data.sheet, e.data.instance)?.sequence.play(e.data.value);
break;
case "pauseSheet":
this.sheet(e.data.sheet, e.data.instance)?.sequence.pause();
break;
case "createSheetObject":
this.sheetObject(
e.data.sheet,
e.data.key,
JSON.parse(e.data.props),
void 0,
e.data.instanceId
);
break;
}
}
getSheetNames() {
const e = [];
return this.sheets.forEach((t, i) => {
e.push(i);
}), e;
}
handleEditorApp() {
if (this.editor) {
this.studio?.ui.restore(), this.studio?.onSelectionChange((h) => {
h.length < 1 || h.forEach((s) => {
let n = s.address.sheetId, f = "setSheet", u = {};
switch (s.type) {
case "Theatre_Sheet_PublicAPI":
f = "setSheet", u = {
sheet: s.address.sheetId
}, this.activeSheet = this.sheets.get(s.address.sheetId);
break;
case "Theatre_SheetObject_PublicAPI":
f = "setSheetObject", n += `_${s.address.objectKey}`, u = {
id: n,
sheet: s.address.sheetId,
key: s.address.objectKey
}, this.activeSheet = this.sheets.get(s.address.sheetId);
break;
}
this.send({ event: f, target: "app", data: u });
});
});
let e = -1;
const t = () => {
if (this.activeSheet !== void 0 && e !== this.activeSheet.sequence.position) {
e = this.activeSheet.sequence.position;
const h = this.activeSheet;
this.send({
event: "updateTimeline",
target: "app",
data: {
position: e,
sheet: h.address.sheetId
}
});
}
}, i = () => {
t(), requestAnimationFrame(i);
};
t(), i();
} else
this.studio?.ui.hide();
}
}
export {
B as default
};