claude-live 2.0.8 → 3.0.0

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/README.md CHANGED
@@ -1,85 +1,75 @@
1
1
  # claude-live
2
2
 
3
- Real-time visualization of [Claude Code](https://docs.anthropic.com/en/docs/claude-code) activity as an orbital solar system.
3
+ **[Try the live demo](https://marisancans.github.io/claude-live/)** no install needed
4
4
 
5
5
  ![claude-live demo](claude-live-demo.gif)
6
6
 
7
- **[Try the demo](https://marisancans.github.io/claude-live/)** (no install needed)
7
+ Real-time visualization of Claude Code activity as a 3D orbital system.
8
8
 
9
9
  ## Install
10
10
 
11
- ### Via Claude plugin marketplace (recommended)
11
+ ### Claude Code Marketplace (recommended)
12
12
 
13
- ```bash
14
- claude plugin marketplace add marisancans/claude-live
13
+ Search for **claude-live** in the Claude Code marketplace, or run inside Claude Code:
14
+
15
+ ```
16
+ /plugins install marisancans/claude-live
15
17
  ```
16
18
 
17
- Hooks are configured automatically. Events stream in the background as you work.
19
+ This gives you the `/claude-live:server` slash command to manage the server from within Claude Code.
18
20
 
19
- ### Via npm (manual setup)
21
+ ### npm (standalone)
20
22
 
21
23
  ```bash
22
24
  npm install -g claude-live
23
25
  ```
24
26
 
25
- Then add hooks to your `~/.claude/settings.json`:
27
+ ## Use
26
28
 
27
- ```json
28
- {
29
- "hooks": {
30
- "PreToolUse": [{ "hooks": [{ "type": "command", "command": "node $(npm root -g)/claude-live/bin/hook.js", "async": true }] }],
31
- "PostToolUse": [{ "hooks": [{ "type": "command", "command": "node $(npm root -g)/claude-live/bin/hook.js", "async": true }] }]
32
- }
33
- }
29
+ ```bash
30
+ claude-live # Start server (foreground)
31
+ claude-live start # Start server in background
34
32
  ```
35
33
 
36
- Run `npm root -g` to find your global node_modules path if the above doesn't work on your shell.
34
+ Open http://localhost:43451 in your browser. Sessions appear automatically as you use Claude Code.
37
35
 
38
- ## Use
39
-
40
- Once installed, use the `/claude-live:server` slash command in Claude Code:
36
+ With the plugin installed, manage the server from inside Claude Code:
41
37
 
42
38
  ```
43
39
  /claude-live:server # Check status, auto-start if needed
44
40
  /claude-live:server stop # Stop the server
45
41
  /claude-live:server restart # Restart the server
46
42
  /claude-live:server logs # Show last 30 log lines
47
- /claude-live:server config # Show current endpoint URL
48
- /claude-live:server config http://192.168.1.50:43451 # Set remote endpoint
49
- /claude-live:server config reset # Reset to localhost default
50
43
  ```
51
44
 
52
- Then open http://localhost:43451 in your browser.
53
-
54
45
  ## How It Works
55
46
 
56
- Sessions appear as star systems. Files orbit as planets -- the more a file is touched, the larger it grows. Tool calls animate between nodes:
47
+ The server watches Claude Code's session transcript files (`~/.claude/projects/`) and tails them in real time. No hooks or additional configuration required.
57
48
 
58
- - **Read / Grep / Glob** -- scanner at the file, data streams back to core
59
- - **Edit / Write** -- ink beam fires from core to file
60
- - **Bash** -- terminal window appears at the node
61
- - **Subagents** -- satellite systems tethered to their parent
49
+ Each Claude Code session appears as an orbiting star system. Every tool call creates a node — the more events a session generates, the larger it grows. Tool calls trigger visual effects:
62
50
 
63
- Multiple Claude sessions show as separate star systems. Prompts fly inward, responses fly outward. Context compaction triggers an implosion/rebirth effect.
51
+ - **Read / Grep / Glob** scan effect radiates from the node
52
+ - **Edit / Write** — energy beam fires from core to node
53
+ - **Bash** — spark burst at the node
54
+ - **Subagents** — child systems orbit their parent session
64
55
 
65
- Under the hood: the plugin sends every event to a lightweight Node.js server (pure passthrough, no persistence). The server broadcasts events to a PixiJS frontend via Server-Sent Events (SSE).
56
+ Multiple Claude sessions show as separate star systems. Prompts pulse outward, context compaction triggers an implosion/rebirth effect.
66
57
 
67
58
  ## Server Endpoints
68
59
 
69
60
  | Endpoint | Method | Description |
70
61
  |---|---|---|
71
- | `/hook` | POST | Receive hook events, broadcast to SSE clients |
62
+ | `/hook` | POST | Receive hook events (legacy/plugin), broadcast to SSE clients |
72
63
  | `/events` | GET | SSE stream for the frontend |
73
- | `/health` | GET | Health check — returns `{"ok":true,"clients":<N>,"port":43451}` |
64
+ | `/health` | GET | Health check — returns `{"ok":true,"version":"X.Y.Z","clients":<N>,"port":43451}` |
74
65
 
75
66
  ## Troubleshooting
76
67
 
77
- | Symptom | Cause | Fix |
78
- |---|---|---|
79
- | No activity in browser | Hooks not firing | Run `/reload-plugins` or check `settings.json` hooks |
80
- | Server not reachable | Server not running | `/claude-live:server` auto-starts it |
81
- | `clients: 0` in `/health` | Server up, no browser tab open | Open `http://localhost:43451` |
82
- | Hook logs location | Debug delivery failures | `~/.config/claude-live/logs/YYYY-MM-DD.jsonl` |
68
+ | Symptom | Fix |
69
+ |---|---|
70
+ | No activity in browser | Make sure Claude Code is running, check `~/.claude/projects/` has `.jsonl` files |
71
+ | Server not reachable | Run `claude-live` to start it |
72
+ | `clients: 0` in `/health` | Open http://localhost:43451 in your browser |
83
73
 
84
74
  ## Development
85
75
 
@@ -91,6 +81,7 @@ npm install
91
81
  node server/index.js # Node.js server on :43451
92
82
  cd client && npm run dev # Vite hot-reload on :7979
93
83
  cd client && npx tsc --noEmit # Type check frontend
84
+ npm run test:server # Run server tests
94
85
  ```
95
86
 
96
87
  ## License
Binary file
@@ -0,0 +1,147 @@
1
+ import{C as W,G as p,a as b,W as z,S as M,P as A,O as S,B as k,b as C,M as F,A as u,d as h,E as j,R,U as L,V,g as E,L as _,h as G,Q as I,k as g,D as f,I as P,r as v,l as o}from"./index-D3vltDuF.js";class D{constructor(e){this.clock=new W,this.elapsed=0,this.agentGroup=new p,this.currentVisual=null,this.currentVariation=null,this.agentTetherLine=null,this.wanderOffsets=new b(Math.random()*100,Math.random()*100,Math.random()*100),this.pulseTimer=0,this.pulseInterval=2,this._onResize=()=>{const d=this.renderer.domElement.parentElement;if(!d)return;const y=Math.max(1,d.clientWidth),l=Math.max(1,d.clientHeight);this.camera.aspect=y/l,this.camera.updateProjectionMatrix(),this.renderer.setSize(y,l),this.composer.setSize(y,l)},this.renderer=new z({antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.setSize(e.clientWidth,e.clientHeight),this.renderer.setClearColor(197384),e.appendChild(this.renderer.domElement),this.scene=new M;const t=Math.max(1,e.clientWidth),r=Math.max(1,e.clientHeight);this.camera=new A(55,t/r,1,2e3),this.camera.position.set(0,30,110),this.controls=new S(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.06,this.controls.autoRotate=!0,this.controls.autoRotateSpeed=.5,this.controls.target.set(0,15,0),this.controls.minDistance=20,this.controls.maxDistance=300,this.background=new k,this.scene.add(this.background.group);const n=new C(3,16,16),a=new F({color:4491519,transparent:!0,opacity:.5,blending:u}),i=new h(n,a);this.scene.add(i),this.scene.add(this.agentGroup),this.composer=new j(this.renderer),this.composer.addPass(new R(this.scene,this.camera));const c=new L(new V(e.clientWidth,e.clientHeight),1.2,.4,.15);this.composer.addPass(c),this.scene.updateMatrixWorld(!0),this.resizeObserver=new ResizeObserver(this._onResize),this.resizeObserver.observe(e),window.addEventListener("resize",this._onResize),this._onResize()}setVariation(e){if(this.currentVariation=e,this._clearVisual(),this.currentVisual=e.build(this.agentGroup),!this.agentTetherLine){const t=new E().setFromPoints(new Array(21).fill(new b)),r=new _({color:4500223,transparent:!0,opacity:.2,blending:u});this.agentTetherLine=new G(t,r),this.scene.add(this.agentTetherLine)}this.pulseTimer=0}triggerPulse(){var e,t;(t=(e=this.currentVisual)==null?void 0:e.pulse)==null||t.call(e)}_clearVisual(){this.currentVisual&&(this.currentVisual.dispose(),this.currentVisual=null)}tick(){const e=Math.min(this.clock.getDelta(),.05);if(this.elapsed+=e,this.controls.update(),this.background.tick(e),this.currentVisual){this.currentVisual.tick(e,this.elapsed);const t=.25;this.wanderOffsets.x+=e*t*.8,this.wanderOffsets.y+=e*t*1.1,this.wanderOffsets.z+=e*t*.9;const r=50;if(this.agentGroup.position.set(Math.sin(this.wanderOffsets.x)*r,25+Math.sin(this.wanderOffsets.y)*15,Math.cos(this.wanderOffsets.z)*r*Math.cos(this.wanderOffsets.x*.5)),this.agentTetherLine){const n=new b(0,0,0),a=this.agentGroup.position.clone(),i=n.clone().lerp(a,.5);i.y-=10+Math.sin(this.elapsed*2)*4;const c=new I(n,i,a);this.agentTetherLine.geometry.setFromPoints(c.getPoints(20))}this.pulseTimer+=e,this.pulseTimer>=this.pulseInterval&&(this.pulseTimer=0,this.pulseInterval=1.5+Math.random()*3)}try{this.composer.render()}catch{}}destroy(){this.resizeObserver.disconnect(),window.removeEventListener("resize",this._onResize),this.renderer.dispose(),this.renderer.domElement.remove(),this._clearVisual(),this.agentTetherLine&&(this.scene.remove(this.agentTetherLine),this.agentTetherLine.geometry.dispose(),this.agentTetherLine.material.dispose())}}const w=new P(3.5,128),T=new P(3.5,32).toNonIndexed();function O(s){const e=new p;s.add(e);const t=new g({uniforms:{uTime:{value:0},uActivity:{value:0}},vertexShader:`
2
+ uniform float uTime; uniform float uActivity;
3
+ varying vec3 vWorldPos;
4
+
5
+ float getWarp(vec3 p) {
6
+ // Classic smooth, large rolling waves
7
+ return sin(p.x*2.0 - uTime) * sin(p.y*3.0 - uTime*0.8) * cos(p.z*2.0 + uTime) * 1.5;
8
+ }
9
+ void main() {
10
+ vec3 pos = position + normal * getWarp(position) * (0.6 + uActivity);
11
+ vec4 wPos = modelMatrix * vec4(pos, 1.0);
12
+ vWorldPos = wPos.xyz;
13
+ gl_Position = projectionMatrix * viewMatrix * wPos;
14
+ }
15
+ `,fragmentShader:`
16
+ uniform float uActivity;
17
+ varying vec3 vWorldPos;
18
+ void main() {
19
+ vec3 n = normalize(cross(dFdx(vWorldPos), dFdy(vWorldPos)));
20
+ vec3 v = normalize(cameraPosition - vWorldPos);
21
+ float fresnel = 1.0 - max(dot(v, n), 0.0);
22
+
23
+ vec3 base = mix(vec3(0.01, 0.02, 0.05), vec3(0.05, 0.01, 0.05), fract(vWorldPos.y * 0.15));
24
+ vec3 col = base + pow(fresnel, 4.0) * vec3(0.1, 0.4, 0.8) * (1.0 + uActivity);
25
+
26
+ gl_FragColor = vec4(col, min(1.0, 0.3 + pow(fresnel, 4.0) * 0.5));
27
+ }
28
+ `,transparent:!0,depthWrite:!1,blending:u,side:f});e.add(new h(w,t));let r=0;return{tick(n,a){r=Math.max(0,r-n*2),t.uniforms.uTime.value=a,t.uniforms.uActivity.value=r},pulse(){r=1},dispose(){s.remove(e),t.dispose()}}}function B(s){const e=new p;s.add(e);const t=new g({uniforms:{uTime:{value:0},uActivity:{value:0}},vertexShader:`
29
+ uniform float uTime; uniform float uActivity;
30
+ varying vec3 vWorldPos;
31
+
32
+ float getWarp(vec3 p) {
33
+ // Absolute sine waves create sharp folds and spikes instead of smooth curves
34
+ float n1 = 1.0 - abs(sin(p.x * 3.0 + uTime));
35
+ float n2 = 1.0 - abs(cos(p.y * 4.0 - uTime * 1.5));
36
+ float n3 = 1.0 - abs(sin(p.z * 5.0 + uTime * 0.5));
37
+ return pow(n1 * n2 * n3, 2.0) * 3.0; // Pushed out aggressively
38
+ }
39
+ void main() {
40
+ vec3 pos = position + normal * getWarp(position) * (0.8 + uActivity);
41
+ vec4 wPos = modelMatrix * vec4(pos, 1.0);
42
+ vWorldPos = wPos.xyz;
43
+ gl_Position = projectionMatrix * viewMatrix * wPos;
44
+ }
45
+ `,fragmentShader:`
46
+ uniform float uActivity;
47
+ varying vec3 vWorldPos;
48
+ void main() {
49
+ // Flat shading calculation (inherent to dFdx/dFdy on non-indexed geometry)
50
+ vec3 n = normalize(cross(dFdx(vWorldPos), dFdy(vWorldPos)));
51
+ vec3 v = normalize(cameraPosition - vWorldPos);
52
+ float fresnel = 1.0 - max(dot(v, n), 0.0);
53
+
54
+ vec3 col = vec3(0.01, 0.05, 0.05); // Deep green/cyan base
55
+ col += pow(fresnel, 2.0) * vec3(0.1, 0.8, 0.4) * (1.0 + uActivity); // Harsher glow on flat edges
56
+
57
+ gl_FragColor = vec4(col, min(1.0, 0.4 + pow(fresnel, 2.0) * 0.6));
58
+ }
59
+ `,transparent:!0,depthWrite:!1,blending:u,side:f});e.add(new h(T,t));let r=0;return{tick(n,a){r=Math.max(0,r-n*2),t.uniforms.uTime.value=a,t.uniforms.uActivity.value=r},pulse(){r=1},dispose(){s.remove(e),t.dispose()}}}function $(s){const e=new p;s.add(e);const t=new g({uniforms:{uTime:{value:0},uActivity:{value:0}},vertexShader:`
60
+ uniform float uTime; uniform float uActivity;
61
+ varying vec3 vWorldPos;
62
+
63
+ float getWarp(vec3 p) {
64
+ // Ripple strictly outward from the center poles based on Y
65
+ float radius = length(p.xz);
66
+ // Add a vertical sweeping element so it looks like a drop hitting water
67
+ return sin(radius * 15.0 - uTime * 6.0) * cos(p.y * 3.0 + uTime) * 0.5;
68
+ }
69
+ void main() {
70
+ // Displace the sphere entirely radially
71
+ vec3 pos = position + normal * getWarp(position) * (1.0 + uActivity * 2.0);
72
+ vec4 wPos = modelMatrix * vec4(pos, 1.0);
73
+ vWorldPos = wPos.xyz;
74
+ gl_Position = projectionMatrix * viewMatrix * wPos;
75
+ }
76
+ `,fragmentShader:`
77
+ uniform float uActivity;
78
+ varying vec3 vWorldPos;
79
+ void main() {
80
+ vec3 n = normalize(cross(dFdx(vWorldPos), dFdy(vWorldPos)));
81
+ vec3 v = normalize(cameraPosition - vWorldPos);
82
+ float fresnel = 1.0 - max(dot(v, n), 0.0);
83
+
84
+ vec3 col = vec3(0.01, 0.01, 0.08); // Indigo
85
+ col += pow(fresnel, 5.0) * vec3(0.5, 0.1, 1.0) * (1.0 + uActivity);
86
+
87
+ gl_FragColor = vec4(col, min(1.0, 0.2 + pow(fresnel, 5.0) * 0.8));
88
+ }
89
+ `,transparent:!0,depthWrite:!1,blending:u,side:f});e.add(new h(w,t));let r=0;return{tick(n,a){r=Math.max(0,r-n*2),t.uniforms.uTime.value=a,t.uniforms.uActivity.value=r},pulse(){r=1},dispose(){s.remove(e),t.dispose()}}}function H(s){const e=new p;s.add(e);const t=new g({uniforms:{uTime:{value:0},uActivity:{value:0}},vertexShader:`
90
+ uniform float uTime; uniform float uActivity;
91
+ varying vec3 vWorldPos;
92
+
93
+ float getWarp(vec3 p) {
94
+ // Floor the position to calculate the wave, tearing the geometry into blocks
95
+ vec3 stepP = floor(p * 3.0) / 3.0; // Quantize the space
96
+ float n = sin(stepP.x*5.0 - uTime) * cos(stepP.y*5.0) * sin(stepP.z*5.0 + uTime);
97
+ return n * 1.5;
98
+ }
99
+ void main() {
100
+ vec3 pos = position + normal * getWarp(position) * (0.8 + uActivity * 2.0);
101
+ vec4 wPos = modelMatrix * vec4(pos, 1.0);
102
+ vWorldPos = wPos.xyz;
103
+ gl_Position = projectionMatrix * viewMatrix * wPos;
104
+ }
105
+ `,fragmentShader:`
106
+ uniform float uActivity;
107
+ varying vec3 vWorldPos;
108
+ void main() {
109
+ vec3 n = normalize(cross(dFdx(vWorldPos), dFdy(vWorldPos)));
110
+ vec3 v = normalize(cameraPosition - vWorldPos);
111
+ float fresnel = 1.0 - max(dot(v, n), 0.0);
112
+
113
+ vec3 col = vec3(0.05, 0.01, 0.01); // Deep crimson base
114
+ col += pow(fresnel, 2.0) * vec3(1.0, 0.2, 0.2) * (1.0 + uActivity);
115
+
116
+ gl_FragColor = vec4(col, min(1.0, 0.5 + pow(fresnel, 2.0) * 0.5));
117
+ }
118
+ `,transparent:!0,depthWrite:!1,blending:u,side:f}),r=new h(T,t);e.add(r);let n=0;return{tick(a,i){n=Math.max(0,n-a*2),t.uniforms.uTime.value=i,t.uniforms.uActivity.value=n},pulse(){n=1},dispose(){s.remove(e),t.dispose()}}}function q(s){const e=new p;s.add(e);const t=new g({uniforms:{uTime:{value:0},uActivity:{value:0}},vertexShader:`
119
+ uniform float uTime; uniform float uActivity;
120
+ varying vec3 vWorldPos;
121
+
122
+ float getWarp(vec3 p) {
123
+ // Obscenely high frequency sine waves create mathematical noise, vibrating the mesh
124
+ float n = sin(p.x * 40.0 + uTime * 10.0) * sin(p.y * 40.0 - uTime * 5.0) * sin(p.z * 40.0 + uTime * 8.0);
125
+ return n * 0.25; // Keep amplitude low so it looks like fuzz, not explosions
126
+ }
127
+ void main() {
128
+ vec3 pos = position + normal * getWarp(position) * (1.0 + uActivity * 3.0);
129
+ vec4 wPos = modelMatrix * vec4(pos, 1.0);
130
+ vWorldPos = wPos.xyz;
131
+ gl_Position = projectionMatrix * viewMatrix * wPos;
132
+ }
133
+ `,fragmentShader:`
134
+ uniform float uActivity;
135
+ varying vec3 vWorldPos;
136
+ void main() {
137
+ vec3 n = normalize(cross(dFdx(vWorldPos), dFdy(vWorldPos)));
138
+ vec3 v = normalize(cameraPosition - vWorldPos);
139
+ float fresnel = 1.0 - max(dot(v, n), 0.0);
140
+
141
+ vec3 col = vec3(0.01, 0.01, 0.01); // Basically black hole
142
+ // The high frequency normals make the fresnel scatter like crazy!
143
+ col += pow(fresnel, 3.0) * vec3(0.8, 0.8, 1.0) * (1.0 + uActivity);
144
+
145
+ gl_FragColor = vec4(col, min(1.0, 0.6 + pow(fresnel, 3.0) * 0.4));
146
+ }
147
+ `,transparent:!0,depthWrite:!1,blending:u,side:f});e.add(new h(w,t));let r=0;return{tick(n,a){r=Math.max(0,r-n*2),t.uniforms.uTime.value=a,t.uniforms.uActivity.value=r},pulse(){r=1},dispose(){s.remove(e),t.dispose()}}}const x=[{name:"Smooth Void",description:"Deep dark rolling liquid displacement (The tuned baseline model).",build:O},{name:"Jagged Crystal",description:"Changes displacement to absolute mathematics and uses flat-shading to create sharp, tearing crystal spikes.",build:B},{name:"Concentric Droplet",description:"Symmetrical ripples flow outward radially from the center like a drop of liquid suspended in time.",build:$},{name:"Voxel Glitch Glass",description:"Forces the displacement math to snap to blocks (quantization), tearing the glass into digital cubes.",build:H},{name:"Micro-Fuzz",description:"Uses an obscenely high frequency wave to vibrate the vertices microscopically, causing intense light scattering.",build:q}];function U(){const s=v.useRef(null),e=v.useRef(null),t=v.useRef(0),[r,n]=v.useState(0);v.useEffect(()=>{if(!s.current)return;const i=new D(s.current);e.current=i,i.setVariation(x[0]);function c(){i.tick(),t.current=requestAnimationFrame(c)}return t.current=requestAnimationFrame(c),()=>{cancelAnimationFrame(t.current),i.destroy(),e.current=null}},[]);function a(i){var c;n(i),(c=e.current)==null||c.setVariation(x[i])}return o.jsxs("div",{style:{width:"100vw",height:"100vh",background:"#030308",position:"relative",overflow:"hidden"},children:[o.jsx("div",{ref:s,style:{position:"absolute",top:0,left:0,right:0,bottom:0}}),o.jsxs("div",{style:{position:"absolute",top:0,right:0,width:320,height:"100%",background:"rgba(3,3,14,0.92)",borderLeft:"1px solid rgba(255,255,255,0.06)",display:"flex",flexDirection:"column",fontFamily:"'Inter', 'SF Pro Display', system-ui, sans-serif",color:"#aaa",overflowY:"auto"},children:[o.jsxs("div",{style:{padding:"20px 20px 16px",borderBottom:"1px solid rgba(255,255,255,0.06)",background:"linear-gradient(180deg, rgba(100,120,255,0.06) 0%, transparent 100%)"},children:[o.jsx("div",{style:{fontSize:10,letterSpacing:"0.18em",color:"#555",marginBottom:6,textTransform:"uppercase"},children:"SUBAGENT VISUALIZATIONS"}),o.jsx("div",{style:{fontSize:16,color:"#e8ecf4",fontWeight:600,letterSpacing:"-0.01em"},children:"Agent Node Concepts"}),o.jsx("div",{style:{fontSize:11,color:"#556",marginTop:4,lineHeight:1.5},children:"Each concept is a completely different visual direction for representing a subagent in the Three.js scene."})]}),o.jsx("div",{style:{padding:12,display:"flex",flexDirection:"column",gap:8,flex:1},children:x.map((i,c)=>{const d=r===c,l=["#66aaff","#aa66ff","#8833cc","#4488ff","#44ddff"][c];return o.jsxs("button",{onClick:()=>a(c),style:{textAlign:"left",padding:"14px 16px",borderRadius:8,border:`1px solid ${d?l:"rgba(255,255,255,0.06)"}`,background:d?`linear-gradient(135deg, ${l}15 0%, ${l}08 100%)`:"rgba(255,255,255,0.02)",cursor:"pointer",color:"inherit",transition:"all 0.2s ease",position:"relative",overflow:"hidden"},onMouseEnter:m=>{d||(m.currentTarget.style.borderColor=`${l}66`,m.currentTarget.style.background=`${l}08`)},onMouseLeave:m=>{d||(m.currentTarget.style.borderColor="rgba(255,255,255,0.06)",m.currentTarget.style.background="rgba(255,255,255,0.02)")},children:[d&&o.jsx("div",{style:{position:"absolute",left:0,top:0,bottom:0,width:3,background:`linear-gradient(180deg, ${l}, ${l}44)`,borderRadius:"0 2px 2px 0"}}),o.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:6},children:[o.jsx("div",{style:{width:28,height:28,borderRadius:6,background:d?`linear-gradient(135deg, ${l}44, ${l}22)`:"rgba(255,255,255,0.04)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:700,color:d?l:"#555",border:`1px solid ${d?`${l}33`:"rgba(255,255,255,0.06)"}`,flexShrink:0},children:c+1}),o.jsx("span",{style:{fontSize:13,fontWeight:600,letterSpacing:"-0.01em",color:d?"#eef2ff":"#bbb"},children:i.name})]}),o.jsx("div",{style:{fontSize:11,color:d?"#8899bb":"#556",lineHeight:1.6,paddingLeft:38},children:i.description})]},i.name)})}),o.jsx("div",{style:{padding:"12px 16px",borderTop:"1px solid rgba(255,255,255,0.06)"},children:o.jsx("button",{onClick:()=>{var i;return(i=e.current)==null?void 0:i.triggerPulse()},style:{width:"100%",padding:"10px 0",background:"linear-gradient(135deg, rgba(100,120,255,0.15), rgba(100,120,255,0.08))",border:"1px solid rgba(100,120,255,0.2)",borderRadius:6,cursor:"pointer",color:"#8899cc",fontSize:12,fontWeight:600,letterSpacing:"0.05em",transition:"all 0.2s ease"},onMouseEnter:i=>{i.currentTarget.style.background="linear-gradient(135deg, rgba(100,120,255,0.25), rgba(100,120,255,0.15))",i.currentTarget.style.borderColor="rgba(100,120,255,0.4)"},onMouseLeave:i=>{i.currentTarget.style.background="linear-gradient(135deg, rgba(100,120,255,0.15), rgba(100,120,255,0.08))",i.currentTarget.style.borderColor="rgba(100,120,255,0.2)"},children:"⚡ TRIGGER PULSE"})}),o.jsxs("div",{style:{padding:"10px 16px",borderTop:"1px solid rgba(255,255,255,0.04)",fontSize:10,color:"#334",display:"flex",justifyContent:"space-between"},children:[o.jsx("span",{children:"drag to orbit · scroll to zoom"}),o.jsx("span",{children:"auto-pulse active"})]})]}),o.jsx("a",{href:"#/three",style:{position:"absolute",top:16,left:16,fontSize:11,color:"#556",textDecoration:"none",fontFamily:"'Inter', system-ui, sans-serif",letterSpacing:"0.05em",padding:"6px 12px",background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)",borderRadius:5,transition:"all 0.2s ease"},onMouseEnter:i=>{i.currentTarget.style.borderColor="rgba(255,255,255,0.15)",i.currentTarget.style.color="#aab"},onMouseLeave:i=>{i.currentTarget.style.borderColor="rgba(255,255,255,0.06)",i.currentTarget.style.color="#556"},children:"← back"})]})}export{U as AgentDemoScene};
@@ -0,0 +1,138 @@
1
+ import{C as K,G as L,W as X,S as Y,P as J,O as Q,B as Z,E as ee,R as te,U as oe,V as ae,L as W,a as u,b as H,M as F,A as M,c as S,d as B,e as re,D as ne,T as ie,f as U,g as N,h as E,i as z,j as se,s as le,k as R,r as _,l as g}from"./index-D3vltDuF.js";const j=new Map;let $=U;function ce(r,t){j.set(r,t),$=(o,i,s)=>{const d=j.get(o);return d?d(i,s):U(o,i,s)}}class ue{constructor(t){this.clock=new K,this.nodeGroup=new L,this.currentNode=null,this.respawnTimer=0,this.currentVariation=null,this.axisGroup=new L,this._onResize=()=>{const i=this.renderer.domElement.parentElement;if(!i)return;const s=i.clientWidth,d=i.clientHeight;this.camera.aspect=s/d,this.camera.updateProjectionMatrix(),this.renderer.setSize(s,d),this.composer.setSize(s,d)},this.renderer=new X({antialias:!0}),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.setClearColor(197384),t.appendChild(this.renderer.domElement),this.scene=new Y,this.camera=new J(55,t.clientWidth/t.clientHeight,1,2e3),this.camera.position.set(0,60,200),this.controls=new Q(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.06,this.controls.autoRotate=!1,this.controls.target.set(-40,5,-15),this.controls.minDistance=50,this.controls.maxDistance=600,this.background=new Z,this.scene.add(this.background.group),this.scene.add(this.nodeGroup),this.scene.add(this.axisGroup),this._buildAxis(),this._buildCoreGlow(),this.composer=new ee(this.renderer),this.composer.addPass(new te(this.scene,this.camera));const o=new oe(new ae(t.clientWidth,t.clientHeight),.7,.4,.75);this.composer.addPass(o),window.addEventListener("resize",this._onResize),this._onResize()}_buildAxis(){const t=new W({color:2236996,transparent:!0,opacity:.4}),o=(i,s)=>{const d=new N().setFromPoints([i,s]);return new E(d,t)};this.axisGroup.add(o(new u(-120,0,0),new u(20,0,0))),this.axisGroup.add(o(new u(0,-20,0),new u(0,30,0))),this.axisGroup.add(o(new u(0,0,-60),new u(0,0,20)))}_buildCoreGlow(){const t=new H(3,16,16),o=new F({color:new S("#22ff88"),transparent:!0,opacity:.15,blending:M});this.scene.add(new B(t,o));const i=new re(5,6,32),s=new F({color:new S("#4ade80"),transparent:!0,opacity:.2,blending:M,side:ne});this.scene.add(new B(i,s));const d=new u(-80,10,-30),v=new H(2,12,12),h=new F({color:new S("#4ade80"),transparent:!0,opacity:.3,blending:M}),m=new B(v,h);m.position.copy(d),this.scene.add(m)}setVariation(t){if(this.currentVariation=t,t.buildCustomEffect){const o=t.spawnParams()._tool??"";ce(o,t.buildCustomEffect)}this._clearNode(),this._spawnNode()}_clearNode(){this.currentNode&&(this.nodeGroup.remove(this.currentNode.group),this.currentNode.dispose(),this.currentNode=null)}_spawnNode(){if(!this.currentVariation)return;const t=this.currentVariation.spawnParams(this.camera.position),o=new ie(t,$);this.nodeGroup.add(o.group),this.currentNode=o,this.respawnTimer=0}tick(){const t=Math.min(this.clock.getDelta(),.05);this.controls.update(),this.background.tick(t),this.currentNode?(this.currentNode.tick(t),this.currentNode.done&&(this._clearNode(),this.respawnTimer=0)):(this.respawnTimer+=t,this.respawnTimer>1&&this.currentVariation&&this._spawnNode()),this.composer.render()}destroy(){window.removeEventListener("resize",this._onResize),this.renderer.dispose(),this._clearNode(),j.clear()}}const q=new u(0,0,0);function x(r,t){return Math.random()*(t-r)+r}function de(){return{origin:new u(-120,15,-60),target:q.clone().add(new u(x(-2,2),x(-2,2),x(-2,2))),color:new S("#b0c8f0"),colorEnd:new S("#ffffff"),travelTime:3,trailLength:0,trailBrightness:0,trailFadeTime:4,headSize:0,pathConfig:{type:"linear",easing:"easeInCubic"},_tool:"prompt:custom"}}function pe(){const r=Math.random()*Math.PI*2,t=Math.acos(x(-1,1)),o=x(250,400);return new u(Math.sin(t)*Math.cos(r)*o,Math.sin(t)*Math.sin(r)*o,Math.cos(t)*o)}function O(r){const t=de();t._tool=r,t.origin=pe(),t.travelTime=x(4,5.5),t.trailFadeTime=1.8;const o=t.origin.clone().add(q).multiplyScalar(.5);return t.pathConfig={type:"quadratic",easing:"easeInOut",c1:new u(o.x+x(-40,40),o.y+x(20,60),o.z+x(-30,30))},t}function he(r,t){return{f1:1.2+Math.random()*1.5,f2:3.5+Math.random()*3,ph1:Math.random()*Math.PI*2,ph2:Math.random()*Math.PI*2,amp:4+Math.random()*6,perp:new u(Math.random()-.5,Math.random()-.5,Math.random()-.5).normalize(),scatter:new u((Math.random()-.5)*400,(Math.random()-.5)*400,(Math.random()-.5)*400),windowStart:-(r/t)*3.5-Math.random()*.2,rollSpeed:.8+Math.random()*.6}}function fe(r,t,o,i,s){const d=se(t.pathConfig.easing,o),v=le(t.pathConfig,t.origin,t.target,d),h=Math.max(0,1-o/.5),m=Math.min(1,o/.5),l=1-Math.pow(o,8),e=(Math.sin(o*r.f1*Math.PI*2+r.ph1+i*s)*r.amp+Math.sin(o*r.f2*Math.PI*2+r.ph2+i*s*1.4)*r.amp*.3)*m*l;return new u(v.x+r.scatter.x*h+r.perp.x*e,v.y+r.scatter.y*h+r.perp.y*e,v.z+r.scatter.z*h+r.perp.z*e)}function P(r,t,o,i,s){const d=Array.from({length:i},(h,m)=>{const l=he(m,i),e=new Float32Array(o*3),n=new N;n.setAttribute("position",new z(e,3));const c=new Float32Array(o);for(let T=0;T<o;T++)c[T]=T/(o-1);n.setAttribute("aT",new z(c,1));const{mat:a,setOpacity:p,setTime:w}=s(m,n);return r.add(new E(n,a)),{...l,posArr:e,geo:n,mat:a,window:l.windowStart,setOpacity:p,setTime:w}}),v={entries:d.map(h=>({obj:new E(h.geo,h.mat),mat:h.mat,meta:{}})),suppressDefaultTrail:!0,trailTick(h,m,l){var c;const e=2.5+l*.1;let n=!0;for(const a of d){const p=a.window>=1?1/(1.5*a.rollSpeed):(1-a.windowStart)/t.travelTime;a.window=Math.min(2,a.window+m*p);const w=a.window;if(w<=0){a.geo.setDrawRange(0,0),n=!1;continue}if(w>=2){a.setOpacity(0),a.geo.setDrawRange(0,0);continue}n=!1;const T=Math.round(Math.min(1,w)*(o-1)),y=Math.round(Math.max(0,w-1)*(o-1)),A=T-y;if(A<1){a.geo.setDrawRange(0,0);continue}for(let b=y;b<=T;b++){const C=fe(a,t,b/(o-1),l,e);a.posArr[b*3]=C.x,a.posArr[b*3+1]=C.y,a.posArr[b*3+2]=C.z}a.geo.attributes.position.needsUpdate=!0,a.geo.setDrawRange(y,A),a.setOpacity(.7),(c=a.setTime)==null||c.call(a,l)}n&&(v.shouldMarkDone=!0)},tick(){},onLand(){},applyFade(h){},shouldMarkDone:!1};return v}function ge(r,t){return P(r,t,120,8,o=>{const i=new W({color:new S().setHSL(.55+o/8*.15,.9,.6+o%2*.2),transparent:!0,opacity:0,blending:M,depthWrite:!1});return{mat:i,setOpacity:s=>{i.opacity=s}}})}const me=`
2
+ attribute float aT;
3
+ varying float vT;
4
+ void main() { vT = aT; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }
5
+ `,ve=`
6
+ uniform float uTime;
7
+ uniform float uOpacity;
8
+ uniform float uHueBase;
9
+ varying float vT;
10
+ vec3 hsl2rgb(float h, float s, float l) {
11
+ h = mod(h, 1.0);
12
+ vec3 rgb = clamp(abs(mod(h*6.0+vec3(0,4,2),6.0)-3.0)-1.0, 0.0, 1.0);
13
+ return l + s*(rgb-0.5)*(1.0-abs(2.0*l-1.0));
14
+ }
15
+ void main() {
16
+ // Hue drifts along length + time
17
+ float hue = mod(uHueBase + vT * 0.3 + uTime * 0.12, 1.0);
18
+ float core = pow(1.0 - vT, 0.3); // bright at head (t=1 is target)
19
+ float bloom = pow(vT, 0.5) * 0.6;
20
+ vec3 col = hsl2rgb(hue, 1.0, 0.55 + bloom * 0.3);
21
+ // White-hot center
22
+ col = mix(col, vec3(1.0), core * 0.4);
23
+ float alpha = (bloom + core * 0.5) * uOpacity;
24
+ gl_FragColor = vec4(col * (bloom + core * 0.5 + 0.05), alpha);
25
+ }
26
+ `;function we(r,t){return P(r,t,120,8,o=>{const i=new R({vertexShader:me,fragmentShader:ve,uniforms:{uTime:{value:0},uOpacity:{value:0},uHueBase:{value:o/8}},blending:M,transparent:!0,depthWrite:!1});return{mat:i,setOpacity:s=>{i.uniforms.uOpacity.value=s},setTime:s=>{i.uniforms.uTime.value=s}}})}const be=`
27
+ attribute float aT;
28
+ varying float vT;
29
+ void main() { vT = aT; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }
30
+ `,Te=`
31
+ uniform float uTime;
32
+ uniform float uOpacity;
33
+ uniform float uPhase;
34
+ varying float vT;
35
+ float hash(float n) { return fract(sin(n)*43758.5453); }
36
+ void main() {
37
+ // High-freq flicker noise
38
+ float noise = hash(floor(vT * 80.0 + uTime * 30.0));
39
+ float flicker = 0.7 + 0.3 * noise;
40
+ // Traveling pulse toward core (vT=1)
41
+ float pulsePos = mod(uPhase + uTime * 0.6, 1.0);
42
+ float pulse = exp(-pow((vT - pulsePos) / 0.05, 2.0)) * 2.5;
43
+ // Base glow — brighter near core
44
+ float base = pow(vT, 0.4) * 0.5;
45
+ float b = (base + pulse) * flicker;
46
+ // Color: deep blue → cyan → white at pulse peak
47
+ vec3 blue = vec3(0.05, 0.2, 1.0);
48
+ vec3 cyan = vec3(0.2, 0.9, 1.0);
49
+ vec3 white = vec3(1.0, 1.0, 1.0);
50
+ vec3 col = mix(blue, cyan, vT);
51
+ col = mix(col, white, clamp(pulse / 2.5, 0.0, 1.0));
52
+ gl_FragColor = vec4(col * b, b * uOpacity);
53
+ }
54
+ `;function ye(r,t){return P(r,t,120,8,o=>{const i=new R({vertexShader:be,fragmentShader:Te,uniforms:{uTime:{value:0},uOpacity:{value:0},uPhase:{value:o/8}},blending:M,transparent:!0,depthWrite:!1});return{mat:i,setOpacity:s=>{i.uniforms.uOpacity.value=s},setTime:s=>{i.uniforms.uTime.value=s}}})}const xe=`
55
+ attribute float aT;
56
+ varying float vT;
57
+ void main() { vT = aT; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }
58
+ `,Me=`
59
+ uniform float uTime;
60
+ uniform float uOpacity;
61
+ uniform float uOffset;
62
+ varying float vT;
63
+ vec3 hsl2rgb(float h, float s, float l) {
64
+ h = mod(h, 1.0);
65
+ vec3 rgb = clamp(abs(mod(h*6.0+vec3(0,4,2),6.0)-3.0)-1.0, 0.0, 1.0);
66
+ return l + s*(rgb-0.5)*(1.0-abs(2.0*l-1.0));
67
+ }
68
+ void main() {
69
+ // Slow drifting color bands along the strand
70
+ float hue = mod(uOffset + vT * 0.5 + uTime * 0.04, 1.0);
71
+ float bright = 0.5 + 0.5 * sin(vT * 3.0 + uTime * 0.8 + uOffset * 6.28);
72
+ // Soft curtain falloff — bright in the middle of length
73
+ float curtain = sin(vT * 3.14159) * 0.8 + 0.2;
74
+ // Very soft, high luminance pastels
75
+ vec3 col = hsl2rgb(hue, 0.6, 0.6 + bright * 0.25);
76
+ float alpha = curtain * bright * 0.5 * uOpacity;
77
+ gl_FragColor = vec4(col * curtain * bright, alpha);
78
+ }
79
+ `;function Se(r,t){return P(r,t,120,10,o=>{const i=new R({vertexShader:xe,fragmentShader:Me,uniforms:{uTime:{value:0},uOpacity:{value:0},uOffset:{value:o/10}},blending:M,transparent:!0,depthWrite:!1});return{mat:i,setOpacity:s=>{i.uniforms.uOpacity.value=s},setTime:s=>{i.uniforms.uTime.value=s}}})}const Ae=`
80
+ attribute float aT;
81
+ varying float vT;
82
+ void main() { vT = aT; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }
83
+ `,Ce=`
84
+ uniform float uTime;
85
+ uniform float uOpacity;
86
+ uniform float uHue;
87
+ varying float vT;
88
+ vec3 hsl2rgb(float h, float s, float l) {
89
+ h = mod(h, 1.0);
90
+ vec3 rgb = clamp(abs(mod(h*6.0+vec3(0,4,2),6.0)-3.0)-1.0, 0.0, 1.0);
91
+ return l + s*(rgb-0.5)*(1.0-abs(2.0*l-1.0));
92
+ }
93
+ void main() {
94
+ // Traveling energy packets
95
+ float packet1 = exp(-pow(mod(vT - uTime * 0.5, 1.0) / 0.08, 2.0));
96
+ float packet2 = exp(-pow(mod(vT - uTime * 0.5 + 0.4, 1.0) / 0.08, 2.0));
97
+ float energy = packet1 + packet2 * 0.6;
98
+ // White-hot spine at high energy, colored bleed otherwise
99
+ vec3 fiberCol = hsl2rgb(uHue, 1.0, 0.5);
100
+ vec3 col = mix(fiberCol, vec3(1.0), clamp(energy, 0.0, 1.0));
101
+ // Base thread glow — constant soft light
102
+ float base = 0.2 + 0.1 * sin(vT * 20.0 - uTime * 3.0);
103
+ float alpha = (base + energy * 0.8) * uOpacity;
104
+ gl_FragColor = vec4(col * (base + energy * 0.8), alpha);
105
+ }
106
+ `;function _e(r,t){return P(r,t,120,8,o=>{const i=new R({vertexShader:Ae,fragmentShader:Ce,uniforms:{uTime:{value:0},uOpacity:{value:0},uHue:{value:.55+o/8*.35}},blending:M,transparent:!0,depthWrite:!1});return{mat:i,setOpacity:s=>{i.uniforms.uOpacity.value=s},setTime:s=>{i.uniforms.uTime.value=s}}})}const ke=[{name:"Writhing",description:"Baseline — colored strands scatter, converge, weave into core",spawnParams:()=>O("prompt:writhing"),buildCustomEffect:ge},{name:"Neon Iridescent",description:"Hue shifts along length and over time — white-hot core bloom",spawnParams:()=>O("prompt:neon"),buildCustomEffect:we},{name:"Plasma",description:"Electric blue-white with noisy flicker and traveling pulses",spawnParams:()=>O("prompt:plasma"),buildCustomEffect:ye},{name:"Aurora",description:"Soft pastel curtains drifting with slow color bands",spawnParams:()=>O("prompt:aurora"),buildCustomEffect:Se},{name:"Fiber Light",description:"White-hot spine with colored energy packets traveling to core",spawnParams:()=>O("prompt:fiber"),buildCustomEffect:_e}];function f(r,t){return Math.random()*(t-r)+r}const Oe=new u(0,0,0);function Re(){const r=Math.random()*Math.PI*2,t=f(60,110),o=new u(Math.cos(r)*t,f(-8,15),Math.sin(r)*t*.5),i=o.clone().multiplyScalar(.5);return{origin:Oe.clone(),target:o,color:new S("#a78bfa"),colorEnd:new S("#e9d5ff"),travelTime:f(2.5,3.5),trailLength:0,trailBrightness:0,trailFadeTime:30,headSize:0,pathConfig:{type:"quadratic",easing:"easeInOut",c1:new u(i.x+f(-25,25),i.y+f(10,35),i.z+f(-20,20))},_tool:"Glob:demo"}}const V=80,I=10,Pe=.35,Ee=`
107
+ attribute float aT;
108
+ varying float vT;
109
+ void main() {
110
+ vT = aT;
111
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
112
+ }
113
+ `,ze=`
114
+ uniform float uTime;
115
+ uniform float uOpacity;
116
+ uniform vec3 uBaseColor;
117
+ uniform vec3 uTipColor;
118
+ uniform float uPhase;
119
+ varying float vT;
120
+
121
+ void main() {
122
+ vec3 col = mix(uBaseColor, uTipColor, vT);
123
+
124
+ // energy flow racing toward tip
125
+ float flow = sin((vT * 8.0 - uTime * 2.0 + uPhase) * 3.14159);
126
+ flow = pow(max(0.0, flow), 3.0) * 0.3;
127
+ col += uTipColor * flow;
128
+
129
+ // hot head: last 10% glows bright
130
+ float head = smoothstep(0.9, 1.0, vT);
131
+ col = mix(col, uTipColor * 1.5, head * 0.7);
132
+
133
+ float bright = 0.4 + vT * 0.3 + flow * 0.3 + head * 0.8;
134
+ float alpha = uOpacity * (0.3 + vT * 0.3 + flow * 0.15 + head * 0.4);
135
+
136
+ gl_FragColor = vec4(min(col * bright, 1.0), min(alpha, 1.0));
137
+ }
138
+ `;function De(r,t){const o=[];function i(e,n){const c=f(0,Math.PI*2),a=f(-.6,.6),p=new u(Math.cos(c)*Math.cos(a),Math.sin(a),Math.sin(c)*Math.cos(a)).normalize(),w=f(14,22),T=p.clone().multiplyScalar(w),y=new Float32Array(V*3),A=new Float32Array(V),b=new N;b.setAttribute("position",new z(y,3)),b.setAttribute("aT",new z(A,1)),b.setDrawRange(0,0);const C=new R({vertexShader:Ee,fragmentShader:ze,uniforms:{uTime:{value:0},uOpacity:{value:.85},uBaseColor:{value:new u(.2,.12,.4)},uTipColor:{value:new u(.5,.35,.9)},uPhase:{value:f(0,6.28)}},blending:M,transparent:!0,depthWrite:!1}),D=new E(b,C);D.visible=!1,r.add(D),y[0]=t.target.x,y[1]=t.target.y,y[2]=t.target.z,A[0]=0;const G={origin:t.target.clone(),isHit:n,fireDelay:e,pos:t.target.clone(),vel:T,searchDist:f(20,45),gravity:new u(f(-1.5,1.5),f(-3,-1),f(-1.5,1.5)),drift:new u(f(-2,2),f(-.5,.5),f(-2,2)),returnStart:new u,returnArc:new u,returnT:0,returnDur:f(1.2,2),points:[t.target.clone()],posArr:y,tArr:A,geo:b,mat:C,line:D,ptCount:1,state:"waiting",elapsed:0,stateTime:0,tailIdx:0};return o.push(G),G}const s=[],d=Array.from({length:I},(e,n)=>n);for(let e=d.length-1;e>0;e--){const n=Math.floor(Math.random()*(e+1));[d[e],d[n]]=[d[n],d[e]]}for(let e=0;e<I;e++){const n=d[e]<I*Pe;s.push(i(f(.1,3),n))}function v(e){const n=Math.min(e.points.length,V),c=e.points.length-n;for(let a=0;a<n;a++){const p=e.points[c+a];e.posArr[a*3]=p.x,e.posArr[a*3+1]=p.y,e.posArr[a*3+2]=p.z,e.tArr[a]=a/(n-1||1)}e.ptCount=n,e.geo.attributes.position.needsUpdate=!0,e.geo.attributes.aT.needsUpdate=!0}function h(e,n,c,a){const p=1-a;return new u(p*p*e.x+2*p*a*n.x+a*a*c.x,p*p*e.y+2*p*a*n.y+a*a*c.y,p*p*e.z+2*p*a*n.z+a*a*c.z)}function m(e,n){if(e.elapsed+=n,e.mat.uniforms.uTime.value=e.elapsed,e.state==="waiting"){e.elapsed>=e.fireDelay&&(e.state="seeking",e.stateTime=0,e.line.visible=!0);return}if(e.stateTime+=n,e.state==="seeking"){if(e.vel.addScaledVector(e.gravity,n),e.vel.addScaledVector(e.drift,n),e.vel.multiplyScalar(1-n*.3),e.pos.addScaledVector(e.vel,n),e.points.push(e.pos.clone()),v(e),e.geo.setDrawRange(0,e.ptCount),e.pos.distanceTo(e.origin)>=e.searchDist)if(e.isHit){e.state="hit_returning",e.stateTime=0,e.returnStart.copy(e.pos);const c=e.pos.clone().add(e.origin).multiplyScalar(.5);e.returnArc.set(c.x+f(-18,18),c.y+f(8,25),c.z+f(-18,18)),e.returnT=0,e.mat.uniforms.uBaseColor.value.set(.05,.35,.15),e.mat.uniforms.uTipColor.value.set(.3,1,.5)}else e.state="miss_dying",e.stateTime=0,e.tailIdx=0,e.mat.uniforms.uBaseColor.value.set(.3,.05,.05),e.mat.uniforms.uTipColor.value.set(.5,.1,.08)}else if(e.state==="hit_returning"){e.returnT=Math.min(1,e.returnT+n/e.returnDur);const c=e.returnT<.5?2*e.returnT*e.returnT:1-Math.pow(-2*e.returnT+2,2)/2;e.pos.copy(h(e.returnStart,e.returnArc,e.origin,c)),e.points.push(e.pos.clone()),v(e),e.geo.setDrawRange(0,e.ptCount),e.returnT>=1&&(e.state="miss_dying",e.stateTime=0,e.tailIdx=0)}else if(e.state==="miss_dying"){const c=e.isHit?25:15;e.tailIdx=Math.min(e.ptCount-1,e.tailIdx+n*c);const a=Math.round(e.tailIdx),p=e.ptCount-a;if(p<=1){e.state="done",e.geo.setDrawRange(0,0),e.line.visible=!1;return}e.geo.setDrawRange(a,p);for(let w=a;w<e.ptCount;w++)e.tArr[w]=(w-a)/(p-1);e.geo.attributes.aT.needsUpdate=!0,e.isHit||(e.mat.uniforms.uOpacity.value=Math.max(0,.85-e.stateTime*.4))}}const l={entries:[],suppressDefaultTrail:!0,trailTick(e,n){for(const c of s)m(c,n);o.every(c=>c.state==="done")&&(l.shouldMarkDone=!0)},tick(){},onLand(){},applyFade(e){},shouldMarkDone:!1,dispose(){for(const e of o)e.geo.dispose(),e.mat.dispose()}};return l}const Fe=[{name:"Seeker Missiles",description:"Missiles launch staggered, seek outward; hits glow green and arc back, misses turn red and dissolve",spawnParams:Re,buildCustomEffect:De}],k=[{label:"Prompt",color:"#93c5fd",variations:ke},{label:"Glob",color:"#a78bfa",variations:Fe}];function Ve(){const r=_.useRef(null),t=_.useRef(null),o=_.useRef(0),[i,s]=_.useState(0),[d,v]=_.useState(0),h=k[i];_.useEffect(()=>{if(!r.current)return;const l=new ue(r.current);t.current=l;const e=k[0].variations[0];l.setVariation(e);function n(){l.tick(),o.current=requestAnimationFrame(n)}return o.current=requestAnimationFrame(n),()=>{cancelAnimationFrame(o.current),l.destroy(),t.current=null}},[]);function m(l,e){var c;s(l),v(e);const n=k[l].variations[e];(c=t.current)==null||c.setVariation(n)}return g.jsxs("div",{style:{width:"100vw",height:"100vh",background:"#030308",display:"flex",position:"relative"},children:[g.jsx("div",{ref:r,style:{flex:1,height:"100%"}}),g.jsxs("div",{style:{position:"absolute",top:0,right:0,width:280,height:"100%",background:"rgba(3,3,14,0.88)",borderLeft:"1px solid rgba(255,255,255,0.06)",display:"flex",flexDirection:"column",fontFamily:"monospace",color:"#aaa",overflowY:"auto"},children:[g.jsxs("div",{style:{padding:"16px 16px 10px",borderBottom:"1px solid rgba(255,255,255,0.06)"},children:[g.jsx("div",{style:{fontSize:11,letterSpacing:"0.1em",color:"#555",marginBottom:4},children:"EFFECT DEMO"}),g.jsx("div",{style:{fontSize:13,color:"#eee"},children:"trail variations"})]}),g.jsx("div",{style:{display:"flex",padding:"10px 10px 0",gap:6,flexWrap:"wrap"},children:k.map((l,e)=>g.jsx("button",{onClick:()=>m(e,0),style:{padding:"4px 10px",fontSize:11,borderRadius:3,border:`1px solid ${i===e?l.color:"rgba(255,255,255,0.1)"}`,background:i===e?`${l.color}18`:"transparent",color:i===e?l.color:"#666",cursor:"pointer",letterSpacing:"0.05em"},children:l.label},l.label))}),g.jsx("div",{style:{padding:10,display:"flex",flexDirection:"column",gap:8,flex:1},children:h.variations.map((l,e)=>{const n=i===k.indexOf(h)&&d===e;return g.jsxs("button",{onClick:()=>m(k.indexOf(h),e),style:{textAlign:"left",padding:"10px 12px",borderRadius:5,border:`1px solid ${n?h.color:"rgba(255,255,255,0.07)"}`,background:n?`${h.color}12`:"rgba(255,255,255,0.02)",cursor:"pointer",color:"inherit",transition:"border-color 0.15s"},children:[g.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:4},children:[g.jsx("span",{style:{display:"inline-block",width:8,height:8,borderRadius:"50%",background:n?h.color:"#444",flexShrink:0}}),g.jsxs("span",{style:{fontSize:12,color:n?h.color:"#ccc",fontWeight:600},children:[e+1,". ",l.name]})]}),g.jsx("div",{style:{fontSize:11,color:"#666",lineHeight:1.5,paddingLeft:16},children:l.description})]},l.name)})}),g.jsx("div",{style:{padding:"10px 16px",borderTop:"1px solid rgba(255,255,255,0.05)",fontSize:10,color:"#444"},children:"drag to orbit · scroll to zoom · node loops automatically"})]}),g.jsx("a",{href:"#/three",style:{position:"absolute",top:14,left:14,fontSize:11,color:"#444",textDecoration:"none",fontFamily:"monospace",letterSpacing:"0.05em"},children:"← back"})]})}export{Ve as EffectDemoScene};