459 lines
12 KiB
Python
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 |