@nadicodeai/ui 8.6.0 → 9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/LICENSES/THINKING-ORBS-MIT.txt +21 -0
- package/NOTICE +7 -10
- package/dist/components/agent-orb-appearance.d.ts +54 -0
- package/dist/components/agent-orb-appearance.d.ts.map +1 -0
- package/dist/components/agent-orb-appearance.js +87 -0
- package/dist/components/agent-orb.d.ts +5 -3
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/internal/agent-orb-motion.d.ts +3 -3
- package/dist/internal/agent-orb-motion.d.ts.map +1 -1
- package/dist/internal/agent-orb-motion.js +1 -0
- package/dist/internal/agent-orb.d.ts +11 -1
- package/dist/internal/agent-orb.d.ts.map +1 -1
- package/dist/internal/agent-orb.js +80 -5
- package/docs/agent-orb.md +47 -14
- package/docs/contract.md +8 -29
- package/docs/migration/9.0.0.md +35 -0
- package/package.json +2 -3
- package/LICENSES/PAPER-SHADERS-APACHE-2.0.txt +0 -186
- package/dist/components/agent-visual.d.ts +0 -17
- package/dist/components/agent-visual.d.ts.map +0 -1
- package/dist/components/agent-visual.js +0 -63
- package/dist/components/forma-appearance.d.ts +0 -13
- package/dist/components/forma-appearance.d.ts.map +0 -1
- package/dist/components/forma-appearance.js +0 -11
- package/dist/components/forma-avatar.d.ts +0 -23
- package/dist/components/forma-avatar.d.ts.map +0 -1
- package/dist/components/forma-avatar.js +0 -95
- package/dist/internal/agent-visual/color.d.ts +0 -4
- package/dist/internal/agent-visual/color.d.ts.map +0 -1
- package/dist/internal/agent-visual/color.js +0 -78
- package/dist/internal/agent-visual/poster.d.ts +0 -6
- package/dist/internal/agent-visual/poster.d.ts.map +0 -1
- package/dist/internal/agent-visual/poster.js +0 -35
- package/dist/internal/agent-visual/recipes.d.ts +0 -15
- package/dist/internal/agent-visual/recipes.d.ts.map +0 -1
- package/dist/internal/agent-visual/recipes.js +0 -72
- package/dist/internal/agent-visual/renderer.d.ts +0 -10
- package/dist/internal/agent-visual/renderer.d.ts.map +0 -1
- package/dist/internal/agent-visual/renderer.js +0 -112
- package/dist/internal/agent-visual/shader.d.ts +0 -2
- package/dist/internal/agent-visual/shader.d.ts.map +0 -1
- package/dist/internal/agent-visual/shader.js +0 -158
- package/dist/internal/forma/frame.d.ts +0 -10
- package/dist/internal/forma/frame.d.ts.map +0 -1
- package/dist/internal/forma/frame.js +0 -211
- package/dist/internal/forma/geometry.d.ts +0 -41
- package/dist/internal/forma/geometry.d.ts.map +0 -1
- package/dist/internal/forma/geometry.js +0 -235
- package/dist/internal/forma/hallmark.d.ts +0 -5
- package/dist/internal/forma/hallmark.d.ts.map +0 -1
- package/dist/internal/forma/hallmark.js +0 -4
- package/dist/internal/forma/model.d.ts +0 -53
- package/dist/internal/forma/model.d.ts.map +0 -1
- package/dist/internal/forma/model.js +0 -70
- package/dist/internal/forma/motion.d.ts +0 -42
- package/dist/internal/forma/motion.d.ts.map +0 -1
- package/dist/internal/forma/motion.js +0 -194
- package/dist/internal/forma/rig.d.ts +0 -10
- package/dist/internal/forma/rig.d.ts.map +0 -1
- package/dist/internal/forma/rig.js +0 -211
- package/dist/internal/forma/still.d.ts +0 -4
- package/dist/internal/forma/still.d.ts.map +0 -1
- package/dist/internal/forma/still.js +0 -8
- package/dist/internal/forma/stored-appearance.d.ts +0 -29
- package/dist/internal/forma/stored-appearance.d.ts.map +0 -1
- package/dist/internal/forma/stored-appearance.js +0 -53
- package/docs/agent-visual.md +0 -114
- package/docs/forma-avatar.md +0 -110
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useId } from "react";
|
|
3
|
-
import { cn } from "../../lib/utils.js";
|
|
4
|
-
import { AGENT_VISUAL_RECIPE_SPECS, identityVariable } from "./recipes.js";
|
|
5
|
-
function Gradient({ id, recipe }) {
|
|
6
|
-
const colors = AGENT_VISUAL_RECIPE_SPECS[recipe].colors;
|
|
7
|
-
return (_jsx("linearGradient", { id: id, x1: "0", x2: "1", y1: "0", y2: "1", children: colors.map((color, index) => (_jsx("stop", { offset: `${(index / Math.max(colors.length - 1, 1)) * 100}%`, stopColor: `var(${identityVariable(color)})` }, color))) }));
|
|
8
|
-
}
|
|
9
|
-
function Surface({ clipId, gradientId, patternId, recipe, }) {
|
|
10
|
-
const { colors, material } = AGENT_VISUAL_RECIPE_SPECS[recipe];
|
|
11
|
-
if (material === "solid") {
|
|
12
|
-
return (_jsx("rect", { width: "160", height: "120", fill: `url(#${gradientId})`, clipPath: `url(#${clipId})` }));
|
|
13
|
-
}
|
|
14
|
-
if (material === "points") {
|
|
15
|
-
return (_jsx("g", { clipPath: `url(#${clipId})`, children: colors.map((color, index) => (_jsx("g", { transform: `translate(${index * 3} ${index * 2})`, children: Array.from({ length: 8 }, (_, row) => Array.from({ length: 11 }, (__, column) => (_jsx("circle", { cx: column * 16, cy: row * 16, fill: `var(${identityVariable(color)})`, r: 1.45 + ((row + column + index) % 3) * 0.35 }, `${row}-${column}`)))) }, color))) }));
|
|
16
|
-
}
|
|
17
|
-
if (material === "wire") {
|
|
18
|
-
return (_jsxs("g", { clipPath: `url(#${clipId})`, fill: "none", children: [Array.from({ length: 14 }, (_, index) => (_jsx("path", { d: `M ${-28 + index * 14} 0 L ${42 + index * 14} 120`, stroke: `var(${identityVariable(colors[index % colors.length])})`, strokeWidth: "1" }, `wire-a-${index}`))), Array.from({ length: 14 }, (_, index) => (_jsx("path", { d: `M ${-28 + index * 14} 120 L ${42 + index * 14} 0`, stroke: `var(${identityVariable(colors[(index + 1) % colors.length])})`, strokeWidth: "1" }, `wire-b-${index}`))), Array.from({ length: 9 }, (_, index) => (_jsx("path", { d: `M 0 ${index * 15} H 160`, stroke: `var(${identityVariable(colors[(index + 2) % colors.length])})`, strokeWidth: "0.8" }, `wire-c-${index}`)))] }));
|
|
19
|
-
}
|
|
20
|
-
return (_jsxs("g", { clipPath: `url(#${clipId})`, children: [_jsx("rect", { width: "160", height: "120", fill: `url(#${patternId})` }), Array.from({ length: 46 }, (_, index) => {
|
|
21
|
-
const color = colors[index % colors.length];
|
|
22
|
-
const x = 20 + ((index * 37) % 125);
|
|
23
|
-
const y = 12 + ((index * 53) % 98);
|
|
24
|
-
const radius = 0.8 + ((index * 7) % 8) * 0.28;
|
|
25
|
-
return (_jsx("circle", { cx: x, cy: y, fill: `var(${identityVariable(color)})`, opacity: 0.48 + (index % 5) * 0.12, r: radius }, `particle-${index}`));
|
|
26
|
-
})] }));
|
|
27
|
-
}
|
|
28
|
-
export function AgentVisualPoster({ className, recipe, }) {
|
|
29
|
-
const id = useId().replaceAll(":", "");
|
|
30
|
-
const clipId = `${id}-clip`;
|
|
31
|
-
const gradientId = `${id}-gradient`;
|
|
32
|
-
const patternId = `${id}-particles`;
|
|
33
|
-
const colors = AGENT_VISUAL_RECIPE_SPECS[recipe].colors;
|
|
34
|
-
return (_jsxs("svg", { "aria-hidden": "true", className: cn("size-full", className), "data-agent-visual-poster": "true", focusable: "false", preserveAspectRatio: "xMidYMid meet", viewBox: "0 0 160 120", children: [_jsxs("defs", { children: [_jsx("clipPath", { id: clipId, children: AGENT_VISUAL_RECIPE_SPECS[recipe].posterForm.map(([cx, cy, radius], index) => (_jsx("circle", { cx: cx, cy: cy, r: radius }, index))) }), _jsx(Gradient, { id: gradientId, recipe: recipe }), _jsxs("pattern", { id: patternId, width: "14", height: "14", patternUnits: "userSpaceOnUse", children: [_jsx("circle", { cx: "2", cy: "3", r: "1.1", fill: `var(${identityVariable(colors[0])})` }), _jsx("circle", { cx: "10", cy: "8", r: "2.1", fill: `var(${identityVariable(colors[1] ?? colors[0])})` }), _jsx("circle", { cx: "5", cy: "12", r: "0.7", fill: `var(${identityVariable(colors[2] ?? colors[0])})` })] })] }), _jsx(Surface, { clipId: clipId, gradientId: gradientId, patternId: patternId, recipe: recipe })] }));
|
|
35
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type AgentVisualRecipe = "general" | "reasoning" | "coordination" | "communication" | "execution";
|
|
2
|
-
export type AgentVisualMaterial = "solid" | "points" | "wire" | "particles";
|
|
3
|
-
type IdentityColor = "arancio" | "cobalto" | "giallo" | "ink" | "rosso" | "verde";
|
|
4
|
-
export type AgentVisualRecipeSpec = {
|
|
5
|
-
colors: readonly IdentityColor[];
|
|
6
|
-
count: number;
|
|
7
|
-
frame: number;
|
|
8
|
-
material: AgentVisualMaterial;
|
|
9
|
-
posterForm: readonly (readonly [number, number, number])[];
|
|
10
|
-
size: number;
|
|
11
|
-
};
|
|
12
|
-
export declare const AGENT_VISUAL_RECIPE_SPECS: Record<AgentVisualRecipe, AgentVisualRecipeSpec>;
|
|
13
|
-
export declare function identityVariable(color: IdentityColor): string;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=recipes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../../../src/internal/agent-visual/recipes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,WAAW,GACX,cAAc,GACd,eAAe,GACf,WAAW,CAAC;AAEhB,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE5E,KAAK,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;AAElF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAoEtF,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,UAEpD"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
export const AGENT_VISUAL_RECIPE_SPECS = {
|
|
2
|
-
general: {
|
|
3
|
-
colors: ["cobalto", "verde", "arancio", "giallo", "rosso"],
|
|
4
|
-
count: 10,
|
|
5
|
-
frame: 0,
|
|
6
|
-
material: "solid",
|
|
7
|
-
posterForm: [
|
|
8
|
-
[45, 64, 29],
|
|
9
|
-
[68, 42, 32],
|
|
10
|
-
[99, 45, 34],
|
|
11
|
-
[116, 71, 27],
|
|
12
|
-
[79, 80, 35],
|
|
13
|
-
],
|
|
14
|
-
size: 0.83,
|
|
15
|
-
},
|
|
16
|
-
reasoning: {
|
|
17
|
-
colors: ["cobalto", "verde", "giallo"],
|
|
18
|
-
count: 10,
|
|
19
|
-
frame: 0,
|
|
20
|
-
material: "points",
|
|
21
|
-
posterForm: [
|
|
22
|
-
[44, 61, 28],
|
|
23
|
-
[69, 39, 31],
|
|
24
|
-
[98, 44, 34],
|
|
25
|
-
[113, 71, 29],
|
|
26
|
-
[76, 80, 34],
|
|
27
|
-
],
|
|
28
|
-
size: 0.83,
|
|
29
|
-
},
|
|
30
|
-
coordination: {
|
|
31
|
-
colors: ["verde", "cobalto", "arancio"],
|
|
32
|
-
count: 8,
|
|
33
|
-
frame: 2_700,
|
|
34
|
-
material: "wire",
|
|
35
|
-
posterForm: [
|
|
36
|
-
[48, 61, 31],
|
|
37
|
-
[77, 40, 33],
|
|
38
|
-
[111, 58, 29],
|
|
39
|
-
[90, 82, 27],
|
|
40
|
-
],
|
|
41
|
-
size: 0.76,
|
|
42
|
-
},
|
|
43
|
-
communication: {
|
|
44
|
-
colors: ["giallo", "arancio", "rosso"],
|
|
45
|
-
count: 12,
|
|
46
|
-
frame: 5_400,
|
|
47
|
-
material: "solid",
|
|
48
|
-
posterForm: [
|
|
49
|
-
[51, 55, 29],
|
|
50
|
-
[79, 43, 35],
|
|
51
|
-
[107, 63, 30],
|
|
52
|
-
[77, 80, 28],
|
|
53
|
-
],
|
|
54
|
-
size: 0.69,
|
|
55
|
-
},
|
|
56
|
-
execution: {
|
|
57
|
-
colors: ["rosso", "arancio", "cobalto"],
|
|
58
|
-
count: 6,
|
|
59
|
-
frame: 8_100,
|
|
60
|
-
material: "particles",
|
|
61
|
-
posterForm: [
|
|
62
|
-
[48, 65, 28],
|
|
63
|
-
[78, 52, 39],
|
|
64
|
-
[109, 64, 32],
|
|
65
|
-
[82, 86, 24],
|
|
66
|
-
],
|
|
67
|
-
size: 0.92,
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
export function identityVariable(color) {
|
|
71
|
-
return `--nc-identity-${color}`;
|
|
72
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type AgentVisualRecipe } from "./recipes.js";
|
|
2
|
-
type AgentVisualRendererProps = {
|
|
3
|
-
host: HTMLElement;
|
|
4
|
-
onReady: () => void;
|
|
5
|
-
onUnavailable: () => void;
|
|
6
|
-
recipe: AgentVisualRecipe;
|
|
7
|
-
};
|
|
8
|
-
export default function AgentVisualRenderer({ host, onReady, onUnavailable, recipe, }: AgentVisualRendererProps): import("react").JSX.Element;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/internal/agent-visual/renderer.tsx"],"names":[],"mappings":"AAYA,OAAO,EAA+C,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAUhG,KAAK,wBAAwB,GAAG;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAC1C,IAAI,EACJ,OAAO,EACP,aAAa,EACb,MAAM,GACP,EAAE,wBAAwB,+BA8G1B"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { defaultObjectSizing, getShaderNoiseTexture, metaballsFragmentShader, ShaderFitOptions, ShaderMount as PaperShaderMount, } from "@paper-design/shaders";
|
|
4
|
-
import { useEffect, useRef } from "react";
|
|
5
|
-
import { resolveIdentityColor } from "./color.js";
|
|
6
|
-
import { AGENT_VISUAL_RECIPE_SPECS, identityVariable } from "./recipes.js";
|
|
7
|
-
import { AGENT_VISUAL_SHADER } from "./shader.js";
|
|
8
|
-
const MATERIAL_INDEX = {
|
|
9
|
-
particles: 3,
|
|
10
|
-
points: 1,
|
|
11
|
-
solid: 0,
|
|
12
|
-
wire: 2,
|
|
13
|
-
};
|
|
14
|
-
export default function AgentVisualRenderer({ host, onReady, onUnavailable, recipe, }) {
|
|
15
|
-
const mountRef = useRef(null);
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const mount = mountRef.current;
|
|
18
|
-
if (!mount)
|
|
19
|
-
return;
|
|
20
|
-
const spec = AGENT_VISUAL_RECIPE_SPECS[recipe];
|
|
21
|
-
const isSolid = spec.material === "solid";
|
|
22
|
-
const colors = spec.colors.map((color) => resolveIdentityColor(host, identityVariable(color)));
|
|
23
|
-
const colorBack = resolveIdentityColor(host, identityVariable("ink"));
|
|
24
|
-
const hasPalette = colors.every((color) => color !== null) && colorBack !== null;
|
|
25
|
-
if (!hasPalette) {
|
|
26
|
-
onUnavailable();
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
let cancelled = false;
|
|
30
|
-
let canvas = null;
|
|
31
|
-
let readyFrame = 0;
|
|
32
|
-
let shaderMount = null;
|
|
33
|
-
const clearMount = () => {
|
|
34
|
-
mount.replaceChildren();
|
|
35
|
-
mount.removeAttribute("data-paper-shader");
|
|
36
|
-
};
|
|
37
|
-
const disposeMount = () => {
|
|
38
|
-
try {
|
|
39
|
-
shaderMount?.dispose();
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
// The deterministic poster remains visible even if vendor cleanup fails.
|
|
43
|
-
}
|
|
44
|
-
shaderMount = null;
|
|
45
|
-
clearMount();
|
|
46
|
-
};
|
|
47
|
-
const handleContextLost = (event) => {
|
|
48
|
-
event.preventDefault();
|
|
49
|
-
cancelled = true;
|
|
50
|
-
cancelAnimationFrame(readyFrame);
|
|
51
|
-
readyFrame = 0;
|
|
52
|
-
canvas?.removeEventListener("webglcontextlost", handleContextLost);
|
|
53
|
-
canvas = null;
|
|
54
|
-
disposeMount();
|
|
55
|
-
onUnavailable();
|
|
56
|
-
};
|
|
57
|
-
const initialize = async () => {
|
|
58
|
-
try {
|
|
59
|
-
const noiseTexture = getShaderNoiseTexture();
|
|
60
|
-
if (noiseTexture && !noiseTexture.complete)
|
|
61
|
-
await noiseTexture.decode();
|
|
62
|
-
if (cancelled)
|
|
63
|
-
return;
|
|
64
|
-
shaderMount = new PaperShaderMount(mount, isSolid ? metaballsFragmentShader : AGENT_VISUAL_SHADER, {
|
|
65
|
-
u_colorBack: colorBack,
|
|
66
|
-
u_colors: colors,
|
|
67
|
-
u_colorsCount: colors.length,
|
|
68
|
-
u_count: spec.count,
|
|
69
|
-
u_fit: ShaderFitOptions[defaultObjectSizing.fit],
|
|
70
|
-
u_noiseTexture: noiseTexture,
|
|
71
|
-
u_offsetX: defaultObjectSizing.offsetX,
|
|
72
|
-
u_offsetY: defaultObjectSizing.offsetY,
|
|
73
|
-
u_originX: defaultObjectSizing.originX,
|
|
74
|
-
u_originY: defaultObjectSizing.originY,
|
|
75
|
-
u_rotation: defaultObjectSizing.rotation,
|
|
76
|
-
u_scale: 1.15,
|
|
77
|
-
u_size: spec.size,
|
|
78
|
-
u_worldHeight: defaultObjectSizing.worldHeight,
|
|
79
|
-
u_worldWidth: defaultObjectSizing.worldWidth,
|
|
80
|
-
...(isSolid
|
|
81
|
-
? {}
|
|
82
|
-
: {
|
|
83
|
-
u_detail: 0.55,
|
|
84
|
-
u_material: MATERIAL_INDEX[spec.material],
|
|
85
|
-
}),
|
|
86
|
-
}, undefined, 0.24, spec.frame, undefined, 720_000);
|
|
87
|
-
canvas = shaderMount.canvasElement;
|
|
88
|
-
canvas.addEventListener("webglcontextlost", handleContextLost);
|
|
89
|
-
readyFrame = requestAnimationFrame(() => {
|
|
90
|
-
readyFrame = 0;
|
|
91
|
-
if (!cancelled)
|
|
92
|
-
onReady();
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
canvas?.removeEventListener("webglcontextlost", handleContextLost);
|
|
97
|
-
canvas = null;
|
|
98
|
-
disposeMount();
|
|
99
|
-
if (!cancelled)
|
|
100
|
-
onUnavailable();
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
void initialize();
|
|
104
|
-
return () => {
|
|
105
|
-
cancelled = true;
|
|
106
|
-
cancelAnimationFrame(readyFrame);
|
|
107
|
-
canvas?.removeEventListener("webglcontextlost", handleContextLost);
|
|
108
|
-
disposeMount();
|
|
109
|
-
};
|
|
110
|
-
}, [host, onReady, onUnavailable, recipe]);
|
|
111
|
-
return _jsx("div", { className: "size-full", ref: mountRef });
|
|
112
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
export declare const AGENT_VISUAL_SHADER = "#version 300 es\nprecision mediump float;\n\nuniform float u_time;\nuniform sampler2D u_noiseTexture;\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[8];\nuniform float u_colorsCount;\nuniform float u_size;\nuniform float u_count;\nuniform float u_material;\nuniform float u_detail;\nuniform vec2 u_resolution;\n\nin vec2 v_objectUV;\nout vec4 fragColor;\n\n#define TWO_PI 6.28318530718\n\nfloat randomR(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).r;\n}\n\nfloat noise(float x) {\n float i = floor(x);\n float f = fract(x);\n float u = f * f * (3.0 - 2.0 * f);\n return mix(randomR(vec2(i, 0.0)), randomR(vec2(i + 1.0, 0.0)), u);\n}\n\nfloat getBallShape(vec2 uv, vec2 c, float p) {\n float s = .5 * length(uv - c);\n s = 1. - clamp(s, 0., 1.);\n return pow(s, p);\n}\n\nfloat hash21(vec2 p) {\n p = fract(p * vec2(123.34, 456.21));\n p += dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nfloat orderedPoints(vec2 surfaceUV, float depth) {\n float density = clamp(min(u_resolution.x, u_resolution.y) / 12.0 * u_detail, 6.0, 34.0);\n vec2 pointUV = fract(surfaceUV * density) - 0.5;\n float radius = mix(0.14, 0.23, depth);\n return 1.0 - smoothstep(radius * 0.7, radius, length(pointUV));\n}\n\nfloat triangularWire(vec2 surfaceUV, float depth) {\n float density = clamp(min(u_resolution.x, u_resolution.y) / 16.0 * u_detail, 5.0, 26.0);\n vec2 grid = surfaceUV * density;\n float horizontal = abs(fract(grid.y) - 0.5);\n float diagonalA = abs(fract(grid.x + grid.y * 0.5) - 0.5);\n float diagonalB = abs(fract(grid.x - grid.y * 0.5) - 0.5);\n float nearestLine = min(horizontal, min(diagonalA, diagonalB));\n float width = mix(0.032, 0.072, depth);\n return 1.0 - smoothstep(width * 0.55, width, nearestLine);\n}\n\nfloat particleLayer(vec2 surfaceUV, float density, float depth, float time, float layerSeed, float threshold) {\n vec2 gridUV = surfaceUV * density + layerSeed;\n vec2 cell = floor(gridUV);\n vec2 local = fract(gridUV) - 0.5;\n float seed = hash21(cell + layerSeed);\n vec2 jitter = vec2(hash21(cell + layerSeed + 3.17), hash21(cell + layerSeed + 8.41)) - 0.5;\n jitter *= 0.72;\n jitter += 0.08 * vec2(sin(time * 0.42 + seed * 18.0 + layerSeed), cos(time * 0.31 + seed * 14.0 - layerSeed));\n float radius = mix(0.055, 0.175, hash21(cell + layerSeed + 14.3)) * mix(0.78, 1.35, depth);\n float particle = 1.0 - smoothstep(radius * 0.68, radius, length(local - jitter));\n float brightness = mix(0.45, 1.0, hash21(cell + layerSeed + 24.7));\n return particle * step(threshold, seed) * brightness;\n}\n\nfloat livingParticles(vec2 surfaceUV, float depth, float time) {\n float density = clamp(min(u_resolution.x, u_resolution.y) / 6.5 * u_detail, 13.0, 68.0);\n float dust = particleLayer(surfaceUV, density, depth, time, 0.0, 0.16);\n float motes = particleLayer(surfaceUV, density * 0.46, depth, time * 0.72, 19.7, 0.62);\n return max(dust * 0.78, motes);\n}\n\nfloat surfacePattern(vec2 surfaceUV, float depth, float material, float time) {\n if (material < 0.5) return 1.0;\n if (material < 1.5) return orderedPoints(surfaceUV, depth);\n if (material < 2.5) return triangularWire(surfaceUV, depth);\n return livingParticles(surfaceUV, depth, time);\n}\n\nvoid main() {\n vec2 shape_uv = v_objectUV + .5;\n const float firstFrameOffset = 2503.4;\n float t = .2 * (u_time + firstFrameOffset);\n vec3 totalColor = vec3(0.);\n float totalShape = 0.;\n float totalOpacity = 0.;\n vec2 weightedCenter = vec2(0.);\n vec2 weightedOrientation = vec2(0.);\n float centerWeight = 0.;\n\n for (int i = 0; i < 20; i++) {\n if (i >= int(ceil(u_count))) break;\n float idxFract = float(i) / 20.0;\n float angle = TWO_PI * idxFract;\n float speed = 1. - .2 * idxFract;\n vec2 pos = vec2(.5) + 1e-4 + .9 * (vec2(noise(angle * 10. + float(i) + t * speed), noise(angle * 20. + float(i) - t * speed)) - .5);\n int safeIndex = i % int(u_colorsCount + 0.5);\n vec4 ballColor = u_colors[safeIndex];\n ballColor.rgb *= ballColor.a;\n float sizeFrac = 1.;\n if (float(i) > floor(u_count - 1.)) sizeFrac *= fract(u_count);\n float shape = getBallShape(shape_uv, pos, 45. - 30. * u_size * sizeFrac);\n shape *= pow(u_size, .2);\n shape = smoothstep(0., 1., shape);\n totalColor += ballColor.rgb * shape;\n totalShape += shape;\n totalOpacity += ballColor.a * shape;\n float centerContribution = shape * shape;\n weightedCenter += pos * centerContribution;\n weightedOrientation += vec2(cos(angle), sin(angle)) * centerContribution;\n centerWeight += centerContribution;\n }\n\n totalColor /= max(totalShape, 1e-4);\n totalOpacity /= max(totalShape, 1e-4);\n float edgeWidth = fwidth(totalShape);\n float finalShape = smoothstep(.4, .4 + edgeWidth, totalShape);\n vec2 fieldCenter = weightedCenter / max(centerWeight, 1e-4);\n vec2 fieldVector = shape_uv - fieldCenter;\n float depth = smoothstep(0.4, 1.45, totalShape);\n float fieldRotation = 0.18 * atan(weightedOrientation.y, weightedOrientation.x);\n float rotationCos = cos(fieldRotation);\n float rotationSin = sin(fieldRotation);\n vec2 surfaceUV = fieldCenter + mat2(rotationCos, rotationSin, -rotationSin, rotationCos) * fieldVector * (1.0 + 0.1 * depth);\n vec2 gradient = vec2(dFdx(totalShape), dFdy(totalShape));\n vec2 gradientDirection = gradient / max(length(gradient), 1e-4);\n surfaceUV += gradientDirection * 0.008 * sin(totalShape * 4.0);\n float feature = surfacePattern(surfaceUV, depth, u_material, t);\n vec3 normal = normalize(vec3(-gradient * 36.0, 1.0));\n vec3 lightDirection = normalize(vec3(-0.45, 0.65, 0.8));\n float surfaceLight = 0.62 + 0.38 * max(dot(normal, lightDirection), 0.0);\n float baseSurface = mix(0.012, 0.06, depth);\n float surface = u_material < 0.5 ? 1.0 : mix(baseSurface, surfaceLight, feature);\n vec3 color = totalColor * finalShape * surface;\n float opacity = totalOpacity * finalShape * surface;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1. - opacity);\n opacity = opacity + u_colorBack.a * (1. - opacity);\n color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);\n fragColor = vec4(color, opacity);\n}\n";
|
|
2
|
-
//# sourceMappingURL=shader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shader.d.ts","sourceRoot":"","sources":["../../../src/internal/agent-visual/shader.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,+oMAuJ/B,CAAC"}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Modified from Paper Shaders 0.0.78 Metaballs (Apache-2.0).
|
|
3
|
-
* The metaball field, motion, colour blending, and edge calculation remain
|
|
4
|
-
* Paper's construction. `surfacePattern` clips the four approved NadicodeAI
|
|
5
|
-
* identity materials inside that generated form. Attribution ships in NOTICE.
|
|
6
|
-
*/
|
|
7
|
-
export const AGENT_VISUAL_SHADER = `#version 300 es
|
|
8
|
-
precision mediump float;
|
|
9
|
-
|
|
10
|
-
uniform float u_time;
|
|
11
|
-
uniform sampler2D u_noiseTexture;
|
|
12
|
-
uniform vec4 u_colorBack;
|
|
13
|
-
uniform vec4 u_colors[8];
|
|
14
|
-
uniform float u_colorsCount;
|
|
15
|
-
uniform float u_size;
|
|
16
|
-
uniform float u_count;
|
|
17
|
-
uniform float u_material;
|
|
18
|
-
uniform float u_detail;
|
|
19
|
-
uniform vec2 u_resolution;
|
|
20
|
-
|
|
21
|
-
in vec2 v_objectUV;
|
|
22
|
-
out vec4 fragColor;
|
|
23
|
-
|
|
24
|
-
#define TWO_PI 6.28318530718
|
|
25
|
-
|
|
26
|
-
float randomR(vec2 p) {
|
|
27
|
-
vec2 uv = floor(p) / 100. + .5;
|
|
28
|
-
return texture(u_noiseTexture, fract(uv)).r;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
float noise(float x) {
|
|
32
|
-
float i = floor(x);
|
|
33
|
-
float f = fract(x);
|
|
34
|
-
float u = f * f * (3.0 - 2.0 * f);
|
|
35
|
-
return mix(randomR(vec2(i, 0.0)), randomR(vec2(i + 1.0, 0.0)), u);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
float getBallShape(vec2 uv, vec2 c, float p) {
|
|
39
|
-
float s = .5 * length(uv - c);
|
|
40
|
-
s = 1. - clamp(s, 0., 1.);
|
|
41
|
-
return pow(s, p);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
float hash21(vec2 p) {
|
|
45
|
-
p = fract(p * vec2(123.34, 456.21));
|
|
46
|
-
p += dot(p, p + 45.32);
|
|
47
|
-
return fract(p.x * p.y);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
float orderedPoints(vec2 surfaceUV, float depth) {
|
|
51
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 12.0 * u_detail, 6.0, 34.0);
|
|
52
|
-
vec2 pointUV = fract(surfaceUV * density) - 0.5;
|
|
53
|
-
float radius = mix(0.14, 0.23, depth);
|
|
54
|
-
return 1.0 - smoothstep(radius * 0.7, radius, length(pointUV));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
float triangularWire(vec2 surfaceUV, float depth) {
|
|
58
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 16.0 * u_detail, 5.0, 26.0);
|
|
59
|
-
vec2 grid = surfaceUV * density;
|
|
60
|
-
float horizontal = abs(fract(grid.y) - 0.5);
|
|
61
|
-
float diagonalA = abs(fract(grid.x + grid.y * 0.5) - 0.5);
|
|
62
|
-
float diagonalB = abs(fract(grid.x - grid.y * 0.5) - 0.5);
|
|
63
|
-
float nearestLine = min(horizontal, min(diagonalA, diagonalB));
|
|
64
|
-
float width = mix(0.032, 0.072, depth);
|
|
65
|
-
return 1.0 - smoothstep(width * 0.55, width, nearestLine);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
float particleLayer(vec2 surfaceUV, float density, float depth, float time, float layerSeed, float threshold) {
|
|
69
|
-
vec2 gridUV = surfaceUV * density + layerSeed;
|
|
70
|
-
vec2 cell = floor(gridUV);
|
|
71
|
-
vec2 local = fract(gridUV) - 0.5;
|
|
72
|
-
float seed = hash21(cell + layerSeed);
|
|
73
|
-
vec2 jitter = vec2(hash21(cell + layerSeed + 3.17), hash21(cell + layerSeed + 8.41)) - 0.5;
|
|
74
|
-
jitter *= 0.72;
|
|
75
|
-
jitter += 0.08 * vec2(sin(time * 0.42 + seed * 18.0 + layerSeed), cos(time * 0.31 + seed * 14.0 - layerSeed));
|
|
76
|
-
float radius = mix(0.055, 0.175, hash21(cell + layerSeed + 14.3)) * mix(0.78, 1.35, depth);
|
|
77
|
-
float particle = 1.0 - smoothstep(radius * 0.68, radius, length(local - jitter));
|
|
78
|
-
float brightness = mix(0.45, 1.0, hash21(cell + layerSeed + 24.7));
|
|
79
|
-
return particle * step(threshold, seed) * brightness;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
float livingParticles(vec2 surfaceUV, float depth, float time) {
|
|
83
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 6.5 * u_detail, 13.0, 68.0);
|
|
84
|
-
float dust = particleLayer(surfaceUV, density, depth, time, 0.0, 0.16);
|
|
85
|
-
float motes = particleLayer(surfaceUV, density * 0.46, depth, time * 0.72, 19.7, 0.62);
|
|
86
|
-
return max(dust * 0.78, motes);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
float surfacePattern(vec2 surfaceUV, float depth, float material, float time) {
|
|
90
|
-
if (material < 0.5) return 1.0;
|
|
91
|
-
if (material < 1.5) return orderedPoints(surfaceUV, depth);
|
|
92
|
-
if (material < 2.5) return triangularWire(surfaceUV, depth);
|
|
93
|
-
return livingParticles(surfaceUV, depth, time);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
void main() {
|
|
97
|
-
vec2 shape_uv = v_objectUV + .5;
|
|
98
|
-
const float firstFrameOffset = 2503.4;
|
|
99
|
-
float t = .2 * (u_time + firstFrameOffset);
|
|
100
|
-
vec3 totalColor = vec3(0.);
|
|
101
|
-
float totalShape = 0.;
|
|
102
|
-
float totalOpacity = 0.;
|
|
103
|
-
vec2 weightedCenter = vec2(0.);
|
|
104
|
-
vec2 weightedOrientation = vec2(0.);
|
|
105
|
-
float centerWeight = 0.;
|
|
106
|
-
|
|
107
|
-
for (int i = 0; i < 20; i++) {
|
|
108
|
-
if (i >= int(ceil(u_count))) break;
|
|
109
|
-
float idxFract = float(i) / 20.0;
|
|
110
|
-
float angle = TWO_PI * idxFract;
|
|
111
|
-
float speed = 1. - .2 * idxFract;
|
|
112
|
-
vec2 pos = vec2(.5) + 1e-4 + .9 * (vec2(noise(angle * 10. + float(i) + t * speed), noise(angle * 20. + float(i) - t * speed)) - .5);
|
|
113
|
-
int safeIndex = i % int(u_colorsCount + 0.5);
|
|
114
|
-
vec4 ballColor = u_colors[safeIndex];
|
|
115
|
-
ballColor.rgb *= ballColor.a;
|
|
116
|
-
float sizeFrac = 1.;
|
|
117
|
-
if (float(i) > floor(u_count - 1.)) sizeFrac *= fract(u_count);
|
|
118
|
-
float shape = getBallShape(shape_uv, pos, 45. - 30. * u_size * sizeFrac);
|
|
119
|
-
shape *= pow(u_size, .2);
|
|
120
|
-
shape = smoothstep(0., 1., shape);
|
|
121
|
-
totalColor += ballColor.rgb * shape;
|
|
122
|
-
totalShape += shape;
|
|
123
|
-
totalOpacity += ballColor.a * shape;
|
|
124
|
-
float centerContribution = shape * shape;
|
|
125
|
-
weightedCenter += pos * centerContribution;
|
|
126
|
-
weightedOrientation += vec2(cos(angle), sin(angle)) * centerContribution;
|
|
127
|
-
centerWeight += centerContribution;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
totalColor /= max(totalShape, 1e-4);
|
|
131
|
-
totalOpacity /= max(totalShape, 1e-4);
|
|
132
|
-
float edgeWidth = fwidth(totalShape);
|
|
133
|
-
float finalShape = smoothstep(.4, .4 + edgeWidth, totalShape);
|
|
134
|
-
vec2 fieldCenter = weightedCenter / max(centerWeight, 1e-4);
|
|
135
|
-
vec2 fieldVector = shape_uv - fieldCenter;
|
|
136
|
-
float depth = smoothstep(0.4, 1.45, totalShape);
|
|
137
|
-
float fieldRotation = 0.18 * atan(weightedOrientation.y, weightedOrientation.x);
|
|
138
|
-
float rotationCos = cos(fieldRotation);
|
|
139
|
-
float rotationSin = sin(fieldRotation);
|
|
140
|
-
vec2 surfaceUV = fieldCenter + mat2(rotationCos, rotationSin, -rotationSin, rotationCos) * fieldVector * (1.0 + 0.1 * depth);
|
|
141
|
-
vec2 gradient = vec2(dFdx(totalShape), dFdy(totalShape));
|
|
142
|
-
vec2 gradientDirection = gradient / max(length(gradient), 1e-4);
|
|
143
|
-
surfaceUV += gradientDirection * 0.008 * sin(totalShape * 4.0);
|
|
144
|
-
float feature = surfacePattern(surfaceUV, depth, u_material, t);
|
|
145
|
-
vec3 normal = normalize(vec3(-gradient * 36.0, 1.0));
|
|
146
|
-
vec3 lightDirection = normalize(vec3(-0.45, 0.65, 0.8));
|
|
147
|
-
float surfaceLight = 0.62 + 0.38 * max(dot(normal, lightDirection), 0.0);
|
|
148
|
-
float baseSurface = mix(0.012, 0.06, depth);
|
|
149
|
-
float surface = u_material < 0.5 ? 1.0 : mix(baseSurface, surfaceLight, feature);
|
|
150
|
-
vec3 color = totalColor * finalShape * surface;
|
|
151
|
-
float opacity = totalOpacity * finalShape * surface;
|
|
152
|
-
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
|
|
153
|
-
color = color + bgColor * (1. - opacity);
|
|
154
|
-
opacity = opacity + u_colorBack.a * (1. - opacity);
|
|
155
|
-
color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);
|
|
156
|
-
fragColor = vec4(color, opacity);
|
|
157
|
-
}
|
|
158
|
-
`;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type FormaMotion, type Pose } from "./motion.js";
|
|
2
|
-
export type PartAttributes = Record<string, string>;
|
|
3
|
-
export type Frame = Record<string, PartAttributes>;
|
|
4
|
-
export declare const SHELL_LAYERS: readonly ["tone", "form", "floor", "key", "rim"];
|
|
5
|
-
export declare const ORBIT_DOTS = 20;
|
|
6
|
-
export declare const RIBBON_BEADS = 8;
|
|
7
|
-
export declare function computeFrame(motion: FormaMotion, pose: Pose, now: number): Frame;
|
|
8
|
-
export declare const RIBBON_TILTS: (48 | -22 | -64)[];
|
|
9
|
-
export declare const ORBIT_TILTS: readonly [-0.36, 0.49];
|
|
10
|
-
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../src/internal/forma/frame.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,UAAU,CAAC;AAE3E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAanD,eAAO,MAAM,YAAY,kDAAmD,CAAC;AAY7E,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAyGhF;AAOD,eAAO,MAAM,YAAY,oBAAuC,CAAC;AACjE,eAAO,MAAM,WAAW,wBAAyB,CAAC"}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { TAU, bodies, closedPath, eyeProfiles, f3, project, shellPath, smooth, stripePath, superellipse, visorPoints, } from "./geometry.js";
|
|
2
|
-
import { HALLMARK_LONGITUDE, HALLMARK_SIZE, ITALY_BOX } from "./hallmark.js";
|
|
3
|
-
import { formDetails } from "./model.js";
|
|
4
|
-
import { easeInOut, easeOut } from "./motion.js";
|
|
5
|
-
const eyeShapes = new Map();
|
|
6
|
-
function eyeShape(form) {
|
|
7
|
-
let shape = eyeShapes.get(form);
|
|
8
|
-
if (!shape) {
|
|
9
|
-
const profile = eyeProfiles[form];
|
|
10
|
-
shape = closedPath(superellipse(profile.width, profile.height, profile.power, 32));
|
|
11
|
-
eyeShapes.set(form, shape);
|
|
12
|
-
}
|
|
13
|
-
return shape;
|
|
14
|
-
}
|
|
15
|
-
export const SHELL_LAYERS = ["tone", "form", "floor", "key", "rim"];
|
|
16
|
-
const VISOR_LAYERS = [
|
|
17
|
-
"visor",
|
|
18
|
-
"visorClip",
|
|
19
|
-
"bezel",
|
|
20
|
-
"bezelLight",
|
|
21
|
-
"visorShade",
|
|
22
|
-
"glass",
|
|
23
|
-
"streak",
|
|
24
|
-
"sole",
|
|
25
|
-
"visorEdge",
|
|
26
|
-
];
|
|
27
|
-
export const ORBIT_DOTS = 20;
|
|
28
|
-
export const RIBBON_BEADS = 8;
|
|
29
|
-
export function computeFrame(motion, pose, now) {
|
|
30
|
-
const body = bodies[motion.form];
|
|
31
|
-
const nadia = motion.form === "nadia";
|
|
32
|
-
const t = (now - motion.entered) / 1000;
|
|
33
|
-
const morph = pose.morph < 0.00005 ? 0 : pose.morph > 0.99995 ? 1 : pose.morph;
|
|
34
|
-
const { yaw, pitch } = pose;
|
|
35
|
-
const frame = {};
|
|
36
|
-
const shell = shellPath(body, morph);
|
|
37
|
-
frame.shell = { d: shell };
|
|
38
|
-
frame.shellClip = { d: shell };
|
|
39
|
-
for (const layer of SHELL_LAYERS)
|
|
40
|
-
frame[layer] = { d: shell };
|
|
41
|
-
frame.tube = { d: shell, opacity: f3(morph) };
|
|
42
|
-
frame.hot = { opacity: f3(1 - morph * 0.6) };
|
|
43
|
-
frame.fade = { d: shell, opacity: f3(nadia ? 0 : morph * 0.28) };
|
|
44
|
-
frame.object = {
|
|
45
|
-
transform: `translate(0 ${f3(pose.lift)}) rotate(${f3((pose.roll * 180) / Math.PI)}) scale(${f3(1 / Math.sqrt(pose.stretch))} ${f3(pose.stretch)})`,
|
|
46
|
-
};
|
|
47
|
-
frame.blockedBar = { opacity: f3(morph > 0.42 ? smooth((morph - 0.42) / 0.4) : 0) };
|
|
48
|
-
if (nadia) {
|
|
49
|
-
frame.bandW = { d: stripePath(body, yaw, -0.36, 0.36) };
|
|
50
|
-
frame.bandR = { d: stripePath(body, yaw, 0.36, Math.PI) };
|
|
51
|
-
frame.bandSand = { d: frame.bandW.d, opacity: f3(morph * 0.28) };
|
|
52
|
-
}
|
|
53
|
-
const faceOpacity = 1 - smooth(morph / 0.52);
|
|
54
|
-
frame.face = { opacity: f3(faceOpacity), display: faceOpacity > 0.001 ? "" : "none" };
|
|
55
|
-
const visor = closedPath(visorPoints.map(([x, y]) => {
|
|
56
|
-
const p = project(body, x, y, yaw, pitch);
|
|
57
|
-
return [p.x, p.y];
|
|
58
|
-
}));
|
|
59
|
-
for (const layer of VISOR_LAYERS)
|
|
60
|
-
frame[layer] = { d: visor };
|
|
61
|
-
if (nadia) {
|
|
62
|
-
const hm = project(body, Math.sin(HALLMARK_LONGITUDE), -0.12, yaw, pitch);
|
|
63
|
-
const scale = HALLMARK_SIZE / ITALY_BOX;
|
|
64
|
-
frame.hallmark = {
|
|
65
|
-
display: hm.front && faceOpacity > 0.001 ? "" : "none",
|
|
66
|
-
transform: `translate(${f3(hm.x)} ${f3(hm.y)}) scale(${f3(hm.sx * scale)} ${f3(-hm.sy * scale)}) translate(${-ITALY_BOX / 2} ${-ITALY_BOX / 2})`,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const happiness = smooth(pose.done);
|
|
70
|
-
const pauseAmount = smooth((pose.waiting - 0.15) / 0.85);
|
|
71
|
-
const blinkPhase = ((t % 5.2) - 3.4) / 0.16;
|
|
72
|
-
const blink = !motion.still &&
|
|
73
|
-
motion.state !== "blocked" &&
|
|
74
|
-
motion.state !== "waiting" &&
|
|
75
|
-
blinkPhase > 0 &&
|
|
76
|
-
blinkPhase < 1
|
|
77
|
-
? 1 - Math.sin(blinkPhase * Math.PI)
|
|
78
|
-
: 1;
|
|
79
|
-
const eyeOpen = Math.max(0.055, pose.open * blink);
|
|
80
|
-
const profile = eyeProfiles[motion.form];
|
|
81
|
-
const glow = formDetails[motion.form].eyes === "ink" ? 0 : profile.signature ? 0.95 : 0.65;
|
|
82
|
-
const shape = eyeShape(motion.form);
|
|
83
|
-
for (const [name, side] of [
|
|
84
|
-
["L", -1],
|
|
85
|
-
["R", 1],
|
|
86
|
-
]) {
|
|
87
|
-
const x = side * ((1 - pauseAmount) * profile.spacing + pauseAmount * 0.125) + pose.gazeX;
|
|
88
|
-
const y = profile.y + pose.gazeY;
|
|
89
|
-
const p = project(body, x, y, yaw, pitch);
|
|
90
|
-
frame[`eye${name}`] = {
|
|
91
|
-
display: p.front ? "" : "none",
|
|
92
|
-
transform: `translate(${f3(p.x)} ${f3(p.y)}) scale(${f3(p.sx)} ${f3(p.sy)})`,
|
|
93
|
-
};
|
|
94
|
-
frame[`light${name}`] = {
|
|
95
|
-
d: shape,
|
|
96
|
-
transform: `scale(1 ${f3(eyeOpen)})`,
|
|
97
|
-
opacity: f3((1 - happiness) * (1 - pauseAmount)),
|
|
98
|
-
};
|
|
99
|
-
frame[`glint${name}`] = frame[`light${name}`];
|
|
100
|
-
frame[`halo${name}`] = {
|
|
101
|
-
rx: f3(profile.width * 2.8),
|
|
102
|
-
ry: f3(profile.height * (1.1 + 0.9 * eyeOpen)),
|
|
103
|
-
opacity: f3(glow * (1 - pauseAmount) * (1 - happiness)),
|
|
104
|
-
};
|
|
105
|
-
if (profile.signature)
|
|
106
|
-
frame[`flick${name}`] = {
|
|
107
|
-
transform: `scale(${side} ${f3(eyeOpen)})`,
|
|
108
|
-
opacity: f3((1 - happiness) * (1 - pauseAmount)),
|
|
109
|
-
};
|
|
110
|
-
frame[`happy${name}`] = {
|
|
111
|
-
opacity: f3(happiness * (1 - pauseAmount)),
|
|
112
|
-
transform: `rotate(${f3(side * pose.done * 1.7)})`,
|
|
113
|
-
};
|
|
114
|
-
frame[`pause${name}`] = { opacity: f3(pauseAmount) };
|
|
115
|
-
frame[`pauseHalo${name}`] = { opacity: f3(pauseAmount * 0.7) };
|
|
116
|
-
}
|
|
117
|
-
for (let i = 0; i < 3; i++) {
|
|
118
|
-
const pulse = motion.still ? 0.6 : 0.18 + (0.82 * (Math.sin(t * 5.6 - i * 1.25) + 1)) / 2;
|
|
119
|
-
const p = project(body, (i - 1) * 0.086, -0.266, yaw, pitch);
|
|
120
|
-
frame[`tick${i}`] = {
|
|
121
|
-
transform: `translate(${f3(p.x - 0.0235 * p.sx)} ${f3(p.y - 0.012)}) scale(${f3(p.sx)} 1)`,
|
|
122
|
-
opacity: f3(pose.working * pulse * 0.75 + pose.thinking * pulse * 0.35),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
writeEffects(frame, motion, pose, now);
|
|
126
|
-
return frame;
|
|
127
|
-
}
|
|
128
|
-
const RIBBONS = [
|
|
129
|
-
{ tilt: -22, aspect: 0.62, radius: 1.2, span: 2.85, phase: 0.2, direction: 1 },
|
|
130
|
-
{ tilt: 48, aspect: 0.5, radius: 1.19, span: 2.5, phase: 2.1, direction: -1 },
|
|
131
|
-
{ tilt: -64, aspect: 0.72, radius: 1.24, span: 2.3, phase: 4.0, direction: 1 },
|
|
132
|
-
];
|
|
133
|
-
export const RIBBON_TILTS = RIBBONS.map((ribbon) => ribbon.tilt);
|
|
134
|
-
export const ORBIT_TILTS = [-0.36, 0.49];
|
|
135
|
-
function writeEffects(frame, motion, pose, now) {
|
|
136
|
-
const morph = pose.morph < 0.00005 ? 0 : pose.morph > 0.99995 ? 1 : pose.morph;
|
|
137
|
-
const clock = motion.still ? 0.6 : (now - motion.started) / 1000;
|
|
138
|
-
const celebrationAge = (now - motion.celebratedAt) / 1000;
|
|
139
|
-
const celebrating = !motion.still && celebrationAge > 0.14 && celebrationAge < 2.4;
|
|
140
|
-
const workAmount = pose.working * (1 - morph);
|
|
141
|
-
const thoughtAmount = pose.thinking * (1 - morph);
|
|
142
|
-
const ribbonOpacity = celebrating ? pose.done * (1 - morph) : 0;
|
|
143
|
-
const active = workAmount > 0.003 || thoughtAmount > 0.003 || ribbonOpacity > 0.003;
|
|
144
|
-
frame.effectsBack = { display: active ? "" : "none" };
|
|
145
|
-
frame.effectsFront = {
|
|
146
|
-
display: active ? "" : "none",
|
|
147
|
-
transform: `translate(0 ${f3(pose.lift * 0.45)})`,
|
|
148
|
-
};
|
|
149
|
-
ORBIT_TILTS.forEach((tilt, index) => {
|
|
150
|
-
for (let i = 0; i < ORBIT_DOTS; i++) {
|
|
151
|
-
const tail = i % 10;
|
|
152
|
-
const offset = i < 10 ? 0 : Math.PI;
|
|
153
|
-
const a = clock * (index === 0 ? 2.8 : -2.2) + index * 2.2 + offset - tail * 0.065;
|
|
154
|
-
const x = 1.2 * Math.cos(a);
|
|
155
|
-
const y = 0.49 * Math.sin(a);
|
|
156
|
-
const front = Math.sin(a) > 0;
|
|
157
|
-
const dot = {
|
|
158
|
-
cx: f3(x * Math.cos(tilt) - y * Math.sin(tilt)),
|
|
159
|
-
cy: f3(x * Math.sin(tilt) + y * Math.cos(tilt) - 0.04),
|
|
160
|
-
opacity: f3(workAmount * (tail === 0 ? 0.94 : 0.47 * (1 - tail / 10))),
|
|
161
|
-
};
|
|
162
|
-
frame[`orbit${index}Back${i}`] = { ...dot, display: front ? "none" : "" };
|
|
163
|
-
frame[`orbit${index}Front${i}`] = { ...dot, display: front ? "" : "none" };
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
for (let i = 0; i < 3; i++) {
|
|
167
|
-
const pulse = motion.still ? 0.72 : 0.23 + (0.77 * (Math.sin(clock * 2.4 - i * 0.9) + 1)) / 2;
|
|
168
|
-
frame[`thought${i}`] = {
|
|
169
|
-
transform: `translate(${f3(0.68 + i * 0.23)} ${f3(0.79 + i * 0.13 + (motion.still ? 0 : 0.025 * Math.sin(clock * 2.4 - i * 0.9)))})`,
|
|
170
|
-
opacity: f3(thoughtAmount * pulse),
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
RIBBONS.forEach((ribbon, index) => {
|
|
174
|
-
const name = `ribbon${index}`;
|
|
175
|
-
if (ribbonOpacity <= 0.003) {
|
|
176
|
-
frame[`${name}Plane`] = { opacity: "0", display: "none" };
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
const age = celebrationAge - 0.14 - index * 0.06;
|
|
180
|
-
const reveal = easeOut(age / 0.46);
|
|
181
|
-
const dissolve = easeInOut((age - 1.1) / 0.95);
|
|
182
|
-
const fade = easeOut(age / 0.2) * (1 - easeOut((age - 1.76) / 0.44)) * ribbonOpacity;
|
|
183
|
-
const a0 = dissolve * ribbon.span;
|
|
184
|
-
const a1 = Math.max(a0, reveal * ribbon.span);
|
|
185
|
-
const points = [];
|
|
186
|
-
for (let i = 0; i <= 24; i++) {
|
|
187
|
-
const a = a0 + ((a1 - a0) * i) / 24;
|
|
188
|
-
points.push(`${i ? "L" : "M"}${f3(Math.cos(a) * ribbon.radius)} ${f3(Math.sin(a) * ribbon.radius * ribbon.aspect)}`);
|
|
189
|
-
}
|
|
190
|
-
frame[`${name}Plane`] = { opacity: f3(fade * 0.88), display: "" };
|
|
191
|
-
frame[`${name}Sweep`] = {
|
|
192
|
-
transform: `rotate(${f3(((ribbon.phase + ribbon.direction * TAU * easeInOut(Math.min(1, Math.max(0, age / 2.12)))) * 180) / Math.PI)})`,
|
|
193
|
-
};
|
|
194
|
-
frame[`${name}Arc`] = { d: a1 > a0 + 0.01 ? points.join("") : "M0 0" };
|
|
195
|
-
frame[`${name}Head`] = {
|
|
196
|
-
cx: f3(Math.cos(a1) * ribbon.radius),
|
|
197
|
-
cy: f3(Math.sin(a1) * ribbon.radius * ribbon.aspect),
|
|
198
|
-
};
|
|
199
|
-
for (let i = 0; i < RIBBON_BEADS; i++) {
|
|
200
|
-
const u = i / 7;
|
|
201
|
-
const angle = a0 - u * (0.95 + 0.48 * dissolve);
|
|
202
|
-
const radial = ribbon.radius + ((i % 3) - 1) * (0.014 + 0.034 * u) + dissolve * u * 0.06;
|
|
203
|
-
frame[`${name}Bead${i}`] = {
|
|
204
|
-
cx: f3(Math.cos(angle) * radial),
|
|
205
|
-
cy: f3(Math.sin(angle) * radial * ribbon.aspect),
|
|
206
|
-
r: f3(0.006 + 0.012 * (1 - u)),
|
|
207
|
-
opacity: f3(dissolve > 0.01 ? 0.78 : 0),
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|