692 lines
26 KiB
Python
692 lines
26 KiB
Python
"""
|
||
粒子编辑器
|
||
提供可视化的粒子效果编辑功能
|
||
"""
|
||
|
||
import json
|
||
from typing import Dict, Optional, Any
|
||
from panda3d.core import Vec3, Point3
|
||
|
||
class ParticleEditor:
|
||
"""
|
||
粒子编辑器
|
||
提供实时编辑粒子效果的功能
|
||
"""
|
||
|
||
def __init__(self, world, particle_manager):
|
||
"""
|
||
初始化粒子编辑器
|
||
|
||
Args:
|
||
world: 3D世界对象
|
||
particle_manager: 粒子管理器
|
||
"""
|
||
self.world = world
|
||
self.particle_manager = particle_manager
|
||
self.visible = False
|
||
|
||
# 当前编辑的发射器
|
||
self.current_emitter_id = None
|
||
self.current_emitter = None
|
||
|
||
# 编辑器GUI元素
|
||
self.gui_elements = []
|
||
self.parameter_controls = {}
|
||
self.effect_type_buttons = {}
|
||
|
||
# 预览模式
|
||
self.preview_mode = True
|
||
self.auto_update = True
|
||
|
||
# 编辑器状态
|
||
self.editor_position = Point3(0, 0, 0)
|
||
self.editor_enabled = False
|
||
|
||
# 编辑参数
|
||
self.edit_parameters = {
|
||
'emitter_type': 'fire',
|
||
'emission_rate': 50,
|
||
'particle_lifetime': 2.0,
|
||
'start_color': Vec3(1.0, 0.3, 0.0),
|
||
'end_color': Vec3(1.0, 0.0, 0.0),
|
||
'start_size': 0.2,
|
||
'end_size': 0.8,
|
||
'velocity': Vec3(0, 0, 2),
|
||
'velocity_variation': 0.5,
|
||
'gravity_scale': -0.2,
|
||
'air_resistance': 0.02,
|
||
'bounce_factor': 0.5,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.3,
|
||
'rotation_enabled': False,
|
||
'rotation_speed': 0.0
|
||
}
|
||
|
||
print("✓ 粒子编辑器初始化完成")
|
||
|
||
def toggle_visibility(self):
|
||
"""切换编辑器可见性"""
|
||
if self.visible:
|
||
self.hide()
|
||
else:
|
||
self.show()
|
||
|
||
def show(self):
|
||
"""显示编辑器"""
|
||
if self.visible:
|
||
return
|
||
|
||
self.visible = True
|
||
self._create_editor_gui()
|
||
|
||
# 如果没有当前发射器,创建一个默认的
|
||
if not self.current_emitter_id:
|
||
self.create_new_effect()
|
||
|
||
print("✓ 粒子编辑器已显示")
|
||
|
||
def hide(self):
|
||
"""隐藏编辑器"""
|
||
if not self.visible:
|
||
return
|
||
|
||
self.visible = False
|
||
self._cleanup_editor_gui()
|
||
|
||
print("✓ 粒子编辑器已隐藏")
|
||
|
||
def _create_editor_gui(self):
|
||
"""创建编辑器GUI"""
|
||
try:
|
||
if not hasattr(self.world, 'gui_manager') or not self.world.gui_manager:
|
||
print("⚠ GUI管理器不可用,无法创建编辑器界面")
|
||
return
|
||
|
||
gui_manager = self.world.gui_manager
|
||
|
||
# 创建编辑器面板标题
|
||
panel = gui_manager.createGUIButton(
|
||
pos=(0.7, 0, 0.95),
|
||
text="粒子编辑器",
|
||
size=0.06
|
||
)
|
||
self.gui_elements.append(panel)
|
||
|
||
# 创建效果类型选择按钮
|
||
effect_types = ["火焰", "烟雾", "爆炸", "水花", "魔法", "雪花", "自定义"]
|
||
for i, effect_type in enumerate(effect_types):
|
||
button = gui_manager.createGUIButton(
|
||
pos=(0.7, 0, 0.88 - i * 0.06),
|
||
text=effect_type,
|
||
size=0.04
|
||
)
|
||
self.gui_elements.append(button)
|
||
self.effect_type_buttons[effect_type] = button
|
||
self.world.accept(f"editor_effect_{effect_type}",
|
||
lambda t=effect_type: self.set_effect_type(t))
|
||
|
||
# 创建参数控制面板
|
||
self._create_parameter_controls()
|
||
|
||
# 创建操作按钮
|
||
self._create_action_buttons()
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 编辑器GUI创建失败: {e}")
|
||
|
||
def _create_parameter_controls(self):
|
||
"""创建参数控制界面"""
|
||
if not hasattr(self.world, 'gui_manager') or not self.world.gui_manager:
|
||
return
|
||
|
||
gui_manager = self.world.gui_manager
|
||
|
||
# 基础参数控制
|
||
parameters = [
|
||
("发射率", "emission_rate", 0, 500, 1),
|
||
("生命周期", "particle_lifetime", 0.1, 10.0, 0.1),
|
||
("起始尺寸", "start_size", 0.01, 5.0, 0.01),
|
||
("结束尺寸", "end_size", 0.01, 5.0, 0.01),
|
||
("速度变化", "velocity_variation", 0.0, 5.0, 0.1),
|
||
("重力缩放", "gravity_scale", -5.0, 5.0, 0.1),
|
||
("空气阻力", "air_resistance", 0.0, 1.0, 0.01),
|
||
("反弹系数", "bounce_factor", 0.0, 1.0, 0.1),
|
||
("发射器半径", "emitter_radius", 0.0, 5.0, 0.1),
|
||
("旋转速度", "rotation_speed", -10.0, 10.0, 0.1)
|
||
]
|
||
|
||
for i, (name, param, min_val, max_val, step) in enumerate(parameters):
|
||
y_pos = 0.8 - i * 0.055
|
||
|
||
# 参数标签
|
||
label = gui_manager.createGUIButton(
|
||
pos=(0.75, 0, y_pos),
|
||
text=f"{name}:",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(label)
|
||
|
||
# 参数值显示
|
||
value_label = gui_manager.createGUIButton(
|
||
pos=(0.88, 0, y_pos),
|
||
text=f"{self.edit_parameters[param]:.2f}",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(value_label)
|
||
|
||
# 减少按钮
|
||
dec_button = gui_manager.createGUIButton(
|
||
pos=(0.83, 0, y_pos),
|
||
text="-",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(dec_button)
|
||
|
||
# 增加按钮
|
||
inc_button = gui_manager.createGUIButton(
|
||
pos=(0.93, 0, y_pos),
|
||
text="+",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(inc_button)
|
||
|
||
# 注册事件
|
||
self.world.accept(f"dec_{param}", lambda p=param, s=step: self._decrease_parameter(p, s))
|
||
self.world.accept(f"inc_{param}", lambda p=param, s=step: self._increase_parameter(p, s))
|
||
|
||
# 存储控制信息
|
||
self.parameter_controls[param] = {
|
||
'name': name,
|
||
'min': min_val,
|
||
'max': max_val,
|
||
'step': step,
|
||
'value_label': value_label,
|
||
'dec_button': dec_button,
|
||
'inc_button': inc_button
|
||
}
|
||
|
||
# 布尔型参数
|
||
bool_params = [
|
||
("启用旋转", "rotation_enabled"),
|
||
("自动更新", "auto_update"),
|
||
("预览模式", "preview_mode")
|
||
]
|
||
|
||
for i, (name, param) in enumerate(bool_params):
|
||
y_pos = 0.25 - i * 0.055
|
||
|
||
# 参数标签
|
||
label = gui_manager.createGUIButton(
|
||
pos=(0.75, 0, y_pos),
|
||
text=f"{name}:",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(label)
|
||
|
||
# 开关按钮
|
||
switch_button = gui_manager.createGUIButton(
|
||
pos=(0.88, 0, y_pos),
|
||
text="开" if self.edit_parameters.get(param, False) else "关",
|
||
size=0.03
|
||
)
|
||
self.gui_elements.append(switch_button)
|
||
|
||
# 注册事件
|
||
self.world.accept(f"toggle_{param}", lambda p=param: self._toggle_boolean_parameter(p))
|
||
|
||
self.parameter_controls[param] = {
|
||
'name': name,
|
||
'value_label': switch_button,
|
||
'type': 'boolean'
|
||
}
|
||
|
||
def _create_action_buttons(self):
|
||
"""创建操作按钮"""
|
||
if not hasattr(self.world, 'gui_manager') or not self.world.gui_manager:
|
||
return
|
||
|
||
gui_manager = self.world.gui_manager
|
||
|
||
actions = [
|
||
("应用更改", 0.15, self.apply_changes),
|
||
("重置参数", 0.09, self.reset_parameters),
|
||
("创建新效果", 0.03, self.create_new_effect),
|
||
("删除当前", -0.03, self.delete_current_effect),
|
||
("保存预设", -0.09, self.save_preset),
|
||
("加载预设", -0.15, self.load_preset)
|
||
]
|
||
|
||
for name, y_offset, callback in actions:
|
||
button = gui_manager.createGUIButton(
|
||
pos=(0.82, 0, y_offset),
|
||
text=name,
|
||
size=0.035
|
||
)
|
||
self.gui_elements.append(button)
|
||
self.world.accept(f"action_{name}", callback)
|
||
|
||
def _cleanup_editor_gui(self):
|
||
"""清理编辑器GUI"""
|
||
try:
|
||
if hasattr(self.world, 'gui_manager') and self.world.gui_manager:
|
||
gui_manager = self.world.gui_manager
|
||
|
||
for element in self.gui_elements:
|
||
gui_manager.deleteGUIElement(element)
|
||
|
||
# 清理事件监听
|
||
for param in self.parameter_controls:
|
||
self.world.ignore(f"dec_{param}")
|
||
self.world.ignore(f"inc_{param}")
|
||
|
||
for param in ['rotation_enabled', 'auto_update', 'preview_mode']:
|
||
self.world.ignore(f"toggle_{param}")
|
||
|
||
self.world.ignore("action_应用更改")
|
||
self.world.ignore("action_重置参数")
|
||
self.world.ignore("action_创建新效果")
|
||
self.world.ignore("action_删除当前")
|
||
self.world.ignore("action_保存预设")
|
||
self.world.ignore("action_加载预设")
|
||
|
||
self.gui_elements.clear()
|
||
self.parameter_controls.clear()
|
||
self.effect_type_buttons.clear()
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 编辑器GUI清理失败: {e}")
|
||
|
||
def _decrease_parameter(self, param_name: str, step: float):
|
||
"""减少参数值"""
|
||
if param_name in self.edit_parameters:
|
||
control = self.parameter_controls[param_name]
|
||
current_value = self.edit_parameters[param_name]
|
||
new_value = max(control['min'], current_value - step)
|
||
self.edit_parameters[param_name] = new_value
|
||
|
||
# 更新显示
|
||
if 'value_label' in control:
|
||
control['value_label'].setText(f"{new_value:.2f}")
|
||
|
||
# 自动应用更改
|
||
if self.auto_update:
|
||
self.apply_changes()
|
||
|
||
def _increase_parameter(self, param_name: str, step: float):
|
||
"""增加参数值"""
|
||
if param_name in self.edit_parameters:
|
||
control = self.parameter_controls[param_name]
|
||
current_value = self.edit_parameters[param_name]
|
||
new_value = min(control['max'], current_value + step)
|
||
self.edit_parameters[param_name] = new_value
|
||
|
||
# 更新显示
|
||
if 'value_label' in control:
|
||
control['value_label'].setText(f"{new_value:.2f}")
|
||
|
||
# 自动应用更改
|
||
if self.auto_update:
|
||
self.apply_changes()
|
||
|
||
def _toggle_boolean_parameter(self, param_name: str):
|
||
"""切换布尔参数"""
|
||
if param_name in self.edit_parameters:
|
||
current_value = self.edit_parameters[param_name]
|
||
new_value = not current_value
|
||
self.edit_parameters[param_name] = new_value
|
||
|
||
# 更新显示
|
||
control = self.parameter_controls[param_name]
|
||
if 'value_label' in control:
|
||
control['value_label'].setText("开" if new_value else "关")
|
||
|
||
# 特殊处理某些参数
|
||
if param_name == 'auto_update':
|
||
self.auto_update = new_value
|
||
elif param_name == 'preview_mode':
|
||
self.preview_mode = new_value
|
||
|
||
# 自动应用更改
|
||
if self.auto_update:
|
||
self.apply_changes()
|
||
|
||
def create_new_effect(self, effect_type: str = "火焰"):
|
||
"""创建新的粒子效果"""
|
||
# 删除当前效果
|
||
if self.current_emitter_id:
|
||
self.particle_manager.remove_emitter(self.current_emitter_id)
|
||
|
||
# 在摄像机前方创建
|
||
camera_pos = self.world.camera.getPos()
|
||
camera_forward = self.world.camera.getNetTransform().getMat().getRow3(1)
|
||
position = camera_pos + camera_forward * 5
|
||
|
||
# 根据类型设置参数
|
||
self.set_effect_type(effect_type)
|
||
|
||
# 创建发射器
|
||
config = self.edit_parameters.copy()
|
||
config['emitter_type'] = effect_type.lower()
|
||
|
||
self.current_emitter_id = self.particle_manager.create_emitter(
|
||
effect_type.lower(),
|
||
position,
|
||
config
|
||
)
|
||
|
||
self.current_emitter = self.particle_manager.get_emitter(self.current_emitter_id)
|
||
self.editor_position = position
|
||
|
||
print(f"✓ 创建新粒子效果: {effect_type}")
|
||
|
||
def set_effect_type(self, effect_type: str):
|
||
"""设置效果类型"""
|
||
self.edit_parameters['emitter_type'] = effect_type.lower()
|
||
|
||
# 根据类型预设参数
|
||
if effect_type == "火焰":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 50,
|
||
'particle_lifetime': 2.0,
|
||
'start_color': Vec3(1.0, 0.3, 0.0),
|
||
'end_color': Vec3(1.0, 0.0, 0.0),
|
||
'start_size': 0.2,
|
||
'end_size': 0.8,
|
||
'velocity': Vec3(0, 0, 2),
|
||
'velocity_variation': 0.5,
|
||
'gravity_scale': -0.2,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.3
|
||
})
|
||
elif effect_type == "烟雾":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 30,
|
||
'particle_lifetime': 4.0,
|
||
'start_color': Vec3(0.8, 0.8, 0.8),
|
||
'end_color': Vec3(0.3, 0.3, 0.3),
|
||
'start_size': 0.3,
|
||
'end_size': 1.5,
|
||
'velocity': Vec3(0, 0, 1),
|
||
'velocity_variation': 0.3,
|
||
'gravity_scale': -0.1,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.5
|
||
})
|
||
elif effect_type == "爆炸":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 200,
|
||
'burst_count': 100,
|
||
'particle_lifetime': 1.5,
|
||
'start_color': Vec3(1.0, 0.8, 0.0),
|
||
'end_color': Vec3(1.0, 0.2, 0.0),
|
||
'start_size': 0.1,
|
||
'end_size': 0.5,
|
||
'velocity': Vec3(0, 0, 0),
|
||
'velocity_variation': 2.0,
|
||
'gravity_scale': 0.5,
|
||
'duration': 0.2,
|
||
'emitter_shape': 'sphere',
|
||
'emitter_radius': 0.1
|
||
})
|
||
elif effect_type == "水花":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 80,
|
||
'particle_lifetime': 3.0,
|
||
'start_color': Vec3(0.2, 0.6, 1.0),
|
||
'end_color': Vec3(0.1, 0.3, 0.8),
|
||
'start_size': 0.1,
|
||
'end_size': 0.05,
|
||
'velocity': Vec3(0, 0, 3),
|
||
'velocity_variation': 1.0,
|
||
'gravity_scale': 2.0,
|
||
'bounce_factor': 0.3,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.2
|
||
})
|
||
elif effect_type == "魔法":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 40,
|
||
'particle_lifetime': 3.0,
|
||
'start_color': Vec3(0.5, 0.2, 1.0),
|
||
'end_color': Vec3(0.8, 0.6, 1.0),
|
||
'start_size': 0.15,
|
||
'end_size': 0.05,
|
||
'velocity': Vec3(0, 0, 0.5),
|
||
'velocity_variation': 0.8,
|
||
'gravity_scale': -0.5,
|
||
'rotation_enabled': True,
|
||
'rotation_speed': 2.0,
|
||
'emitter_shape': 'sphere',
|
||
'emitter_radius': 0.8
|
||
})
|
||
elif effect_type == "雪花":
|
||
self.edit_parameters.update({
|
||
'emission_rate': 60,
|
||
'particle_lifetime': 8.0,
|
||
'start_color': Vec3(0.9, 0.9, 1.0),
|
||
'end_color': Vec3(0.9, 0.9, 1.0),
|
||
'start_size': 0.05,
|
||
'end_size': 0.05,
|
||
'velocity': Vec3(0, 0, -1),
|
||
'velocity_variation': 0.5,
|
||
'gravity_scale': 0.8,
|
||
'air_resistance': 0.1,
|
||
'bounce_factor': 0.2,
|
||
'emitter_shape': 'box',
|
||
'emitter_dimensions': Vec3(20, 20, 1)
|
||
})
|
||
|
||
# 更新GUI显示
|
||
self._update_parameter_display()
|
||
|
||
def _update_parameter_display(self):
|
||
"""更新参数显示"""
|
||
for param_name, control in self.parameter_controls.items():
|
||
if param_name in self.edit_parameters:
|
||
value = self.edit_parameters[param_name]
|
||
if control.get('type') == 'boolean':
|
||
if 'value_label' in control:
|
||
control['value_label'].setText("开" if value else "关")
|
||
else:
|
||
if 'value_label' in control:
|
||
if isinstance(value, (int, float)):
|
||
control['value_label'].setText(f"{value:.2f}")
|
||
else:
|
||
control['value_label'].setText(str(value))
|
||
|
||
def apply_changes(self):
|
||
"""应用更改到当前效果"""
|
||
if not self.current_emitter_id or not self.current_emitter:
|
||
print("⚠ 没有选中的效果")
|
||
return
|
||
|
||
# 更新发射器参数
|
||
try:
|
||
# 更新发射器配置
|
||
for param_name, value in self.edit_parameters.items():
|
||
if hasattr(self.current_emitter, param_name):
|
||
setattr(self.current_emitter, param_name, value)
|
||
|
||
print("✓ 参数已应用")
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 参数应用失败: {e}")
|
||
|
||
def reset_parameters(self):
|
||
"""重置参数为默认值"""
|
||
# 重新设置当前类型参数
|
||
current_type = self.edit_parameters.get('emitter_type', 'fire')
|
||
self.set_effect_type(current_type.capitalize())
|
||
print("✓ 参数已重置")
|
||
|
||
def delete_current_effect(self):
|
||
"""删除当前效果"""
|
||
if self.current_emitter_id:
|
||
self.particle_manager.remove_emitter(self.current_emitter_id)
|
||
self.current_emitter_id = None
|
||
self.current_emitter = None
|
||
print("✓ 当前效果已删除")
|
||
|
||
def update_parameter(self, param_name: str, value: float):
|
||
"""更新参数值"""
|
||
if not self.current_emitter or param_name not in self.parameter_controls:
|
||
return
|
||
|
||
# 更新控制信息
|
||
control = self.parameter_controls[param_name]
|
||
|
||
# 更新GUI显示
|
||
if 'value_label' in control:
|
||
try:
|
||
control['value_label'].setText(f"{value:.2f}")
|
||
except:
|
||
pass
|
||
|
||
# 应用到发射器
|
||
self._apply_parameter_to_emitter(param_name, value)
|
||
|
||
if self.auto_update:
|
||
print(f"✓ 更新参数 {param_name}: {value}")
|
||
|
||
def _apply_parameter_to_emitter(self, param_name: str, value: float):
|
||
"""将参数应用到发射器"""
|
||
if not self.current_emitter:
|
||
return
|
||
|
||
try:
|
||
if param_name == "emission_rate":
|
||
self.current_emitter.emission_rate = value
|
||
elif param_name == "particle_lifetime":
|
||
self.current_emitter.particle_lifetime = value
|
||
elif param_name == "start_size":
|
||
self.current_emitter.start_size = value
|
||
elif param_name == "end_size":
|
||
self.current_emitter.end_size = value
|
||
elif param_name == "velocity_variation":
|
||
self.current_emitter.velocity_variation = value
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 参数应用失败 {param_name}: {e}")
|
||
|
||
def set_emitter_position(self, position: Point3):
|
||
"""设置发射器位置"""
|
||
self.editor_position = position
|
||
if self.current_emitter:
|
||
self.current_emitter.set_position(position)
|
||
|
||
def get_current_config(self) -> Dict[str, Any]:
|
||
"""获取当前配置"""
|
||
config = self.edit_parameters.copy()
|
||
config['emitter_type'] = self.edit_parameters.get('emitter_type', 'fire')
|
||
config['position'] = [
|
||
self.editor_position.x,
|
||
self.editor_position.y,
|
||
self.editor_position.z
|
||
]
|
||
return config
|
||
|
||
def load_config(self, config: Dict[str, Any]):
|
||
"""加载配置"""
|
||
try:
|
||
# 设置位置
|
||
if 'position' in config:
|
||
pos = config['position']
|
||
position = Point3(pos[0], pos[1], pos[2])
|
||
self.set_emitter_position(position)
|
||
|
||
# 更新编辑参数
|
||
for param_name, value in config.items():
|
||
if param_name in self.edit_parameters:
|
||
self.edit_parameters[param_name] = value
|
||
|
||
# 更新GUI显示
|
||
self._update_parameter_display()
|
||
|
||
# 应用到当前效果
|
||
if self.auto_update:
|
||
self.apply_changes()
|
||
|
||
print("✓ 配置加载完成")
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 配置加载失败: {e}")
|
||
|
||
def save_preset(self, name: str = "自定义预设") -> bool:
|
||
"""保存预设"""
|
||
try:
|
||
config = self.get_current_config()
|
||
|
||
# 这里应该调用预设管理器保存
|
||
print(f"✓ 保存预设 '{name}':")
|
||
print(json.dumps(config, indent=2, default=str))
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 预设保存失败: {e}")
|
||
return False
|
||
|
||
def load_preset(self, name: str = "经典火焰") -> bool:
|
||
"""加载预设"""
|
||
try:
|
||
# 这里应该调用预设管理器加载
|
||
# 简化实现:使用默认配置
|
||
default_configs = {
|
||
"经典火焰": {
|
||
'emitter_type': 'fire',
|
||
'emission_rate': 50,
|
||
'particle_lifetime': 2.0,
|
||
'start_color': [1.0, 0.3, 0.0],
|
||
'end_color': [1.0, 0.0, 0.0],
|
||
'start_size': 0.2,
|
||
'end_size': 0.8,
|
||
'velocity': [0, 0, 2],
|
||
'velocity_variation': 0.5,
|
||
'gravity_scale': -0.2,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.3
|
||
},
|
||
"浓密烟雾": {
|
||
'emitter_type': 'smoke',
|
||
'emission_rate': 30,
|
||
'particle_lifetime': 4.0,
|
||
'start_color': [0.8, 0.8, 0.8],
|
||
'end_color': [0.3, 0.3, 0.3],
|
||
'start_size': 0.3,
|
||
'end_size': 1.5,
|
||
'velocity': [0, 0, 1],
|
||
'velocity_variation': 0.3,
|
||
'gravity_scale': -0.1,
|
||
'emitter_shape': 'circle',
|
||
'emitter_radius': 0.5
|
||
}
|
||
}
|
||
|
||
if name in default_configs:
|
||
self.load_config(default_configs[name])
|
||
print(f"✓ 加载预设 '{name}'")
|
||
return True
|
||
else:
|
||
print(f"⚠ 预设 '{name}' 不存在")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"⚠ 预设加载失败: {e}")
|
||
return False
|
||
|
||
def reset_to_defaults(self):
|
||
"""重置为默认值"""
|
||
if self.current_emitter:
|
||
# 重新创建当前类型的发射器
|
||
effect_type = self.current_emitter.emitter_type
|
||
self.create_new_effect(effect_type.capitalize())
|
||
|
||
def cleanup(self):
|
||
"""清理编辑器资源"""
|
||
self.hide()
|
||
|
||
if self.current_emitter_id:
|
||
self.particle_manager.remove_emitter(self.current_emitter_id)
|
||
|
||
self.current_emitter_id = None
|
||
self.current_emitter = None |