claude-live 2.0.7 → 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 +30 -39
- package/bin/claude-live +0 -0
- package/client/dist/assets/AgentDemoScene-DmPViizX.js +147 -0
- package/client/dist/assets/EffectDemoScene-DiyNw7OL.js +138 -0
- package/client/dist/assets/SakuraPage-BuSWb222.js +518 -0
- package/client/dist/assets/index-D3vltDuF.js +4446 -0
- package/client/dist/assets/index-TkH4paIm.css +1 -0
- package/client/dist/index.html +2 -2
- package/package.json +14 -8
- package/server/history-reader.js +68 -0
- package/server/index.js +101 -7
- package/server/project-tree.js +178 -0
- package/server/session-scanner.js +150 -0
- package/server/transcript-parser.js +177 -0
- package/.claude-plugin/hooks/hooks.json +0 -161
- package/client/dist/assets/BufferResource-B3YcFk1L.js +0 -185
- package/client/dist/assets/CanvasRenderer-B7cP3KcG.js +0 -1
- package/client/dist/assets/Filter-BXkJkOCD.js +0 -1
- package/client/dist/assets/RenderTargetSystem-DkV5EZ2H.js +0 -172
- package/client/dist/assets/WebGLRenderer-Cgmusykq.js +0 -156
- package/client/dist/assets/WebGPURenderer-B_Gw9-ml.js +0 -41
- package/client/dist/assets/browserAll-wXmCMyRg.js +0 -14
- package/client/dist/assets/index-BGs_09Jl.js +0 -318
- package/client/dist/assets/index-DjcKbX6b.css +0 -1
- package/client/dist/assets/webworkerAll-Hyzs6HuJ.js +0 -83
- package/hooks/hooks.json +0 -161
- package/hooks/run-hook.cmd +0 -38
- package/hooks/send-event +0 -5
- package/hooks/session-start +0 -40
package/README.md
CHANGED
|
@@ -1,85 +1,75 @@
|
|
|
1
1
|
# claude-live
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**[Try the live demo](https://marisancans.github.io/claude-live/)** — no install needed
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Real-time visualization of Claude Code activity as a 3D orbital system.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Claude Code Marketplace (recommended)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
19
|
+
This gives you the `/claude-live:server` slash command to manage the server from within Claude Code.
|
|
18
20
|
|
|
19
|
-
###
|
|
21
|
+
### npm (standalone)
|
|
20
22
|
|
|
21
23
|
```bash
|
|
22
24
|
npm install -g claude-live
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
## Use
|
|
26
28
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
34
|
+
Open http://localhost:43451 in your browser. Sessions appear automatically as you use Claude Code.
|
|
37
35
|
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 |
|
|
78
|
-
|
|
79
|
-
| No activity in browser |
|
|
80
|
-
| Server not reachable |
|
|
81
|
-
| `clients: 0` in `/health` |
|
|
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
|
package/bin/claude-live
ADDED
|
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};
|