UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

258 lines (257 loc) • 10.8 kB
import { BufferGeometry, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SpriteMaterial, Vector3 } from "three"; import type { Behavior, Particle } from "three.quarks"; import { ParticleSystem as _ParticleSystem } from "three.quarks"; import { Context } from "../../engine/engine_setup.js"; import { Behaviour, GameObject } from "../Component.js"; import { ColorBySpeedModule, ColorOverLifetimeModule, EmissionModule, InheritVelocityModule, type IParticleSystem, LimitVelocityOverLifetimeModule, MainModule, NoiseModule, ParticleSystemRenderMode, RotationBySpeedModule, RotationOverLifetimeModule, ShapeModule, SizeBySpeedModule, SizeOverLifetimeModule, TextureSheetAnimationModule, TrailModule, VelocityOverLifetimeModule } from "./ParticleSystemModules.js"; export type { Particle as QParticle, Behavior as QParticleBehaviour, TrailParticle as QTrailParticle } from "three.quarks"; /** * Defines when a sub-emitter spawns particles relative to the parent particle's lifecycle. * Used to create complex effects like explosions on impact or trails following particles. */ export declare enum SubEmitterType { /** Sub-emitter triggers when the parent particle is born */ Birth = 0, /** Sub-emitter triggers when the parent particle collides */ Collision = 1, /** Sub-emitter triggers when the parent particle dies */ Death = 2, /** Sub-emitter triggers when the parent particle enters a trigger zone */ Trigger = 3, /** Sub-emitter is triggered manually via code */ Manual = 4 } /** @internal */ export declare class ParticleSystemRenderer extends Behaviour { renderMode?: ParticleSystemRenderMode; particleMaterial?: SpriteMaterial | MeshBasicMaterial; trailMaterial?: SpriteMaterial | MeshBasicMaterial; particleMesh?: Mesh | string; maxParticleSize: number; minParticleSize: number; velocityScale?: number; cameraVelocityScale?: number; lengthScale?: number; start(): void; get transparent(): boolean; getMaterial(trailEnabled?: boolean): MeshBasicMaterial | SpriteMaterial | undefined; getMesh(_renderMode?: ParticleSystemRenderMode): Mesh<BufferGeometry<import("three").NormalBufferAttributes>, MeshBasicMaterial | SpriteMaterial, import("three").Object3DEventMap>; } /** * Base class for custom particle behaviors. Extend this to create custom particle logic. * * Override `initialize()` to set up per-particle state when particles spawn. * Override `update()` to modify particles each frame (position, velocity, color, size, etc.). * Override `frameUpdate()` for logic that runs once per frame (not per particle). * * @example Custom wind effect * ```ts * class WindBehaviour extends ParticleSystemBaseBehaviour { * windStrength = 2; * windDirection = new Vector3(1, 0, 0); * * update(particle: Particle, delta: number) { * particle.velocity.addScaledVector(this.windDirection, this.windStrength * delta); * } * } * ``` * * @see {@link ParticleSystem.addBehaviour} to register your custom behavior * @link https://github.com/Alchemist0823/three.quarks */ export declare abstract class ParticleSystemBaseBehaviour implements Behavior { /** Reference to the particle system this behavior belongs to */ system: ParticleSystem; /** Access to the engine context for timing, input, etc. */ get context(): Context; constructor(ps?: ParticleSystem); /** Behavior type identifier used by three.quarks */ type: string; /** Called once when a particle is spawned. Use to initialize per-particle state. */ initialize(_particle: Particle): void; /** Called every frame for each active particle. Use to update particle properties. */ update(_particle: Particle, _delta: number): void; /** Called once per frame before particle updates. Use for shared calculations. */ frameUpdate(_delta: number): void; toJSON(): void; clone(): Behavior; /** Called when the particle system is reset. */ reset(): void; } export declare const $particleLife: unique symbol; /** * ParticleSystem efficiently handles the motion and rendering of many individual particles. * Use it for visual effects like fire, smoke, sparks, rain, magic spells, and more. * * ![](https://cloud.needle.tools/-/media/qz5nO-raa7dNb_XCBNxHmA.gif) * ![](https://cloud.needle.tools/-/media/IKOrLhesy1dKTfQQxx_pLA.gif) * * **Modules:** * Configure particle behavior through modules like {@link EmissionModule}, {@link ShapeModule}, * {@link ColorOverLifetimeModule}, {@link SizeOverLifetimeModule}, {@link VelocityOverLifetimeModule}, * {@link NoiseModule}, and {@link TrailModule}. * * **Custom behaviors:** * Add custom particle behaviors by extending {@link ParticleSystemBaseBehaviour} and * calling `addBehaviour()`. This gives you full control over particle initialization and updates. * * **Performance:** * Particles are batched together for fast, performant rendering even on low-end devices. * Needle Engine uses [three.quarks](https://github.com/Alchemist0823/three.quarks) internally. * * @example Basic playback control * ```ts * const ps = myObject.getComponent(ParticleSystem); * ps.play(); * ps.emit(10); // Emit 10 particles immediately * ps.pause(); * ps.stop(true, true); // Stop and clear all particles * ``` * * @example Custom particle behavior * ```ts * class GravityBehaviour extends ParticleSystemBaseBehaviour { * update(particle: Particle, delta: number) { * particle.velocity.y -= 9.8 * delta; * } * } * particleSystem.addBehaviour(new GravityBehaviour()); * ``` * * - Example: https://engine.needle.tools/samples/particles * - Example: https://engine.needle.tools/samples/particle-bursts * - Example: https://engine.needle.tools/samples/particles-on-collision * * @summary Handles the motion and rendering of many individual particles * @category Rendering * @group Components * @see {@link ParticleSystemBaseBehaviour} for custom particle behaviors * @see {@link EmissionModule} for emission configuration * @see {@link ShapeModule} for emission shape control * @see {@link TrailModule} for particle trails * @link https://engine.needle.tools/docs/features/particles.html */ export declare class ParticleSystem extends Behaviour implements IParticleSystem { play(includeChildren?: boolean): void; pause(includeChildren?: boolean): void; /** clear=true removes all emitted particles */ stop(includeChildren?: boolean, clear?: boolean): void; /** remove emitted particles and reset time */ reset(): void; private _state?; emit(count: number): void; get playOnAwake(): boolean; set playOnAwake(val: boolean); readonly colorOverLifetime: ColorOverLifetimeModule; readonly main: MainModule; readonly emission: EmissionModule; readonly sizeOverLifetime: SizeOverLifetimeModule; readonly shape: ShapeModule; readonly noise: NoiseModule; readonly trails: TrailModule; readonly velocityOverLifetime: VelocityOverLifetimeModule; readonly limitVelocityOverLifetime: LimitVelocityOverLifetimeModule; inheritVelocity: InheritVelocityModule; readonly colorBySpeed: ColorBySpeedModule; readonly textureSheetAnimation: TextureSheetAnimationModule; readonly rotationOverLifetime: RotationOverLifetimeModule; readonly rotationBySpeed: RotationBySpeedModule; readonly sizeBySpeed: SizeBySpeedModule; get renderer(): ParticleSystemRenderer; get isPlaying(): boolean; get currentParticles(): number; get maxParticles(): number; get time(): number; get duration(): number; get deltaTime(): number; get scale(): number; get cameraScale(): number; private _cameraScale; get container(): Object3D; get worldspace(): boolean; get localspace(): boolean; private __worldQuaternion; get worldQuaternion(): Quaternion; private _worldQuaternionInverted; get worldQuaternionInverted(): Quaternion; private _worldScale; get worldScale(): Vector3; private _worldPositionFrame; private _worldPos; get worldPos(): Vector3; get matrixWorld(): Matrix4; get isSubsystem(): boolean; /** Add a custom quarks behaviour to the particle system. * You can add a quarks.Behaviour type or derive from {@link ParticleSystemBaseBehaviour} * @link https://github.com/Alchemist0823/three.quarks * @example * ```typescript * class MyBehaviour extends ParticleSystemBaseBehaviour { * initialize(particle: Particle) { * // initialize the particle * } * update(particle: Particle, delta: number) { * // do something with the particle * } * } * * const system = gameObject.getComponent(ParticleSystem); * system.addBehaviour(new MyBehaviour()); * ``` */ addBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean; /** Remove a custom quarks behaviour from the particle system. **/ removeBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean; /** Removes all behaviours from the particle system * **Note:** this will also remove the default behaviours like SizeBehaviour, ColorBehaviour etc. */ removeAllBehaviours(): boolean; /** Get the underlying three.quarks particle system behaviours. This can be used to fully customize the behaviour of the particles. */ get behaviours(): Behavior[] | null; /** Get access to the underlying quarks particle system if you need more control * @link https://github.com/Alchemist0823/three.quarks */ get particleSystem(): _ParticleSystem | null; private _renderer; private _batchSystem?; private _particleSystem?; private _interface; private _container; private _time; private _isPlaying; private _isUsedAsSubsystem; private _didPreWarm; /** called from deserialization */ private set bursts(value); private _bursts?; /** called from deserialization */ private set subEmitterSystems(value); private _subEmitterSystems?; /** @internal */ onAfterDeserialize(_: any): void; /** @internal */ awake(): void; /** @internal */ start(): void; /** @internal */ onDestroy(): void; /** @internal */ onEnable(): void; onDisable(): void; /** @internal */ onBeforeRender(): void; private preWarm; private _lastBatchesCount; private onSimulate; private updateLayers; private onUpdate; private addSubParticleSystems; } /** @internal */ export declare class SubEmitterSystem { particleSystem?: ParticleSystem; emitProbability: number; properties?: number; type?: SubEmitterType; _deserialize(_context: Context, gameObject: GameObject): void; }