feat:加上 Vue 学习站与可嵌入机芯
站点按 bloub 三栏做自定义、动画时间线和设置,支持序列导出。 形体只留常见几种并配中文名;动画页右栏拉满时间线旁空位,滚动条隐藏。 机芯补 GROK.create / <grok-bot>,以及暂停冻结。
This commit is contained in:
Executable → Regular
+232
-4
@@ -146,14 +146,21 @@ async function main() {
|
||||
if (ready) break;
|
||||
await sleep(100);
|
||||
}
|
||||
const report = [];
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const [stage, login] = window.__bots || [];
|
||||
return {
|
||||
label: "boot-modes",
|
||||
stage: { state: stage?.state, mode: stage?.mode, moodN: stage?.moodN },
|
||||
login: { state: login?.state, mode: login?.mode, moodN: login?.moodN },
|
||||
};
|
||||
})()`));
|
||||
await click(cdp, "#mode-hold");
|
||||
await click(cdp, "#opt-follow"); // default on → off for stable transforms
|
||||
await sleep(80);
|
||||
|
||||
const report = [];
|
||||
const states = [
|
||||
"playful", "laughing", "sleeping", "idle", "celebrate",
|
||||
"thinking", "writing", "orbit", "humming", "loading",
|
||||
"playful", "laughing", "sleeping", "waking", "idle", "celebrate",
|
||||
"thinking", "writing", "orbit", "humming", "loading", "notifying",
|
||||
];
|
||||
for (const name of states) {
|
||||
await click(cdp, `button[data-state="${name}"]`);
|
||||
@@ -201,6 +208,227 @@ async function main() {
|
||||
await shot(cdp, `${shape}-spin`);
|
||||
}
|
||||
|
||||
// Gr() Lt/Mt: locals default to 1 each frame (not prev)
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.setMode("hold");
|
||||
b.setState("laughing", { resetEyes: false });
|
||||
b.poseOut.lid = 0.7;
|
||||
b.poseOut.eyeBoost = 1.12;
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(80);
|
||||
await click(cdp, 'button[data-state="loading"]');
|
||||
await sleep(80);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "loading-after-laughing",
|
||||
lid: b.poseOut.lid,
|
||||
eyeBoost: b.poseOut.eyeBoost,
|
||||
trick: b.trick?.kind || null,
|
||||
spinTurn: !!b.spinTurn,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await click(cdp, 'button[data-state="excited"]');
|
||||
await sleep(80);
|
||||
await click(cdp, 'button[data-state="waking"]');
|
||||
await sleep(1600);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "[email protected]",
|
||||
dt: (performance.now() - b.stateAt) / 1000,
|
||||
lid: b.poseOut.lid,
|
||||
eyeBoost: b.poseOut.eyeBoost,
|
||||
ty: b.poseOut.ty,
|
||||
squash: b.poseOut.squash,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await click(cdp, 'button[data-state="dragging"]');
|
||||
await sleep(50);
|
||||
const drag = await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
const now = performance.now();
|
||||
const dt = (now - b.stateAt) / 1000;
|
||||
const a = window.GROK_POSE.applyPose("dragging", 0, 0.05, now, b.ctx, { prev: { spin: 0, tx: 0, ty: 0, squash: 1, lid: 1, eyeBoost: 1.06 } });
|
||||
const mid = window.GROK_POSE.applyPose("dragging", 0, 1.2, now, b.ctx, { prev: { spin: 0, tx: 0, ty: 0, squash: 1, lid: 1, eyeBoost: 1 } });
|
||||
const late = window.GROK_POSE.applyPose("dragging", 0, 2.5, now, b.ctx, { prev: { spin: 0, tx: 0, ty: 0, squash: 1, lid: 1, eyeBoost: 1.06 } });
|
||||
return { label: "dragging-Lt", dt, a: a.eyeBoost, mid: mid.eyeBoost, late: late.eyeBoost };
|
||||
})()`);
|
||||
report.push(drag);
|
||||
|
||||
// hold 切态 must not tear rn/ys
|
||||
await click(cdp, 'button[data-state="idle"]');
|
||||
await sleep(60);
|
||||
await click(cdp, "#act-spin");
|
||||
await sleep(40);
|
||||
const beforeHold = await cdp.eval(`({ spinTurn: !!window.__bots[0].spinTurn, trick: window.__bots[0].trick?.kind || null })`);
|
||||
await click(cdp, 'button[data-state="thinking"]');
|
||||
await sleep(40);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "hold-keeps-pn",
|
||||
before: ${JSON.stringify(beforeHold)},
|
||||
state: b.state,
|
||||
spinTurn: !!b.spinTurn,
|
||||
trick: b.trick?.kind || null,
|
||||
};
|
||||
})()`));
|
||||
|
||||
// notifying badge = rest ring 7/8
|
||||
await click(cdp, 'button[data-state="notifying"]');
|
||||
await sleep(400);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
const R = b.geo.Re;
|
||||
const ring = window.GROK_FX.shapeRing(b.geo.shapes[b.shapeName].path, R);
|
||||
const Yl = ring[Math.round(ring.length * 7 / 8) % ring.length];
|
||||
const badge = b.badge;
|
||||
const vis = badge && badge.style.display !== "none";
|
||||
const cx = vis ? +badge.getAttribute("cx") : null;
|
||||
const cy = vis ? +badge.getAttribute("cy") : null;
|
||||
return {
|
||||
label: "notifying-Yl",
|
||||
vis,
|
||||
cx, cy,
|
||||
Yl,
|
||||
dx: vis ? Math.abs(cx - Yl[0]) : null,
|
||||
dy: vis ? Math.abs(cy - Yl[1]) : null,
|
||||
notifyX: b.notify.x,
|
||||
};
|
||||
})()`));
|
||||
|
||||
// excited pn must survive 1200ms onboard cut to idle
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.setMode("hold");
|
||||
b.moodN = 7;
|
||||
b.setState("excited", { resetEyes: false });
|
||||
b._pn(1);
|
||||
b.mode = "onboarding";
|
||||
b.stateAt = performance.now() - 1190;
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(80);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "onboard-excited-to-idle",
|
||||
state: b.state,
|
||||
moodN: b.moodN,
|
||||
spinTurn: !!b.spinTurn,
|
||||
trick: b.trick?.kind || null,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await click(cdp, 'button[data-state="idle"]');
|
||||
await sleep(40);
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.trick = null;
|
||||
b.spinOnce(1);
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(50);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
const rn = b.spinTurn;
|
||||
const turn = b.extras.turn;
|
||||
return {
|
||||
label: "pn-post-spring",
|
||||
hasRn: !!rn,
|
||||
turn,
|
||||
rnX: rn ? rn.x : null,
|
||||
match: rn ? Math.abs(turn - rn.x) < 1e-9 : turn == null,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.setFollowPointer(true);
|
||||
b.pointerRaw = { x: 0, y: 0 };
|
||||
b.pointer.tx = 12;
|
||||
b.pointer.ty = 8;
|
||||
b.pointer.x = 12;
|
||||
b.pointer.y = 8;
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(30);
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.pointerRaw = null;
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(80);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "pointer-leave-decay",
|
||||
tracking: !!(b.gazeTarget || (b.followPointer && b.pointerRaw)),
|
||||
x: b.pointer.x,
|
||||
tx: b.pointer.tx,
|
||||
decaying: b.pointer.tx === 0 && b.pointer.x > 0.05 && b.pointer.x < 12,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await click(cdp, 'button[data-state="writing"]');
|
||||
await sleep(400);
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.fx.ink = [[10, 10], [20, 20]];
|
||||
b.fx.recvTick = 3;
|
||||
b.fx.recvDir = 1.2;
|
||||
b.setState("writing", { resetEyes: false });
|
||||
return true;
|
||||
})()`);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "setState-resets-ink-recv",
|
||||
ink: b.fx.ink.length,
|
||||
recvTick: b.fx.recvTick,
|
||||
recvDir: b.fx.recvDir,
|
||||
};
|
||||
})()`));
|
||||
|
||||
await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
b.setMode("hold");
|
||||
b.trick = null;
|
||||
b.spinTurn = null;
|
||||
b.hopAt = -1;
|
||||
b.particles.clear();
|
||||
b.overlay.x = 0; b.overlay.v = 0; b.overlay.t = 0;
|
||||
b.overlayTurn.x = 0; b.overlayTurn.v = 0; b.overlayTurn.t = 0;
|
||||
b.overlayMix.x = 1; b.overlayMix.v = 0; b.overlayMix.t = 1;
|
||||
b.shapeSpring.x = 1; b.shapeSpring.v = 0; b.shapeSpring.t = 1;
|
||||
b.eyeMorph.x = 1; b.eyeMorph.v = 0; b.eyeMorph.t = 1;
|
||||
b.ovOn = false;
|
||||
b.ovKind = null;
|
||||
b.ovTarget = null;
|
||||
b.ovPrev = null;
|
||||
b.setState("sleeping", { resetEyes: false });
|
||||
b.setPaused(true);
|
||||
return true;
|
||||
})()`);
|
||||
await sleep(200);
|
||||
report.push(await cdp.eval(`(() => {
|
||||
const b = window.__bots[0];
|
||||
return {
|
||||
label: "pause-settle-snap",
|
||||
raf: b._raf,
|
||||
eyeFrom: b.eyeFrom,
|
||||
eyeTo: b.eyeTo,
|
||||
poseOut: b.poseOut,
|
||||
fromPolys: b._fromPolys,
|
||||
};
|
||||
})()`));
|
||||
await cdp.eval(`window.__bots[0].setPaused(false)`);
|
||||
|
||||
await writeFile(join(OUT, "report.json"), JSON.stringify(report, null, 2));
|
||||
console.log(JSON.stringify(report, null, 2));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user