import { Utils } from '../common/Utils';
import { BaseTickableObject3D } from './BaseTickableObject3D';
import { ParticleGroup } from './ParticleGroup';
import { Object3D } from './Object3D';
import { StyleModifier } from '../resources/StyleModifier';
import { Style } from '../resources/Style';
let dummyStyle;
/**
* @class ParticleSystem
* The particle system object.
* @memberof THING
* @extends THING.BaseTickableObject3D
* @public
*/
class ParticleSystem extends BaseTickableObject3D {
/**
* The particle system object in scene.
* @param {Object} param The initial parameters.
*/
constructor(param = {}) {
super(param);
const gl = this.app.camera.bodyNode.$uAppView._renderer.context;
const sizeMax = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)[1];
if (sizeMax < 1024) {
console.warn("The maximum settable gl_pointSize supported by the current browser is " + sizeMax + ", when the calculated value exceeds this value, the display may be incorrect.");
}
}
// #region BaseObject Interface
onUpdate(deltaTime) {
if (this.loaded) {
this.bodyNode.update(deltaTime, this.app.camera.node);
}
}
getStyle() {
dummyStyle = dummyStyle || new Style(new StyleModifier(new Object3D({ parent: null })));
console.warn("This interface cannot be used for particle!");
return dummyStyle;
}
/**
* Add group.
* @param {ParticleGroup} group The group.
* @returns {ParticleGroup}
* @public
* @example
* const group = new THING.ParticleGroup();
* particleSystem.addGroup(group);
*/
addGroup(group) {
let node = group.node;
if (!this.node) {
return;
}
this.node.addGroup(node);
this._updateGroups();
return this.groups[this.groups.length - 1];
}
/**
* Remove group.
* @param {ParticleGroup} group The group.
* @public
* @example
* const groups = particleSystem.getGroups();
* particleSystem.removeGroup(groups[0]);
*/
removeGroup(group) {
if (!this.node) {
return;
}
if (this.groups.length == 0) {
return;
}
this.node.removeGroup(group.node);
this._updateGroups();
}
_updateGroups() {
this._groups = [];
const that = this;
this.getGroups().forEach(node => {
const group = new ParticleGroup({ node });
that._groups.push(group);
})
}
/**
* Get group.
* @returns {Array<ParticleGroup>}
* @private
* @example
* const groups = particleSystem.getGroups();
*/
getGroups() {
return this.node.getGroups();
}
/**
* Get current ParticleSystem data.
* @param {Object} param { dataVersion2:false } Get data for thingjs2.0 when dataVersion2 is true.
* @returns {Object} ParticleSystem data
* @public
* @example
* const data = particleSystem.getParticleData({ dataVersion2:false });
*/
getParticleData(param) {
return this.node.getParticleData(param);
}
/**
* Set root path.
* @param {String} The root path.
* @private
*/
setRootPath(value) {
this.node.setRootPath(value);
}
/**
* Get root path.
* @returns {String}
* @private
*/
getRootPath() {
return this.node.getRootPath();
}
// #endregion
// #region Resources
/**
* When load reosurce.
* @param {Object} options The options to load.
* @param {Function} resolve The promise resolve callback function.
* @param {Function} reject The promise reject callback function.
* @private
*/
onLoadResource(options, resolve, reject) {
let dynamic = Utils.parseValue(options['dynamic'], false);
if (!dynamic) {
let app = this.app;
options['screenSize'] = options['screenSize'] || app.size;
options['maxVaryings'] = options['maxVaryings'] || app.renderCapabilities.maxVaryings;
// Start to load particle resource
let url = this.resource.url;
if (url) {
app.resourceManager.loadParticle(
this.resource.url,
(ev) => {
this.body.setNode(ev.node);
resolve();
},
(ev) => {
},
(ev) => {
reject(ev);
},
options
);
}
// Load from data
else if (options['data']) {
let node = app.resourceManager.parseParticle(options['data'], options);
if (node) {
this.body.setNode(node);
resolve();
}
else {
reject(`Parse particle data failed`);
}
}
else {
// Create default particle
const node = Utils.createObject('ParticleSystem');
const particleGroup = Utils.createObject('ParticleGroup');
const particleEmitter = Utils.createObject('ParticleEmitter');
node.addGroup(particleGroup);
particleGroup.addEmitter(particleEmitter);
this.body.setNode(node);
resolve();
}
}
else {
resolve();
}
}
// #endregion
// #region Accessor
/**
* Get groups.
* @type {Array<ParticleGroup>}
* @public
*/
get groups() {
if (!this._groups) {
this._updateGroups();
}
return this._groups;
}
// #endregion
/**
* Check whether it's ParticleSystem type or inherit from it.
* @type {Boolean}
* @public
*/
get isParticleSystem() {
return true;
}
}
export { ParticleSystem }