Source: objects/ParticleGroup.js

import { Utils } from '../common/Utils';
import { ParticleEmitter } from './ParticleEmitter';

const __ = {
	private: Symbol('private'),
}

/**
 * @class ParticleGroup
 * The particle group.
 * @memberof THING
 * @public
 * @example
 * const group = new THING.ParticleGroup();
 * group.maxParticleCount = 200;
 * group.useMesh = false;
 * group.meshUrl = "BuildIn/Box";
 * group.texture = {
 * 	url:"./particle.png"
 * };
 * group.blendingMode = "normal";
 * group.isTransparent = true;
 * group.alphaTest = true;
 * group.depthWrite = false;
 * group.depthTest = false;
 * group.url = "./particle.png";
 */
class ParticleGroup {

	constructor(param = {}) {
		this.node = param['node'] || Utils.createObject('ParticleGroup');
	}


	/**
	 * Get attribute.
	 * @param {ParticleGroupAttributeType} key The key.
	 * @returns {any}
	 * @public
	 */
	getAttribute(key) {
		return this.node.getAttribute(key);
	}

	/**
	 * Set attribute.
	 * @param {ParticleGroupAttributeType} key The key.
	 * @param {any} value The value.
	 * @public
	 */
	setAttribute(key, value) {
		if (key === "Texture") {
			this.node.setAttribute(key, value.getTextureResource());
		}
		else {
			this.node.setAttribute(key, value);
		}
	}

	/**
	 * Add emitter.
	 * @param {ParticleEmitter} emitter The emitter.
	 * @returns {ParticleEmitter}
	 * @public
	 * @example
	 * const emitter = new THING.ParticelEmitter();
	 * group.addEmitter(emitter);
	 */
	addEmitter(emitter) {
		let node = emitter.node;

		if (!this.node) {
			return;
		}

		this.node.addEmitter(node);

		this._updateEmitters();

		return this.emitters[this.emitters.length - 1];
	}

	/**
	 * Remove emitter by ParticleEmitter.
	 * @param {ParticleEmitter} emitter The emitter.
	 * @public
	 * @example
	 * const emitter = group.getEmitters();
	 * group.removeEmitter(emitter);
	 */
	removeEmitter(emitter) {
		if (!this.node) {
			return;
		}

		if (this.emitters.length == 0) {
			return;
		}

		this.node.removeEmitter(emitter.node);
		this._updateEmitters();
	}


	_updateEmitters() {
		this._emitters = [];
		const that = this;
		this.getEmitters().forEach(node => {
			const _emitter = new ParticleEmitter({ node });
			that._emitters.push(_emitter);
		})
	}

	/**
	 * Get emitters.
	 * @returns {Array<ParticleEmitter>}
	 * @private
	 * @example
	 * const emitter = group.getEmitters();
	 */
	getEmitters() {
		return this.node.getEmitters();
	}

	// #region Accessor

	/**
	 * Get emitters.
	 * @type {Array<ParticleEmitter>}
	 * @public
	 */
	get emitters() {
		if (!this._emitters) {
			this._updateEmitters();
		}

		return this._emitters;
	}


	/**
	 * Get/Set maxParticleCount.The max count of these particle.
	 * @type {Number}
	 * @public
	 */
	get maxParticleCount() {
		return this.getAttribute('MaxParticleCount');
	}
	set maxParticleCount(value) {
		return this.setAttribute('MaxParticleCount', value);
	}

	/**
	 * Get/Set useMesh.True indicates these particle use mesh but not points.
	 * @type {Boolean}
	 * @public
	 */
	get useMesh() {
		return this.getAttribute('UseMesh');
	}
	set useMesh(value) {
		this.setAttribute('UseMesh', value);
		for (let i = 0; i < this.emitters.length; i++) {
			this.emitters[i].node = this.node._emitters[i];
		}
	}

	/**
	 * Get/Set mesh url.It takes effect when UseMesh is true, and indicates particle mesh type.The options are 'BuildIn/Box', 'BuildIn/Plane', 'BuildIn/Sphere'.
	 * @type {String}
	 * @public
	 */
	get meshUrl() {
		return this.getAttribute('MeshUrl');
	}
	set meshUrl(value) {
		this.setAttribute('MeshUrl', value);
	}

	/**
	 * Get/Set mesh parmas.It takes effect when UseMesh is true, and indicates particle mesh type's attribute.
	 * @type {Array}
	 * @public
	 */
	get meshParams() {
		return this.getAttribute('MeshParams');
	}
	set meshParams(value) {
		this.setAttribute('MeshParams', value);
	}

	/**
	 * Get/Set texture.The image value of particle.
	 * @type {ImageTextureResource}
	 * @public
	 */
	get texture() {
		return this.getAttribute('Texture');
	}
	set texture(value) {
		this.setAttribute('Texture', value);
	}

	/**
	 * The texture's animation attribute.
	 * @typedef {Object} TextureAnimation
	 * @property {Array<Number>} frames The number of frames on the x- and y-axis of the given texture.
	 * @property {Number} frameCount The total number of frames in the sprite-sheet.
	 * @property {Number} loop The number of loops through the sprite-sheet that should be performed over the course of a single particle's lifetime.
	 */

	/**
	 * Get/Set textureAnimation.
	 * @type {TextureAnimation}
	 * @public
	 */
	get textureAnimation() {
		return this.getAttribute('TextureAnimation');
	}
	set textureAnimation(value) {
		this.setAttribute('TextureAnimation', value);
	}

	/**
	 * Get/Set blend mode.The blend mode of these particle.The options are 'none', 'normal', 'add', 'sub', 'mul', 'custom'.
	 * @type {String}
	 * @public
	 */
	get blendingMode() {
		return this.getAttribute('BlendingMode');
	}
	set blendingMode(value) {
		this.setAttribute('BlendingMode', value);
	}

	/**
	 * Get/Set isTransparent.True indicates these particle's should be rendered with transparency.
	 * @type {Boolean}
	 * @public
	 */
	get isTransparent() {
		return this.getAttribute('IsTransparent');
	}
	set isTransparent(value) {
		this.setAttribute('IsTransparent', value);
	}

	/**
	 * Get/Set isColorize.True indicates these particles should be rendered with color, or the only color of particles will come from the provided texture.
	 * @type {Boolean}
	 * @public
	 */
	get isColorize() {
		return this.getAttribute('IsColorize');
	}
	set isColorize(value) {
		this.setAttribute('IsColorize', value);
	}

	/**
	 * Get/Set alphaTest.Sets the alpha value to particle. Value between 0 and 1.
	 * @type {Number}
	 * @public
	 */
	get alphaTest() {
		return this.getAttribute('AlphaTest');
	}
	set alphaTest(value) {
		this.setAttribute('AlphaTest', value);
	}

	/**
	 * Get/Set depthWrite.Sets the depthWrite to particle.
	 * @type {Boolean}
	 * @public
	 */
	get depthWrite() {
		return this.getAttribute('DepthWrite');
	}
	set depthWrite(value) {
		this.setAttribute('DepthWrite', value);
	}

	/**
	 * Get/Set depthTest.Sets the depthTest to particle.
	 * @type {Boolean}
	 * @public
	 */
	get depthTest() {
		return this.getAttribute('DepthTest');
	}
	set depthTest(value) {
		this.setAttribute('DepthTest', value);
	}

	/**
	 * Get/Set texture url.The image url of particle.
	 * @type {String}
	 * @public
	 */
	get url() {
		return this.getAttribute('Url');
	}
	set url(value) {
		this.setAttribute('Url', value);
	}

	/**
	 * Get/Set fog.True indicates these particles should be affected by their scene's fog.
	 * @type {Boolean}
	 * @public
	 */
	get fog() {
		return this.getAttribute('Fog');
	}
	set fog(value) {
		this.setAttribute('Fog', value);
	}

	// #endregion

}


export { ParticleGroup }