playcanvas
Version:
PlayCanvas WebGL game engine
1,052 lines (1,049 loc) • 27.7 kB
JavaScript
import { LAYERID_DEPTH } from '../../../scene/constants.js';
import { Mesh } from '../../../scene/mesh.js';
import { ParticleEmitter } from '../../../scene/particle-system/particle-emitter.js';
import { Asset } from '../../asset/asset.js';
import { Component } from '../component.js';
const SIMPLE_PROPERTIES = [
'emitterExtents',
'emitterRadius',
'emitterExtentsInner',
'emitterRadiusInner',
'loop',
'initialVelocity',
'animSpeed',
'normalMap',
'particleNormal'
];
const COMPLEX_PROPERTIES = [
'numParticles',
'lifetime',
'rate',
'rate2',
'startAngle',
'startAngle2',
'lighting',
'halfLambert',
'intensity',
'wrap',
'wrapBounds',
'depthWrite',
'noFog',
'sort',
'stretch',
'alignToMotion',
'preWarm',
'emitterShape',
'animTilesX',
'animTilesY',
'animStartFrame',
'animNumFrames',
'animNumAnimations',
'animIndex',
'randomizeAnimIndex',
'animLoop',
'colorMap',
'localSpace',
'screenSpace',
'orientation'
];
const GRAPH_PROPERTIES = [
'scaleGraph',
'scaleGraph2',
'colorGraph',
'colorGraph2',
'alphaGraph',
'alphaGraph2',
'velocityGraph',
'velocityGraph2',
'localVelocityGraph',
'localVelocityGraph2',
'rotationSpeedGraph',
'rotationSpeedGraph2',
'radialSpeedGraph',
'radialSpeedGraph2'
];
const ASSET_PROPERTIES = [
'colorMapAsset',
'normalMapAsset',
'meshAsset',
'renderAsset'
];
let depthLayer;
class ParticleSystemComponent extends Component {
constructor(system, entity){
super(system, entity), this._requestedDepth = false, this._drawOrder = 0, this._evtLayersChanged = null, this._evtLayerAdded = null, this._evtLayerRemoved = null, this._evtSetMeshes = null;
this.on('set_colorMapAsset', this.onSetColorMapAsset, this);
this.on('set_normalMapAsset', this.onSetNormalMapAsset, this);
this.on('set_meshAsset', this.onSetMeshAsset, this);
this.on('set_mesh', this.onSetMesh, this);
this.on('set_renderAsset', this.onSetRenderAsset, this);
this.on('set_loop', this.onSetLoop, this);
this.on('set_blendType', this.onSetBlendType, this);
this.on('set_depthSoftening', this.onSetDepthSoftening, this);
this.on('set_layers', this.onSetLayers, this);
SIMPLE_PROPERTIES.forEach((prop)=>{
this.on(`set_${prop}`, this.onSetSimpleProperty, this);
});
COMPLEX_PROPERTIES.forEach((prop)=>{
this.on(`set_${prop}`, this.onSetComplexProperty, this);
});
GRAPH_PROPERTIES.forEach((prop)=>{
this.on(`set_${prop}`, this.onSetGraphProperty, this);
});
}
get data() {
const record = this.system.store[this.entity.getGuid()];
return record ? record.data : null;
}
set enabled(arg) {
this._setValue('enabled', arg);
}
get enabled() {
return this.data.enabled;
}
set autoPlay(arg) {
this._setValue('autoPlay', arg);
}
get autoPlay() {
return this.data.autoPlay;
}
set numParticles(arg) {
this._setValue('numParticles', arg);
}
get numParticles() {
return this.data.numParticles;
}
set lifetime(arg) {
this._setValue('lifetime', arg);
}
get lifetime() {
return this.data.lifetime;
}
set rate(arg) {
this._setValue('rate', arg);
}
get rate() {
return this.data.rate;
}
set rate2(arg) {
this._setValue('rate2', arg);
}
get rate2() {
return this.data.rate2;
}
set startAngle(arg) {
this._setValue('startAngle', arg);
}
get startAngle() {
return this.data.startAngle;
}
set startAngle2(arg) {
this._setValue('startAngle2', arg);
}
get startAngle2() {
return this.data.startAngle2;
}
set loop(arg) {
this._setValue('loop', arg);
}
get loop() {
return this.data.loop;
}
set preWarm(arg) {
this._setValue('preWarm', arg);
}
get preWarm() {
return this.data.preWarm;
}
set lighting(arg) {
this._setValue('lighting', arg);
}
get lighting() {
return this.data.lighting;
}
set halfLambert(arg) {
this._setValue('halfLambert', arg);
}
get halfLambert() {
return this.data.halfLambert;
}
set intensity(arg) {
this._setValue('intensity', arg);
}
get intensity() {
return this.data.intensity;
}
set depthWrite(arg) {
this._setValue('depthWrite', arg);
}
get depthWrite() {
return this.data.depthWrite;
}
set noFog(arg) {
this._setValue('noFog', arg);
}
get noFog() {
return this.data.noFog;
}
set depthSoftening(arg) {
this._setValue('depthSoftening', arg);
}
get depthSoftening() {
return this.data.depthSoftening;
}
set sort(arg) {
this._setValue('sort', arg);
}
get sort() {
return this.data.sort;
}
set blendType(arg) {
this._setValue('blendType', arg);
}
get blendType() {
return this.data.blendType;
}
set stretch(arg) {
this._setValue('stretch', arg);
}
get stretch() {
return this.data.stretch;
}
set alignToMotion(arg) {
this._setValue('alignToMotion', arg);
}
get alignToMotion() {
return this.data.alignToMotion;
}
set emitterShape(arg) {
this._setValue('emitterShape', arg);
}
get emitterShape() {
return this.data.emitterShape;
}
set emitterExtents(arg) {
this._setValue('emitterExtents', arg);
}
get emitterExtents() {
return this.data.emitterExtents;
}
set emitterExtentsInner(arg) {
this._setValue('emitterExtentsInner', arg);
}
get emitterExtentsInner() {
return this.data.emitterExtentsInner;
}
set emitterRadius(arg) {
this._setValue('emitterRadius', arg);
}
get emitterRadius() {
return this.data.emitterRadius;
}
set emitterRadiusInner(arg) {
this._setValue('emitterRadiusInner', arg);
}
get emitterRadiusInner() {
return this.data.emitterRadiusInner;
}
set initialVelocity(arg) {
this._setValue('initialVelocity', arg);
}
get initialVelocity() {
return this.data.initialVelocity;
}
set wrap(arg) {
this._setValue('wrap', arg);
}
get wrap() {
return this.data.wrap;
}
set wrapBounds(arg) {
this._setValue('wrapBounds', arg);
}
get wrapBounds() {
return this.data.wrapBounds;
}
set localSpace(arg) {
this._setValue('localSpace', arg);
}
get localSpace() {
return this.data.localSpace;
}
set screenSpace(arg) {
this._setValue('screenSpace', arg);
}
get screenSpace() {
return this.data.screenSpace;
}
set colorMapAsset(arg) {
this._setValue('colorMapAsset', arg);
}
get colorMapAsset() {
return this.data.colorMapAsset;
}
set normalMapAsset(arg) {
this._setValue('normalMapAsset', arg);
}
get normalMapAsset() {
return this.data.normalMapAsset;
}
set mesh(arg) {
this._setValue('mesh', arg);
}
get mesh() {
return this.data.mesh;
}
set meshAsset(arg) {
this._setValue('meshAsset', arg);
}
get meshAsset() {
return this.data.meshAsset;
}
set renderAsset(arg) {
this._setValue('renderAsset', arg);
}
get renderAsset() {
return this.data.renderAsset;
}
set orientation(arg) {
this._setValue('orientation', arg);
}
get orientation() {
return this.data.orientation;
}
set particleNormal(arg) {
this._setValue('particleNormal', arg);
}
get particleNormal() {
return this.data.particleNormal;
}
set localVelocityGraph(arg) {
this._setValue('localVelocityGraph', arg);
}
get localVelocityGraph() {
return this.data.localVelocityGraph;
}
set localVelocityGraph2(arg) {
this._setValue('localVelocityGraph2', arg);
}
get localVelocityGraph2() {
return this.data.localVelocityGraph2;
}
set velocityGraph(arg) {
this._setValue('velocityGraph', arg);
}
get velocityGraph() {
return this.data.velocityGraph;
}
set velocityGraph2(arg) {
this._setValue('velocityGraph2', arg);
}
get velocityGraph2() {
return this.data.velocityGraph2;
}
set rotationSpeedGraph(arg) {
this._setValue('rotationSpeedGraph', arg);
}
get rotationSpeedGraph() {
return this.data.rotationSpeedGraph;
}
set rotationSpeedGraph2(arg) {
this._setValue('rotationSpeedGraph2', arg);
}
get rotationSpeedGraph2() {
return this.data.rotationSpeedGraph2;
}
set radialSpeedGraph(arg) {
this._setValue('radialSpeedGraph', arg);
}
get radialSpeedGraph() {
return this.data.radialSpeedGraph;
}
set radialSpeedGraph2(arg) {
this._setValue('radialSpeedGraph2', arg);
}
get radialSpeedGraph2() {
return this.data.radialSpeedGraph2;
}
set scaleGraph(arg) {
this._setValue('scaleGraph', arg);
}
get scaleGraph() {
return this.data.scaleGraph;
}
set scaleGraph2(arg) {
this._setValue('scaleGraph2', arg);
}
get scaleGraph2() {
return this.data.scaleGraph2;
}
set colorGraph(arg) {
this._setValue('colorGraph', arg);
}
get colorGraph() {
return this.data.colorGraph;
}
set colorGraph2(arg) {
this._setValue('colorGraph2', arg);
}
get colorGraph2() {
return this.data.colorGraph2;
}
set alphaGraph(arg) {
this._setValue('alphaGraph', arg);
}
get alphaGraph() {
return this.data.alphaGraph;
}
set alphaGraph2(arg) {
this._setValue('alphaGraph2', arg);
}
get alphaGraph2() {
return this.data.alphaGraph2;
}
set colorMap(arg) {
this._setValue('colorMap', arg);
}
get colorMap() {
return this.data.colorMap;
}
set normalMap(arg) {
this._setValue('normalMap', arg);
}
get normalMap() {
return this.data.normalMap;
}
set animTilesX(arg) {
this._setValue('animTilesX', arg);
}
get animTilesX() {
return this.data.animTilesX;
}
set animTilesY(arg) {
this._setValue('animTilesY', arg);
}
get animTilesY() {
return this.data.animTilesY;
}
set animStartFrame(arg) {
this._setValue('animStartFrame', arg);
}
get animStartFrame() {
return this.data.animStartFrame;
}
set animNumFrames(arg) {
this._setValue('animNumFrames', arg);
}
get animNumFrames() {
return this.data.animNumFrames;
}
set animNumAnimations(arg) {
this._setValue('animNumAnimations', arg);
}
get animNumAnimations() {
return this.data.animNumAnimations;
}
set animIndex(arg) {
this._setValue('animIndex', arg);
}
get animIndex() {
return this.data.animIndex;
}
set randomizeAnimIndex(arg) {
this._setValue('randomizeAnimIndex', arg);
}
get randomizeAnimIndex() {
return this.data.randomizeAnimIndex;
}
set animSpeed(arg) {
this._setValue('animSpeed', arg);
}
get animSpeed() {
return this.data.animSpeed;
}
set animLoop(arg) {
this._setValue('animLoop', arg);
}
get animLoop() {
return this.data.animLoop;
}
set layers(arg) {
this._setValue('layers', arg);
}
get layers() {
return this.data.layers;
}
set drawOrder(drawOrder) {
this._drawOrder = drawOrder;
if (this.emitter) {
this.emitter.drawOrder = drawOrder;
}
}
get drawOrder() {
return this._drawOrder;
}
_setValue(name, value) {
const data = this.data;
const oldValue = data[name];
data[name] = value;
this.fire('set', name, oldValue, value);
}
addMeshInstanceToLayers() {
if (!this.emitter) return;
for(let i = 0; i < this.layers.length; i++){
const layer = this.system.app.scene.layers.getLayerById(this.layers[i]);
if (!layer) continue;
layer.addMeshInstances([
this.emitter.meshInstance
]);
this.emitter._layer = layer;
}
}
removeMeshInstanceFromLayers() {
if (!this.emitter) return;
for(let i = 0; i < this.layers.length; i++){
const layer = this.system.app.scene.layers.getLayerById(this.layers[i]);
if (!layer) continue;
layer.removeMeshInstances([
this.emitter.meshInstance
]);
}
}
onSetLayers(name, oldValue, newValue) {
if (!this.emitter) return;
for(let i = 0; i < oldValue.length; i++){
const layer = this.system.app.scene.layers.getLayerById(oldValue[i]);
if (!layer) continue;
layer.removeMeshInstances([
this.emitter.meshInstance
]);
}
if (!this.enabled || !this.entity.enabled) return;
for(let i = 0; i < newValue.length; i++){
const layer = this.system.app.scene.layers.getLayerById(newValue[i]);
if (!layer) continue;
layer.addMeshInstances([
this.emitter.meshInstance
]);
}
}
onLayersChanged(oldComp, newComp) {
this.addMeshInstanceToLayers();
oldComp.off('add', this.onLayerAdded, this);
oldComp.off('remove', this.onLayerRemoved, this);
newComp.on('add', this.onLayerAdded, this);
newComp.on('remove', this.onLayerRemoved, this);
}
onLayerAdded(layer) {
if (!this.emitter) return;
const index = this.layers.indexOf(layer.id);
if (index < 0) return;
layer.addMeshInstances([
this.emitter.meshInstance
]);
}
onLayerRemoved(layer) {
if (!this.emitter) return;
const index = this.layers.indexOf(layer.id);
if (index < 0) return;
layer.removeMeshInstances([
this.emitter.meshInstance
]);
}
_bindColorMapAsset(asset) {
asset.on('load', this._onColorMapAssetLoad, this);
asset.on('unload', this._onColorMapAssetUnload, this);
asset.on('remove', this._onColorMapAssetRemove, this);
asset.on('change', this._onColorMapAssetChange, this);
if (asset.resource) {
this._onColorMapAssetLoad(asset);
} else {
if (!this.enabled || !this.entity.enabled) return;
this.system.app.assets.load(asset);
}
}
_unbindColorMapAsset(asset) {
asset.off('load', this._onColorMapAssetLoad, this);
asset.off('unload', this._onColorMapAssetUnload, this);
asset.off('remove', this._onColorMapAssetRemove, this);
asset.off('change', this._onColorMapAssetChange, this);
}
_onColorMapAssetLoad(asset) {
this.colorMap = asset.resource;
}
_onColorMapAssetUnload(asset) {
this.colorMap = null;
}
_onColorMapAssetRemove(asset) {
this._onColorMapAssetUnload(asset);
}
_onColorMapAssetChange(asset) {}
onSetColorMapAsset(name, oldValue, newValue) {
const assets = this.system.app.assets;
if (oldValue) {
const asset = assets.get(oldValue);
if (asset) {
this._unbindColorMapAsset(asset);
}
}
if (newValue) {
if (newValue instanceof Asset) {
this.data.colorMapAsset = newValue.id;
newValue = newValue.id;
}
const asset = assets.get(newValue);
if (asset) {
this._bindColorMapAsset(asset);
} else {
assets.once(`add:${newValue}`, (asset)=>{
this._bindColorMapAsset(asset);
});
}
} else {
this.colorMap = null;
}
}
_bindNormalMapAsset(asset) {
asset.on('load', this._onNormalMapAssetLoad, this);
asset.on('unload', this._onNormalMapAssetUnload, this);
asset.on('remove', this._onNormalMapAssetRemove, this);
asset.on('change', this._onNormalMapAssetChange, this);
if (asset.resource) {
this._onNormalMapAssetLoad(asset);
} else {
if (!this.enabled || !this.entity.enabled) return;
this.system.app.assets.load(asset);
}
}
_unbindNormalMapAsset(asset) {
asset.off('load', this._onNormalMapAssetLoad, this);
asset.off('unload', this._onNormalMapAssetUnload, this);
asset.off('remove', this._onNormalMapAssetRemove, this);
asset.off('change', this._onNormalMapAssetChange, this);
}
_onNormalMapAssetLoad(asset) {
this.normalMap = asset.resource;
}
_onNormalMapAssetUnload(asset) {
this.normalMap = null;
}
_onNormalMapAssetRemove(asset) {
this._onNormalMapAssetUnload(asset);
}
_onNormalMapAssetChange(asset) {}
onSetNormalMapAsset(name, oldValue, newValue) {
const assets = this.system.app.assets;
if (oldValue) {
const asset = assets.get(oldValue);
if (asset) {
this._unbindNormalMapAsset(asset);
}
}
if (newValue) {
if (newValue instanceof Asset) {
this.data.normalMapAsset = newValue.id;
newValue = newValue.id;
}
const asset = assets.get(newValue);
if (asset) {
this._bindNormalMapAsset(asset);
} else {
assets.once(`add:${newValue}`, (asset)=>{
this._bindNormalMapAsset(asset);
});
}
} else {
this.normalMap = null;
}
}
_bindMeshAsset(asset) {
asset.on('load', this._onMeshAssetLoad, this);
asset.on('unload', this._onMeshAssetUnload, this);
asset.on('remove', this._onMeshAssetRemove, this);
asset.on('change', this._onMeshAssetChange, this);
if (asset.resource) {
this._onMeshAssetLoad(asset);
} else {
if (!this.enabled || !this.entity.enabled) return;
this.system.app.assets.load(asset);
}
}
_unbindMeshAsset(asset) {
asset.off('load', this._onMeshAssetLoad, this);
asset.off('unload', this._onMeshAssetUnload, this);
asset.off('remove', this._onMeshAssetRemove, this);
asset.off('change', this._onMeshAssetChange, this);
}
_onMeshAssetLoad(asset) {
this._onMeshChanged(asset.resource);
}
_onMeshAssetUnload(asset) {
this.mesh = null;
}
_onMeshAssetRemove(asset) {
this._onMeshAssetUnload(asset);
}
_onMeshAssetChange(asset) {}
onSetMeshAsset(name, oldValue, newValue) {
const assets = this.system.app.assets;
if (oldValue) {
const asset = assets.get(oldValue);
if (asset) {
this._unbindMeshAsset(asset);
}
}
if (newValue) {
if (newValue instanceof Asset) {
this.data.meshAsset = newValue.id;
newValue = newValue.id;
}
const asset = assets.get(newValue);
if (asset) {
this._bindMeshAsset(asset);
}
} else {
this._onMeshChanged(null);
}
}
onSetMesh(name, oldValue, newValue) {
if (!newValue || newValue instanceof Asset || typeof newValue === 'number') {
this.meshAsset = newValue;
} else {
this._onMeshChanged(newValue);
}
}
_onMeshChanged(mesh) {
if (mesh && !(mesh instanceof Mesh)) {
if (mesh.meshInstances[0]) {
mesh = mesh.meshInstances[0].mesh;
} else {
mesh = null;
}
}
this.data.mesh = mesh;
if (this.emitter) {
this.emitter.mesh = mesh;
this.emitter.resetMaterial();
this.rebuild();
}
}
onSetRenderAsset(name, oldValue, newValue) {
const assets = this.system.app.assets;
if (oldValue) {
const asset = assets.get(oldValue);
if (asset) {
this._unbindRenderAsset(asset);
}
}
if (newValue) {
if (newValue instanceof Asset) {
this.data.renderAsset = newValue.id;
newValue = newValue.id;
}
const asset = assets.get(newValue);
if (asset) {
this._bindRenderAsset(asset);
}
} else {
this._onRenderChanged(null);
}
}
_bindRenderAsset(asset) {
asset.on('load', this._onRenderAssetLoad, this);
asset.on('unload', this._onRenderAssetUnload, this);
asset.on('remove', this._onRenderAssetRemove, this);
if (asset.resource) {
this._onRenderAssetLoad(asset);
} else {
if (!this.enabled || !this.entity.enabled) return;
this.system.app.assets.load(asset);
}
}
_unbindRenderAsset(asset) {
asset.off('load', this._onRenderAssetLoad, this);
asset.off('unload', this._onRenderAssetUnload, this);
asset.off('remove', this._onRenderAssetRemove, this);
this._evtSetMeshes?.off();
this._evtSetMeshes = null;
}
_onRenderAssetLoad(asset) {
this._onRenderChanged(asset.resource);
}
_onRenderAssetUnload(asset) {
this._onRenderChanged(null);
}
_onRenderAssetRemove(asset) {
this._onRenderAssetUnload(asset);
}
_onRenderChanged(render) {
if (!render) {
this._onMeshChanged(null);
return;
}
this._evtSetMeshes?.off();
this._evtSetMeshes = render.on('set:meshes', this._onRenderSetMeshes, this);
if (render.meshes) {
this._onRenderSetMeshes(render.meshes);
}
}
_onRenderSetMeshes(meshes) {
this._onMeshChanged(meshes && meshes[0]);
}
onSetLoop(name, oldValue, newValue) {
if (this.emitter) {
this.emitter[name] = newValue;
this.emitter.resetTime();
}
}
onSetBlendType(name, oldValue, newValue) {
if (this.emitter) {
this.emitter[name] = newValue;
this.emitter.material.blendType = newValue;
this.emitter.resetMaterial();
this.rebuild();
}
}
_requestDepth() {
if (this._requestedDepth) return;
if (!depthLayer) depthLayer = this.system.app.scene.layers.getLayerById(LAYERID_DEPTH);
if (depthLayer) {
depthLayer.incrementCounter();
this._requestedDepth = true;
}
}
_releaseDepth() {
if (!this._requestedDepth) return;
if (depthLayer) {
depthLayer.decrementCounter();
this._requestedDepth = false;
}
}
onSetDepthSoftening(name, oldValue, newValue) {
if (oldValue !== newValue) {
if (newValue) {
if (this.enabled && this.entity.enabled) this._requestDepth();
if (this.emitter) this.emitter[name] = newValue;
} else {
if (this.enabled && this.entity.enabled) this._releaseDepth();
if (this.emitter) this.emitter[name] = newValue;
}
if (this.emitter) {
this.reset();
this.emitter.resetMaterial();
this.rebuild();
}
}
}
onSetSimpleProperty(name, oldValue, newValue) {
if (this.emitter) {
this.emitter[name] = newValue;
this.emitter.resetMaterial();
}
}
onSetComplexProperty(name, oldValue, newValue) {
if (this.emitter) {
this.emitter[name] = newValue;
this.emitter.resetMaterial();
this.rebuild();
this.reset();
}
}
onSetGraphProperty(name, oldValue, newValue) {
if (this.emitter) {
this.emitter[name] = newValue;
this.emitter.rebuildGraphs();
this.emitter.resetMaterial();
}
}
onEnable() {
const scene = this.system.app.scene;
const layers = scene.layers;
const data = this.data;
for(let i = 0, len = ASSET_PROPERTIES.length; i < len; i++){
let asset = data[ASSET_PROPERTIES[i]];
if (asset) {
if (!(asset instanceof Asset)) {
const id = parseInt(asset, 10);
if (id >= 0) {
asset = this.system.app.assets.get(asset);
} else {
continue;
}
}
if (asset && !asset.resource) {
this.system.app.assets.load(asset);
}
}
}
if (this.system.app.graphicsDevice.disableParticleSystem) {
return;
}
if (!this.emitter) {
let mesh = data.mesh;
if (!(mesh instanceof Mesh)) {
mesh = null;
}
this.emitter = new ParticleEmitter(this.system.app.graphicsDevice, {
numParticles: data.numParticles,
emitterExtents: data.emitterExtents,
emitterExtentsInner: data.emitterExtentsInner,
emitterRadius: data.emitterRadius,
emitterRadiusInner: data.emitterRadiusInner,
emitterShape: data.emitterShape,
initialVelocity: data.initialVelocity,
wrap: data.wrap,
localSpace: data.localSpace,
screenSpace: data.screenSpace,
wrapBounds: data.wrapBounds,
lifetime: data.lifetime,
rate: data.rate,
rate2: data.rate2,
orientation: data.orientation,
particleNormal: data.particleNormal,
animTilesX: data.animTilesX,
animTilesY: data.animTilesY,
animStartFrame: data.animStartFrame,
animNumFrames: data.animNumFrames,
animNumAnimations: data.animNumAnimations,
animIndex: data.animIndex,
randomizeAnimIndex: data.randomizeAnimIndex,
animSpeed: data.animSpeed,
animLoop: data.animLoop,
startAngle: data.startAngle,
startAngle2: data.startAngle2,
scaleGraph: data.scaleGraph,
scaleGraph2: data.scaleGraph2,
colorGraph: data.colorGraph,
colorGraph2: data.colorGraph2,
alphaGraph: data.alphaGraph,
alphaGraph2: data.alphaGraph2,
localVelocityGraph: data.localVelocityGraph,
localVelocityGraph2: data.localVelocityGraph2,
velocityGraph: data.velocityGraph,
velocityGraph2: data.velocityGraph2,
rotationSpeedGraph: data.rotationSpeedGraph,
rotationSpeedGraph2: data.rotationSpeedGraph2,
radialSpeedGraph: data.radialSpeedGraph,
radialSpeedGraph2: data.radialSpeedGraph2,
colorMap: data.colorMap,
normalMap: data.normalMap,
loop: data.loop,
preWarm: data.preWarm,
sort: data.sort,
stretch: data.stretch,
alignToMotion: data.alignToMotion,
lighting: data.lighting,
halfLambert: data.halfLambert,
intensity: data.intensity,
depthSoftening: data.depthSoftening,
scene: this.system.app.scene,
mesh: mesh,
depthWrite: data.depthWrite,
noFog: data.noFog,
node: this.entity,
blendType: data.blendType
});
this.emitter.meshInstance.node = this.entity;
this.emitter.drawOrder = this.drawOrder;
if (!data.autoPlay) {
this.pause();
this.emitter.meshInstance.visible = false;
}
}
if (this.emitter.colorMap) {
this.addMeshInstanceToLayers();
}
this._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this);
if (layers) {
this._evtLayerAdded = layers.on('add', this.onLayerAdded, this);
this._evtLayerRemoved = layers.on('remove', this.onLayerRemoved, this);
}
if (this.enabled && this.entity.enabled && data.depthSoftening) {
this._requestDepth();
}
}
onDisable() {
const scene = this.system.app.scene;
const layers = scene.layers;
this._evtLayersChanged?.off();
this._evtLayersChanged = null;
if (layers) {
this._evtLayerAdded?.off();
this._evtLayerAdded = null;
this._evtLayerRemoved?.off();
this._evtLayerRemoved = null;
}
if (this.emitter) {
this.removeMeshInstanceFromLayers();
if (this.data.depthSoftening) this._releaseDepth();
this.emitter.camera = null;
}
}
onBeforeRemove() {
if (this.enabled) {
this.enabled = false;
}
if (this.emitter) {
this.emitter.destroy();
this.emitter = null;
}
for(let i = 0; i < ASSET_PROPERTIES.length; i++){
const prop = ASSET_PROPERTIES[i];
if (this.data[prop]) {
this[prop] = null;
}
}
this.off();
}
reset() {
if (this.emitter) {
this.emitter.reset();
}
}
stop() {
if (this.emitter) {
this.emitter.loop = false;
this.emitter.resetTime();
this.emitter.addTime(0, true);
}
}
pause() {
this.data.paused = true;
}
unpause() {
this.data.paused = false;
}
play() {
this.data.paused = false;
if (this.emitter) {
this.emitter.meshInstance.visible = true;
this.emitter.loop = this.data.loop;
this.emitter.resetTime();
}
}
isPlaying() {
if (this.data.paused) {
return false;
}
if (this.emitter && this.emitter.loop) {
return true;
}
return Date.now() <= this.emitter.endTime;
}
setInTools() {
const { emitter } = this;
if (emitter && !emitter.inTools) {
emitter.inTools = true;
this.rebuild();
}
}
rebuild() {
const enabled = this.enabled;
this.enabled = false;
if (this.emitter) {
this.emitter.rebuild();
}
this.enabled = enabled;
}
}
export { ParticleSystemComponent };