import { Vector3D } from '@awayjs/core';
import { ShaderRegisterCache, ShaderRegisterElement } from '@awayjs/stage';
import { ShaderBase, AnimationRegisterData } from '@awayjs/renderer';
import { ParticlePropertiesMode } from '../data/ParticlePropertiesMode';
import { ParticleUVState } from '../states/ParticleUVState';
import { ParticleAnimationSet } from '../ParticleAnimationSet';
import { AnimatorBase } from '../AnimatorBase';
import { ParticleNodeBase } from './ParticleNodeBase';
/**
* A particle animation node used to control the UV offset and scale of a particle over time.
*/
export class ParticleUVNode extends ParticleNodeBase {
/** @private */
public _iUvData: Vector3D;
/**
*
*/
public static U_AXIS: string = 'x';
/**
*
*/
public static V_AXIS: string = 'y';
private _cycle: number;
private _scale: number;
private _axis: string;
/**
* Creates a new ParticleTimeNode
*
* @param mode Defines whether the mode of operation acts on local properties of a particle or global properties of the node.
* @param [optional] cycle Defines whether the time track is in loop mode. Defaults to false.
* @param [optional] scale Defines whether the time track is in loop mode. Defaults to false.
* @param [optional] axis Defines whether the time track is in loop mode. Defaults to false.
*/
constructor(mode: number, cycle: number = 1, scale: number = 1, axis: string = 'x') {
//because of the stage3d register limitation, it only support the global mode
super('ParticleUV', ParticlePropertiesMode.GLOBAL, 4, ParticleAnimationSet.POST_PRIORITY + 1);
this._pStateClass = ParticleUVState;
this._cycle = cycle;
this._scale = scale;
this._axis = axis;
this.updateUVData();
}
/**
*
*/
public get cycle(): number {
return this._cycle;
}
public set cycle(value: number) {
this._cycle = value;
this.updateUVData();
}
/**
*
*/
public get scale(): number {
return this._scale;
}
public set scale(value: number) {
this._scale = value;
this.updateUVData();
}
/**
*
*/
public get axis(): string {
return this._axis;
}
public set axis(value: string) {
this._axis = value;
}
/**
* @inheritDoc
*/
public getAGALUVCode(shader: ShaderBase, animationSet: ParticleAnimationSet, registerCache: ShaderRegisterCache, animationRegisterData: AnimationRegisterData): string {
let code: string = '';
const uvConst: ShaderRegisterElement = registerCache.getFreeVertexConstant();
animationRegisterData.setRegisterIndex(this, ParticleUVState.UV_INDEX, uvConst.index);
const axisIndex: number = this._axis == 'x' ? 0 : (this._axis == 'y' ? 1 : 2);
const target: ShaderRegisterElement = new ShaderRegisterElement(animationRegisterData.uvTarget.regName, animationRegisterData.uvTarget.index, axisIndex);
const sin: ShaderRegisterElement = registerCache.getFreeVertexSingleTemp();
if (this._scale != 1)
code += 'mul ' + target + ',' + target + ',' + uvConst + '.y\n';
code += 'mul ' + sin + ',' + animationRegisterData.vertexTime + ',' + uvConst + '.x\n';
code += 'sin ' + sin + ',' + sin + '\n';
code += 'add ' + target + ',' + target + ',' + sin + '\n';
return code;
}
/**
* @inheritDoc
*/
public getAnimationState(animator: AnimatorBase): ParticleUVState {
return animator.getAnimationState(this);
}
private updateUVData(): void {
this._iUvData = new Vector3D(Math.PI * 2 / this._cycle, this._scale, 0, 0);
}
/**
* @inheritDoc
*/
public _iProcessAnimationSetting(particleAnimationSet: ParticleAnimationSet): void {
particleAnimationSet.hasUVNode = true;
}
}