EG/plugins/user/weather_season_system/effects/visual_effects.py
2025-12-12 16:16:15 +08:00

624 lines
21 KiB
Python

"""
视觉效果系统
负责管理天气和季节的视觉效果,如粒子效果、光照变化等
"""
import time
import random
from typing import Dict, Any, List, Optional
import math
class VisualEffects:
"""
视觉效果系统
负责管理天气和季节的视觉效果,包括粒子效果、光照变化、材质变化等
"""
def __init__(self, plugin):
"""
初始化视觉效果系统
Args:
plugin: 天气和季节系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 粒子效果配置
self.particle_effects = {
'rain': {
'name': '雨滴',
'particle_count': 1000,
'particle_size': (0.1, 0.5),
'particle_speed': (5.0, 15.0),
'particle_lifetime': (0.5, 2.0),
'particle_color': (0.7, 0.7, 1.0, 0.8),
'emission_rate': 100,
'spread': (100.0, 50.0), # 水平和垂直扩散范围
'affected_by_wind': True
},
'snow': {
'name': '雪花',
'particle_count': 800,
'particle_size': (0.2, 1.0),
'particle_speed': (0.5, 3.0),
'particle_lifetime': (3.0, 8.0),
'particle_color': (1.0, 1.0, 1.0, 0.9),
'emission_rate': 80,
'spread': (100.0, 50.0),
'affected_by_wind': True
},
'storm': {
'name': '暴风雨',
'particle_count': 1500,
'particle_size': (0.1, 0.8),
'particle_speed': (8.0, 25.0),
'particle_lifetime': (0.3, 1.5),
'particle_color': (0.5, 0.5, 0.8, 0.7),
'emission_rate': 200,
'spread': (150.0, 80.0),
'affected_by_wind': True
},
'hail': {
'name': '冰雹',
'particle_count': 500,
'particle_size': (0.3, 1.5),
'particle_speed': (10.0, 20.0),
'particle_lifetime': (1.0, 3.0),
'particle_color': (0.9, 0.9, 1.0, 0.9),
'emission_rate': 50,
'spread': (80.0, 60.0),
'affected_by_wind': True
},
'light_fog': {
'name': '薄雾',
'particle_count': 200,
'particle_size': (5.0, 15.0),
'particle_speed': (0.1, 0.5),
'particle_lifetime': (5.0, 15.0),
'particle_color': (0.8, 0.8, 0.8, 0.3),
'emission_rate': 20,
'spread': (200.0, 100.0),
'affected_by_wind': True
},
'heavy_fog': {
'name': '浓雾',
'particle_count': 500,
'particle_size': (10.0, 30.0),
'particle_speed': (0.05, 0.3),
'particle_lifetime': (10.0, 30.0),
'particle_color': (0.7, 0.7, 0.7, 0.5),
'emission_rate': 50,
'spread': (300.0, 150.0),
'affected_by_wind': True
},
'wind_debris': {
'name': '风中碎片',
'particle_count': 100,
'particle_size': (0.5, 2.0),
'particle_speed': (2.0, 10.0),
'particle_lifetime': (1.0, 5.0),
'particle_color': (0.6, 0.5, 0.4, 0.7),
'emission_rate': 10,
'spread': (100.0, 30.0),
'affected_by_wind': True
}
}
# 当前激活的视觉效果
self.active_effects = {}
# 材质变化配置
self.material_effects = {
'wet_surface': {
'name': '湿润表面',
'roughness_multiplier': 0.7,
'metallic_multiplier': 1.2,
'specular_multiplier': 1.5,
'normal_strength': 0.8
},
'snow_cover': {
'name': '积雪覆盖',
'roughness_multiplier': 1.3,
'metallic_multiplier': 0.8,
'specular_multiplier': 0.5,
'normal_strength': 1.2
}
}
# 光照效果配置
self.lighting_effects = {
'lightning': {
'name': '闪电',
'intensity': 5.0,
'color': (0.8, 0.8, 1.0),
'duration': 0.1,
'frequency': 0.05 # 每秒闪电概率
}
}
# 视觉效果更新配置
self.update_interval = 0.05 # 更新间隔(秒)
self.last_update_time = 0.0
# 粒子系统配置
self.particle_system_config = {
'max_particles': 10000,
'particle_lod': 'medium', # 'low', 'medium', 'high'
'distance_fade': True,
'collision_detection': False
}
# 统计信息
self.stats = {
'effects_activated': 0,
'particles_generated': 0,
'effects_deactivated': 0,
'total_effect_time': 0.0
}
print("✓ 视觉效果系统已创建")
def initialize(self) -> bool:
"""
初始化视觉效果系统
Returns:
是否初始化成功
"""
try:
self.initialized = True
print("✓ 视觉效果系统初始化完成")
return True
except Exception as e:
print(f"✗ 视觉效果系统初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用视觉效果系统
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 视觉效果系统未初始化")
return False
self.enabled = True
print("✓ 视觉效果系统已启用")
return True
except Exception as e:
print(f"✗ 视觉效果系统启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用视觉效果系统"""
try:
self.enabled = False
self._deactivate_all_effects()
print("✓ 视觉效果系统已禁用")
except Exception as e:
print(f"✗ 视觉效果系统禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理视觉效果系统资源"""
try:
self.disable()
self.initialized = False
print("✓ 视觉效果系统资源已清理")
except Exception as e:
print(f"✗ 视觉效果系统资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新视觉效果系统状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 更新计时器
self.last_update_time += dt
if self.last_update_time < self.update_interval:
return
# 重置更新计时器
self.last_update_time = 0.0
# 更新激活的视觉效果
self._update_active_effects(dt)
# 根据当前天气激活相应的视觉效果
self._update_weather_effects()
# 更新统计信息
self.stats['total_effect_time'] += dt
except Exception as e:
print(f"✗ 视觉效果系统更新失败: {e}")
import traceback
traceback.print_exc()
def _update_active_effects(self, dt: float):
"""
更新激活的视觉效果
Args:
dt: 时间增量
"""
try:
effects_to_remove = []
for effect_name, effect_data in self.active_effects.items():
# 更新效果持续时间
effect_data['duration'] -= dt
# 检查效果是否应该结束
if effect_data['duration'] <= 0 and not effect_data['persistent']:
effects_to_remove.append(effect_name)
# 移除过期的效果
for effect_name in effects_to_remove:
self._deactivate_effect(effect_name)
except Exception as e:
print(f"✗ 激活效果更新失败: {e}")
def _update_weather_effects(self):
"""根据当前天气更新视觉效果"""
try:
if not self.plugin.weather_manager:
return
current_weather = self.plugin.weather_manager.get_current_weather()
weather_info = self.plugin.weather_manager.get_weather_info(current_weather)
if not weather_info:
return
# 获取天气对应的粒子效果
particle_effect = weather_info.get('particle_effect')
# 检查是否需要激活或更新粒子效果
if particle_effect and particle_effect in self.particle_effects:
# 检查效果是否已经激活
if particle_effect not in self.active_effects:
# 激活粒子效果
self._activate_particle_effect(particle_effect)
else:
# 更新现有效果的参数
self._update_particle_effect_parameters(particle_effect)
else:
# 检查是否需要停用粒子效果
active_particle_effects = [
name for name in self.active_effects.keys()
if name in self.particle_effects
]
for effect_name in active_particle_effects:
self._deactivate_effect(effect_name)
except Exception as e:
print(f"✗ 天气效果更新失败: {e}")
def _activate_particle_effect(self, effect_name: str):
"""
激活粒子效果
Args:
effect_name: 粒子效果名称
"""
try:
if effect_name not in self.particle_effects:
return
effect_config = self.particle_effects[effect_name]
# 创建效果数据
effect_data = {
'name': effect_config['name'],
'type': 'particle',
'config': effect_config,
'start_time': time.time(),
'duration': float('inf'), # 持续到手动停用
'persistent': True,
'intensity': 1.0
}
# 添加到激活效果列表
self.active_effects[effect_name] = effect_data
# 更新统计信息
self.stats['effects_activated'] += 1
self.stats['particles_generated'] += effect_config['particle_count']
print(f"✓ 粒子效果已激活: {effect_config['name']}")
except Exception as e:
print(f"✗ 粒子效果激活失败: {e}")
def _update_particle_effect_parameters(self, effect_name: str):
"""
更新粒子效果参数
Args:
effect_name: 粒子效果名称
"""
try:
if effect_name not in self.active_effects:
return
# 在实际实现中,这里会根据当前天气强度等因素更新粒子效果参数
# 例如:根据降水强度调整雨滴数量和速度
pass
except Exception as e:
print(f"✗ 粒子效果参数更新失败: {e}")
def _deactivate_effect(self, effect_name: str):
"""
停用视觉效果
Args:
effect_name: 效果名称
"""
try:
if effect_name in self.active_effects:
effect_data = self.active_effects.pop(effect_name)
# 更新统计信息
self.stats['effects_deactivated'] += 1
print(f"✓ 视觉效果已停用: {effect_data['name']}")
except Exception as e:
print(f"✗ 视觉效果停用失败: {e}")
def _deactivate_all_effects(self):
"""停用所有视觉效果"""
try:
effect_names = list(self.active_effects.keys())
for effect_name in effect_names:
self._deactivate_effect(effect_name)
except Exception as e:
print(f"✗ 所有效果停用失败: {e}")
def activate_effect(self, effect_name: str, duration: float = float('inf'), intensity: float = 1.0):
"""
激活视觉效果
Args:
effect_name: 效果名称
duration: 持续时间(秒),默认为无限
intensity: 效果强度(0-1)
"""
try:
# 检查效果类型
if effect_name in self.particle_effects:
self._activate_particle_effect(effect_name)
else:
# 创建通用效果数据
effect_data = {
'name': effect_name,
'type': 'generic',
'start_time': time.time(),
'duration': duration,
'persistent': duration == float('inf'),
'intensity': max(0.0, min(1.0, intensity))
}
self.active_effects[effect_name] = effect_data
self.stats['effects_activated'] += 1
print(f"✓ 视觉效果已激活: {effect_name}")
except Exception as e:
print(f"✗ 视觉效果激活失败: {e}")
def deactivate_effect(self, effect_name: str):
"""
停用视觉效果
Args:
effect_name: 效果名称
"""
self._deactivate_effect(effect_name)
def set_effect_intensity(self, effect_name: str, intensity: float):
"""
设置效果强度
Args:
effect_name: 效果名称
intensity: 效果强度(0-1)
"""
try:
if effect_name in self.active_effects:
self.active_effects[effect_name]['intensity'] = max(0.0, min(1.0, intensity))
print(f"✓ 效果强度已设置: {effect_name} = {intensity}")
else:
print(f"✗ 效果未激活: {effect_name}")
except Exception as e:
print(f"✗ 效果强度设置失败: {e}")
def get_active_effects(self) -> List[str]:
"""
获取激活的视觉效果列表
Returns:
激活的效果名称列表
"""
return list(self.active_effects.keys())
def get_effect_info(self, effect_name: str) -> Optional[Dict[str, Any]]:
"""
获取效果信息
Args:
effect_name: 效果名称
Returns:
效果信息字典或None
"""
try:
# 检查粒子效果
if effect_name in self.particle_effects:
return self.particle_effects[effect_name].copy()
# 检查激活的效果
if effect_name in self.active_effects:
return self.active_effects[effect_name].copy()
return None
except Exception as e:
print(f"✗ 效果信息获取失败: {e}")
return None
def get_particle_effects_list(self) -> List[str]:
"""
获取所有粒子效果列表
Returns:
粒子效果名称列表
"""
return list(self.particle_effects.keys())
def get_material_effects_list(self) -> List[str]:
"""
获取所有材质效果列表
Returns:
材质效果名称列表
"""
return list(self.material_effects.keys())
def apply_material_effect(self, material_name: str, effect_name: str):
"""
应用材质效果
Args:
material_name: 材质名称
effect_name: 效果名称
"""
try:
if effect_name in self.material_effects:
effect_config = self.material_effects[effect_name]
# 在实际实现中,这里会应用材质效果到指定材质
print(f"✓ 材质效果已应用: {material_name} + {effect_config['name']}")
else:
print(f"✗ 无效的材质效果: {effect_name}")
except Exception as e:
print(f"✗ 材质效果应用失败: {e}")
def remove_material_effect(self, material_name: str, effect_name: str):
"""
移除材质效果
Args:
material_name: 材质名称
effect_name: 效果名称
"""
try:
# 在实际实现中,这里会从指定材质移除效果
print(f"✓ 材质效果已移除: {material_name} - {effect_name}")
except Exception as e:
print(f"✗ 材质效果移除失败: {e}")
def trigger_lighting_effect(self, effect_name: str):
"""
触发瞬时光照效果
Args:
effect_name: 光照效果名称
"""
try:
if effect_name in self.lighting_effects:
effect_config = self.lighting_effects[effect_name]
# 在实际实现中,这里会触发瞬时光照效果
print(f"✓ 光照效果已触发: {effect_config['name']}")
else:
print(f"✗ 无效的光照效果: {effect_name}")
except Exception as e:
print(f"✗ 光照效果触发失败: {e}")
def set_particle_system_config(self, config: Dict[str, Any]):
"""
设置粒子系统配置
Args:
config: 配置字典
"""
self.particle_system_config.update(config)
print(f"✓ 粒子系统配置已更新: {self.particle_system_config}")
def get_particle_system_config(self) -> Dict[str, Any]:
"""
获取粒子系统配置
Returns:
粒子系统配置字典
"""
return self.particle_system_config.copy()
def get_stats(self) -> Dict[str, Any]:
"""
获取统计信息
Returns:
统计信息字典
"""
return self.stats.copy()
def reset_stats(self):
"""重置统计信息"""
self.stats = {
'effects_activated': 0,
'particles_generated': 0,
'effects_deactivated': 0,
'total_effect_time': 0.0
}
print("✓ 视觉效果系统统计信息已重置")
def set_update_interval(self, interval: float):
"""
设置更新间隔
Args:
interval: 更新间隔(秒)
"""
self.update_interval = max(0.01, interval)
print(f"✓ 视觉效果更新间隔设置为: {interval}")
def is_effect_active(self, effect_name: str) -> bool:
"""
检查效果是否激活
Args:
effect_name: 效果名称
Returns:
效果是否激活
"""
return effect_name in self.active_effects