EG/plugins/user/spatial_audio/components/audio_component.py
2025-12-12 16:16:15 +08:00

459 lines
12 KiB
Python

"""
音频组件基类
提供音频组件的基础功能和接口
"""
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional
import uuid
class AudioComponent(ABC):
"""
音频组件基类
提供音频组件的基础功能和接口
"""
def __init__(self, plugin, name: str = ""):
"""
初始化音频组件
Args:
plugin: 3D音频插件实例
name: 组件名称
"""
self.plugin = plugin
self.name = name if name else f"AudioComponent_{uuid.uuid4()}"
self.enabled = True
self.properties: Dict[str, Any] = {}
@abstractmethod
def initialize(self) -> bool:
"""
初始化组件
Returns:
是否初始化成功
"""
pass
@abstractmethod
def cleanup(self):
"""清理组件资源"""
pass
@abstractmethod
def update(self, dt: float):
"""
更新组件状态
Args:
dt: 时间增量
"""
pass
def enable(self):
"""启用组件"""
self.enabled = True
def disable(self):
"""禁用组件"""
self.enabled = False
def is_enabled(self) -> bool:
"""
检查组件是否启用
Returns:
是否启用
"""
return self.enabled
def set_property(self, name: str, value: Any) -> bool:
"""
设置属性
Args:
name: 属性名
value: 属性值
Returns:
是否设置成功
"""
try:
self.properties[name] = value
return True
except Exception:
return False
def get_property(self, name: str, default: Any = None) -> Any:
"""
获取属性
Args:
name: 属性名
default: 默认值
Returns:
属性值
"""
return self.properties.get(name, default)
def remove_property(self, name: str) -> bool:
"""
移除属性
Args:
name: 属性名
Returns:
是否移除成功
"""
if name in self.properties:
del self.properties[name]
return True
return False
def get_all_properties(self) -> Dict[str, Any]:
"""
获取所有属性
Returns:
属性字典
"""
return self.properties.copy()
class AudioSourceComponent(AudioComponent):
"""
音频源组件
用于为游戏对象添加音频播放功能
"""
def __init__(self, plugin, name: str = ""):
super().__init__(plugin, name)
self.sound_id: Optional[str] = None
self.spatial = False
self.loop = False
self.volume = 1.0
self.attached_object = None
def initialize(self) -> bool:
"""初始化音频源组件"""
# 音频源组件在需要时才创建音效
return True
def cleanup(self):
"""清理音频源组件"""
if self.sound_id:
self.plugin.audio_source_manager.delete_sound(self.sound_id)
self.sound_id = None
def update(self, dt: float):
"""更新音频源组件"""
if not self.enabled:
return
# 如果附加到对象,同步位置
if self.attached_object and self.sound_id and self.spatial:
pos = self.attached_object.getPos()
self.plugin.audio_source_manager.set_sound_position(
self.sound_id, (pos.x, pos.y, pos.z))
def load_sound(self, filepath: str, spatial: bool = False,
loop: bool = False, volume: float = 1.0) -> bool:
"""
加载音频文件
Args:
filepath: 音频文件路径
spatial: 是否为3D音效
loop: 是否循环播放
volume: 音量
Returns:
是否加载成功
"""
try:
# 删除现有音效
if self.sound_id:
self.plugin.audio_source_manager.delete_sound(self.sound_id)
# 创建新音效
if spatial:
pos = (0, 0, 0)
if self.attached_object:
obj_pos = self.attached_object.getPos()
pos = (obj_pos.x, obj_pos.y, obj_pos.z)
self.sound_id = self.plugin.audio_source_manager.create_3d_sound(
filepath, pos, loop, volume)
else:
self.sound_id = self.plugin.audio_source_manager.create_2d_sound(
filepath, loop, volume)
if self.sound_id:
self.spatial = spatial
self.loop = loop
self.volume = volume
return True
else:
return False
except Exception as e:
print(f"✗ 加载音频文件失败: {e}")
return False
def play(self) -> bool:
"""
播放音效
Returns:
是否播放成功
"""
if self.sound_id:
return self.plugin.audio_source_manager.play_sound(self.sound_id)
return False
def stop(self) -> bool:
"""
停止音效
Returns:
是否停止成功
"""
if self.sound_id:
return self.plugin.audio_source_manager.stop_sound(self.sound_id)
return False
def pause(self) -> bool:
"""
暂停音效
Returns:
是否暂停成功
"""
if self.sound_id:
return self.plugin.audio_source_manager.pause_sound(self.sound_id)
return False
def resume(self) -> bool:
"""
恢复音效
Returns:
是否恢复成功
"""
if self.sound_id:
return self.plugin.audio_source_manager.resume_sound(self.sound_id)
return False
def is_playing(self) -> bool:
"""
检查音效是否正在播放
Returns:
是否正在播放
"""
if self.sound_id:
return self.plugin.audio_source_manager.is_sound_playing(self.sound_id)
return False
def set_volume(self, volume: float) -> bool:
"""
设置音量
Args:
volume: 音量 (0.0-1.0)
Returns:
是否设置成功
"""
if self.sound_id:
success = self.plugin.audio_source_manager.set_sound_volume(self.sound_id, volume)
if success:
self.volume = volume
return success
return False
def set_loop(self, loop: bool) -> bool:
"""
设置循环模式
Args:
loop: 是否循环
Returns:
是否设置成功
"""
if self.sound_id:
success = self.plugin.audio_source_manager.set_sound_loop(self.sound_id, loop)
if success:
self.loop = loop
return success
return False
def attach_to_object(self, obj):
"""
附加到游戏对象
Args:
obj: 游戏对象
"""
self.attached_object = obj
def detach_from_object(self):
"""从游戏对象分离"""
self.attached_object = None
class AudioListenerComponent(AudioComponent):
"""
音频听者组件
用于设置音频听者位置和方向
"""
def __init__(self, plugin, name: str = ""):
super().__init__(plugin, name)
self.attached_object = None
def initialize(self) -> bool:
"""初始化音频听者组件"""
return True
def cleanup(self):
"""清理音频听者组件"""
pass
def update(self, dt: float):
"""更新音频听者组件"""
if not self.enabled:
return
# 如果附加到对象,同步位置和方向
if self.attached_object:
pos = self.attached_object.getPos()
hpr = self.attached_object.getHpr()
self.plugin.set_listener_position((pos.x, pos.y, pos.z))
self.plugin.set_listener_orientation((hpr.x, hpr.y, hpr.z))
def attach_to_object(self, obj):
"""
附加到游戏对象
Args:
obj: 游戏对象
"""
self.attached_object = obj
def detach_from_object(self):
"""从游戏对象分离"""
self.attached_object = None
class AudioEffectComponent(AudioComponent):
"""
音频效果组件
用于为音频源应用效果
"""
def __init__(self, plugin, name: str = ""):
super().__init__(plugin, name)
self.effect_id: Optional[str] = None
self.effect_type = ""
self.target_sound_id: Optional[str] = None
def initialize(self) -> bool:
"""初始化音频效果组件"""
return True
def cleanup(self):
"""清理音频效果组件"""
if self.effect_id:
self.plugin.audio_effect_processor.delete_effect(self.effect_id)
self.effect_id = None
def update(self, dt: float):
"""更新音频效果组件"""
if not self.enabled:
return
def create_effect(self, effect_type: str, parameters: Dict[str, Any]) -> bool:
"""
创建音频效果
Args:
effect_type: 效果类型
parameters: 效果参数
Returns:
是否创建成功
"""
try:
# 删除现有效果
if self.effect_id:
self.plugin.audio_effect_processor.delete_effect(self.effect_id)
# 创建新效果
self.effect_id = self.plugin.audio_effect_processor.create_effect(
effect_type, parameters)
if self.effect_id:
self.effect_type = effect_type
return True
else:
return False
except Exception as e:
print(f"✗ 创建音频效果失败: {e}")
return False
def apply_to_sound(self, sound_id: str) -> bool:
"""
应用效果到音效
Args:
sound_id: 音源ID
Returns:
是否应用成功
"""
if self.effect_id:
success = self.plugin.audio_effect_processor.apply_effect_to_sound(
sound_id, self.effect_id)
if success:
self.target_sound_id = sound_id
return success
return False
def remove_from_sound(self, sound_id: str) -> bool:
"""
从音效移除效果
Args:
sound_id: 音源ID
Returns:
是否移除成功
"""
if self.effect_id:
success = self.plugin.audio_effect_processor.remove_effect_from_sound(
sound_id, self.effect_id)
if success and self.target_sound_id == sound_id:
self.target_sound_id = None
return success
return False
def set_parameter(self, parameter: str, value: Any) -> bool:
"""
设置效果参数
Args:
parameter: 参数名
value: 参数值
Returns:
是否设置成功
"""
if self.effect_id:
return self.plugin.audio_effect_processor.set_effect_parameter(
self.effect_id, parameter, value)
return False