From faed948ba3f18fd1cbca42e074651fa0c057d0fa Mon Sep 17 00:00:00 2001 From: Santy Wang Date: Wed, 19 Apr 2023 02:06:11 +0800 Subject: [PATCH] add expressions --- cocos/vfx/expression.ts | 11 +- cocos/vfx/expression/constant-expression.ts | 0 cocos/vfx/expression/float-expression.ts | 238 ------------------ .../color.ts} | 0 cocos/vfx/expressions/constant-vec3.ts | 45 ++++ cocos/vfx/expressions/constant.ts | 53 ++++ cocos/vfx/expressions/float-from-curve.ts | 47 ++++ cocos/vfx/expressions/float.ts | 38 +++ cocos/vfx/expressions/index.ts | 12 + cocos/vfx/expressions/make-float-from-vec3.ts | 72 ++++++ cocos/vfx/expressions/make-vec3.ts | 48 ++++ cocos/vfx/expressions/random-range-float.ts | 44 ++++ cocos/vfx/expressions/random-range-vec3.ts | 56 +++++ cocos/vfx/expressions/vec3-from-curve.ts | 72 ++++++ cocos/vfx/expressions/vec3-from-float.ts | 43 ++++ cocos/vfx/expressions/vec3.ts | 39 +++ cocos/vfx/index.ts | 7 +- .../modules/add-speed-in-initial-direction.ts | 57 +---- cocos/vfx/modules/add-velocity.ts | 2 +- cocos/vfx/modules/angle-based-shape.ts | 2 +- cocos/vfx/modules/curl-noise.ts | 2 +- cocos/vfx/modules/drag.ts | 2 +- cocos/vfx/modules/force.ts | 2 +- cocos/vfx/modules/gravity.ts | 2 +- cocos/vfx/modules/inherit-velocity.ts | 2 +- cocos/vfx/modules/limit-velocity.ts | 2 +- cocos/vfx/modules/line-shape.ts | 2 +- cocos/vfx/modules/multiply-color-by-speed.ts | 2 +- cocos/vfx/modules/multiply-color.ts | 2 +- cocos/vfx/modules/multiply-size.ts | 2 +- cocos/vfx/modules/rotation.ts | 2 +- cocos/vfx/modules/scale-size-by-speed.ts | 2 +- cocos/vfx/modules/scale-speed.ts | 2 +- cocos/vfx/modules/set-color.ts | 2 +- cocos/vfx/modules/set-life-time.ts | 2 +- cocos/vfx/modules/set-rotation.ts | 2 +- cocos/vfx/modules/set-size.ts | 2 +- cocos/vfx/modules/spawn-burst.ts | 28 +-- cocos/vfx/modules/spawn-per-unit.ts | 12 +- cocos/vfx/modules/spawn-rate.ts | 12 +- cocos/vfx/modules/sub-uv-animation.ts | 2 +- 41 files changed, 631 insertions(+), 343 deletions(-) delete mode 100644 cocos/vfx/expression/constant-expression.ts delete mode 100644 cocos/vfx/expression/float-expression.ts rename cocos/vfx/{expression/color-expression.ts => expressions/color.ts} (100%) create mode 100644 cocos/vfx/expressions/constant-vec3.ts create mode 100644 cocos/vfx/expressions/constant.ts create mode 100644 cocos/vfx/expressions/float-from-curve.ts create mode 100644 cocos/vfx/expressions/float.ts create mode 100644 cocos/vfx/expressions/index.ts create mode 100644 cocos/vfx/expressions/make-float-from-vec3.ts create mode 100644 cocos/vfx/expressions/make-vec3.ts create mode 100644 cocos/vfx/expressions/random-range-float.ts create mode 100644 cocos/vfx/expressions/random-range-vec3.ts create mode 100644 cocos/vfx/expressions/vec3-from-curve.ts create mode 100644 cocos/vfx/expressions/vec3-from-float.ts create mode 100644 cocos/vfx/expressions/vec3.ts diff --git a/cocos/vfx/expression.ts b/cocos/vfx/expression.ts index c10fc0d288c..6ac6694b048 100644 --- a/cocos/vfx/expression.ts +++ b/cocos/vfx/expression.ts @@ -22,11 +22,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { ParticleEmitterParams, ParticleExecContext } from "./particle-base"; -import { ParticleDataSet } from "./particle-data-set"; +import { ccclass } from '../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from './particle-base'; +import { ParticleDataSet } from './particle-data-set'; +@ccclass('cc.Expression') export abstract class Expression { public abstract tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext); - public abstract bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext); - public abstract evaluate (index: number); -} \ No newline at end of file + public abstract bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number); +} diff --git a/cocos/vfx/expression/constant-expression.ts b/cocos/vfx/expression/constant-expression.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/cocos/vfx/expression/float-expression.ts b/cocos/vfx/expression/float-expression.ts deleted file mode 100644 index 4c68ecd9273..00000000000 --- a/cocos/vfx/expression/float-expression.ts +++ /dev/null @@ -1,238 +0,0 @@ -/* - Copyright (c) 2020 Xiamen Yaji Software Co., Ltd. - - https://www.cocos.com/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated engine source code (the "Software"), a limited, - worldwide, royalty-free, non-assignable, revocable and non-exclusive license - to use Cocos Creator solely to develop games on your target platforms. You shall - not use Cocos Creator software for developing other software or tools that's - used for developing games. You are not granted to publish, distribute, - sublicense, and/or sell copies of Cocos Creator. - - The software or tools in this License Agreement are licensed, not sold. - Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -import { ccclass } from 'cc.decorator'; -import { approx, lerp, Enum, RealCurve, CCClass, RealKeyframeValue } from '../../core'; -import { constructLegacyCurveAndConvert } from '../../core/geometry/curve'; -import { Expression } from '../expression'; -import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; -import { ParticleDataSet } from '../particle-data-set'; - -const setClassAttr = CCClass.Attr.setClassAttr; - -export enum FloatExpressionMode { - CONSTANT, - CURVE, - TWO_CURVES, - TWO_CONSTANTS, -} -// TODO: can not remove ccclass for now, we need ccclass specified deserialization to handle deserialization of RealCurve -@ccclass('cc.FloatExpression') -export abstract class FloatExpression extends Expression { - public static Mode = FloatExpressionMode; - - /** - * @zh 曲线类型[[Mode]]。 - */ - public get mode () { - return this._mode; - } - - public set mode (val) { - if (val !== this._mode) { - switch (val) { - case FloatExpressionMode.TWO_CURVES: - case FloatExpressionMode.CURVE: - if (approx(this.multiplier, 0)) { this.multiplier = 1; } - break; - default: - break; - } - this._mode = val; - } - } - - /** - * @zh 当mode为Curve时,使用的曲线。 - */ - public get spline () { - if (!this._spline) { - this._spline = constructLegacyCurveAndConvert(); - } - return this._spline; - } - - public set spline (val) { - this._spline = val; - } - - public get splineMin () { - if (!this._splineMin) { - this._splineMin = constructLegacyCurveAndConvert(); - } - return this._splineMin; - } - - public set splineMin (val) { - this._splineMin = val; - } - - /** - * @zh 当mode为TwoCurves时,使用的曲线上限。 - */ - public get splineMax () { - return this.spline; - } - - public set splineMax (val) { - this.spline = val; - } - - /** - * @zh 当mode为TwoConstants时,曲线的上限。 - */ - public get constantMax () { - return this.constant; - } - - public set constantMax (val) { - this.constant = val; - } - - /** - * @zh 应用于曲线插值的系数。 - */ - public get multiplier () { - return this.constant; - } - - public set multiplier (val) { - this.constant = val; - } - - /** - * @zh 当mode为Constant时,曲线的值。 - */ - public constant = 0; - - /** - * @zh 当mode为TwoConstants时,曲线的下限。 - */ - public constantMin = 0; - - private _mode = FloatExpressionMode.CONSTANT; - private _spline: RealCurve | null = null; - private _splineMin: RealCurve | null = null; - - constructor (); - constructor (scalar: number); - constructor (scalar: number, minScaler: number); - constructor (scalar: number, spline: RealCurve); - constructor (scalar: number, spline: RealCurve, minSpline: RealCurve) - constructor (scalar = 0, splineOrMinScalar?: RealCurve | number, minSpline?: RealCurve) { - this.constant = scalar; - if (typeof splineOrMinScalar === 'number') { - this.mode = FloatExpressionMode.TWO_CONSTANTS; - this.constantMin = splineOrMinScalar; - } else if (typeof splineOrMinScalar === 'object') { - this.spline = splineOrMinScalar; - if (typeof minSpline === 'object') { - this.mode = FloatExpressionMode.TWO_CURVES; - this.splineMin = minSpline; - } else { - this.mode = FloatExpressionMode.CURVE; - } - } - } - - public evaluate (time: number, rndRatio: number) { - switch (this.mode) { - default: - case FloatExpressionMode.CONSTANT: - return this.constant; - case FloatExpressionMode.CURVE: - return this.spline.evaluate(time) * this.multiplier; - case FloatExpressionMode.TWO_CURVES: - return lerp(this.splineMin.evaluate(time), this.splineMax.evaluate(time), rndRatio) * this.multiplier; - case FloatExpressionMode.TWO_CONSTANTS: - return lerp(this.constantMin, this.constantMax, rndRatio); - } - } - - public getScalar (): number { - return this.constant; - } - - protected _onBeforeSerialize (props) { - switch (this._mode) { - case FloatExpressionMode.CONSTANT: - return ['mode', 'constant']; - case FloatExpressionMode.CURVE: - return ['mode', 'spline', 'multiplier']; - case FloatExpressionMode.TWO_CURVES: - return ['mode', 'splineMin', 'splineMax', 'multiplier']; - case FloatExpressionMode.TWO_CONSTANTS: - return ['mode', 'constantMin', 'constantMax']; - default: - return []; - } - } -} - -CCClass.fastDefine('cc.FloatExpression', FloatExpression, { - multiplier: 0, - constant: 0, - constantMin: 0, - constantMax: 0, - mode: FloatExpressionMode.CONSTANT, - spline: null, - splineMin: null, - splineMax: null, -}); - -setClassAttr(FloatExpression, 'multiplier', 'visible', true); -setClassAttr(FloatExpression, 'multiplier', 'hasSetter', true); -setClassAttr(FloatExpression, 'multiplier', 'hasGetter', true); -setClassAttr(FloatExpression, 'constantMax', 'visible', true); -setClassAttr(FloatExpression, 'constantMax', 'hasSetter', true); -setClassAttr(FloatExpression, 'constantMax', 'hasGetter', true); -setClassAttr(FloatExpression, 'constantMin', 'visible', true); -setClassAttr(FloatExpression, 'constant', 'visible', true); -setClassAttr(FloatExpression, 'mode', 'type', 'Enum'); -setClassAttr(FloatExpression, 'mode', 'enumList', Enum.getList(Enum(FloatExpressionMode))); -setClassAttr(FloatExpression, 'mode', 'visible', true); -setClassAttr(FloatExpression, 'mode', 'hasSetter', true); -setClassAttr(FloatExpression, 'mode', 'hasGetter', true); -setClassAttr(FloatExpression, 'splineMax', 'type', 'Object'); -setClassAttr(FloatExpression, 'splineMax', 'ctor', RealCurve); -setClassAttr(FloatExpression, 'splineMax', 'visible', true); -setClassAttr(FloatExpression, 'splineMax', 'hasGetter', true); -setClassAttr(FloatExpression, 'splineMax', 'hasSetter', true); -setClassAttr(FloatExpression, 'splineMin', 'type', 'Object'); -setClassAttr(FloatExpression, 'splineMin', 'ctor', RealCurve); -setClassAttr(FloatExpression, 'splineMin', 'visible', true); -setClassAttr(FloatExpression, 'splineMin', 'hasGetter', true); -setClassAttr(FloatExpression, 'splineMin', 'hasSetter', true); -setClassAttr(FloatExpression, 'spline', 'type', 'Object'); -setClassAttr(FloatExpression, 'spline', 'ctor', RealCurve); -setClassAttr(FloatExpression, 'spline', 'visible', true); -setClassAttr(FloatExpression, 'spline', 'hasGetter', true); -setClassAttr(FloatExpression, 'spline', 'hasSetter', true); - -export function createRealCurve (keyframes: Iterable<[number, number | Partial]>) { - const curve = new RealCurve(); - curve.assignSorted(keyframes); - return curve; -} diff --git a/cocos/vfx/expression/color-expression.ts b/cocos/vfx/expressions/color.ts similarity index 100% rename from cocos/vfx/expression/color-expression.ts rename to cocos/vfx/expressions/color.ts diff --git a/cocos/vfx/expressions/constant-vec3.ts b/cocos/vfx/expressions/constant-vec3.ts new file mode 100644 index 00000000000..3a7cec8d373 --- /dev/null +++ b/cocos/vfx/expressions/constant-vec3.ts @@ -0,0 +1,45 @@ +import { CCFloat, Vec3, serializable } from '../../core'; +import { ccclass, type } from '../../core/data/class-decorator'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { ParticleDataSet } from '../particle-data-set'; +import { RandomStream } from '../random-stream'; +import { Vec3Expression } from './vec3'; + +@ccclass('cc.ConstantVec3') +export class ConstantVec3Expression extends Vec3Expression { + @type(CCFloat) + @serializable + public x = 0; + + @type(CCFloat) + @serializable + public y = 0; + + @type(CCFloat) + @serializable + public z = 0; + + constructor (val: Vec3 = Vec3.ZERO) { + super(); + this.x = val.x; + this.y = val.y; + this.z = val.z; + } + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) {} + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) {} + + public evaluate (index: number, out: Vec3) { + out.x = this.x; + out.y = this.y; + out.z = this.z; + return out; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3) { + out.x = this.x; + out.y = this.y; + out.z = this.z; + return out; + } +} diff --git a/cocos/vfx/expressions/constant.ts b/cocos/vfx/expressions/constant.ts new file mode 100644 index 00000000000..d8b9036560c --- /dev/null +++ b/cocos/vfx/expressions/constant.ts @@ -0,0 +1,53 @@ +/* + Copyright (c) 2020 Xiamen Yaji Software Co., Ltd. + + https://www.cocos.com/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated engine source code (the "Software"), a limited, + worldwide, royalty-free, non-assignable, revocable and non-exclusive license + to use Cocos Creator solely to develop games on your target platforms. You shall + not use Cocos Creator software for developing other software or tools that's + used for developing games. You are not granted to publish, distribute, + sublicense, and/or sell copies of Cocos Creator. + + The software or tools in this License Agreement are licensed, not sold. + Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +import { CCFloat } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/class-decorator'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { ParticleDataSet } from '../particle-data-set'; +import { RandomStream } from '../random-stream'; +import { FloatExpression } from './float'; + +@ccclass('cc.ConstantExpression') +export class ConstantExpression extends FloatExpression { + @type(CCFloat) + @serializable + public value = 0; + + constructor (value = 0) { + super(); + this.value = value; + } + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) {} + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) {} + + public evaluate (index: number): number { + return this.value; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext): number { + return this.value; + } +} diff --git a/cocos/vfx/expressions/float-from-curve.ts b/cocos/vfx/expressions/float-from-curve.ts new file mode 100644 index 00000000000..017f97b3def --- /dev/null +++ b/cocos/vfx/expressions/float-from-curve.ts @@ -0,0 +1,47 @@ +import { RealCurve } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; +import { ModuleExecStage } from '../particle-module'; +import { RandomStream } from '../random-stream'; +import { ConstantExpression } from './constant'; +import { FloatExpression } from './float'; + +@ccclass('cc.FloatFromCurveExpression') +export class FloatFromCurveExpression extends FloatExpression { + @type(RealCurve) + @serializable + public curve = new RealCurve(); + + @type(FloatExpression) + @serializable + public curveScaler: FloatExpression = new ConstantExpression(1); + + private declare _time: Float32Array; + + constructor (curve?: RealCurve) { + super(); + if (curve) { + this.curve = curve; + } + } + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + context.markRequiredBuiltinParameters(context.executionStage === ModuleExecStage.UPDATE + ? BuiltinParticleParameterFlags.NORMALIZED_ALIVE_TIME : BuiltinParticleParameterFlags.SPAWN_NORMALIZED_TIME); + this.curveScaler.tick(particles, params, context); + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this._time = context.executionStage === ModuleExecStage.UPDATE ? particles.normalizedAliveTime.data : particles.spawnNormalizedTime.data; + this.curveScaler.bind(particles, params, context, randomOffset); + } + + public evaluate (index: number): number { + return this.curve.evaluate(this._time[index]) * this.curveScaler.evaluate(index); + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext): number { + return this.curve.evaluate(time) * this.curveScaler.evaluateSingle(time, randomStream, context); + } +} diff --git a/cocos/vfx/expressions/float.ts b/cocos/vfx/expressions/float.ts new file mode 100644 index 00000000000..2f3feb6f3a6 --- /dev/null +++ b/cocos/vfx/expressions/float.ts @@ -0,0 +1,38 @@ +/* + Copyright (c) 2020 Xiamen Yaji Software Co., Ltd. + + https://www.cocos.com/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated engine source code (the "Software"), a limited, + worldwide, royalty-free, non-assignable, revocable and non-exclusive license + to use Cocos Creator solely to develop games on your target platforms. You shall + not use Cocos Creator software for developing other software or tools that's + used for developing games. You are not granted to publish, distribute, + sublicense, and/or sell copies of Cocos Creator. + + The software or tools in this License Agreement are licensed, not sold. + Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +import { ccclass } from 'cc.decorator'; +import { Expression } from '../expression'; +import { ParticleExecContext } from '../particle-base'; +import { RandomStream } from '../random-stream'; + +@ccclass('cc.FloatExpression') +export abstract class FloatExpression extends Expression { + public get type () { + return 'Float'; + } + public abstract evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext): number; + public abstract evaluate (index: number): number; +} diff --git a/cocos/vfx/expressions/index.ts b/cocos/vfx/expressions/index.ts new file mode 100644 index 00000000000..12ee5092675 --- /dev/null +++ b/cocos/vfx/expressions/index.ts @@ -0,0 +1,12 @@ +export * from './constant'; +export * from './float'; +export * from './color'; +export * from './random-range-float'; +export * from './float-from-curve'; +export * from './vec3'; +export * from './constant-vec3'; +export * from './random-range-vec3'; +export * from './vec3-from-curve'; +export * from './vec3-from-float'; +export * from './make-vec3'; +export * from './make-float-from-vec3'; diff --git a/cocos/vfx/expressions/make-float-from-vec3.ts b/cocos/vfx/expressions/make-float-from-vec3.ts new file mode 100644 index 00000000000..881f86cb2fc --- /dev/null +++ b/cocos/vfx/expressions/make-float-from-vec3.ts @@ -0,0 +1,72 @@ +import { Enum, RealCurve, Vec3 } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { ParticleDataSet } from '../particle-data-set'; +import { ModuleExecStage } from '../particle-module'; +import { RandomStream } from '../random-stream'; +import { ConstantExpression } from './constant'; +import { ConstantVec3Expression } from './constant-vec3'; +import { FloatExpression } from './float'; +import { Vec3Expression } from './vec3'; + +const temp = new Vec3(); + +export enum Vec3Channel { + X, + Y, + Z, +} + +@ccclass('cc.MakeFloatFromVec3Expression') +export class MakeFloatFromVec3Expression extends FloatExpression { + @type(Vec3Expression) + @serializable + public vec3 = new ConstantVec3Expression(); + + @type(Enum(Vec3Channel)) + @serializable + public channel = Vec3Channel.X; + + private _getChannel = this._getX; + + private _getX (vec3: Vec3) { + return vec3.x; + } + + private _getY (vec3: Vec3) { + return vec3.y; + } + + private _getZ (vec3: Vec3) { + return vec3.z; + } + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + this.vec3.tick(particles, params, context); + switch (this.channel) { + case Vec3Channel.X: this._getChannel = this._getX; break; + case Vec3Channel.Y: this._getChannel = this._getY; break; + case Vec3Channel.Z: this._getChannel = this._getZ; break; + default: this._getChannel = this._getX; break; + } + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this.vec3.bind(particles, params, context, randomOffset); + } + + public evaluate (index: number): number { + this.vec3.evaluate(index, temp); + return this._getChannel(temp); + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext): number { + this.vec3.evaluateSingle(time, randomStream, context, temp); + switch (this.channel) { + case Vec3Channel.X: return temp.x; + case Vec3Channel.Y: return temp.y; + case Vec3Channel.Z: return temp.z; + default: return temp.x; + } + } +} diff --git a/cocos/vfx/expressions/make-vec3.ts b/cocos/vfx/expressions/make-vec3.ts new file mode 100644 index 00000000000..d9b26c3e6c4 --- /dev/null +++ b/cocos/vfx/expressions/make-vec3.ts @@ -0,0 +1,48 @@ +import { CCFloat, Vec3, serializable } from '../../core'; +import { ccclass, type } from '../../core/data/class-decorator'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { ParticleDataSet } from '../particle-data-set'; +import { RandomStream } from '../random-stream'; +import { ConstantExpression } from './constant'; +import { FloatExpression } from './float'; +import { Vec3Expression } from './vec3'; + +@ccclass('cc.MakeVec3Expression') +export class MakeVec3Expression extends Vec3Expression { + @type(FloatExpression) + @serializable + public x: FloatExpression = new ConstantExpression(); + + @type(CCFloat) + @serializable + public y: FloatExpression = new ConstantExpression(); + + @type(CCFloat) + @serializable + public z: FloatExpression = new ConstantExpression(); + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + this.x.tick(particles, params, context); + this.y.tick(particles, params, context); + this.z.tick(particles, params, context); + } + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this.x.bind(particles, params, context, randomOffset); + this.y.bind(particles, params, context, randomOffset); + this.z.bind(particles, params, context, randomOffset); + } + + public evaluate (index: number, out: Vec3) { + out.x = this.x.evaluate(index); + out.y = this.y.evaluate(index); + out.z = this.z.evaluate(index); + return out; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3) { + out.x = this.x.evaluateSingle(time, randomStream, context); + out.y = this.y.evaluateSingle(time, randomStream, context); + out.z = this.z.evaluateSingle(time, randomStream, context); + return out; + } +} diff --git a/cocos/vfx/expressions/random-range-float.ts b/cocos/vfx/expressions/random-range-float.ts new file mode 100644 index 00000000000..78df1e270d0 --- /dev/null +++ b/cocos/vfx/expressions/random-range-float.ts @@ -0,0 +1,44 @@ +import { lerp } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; +import { RandomStream } from '../random-stream'; +import { ConstantExpression } from './constant'; +import { FloatExpression } from './float'; + +@ccclass('cc.RandomRangeFloat') +export class RandomRangeFloat extends FloatExpression { + @type(FloatExpression) + @serializable + public maximum: FloatExpression = new ConstantExpression(0); + + @type(FloatExpression) + @serializable + public minimum: FloatExpression = new ConstantExpression(0); + + private declare _seed: Uint32Array; + private _randomOffset = 0; + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + this.maximum.tick(particles, params, context); + this.minimum.tick(particles, params, context); + context.markRequiredBuiltinParameters(BuiltinParticleParameterFlags.RANDOM_SEED); + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this.maximum.bind(particles, params, context, randomOffset); + this.minimum.bind(particles, params, context, randomOffset); + this._seed = particles.randomSeed.data; + this._randomOffset = randomOffset; + } + + public evaluate (index: number): number { + return lerp(this.minimum.evaluate(index), this.maximum.evaluate(index), RandomStream.getFloat(this._seed[index] + this._randomOffset)); + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext): number { + const min = this.minimum.evaluateSingle(time, randomStream, context); + const max = this.maximum.evaluateSingle(time, randomStream, context); + return lerp(min, max, randomStream.getFloat()); + } +} diff --git a/cocos/vfx/expressions/random-range-vec3.ts b/cocos/vfx/expressions/random-range-vec3.ts new file mode 100644 index 00000000000..51e106071ee --- /dev/null +++ b/cocos/vfx/expressions/random-range-vec3.ts @@ -0,0 +1,56 @@ +import { lerp, Vec3 } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; +import { RandomStream } from '../random-stream'; +import { ConstantVec3Expression } from './constant-vec3'; +import { Vec3Expression } from './vec3'; + +const temp = new Vec3(); +const tempRatio = new Vec3(); + +@ccclass('cc.RandomRangeVec3') +export class RandomRangeVec3 extends Vec3Expression { + @type(Vec3Expression) + @serializable + public maximum: Vec3Expression = new ConstantVec3Expression(Vec3.ZERO); + + @type(Vec3Expression) + @serializable + public minimum: Vec3Expression = new ConstantVec3Expression(Vec3.ZERO); + + private declare _seed: Uint32Array; + private _randomOffset = 0; + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + this.maximum.tick(particles, params, context); + this.minimum.tick(particles, params, context); + context.markRequiredBuiltinParameters(BuiltinParticleParameterFlags.RANDOM_SEED); + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this.maximum.bind(particles, params, context, randomOffset); + this.minimum.bind(particles, params, context, randomOffset); + this._seed = particles.randomSeed.data; + this._randomOffset = randomOffset; + } + + public evaluate (index: number, out: Vec3) { + this.minimum.evaluate(index, out); + this.maximum.evaluate(index, temp); + const ratio = RandomStream.get3Float(this._seed[index] + this._randomOffset, tempRatio); + out.x = lerp(out.x, temp.x, ratio.x); + out.y = lerp(out.y, temp.y, ratio.y); + out.z = lerp(out.z, temp.z, ratio.z); + return out; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3) { + this.minimum.evaluateSingle(time, randomStream, context, out); + this.maximum.evaluateSingle(time, randomStream, context, temp); + out.x = lerp(out.x, temp.x, randomStream.getFloat()); + out.y = lerp(out.y, temp.y, randomStream.getFloat()); + out.z = lerp(out.z, temp.z, randomStream.getFloat()); + return out; + } +} diff --git a/cocos/vfx/expressions/vec3-from-curve.ts b/cocos/vfx/expressions/vec3-from-curve.ts new file mode 100644 index 00000000000..8f82f81fabb --- /dev/null +++ b/cocos/vfx/expressions/vec3-from-curve.ts @@ -0,0 +1,72 @@ +import { RealCurve, Vec3 } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; +import { ModuleExecStage } from '../particle-module'; +import { RandomStream } from '../random-stream'; +import { ConstantVec3Expression } from './constant-vec3'; +import { Vec3Expression } from './vec3'; + +const ratio = new Vec3(); + +@ccclass('cc.Vec3FromCurveExpression') +export class Vec3FromCurveExpression extends Vec3Expression { + @type(RealCurve) + @serializable + public x = new RealCurve(); + + @type(RealCurve) + @serializable + public y = new RealCurve(); + + @type(RealCurve) + @serializable + public z = new RealCurve(); + + @type(Vec3Expression) + @serializable + public curveScaler: Vec3Expression = new ConstantVec3Expression(Vec3.ONE); + + private declare _time: Float32Array; + + constructor (x?: RealCurve, y?: RealCurve, z?: RealCurve) { + super(); + if (x) { + this.x = x; + } + if (y) { + this.y = y; + } + if (z) { + this.z = z; + } + } + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + context.markRequiredBuiltinParameters(context.executionStage === ModuleExecStage.UPDATE + ? BuiltinParticleParameterFlags.NORMALIZED_ALIVE_TIME : BuiltinParticleParameterFlags.SPAWN_NORMALIZED_TIME); + this.curveScaler.tick(particles, params, context); + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this._time = context.executionStage === ModuleExecStage.UPDATE ? particles.normalizedAliveTime.data : particles.spawnNormalizedTime.data; + this.curveScaler.bind(particles, params, context, randomOffset); + } + + public evaluate (index: number, out: Vec3) { + this.curveScaler.evaluate(index, ratio); + const time = this._time[index]; + out.x = this.x.evaluate(time) * ratio.x; + out.y = this.y.evaluate(time) * ratio.y; + out.z = this.z.evaluate(time) * ratio.z; + return out; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3): Vec3 { + this.curveScaler.evaluateSingle(time, randomStream, context, out); + out.x = this.x.evaluate(time) * ratio.x; + out.y = this.y.evaluate(time) * ratio.y; + out.z = this.z.evaluate(time) * ratio.z; + return out; + } +} diff --git a/cocos/vfx/expressions/vec3-from-float.ts b/cocos/vfx/expressions/vec3-from-float.ts new file mode 100644 index 00000000000..400e202cc5b --- /dev/null +++ b/cocos/vfx/expressions/vec3-from-float.ts @@ -0,0 +1,43 @@ +import { RealCurve, Vec3 } from '../../core'; +import { ccclass, serializable, type } from '../../core/data/decorators'; +import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; +import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; +import { ModuleExecStage } from '../particle-module'; +import { RandomStream } from '../random-stream'; +import { ConstantExpression } from './constant'; +import { ConstantVec3Expression } from './constant-vec3'; +import { FloatExpression } from './float'; +import { Vec3Expression } from './vec3'; + +const ratio = new Vec3(); + +@ccclass('cc.Vec3FromFloatExpression') +export class Vec3FromFloatExpression extends Vec3Expression { + @type(FloatExpression) + @serializable + public value: FloatExpression = new ConstantExpression(); + + public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { + this.value.tick(particles, params, context); + } + + public bind (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext, randomOffset: number) { + this.value.bind(particles, params, context, randomOffset); + } + + public evaluate (index: number, out: Vec3) { + const val = this.value.evaluate(index); + out.x = val; + out.y = val; + out.z = val; + return out; + } + + public evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3): Vec3 { + const val = this.value.evaluateSingle(time, randomStream, context); + out.x = val; + out.y = val; + out.z = val; + return out; + } +} diff --git a/cocos/vfx/expressions/vec3.ts b/cocos/vfx/expressions/vec3.ts new file mode 100644 index 00000000000..46abff6f30e --- /dev/null +++ b/cocos/vfx/expressions/vec3.ts @@ -0,0 +1,39 @@ +/* + Copyright (c) 2020 Xiamen Yaji Software Co., Ltd. + + https://www.cocos.com/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated engine source code (the "Software"), a limited, + worldwide, royalty-free, non-assignable, revocable and non-exclusive license + to use Cocos Creator solely to develop games on your target platforms. You shall + not use Cocos Creator software for developing other software or tools that's + used for developing games. You are not granted to publish, distribute, + sublicense, and/or sell copies of Cocos Creator. + + The software or tools in this License Agreement are licensed, not sold. + Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +import { ccclass } from 'cc.decorator'; +import { Expression } from '../expression'; +import { ParticleExecContext } from '../particle-base'; +import { RandomStream } from '../random-stream'; +import { Vec3 } from '../../core'; + +@ccclass('cc.Vec3Expression') +export abstract class Vec3Expression extends Expression { + public get type () { + return 'Vec3'; + } + public abstract evaluateSingle (time: number, randomStream: RandomStream, context: ParticleExecContext, out: Vec3): Vec3; + public abstract evaluate (index: number, out: Vec3): Vec3; +} diff --git a/cocos/vfx/index.ts b/cocos/vfx/index.ts index 9285a192c60..53c73de1874 100644 --- a/cocos/vfx/index.ts +++ b/cocos/vfx/index.ts @@ -25,8 +25,8 @@ import { ParticleEmitter } from './particle-emitter'; import { EventHandler } from './event-handler'; -import { FloatExpression } from './expression/float-expression'; -import { ColorExpression } from './expression/color-expression'; +import { FloatExpression } from './expressions/float'; +import { ColorExpression } from './expressions/color'; import './vfx-manager'; import { ParticleRenderer } from './particle-renderer'; import { Expression } from './expression'; @@ -37,7 +37,8 @@ export { FloatExpression, ColorExpression, EventHandler, - Expression + Expression, }; export * from './modules'; +export * from './expressions'; diff --git a/cocos/vfx/modules/add-speed-in-initial-direction.ts b/cocos/vfx/modules/add-speed-in-initial-direction.ts index 2384a8b54a4..6abc0c5cfe2 100644 --- a/cocos/vfx/modules/add-speed-in-initial-direction.ts +++ b/cocos/vfx/modules/add-speed-in-initial-direction.ts @@ -27,10 +27,11 @@ import { ccclass, range, serializable, tooltip, type } from 'cc.decorator'; import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { lerp, Vec3 } from '../../core'; import { RandomStream } from '../random-stream'; import { ParticleVec3ArrayParameter } from '../particle-parameter'; +import { ConstantExpression } from '../expressions'; const tempVelocity = new Vec3(); const requiredParameter = BuiltinParticleParameterFlags.POSITION | BuiltinParticleParameterFlags.VELOCITY | BuiltinParticleParameterFlags.START_DIR; @@ -45,7 +46,7 @@ export class AddSpeedInInitialDirectionModule extends ParticleModule { @serializable @range([-1, 1]) @tooltip('i18n:particle_system.startSpeed') - public speed = new FloatExpression(5); + public speed: FloatExpression = new ConstantExpression(5); private _randomOffset = 0; @@ -55,12 +56,7 @@ export class AddSpeedInInitialDirectionModule extends ParticleModule { public tick (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { context.markRequiredBuiltinParameters(requiredParameter); - if (this.speed.mode === FloatExpression.Mode.CURVE || this.speed.mode === FloatExpression.Mode.TWO_CURVES) { - context.markRequiredBuiltinParameters(BuiltinParticleParameterFlags.SPAWN_NORMALIZED_TIME); - } - if (this.speed.mode === FloatExpression.Mode.TWO_CURVES || this.speed.mode === FloatExpression.Mode.TWO_CONSTANTS) { - context.markRequiredBuiltinParameters(BuiltinParticleParameterFlags.RANDOM_SEED); - } + this.speed.tick(particles, params, context); if (context.executionStage !== ModuleExecStage.UPDATE) { context.markRequiredBuiltinParameters(BuiltinParticleParameterFlags.BASE_VELOCITY); } @@ -69,45 +65,14 @@ export class AddSpeedInInitialDirectionModule extends ParticleModule { public execute (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { const { fromIndex, toIndex } = context; const velocity = context.executionStage === ModuleExecStage.SPAWN ? particles.baseVelocity : particles.velocity; - + this.speed.bind(particles, params, context, this._randomOffset); const { startDir } = particles; - const mode = this.speed.mode; - const randomOffset = this._randomOffset; - if (mode === FloatExpression.Mode.CONSTANT) { - const constant = this.speed.constant; - ParticleVec3ArrayParameter.scaleAndAdd(velocity, velocity, startDir, constant, fromIndex, toIndex); - } else if (mode === FloatExpression.Mode.TWO_CONSTANTS) { - const { constantMin, constantMax } = this.speed; - const randomSeed = particles.randomSeed.data; - for (let i = fromIndex; i < toIndex; ++i) { - const curveStartSpeed = lerp(constantMin, constantMax, RandomStream.getFloat(randomSeed[i] + randomOffset)); - startDir.getVec3At(tempVelocity, i); - Vec3.multiplyScalar(tempVelocity, tempVelocity, curveStartSpeed); - velocity.addVec3At(tempVelocity, i); - } - } else if (mode === FloatExpression.Mode.CURVE) { - const { spline, multiplier } = this.speed; - const normalizedTime = context.executionStage === ModuleExecStage.SPAWN - ? particles.spawnNormalizedTime.data : particles.normalizedAliveTime.data; - for (let i = fromIndex; i < toIndex; ++i) { - const curveStartSpeed = spline.evaluate(normalizedTime[i]) * multiplier; - startDir.getVec3At(tempVelocity, i); - Vec3.multiplyScalar(tempVelocity, tempVelocity, curveStartSpeed); - velocity.addVec3At(tempVelocity, i); - } - } else { - const { splineMin, splineMax, multiplier } = this.speed; - const randomSeed = particles.randomSeed.data; - const normalizedTime = context.executionStage === ModuleExecStage.SPAWN - ? particles.spawnNormalizedTime.data : particles.normalizedAliveTime.data; - for (let i = fromIndex; i < toIndex; ++i) { - const time = normalizedTime[i]; - const curveStartSpeed = lerp(splineMin.evaluate(time), - splineMax.evaluate(time), RandomStream.getFloat(randomSeed[i] + randomOffset)) * multiplier; - startDir.getVec3At(tempVelocity, i); - Vec3.multiplyScalar(tempVelocity, tempVelocity, curveStartSpeed); - velocity.addVec3At(tempVelocity, i); - } + const speed = this.speed; + for (let i = fromIndex; i < toIndex; ++i) { + const curveStartSpeed = speed.evaluate(i); + startDir.getVec3At(tempVelocity, i); + Vec3.multiplyScalar(tempVelocity, tempVelocity, curveStartSpeed); + velocity.addVec3At(tempVelocity, i); } } } diff --git a/cocos/vfx/modules/add-velocity.ts b/cocos/vfx/modules/add-velocity.ts index 0342be2ab9d..b83bdc0bcd5 100644 --- a/cocos/vfx/modules/add-velocity.ts +++ b/cocos/vfx/modules/add-velocity.ts @@ -29,7 +29,7 @@ import { Space } from '../enum'; import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { RandomStream } from '../random-stream'; const tempVelocity = new Vec3(); diff --git a/cocos/vfx/modules/angle-based-shape.ts b/cocos/vfx/modules/angle-based-shape.ts index a683f1806c4..a6f7363a215 100644 --- a/cocos/vfx/modules/angle-based-shape.ts +++ b/cocos/vfx/modules/angle-based-shape.ts @@ -27,7 +27,7 @@ import { DistributionMode, MoveWarpMode, ShapeModule } from './shape'; import { Enum, lerp, toDegree, toRadian } from '../../core'; import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleVec3ArrayParameter } from '../particle-parameter'; @ccclass('cc.AngleBasedShapeModule') diff --git a/cocos/vfx/modules/curl-noise.ts b/cocos/vfx/modules/curl-noise.ts index 6658ea08f25..ec44abf4910 100644 --- a/cocos/vfx/modules/curl-noise.ts +++ b/cocos/vfx/modules/curl-noise.ts @@ -26,7 +26,7 @@ import { ccclass, type, serializable, range, rangeMin, visible } from 'cc.decorator'; import { DEBUG } from 'internal:constants'; import { assertIsTrue, CCFloat, Enum, approx, clamp, lerp, Vec2, Vec3 } from '../../core'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameter, BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; diff --git a/cocos/vfx/modules/drag.ts b/cocos/vfx/modules/drag.ts index 288ed805aad..8c38493fcc7 100644 --- a/cocos/vfx/modules/drag.ts +++ b/cocos/vfx/modules/drag.ts @@ -25,7 +25,7 @@ import { ccclass, type, serializable, visible } from 'cc.decorator'; import { lerp, Vec3, CCBoolean } from '../../core'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; diff --git a/cocos/vfx/modules/force.ts b/cocos/vfx/modules/force.ts index 113e7c8a5af..ee172ba8c68 100644 --- a/cocos/vfx/modules/force.ts +++ b/cocos/vfx/modules/force.ts @@ -27,7 +27,7 @@ import { ccclass, tooltip, displayOrder, range, type, serializable } from 'cc.de import { DEBUG } from 'internal:constants'; import { lerp, Vec3, assertIsTrue, Enum } from '../../core'; import { Space } from '../enum'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; diff --git a/cocos/vfx/modules/gravity.ts b/cocos/vfx/modules/gravity.ts index 1c7aef17466..45b640eb4cd 100644 --- a/cocos/vfx/modules/gravity.ts +++ b/cocos/vfx/modules/gravity.ts @@ -27,7 +27,7 @@ import { ccclass, displayOrder, range, serializable, tooltip, type } from 'cc.de import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { lerp, Vec3 } from '../../core'; import { Space } from '../enum'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/inherit-velocity.ts b/cocos/vfx/modules/inherit-velocity.ts index cb753eac642..5e8220a8e71 100644 --- a/cocos/vfx/modules/inherit-velocity.ts +++ b/cocos/vfx/modules/inherit-velocity.ts @@ -28,7 +28,7 @@ import { lerp, Vec3 } from '../../core'; import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { RandomStream } from '../random-stream'; const tempVelocity = new Vec3(); diff --git a/cocos/vfx/modules/limit-velocity.ts b/cocos/vfx/modules/limit-velocity.ts index 7eebd40545b..60f2af944b5 100644 --- a/cocos/vfx/modules/limit-velocity.ts +++ b/cocos/vfx/modules/limit-velocity.ts @@ -28,7 +28,7 @@ import { DEBUG } from 'internal:constants'; import { lerp, Vec3, approx, assertIsTrue } from '../../core'; import { Space } from '../enum'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/line-shape.ts b/cocos/vfx/modules/line-shape.ts index d4bbd32644f..78bded99016 100644 --- a/cocos/vfx/modules/line-shape.ts +++ b/cocos/vfx/modules/line-shape.ts @@ -28,7 +28,7 @@ import { ModuleExecStageFlags, ParticleModule } from '../particle-module'; import { Enum, lerp } from '../../core'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; @ccclass('cc.LineShapeModule') @ParticleModule.register('LineShape', ModuleExecStageFlags.SPAWN, [BuiltinParticleParameterName.START_DIR]) diff --git a/cocos/vfx/modules/multiply-color-by-speed.ts b/cocos/vfx/modules/multiply-color-by-speed.ts index a84118dbce4..0c2c4b6eaf0 100644 --- a/cocos/vfx/modules/multiply-color-by-speed.ts +++ b/cocos/vfx/modules/multiply-color-by-speed.ts @@ -23,7 +23,7 @@ THE SOFTWARE. */ import { ccclass, rangeMin, serializable, type } from 'cc.decorator'; -import { ColorExpression } from '../expression/color-expression'; +import { ColorExpression } from '../expressions/color'; import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; import { ModuleExecStageFlags, ParticleModule } from '../particle-module'; import { BuiltinParticleParameter, BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; diff --git a/cocos/vfx/modules/multiply-color.ts b/cocos/vfx/modules/multiply-color.ts index b09e6abb967..bd589cf0c4a 100644 --- a/cocos/vfx/modules/multiply-color.ts +++ b/cocos/vfx/modules/multiply-color.ts @@ -26,7 +26,7 @@ import { ccclass, displayOrder, type, serializable } from 'cc.decorator'; import { Color } from '../../core'; import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; -import { ColorExpression } from '../expression/color-expression'; +import { ColorExpression } from '../expressions/color'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/multiply-size.ts b/cocos/vfx/modules/multiply-size.ts index 0bf6dbcd5ff..4f96ff92abf 100644 --- a/cocos/vfx/modules/multiply-size.ts +++ b/cocos/vfx/modules/multiply-size.ts @@ -26,7 +26,7 @@ import { ccclass, tooltip, displayOrder, type, serializable, range, visible } from 'cc.decorator'; import { lerp, Vec3 } from '../../core'; import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleEmitterState, ParticleExecContext } from '../particle-base'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/rotation.ts b/cocos/vfx/modules/rotation.ts index 4f1ef9c1e75..39c46a895b1 100644 --- a/cocos/vfx/modules/rotation.ts +++ b/cocos/vfx/modules/rotation.ts @@ -28,7 +28,7 @@ import { ccclass, tooltip, displayOrder, range, type, radian, serializable, visi import { DEBUG } from 'internal:constants'; import { Vec3, lerp, assertIsTrue, CCBoolean } from '../../core'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/scale-size-by-speed.ts b/cocos/vfx/modules/scale-size-by-speed.ts index 9a9ef268d53..ecbef354116 100644 --- a/cocos/vfx/modules/scale-size-by-speed.ts +++ b/cocos/vfx/modules/scale-size-by-speed.ts @@ -26,7 +26,7 @@ import { ccclass, tooltip, displayOrder, type, serializable, range, visible, rangeMin } from 'cc.decorator'; import { approx, lerp, Vec2, assertIsTrue } from '../../core'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/scale-speed.ts b/cocos/vfx/modules/scale-speed.ts index 80abe7af62c..ea55f296dc2 100644 --- a/cocos/vfx/modules/scale-speed.ts +++ b/cocos/vfx/modules/scale-speed.ts @@ -25,7 +25,7 @@ import { ccclass, displayOrder, range, serializable, tooltip, type } from 'cc.decorator'; import { lerp } from '../../core'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameter, BuiltinParticleParameterFlags, BuiltinParticleParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; diff --git a/cocos/vfx/modules/set-color.ts b/cocos/vfx/modules/set-color.ts index 50a93a7677d..9ab15475aec 100644 --- a/cocos/vfx/modules/set-color.ts +++ b/cocos/vfx/modules/set-color.ts @@ -27,7 +27,7 @@ import { ccclass, displayOrder, serializable, tooltip, type } from 'cc.decorator import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { ColorExpression } from '../expression/color-expression'; +import { ColorExpression } from '../expressions/color'; import { Color } from '../../core'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/set-life-time.ts b/cocos/vfx/modules/set-life-time.ts index 8e69ece6d1d..0dc0821b420 100644 --- a/cocos/vfx/modules/set-life-time.ts +++ b/cocos/vfx/modules/set-life-time.ts @@ -27,7 +27,7 @@ import { ccclass, displayOrder, range, serializable, tooltip, type } from 'cc.de import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { lerp } from '../../core'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/set-rotation.ts b/cocos/vfx/modules/set-rotation.ts index 4b40d67bd0b..301f12fc4b5 100644 --- a/cocos/vfx/modules/set-rotation.ts +++ b/cocos/vfx/modules/set-rotation.ts @@ -27,7 +27,7 @@ import { ccclass, radian, range, serializable, tooltip, type, visible } from 'cc import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { lerp } from '../../core'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/set-size.ts b/cocos/vfx/modules/set-size.ts index 42ae5dff781..0bdbeaddbfb 100644 --- a/cocos/vfx/modules/set-size.ts +++ b/cocos/vfx/modules/set-size.ts @@ -28,7 +28,7 @@ import { ccclass, range, serializable, tooltip, type, visible } from 'cc.decorat import { ParticleModule, ModuleExecStage, ModuleExecStageFlags } from '../particle-module'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { lerp, Vec3, assertIsTrue } from '../../core'; import { RandomStream } from '../random-stream'; diff --git a/cocos/vfx/modules/spawn-burst.ts b/cocos/vfx/modules/spawn-burst.ts index 7a3af8a34ab..490fa79ac0d 100644 --- a/cocos/vfx/modules/spawn-burst.ts +++ b/cocos/vfx/modules/spawn-burst.ts @@ -25,11 +25,12 @@ import { ccclass, serializable, type, range, editable } from 'cc.decorator'; import { lerp } from '../../core'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; import { RandomStream } from '../random-stream'; +import { ConstantExpression } from '../expressions'; @ccclass('cc.SpawnBurstModule') @ParticleModule.register('SpawnBurst', ModuleExecStageFlags.EMITTER_UPDATE | ModuleExecStageFlags.EVENT_HANDLER) @@ -40,7 +41,7 @@ export class SpawnBurstModule extends ParticleModule { @type(FloatExpression) @serializable @range([0, 1]) - public count = new FloatExpression(); + public count = new ConstantExpression(); /** * @zh 粒子系统开始运行到触发此次 Burst 的时间。 @@ -88,8 +89,10 @@ export class SpawnBurstModule extends ParticleModule { let prevT = emitterPreviousTime; // handle loop. if (prevT > emitterCurrentTime) { + const seed = this._rand.seed; this._accumulateBurst(prevT, params.duration, 1, context); prevT = 0; + this._rand.seed = seed; } this._accumulateBurst(prevT, emitterCurrentTime, emitterNormalizedTime, context); } @@ -102,25 +105,8 @@ export class SpawnBurstModule extends ParticleModule { const currentEmitTime = Math.min(Math.ceil((currT - this.time) / this.repeatInterval), this.repeatCount); const toEmitTime = currentEmitTime - preEmitTime; if (toEmitTime === 0) { return; } - if (this.count.mode === FloatExpression.Mode.CONSTANT) { - for (let j = 0; j < toEmitTime; j++) { - context.burstCount += this.count.constant; - } - } else if (this.count.mode === FloatExpression.Mode.CURVE) { - const { spline, multiplier } = this.count; - for (let j = 0; j < toEmitTime; j++) { - context.burstCount += spline.evaluate(normalizeT) * multiplier; - } - } else if (this.count.mode === FloatExpression.Mode.TWO_CONSTANTS) { - const { constantMin, constantMax } = this.count; - for (let j = 0; j < toEmitTime; j++) { - context.burstCount += lerp(constantMin, constantMax, rand.getFloat()); - } - } else { - const { splineMin, splineMax, multiplier } = this.count; - for (let j = 0; j < toEmitTime; j++) { - context.burstCount += lerp(splineMin.evaluate(normalizeT), splineMax.evaluate(normalizeT), rand.getFloat()) * multiplier; - } + for (let j = 0; j < toEmitTime; j++) { + context.burstCount += this.count.evaluateSingle(normalizeT, rand, context); } } } diff --git a/cocos/vfx/modules/spawn-per-unit.ts b/cocos/vfx/modules/spawn-per-unit.ts index 278e2c2f05f..dcb55486fec 100644 --- a/cocos/vfx/modules/spawn-per-unit.ts +++ b/cocos/vfx/modules/spawn-per-unit.ts @@ -26,9 +26,10 @@ import { ccclass, displayOrder, serializable, tooltip, type, range } from 'cc.decorator'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { ParticleDataSet } from '../particle-data-set'; import { RandomStream } from '../random-stream'; +import { ConstantExpression } from '../expressions'; @ccclass('cc.SpawnPerUnitModule') @ParticleModule.register('SpawnPerUnit', ModuleExecStageFlags.EMITTER_UPDATE | ModuleExecStageFlags.EVENT_HANDLER) @@ -41,7 +42,7 @@ export class SpawnPerUnitModule extends ParticleModule { @range([0, 1]) @displayOrder(15) @tooltip('i18n:particle_system.rateOverDistance') - public rate = new FloatExpression(); + public rate = new ConstantExpression(); private _rand = new RandomStream(); @@ -52,11 +53,12 @@ export class SpawnPerUnitModule extends ParticleModule { public execute (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { const { emitterVelocity, emitterNormalizedTime: normalizeT, emitterDeltaTime, emitterPreviousTime, emitterCurrentTime } = context; let deltaTime = emitterDeltaTime; - const random = this._rand.getFloat(); if (emitterPreviousTime > emitterCurrentTime) { - context.spawnContinuousCount += emitterVelocity.length() * this.rate.evaluate(1, random) * (params.duration - emitterPreviousTime); + const seed = this._rand.seed; + context.spawnContinuousCount += emitterVelocity.length() * this.rate.evaluateSingle(1, this._rand, context) * (params.duration - emitterPreviousTime); deltaTime = emitterCurrentTime; + this._rand.seed = seed; } - context.spawnContinuousCount += emitterVelocity.length() * this.rate.evaluate(normalizeT, random) * deltaTime; + context.spawnContinuousCount += emitterVelocity.length() * this.rate.evaluateSingle(normalizeT, this._rand, context) * deltaTime; } } diff --git a/cocos/vfx/modules/spawn-rate.ts b/cocos/vfx/modules/spawn-rate.ts index 88605ffac59..368a5e6fbab 100644 --- a/cocos/vfx/modules/spawn-rate.ts +++ b/cocos/vfx/modules/spawn-rate.ts @@ -27,8 +27,9 @@ import { ccclass, displayOrder, serializable, tooltip, type, range } from 'cc.de import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; import { ParticleDataSet } from '../particle-data-set'; import { ParticleExecContext, ParticleEmitterParams, ParticleEmitterState } from '../particle-base'; -import { FloatExpression } from '../expression/float-expression'; +import { FloatExpression } from '../expressions/float'; import { RandomStream } from '../random-stream'; +import { ConstantExpression } from '../expressions'; @ccclass('cc.SpawnRateModule') @ParticleModule.register('SpawnRate', ModuleExecStageFlags.EMITTER_UPDATE | ModuleExecStageFlags.EVENT_HANDLER) @@ -41,7 +42,7 @@ export class SpawnRateModule extends ParticleModule { @range([0, 1]) @displayOrder(14) @tooltip('i18n:particle_system.rateOverTime') - public rate = new FloatExpression(10); + public rate = new ConstantExpression(10); private _rand = new RandomStream(); @@ -52,11 +53,12 @@ export class SpawnRateModule extends ParticleModule { public execute (particles: ParticleDataSet, params: ParticleEmitterParams, context: ParticleExecContext) { const { emitterDeltaTime, emitterNormalizedTime: normalizedT, emitterPreviousTime, emitterCurrentTime } = context; let deltaTime = emitterDeltaTime; - const random = this._rand.getFloat(); if (emitterPreviousTime > emitterCurrentTime) { - context.spawnContinuousCount += this.rate.evaluate(1, random) * (params.duration - emitterPreviousTime); + const seed = this._rand.seed; + context.spawnContinuousCount += this.rate.evaluateSingle(1, this._rand, context) * (params.duration - emitterPreviousTime); deltaTime = emitterCurrentTime; + this._rand.seed = seed; } - context.spawnContinuousCount += this.rate.evaluate(normalizedT, random) * deltaTime; + context.spawnContinuousCount += this.rate.evaluateSingle(normalizedT, this._rand, context) * deltaTime; } } diff --git a/cocos/vfx/modules/sub-uv-animation.ts b/cocos/vfx/modules/sub-uv-animation.ts index 59d38fac4fa..0e3f667a586 100644 --- a/cocos/vfx/modules/sub-uv-animation.ts +++ b/cocos/vfx/modules/sub-uv-animation.ts @@ -27,7 +27,7 @@ import { ccclass, tooltip, type, serializable, range, visible } from 'cc.decorat import { DEBUG } from 'internal:constants'; import { lerp, repeat, Enum, assertIsTrue, CCFloat, CCInteger } from '../../core'; import { ParticleModule, ModuleExecStageFlags } from '../particle-module'; -import { createRealCurve, FloatExpression } from '../expression/float-expression'; +import { createRealCurve, FloatExpression } from '../expressions/float'; import { BuiltinParticleParameterFlags, BuiltinParticleParameterName as ParameterName, ParticleDataSet } from '../particle-data-set'; import { ParticleEmitterParams, ParticleExecContext } from '../particle-base'; import { RandomStream } from '../random-stream';