diff --git a/cocos/particle/Impl.ts b/cocos/particle/Impl.ts index 89d84c5eaff..d4741fea982 100644 --- a/cocos/particle/Impl.ts +++ b/cocos/particle/Impl.ts @@ -1,4 +1,4 @@ -import { CustomDataMode, BoxShapeEmitFrom, PlaybackState, NoiseQuality, ConeShapeEmitFrom, CoordinateSpace, CurveRangeMode, GradientRangeMode, AnimationMode, TimeMode, RowMode, TextureMode, ScalingMode } from './define'; +import { CustomDataMode, BoxShapeEmitFrom, PlaybackState, NoiseQuality, ConeShapeEmitFrom, CoordinateSpace, CurveRangeMode, GradientRangeMode, AnimationMode, TimeMode, RowMode, TextureMode, ScalingMode, ParticleSystemModuleStage } from './define'; export declare namespace Impl { export class ParticleSystem { @@ -23,6 +23,9 @@ export declare namespace Impl { setCapacity(capacity: number): void; setAutoRandomSeed(autoRandomSeed: boolean): void; setRandomSeed(seed: number): void; + + addModule(module: ParticleSystemModule): void; + removeModule(module: ParticleSystemModule): void; } export class ParticleSystemManager { @@ -63,6 +66,8 @@ export declare namespace Impl { export class ParticleSystemModule { setEnabled(enable: boolean): void; + setStage(stage: ParticleSystemModuleStage): void; + setExecutionOrder(executionOrder: number): void; dispose(): void; } diff --git a/cocos/particle/define.ts b/cocos/particle/define.ts index 4cd79287cd9..e2a32b356fe 100644 --- a/cocos/particle/define.ts +++ b/cocos/particle/define.ts @@ -209,6 +209,24 @@ export enum ScalingMode { SHAPE, } +export enum ShapeType { + SPHERE, + CONE, + DONUT, + BOX, + CIRCLE, + EDGE, + RECTANGLE +} + +export enum ParticleSystemModuleStage { + EMISSION, + SPAWN, + PRE_SOLVE_UPDATE, + POST_SOLVE_UPDATE, + RENDER +} + export const meshPosition = new Attribute(AttributeName.ATTR_POSITION, Format.RGB32F, false, 0); // mesh position export const meshUv = new Attribute(AttributeName.ATTR_TEX_COORD, Format.RGB32F, false, 0); // mesh uv export const meshNormal = new Attribute(AttributeName.ATTR_NORMAL, Format.RGB32F, false, 0); // mesh normal @@ -217,6 +235,6 @@ export const meshColorRGBA32 = new Attribute(AttributeName.ATTR_COLOR, Format.RG export const particlePosition = new Attribute('a_particle_position', Format.RGB32F, false, 1, true); // particle position export const particleRotation = new Attribute('a_particle_rotation', Format.RGB32F, false, 1, true); // particle rotation export const particleSize = new Attribute('a_particle_size', Format.RGB32F, false, 1, true); // particle size -export const particleColor = new Attribute('a_particle_color', Format.RGBA8, true, 1, true); // particle color -export const particleSubUVIndex = new Attribute('a_particle_sub_uv_index', Format.R32F, false, 1, true); // particle sub uv index -export const particleVelocity = new Attribute('a_particle_velocity', Format.RGB32F, false, 1, true); // particle velocity +export const particleColor = new Attribute('a_particle_color', Format.RGBA8, true, 1, true); // particle color +export const particleSubUVIndex = new Attribute('a_particle_sub_uv_index', Format.R32F, false, 1, true); // particle sub uv index +export const particleVelocity = new Attribute('a_particle_velocity', Format.RGB32F, false, 1, true); // particle velocity diff --git a/cocos/particle/modules/box-shape.ts b/cocos/particle/modules/box-shape.ts index 547d2ae548d..4870c11fa3f 100644 --- a/cocos/particle/modules/box-shape.ts +++ b/cocos/particle/modules/box-shape.ts @@ -1,10 +1,12 @@ import { Enum, Vec3 } from '../../core'; import { ccclass, serializable, tooltip, type, visible } from '../../core/data/class-decorator'; -import { BoxShapeEmitFrom } from '../define'; +import { BoxShapeEmitFrom, ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { Shape } from './shape'; @ccclass('cc.BoxShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class BoxShape extends Shape { /** * @en Specify the position from which the particles are to be emitted. diff --git a/cocos/particle/modules/circle-shape.ts b/cocos/particle/modules/circle-shape.ts index 281673524c7..1255cbb9cf1 100644 --- a/cocos/particle/modules/circle-shape.ts +++ b/cocos/particle/modules/circle-shape.ts @@ -1,10 +1,13 @@ import { CCFloat, clamp, clamp01 } from '../../core'; import { ccclass, range, rangeStep, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { DistributableShape } from './distributable-shape'; @ccclass('cc.CircleShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class CircleShape extends DistributableShape { @type(CCFloat) @tooltip('i18n:ParticleSystem.CircleShape.radius') diff --git a/cocos/particle/modules/color-by-speed.ts b/cocos/particle/modules/color-by-speed.ts index 8b7cd0f8c7c..3c14e93f5b0 100644 --- a/cocos/particle/modules/color-by-speed.ts +++ b/cocos/particle/modules/color-by-speed.ts @@ -1,6 +1,7 @@ import { Vec2 } from '../../core'; import { ccclass, rangeStep, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; +import { ParticleSystemModuleStage } from '../define'; import { GradientRange } from '../gradient-range'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -10,6 +11,7 @@ import { ParticleSystemModule } from '../particle-system-module'; * @en Controls the color of each particle based on its speed. */ @ccclass('cc.ColorBySpeed') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 1) export class ColorBySpeed extends ParticleSystemModule { /** * @zh 基于每个粒子的速度控制其颜色。 diff --git a/cocos/particle/modules/color-over-lifetime.ts b/cocos/particle/modules/color-over-lifetime.ts index 01e87dd8425..86fcd76c914 100644 --- a/cocos/particle/modules/color-over-lifetime.ts +++ b/cocos/particle/modules/color-over-lifetime.ts @@ -26,6 +26,7 @@ import { ccclass, type, serializable, tooltip } from 'cc.decorator'; import { ParticleSystemModule } from '../particle-system-module'; import { GradientRange } from '../gradient-range'; import { Impl } from '../impl'; +import { ParticleSystemModuleStage } from '../define'; /** * @en @@ -34,6 +35,7 @@ import { Impl } from '../impl'; * 本模块用于在粒子生命周期内对颜色进行改变,可以修改模块下的颜色渐变条来查看粒子颜色渐变效果。 */ @ccclass('cc.ColorOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 0) export class ColorOverLifetime extends ParticleSystemModule { /** * @en Change color over life time. Evaluate by key interpolation. diff --git a/cocos/particle/modules/cone-shape.ts b/cocos/particle/modules/cone-shape.ts index 3b03b34d518..6a390482051 100644 --- a/cocos/particle/modules/cone-shape.ts +++ b/cocos/particle/modules/cone-shape.ts @@ -1,11 +1,13 @@ import { CCFloat, clamp, clamp01, Enum } from '../../core'; import { ccclass, range, serializable, tooltip, type, visible } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; -import { ConeShapeEmitFrom } from '../define'; +import { ConeShapeEmitFrom, ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { DistributableShape } from './distributable-shape'; @ccclass('cc.ConeShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class ConeShape extends DistributableShape { @type(CCFloat) @range([0, 90]) diff --git a/cocos/particle/modules/curl-noise-over-lifetime.ts b/cocos/particle/modules/curl-noise-over-lifetime.ts index 98ed5f32b1e..108fb0d081c 100644 --- a/cocos/particle/modules/curl-noise-over-lifetime.ts +++ b/cocos/particle/modules/curl-noise-over-lifetime.ts @@ -25,7 +25,7 @@ import { CCBoolean, CCFloat, CCInteger, clamp, clamp01, Enum, _decorator } from '../../core'; import { rangeMin, tooltip } from '../../core/data/decorators'; import { CurveRange, NEGATIVE_ONE_TO_ONE } from '../curve-range'; -import { NoiseQuality } from '../define'; +import { NoiseQuality, ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -38,6 +38,7 @@ const { ccclass, serializable, type, range, visible } = _decorator; * 为粒子添加噪声是创建有趣方案和效果的简单有效方法。 */ @ccclass('cc.CurlNoiseOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 6) export class CurlNoiseOverLifetime extends ParticleSystemModule { @type(CCBoolean) @tooltip('i18n:ParticleSystem.CurlNoiseOverLifetime.separateAxes') diff --git a/cocos/particle/modules/custom-data.ts b/cocos/particle/modules/custom-data.ts index 1b2c5cdeaf8..6f13be2f9df 100644 --- a/cocos/particle/modules/custom-data.ts +++ b/cocos/particle/modules/custom-data.ts @@ -1,12 +1,13 @@ import { CCInteger, clamp, Enum } from '../../core'; import { ccclass, range, serializable, tooltip, type, visible } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; -import { CustomDataMode } from '../define'; +import { CustomDataMode, ParticleSystemModuleStage } from '../define'; import { GradientRange } from '../gradient-range'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.CustomData') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 5) export class CustomData extends ParticleSystemModule { @type(Enum(CustomDataMode)) @tooltip('i18n:ParticleSystem.CustomData.mode1') diff --git a/cocos/particle/modules/dampen-over-lifetime.ts b/cocos/particle/modules/dampen-over-lifetime.ts index 6d5eae31a3e..8c3c9f2c666 100644 --- a/cocos/particle/modules/dampen-over-lifetime.ts +++ b/cocos/particle/modules/dampen-over-lifetime.ts @@ -24,7 +24,7 @@ import { ccclass, tooltip, displayOrder, type, serializable, visible, range, rangeMin } from 'cc.decorator'; import { CCBoolean, CCFloat, clamp01, Enum } from '../../core'; -import { CoordinateSpace } from '../define'; +import { CoordinateSpace, ParticleSystemModuleStage } from '../define'; import { ParticleSystemModule } from '../particle-system-module'; import { CurveRange } from '../curve-range'; import { Impl } from '../impl'; @@ -40,6 +40,7 @@ import { Impl } from '../impl'; * 每个轴上的粒子极限速度大小都是可以用曲线来进行编辑,修改曲线就能够看到粒子大小变化的效果了。 */ @ccclass('cc.DampenOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 7) export class DampenOverLifetime extends ParticleSystemModule { /** * @en Limit velocity on separate axis. @@ -167,7 +168,7 @@ export class DampenOverLifetime extends ParticleSystemModule { @visible(function (this: DampenOverLifetime): boolean { return this.separateAxes; }) - @tooltip('i18n:limitVelocityOvertimeModule.space') + @tooltip('i18n:ParticleSystem.DampenOverLifetime..space') public get space (): CoordinateSpace { return this._space; } diff --git a/cocos/particle/modules/donut-shape.ts b/cocos/particle/modules/donut-shape.ts index bb734af04c0..6be9c2280a2 100644 --- a/cocos/particle/modules/donut-shape.ts +++ b/cocos/particle/modules/donut-shape.ts @@ -1,10 +1,13 @@ import { CCFloat, clamp, clamp01 } from '../../core'; import { ccclass, range, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { DistributableShape } from './distributable-shape'; @ccclass('cc.DonutShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class DonutShape extends DistributableShape { @type(CCFloat) @tooltip('i18n:ParticleSystem.DonutShape.radius') diff --git a/cocos/particle/modules/drag-over-lifetime.ts b/cocos/particle/modules/drag-over-lifetime.ts index a52c84052cf..b36e20a70a7 100644 --- a/cocos/particle/modules/drag-over-lifetime.ts +++ b/cocos/particle/modules/drag-over-lifetime.ts @@ -2,10 +2,12 @@ import { CCBoolean } from '../../core'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.DragOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 8) export class DragOverLifetime extends ParticleSystemModule { @type(CurveRange) @rangeMin(0) diff --git a/cocos/particle/modules/edge-shape.ts b/cocos/particle/modules/edge-shape.ts index 2545ffedcfc..2df4b1d99bd 100644 --- a/cocos/particle/modules/edge-shape.ts +++ b/cocos/particle/modules/edge-shape.ts @@ -1,10 +1,13 @@ import { CCFloat } from '../../core'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { DistributableShape } from './distributable-shape'; @ccclass('cc.EdgeShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class EdgeShape extends DistributableShape { @type(CCFloat) @tooltip('i18n:ParticleSystem.EdgeShape.length') diff --git a/cocos/particle/modules/emission-by-burst.ts b/cocos/particle/modules/emission-by-burst.ts index 6a57959eb4e..ceb51d99b02 100644 --- a/cocos/particle/modules/emission-by-burst.ts +++ b/cocos/particle/modules/emission-by-burst.ts @@ -2,6 +2,7 @@ import { CCFloat, CCInteger, clamp01 } from '../../core'; import { ccclass, displayOrder, editable, range, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -101,6 +102,7 @@ export class Burst { } @ccclass('cc.EmissionByBurst') +@ParticleSystemModule.register(ParticleSystemModuleStage.EMISSION, 2) export class EmissionByBurst extends ParticleSystemModule { /** * @en Burst triggers of the particle system. diff --git a/cocos/particle/modules/emission-over-distance.ts b/cocos/particle/modules/emission-over-distance.ts index 3d7a68d6ee0..2fa26ba5dea 100644 --- a/cocos/particle/modules/emission-over-distance.ts +++ b/cocos/particle/modules/emission-over-distance.ts @@ -1,10 +1,12 @@ import { serializable, range, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.EmissionOverDistance') +@ParticleSystemModule.register(ParticleSystemModuleStage.EMISSION, 1) export class EmissionOverDistance extends ParticleSystemModule { /** * @en The value curve of emission rate over distance. diff --git a/cocos/particle/modules/emission-over-time.ts b/cocos/particle/modules/emission-over-time.ts index bec928091cc..372169a0ed4 100644 --- a/cocos/particle/modules/emission-over-time.ts +++ b/cocos/particle/modules/emission-over-time.ts @@ -1,10 +1,12 @@ import { serializable, range, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.EmissionOverTime') +@ParticleSystemModule.register(ParticleSystemModuleStage.EMISSION, 0) export class EmissionOverTime extends ParticleSystemModule { /** * @en The value curve of emission rate over time. diff --git a/cocos/particle/modules/force-over-lifetime.ts b/cocos/particle/modules/force-over-lifetime.ts index f324285d9f8..24065d2e47c 100644 --- a/cocos/particle/modules/force-over-lifetime.ts +++ b/cocos/particle/modules/force-over-lifetime.ts @@ -24,7 +24,7 @@ import { ccclass, tooltip, displayOrder, type, serializable } from 'cc.decorator'; import { CCBoolean, Enum } from '../../core'; -import { CoordinateSpace } from '../define'; +import { CoordinateSpace, ParticleSystemModuleStage } from '../define'; import { CurveRange } from '../curve-range'; import { ParticleSystemModule } from '../particle-system-module'; import { Impl } from '../impl'; @@ -38,6 +38,7 @@ import { Impl } from '../impl'; * 每个轴上的受力大小都是可以用曲线来进行编辑,修改曲线就能够看到粒子受力变化的效果了。 */ @ccclass('cc.ForceOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 0) export class ForceOverLifetime extends ParticleSystemModule { /** * @en Force on the X axis. diff --git a/cocos/particle/modules/gravity-over-lifetime.ts b/cocos/particle/modules/gravity-over-lifetime.ts index bfe341c83f2..0f349cdbfe4 100644 --- a/cocos/particle/modules/gravity-over-lifetime.ts +++ b/cocos/particle/modules/gravity-over-lifetime.ts @@ -1,10 +1,12 @@ import { serializable, displayOrder, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.GravityOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 1) export class GravityOverLifetime extends ParticleSystemModule { @type(CurveRange) @tooltip('i18n:ParticleSystem.GravityOverLifetime.x') diff --git a/cocos/particle/modules/inherit-start-velocity.ts b/cocos/particle/modules/inherit-start-velocity.ts index 10722e9deb9..3549beafda2 100644 --- a/cocos/particle/modules/inherit-start-velocity.ts +++ b/cocos/particle/modules/inherit-start-velocity.ts @@ -1,9 +1,11 @@ import { CurveRange } from '../../../typedoc-index'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.InheritStartVelocity') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 6) export class InheritStartVelocity extends ParticleSystemModule { @type(CurveRange) @tooltip('i18n:ParticleSystem.InheritVelocity.rate') diff --git a/cocos/particle/modules/inherit-velocity-over-lifetime.ts b/cocos/particle/modules/inherit-velocity-over-lifetime.ts index 5becb723db6..83cc4c5ab7e 100644 --- a/cocos/particle/modules/inherit-velocity-over-lifetime.ts +++ b/cocos/particle/modules/inherit-velocity-over-lifetime.ts @@ -1,9 +1,11 @@ import { CurveRange } from '../../../typedoc-index'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.InheritVelocityOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 5) export class InheritVelocityOverLifetime extends ParticleSystemModule { @type(CurveRange) @tooltip('i18n:ParticleSystem.InheritVelocityOverLifetime.rate') diff --git a/cocos/particle/modules/linear-velocity-over-lifetime.ts b/cocos/particle/modules/linear-velocity-over-lifetime.ts index 6deef05b4fd..74dead8cab3 100644 --- a/cocos/particle/modules/linear-velocity-over-lifetime.ts +++ b/cocos/particle/modules/linear-velocity-over-lifetime.ts @@ -23,7 +23,7 @@ */ import { ccclass, tooltip, type, serializable } from 'cc.decorator'; -import { CoordinateSpace } from '../define'; +import { CoordinateSpace, ParticleSystemModuleStage } from '../define'; import { CurveRange } from '../curve-range'; import { ParticleSystemModule } from '../particle-system-module'; import { Impl } from '../impl'; @@ -40,6 +40,7 @@ import { Enum } from '../../core'; * 每个轴上的速度大小都是可以用曲线来进行编辑,修改曲线就能够看到粒子速度变化的效果了。 */ @ccclass('cc.LinearVelocityOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 3) export class LinearVelocityOverLifetime extends ParticleSystemModule { /** * @en Velocity on X axis. diff --git a/cocos/particle/modules/orbital-velocity-over-lifetime.ts b/cocos/particle/modules/orbital-velocity-over-lifetime.ts index cfb016d7935..5ac7cc69db8 100644 --- a/cocos/particle/modules/orbital-velocity-over-lifetime.ts +++ b/cocos/particle/modules/orbital-velocity-over-lifetime.ts @@ -1,9 +1,11 @@ import { CurveRange } from '../../../typedoc-index'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.OrbitalVelocityOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 4) export class OrbitalVelocityOverLifetime extends ParticleSystemModule { @type(CurveRange) @tooltip('i18n:ParticleSystem.OrbitalVelocityOverLifetime.orbitalX') diff --git a/cocos/particle/modules/rectangle-shape.ts b/cocos/particle/modules/rectangle-shape.ts index dc2e7dad3c8..433b179effd 100644 --- a/cocos/particle/modules/rectangle-shape.ts +++ b/cocos/particle/modules/rectangle-shape.ts @@ -1,8 +1,11 @@ import { ccclass } from '../../core/data/class-decorator'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { Shape } from './shape'; @ccclass('cc.RectangleShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class RectangleShape extends Shape { protected createImpl (): Impl.ParticleSystemModule { return new Impl.RectangleShape(); diff --git a/cocos/particle/modules/rotation-by-speed.ts b/cocos/particle/modules/rotation-by-speed.ts index 5ea4d4737cf..c5cd041e81d 100644 --- a/cocos/particle/modules/rotation-by-speed.ts +++ b/cocos/particle/modules/rotation-by-speed.ts @@ -2,10 +2,12 @@ import { CCBoolean, Vec2 } from '../../core'; import { ccclass, serializable, tooltip, type, visible } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.RotationBySpeed') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 10) export class RotationBySpeed extends ParticleSystemModule { @type(CCBoolean) @tooltip('i18n:ParticleSystem.RotationBySpeed.separateAxes') diff --git a/cocos/particle/modules/rotation-over-lifetime.ts b/cocos/particle/modules/rotation-over-lifetime.ts index 6806a822cec..a115299476a 100644 --- a/cocos/particle/modules/rotation-over-lifetime.ts +++ b/cocos/particle/modules/rotation-over-lifetime.ts @@ -25,6 +25,7 @@ import { ccclass, tooltip, type, serializable, visible } from 'cc.decorator'; import { CCBoolean } from '../../core'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -39,6 +40,7 @@ import { ParticleSystemModule } from '../particle-system-module'; * 每个轴上的旋转角速度都是可以用曲线来进行编辑,修改曲线就能够看到粒子受力变化的效果了。 */ @ccclass('cc.RotationOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 9) export class RotationOverLifetime extends ParticleSystemModule { /** * @en Rotation around separate axis. diff --git a/cocos/particle/modules/shape.ts b/cocos/particle/modules/shape.ts index a3f10bb5ac0..02586a88b29 100644 --- a/cocos/particle/modules/shape.ts +++ b/cocos/particle/modules/shape.ts @@ -23,7 +23,7 @@ */ import { ccclass, tooltip, displayOrder, serializable, range, rangeMin, type } from 'cc.decorator'; -import { clamp01, Vec3 } from '../../core'; +import { CCBoolean, clamp01, Vec3 } from '../../core'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -88,6 +88,7 @@ export abstract class Shape extends ParticleSystemModule { * @en Align particle with particle direction. * @zh 根据粒子的初始方向决定粒子的移动方向。 */ + @type(CCBoolean) @tooltip('i18n:ParticleSystem.Shape.alignToDirection') public get alignToDirection (): boolean { return this._alignToDirection; @@ -117,7 +118,7 @@ export abstract class Shape extends ParticleSystemModule { * @en Blend particle directions towards a spherical direction, where they travel outwards from the center of their transform. * @zh 表示当前发射方向与当前位置到结点中心连线方向的插值。 */ - @tooltip('i18n:shapeModule.sphericalDirectionAmount') + @tooltip('i18n:ParticleSystem.Shape.spherizeDirection') @range([0, 1, 0.01]) public get spherizeDirection (): number { return this._spherizeDirection; @@ -132,7 +133,7 @@ export abstract class Shape extends ParticleSystemModule { * @en Particle position random amount. * @zh 粒子生成位置随机设定(设定此值为非 0 会使粒子生成位置超出生成器大小范围)。 */ - @tooltip('i18n:shapeModule.randomPositionAmount') + @tooltip('i18n:ParticleSystem.Shape.randomizePosition') @range([0, Number.MAX_VALUE, 0.01]) public get randomizePosition (): number { return this._randomizePosition; diff --git a/cocos/particle/modules/size-by-speed.ts b/cocos/particle/modules/size-by-speed.ts index 75bd160c715..8350389fe97 100644 --- a/cocos/particle/modules/size-by-speed.ts +++ b/cocos/particle/modules/size-by-speed.ts @@ -2,10 +2,12 @@ import { CCBoolean, Vec2 } from '../../core'; import { ccclass, serializable, tooltip, type, visible } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange, ZERO_TO_ONE } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.SizeBySpeed') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 3) export class SizeBySpeed extends ParticleSystemModule { @type(CCBoolean) @tooltip('i18n:ParticleSystem.SizeBySpeed.separateAxes') diff --git a/cocos/particle/modules/size-over-lifetime.ts b/cocos/particle/modules/size-over-lifetime.ts index 3504848b537..3e4198fa2c8 100644 --- a/cocos/particle/modules/size-over-lifetime.ts +++ b/cocos/particle/modules/size-over-lifetime.ts @@ -27,6 +27,7 @@ import { ParticleSystemModule } from '../particle-system-module'; import { CurveRange, ZERO_TO_ONE } from '../curve-range'; import { Impl } from '../impl'; import { CCBoolean } from '../../core'; +import { ParticleSystemModuleStage } from '../define'; /** * @en @@ -39,6 +40,7 @@ import { CCBoolean } from '../../core'; * 每个轴上的粒子大小都是可以用曲线来进行编辑,修改曲线就能够看到粒子大小变化的效果了。 */ @ccclass('cc.SizeOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 2) export class SizeOverLifetime extends ParticleSystemModule { @type(CCBoolean) @tooltip('i18n:ParticleSystem.SizeOverLifetime.separateAxes') diff --git a/cocos/particle/modules/speed-multiplier-over-lifetime.ts b/cocos/particle/modules/speed-multiplier-over-lifetime.ts index e231eac20e2..c9d692824ff 100644 --- a/cocos/particle/modules/speed-multiplier-over-lifetime.ts +++ b/cocos/particle/modules/speed-multiplier-over-lifetime.ts @@ -1,10 +1,12 @@ import { serializable } from '../../core'; import { ccclass, tooltip, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.SpeedMultiplierOverLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.PRE_SOLVE_UPDATE, 2) export class SpeedMultiplierOverLifetime extends ParticleSystemModule { /** * @en diff --git a/cocos/particle/modules/sphere-shape.ts b/cocos/particle/modules/sphere-shape.ts index 1a32234859c..c9d2ebe0f00 100644 --- a/cocos/particle/modules/sphere-shape.ts +++ b/cocos/particle/modules/sphere-shape.ts @@ -1,10 +1,13 @@ import { CCBoolean, CCFloat, clamp, clamp01 } from '../../core'; import { ccclass, range, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; +import { ParticleSystemModule } from '../particle-system-module'; import { DistributableShape } from './distributable-shape'; @ccclass('cc.SphereShape') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 0) export class SphereShape extends DistributableShape { @type(CCFloat) @rangeMin(0.0001) diff --git a/cocos/particle/modules/start-color.ts b/cocos/particle/modules/start-color.ts index ed39a2e15fe..27a0b04130a 100644 --- a/cocos/particle/modules/start-color.ts +++ b/cocos/particle/modules/start-color.ts @@ -1,10 +1,12 @@ import { serializable, displayOrder, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; +import { ParticleSystemModuleStage } from '../define'; import { GradientRange } from '../gradient-range'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartColor') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 5) export class StartColor extends ParticleSystemModule { /** * @en The initial color of the particle. diff --git a/cocos/particle/modules/start-lifetime-by-emitter-speed.ts b/cocos/particle/modules/start-lifetime-by-emitter-speed.ts index e0782bbb8ac..1198cee6810 100644 --- a/cocos/particle/modules/start-lifetime-by-emitter-speed.ts +++ b/cocos/particle/modules/start-lifetime-by-emitter-speed.ts @@ -2,10 +2,12 @@ import { Vec2 } from '../../core'; import { ccclass, serializable, tooltip, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange, ONE_TO_ZERO } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartLifetimeByEmitterSpeed') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 7) export class StartLifetimeByEmitterSpeed extends ParticleSystemModule { @type(CurveRange) @rangeMin(0) diff --git a/cocos/particle/modules/start-lifetime.ts b/cocos/particle/modules/start-lifetime.ts index da3658b11f4..264f018a899 100644 --- a/cocos/particle/modules/start-lifetime.ts +++ b/cocos/particle/modules/start-lifetime.ts @@ -2,10 +2,12 @@ import { serializable, range, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartLifetime') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 1) export class StartLifetime extends ParticleSystemModule { /** * @en Particle life time. diff --git a/cocos/particle/modules/start-rotation.ts b/cocos/particle/modules/start-rotation.ts index d866b15b971..c98d07815e4 100644 --- a/cocos/particle/modules/start-rotation.ts +++ b/cocos/particle/modules/start-rotation.ts @@ -1,10 +1,12 @@ import { CCBoolean, serializable, tooltip, visible } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartRotation') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 4) export class StartRotation extends ParticleSystemModule { /** * @en Whether to modify particle rotation on XYZ axis. diff --git a/cocos/particle/modules/start-size.ts b/cocos/particle/modules/start-size.ts index 18abeb7458d..9c0f1134aa0 100644 --- a/cocos/particle/modules/start-size.ts +++ b/cocos/particle/modules/start-size.ts @@ -2,10 +2,12 @@ import { serializable, tooltip, range, visible, CCFloat } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { rangeMin } from '../../core/data/decorators'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartSize') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 3) export class StartSize extends ParticleSystemModule { /** * @en Whether to modify particle size on XYZ axis. diff --git a/cocos/particle/modules/start-speed.ts b/cocos/particle/modules/start-speed.ts index bf6f15309d2..022f3594384 100644 --- a/cocos/particle/modules/start-speed.ts +++ b/cocos/particle/modules/start-speed.ts @@ -1,10 +1,12 @@ import { serializable, tooltip } from '../../core'; import { ccclass, type } from '../../core/data/class-decorator'; import { CurveRange } from '../curve-range'; +import { ParticleSystemModuleStage } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @ccclass('cc.StartSpeed') +@ParticleSystemModule.register(ParticleSystemModuleStage.SPAWN, 2) export class StartSpeed extends ParticleSystemModule { /** * @en The initial velocity of the particle. diff --git a/cocos/particle/modules/texture-sheet-animation.ts b/cocos/particle/modules/texture-sheet-animation.ts index a157c1be5a1..840bbe0c253 100644 --- a/cocos/particle/modules/texture-sheet-animation.ts +++ b/cocos/particle/modules/texture-sheet-animation.ts @@ -24,7 +24,7 @@ import { ccclass, tooltip, type, serializable, rangeMin, visible } from 'cc.decorator'; import { CCFloat, CCInteger, clamp, Vec2 } from '../../core'; import { CurveRange, ZERO_TO_ONE } from '../curve-range'; -import { AnimationMode, RowMode, TimeMode } from '../define'; +import { AnimationMode, ParticleSystemModuleStage, RowMode, TimeMode } from '../define'; import { Impl } from '../impl'; import { ParticleSystemModule } from '../particle-system-module'; @@ -35,6 +35,7 @@ import { ParticleSystemModule } from '../particle-system-module'; * 这个模块用于播放粒子纹理带的纹理帧动画。 */ @ccclass('cc.TextureSheetAnimation') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 4) export class TextureSheetAnimation extends ParticleSystemModule { /** * @en Tile count on X axis. diff --git a/cocos/particle/modules/trail.ts b/cocos/particle/modules/trail.ts index 00f16eec293..0b68a7986c4 100644 --- a/cocos/particle/modules/trail.ts +++ b/cocos/particle/modules/trail.ts @@ -25,12 +25,13 @@ import { ccclass, tooltip, type, serializable, range, rangeMin } from 'cc.decorator'; import { CurveRange } from '../curve-range'; import { GradientRange } from '../gradient-range'; -import { CoordinateSpace, TextureMode } from '../define'; +import { CoordinateSpace, ParticleSystemModuleStage, TextureMode } from '../define'; import { ParticleSystemModule } from '../particle-system-module'; import { Impl } from '../impl'; import { CCBoolean, CCFloat, clamp01, Enum } from '../../core'; @ccclass('cc.Trail') +@ParticleSystemModule.register(ParticleSystemModuleStage.POST_SOLVE_UPDATE, 6) export class Trail extends ParticleSystemModule { @type(CCFloat) @range([0, 1]) diff --git a/cocos/particle/particle-system-module.ts b/cocos/particle/particle-system-module.ts index d76cdf68f18..ea470a417be 100644 --- a/cocos/particle/particle-system-module.ts +++ b/cocos/particle/particle-system-module.ts @@ -24,10 +24,18 @@ import { serializable } from '../core'; import { ccclass } from '../core/data/class-decorator'; +import { ParticleSystemModuleStage } from './define'; import { Impl } from './impl'; @ccclass('cc.ParticleSystemModule') export abstract class ParticleSystemModule { + public static register (stage: ParticleSystemModuleStage, executionOrder: number) { + return function (ctor: Constructor): void { + ctor.executionOrder = executionOrder; + ctor.stage = stage; + }; + } + public get enabled (): boolean { return this._enabled; } @@ -54,6 +62,8 @@ export abstract class ParticleSystemModule { public initialize (): void { this._impl = this.createImpl(); this._impl.setEnabled(this._enabled); + this._impl.setStage(this.constructor.stage); + this._impl.setExecutionOrder(this.constructor.executionOrder); } /** diff --git a/cocos/particle/particle-system.ts b/cocos/particle/particle-system.ts index 467e55fc910..c6cd58ff381 100644 --- a/cocos/particle/particle-system.ts +++ b/cocos/particle/particle-system.ts @@ -26,11 +26,13 @@ import { ccclass, help, executeInEditMode, executionOrder, menu, tooltip, displayOrder, type, range, serializable, rangeMin, rangeStep } from 'cc.decorator'; import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { Curve } from '../animation/tracks/track'; -import { CCBoolean, CCFloat, CCInteger, Enum, warn } from '../core'; +import { assertIsTrue, CCBoolean, CCFloat, CCInteger, clamp01, Enum, warn } from '../core'; import { Component } from '../scene-graph/component'; import { CurveRange } from './curve-range'; -import { CoordinateSpace, CullingMode, PlaybackState, ScalingMode } from './define'; +import { CoordinateSpace, CullingMode, PlaybackState, ScalingMode, ShapeType } from './define'; import { Impl } from './impl'; +import { BoxShape, CircleShape, ColorBySpeed, ColorOverLifetime, ConeShape, CurlNoiseOverLifetime, CustomData, DampenOverLifetime, DonutShape, DragOverLifetime, EdgeShape, EmissionByBurst, EmissionOverDistance, EmissionOverTime, ForceOverLifetime, GravityOverLifetime, InheritStartVelocity, InheritVelocityOverLifetime, LinearVelocityOverLifetime, OrbitalVelocityOverLifetime, RectangleShape, Renderer, RotationBySpeed, RotationOverLifetime, Shape, SizeBySpeed, SizeOverLifetime, SpeedMultiplierOverLifetime, SphereShape, StartColor, StartLifetime, StartLifetimeByEmitterSpeed, StartRotation, StartSize, StartSpeed, TextureSheetAnimation, Trail } from './modules'; +import { ParticleSystemModule } from './particle-system-module'; /** * @en @@ -115,10 +117,18 @@ export class ParticleSystem extends Component { } } + @type(CCFloat) + @range([0, 1]) + @tooltip('i18n:ParticleSystem.flipRotation') public get flipRotation (): number { return this._flipRotation; } + public set flipRotation (val) { + this._flipRotation = clamp01(val); + this._impl?.setFlipRotation(this._flipRotation); + } + /** * @en The simulation space of the particle system, it could be world, local or custom. * @zh 选择粒子系统所在的坐标系[[Space]]。
@@ -165,6 +175,14 @@ export class ParticleSystem extends Component { this._impl?.setScalingMode(val); } + /** + * @en Automatically start playing after particle system initialized. + * @zh 粒子系统加载后是否自动开始播放。 + */ + @serializable + @tooltip('i18n:ParticleSystem.playOnAwake') + public playOnAwake = true; + /** * @en Maximum particle capacity to generate. * @zh 粒子系统能生成的最大粒子数量。 @@ -181,6 +199,200 @@ export class ParticleSystem extends Component { this._impl?.setCapacity(this._capacity); } + /** + * @en Particle culling mode option. Includes pause, pause and catchup, always simulate. + * @zh 粒子剔除模式选择。包括暂停模拟,暂停以后快进继续以及不间断模拟。 + */ + @type(CullingMode) + @tooltip('i18n:ParticleSystem.cullingMode') + public get cullingMode (): number { + return this._cullingMode; + } + + public set cullingMode (value: number) { + this._cullingMode = value; + } + + @type(EmissionOverTime) + @tooltip('i18n:ParticleSystem.emissionOverTime') + public get emissionOverTime (): EmissionOverTime | null { + return this.getModule(EmissionOverTime); + } + + @type(EmissionOverDistance) + @tooltip('i18n:ParticleSystem.emissionOverDistance') + public get emissionOverDistance (): EmissionOverDistance | null { + return this.getModule(EmissionOverDistance); + } + + @type(EmissionByBurst) + @tooltip('i18n:ParticleSystem.emissionByBurst') + public get emissionByBurst (): EmissionByBurst | null { + return this.getModule(EmissionByBurst); + } + + @type(Shape) + @tooltip('i18n:ParticleSystem.shape') + public get shape (): Shape | null { + return this.getModule(Shape); + } + + @type(StartLifetime) + @tooltip('i18n:ParticleSystem.startLifetime') + public get startLifetime (): StartLifetime | null { + return this.getModule(StartLifetime); + } + + @type(StartSpeed) + @tooltip('i18n:ParticleSystem.startSpeed') + public get startSpeed (): StartSpeed | null { + return this.getModule(StartSpeed); + } + + @type(StartSize) + @tooltip('i18n:ParticleSystem.startSize') + public get startSize (): StartSize | null { + return this.getModule(StartSize); + } + + @type(StartRotation) + @tooltip('i18n:ParticleSystem.startRotation') + public get startRotation (): StartRotation | null { + return this.getModule(StartRotation); + } + + @type(StartColor) + @tooltip('i18n:ParticleSystem.startColor') + public get startColor (): StartColor | null { + return this.getModule(StartColor); + } + + @type(InheritStartVelocity) + @tooltip('i18n:ParticleSystem.inheritStartVelocity') + public get inheritStartVelocity (): InheritStartVelocity | null { + return this.getModule(InheritStartVelocity); + } + + @type(StartLifetimeByEmitterSpeed) + @tooltip('i18n:ParticleSystem.startLifetimeByEmitterSpeed') + public get startLifetimeByEmitterSpeed (): StartLifetimeByEmitterSpeed | null { + return this.getModule(StartLifetimeByEmitterSpeed); + } + + @type(ForceOverLifetime) + @tooltip('i18n:ParticleSystem.forceOverLifetime') + public get forceOverLifetime (): ForceOverLifetime | null { + return this.getModule(ForceOverLifetime); + } + + @type(GravityOverLifetime) + @tooltip('i18n:ParticleSystem.gravityOverLifetime') + public get gravityOverLifetime (): GravityOverLifetime | null { + return this.getModule(GravityOverLifetime); + } + + @type(SpeedMultiplierOverLifetime) + @tooltip('i18n:ParticleSystem.speedMultiplierOverLifetime') + public get speedMultiplierOverLifetime (): SpeedMultiplierOverLifetime | null { + return this.getModule(SpeedMultiplierOverLifetime); + } + + @type(LinearVelocityOverLifetime) + @tooltip('i18n:ParticleSystem.linearVelocityOverLifetime') + public get linearVelocityOverLifetime (): LinearVelocityOverLifetime | null { + return this.getModule(LinearVelocityOverLifetime); + } + + @type(OrbitalVelocityOverLifetime) + @tooltip('i18n:ParticleSystem.orbitalVelocityOverLifetime') + public get orbitalVelocityOverLifetime (): OrbitalVelocityOverLifetime | null { + return this.getModule(OrbitalVelocityOverLifetime); + } + + @type(InheritVelocityOverLifetime) + @tooltip('i18n:ParticleSystem.inheritVelocityOverLifetime') + public get inheritVelocityOverLifetime (): InheritVelocityOverLifetime | null { + return this.getModule(InheritVelocityOverLifetime); + } + + @type(CurlNoiseOverLifetime) + @tooltip('i18n:ParticleSystem.curlNoiseOverLifetime') + public get curlNoiseOverLifetime (): CurlNoiseOverLifetime | null { + return this.getModule(CurlNoiseOverLifetime); + } + + @type(DampenOverLifetime) + @tooltip('i18n:ParticleSystem.dampenOverLifetime') + public get dampenOverLifetime (): DampenOverLifetime | null { + return this.getModule(DampenOverLifetime); + } + + @type(DragOverLifetime) + @tooltip('i18n:ParticleSystem.dragOverLifetime') + public get dragOverLifetime (): DragOverLifetime | null { + return this.getModule(DragOverLifetime); + } + + @type(RotationOverLifetime) + @tooltip('i18n:ParticleSystem.rotationOverLifetime') + public get rotationOverLifetime (): RotationOverLifetime | null { + return this.getModule(RotationOverLifetime); + } + + @type(RotationBySpeed) + @tooltip('i18n:ParticleSystem.rotationBySpeed') + public get rotationBySpeed (): RotationBySpeed | null { + return this.getModule(RotationBySpeed); + } + + @type(ColorOverLifetime) + @tooltip('i18n:ParticleSystem.colorOverLifetime') + public get colorOverLifetime (): ColorOverLifetime | null { + return this.getModule(ColorOverLifetime); + } + + @type(ColorBySpeed) + @tooltip('i18n:ParticleSystem.colorBySpeed') + public get colorBySpeed (): ColorBySpeed | null { + return this.getModule(ColorBySpeed); + } + + @type(SizeOverLifetime) + @tooltip('i18n:ParticleSystem.sizeOverLifetime') + public get sizeOverLifetime (): SizeOverLifetime | null { + return this.getModule(SizeOverLifetime); + } + + @type(SizeBySpeed) + @tooltip('i18n:ParticleSystem.sizeBySpeed') + public get sizeBySpeed (): SizeBySpeed | null { + return this.getModule(SizeBySpeed); + } + + @type(TextureSheetAnimation) + @tooltip('i18n:ParticleSystem.textureSheetAnimation') + public get textureSheetAnimation (): TextureSheetAnimation | null { + return this.getModule(TextureSheetAnimation); + } + + @type(CustomData) + @tooltip('i18n:ParticleSystem.customData') + public get customData (): CustomData | null { + return this.getModule(CustomData); + } + + @type(Trail) + @tooltip('i18n:ParticleSystem.trail') + public get trail (): Trail | null { + return this.getModule(Trail); + } + + @type(Renderer) + @tooltip('i18n:ParticleSystem.renderer') + public get renderer (): Renderer | null { + return this.getModule(Renderer); + } + /** * @en Whether this particle system is playing or not. * @zh 粒子系统是否正在播放。 @@ -221,28 +433,6 @@ export class ParticleSystem extends Component { return this._impl ? this._impl.getTotalTime() : 0; } - /** - * @en Automatically start playing after particle system initialized. - * @zh 粒子系统加载后是否自动开始播放。 - */ - @serializable - @tooltip('i18n:ParticleSystem.playOnAwake') - public playOnAwake = true; - - /** - * @en Particle culling mode option. Includes pause, pause and catchup, always simulate. - * @zh 粒子剔除模式选择。包括暂停模拟,暂停以后快进继续以及不间断模拟。 - */ - @type(CullingMode) - @tooltip('i18n:ParticleSystem.cullingMode') - get cullingMode (): number { - return this._cullingMode; - } - - set cullingMode (value: number) { - this._cullingMode = value; - } - /** * @en Emitter culling mode. * @zh 发射器的各种剔除模式。 @@ -269,11 +459,33 @@ export class ParticleSystem extends Component { private _delay = new CurveRange(); @serializable private _cullingMode = CullingMode.PAUSE; + @serializable + private _autoRandomSeed = false; + @serializable + private _randomSeed = 0; + @serializable + private _modules: ParticleSystemModule[] = []; private _impl: Impl.ParticleSystem | null = null; protected onLoad (): void { this._impl = new Impl.ParticleSystem(); + this._impl.setDuration(this._duration); + this._impl.setLooping(this._looping); + this._impl.setPrewarm(this._prewarm); + this._delay.copyToLowLevelCurveRange(this._impl.getDelay()); + this._impl.setFlipRotation(this._flipRotation); + this._impl.setSimulationSpace(this._simulationSpace); + this._impl.setSimulationSpeed(this._simulationSpeed); + this._impl.setScalingMode(this._scalingMode); + this._impl.setCapacity(this._capacity); + this._impl.setAutoRandomSeed(this._autoRandomSeed); + this._impl.setRandomSeed(this._randomSeed); + for (const module of this._modules) { + module.initialize(); + assertIsTrue(module.impl); + this._impl.addModule(module.impl); + } } protected onEnable (): void { @@ -291,6 +503,39 @@ export class ParticleSystem extends Component { this._impl = null; } + protected getModule (ParticleSystemModuleCtor: AbstractedConstructor | Constructor): T | null { + for (const module of this._modules) { + if (module instanceof ParticleSystemModuleCtor) { + return module; + } + } + return null; + } + + protected createModule (ParticleSystemModuleCtor: Constructor): void { + if (!this.getModule(ParticleSystemModuleCtor)) { + const module = new ParticleSystemModuleCtor(); + this._modules.push(module); + if (this._impl) { + module.initialize(); + assertIsTrue(module.impl); + this._impl.addModule(module.impl); + } + } + } + + protected deleteModule (ParticleSystemModuleCtor: AbstractedConstructor | Constructor): void { + const module = this.getModule(ParticleSystemModuleCtor); + if (module) { + this._modules.splice(this._modules.indexOf(module), 1); + if (this._impl) { + assertIsTrue(module.impl); + this._impl.removeModule(module.impl); + module.dispose(); + } + } + } + /** * @en Get current particle capacity. * @zh 获取当前粒子数量。 @@ -343,4 +588,120 @@ export class ParticleSystem extends Component { public clear (): void { this._impl?.clear(); } + + public createEmissionOverTime (): void { + this.createModule(EmissionOverTime); + } + + public deleteEmissionOverTime (): void { + this.deleteModule(EmissionOverTime); + } + + public createEmissionOverDistance (): void { + this.createModule(EmissionOverDistance); + } + + public deleteEmissionOverDistance (): void { + this.deleteModule(EmissionOverDistance); + } + + public createEmissionByBurst (): void { + this.createModule(EmissionByBurst); + } + + public deleteEmissionByBurst (): void { + this.deleteModule(EmissionByBurst); + } + + public createShape (shapeType: ShapeType): void { + this.deleteModule(Shape); + switch (shapeType) { + case ShapeType.BOX: + this.createModule(BoxShape); + break; + case ShapeType.SPHERE: + this.createModule(SphereShape); + break; + case ShapeType.CONE: + this.createModule(ConeShape); + break; + case ShapeType.CIRCLE: + this.createModule(CircleShape); + break; + case ShapeType.EDGE: + this.createModule(EdgeShape); + break; + case ShapeType.RECTANGLE: + this.createModule(RectangleShape); + break; + case ShapeType.DONUT: + this.createModule(DonutShape); + break; + default: + } + } + + public deleteShape (): void { + this.deleteModule(Shape); + } + + public createStartLifetime (): void { + this.createModule(StartLifetime); + } + + public deleteStartLifetime (): void { + this.deleteModule(StartLifetime); + } + + public createStartSpeed (): void { + this.createModule(StartSpeed); + } + + public deleteStartSpeed (): void { + this.deleteModule(StartSpeed); + } + + public createStartSize (): void { + this.createModule(StartSize); + } + + public deleteStartSize (): void { + this.deleteModule(StartSize); + } + + public createStartRotation (): void { + this.createModule(StartRotation); + } + + public deleteStartRotation (): void { + this.deleteModule(StartRotation); + } + + public createInheritStartVelocity (): void { + this.createModule(InheritStartVelocity); + } + + public deleteInheritStartVelocity (): void { + this.deleteModule(InheritStartVelocity); + } + + public createStartLifetimeByEmitterSpeed (): void { + this.createModule(StartLifetimeByEmitterSpeed); + } + + public deleteStartLifetimeByEmitterSpeed (): void { + this.deleteModule(StartLifetimeByEmitterSpeed); + } + + public createForceOverLifetime (): void { + this.createModule(ForceOverLifetime); + } + + public deleteForceOverLifetime (): void { + this.deleteModule(ForceOverLifetime); + } + + public createGravityOverLifetime (): void { + this.createModule(GravityOverLifetime); + } } diff --git a/native/cocos/particle/Define.h b/native/cocos/particle/Define.h index e62cd29db21..045fddce933 100644 --- a/native/cocos/particle/Define.h +++ b/native/cocos/particle/Define.h @@ -74,3 +74,11 @@ enum class TextureMode : uint8_t { DISTRIBUTE_PER_SEGMENT, REPEAT_PER_SEGMENT, }; + +enum class ParticleSystemModuleStage : uint8_t { + EMISSION, + SPAWN, + PRE_SOLVE_UPDATE, + POST_SOLVE_UPDATE, + RENDER +} diff --git a/native/cocos/particle/ParticleSystem.cpp b/native/cocos/particle/ParticleSystem.cpp index 856e4766b5d..d8b211de77e 100644 --- a/native/cocos/particle/ParticleSystem.cpp +++ b/native/cocos/particle/ParticleSystem.cpp @@ -9,7 +9,7 @@ namespace cc { void ParticleSystem::tick(float deltaTime) { ParticleSystemContext context{_particles, _emitter, _spawnInfos, deltaTime * _emitter.simulationSpeed}; updateEmitterState(context); - + updateEmissionModules(context); // update existing particle; size_t particleNum = _particles.size(); if (particleNum > 0) { @@ -23,11 +23,56 @@ void ParticleSystem::tick(float deltaTime) { // spawn new particles if (_emitter.isEmitting) { - updateEmissionModules(context); spawnNewParticles(context); } } +void ParticleSystem::addModule(ParticleSystemModule& module) { + switch (module.getStage()) { + case ParticleSystemModuleStage::EMISSION: + _emissionModules.push_back(&module); + break; + case ParticleSystemModuleStage::SPAWN: + _spawnModules.push_back(&module); + break; + case ParticleSystemModuleStage::PRE_SOLVE_UPDATE: + _preSolveUpdateModules.push_back(&module); + break; + case ParticleSystemModuleStage::POST_SOLVE_UPDATE: + _postSolveUpdateModules.push_back(&module); + break; + case ParticleSystemModuleStage::RENDER: + _renderModules.push_back(&module); + break; + } +} + +void ParticleSystem::removeModule(ParticleSystemModule& module) { + std::vector* stage; + switch (module.getStage()) { + case ParticleSystemModuleStage::EMISSION: + stage = &_emissionModules; + break; + case ParticleSystemModuleStage::SPAWN: + stage = &_spawnModules; + break; + case ParticleSystemModuleStage::PRE_SOLVE_UPDATE: + stage = &_preSolveUpdateModules; + break; + case ParticleSystemModuleStage::POST_SOLVE_UPDATE: + stage = &_postSolveUpdateModules; + break; + case ParticleSystemModuleStage::RENDER: + stage = &_renderModules; + break; + } + + auto& index = std::find(stage->begin(), stage->end(), &module); + if (index != stage->end()) { + stage->erase(index); + } +} + void ParticleSystem::spawnNewParticles(ParticleSystemContext& context) { ParticleVec3Array& position = _particles.getPosition(); ParticleVec3Array& baseVelocity = _particles.getBaseVelocity(); @@ -130,62 +175,18 @@ void ParticleSystem::updateParticleState(ParticleSystemContext& context) { } void ParticleSystem::updatePreSolveModules(ParticleSystemContext& context) { - if (_forceOverLifetime && _forceOverLifetime->isEnabled()) { - _forceOverLifetime->update(context); - } - if (_gravityOverLifetime && _gravityOverLifetime->isEnabled()) { - _gravityOverLifetime->update(context); - } - if (_dragOverLifetime && _dragOverLifetime->isEnabled()) { - _dragOverLifetime->update(context); - } - if (_curlNoiseOverLifetime && _curlNoiseOverLifetime->isEnabled()) { - _curlNoiseOverLifetime->update(context); - } - if (_speedMultiplierOverLifetime && _speedMultiplierOverLifetime->isEnabled()) { - _speedMultiplierOverLifetime->update(context); - } - if (_inheritVelocityOverLifetime && _inheritVelocityOverLifetime->isEnabled()) { - _inheritVelocityOverLifetime->update(context); - } - if (_linearVelocityOverLifetime && _linearVelocityOverLifetime->isEnabled()) { - _linearVelocityOverLifetime->update(context); - } - if (_orbitalVelocityOverLifetime && _orbitalVelocityOverLifetime->isEnabled()) { - _orbitalVelocityOverLifetime->update(context); - } - if (_dampenOverLifetime && _dampenOverLifetime->isEnabled()) { - _dampenOverLifetime->update(context); - } - if (_rotationBySpeed && _rotationBySpeed->isEnabled()) { - _rotationBySpeed->update(context); - } - if (_rotationOverLifetime && _rotationOverLifetime->isEnabled()) { - _rotationOverLifetime->update(context); + for (auto& m : _preSolveUpdateModules) { + if (m->isEnabled()) { + m->update(context); + } } } void ParticleSystem::updatePostSolveModules(ParticleSystemContext& context) { - if (_colorOverLifetime && _colorOverLifetime->isEnabled()) { - _colorOverLifetime->update(context); - } - if (_colorBySpeed && _colorBySpeed->isEnabled()) { - _colorBySpeed->update(context); - } - if (_sizeOverLifetime && _sizeOverLifetime->isEnabled()) { - _sizeOverLifetime->update(context); - } - if (_sizeBySpeed && _sizeBySpeed->isEnabled()) { - _sizeBySpeed->update(context); - } - if (_textureSheetAnimation && _textureSheetAnimation->isEnabled()) { - _textureSheetAnimation->update(context); - } - if (_customData && _customData->isEnabled()) { - _customData->update(context); - } - if (_trail && _trail->isEnabled()) { - _trail->update(context); + for (auto& m : _postSolveUpdateModules) { + if (m->isEnabled()) { + m->update(context); + } } } @@ -301,21 +302,14 @@ void ParticleSystem::updateEmitterState(ParticleSystemContext& context) { _emitter.prevNormalizedLoopAge = prevTime * invDuration; _emitter.loopedAge = currentTime; _emitter.normalizedLoopAge = currentTime * invDuration; + context.spawnInfos.clear(); } void ParticleSystem::updateEmissionModules(ParticleSystemContext& context) { - context.spawnInfos.clear(); - if (_emissionOverTime && _emissionOverTime->isEnabled()) { - _emissionOverTime->update(context); - } - if (_emissionOverDistance && _emissionOverDistance->isEnabled()) { - _emissionOverDistance->update(context); - } - if (_emissionByBurst && _emissionByBurst->isEnabled()) { - _emissionByBurst->update(context); - } - if (_emissionByEvent && _emissionByEvent->isEnabled()) { - _emissionByEvent->update(context); + for (auto& m : _emissionModules) { + if (m->isEnabled()) { + m->update(context); + } } } diff --git a/native/cocos/particle/ParticleSystem.h b/native/cocos/particle/ParticleSystem.h index 351716a4715..e29172bb8bc 100644 --- a/native/cocos/particle/ParticleSystem.h +++ b/native/cocos/particle/ParticleSystem.h @@ -1,36 +1,7 @@ #pragma once #include "particle/Particles.h" #include "particle/Emitter.h" -#include "particle/modules/ForceOverLifetime.h" -#include "particle/modules/ColorOverLifetime.h" -#include "particle/modules/ColorBySpeed.h" -#include "particle/modules/SpeedMultiplierOverLifetime.h" -#include "particle/modules/EmissionOverTime.h" -#include "particle/modules/EmissionOverDistance.h" -#include "particle/modules/EmissionByBurst.h" -#include "particle/modules/GravityOverLifetime.h" -#include "particle/modules/StartLifetime.h" -#include "particle/modules/StartColor.h" -#include "particle/modules/StartLifetimeByEmitterSpeed.h" -#include "particle/modules/StartRotation.h" -#include "particle/modules/StartSize.h" -#include "particle/modules/StartSpeed.h" -#include "particle/modules/InheritStartVelocity.h" -#include "particle/modules/Shape.h" -#include "particle/modules/CustomData.h" -#include "particle/modules/DragOverLifetime.h" -#include "particle/modules/InheritVelocityOverLifetime.h" -#include "particle/modules/LinearVelocityOverLifetime.h" -#include "particle/modules/OrbitalVelocityOverLifetime.h" -#include "particle/modules/DampenOverLifetime.h" -#include "particle/modules/CurlNoiseOverLifetime.h" -#include "particle/modules/RotationBySpeed.h" -#include "particle/modules/RotationOverLifetime.h" -#include "particle/modules/SizeBySpeed.h" -#include "particle/modules/SizeOverLifetime.h" -#include "particle/modules/TextureSheetAnimation.h" -#include "particle/modules/Trail.h" -#include "particle/modules/Renderer.h" +#include "particle/ParticleSystemModule.h" namespace cc { @@ -43,29 +14,6 @@ class ParticleSystem { return _particles.size(); } - void tick(float deltaTime); - void updateEmitterState(ParticleSystemContext& context); - void updateParticleState(ParticleSystemContext& context); - void updatePreSolveModules(ParticleSystemContext& context); - void solvePositionAndRotation(ParticleSystemContext& context); - void updatePostSolveModules(ParticleSystemContext& context); - void updateEmissionModules(ParticleSystemContext& context); - void spawnNewParticles(ParticleSystemContext& context); - void updateRenderer(ParticleSystemContext& context); - void play(); - void pause(); - void stop(bool clear = false); - void clear(); - - - inline Renderer* getRenderer() { - return _renderer; - } - - inline void setRenderer(Renderer* renderer) { - _renderer = renderer; - } - inline PlaybackState getPlaybackState() const { return _emitter.playbackState; } @@ -170,48 +118,30 @@ class ParticleSystem { _emitter.randomSeed = randomSeed; } + void addModule(ParticleSystemModule& module); + void removeModule(ParticleSystemModule& module); + void tick(float deltaTime); + void updateEmitterState(ParticleSystemContext& context); + void updateEmissionModules(ParticleSystemContext& context); + void updateParticleState(ParticleSystemContext& context); + void updatePreSolveModules(ParticleSystemContext& context); + void solvePositionAndRotation(ParticleSystemContext& context); + void updatePostSolveModules(ParticleSystemContext& context); + void spawnNewParticles(ParticleSystemContext& context); + void updateRenderModules(ParticleSystemContext& context); + void play(); + void pause(); + void stop(bool clear = false); + void clear(); + private: Emitter _emitter{}; Particles _particles{}; std::vector _spawnInfos{}; - - // Emission modules - EmissionOverTime* _emissionOverTime{nullptr}; - EmissionOverDistance* _emissionOverDistance{nullptr}; - EmissionByBurst* _emissionByBurst{nullptr}; - - // Particle Initialization modules - StartLifetime* _startLifetime{nullptr}; - StartLifetimeByEmitterSpeed* _startLifetimeByEmitterSpeed{nullptr}; - StartColor* _startColor{nullptr}; - StartRotation* _startRotation{nullptr}; - StartSize* _startSize{nullptr}; - StartSpeed* _startSpeed{nullptr}; - InheritStartVelocity* _inheritStartVelocity{nullptr}; - Shape* _shape{nullptr}; - - // Particle update modules - ForceOverLifetime* _forceOverLifetime{nullptr}; - GravityOverLifetime* _gravityOverLifetime{nullptr}; - SpeedMultiplierOverLifetime* _speedMultiplierOverLifetime{nullptr}; - InheritVelocityOverLifetime* _inheritVelocityOverLifetime{nullptr}; - LinearVelocityOverLifetime* _linearVelocityOverLifetime{nullptr}; - OrbitalVelocityOverLifetime* _orbitalVelocityOverLifetime{nullptr}; - CurlNoiseOverLifetime* _curlNoiseOverLifetime{nullptr}; - DampenOverLifetime* _dampenOverLifetime{nullptr}; - DragOverLifetime* _dragOverLifetime{nullptr}; - RotationBySpeed* _rotationBySpeed{nullptr}; - RotationOverLifetime* _rotationOverLifetime{nullptr}; - - ColorOverLifetime* _colorOverLifetime{nullptr}; - ColorBySpeed* _colorBySpeed{nullptr}; - SizeOverLifetime* _sizeOverLifetime{nullptr}; - SizeBySpeed* _sizeBySpeed{nullptr}; - TextureSheetAnimation* _textureSheetAnimation{nullptr}; - CustomData* _customData{nullptr}; - Trail* _trail{nullptr}; - - // Renderer - Renderer* _renderer{nullptr}; + std::vector _emissionModules{}; + std::vector _spawnModules{}; + std::vector _preSolveUpdateModules{}; + std::vector _postSolveUpdateModules{}; + std::vector _renderModules{}; }; }; diff --git a/native/cocos/particle/ParticleSystemModule.h b/native/cocos/particle/ParticleSystemModule.h index 23a14465992..c955e6675d6 100644 --- a/native/cocos/particle/ParticleSystemModule.h +++ b/native/cocos/particle/ParticleSystemModule.h @@ -46,6 +46,22 @@ class ParticleSystemModule { _enabled = enabled; } + inline ParticleSystemModuleStage getStage() const { + return _stage; + } + + inline void setStage(ParticleSystemModuleStage stage) { + _stage = stage; + } + + inline uint8_t getExecutionOrder() const { + return _executionOrder; + } + + inline void setExecutionOrder(uint8_t executionOrder) { + _executionOrder = executionOrder; + } + virtual void update(ParticleSystemContext& context) const = 0; inline void dispose() { @@ -53,6 +69,8 @@ class ParticleSystemModule { } private: + ParticleSystemModuleStage _stage{ParticleSystemModuleStage::EMISSION}; + uint8_t _executionOrder{0}; bool _enabled{false}; }; } // namespace cc