import { ObjectProxy } from '@uino/base-thing';
import { Utils } from '../common/Utils'
const __ = {
private: Symbol('private'),
}
/**
* @class ParticleEmitter
* The particle emitter.
* @memberof THING
* @public
* @example
* const emitter = new THING.ParticleEmitter();
* emitter.particleCount = 100;
* emitter.distribution = 1;
* emitter.duration = 2;
* emitter.isLookAtCamera = true;
* emitter.isLookAtCameraY = true;
* emitter.wiggle = {
* spread:0,
* value:0
* };
* emitter.rotation = {
* axisSpread:[0, 0, 0],
* randomise:false,
* angleSpread:0,
* center:[0, 0, 0],
* angle:0,
* static:false,
* axis:[0, 1, 0]
* };
* emitter.velocity = {
* randomise:false,
* value:[0, 25, 0],
* distribution:1,
* spread:[10, 7.5, 10]
* };
* emitter.size = {
* randomise:[false, false],
* spread:[0, 0],
* value:[2, 0]
* };
* emitter.angle = {
* randomise:[false, false],
* spread:[0, 0],
* value:[1, 0]
* };
* emitter.opacity = {
* randomise:[false, false],
* spread:[0, 0],
* value:[1, 0.1]
* };
* emitter.color = {
* randomise:[false, false],
* spread:[[0, 0, 0], [0, 0, 0]],
* value:[[0, 0, 0], [1, 1, 0]]
* };
* emitter.acceleration = {
* randomise:false,
* value:[0, -10, 0],
* distribution:1,
* spread:[0, 0, 0]
* };
* emitter.maxAge = {
* spread:0,
* value:2
* };
* emitter.position = {
* randomise:false,
* radius:10,
* spreadClamp:[0, 0, 0],
* value:[0, 0, -50],
* radiusScale:[1, 1, 1],
* distribution:1,
* spread:[0, 0, 0]
* };
* emitter.drag = {
* randomise:false,
* spread:0,
* value:0
* };
*/
class ParticleEmitter {
constructor(param = {}) {
this.node = param['node'] || Utils.createObject('ParticleEmitter');
this[__.private] = {};
let _private = this[__.private];
_private.maxAge = this.node.getAttribute('MaxAge');
_private.position = this.node.getAttribute('Position');
_private.rotation = this.node.getAttribute('Rotation');
_private.velocity = this.node.getAttribute('Velocity');
_private.listColor = this.node.getAttribute('ListColor');
_private.listOpacity = this.node.getAttribute('ListOpacity');
_private.listSize = this.node.getAttribute('ListSize');
_private.listAngle = this.node.getAttribute('ListAngle');
_private.acceleration = this.node.getAttribute('Acceleration');
_private.drag = this.node.getAttribute('Drag');
_private.onChange = null;
const that = this;
_private.objectProxy = new ObjectProxy({
data: {
MaxAge: _private.maxAge,
Position: _private.position,
Rotation: _private.rotation,
Velocity: _private.velocity,
ListColor: _private.listColor,
ListOpacity: _private.listOpacity,
ListSize: _private.listSize,
ListAngle: _private.listAngle,
Acceleration: _private.acceleration,
Drag: _private.drag,
},
onChange: function (ev) {
that.setAttribute(ev.propName, ev.data[ev.propName]);
if (_private.onChange) {
_private.onChange(ev);
}
}
});
}
/**
* Get attribute.
* @param {ParticleEmitterAttributeType} key The key
* @returns {any}
* @public
*/
getAttribute(key) {
return this.node.getAttribute(key);
}
/**
* Set attribute.
* @param {ParticleEmitterAttributeType} key The key
* @param {any} value The value.
* @public
*/
setAttribute(key, value) {
this.node.setAttribute(key, value);
}
// #region Accessors
/**
* Get/Set particle count.The count of particle when rendering.
* @type {Number}
* @public
*/
get particleCount() {
return this.getAttribute('ParticleCount');
}
set particleCount(value) {
this.setAttribute('ParticleCount', value);
}
/**
* Get/Set direction.The direction of the particle. If value is `1`, particle will start at beginning of particle's lifecycle.If value is `-1`, particle will start at end of particle's lifecycle and work it's way backwards.
* @type {Number}
* @public
*/
get direction() {
return this.getAttribute('Direction');
}
set direction(value) {
this.setAttribute('Direction', value);
}
/**
* Get/Set isStatic.True indicates these particles should be not be simulated.
* @type {Boolean}
* @public
*/
get isStatic() {
return this.getAttribute('IsStatic');
}
set isStatic(value) {
this.setAttribute('IsStatic', value);
}
/**
* Get/Set active multiplier.A value between 0 and 1 describing what percentage of this particle's particlesPerSecond should be emitted, where 0 is 0%, and 1 is 100%.
* @type {Number}
* @public
*/
get activeMultiplier() {
return this.getAttribute('ActiveMultiplier');
}
set activeMultiplier(value) {
this.setAttribute('ActiveMultiplier', value);
}
/**
* Get/Set distribution.It use to control its particle's spawn position and force behaviour.The options are 1(Box),2(Sphere),3(Disc),4(Line).
* @type {Number}
* @public
*/
get distribution() {
return this.getAttribute('Distribution');
}
set distribution(value) {
this.setAttribute('Distribution', value);
}
/**
* Get/Set duration.The duration in seconds that this emitter should live for.If not specified, the emitter will emit particles indefinitely.
* @type {Number|null}
* @public
*/
get duration() {
return this.getAttribute('Duration');
}
set duration(value) {
this.setAttribute('Duration', value);
}
/**
* Get/Set IsLookAtCamera.It takes effect when UseMesh is true.True indicates its particle will always look at camera.
* @type {Boolean}
* @public
*/
get isLookAtCamera() {
return this.getAttribute('IsLookAtCamera');
}
set isLookAtCamera(value) {
this.setAttribute('IsLookAtCamera', value);
}
/**
* Get/Set IsLookAtCamera.It takes effect when UseMesh is true.True indicates its particle will always look at camera and lock y-axis.
* @type {Boolean}
* @public
*/
get isLookAtCameraY() {
return this.getAttribute('IsLookAtCameraY');
}
set isLookAtCameraY(value) {
this.setAttribute('IsLookAtCameraY', value);
}
/**
* The particle's maximum age attribute.
* @typedef {Object} MaxAge
* @property {Number} value A number describing the amount of maxAge to apply to all particles.
* @property {Number} spread A number describing the maxAge variance on a per-particle basis.
*/
/**
* Get/Set maxAge attribute.
* @type {MaxAge}
* @public
*/
get maxAge() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.MaxAge;
}
set maxAge(value) {
for (let i in value) {
switch (i) {
default:
this.maxAge[i] = value[i];
break;
}
}
}
/**
* The emitter's position attribute.
* @typedef {Object} Position
* @property {Array<Number>} value An array describing this emitter's base position.
* @property {Array<Number>} spread An array describing this emitter's position variance on a per-particle basis.
* @property {Array<Number>} spreadClamp An array describing the numeric multiples the particle's should be spread out over.
* @property {Number} radius This emitter's base radius.
* @property {Array<Number>} radiusScale An array describing the radius's scale in all three axes.
* @property {Number} distribution A specific distribution to use when radiusing particles. Overrides the `ParticleEmitterAttributeType.Distribution` option.
* @property {Boolean} randomise When a particle is re-spawned, whether it's position should be re-randomised or not.
*/
/**
* Get position.
* @type {Position}
* @public
*/
get position() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.Position;
}
set position(value) {
for (let i in value) {
switch (i) {
default:
this.position[i] = value[i];
break;
}
}
}
/**
* The emitter's rotation attribute.
* @typedef {Object} Rotation
* @property {Array<Number>} axis An array describing this emitter's axis of rotation.
* @property {Array<Number>} axisSpread An array describing the amount of variance to apply to the axis of rotation on a per-particle basis.
* @property {Number} angle The angle of rotation, given in radians. If `Rotation.static` is true, the emitter will start off rotated at this angle, and stay as such.
* Otherwise, the particles will rotate from 0radians to this value over their lifetimes.
* @property {Number} angleSpread The amount of variance in each particle's rotation angle.
* @property {Boolean} static Whether the rotation should be static or not.
* @property {Array<Number>} center An array describing the center point of rotation.
* @property {Boolean} randomise When a particle is re-spawned, whether it's rotation should be re-randomised or not.
*/
/**
* Get rotation.
* @type {Rotation}
* @public
*/
get rotation() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.Rotation;
}
set rotation(value) {
for (let i in value) {
switch (i) {
default:
this.rotation[i] = value[i];
break;
}
}
}
/**
* The emitter's velocity attribute.
* @typedef {Object} Velocity
* @property {Array<Number>} value An array describing this emitter's base velocity.
* @property {Array<Number>} spread An array describing this emitter's velocity variance on a per-particle basis.
* @property {Number} distribution A specific distribution to use when calculating a particle's velocity. Overrides the `ParticleEmitterAttributeType.Distribution` option.
* @property {Boolean} randomise When a particle is re-spawned, whether it's velocity should be re-randomised or not.
*/
/**
* Get velocity.
* @type {Velocity}
* @public
*/
get velocity() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.Velocity;
}
set velocity(value) {
for (let i in value) {
switch (i) {
default:
this.velocity[i] = value[i];
break;
}
}
}
/**
* The emitter's color attribute.
* @typedef {Object} ListColor
* @property {Array<Number>} value Either an array, or multiple arrays to describe the color of a particle over it's lifetime.
* @property {Array<Number>} spread Either an array, or multiple arrays to describe the color variance of a particle over it's lifetime.
* @property {Boolean} randomise When a particle is re-spawned, whether it's color should be re-randomised or not.
*/
/**
* Get color.
* @type {ListColor}
* @public
*/
get color() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.ListColor;
}
set color(value) {
for (let i in value) {
switch (i) {
default:
this.color[i] = value[i];
break;
}
}
}
/**
* The emitter's opacity attribute.
* @typedef {Object} ListOpacity
* @property {Number} value Either a number, or an array of numbers to describe the opacity of a particle over it's lifetime.
* @property {Number} spread Either a number, or an array of numbers to describe the opacity variance of a particle over it's lifetime.
* @property {Boolean} randomise When a particle is re-spawned, whether it's opacity should be re-randomised or not.
*/
/**
* Get opacity.
* @type {ListOpacity}
* @public
*/
get opacity() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.ListOpacity;
}
set opacity(value) {
for (let i in value) {
switch (i) {
default:
this.opacity[i] = value[i];
break;
}
}
}
/**
* The emitter's size attribute.
* @typedef {Object} ListSize
* @property {Number} value Either a number, or an array of numbers to describe the size of a particle over it's lifetime.
* @property {Number} spread Either a number, or an array of numbers to describe the size variance of a particle over it's lifetime.
* @property {Boolean} randomise When a particle is re-spawned, whether it's size should be re-randomised or not.
*/
/**
* Get size.
* @type {ListSize}
* @public
*/
get size() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.ListSize;
}
set size(value) {
for (let i in value) {
switch (i) {
default:
this.size[i] = value[i];
break;
}
}
}
/**
* The emitter's angle attribute.
* @typedef {Object} ListAngle
* @property {Number} value Either a number, or an array of numbers to describe the angle of a particle over it's lifetime.
* @property {Number} spread Either a number, or an array of numbers to describe the angle variance of a particle over it's lifetime.
* @property {Boolean} randomise When a particle is re-spawned, whether it's angle should be re-randomised or not.
*/
/**
* Get angle.
* @type {ListAngle}
* @public
*/
get angle() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.ListAngle;
}
set angle(value) {
for (let i in value) {
switch (i) {
default:
this.angle[i] = value[i];
break;
}
}
}
/**
* The emitter's acceleration attribute.
* @typedef {Object} Acceleration
* @property {Array<Number>} value An array describing this emitter's base acceleration.
* @property {Array<Number>} spread An array describing this emitter's acceleration variance on a per-particle basis.
* @property {Number} distribution A specific distribution to use when calculating a particle's acceleration. Overrides the `ParticleEmitterAttributeType.Distribution` option.
* @property {Boolean} randomise When a particle is re-spawned, whether it's acceleration should be re-randomised or not.
*/
/**
* Get acceleration.
* @type {Acceleration}
* @public
*/
get acceleration() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.Acceleration;
}
set acceleration(value) {
for (let i in value) {
switch (i) {
default:
this.acceleration[i] = value[i];
break;
}
}
}
/**
* The emitter's drag attribute.
* @typedef {Object} Drag
* @property {Number} value A number between 0 and 1 describing the amount of drag to apply to all particles.
* @property {Number} spread A number describing the drag variance on a per-particle basis.
* @property {Boolean} randomise When a particle is re-spawned, whether it's drag should be re-randomised or not.
*/
/**
* Get drag attribute.
* @type {Drag}
* @public
*/
get drag() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.Drag;
}
set drag(value) {
for (let i in value) {
switch (i) {
default:
this.drag[i] = value[i];
break;
}
}
}
/**
* Get/Set when change callback function.
* @type {Function}
* @private
*/
get onChange() {
let _private = this[__.private];
return _private.onChange;
}
set onChange(value) {
let _private = this[__.private];
_private.onChange = value;
}
// #endregion
}
export { ParticleEmitter }