Files
esengine/packages/rendering/particle/src/Particle.ts
YHH 155411e743 refactor: reorganize package structure and decouple framework packages (#338)
* refactor: reorganize package structure and decouple framework packages

## Package Structure Reorganization
- Reorganized 55 packages into categorized subdirectories:
  - packages/framework/ - Generic framework (Laya/Cocos compatible)
  - packages/engine/ - ESEngine core modules
  - packages/rendering/ - Rendering modules (WASM dependent)
  - packages/physics/ - Physics modules
  - packages/streaming/ - World streaming
  - packages/network-ext/ - Network extensions
  - packages/editor/ - Editor framework and plugins
  - packages/rust/ - Rust WASM engine
  - packages/tools/ - Build tools and SDK

## Framework Package Decoupling
- Decoupled behavior-tree and blueprint packages from ESEngine dependencies
- Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent)
- ESEngine-specific code moved to esengine/ subpath exports
- Framework packages now usable with Cocos/Laya without ESEngine

## CI Configuration
- Updated CI to only type-check and lint framework packages
- Added type-check:framework and lint:framework scripts

## Breaking Changes
- Package import paths changed due to directory reorganization
- ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine')

* fix: update es-engine file path after directory reorganization

* docs: update README to focus on framework over engine

* ci: only build framework packages, remove Rust/WASM dependencies

* fix: remove esengine subpath from behavior-tree and blueprint builds

ESEngine integration code will only be available in full engine builds.
Framework packages are now purely engine-agnostic.

* fix: move network-protocols to framework, build both in CI

* fix: update workflow paths from packages/core to packages/framework/core

* fix: exclude esengine folder from type-check in behavior-tree and blueprint

* fix: update network tsconfig references to new paths

* fix: add test:ci:framework to only test framework packages in CI

* fix: only build core and math npm packages in CI

* fix: exclude test files from CodeQL and fix string escaping security issue
2025-12-26 14:50:35 +08:00

249 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 粒子数据结构
* Particle data structure
*
* Represents a single particle with all its runtime state.
* 表示单个粒子及其所有运行时状态。
*/
export interface Particle {
/** 是否存活 | Whether particle is alive */
alive: boolean;
/** 位置X | Position X */
x: number;
/** 位置Y | Position Y */
y: number;
/** 速度X | Velocity X */
vx: number;
/** 速度Y | Velocity Y */
vy: number;
/** 加速度X | Acceleration X */
ax: number;
/** 加速度Y | Acceleration Y */
ay: number;
/** 旋转角度(弧度)| Rotation (radians) */
rotation: number;
/** 角速度 | Angular velocity */
angularVelocity: number;
/** 缩放X | Scale X */
scaleX: number;
/** 缩放Y | Scale Y */
scaleY: number;
/** 颜色R (0-1) | Color R (0-1) */
r: number;
/** 颜色G (0-1) | Color G (0-1) */
g: number;
/** 颜色B (0-1) | Color B (0-1) */
b: number;
/** 透明度 (0-1) | Alpha (0-1) */
alpha: number;
/** 当前生命时间(秒)| Current lifetime (seconds) */
age: number;
/** 总生命时间(秒)| Total lifetime (seconds) */
lifetime: number;
/** 初始缩放X | Initial scale X */
startScaleX: number;
/** 初始缩放Y | Initial scale Y */
startScaleY: number;
/** 初始颜色R | Initial color R */
startR: number;
/** 初始颜色G | Initial color G */
startG: number;
/** 初始颜色B | Initial color B */
startB: number;
/** 初始透明度 | Initial alpha */
startAlpha: number;
// ============= 模块运行时状态 | Module Runtime State =============
// 这些字段由各模块在运行时设置 | These fields are set by modules at runtime
/** 初始速度XVelocityOverLifetimeModule 使用)| Initial velocity X (used by VelocityOverLifetimeModule) */
startVx?: number;
/** 初始速度YVelocityOverLifetimeModule 使用)| Initial velocity Y (used by VelocityOverLifetimeModule) */
startVy?: number;
/** 动画帧索引TextureSheetAnimationModule 使用)| Animation frame index (used by TextureSheetAnimationModule) */
_animFrame?: number;
/** 动画图块列数TextureSheetAnimationModule 使用)| Animation tiles X (used by TextureSheetAnimationModule) */
_animTilesX?: number;
/** 动画图块行数TextureSheetAnimationModule 使用)| Animation tiles Y (used by TextureSheetAnimationModule) */
_animTilesY?: number;
/** 自定义数据槽 | Custom data slot */
userData?: unknown;
}
/**
* 创建新粒子
* Create a new particle
*/
export function createParticle(): Particle {
return {
alive: false,
x: 0,
y: 0,
vx: 0,
vy: 0,
ax: 0,
ay: 0,
rotation: 0,
angularVelocity: 0,
scaleX: 1,
scaleY: 1,
r: 1,
g: 1,
b: 1,
alpha: 1,
age: 0,
lifetime: 1,
startScaleX: 1,
startScaleY: 1,
startR: 1,
startG: 1,
startB: 1,
startAlpha: 1
};
}
/**
* 重置粒子状态
* Reset particle state
*/
export function resetParticle(p: Particle): void {
p.alive = false;
p.x = 0;
p.y = 0;
p.vx = 0;
p.vy = 0;
p.ax = 0;
p.ay = 0;
p.rotation = 0;
p.angularVelocity = 0;
p.scaleX = 1;
p.scaleY = 1;
p.r = 1;
p.g = 1;
p.b = 1;
p.alpha = 1;
p.age = 0;
p.lifetime = 1;
p.startScaleX = 1;
p.startScaleY = 1;
p.startR = 1;
p.startG = 1;
p.startB = 1;
p.startAlpha = 1;
p.userData = undefined;
}
/**
* 粒子池
* Particle pool for efficient memory management
*/
export class ParticlePool {
private _particles: Particle[] = [];
private _capacity: number;
private _activeCount: number = 0;
constructor(capacity: number) {
this._capacity = capacity;
for (let i = 0; i < capacity; i++) {
this._particles.push(createParticle());
}
}
/** 池容量 | Pool capacity */
get capacity(): number {
return this._capacity;
}
/** 活跃粒子数 | Active particle count */
get activeCount(): number {
return this._activeCount;
}
/** 所有粒子(包括不活跃的)| All particles (including inactive) */
get particles(): readonly Particle[] {
return this._particles;
}
/**
* 获取一个空闲粒子
* Get an inactive particle
*/
spawn(): Particle | null {
for (const p of this._particles) {
if (!p.alive) {
p.alive = true;
this._activeCount++;
return p;
}
}
return null;
}
/**
* 回收粒子
* Recycle a particle
*/
recycle(p: Particle): void {
if (p.alive) {
p.alive = false;
this._activeCount--;
}
}
/**
* 回收所有粒子
* Recycle all particles
*/
recycleAll(): void {
for (const p of this._particles) {
p.alive = false;
}
this._activeCount = 0;
}
/**
* 遍历活跃粒子
* Iterate over active particles
*/
forEachActive(callback: (p: Particle, index: number) => void): void {
let index = 0;
for (const p of this._particles) {
if (p.alive) {
callback(p, index++);
}
}
}
/**
* 调整池大小
* Resize the pool
*/
resize(newCapacity: number): void {
if (newCapacity > this._capacity) {
for (let i = this._capacity; i < newCapacity; i++) {
this._particles.push(createParticle());
}
} else if (newCapacity < this._capacity) {
// 回收超出容量的活跃粒子 | Recycle active particles beyond capacity
for (let i = newCapacity; i < this._capacity; i++) {
if (this._particles[i].alive) {
this._activeCount--;
}
}
this._particles.length = newCapacity;
}
this._capacity = newCapacity;
}
}