get-claudia 1.40.4 → 1.40.5
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/package.json +1 -1
- package/visualizer/src/effects.js +4 -1
- package/visualizer/src/graph.js +77 -11
- package/visualizer/src/links.js +6 -2
- package/visualizer/src/main.js +1 -1
- package/visualizer/src/nodes.js +38 -7
- package/visualizer/src/themes.js +10 -10
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@ const QUALITY_PRESETS = {
|
|
|
22
22
|
low: { bloom: false, bloomStrength: 0, bloomRadius: 0, bloomThreshold: 0 },
|
|
23
23
|
medium: { bloom: true, bloomStrength: 1.0, bloomRadius: 0.8, bloomThreshold: 0.2 },
|
|
24
24
|
high: null, // use theme defaults
|
|
25
|
-
ultra: { bloom: true, bloomStrength:
|
|
25
|
+
ultra: { bloom: true, bloomStrength: 2.1, bloomRadius: 0.9, bloomThreshold: 0.05 }
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
// FPS tracking
|
|
@@ -136,6 +136,9 @@ export function animateNodes(Graph, elapsed, delta) {
|
|
|
136
136
|
const ud = obj.userData;
|
|
137
137
|
if (!ud || ud.hidden) continue;
|
|
138
138
|
|
|
139
|
+
// Skip memory nodes with no active animations (they don't breathe/rotate)
|
|
140
|
+
if (ud.nodeType === 'memory' && !node.__spawn && !node.__pulse && !node.__shimmer) continue;
|
|
141
|
+
|
|
139
142
|
const baseScale = ud.baseScale || 1;
|
|
140
143
|
const phase = ud.phase || 0;
|
|
141
144
|
const coreMesh = ud.coreMesh;
|
package/visualizer/src/graph.js
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* the library handles all of that internally.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { Color } from 'three';
|
|
10
|
+
import { getActiveTheme } from './themes.js';
|
|
11
|
+
|
|
9
12
|
let Graph = null;
|
|
10
13
|
let graphData = { nodes: [], links: [] };
|
|
11
14
|
let fullData = null; // Stashed for filter/reset
|
|
@@ -13,6 +16,10 @@ let highlightNodes = new Set();
|
|
|
13
16
|
let highlightLinks = new Set();
|
|
14
17
|
let selectedNode = null;
|
|
15
18
|
|
|
19
|
+
// Saved material state for restoring after clearSelection()
|
|
20
|
+
let savedMaterials = new Map(); // nodeId -> { color, emissiveIntensity }
|
|
21
|
+
let savedLinkColors = new Map(); // link -> { color, width }
|
|
22
|
+
|
|
16
23
|
// ── Graph instance ─────────────────────────────────────────
|
|
17
24
|
|
|
18
25
|
export function setGraphInstance(instance) {
|
|
@@ -62,13 +69,13 @@ export function updateNodeData(nodeId, updates) {
|
|
|
62
69
|
// ── Selection + highlighting ──────────────────────────────
|
|
63
70
|
|
|
64
71
|
export function highlightNeighborhood(node) {
|
|
72
|
+
// Restore previous highlight before applying new one
|
|
73
|
+
restoreSavedMaterials();
|
|
74
|
+
|
|
65
75
|
highlightNodes.clear();
|
|
66
76
|
highlightLinks.clear();
|
|
67
77
|
|
|
68
|
-
if (!node)
|
|
69
|
-
triggerRefresh();
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
78
|
+
if (!node) return;
|
|
72
79
|
|
|
73
80
|
highlightNodes.add(node.id);
|
|
74
81
|
|
|
@@ -86,14 +93,14 @@ export function highlightNeighborhood(node) {
|
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
|
|
89
|
-
|
|
96
|
+
applyHighlightMaterials();
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
export function clearSelection() {
|
|
93
100
|
selectedNode = null;
|
|
101
|
+
restoreSavedMaterials();
|
|
94
102
|
highlightNodes.clear();
|
|
95
103
|
highlightLinks.clear();
|
|
96
|
-
triggerRefresh();
|
|
97
104
|
document.getElementById('detail-panel')?.classList.add('hidden');
|
|
98
105
|
}
|
|
99
106
|
|
|
@@ -130,12 +137,71 @@ function pushData() {
|
|
|
130
137
|
Graph.graphData({ nodes: graphData.nodes, links: graphData.links });
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Apply highlight visuals directly on Three.js materials for the
|
|
142
|
+
* selected neighborhood. O(k) where k = neighborhood size, not O(N).
|
|
143
|
+
*/
|
|
144
|
+
function applyHighlightMaterials() {
|
|
134
145
|
if (!Graph) return;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
const theme = getActiveTheme();
|
|
147
|
+
const highlightColor = new Color(0x7dd3fc); // bright cyan highlight
|
|
148
|
+
|
|
149
|
+
// Highlight nodes: boost emissive intensity
|
|
150
|
+
for (const nodeId of highlightNodes) {
|
|
151
|
+
const node = graphData.nodes.find(n => n.id === nodeId);
|
|
152
|
+
if (!node?.__threeObj) continue;
|
|
153
|
+
|
|
154
|
+
const ud = node.__threeObj.userData;
|
|
155
|
+
const mesh = ud?.coreMesh;
|
|
156
|
+
if (!mesh?.material) continue;
|
|
157
|
+
|
|
158
|
+
// Save original state
|
|
159
|
+
savedMaterials.set(nodeId, {
|
|
160
|
+
emissiveIntensity: mesh.material.emissiveIntensity,
|
|
161
|
+
emissive: mesh.material.emissive.getHex()
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Boost: brighter emissive
|
|
165
|
+
mesh.material.emissiveIntensity = Math.min(1.0, mesh.material.emissiveIntensity * 2.5);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Highlight links: change color and width
|
|
169
|
+
for (const link of highlightLinks) {
|
|
170
|
+
const linkObj = link.__lineObj;
|
|
171
|
+
if (linkObj?.material) {
|
|
172
|
+
savedLinkColors.set(link, {
|
|
173
|
+
color: linkObj.material.color.getHex(),
|
|
174
|
+
linewidth: linkObj.material.linewidth
|
|
175
|
+
});
|
|
176
|
+
linkObj.material.color.set(theme.links.highlight);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Restore materials saved before highlighting.
|
|
183
|
+
*/
|
|
184
|
+
function restoreSavedMaterials() {
|
|
185
|
+
// Restore node materials
|
|
186
|
+
for (const [nodeId, saved] of savedMaterials) {
|
|
187
|
+
const node = graphData.nodes.find(n => n.id === nodeId);
|
|
188
|
+
if (!node?.__threeObj) continue;
|
|
189
|
+
const mesh = node.__threeObj.userData?.coreMesh;
|
|
190
|
+
if (!mesh?.material) continue;
|
|
191
|
+
|
|
192
|
+
mesh.material.emissiveIntensity = saved.emissiveIntensity;
|
|
193
|
+
mesh.material.emissive.setHex(saved.emissive);
|
|
194
|
+
}
|
|
195
|
+
savedMaterials.clear();
|
|
196
|
+
|
|
197
|
+
// Restore link materials
|
|
198
|
+
for (const [link, saved] of savedLinkColors) {
|
|
199
|
+
const linkObj = link.__lineObj;
|
|
200
|
+
if (linkObj?.material) {
|
|
201
|
+
linkObj.material.color.setHex(saved.color);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
savedLinkColors.clear();
|
|
139
205
|
}
|
|
140
206
|
|
|
141
207
|
// ── Focus camera on a node ───────────────────────────────
|
package/visualizer/src/links.js
CHANGED
|
@@ -10,11 +10,15 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { getGraphInstance, getHighlightLinks } from './graph.js';
|
|
13
|
-
import { getActiveTheme, onThemeChange } from './themes.js';
|
|
13
|
+
import { getActiveTheme, getActiveThemeId, onThemeChange } from './themes.js';
|
|
14
14
|
import { getSetting } from './settings.js';
|
|
15
15
|
|
|
16
|
-
// Re-configure links when theme changes
|
|
16
|
+
// Re-configure links when theme actually changes (guard against redundant calls)
|
|
17
|
+
let lastLinkThemeId = null;
|
|
17
18
|
onThemeChange(() => {
|
|
19
|
+
const currentId = getActiveThemeId();
|
|
20
|
+
if (currentId === lastLinkThemeId) return;
|
|
21
|
+
lastLinkThemeId = currentId;
|
|
18
22
|
const Graph = getGraphInstance();
|
|
19
23
|
if (Graph) configureLinks(Graph);
|
|
20
24
|
});
|
package/visualizer/src/main.js
CHANGED
|
@@ -89,7 +89,7 @@ async function init() {
|
|
|
89
89
|
.backgroundColor(theme.background)
|
|
90
90
|
|
|
91
91
|
// Force simulation tuning
|
|
92
|
-
.d3AlphaDecay(getSetting('simulation.alphaDecay') ?? 0.
|
|
92
|
+
.d3AlphaDecay(getSetting('simulation.alphaDecay') ?? 0.02)
|
|
93
93
|
.d3VelocityDecay(getSetting('simulation.velocityDecay') ?? 0.4)
|
|
94
94
|
|
|
95
95
|
// Node rendering
|
package/visualizer/src/nodes.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Patterns use wireframe icosahedra.
|
|
7
7
|
*
|
|
8
8
|
* Colors and emissive intensities are read from the active theme.
|
|
9
|
-
*
|
|
9
|
+
* Theme changes update materials in-place (no geometry recreation).
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
Group,
|
|
21
21
|
Sprite,
|
|
22
22
|
SpriteMaterial,
|
|
23
|
-
CanvasTexture
|
|
23
|
+
CanvasTexture,
|
|
24
|
+
Color
|
|
24
25
|
} from 'three';
|
|
25
|
-
|
|
26
|
-
import { getActiveTheme, onThemeChange } from './themes.js';
|
|
26
|
+
import { getActiveTheme, getActiveThemeId, onThemeChange } from './themes.js';
|
|
27
27
|
import { getSetting } from './settings.js';
|
|
28
28
|
import { getGraphInstance } from './graph.js';
|
|
29
29
|
|
|
@@ -32,14 +32,45 @@ import { getGraphInstance } from './graph.js';
|
|
|
32
32
|
export let ENTITY_COLORS = { ...getActiveTheme().entities };
|
|
33
33
|
export let MEMORY_COLORS = { ...getActiveTheme().memories };
|
|
34
34
|
|
|
35
|
+
// Direct material color update instead of rebuilding all Three.js objects
|
|
36
|
+
let lastNodeThemeId = null;
|
|
35
37
|
onThemeChange((theme) => {
|
|
38
|
+
const currentId = getActiveThemeId();
|
|
39
|
+
if (currentId === lastNodeThemeId) return;
|
|
40
|
+
lastNodeThemeId = currentId;
|
|
41
|
+
|
|
36
42
|
Object.assign(ENTITY_COLORS, theme.entities);
|
|
37
43
|
Object.assign(MEMORY_COLORS, theme.memories);
|
|
38
44
|
|
|
39
|
-
//
|
|
45
|
+
// Update existing node materials in-place (no geometry recreation)
|
|
40
46
|
const Graph = getGraphInstance();
|
|
41
|
-
if (Graph)
|
|
42
|
-
|
|
47
|
+
if (!Graph) return;
|
|
48
|
+
const graphData = Graph.graphData();
|
|
49
|
+
if (!graphData?.nodes) return;
|
|
50
|
+
|
|
51
|
+
for (const node of graphData.nodes) {
|
|
52
|
+
const obj = node.__threeObj;
|
|
53
|
+
if (!obj) continue;
|
|
54
|
+
|
|
55
|
+
const ud = obj.userData;
|
|
56
|
+
const mesh = ud?.coreMesh;
|
|
57
|
+
if (!mesh?.material) continue;
|
|
58
|
+
|
|
59
|
+
if (ud.nodeType === 'entity') {
|
|
60
|
+
const color = theme.entities[node.entityType] || node.color || '#888888';
|
|
61
|
+
mesh.material.color.set(color);
|
|
62
|
+
mesh.material.emissive.set(color);
|
|
63
|
+
mesh.material.emissiveIntensity = theme.emissive.entity;
|
|
64
|
+
} else if (ud.nodeType === 'pattern') {
|
|
65
|
+
mesh.material.color.set(theme.pattern.color);
|
|
66
|
+
mesh.material.emissive.set(theme.pattern.emissive);
|
|
67
|
+
mesh.material.emissiveIntensity = theme.emissive.pattern;
|
|
68
|
+
} else if (ud.nodeType === 'memory') {
|
|
69
|
+
const color = theme.memories[node.memoryType] || node.color || '#888888';
|
|
70
|
+
mesh.material.color.set(color);
|
|
71
|
+
mesh.material.emissive.set(color);
|
|
72
|
+
mesh.material.emissiveIntensity = theme.emissive.memory;
|
|
73
|
+
}
|
|
43
74
|
}
|
|
44
75
|
});
|
|
45
76
|
|
package/visualizer/src/themes.js
CHANGED
|
@@ -61,7 +61,7 @@ const THEMES = {
|
|
|
61
61
|
strong: '#00ffaa',
|
|
62
62
|
normal: '#818cf8',
|
|
63
63
|
},
|
|
64
|
-
bloom: { strength:
|
|
64
|
+
bloom: { strength: 1.4, radius: 0.75, threshold: 0.12 },
|
|
65
65
|
emissive: { entity: 0.35, memory: 0.04, pattern: 0.5 },
|
|
66
66
|
},
|
|
67
67
|
|
|
@@ -110,7 +110,7 @@ const THEMES = {
|
|
|
110
110
|
strong: '#f0abfc',
|
|
111
111
|
normal: '#d946ef',
|
|
112
112
|
},
|
|
113
|
-
bloom: { strength:
|
|
113
|
+
bloom: { strength: 1.55, radius: 0.8, threshold: 0.10 },
|
|
114
114
|
emissive: { entity: 0.40, memory: 0.04, pattern: 0.55 },
|
|
115
115
|
},
|
|
116
116
|
|
|
@@ -159,7 +159,7 @@ const THEMES = {
|
|
|
159
159
|
strong: '#4ade80',
|
|
160
160
|
normal: '#06b6d4',
|
|
161
161
|
},
|
|
162
|
-
bloom: { strength:
|
|
162
|
+
bloom: { strength: 1.4, radius: 0.75, threshold: 0.10 },
|
|
163
163
|
emissive: { entity: 0.38, memory: 0.04, pattern: 0.5 },
|
|
164
164
|
},
|
|
165
165
|
|
|
@@ -208,7 +208,7 @@ const THEMES = {
|
|
|
208
208
|
strong: '#fbbf24',
|
|
209
209
|
normal: '#f97316',
|
|
210
210
|
},
|
|
211
|
-
bloom: { strength:
|
|
211
|
+
bloom: { strength: 1.55, radius: 0.75, threshold: 0.12 },
|
|
212
212
|
emissive: { entity: 0.40, memory: 0.05, pattern: 0.5 },
|
|
213
213
|
},
|
|
214
214
|
|
|
@@ -257,7 +257,7 @@ const THEMES = {
|
|
|
257
257
|
strong: '#e0f2fe',
|
|
258
258
|
normal: '#38bdf8',
|
|
259
259
|
},
|
|
260
|
-
bloom: { strength: 1.
|
|
260
|
+
bloom: { strength: 1.25, radius: 0.7, threshold: 0.14 },
|
|
261
261
|
emissive: { entity: 0.35, memory: 0.04, pattern: 0.45 },
|
|
262
262
|
},
|
|
263
263
|
|
|
@@ -306,7 +306,7 @@ const THEMES = {
|
|
|
306
306
|
strong: '#86efac',
|
|
307
307
|
normal: '#22c55e',
|
|
308
308
|
},
|
|
309
|
-
bloom: { strength:
|
|
309
|
+
bloom: { strength: 1.75, radius: 0.6, threshold: 0.08 },
|
|
310
310
|
emissive: { entity: 0.45, memory: 0.03, pattern: 0.55 },
|
|
311
311
|
},
|
|
312
312
|
|
|
@@ -355,7 +355,7 @@ const THEMES = {
|
|
|
355
355
|
strong: '#fb923c',
|
|
356
356
|
normal: '#f43f5e',
|
|
357
357
|
},
|
|
358
|
-
bloom: { strength:
|
|
358
|
+
bloom: { strength: 1.4, radius: 0.75, threshold: 0.12 },
|
|
359
359
|
emissive: { entity: 0.38, memory: 0.05, pattern: 0.50 },
|
|
360
360
|
},
|
|
361
361
|
|
|
@@ -404,7 +404,7 @@ const THEMES = {
|
|
|
404
404
|
strong: '#e4e4e7',
|
|
405
405
|
normal: '#a1a1aa',
|
|
406
406
|
},
|
|
407
|
-
bloom: { strength: 1.
|
|
407
|
+
bloom: { strength: 1.25, radius: 0.6, threshold: 0.15 },
|
|
408
408
|
emissive: { entity: 0.32, memory: 0.04, pattern: 0.40 },
|
|
409
409
|
},
|
|
410
410
|
|
|
@@ -453,7 +453,7 @@ const THEMES = {
|
|
|
453
453
|
strong: '#fbcfe8',
|
|
454
454
|
normal: '#f9a8d4',
|
|
455
455
|
},
|
|
456
|
-
bloom: { strength: 1.
|
|
456
|
+
bloom: { strength: 1.25, radius: 0.75, threshold: 0.14 },
|
|
457
457
|
emissive: { entity: 0.35, memory: 0.05, pattern: 0.45 },
|
|
458
458
|
},
|
|
459
459
|
|
|
@@ -502,7 +502,7 @@ const THEMES = {
|
|
|
502
502
|
strong: '#a5b4fc',
|
|
503
503
|
normal: '#6366f1',
|
|
504
504
|
},
|
|
505
|
-
bloom: { strength:
|
|
505
|
+
bloom: { strength: 2.1, radius: 0.9, threshold: 0.08 },
|
|
506
506
|
emissive: { entity: 0.50, memory: 0.02, pattern: 0.60 },
|
|
507
507
|
},
|
|
508
508
|
};
|