| |
| |
| |
| |
|
|
| class ConnectionManager { |
| constructor(scene) { |
| this.scene = scene; |
| this.connections = new Map(); |
| this.connectionLines = new Map(); |
| this.materials = new Map(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| addConnection(id, startPos, endPos, config = {}) { |
| |
| if (this.connections.has(id)) { |
| console.warn(`Connection "${id}" already exists.`); |
| return null; |
| } |
|
|
| const color = config.color || '#00ff00'; |
| const lineWidth = config.lineWidth || 2; |
|
|
| |
| const geometry = new THREE.BufferGeometry(); |
| geometry.setAttribute('position', new THREE.BufferAttribute( |
| new Float32Array([ |
| startPos.x, startPos.y, startPos.z, |
| endPos.x, endPos.y, endPos.z |
| ]), 3 |
| )); |
|
|
| |
| const material = new THREE.LineBasicMaterial({ |
| color: new THREE.Color(color), |
| linewidth: lineWidth, |
| transparent: true, |
| opacity: 0.8 |
| }); |
|
|
| |
| const line = new THREE.Line(geometry, material); |
| line.name = id; |
| line.userData = { |
| connectionId: id, |
| fromSphere: config.fromSphere, |
| toSphere: config.toSphere, |
| color: color, |
| lineWidth: lineWidth, |
| startPos: startPos.clone(), |
| endPos: endPos.clone() |
| }; |
|
|
| |
| this.scene.add(line); |
| this.connections.set(id, line.userData); |
| this.connectionLines.set(id, line); |
| this.materials.set(id, material); |
|
|
| |
| return line; |
| } |
|
|
| |
| |
| |
| |
| removeConnection(id) { |
| const line = this.connectionLines.get(id); |
| if (!line) { |
| console.warn(`Connection "${id}" not found.`); |
| return; |
| } |
|
|
| |
| this.scene.remove(line); |
|
|
| |
| const geometry = line.geometry; |
| const material = this.materials.get(id); |
| if (geometry) geometry.dispose(); |
| if (material) material.dispose(); |
|
|
| |
| this.connections.delete(id); |
| this.connectionLines.delete(id); |
| this.materials.delete(id); |
|
|
| |
| } |
|
|
| |
| |
| |
| |
| |
| |
| updateConnectionPositions(id, startPos, endPos) { |
| const line = this.connectionLines.get(id); |
| if (!line) return; |
|
|
| const positions = line.geometry.attributes.position.array; |
| positions[0] = startPos.x; |
| positions[1] = startPos.y; |
| positions[2] = startPos.z; |
| positions[3] = endPos.x; |
| positions[4] = endPos.y; |
| positions[5] = endPos.z; |
|
|
| line.geometry.attributes.position.needsUpdate = true; |
| line.userData.startPos = startPos.clone(); |
| line.userData.endPos = endPos.clone(); |
| } |
|
|
| |
| |
| |
| |
| |
| updateConnectionColor(id, newColor) { |
| const material = this.materials.get(id); |
| if (!material) return; |
|
|
| material.color.set(new THREE.Color(newColor)); |
| this.connections.get(id).color = newColor; |
| } |
|
|
| |
| |
| |
| |
| |
| getConnection(id) { |
| return this.connections.get(id); |
| } |
|
|
| |
| |
| |
| |
| getAllConnections() { |
| return Array.from(this.connections.entries()).map(([id, data]) => ({ |
| id, |
| ...data, |
| line: this.connectionLines.get(id) |
| })); |
| } |
|
|
| |
| |
| |
| |
| |
| getConnectionsForSphere(sphereName) { |
| return Array.from(this.connections.values()).filter(conn => |
| conn.fromSphere === sphereName || conn.toSphere === sphereName |
| ); |
| } |
|
|
| |
| |
| |
| |
| removeConnectionsForSphere(sphereName) { |
| const connectionsToRemove = Array.from(this.connections.keys()).filter(id => { |
| const conn = this.connections.get(id); |
| return conn.fromSphere === sphereName || conn.toSphere === sphereName; |
| }); |
|
|
| connectionsToRemove.forEach(id => this.removeConnection(id)); |
| } |
|
|
| |
| |
| |
| |
| |
| pulseConnection(id, duration = 500) { |
| const material = this.materials.get(id); |
| if (!material) return; |
|
|
| const startOpacity = material.opacity; |
| const startTime = Date.now(); |
|
|
| const animate = () => { |
| const elapsed = Date.now() - startTime; |
| const progress = (elapsed % duration) / duration; |
| const opacityPulse = Math.sin(progress * Math.PI * 2); |
|
|
| material.opacity = startOpacity + opacityPulse * 0.2; |
|
|
| if (elapsed < duration * 2) { |
| requestAnimationFrame(animate); |
| } else { |
| material.opacity = startOpacity; |
| } |
| }; |
|
|
| animate(); |
| } |
|
|
| |
| |
| |
| clearAll() { |
| const ids = Array.from(this.connections.keys()); |
| ids.forEach(id => this.removeConnection(id)); |
| console.log('✓ All connections cleared'); |
| } |
|
|
| |
| |
| |
| |
| getCount() { |
| return this.connections.size; |
| } |
| } |
|
|