@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
93 lines (81 loc) • 3.07 kB
text/typescript
import { AudioListener as ThreeAudioListener } from "three";
import { Application } from "../engine/engine_application.js";
import { Camera } from "./Camera.js";
import { Behaviour, GameObject } from "./Component.js";
/**
* AudioListener represents a listener that can hear audio sources in the scene.
* This component creates and manages a Three.js {@link three#AudioListener}, automatically connecting it
* to the main camera or a Camera in the parent hierarchy.
* @category Multimedia
* @group Components
*/
export class AudioListener extends Behaviour {
/**
* Gets the existing Three.js {@link three#AudioListener} instance or creates a new one if it doesn't exist.
* This listener is responsible for capturing audio in the 3D scene.
* @returns The {@link three#AudioListener} instance
*/
get listener(): ThreeAudioListener {
if (this._listener == null)
this._listener = new ThreeAudioListener();
return this._listener;
}
private _listener: ThreeAudioListener | null = null;
/**
* Registers for interaction events and initializes the audio listener
* when this component is enabled.
* @internal
*/
onEnable(): void {
Application.registerWaitForInteraction(this.onInteraction);
this.addListenerIfItExists();
}
/**
* Cleans up event registrations and removes the audio listener
* when this component is disabled.
* @internal
*/
onDisable(): void {
Application.unregisterWaitForInteraction(this.onInteraction);
this.removeListenerIfItExists();
}
private onInteraction = () => {
if (this.destroyed) return;
const listener = this.listener;
if (listener == null) return;
this.addListenerIfItExists();
}
private addListenerIfItExists() {
const listener = this._listener;
if (!listener) return;
// if the listener is already parented to some object dont change it
if (listener?.parent) return;
const cam = this.context.mainCameraComponent || GameObject.getComponentInParent(this.gameObject, Camera);
if (cam?.threeCamera) {
cam.threeCamera.add(listener);
}
else {
this.gameObject.add(listener);
}
// connect the listeners audio nodes
if (!listener.filter) {
listener.gain.connect(listener.context.destination);
}
else {
listener.gain.connect(listener.filter);
listener.filter.connect(listener.context.destination);
}
}
private removeListenerIfItExists() {
const listener = this._listener;
if (!listener) return;
listener.removeFromParent();
// disconnect the listeners audio nodes
if (listener.filter) {
listener.filter.disconnect();
}
if (listener.gain) {
listener.gain.disconnect();
}
}
}