| |
| |
| |
| |
|
|
| class SphereManager { |
| constructor(scene) { |
| this.scene = scene; |
| this.spheres = new Map(); |
| this.sphereMeshes = new Map(); |
| this.geometries = new Map(); |
| this.materials = new Map(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| addSphere(name, config = {}) { |
| |
| if (this.spheres.has(name)) { |
| console.warn(`Sphere with name "${name}" already exists. Skipping.`); |
| return null; |
| } |
|
|
| |
| const radius = config.radius || 1; |
| const color = config.color || '#ff0000'; |
| const position = config.position || new THREE.Vector3(0, 0, 0); |
| const opacity = config.opacity !== undefined ? config.opacity : 1; |
|
|
| |
| const geometry = new THREE.SphereGeometry(radius, 32, 32); |
| const material = new THREE.MeshStandardMaterial({ |
| color: new THREE.Color(color), |
| opacity: opacity, |
| transparent: opacity < 1, |
| emissive: new THREE.Color(color), |
| emissiveIntensity: 0.3, |
| metalness: 0.3, |
| roughness: 0.4 |
| }); |
|
|
| |
| const mesh = new THREE.Mesh(geometry, material); |
| mesh.position.copy(position); |
| mesh.name = name; |
| mesh.userData = { |
| sphereName: name, |
| radius: radius, |
| originalColor: color, |
| connections: [] |
| }; |
|
|
| |
| this.scene.add(mesh); |
| this.spheres.set(name, mesh.userData); |
| this.sphereMeshes.set(name, mesh); |
| this.geometries.set(name, geometry); |
| this.materials.set(name, material); |
|
|
| console.log(`✓ Sphere added: ${name}`, config); |
| return mesh; |
| } |
|
|
| |
| |
| |
| |
| removeSphere(name) { |
| const mesh = this.sphereMeshes.get(name); |
| if (!mesh) { |
| console.warn(`Sphere "${name}" not found.`); |
| return; |
| } |
|
|
| |
| this.scene.remove(mesh); |
|
|
| |
| const geometry = this.geometries.get(name); |
| const material = this.materials.get(name); |
| if (geometry) geometry.dispose(); |
| if (material) material.dispose(); |
|
|
| |
| this.spheres.delete(name); |
| this.sphereMeshes.delete(name); |
| this.geometries.delete(name); |
| this.materials.delete(name); |
|
|
| console.log(`✓ Sphere removed: ${name}`); |
| } |
|
|
| |
| |
| |
| |
| |
| updateSphere(name, config = {}) { |
| const mesh = this.sphereMeshes.get(name); |
| if (!mesh) { |
| console.warn(`Sphere "${name}" not found.`); |
| return; |
| } |
|
|
| |
| if (config.position) { |
| mesh.position.copy(config.position); |
| } |
|
|
| |
| if (config.color) { |
| const colorObj = new THREE.Color(config.color); |
| mesh.material.color.copy(colorObj); |
| mesh.material.emissive.copy(colorObj); |
| mesh.userData.originalColor = config.color; |
| } |
|
|
| |
| if (config.opacity !== undefined) { |
| mesh.material.opacity = config.opacity; |
| mesh.material.transparent = config.opacity < 1; |
| } |
|
|
| |
| if (config.scale !== undefined) { |
| mesh.scale.set(config.scale, config.scale, config.scale); |
| } |
|
|
| console.log(`✓ Sphere updated: ${name}`); |
| } |
|
|
| |
| |
| |
| |
| |
| getSphere(name) { |
| return this.sphereMeshes.get(name); |
| } |
|
|
| |
| |
| |
| |
| getAllSpheres() { |
| return Array.from(this.spheres.entries()).map(([name, data]) => ({ |
| name, |
| ...data, |
| mesh: this.sphereMeshes.get(name) |
| })); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| changeColorSmooth(name, newColor, duration = 500) { |
| const mesh = this.sphereMeshes.get(name); |
| if (!mesh) return; |
|
|
| const startColor = mesh.material.color.getHex(); |
| const endColor = new THREE.Color(newColor).getHex(); |
| const startTime = Date.now(); |
|
|
| const animate = () => { |
| const elapsed = Date.now() - startTime; |
| const progress = Math.min(elapsed / duration, 1); |
|
|
| const currentColor = new THREE.Color().lerpHexColors(startColor, endColor, progress); |
| mesh.material.color.copy(currentColor); |
| mesh.material.emissive.copy(currentColor); |
|
|
| if (progress < 1) { |
| requestAnimationFrame(animate); |
| } else { |
| mesh.userData.originalColor = newColor; |
| } |
| }; |
|
|
| animate(); |
| } |
|
|
| |
| |
| |
| |
| |
| setGlow(name, enable = true) { |
| const mesh = this.sphereMeshes.get(name); |
| if (!mesh) return; |
|
|
| if (enable) { |
| mesh.material.emissiveIntensity = 0.8; |
| } else { |
| mesh.material.emissiveIntensity = 0.3; |
| } |
| } |
|
|
| |
| |
| |
| clearAll() { |
| const names = Array.from(this.spheres.keys()); |
| names.forEach(name => this.removeSphere(name)); |
| console.log('✓ All spheres cleared'); |
| } |
|
|
| |
| |
| |
| |
| getCount() { |
| return this.spheres.size; |
| } |
| } |
|
|