133 lines
3.6 KiB
JavaScript
133 lines
3.6 KiB
JavaScript
import { Smc } from "./smc/lib.js"
|
|
|
|
main();
|
|
|
|
async function fetchShader(uri, delegate) {
|
|
const res = await fetch(uri);
|
|
if (res.ok)
|
|
return await res.text();
|
|
this.raiseError(
|
|
SmcErr.FETCH_SHADER,
|
|
`Failed to load shader source ${url}: ${res.status} ${res.json()}`);
|
|
return ""
|
|
}
|
|
|
|
|
|
function animDelta(anim) {
|
|
const timing = anim.effect.getComputedTiming();
|
|
return (timing.delay ?? 0) + (timing.duration ?? 0) + (timing.endDelay ?? 0);
|
|
}
|
|
|
|
function main() {
|
|
const cps = 12; // chars per second
|
|
const promptDelay = 0.5;
|
|
const commandDelay = 5;
|
|
const outputDelay = 5;
|
|
const blinkTime = 600; // x2 then x1000
|
|
|
|
// WARNING: delay does not account for runtime
|
|
// WARNING: it assumes all computations are down instantaneously
|
|
var delay = 0;
|
|
|
|
const boot = document.querySelector("#boot-ppty");
|
|
// WARNING: ensure boot != null
|
|
boot
|
|
.querySelectorAll(".ppty-block")
|
|
.forEach((block, index, blocks) => {
|
|
const prompt = block.querySelector(".ppty-prompt");
|
|
const command = block.querySelector(".ppty-command");
|
|
const output = block.querySelector(".ppty-output");
|
|
|
|
// WARNING: ensure prompt|command|output != null
|
|
const promptAnim = prompt.animate(
|
|
[{ visibility: "visible" }],
|
|
{
|
|
delay: delay + promptDelay * 1000,
|
|
fill: "forwards",
|
|
},
|
|
);
|
|
delay = animDelta(promptAnim);
|
|
|
|
const showCursor = () => { command.style.borderRightColor = cursorColor; return true; };
|
|
const hideCursor = () => { command.style.borderRightColor = "transparent"; return false; };
|
|
const startCursorBlink = () => setInterval(() => {
|
|
cursorVisible = cursorVisible ? hideCursor() : showCursor();
|
|
}, blinkTime);
|
|
|
|
const cursorColor = command.style.borderRightColor;
|
|
var cursorVisible = true;
|
|
var blinkId = null;
|
|
setTimeout(() => {
|
|
command.style.visibility = "visible";
|
|
blinkId = startCursorBlink();
|
|
}, delay);
|
|
|
|
// WARNING: ensure command.textContent != null
|
|
const commandLen = command.textContent.trim().length
|
|
const commandAnim = command.animate(
|
|
[
|
|
{
|
|
width: "0ch",
|
|
visibility: "visible",
|
|
},
|
|
{
|
|
width: `${commandLen}ch`,
|
|
visibility: "visible",
|
|
}
|
|
],
|
|
{
|
|
duration: commandLen / cps * 1000,
|
|
delay: delay + commandDelay * 1000,
|
|
easing: `steps(${commandLen}, end)`,
|
|
fill: "forwards",
|
|
}
|
|
);
|
|
// pause the cursor while typing
|
|
setTimeout(() => {
|
|
clearInterval(blinkId);
|
|
showCursor();
|
|
cursorVisible = true;
|
|
}, delay + commandDelay * 1000);
|
|
delay = animDelta(commandAnim);
|
|
setTimeout(() => {
|
|
blinkId = startCursorBlink();
|
|
}, delay);
|
|
|
|
|
|
setTimeout(() => {
|
|
clearInterval(blinkId);
|
|
hideCursor();
|
|
}, delay + outputDelay * 1000);
|
|
|
|
// unhide output
|
|
output.animate(
|
|
[{ visibility: "visible" }],
|
|
{
|
|
delay: delay + outputDelay * 1000,
|
|
fill: "forwards",
|
|
}
|
|
);
|
|
delay += outputDelay * 1000;
|
|
|
|
// hide the cursor after output displays
|
|
setTimeout(() => command.style.borderRightColor = "transparent", delay);
|
|
});
|
|
|
|
|
|
|
|
const canvas = document.querySelector("#bg-canvas");
|
|
canvas.setAttribute('width', window.innerWidth);
|
|
canvas.setAttribute('height', window.innerHeight);
|
|
|
|
|
|
fetchShader("../shaders/segfault.glsl")
|
|
.then(frag =>
|
|
new Smc(canvas)
|
|
.setMaxFps(30)
|
|
.setProgram(builder =>
|
|
builder
|
|
.addFragmentShader(frag))
|
|
.run()
|
|
);
|
|
}
|
|
|