* feat(editor-core): 添加用户系统自动注册功能 - IUserCodeService 新增 registerSystems/unregisterSystems/getRegisteredSystems 方法 - UserCodeService 实现系统检测、实例化和场景注册逻辑 - ServiceRegistry 在预览开始时注册用户系统,停止时移除 - 热更新时自动重新加载用户系统 - 更新 System 脚本模板添加 @ECSSystem 装饰器 * feat(editor-core): 添加编辑器脚本支持(Inspector/Gizmo) - registerEditorExtensions 实际注册用户 Inspector 和 Gizmo - 添加 unregisterEditorExtensions 方法 - ServiceRegistry 在项目加载时编译并加载编辑器脚本 - 项目关闭时自动清理编辑器扩展 - 添加 Inspector 和 Gizmo 脚本创建模板 * feat(particle): 添加粒子系统和粒子编辑器 新增两个包: - @esengine/particle: 粒子系统核心库 - @esengine/particle-editor: 粒子编辑器 UI 粒子系统功能: - ECS 组件架构,支持播放/暂停/重置控制 - 7种发射形状:点、圆、环、矩形、边缘、线、锥形 - 5个动画模块:颜色渐变、缩放曲线、速度控制、旋转、噪声 - 纹理动画模块支持精灵表动画 - 3种混合模式:Normal、Additive、Multiply - 11个内置预设:火焰、烟雾、爆炸、雨、雪等 - 对象池优化,支持粒子复用 编辑器功能: - 实时 Canvas 预览,支持全屏和鼠标跟随 - 点击触发爆发效果(用于测试爆炸类特效) - 渐变编辑器:可视化颜色关键帧编辑 - 曲线编辑器:支持缩放曲线和缓动函数 - 预设浏览器:快速应用内置预设 - 模块开关:独立启用/禁用各个模块 - Vector2 样式输入(重力 X/Y) * feat(particle): 完善粒子系统核心功能 1. Burst 定时爆发系统 - BurstConfig 接口支持时间、数量、循环次数、间隔 - 运行时自动处理定时爆发 - 支持无限循环爆发 2. 速度曲线模块 (VelocityOverLifetimeModule) - 6种曲线类型:Constant、Linear、EaseIn、EaseOut、EaseInOut、Custom - 自定义关键帧曲线支持 - 附加速度 X/Y - 轨道速度和径向速度 3. 碰撞边界模块 (CollisionModule) - 矩形和圆形边界类型 - 3种碰撞行为:Kill、Bounce、Wrap - 反弹系数和最小速度阈值 - 反弹时生命损失 * feat(particle): 添加力场模块、碰撞模块和世界/本地空间支持 - 新增 ForceFieldModule 支持风力、吸引点、漩涡、湍流四种力场类型 - 新增 SimulationSpace 枚举支持世界空间和本地空间切换 - ParticleSystemComponent 集成力场模块和空间模式 - 粒子编辑器添加 Collision 和 ForceField 模块的 UI 编辑支持 - 新增 Vortex、Leaves、Bouncing 三个预设展示新功能 - 编辑器预览实现完整的碰撞和力场效果 * fix(particle): 移除未使用的 transform 循环变量
775 lines
15 KiB
TypeScript
775 lines
15 KiB
TypeScript
/**
|
|
* 粒子效果预设
|
|
* Particle effect presets
|
|
*
|
|
* Collection of pre-configured particle system settings.
|
|
* 预配置的粒子系统设置集合。
|
|
*/
|
|
|
|
import { EmissionShape, type ColorValue } from '../ParticleEmitter';
|
|
import { ParticleBlendMode, SimulationSpace } from '../ParticleSystemComponent';
|
|
import { ForceFieldType } from '../modules/ForceFieldModule';
|
|
import { BoundaryType, CollisionBehavior } from '../modules/CollisionModule';
|
|
|
|
/**
|
|
* 辅助函数:十六进制转 ColorValue
|
|
* Helper: hex to ColorValue
|
|
*/
|
|
function hexToColor(hex: string, alpha = 1): ColorValue {
|
|
const h = hex.replace('#', '');
|
|
return {
|
|
r: parseInt(h.slice(0, 2), 16) / 255,
|
|
g: parseInt(h.slice(2, 4), 16) / 255,
|
|
b: parseInt(h.slice(4, 6), 16) / 255,
|
|
a: alpha,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 预设配置接口
|
|
* Preset configuration interface
|
|
*/
|
|
export interface ParticlePreset {
|
|
/** 预设名称 | Preset name */
|
|
name: string;
|
|
/** 预设描述 | Preset description */
|
|
description: string;
|
|
/** 预设分类 | Preset category */
|
|
category: PresetCategory;
|
|
/** 预设图标 | Preset icon */
|
|
icon?: string;
|
|
|
|
// 基础属性 | Basic properties
|
|
maxParticles: number;
|
|
looping: boolean;
|
|
duration: number;
|
|
playbackSpeed: number;
|
|
|
|
// 发射属性 | Emission properties
|
|
emissionRate: number;
|
|
emissionShape: EmissionShape;
|
|
shapeRadius: number;
|
|
shapeWidth: number;
|
|
shapeHeight: number;
|
|
shapeAngle: number;
|
|
|
|
// 粒子属性 | Particle properties
|
|
lifetimeMin: number;
|
|
lifetimeMax: number;
|
|
speedMin: number;
|
|
speedMax: number;
|
|
direction: number;
|
|
directionSpread: number;
|
|
scaleMin: number;
|
|
scaleMax: number;
|
|
gravityX: number;
|
|
gravityY: number;
|
|
|
|
// 颜色属性 | Color properties
|
|
startColor: ColorValue;
|
|
endColor?: ColorValue;
|
|
startAlpha: number;
|
|
endAlpha: number;
|
|
endScale: number;
|
|
|
|
// 渲染属性 | Rendering properties
|
|
particleSize: number;
|
|
blendMode: ParticleBlendMode;
|
|
|
|
// 可选模块 | Optional modules
|
|
simulationSpace?: SimulationSpace;
|
|
forceField?: {
|
|
type: ForceFieldType;
|
|
strength: number;
|
|
directionX?: number;
|
|
directionY?: number;
|
|
centerX?: number;
|
|
centerY?: number;
|
|
inwardStrength?: number;
|
|
frequency?: number;
|
|
};
|
|
collision?: {
|
|
boundaryType: BoundaryType;
|
|
behavior: CollisionBehavior;
|
|
radius?: number;
|
|
bounceFactor?: number;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 预设分类
|
|
* Preset category
|
|
*/
|
|
export enum PresetCategory {
|
|
/** 自然效果 | Natural effects */
|
|
Nature = 'nature',
|
|
/** 魔法效果 | Magic effects */
|
|
Magic = 'magic',
|
|
/** 爆炸效果 | Explosion effects */
|
|
Explosion = 'explosion',
|
|
/** 环境效果 | Environment effects */
|
|
Environment = 'environment',
|
|
/** UI 效果 | UI effects */
|
|
UI = 'ui',
|
|
/** 基础效果 | Basic effects */
|
|
Basic = 'basic',
|
|
}
|
|
|
|
/**
|
|
* 火焰预设
|
|
* Fire preset
|
|
*/
|
|
export const FirePreset: ParticlePreset = {
|
|
name: 'Fire',
|
|
description: 'Realistic fire effect with hot colors',
|
|
category: PresetCategory.Nature,
|
|
icon: 'Flame',
|
|
|
|
maxParticles: 200,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 40,
|
|
emissionShape: EmissionShape.Rectangle,
|
|
shapeRadius: 20,
|
|
shapeWidth: 30,
|
|
shapeHeight: 5,
|
|
shapeAngle: 30,
|
|
|
|
lifetimeMin: 0.5,
|
|
lifetimeMax: 1.2,
|
|
speedMin: 80,
|
|
speedMax: 150,
|
|
direction: 90,
|
|
directionSpread: 25,
|
|
scaleMin: 0.8,
|
|
scaleMax: 1.2,
|
|
gravityX: 0,
|
|
gravityY: 50,
|
|
|
|
startColor: hexToColor('#ff6600'),
|
|
endColor: hexToColor('#ff0000'),
|
|
startAlpha: 1,
|
|
endAlpha: 0,
|
|
endScale: 0.3,
|
|
|
|
particleSize: 16,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
};
|
|
|
|
/**
|
|
* 烟雾预设
|
|
* Smoke preset
|
|
*/
|
|
export const SmokePreset: ParticlePreset = {
|
|
name: 'Smoke',
|
|
description: 'Soft rising smoke effect',
|
|
category: PresetCategory.Nature,
|
|
icon: 'Cloud',
|
|
|
|
maxParticles: 150,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 15,
|
|
emissionShape: EmissionShape.Circle,
|
|
shapeRadius: 15,
|
|
shapeWidth: 30,
|
|
shapeHeight: 30,
|
|
shapeAngle: 30,
|
|
|
|
lifetimeMin: 2,
|
|
lifetimeMax: 4,
|
|
speedMin: 20,
|
|
speedMax: 50,
|
|
direction: 90,
|
|
directionSpread: 20,
|
|
scaleMin: 0.5,
|
|
scaleMax: 1,
|
|
gravityX: 10,
|
|
gravityY: -5,
|
|
|
|
startColor: hexToColor('#888888'),
|
|
endColor: hexToColor('#cccccc'),
|
|
startAlpha: 0.6,
|
|
endAlpha: 0,
|
|
endScale: 2.5,
|
|
|
|
particleSize: 32,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 火花预设
|
|
* Sparkle preset
|
|
*/
|
|
export const SparklePreset: ParticlePreset = {
|
|
name: 'Sparkle',
|
|
description: 'Twinkling star-like particles',
|
|
category: PresetCategory.Magic,
|
|
icon: 'Sparkles',
|
|
|
|
maxParticles: 100,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 20,
|
|
emissionShape: EmissionShape.Circle,
|
|
shapeRadius: 40,
|
|
shapeWidth: 40,
|
|
shapeHeight: 40,
|
|
shapeAngle: 360,
|
|
|
|
lifetimeMin: 0.3,
|
|
lifetimeMax: 0.8,
|
|
speedMin: 10,
|
|
speedMax: 30,
|
|
direction: 90,
|
|
directionSpread: 360,
|
|
scaleMin: 0.5,
|
|
scaleMax: 1.5,
|
|
gravityX: 0,
|
|
gravityY: -20,
|
|
|
|
startColor: hexToColor('#ffffff'),
|
|
startAlpha: 1,
|
|
endAlpha: 0,
|
|
endScale: 0,
|
|
|
|
particleSize: 8,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
};
|
|
|
|
/**
|
|
* 爆炸预设
|
|
* Explosion preset
|
|
*/
|
|
export const ExplosionPreset: ParticlePreset = {
|
|
name: 'Explosion',
|
|
description: 'Radial burst explosion effect',
|
|
category: PresetCategory.Explosion,
|
|
icon: 'Zap',
|
|
|
|
maxParticles: 300,
|
|
looping: false,
|
|
duration: 1,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 0, // Burst only
|
|
emissionShape: EmissionShape.Point,
|
|
shapeRadius: 5,
|
|
shapeWidth: 10,
|
|
shapeHeight: 10,
|
|
shapeAngle: 360,
|
|
|
|
lifetimeMin: 0.3,
|
|
lifetimeMax: 0.8,
|
|
speedMin: 200,
|
|
speedMax: 400,
|
|
direction: 0,
|
|
directionSpread: 360,
|
|
scaleMin: 0.8,
|
|
scaleMax: 1.2,
|
|
gravityX: 0,
|
|
gravityY: 200,
|
|
|
|
startColor: hexToColor('#ffaa00'),
|
|
endColor: hexToColor('#ff4400'),
|
|
startAlpha: 1,
|
|
endAlpha: 0,
|
|
endScale: 0.2,
|
|
|
|
particleSize: 12,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
};
|
|
|
|
/**
|
|
* 雨滴预设
|
|
* Rain preset
|
|
*/
|
|
export const RainPreset: ParticlePreset = {
|
|
name: 'Rain',
|
|
description: 'Falling rain drops',
|
|
category: PresetCategory.Environment,
|
|
icon: 'CloudRain',
|
|
|
|
maxParticles: 500,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 80,
|
|
emissionShape: EmissionShape.Line,
|
|
shapeRadius: 200,
|
|
shapeWidth: 400,
|
|
shapeHeight: 10,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 0.5,
|
|
lifetimeMax: 1,
|
|
speedMin: 400,
|
|
speedMax: 600,
|
|
direction: -80,
|
|
directionSpread: 5,
|
|
scaleMin: 0.8,
|
|
scaleMax: 1,
|
|
gravityX: 0,
|
|
gravityY: 0,
|
|
|
|
startColor: hexToColor('#88ccff'),
|
|
startAlpha: 0.7,
|
|
endAlpha: 0.3,
|
|
endScale: 1,
|
|
|
|
particleSize: 6,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 雪花预设
|
|
* Snow preset
|
|
*/
|
|
export const SnowPreset: ParticlePreset = {
|
|
name: 'Snow',
|
|
description: 'Gently falling snowflakes',
|
|
category: PresetCategory.Environment,
|
|
icon: 'Snowflake',
|
|
|
|
maxParticles: 300,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 30,
|
|
emissionShape: EmissionShape.Line,
|
|
shapeRadius: 200,
|
|
shapeWidth: 400,
|
|
shapeHeight: 10,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 3,
|
|
lifetimeMax: 6,
|
|
speedMin: 20,
|
|
speedMax: 50,
|
|
direction: -90,
|
|
directionSpread: 30,
|
|
scaleMin: 0.3,
|
|
scaleMax: 1,
|
|
gravityX: 0,
|
|
gravityY: 0,
|
|
|
|
startColor: hexToColor('#ffffff'),
|
|
startAlpha: 0.9,
|
|
endAlpha: 0.5,
|
|
endScale: 1,
|
|
|
|
particleSize: 8,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 魔法光环预设
|
|
* Magic aura preset
|
|
*/
|
|
export const MagicAuraPreset: ParticlePreset = {
|
|
name: 'Magic Aura',
|
|
description: 'Mystical swirling aura',
|
|
category: PresetCategory.Magic,
|
|
icon: 'Star',
|
|
|
|
maxParticles: 100,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 20,
|
|
emissionShape: EmissionShape.Circle,
|
|
shapeRadius: 50,
|
|
shapeWidth: 50,
|
|
shapeHeight: 50,
|
|
shapeAngle: 360,
|
|
|
|
lifetimeMin: 1,
|
|
lifetimeMax: 2,
|
|
speedMin: 5,
|
|
speedMax: 15,
|
|
direction: 0,
|
|
directionSpread: 360,
|
|
scaleMin: 0.5,
|
|
scaleMax: 1,
|
|
gravityX: 0,
|
|
gravityY: -30,
|
|
|
|
startColor: hexToColor('#aa55ff'),
|
|
endColor: hexToColor('#5555ff'),
|
|
startAlpha: 0.8,
|
|
endAlpha: 0,
|
|
endScale: 0.5,
|
|
|
|
particleSize: 10,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
};
|
|
|
|
/**
|
|
* 灰尘预设
|
|
* Dust preset
|
|
*/
|
|
export const DustPreset: ParticlePreset = {
|
|
name: 'Dust',
|
|
description: 'Floating dust particles',
|
|
category: PresetCategory.Environment,
|
|
icon: 'Wind',
|
|
|
|
maxParticles: 200,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 15,
|
|
emissionShape: EmissionShape.Rectangle,
|
|
shapeRadius: 100,
|
|
shapeWidth: 200,
|
|
shapeHeight: 150,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 4,
|
|
lifetimeMax: 8,
|
|
speedMin: 5,
|
|
speedMax: 15,
|
|
direction: 45,
|
|
directionSpread: 90,
|
|
scaleMin: 0.2,
|
|
scaleMax: 0.6,
|
|
gravityX: 10,
|
|
gravityY: -2,
|
|
|
|
startColor: hexToColor('#ccbb99'),
|
|
startAlpha: 0.3,
|
|
endAlpha: 0.1,
|
|
endScale: 1.2,
|
|
|
|
particleSize: 4,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 泡泡预设
|
|
* Bubble preset
|
|
*/
|
|
export const BubblePreset: ParticlePreset = {
|
|
name: 'Bubbles',
|
|
description: 'Rising soap bubbles',
|
|
category: PresetCategory.Environment,
|
|
icon: 'CircleDot',
|
|
|
|
maxParticles: 50,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 5,
|
|
emissionShape: EmissionShape.Rectangle,
|
|
shapeRadius: 40,
|
|
shapeWidth: 80,
|
|
shapeHeight: 20,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 2,
|
|
lifetimeMax: 4,
|
|
speedMin: 30,
|
|
speedMax: 60,
|
|
direction: 90,
|
|
directionSpread: 20,
|
|
scaleMin: 0.5,
|
|
scaleMax: 1.5,
|
|
gravityX: 10,
|
|
gravityY: -10,
|
|
|
|
startColor: hexToColor('#aaddff'),
|
|
startAlpha: 0.5,
|
|
endAlpha: 0.2,
|
|
endScale: 1.3,
|
|
|
|
particleSize: 16,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 星轨预设
|
|
* Star trail preset
|
|
*/
|
|
export const StarTrailPreset: ParticlePreset = {
|
|
name: 'Star Trail',
|
|
description: 'Glowing star trail effect',
|
|
category: PresetCategory.Magic,
|
|
icon: 'Sparkle',
|
|
|
|
maxParticles: 150,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 50,
|
|
emissionShape: EmissionShape.Point,
|
|
shapeRadius: 2,
|
|
shapeWidth: 4,
|
|
shapeHeight: 4,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 0.2,
|
|
lifetimeMax: 0.6,
|
|
speedMin: 5,
|
|
speedMax: 20,
|
|
direction: 180,
|
|
directionSpread: 30,
|
|
scaleMin: 0.8,
|
|
scaleMax: 1.2,
|
|
gravityX: 0,
|
|
gravityY: 0,
|
|
|
|
startColor: hexToColor('#ffff88'),
|
|
endColor: hexToColor('#ffaa44'),
|
|
startAlpha: 1,
|
|
endAlpha: 0,
|
|
endScale: 0.1,
|
|
|
|
particleSize: 6,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
};
|
|
|
|
/**
|
|
* 默认预设(简单)
|
|
* Default preset (simple)
|
|
*/
|
|
export const DefaultPreset: ParticlePreset = {
|
|
name: 'Default',
|
|
description: 'Basic particle emitter',
|
|
category: PresetCategory.Basic,
|
|
icon: 'Circle',
|
|
|
|
maxParticles: 100,
|
|
looping: true,
|
|
duration: 5,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 10,
|
|
emissionShape: EmissionShape.Point,
|
|
shapeRadius: 0,
|
|
shapeWidth: 0,
|
|
shapeHeight: 0,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 1,
|
|
lifetimeMax: 2,
|
|
speedMin: 50,
|
|
speedMax: 100,
|
|
direction: 90,
|
|
directionSpread: 30,
|
|
scaleMin: 1,
|
|
scaleMax: 1,
|
|
gravityX: 0,
|
|
gravityY: 0,
|
|
|
|
startColor: hexToColor('#ffffff'),
|
|
startAlpha: 1,
|
|
endAlpha: 0,
|
|
endScale: 1,
|
|
|
|
particleSize: 8,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
};
|
|
|
|
/**
|
|
* 漩涡预设
|
|
* Vortex preset
|
|
*/
|
|
export const VortexPreset: ParticlePreset = {
|
|
name: 'Vortex',
|
|
description: 'Swirling vortex with inward pull',
|
|
category: PresetCategory.Magic,
|
|
icon: 'Tornado',
|
|
|
|
maxParticles: 200,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 30,
|
|
emissionShape: EmissionShape.Circle,
|
|
shapeRadius: 80,
|
|
shapeWidth: 160,
|
|
shapeHeight: 160,
|
|
shapeAngle: 360,
|
|
|
|
lifetimeMin: 2,
|
|
lifetimeMax: 4,
|
|
speedMin: 10,
|
|
speedMax: 30,
|
|
direction: 0,
|
|
directionSpread: 360,
|
|
scaleMin: 0.5,
|
|
scaleMax: 1,
|
|
gravityX: 0,
|
|
gravityY: 0,
|
|
|
|
startColor: hexToColor('#88ccff'),
|
|
startAlpha: 0.8,
|
|
endAlpha: 0,
|
|
endScale: 0.3,
|
|
|
|
particleSize: 8,
|
|
blendMode: ParticleBlendMode.Additive,
|
|
|
|
forceField: {
|
|
type: ForceFieldType.Vortex,
|
|
strength: 150,
|
|
centerX: 0,
|
|
centerY: 0,
|
|
inwardStrength: 30,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 落叶预设
|
|
* Falling leaves preset
|
|
*/
|
|
export const LeavesPreset: ParticlePreset = {
|
|
name: 'Leaves',
|
|
description: 'Falling leaves with wind effect',
|
|
category: PresetCategory.Environment,
|
|
icon: 'Leaf',
|
|
|
|
maxParticles: 100,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 8,
|
|
emissionShape: EmissionShape.Line,
|
|
shapeRadius: 200,
|
|
shapeWidth: 400,
|
|
shapeHeight: 10,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 4,
|
|
lifetimeMax: 8,
|
|
speedMin: 30,
|
|
speedMax: 60,
|
|
direction: -90,
|
|
directionSpread: 20,
|
|
scaleMin: 0.6,
|
|
scaleMax: 1.2,
|
|
gravityX: 0,
|
|
gravityY: 20,
|
|
|
|
startColor: hexToColor('#dd8844'),
|
|
startAlpha: 0.9,
|
|
endAlpha: 0.6,
|
|
endScale: 1,
|
|
|
|
particleSize: 12,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
|
|
forceField: {
|
|
type: ForceFieldType.Turbulence,
|
|
strength: 40,
|
|
frequency: 0.5,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 弹球预设
|
|
* Bouncing balls preset
|
|
*/
|
|
export const BouncingPreset: ParticlePreset = {
|
|
name: 'Bouncing',
|
|
description: 'Bouncing particles in a box',
|
|
category: PresetCategory.Basic,
|
|
icon: 'Circle',
|
|
|
|
maxParticles: 50,
|
|
looping: true,
|
|
duration: 10,
|
|
playbackSpeed: 1,
|
|
|
|
emissionRate: 5,
|
|
emissionShape: EmissionShape.Point,
|
|
shapeRadius: 0,
|
|
shapeWidth: 0,
|
|
shapeHeight: 0,
|
|
shapeAngle: 0,
|
|
|
|
lifetimeMin: 8,
|
|
lifetimeMax: 12,
|
|
speedMin: 100,
|
|
speedMax: 200,
|
|
direction: 90,
|
|
directionSpread: 60,
|
|
scaleMin: 0.8,
|
|
scaleMax: 1.2,
|
|
gravityX: 0,
|
|
gravityY: 200,
|
|
|
|
startColor: hexToColor('#66aaff'),
|
|
startAlpha: 1,
|
|
endAlpha: 0.8,
|
|
endScale: 1,
|
|
|
|
particleSize: 16,
|
|
blendMode: ParticleBlendMode.Normal,
|
|
|
|
collision: {
|
|
boundaryType: BoundaryType.Rectangle,
|
|
behavior: CollisionBehavior.Bounce,
|
|
bounceFactor: 0.8,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 所有预设
|
|
* All presets
|
|
*/
|
|
export const AllPresets: ParticlePreset[] = [
|
|
DefaultPreset,
|
|
FirePreset,
|
|
SmokePreset,
|
|
SparklePreset,
|
|
ExplosionPreset,
|
|
RainPreset,
|
|
SnowPreset,
|
|
MagicAuraPreset,
|
|
DustPreset,
|
|
BubblePreset,
|
|
StarTrailPreset,
|
|
VortexPreset,
|
|
LeavesPreset,
|
|
BouncingPreset,
|
|
];
|
|
|
|
/**
|
|
* 按分类获取预设
|
|
* Get presets by category
|
|
*/
|
|
export function getPresetsByCategory(category: PresetCategory): ParticlePreset[] {
|
|
return AllPresets.filter(p => p.category === category);
|
|
}
|
|
|
|
/**
|
|
* 获取预设名称列表
|
|
* Get preset name list
|
|
*/
|
|
export function getPresetNames(): string[] {
|
|
return AllPresets.map(p => p.name);
|
|
}
|
|
|
|
/**
|
|
* 按名称获取预设
|
|
* Get preset by name
|
|
*/
|
|
export function getPresetByName(name: string): ParticlePreset | undefined {
|
|
return AllPresets.find(p => p.name === name);
|
|
}
|