/** * Creates a Particle object * @param graphics GameLib.GraphicsRuntime * @param apiParticle GameLib.D3.API.Particle * @constructor */ GameLib.D3.Particle = function( graphics, apiParticle ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(apiParticle)) { apiParticle = {}; } GameLib.D3.API.Particle.call( this, apiParticle.id, apiParticle.name, apiParticle.lifeTime, apiParticle.elapsed, apiParticle.mesh, apiParticle.opacityType, apiParticle.opacityFactor, apiParticle.positionOffsetType, apiParticle.positionOffset, apiParticle.positionOffsetFn, apiParticle.directionType, apiParticle.direction, apiParticle.directionFn, apiParticle.speedType, apiParticle.speed, apiParticle.scaleType, apiParticle.scale, apiParticle.scaleFn, apiParticle.rotationType, apiParticle.rotation, apiParticle.rotationFn, apiParticle.parentParticleEngine, apiParticle.parentEntity ); if (this.mesh instanceof GameLib.D3.API.Mesh) { this.mesh = new GameLib.D3.Mesh( graphics, this.mesh ) } this.positionOffset = new GameLib.Vector3( graphics, this.positionOffset, this ); this.direction = new GameLib.Vector3( graphics, this.direction, this ); this.scale = new GameLib.Vector3( graphics, this.scale, this ); this.rotation = new GameLib.Vector3( graphics, this.rotation, this ); GameLib.Component.call( this, { mesh : GameLib.D3.Mesh, parentParticleEngine : GameLib.D3.ParticleEngine } ); }; GameLib.D3.Particle.prototype = Object.create(GameLib.Component.prototype); GameLib.D3.Particle.prototype.constructor = GameLib.D3.Particle; GameLib.D3.Particle.OPACITY_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.OPACITY_TYPE_DECREASE_LINEAR = 0x2; GameLib.D3.Particle.OPACITY_TYPE_INCREASE_LINEAR = 0x3; GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.POSITION_OFFSET_TYPE_RANDOM = 0x2; GameLib.D3.Particle.POSITION_OFFSET_TYPE_FUNCTION = 0x3; GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.DIRECTION_TYPE_RANDOM = 0x2; GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED = 0x3; GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION = 0x4; GameLib.D3.Particle.SCALE_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.SCALE_TYPE_LINEAR = 0x2; GameLib.D3.Particle.SCALE_TYPE_EXPONENTIAL = 0x3; GameLib.D3.Particle.SCALE_TYPE_RANDOM = 0x4; GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y = 0x6; GameLib.D3.Particle.SCALE_TYPE_FUNCTION = 0x7; GameLib.D3.Particle.SPEED_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.SPEED_TYPE_LINEAR = 0x2; GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL = 0x3; GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC = 0x4; GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG = 0x5; GameLib.D3.Particle.SPEED_TYPE_EXP = 0x6; GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP = 0x7; GameLib.D3.Particle.ROTATION_TYPE_CONSTANT = 0x1; GameLib.D3.Particle.ROTATION_TYPE_RANDOM = 0x2; GameLib.D3.Particle.ROTATION_TYPE_FUNCTION = 0x3; /** * Particle create instance */ GameLib.D3.Particle.prototype.createInstance = function() { if (!this.mesh) { console.warn('no mesh to clone from - failed dependency check?'); return } this.instance = this.mesh.instance; GameLib.Component.prototype.createInstance.call(this); }; /** * Updates the instance with the current state */ GameLib.D3.Particle.prototype.updateInstance = function(property) { if (property === 'positionOffset') { this.positionOffset.instance.x = this.positionOffset.x; this.positionOffset.instance.y = this.positionOffset.y; this.positionOffset.instance.z = this.positionOffset.z; } if (property === 'direction') { this.direction.instance.x = this.direction.x; this.direction.instance.y = this.direction.y; this.direction.instance.z = this.direction.z; } if (property === 'scale') { this.scale.instance.x = this.scale.x; this.scale.instance.y = this.scale.y; this.scale.instance.z = this.scale.z; } if (property === 'rotation') { this.rotation.instance.x = this.rotation.x; this.rotation.instance.y = this.rotation.y; this.rotation.instance.z = this.rotation.z; } }; /** * Clones a particle - this only clones 3rd party instances, so we have less overhead of creating these types of objects */ GameLib.D3.Particle.prototype.cloneInstance = function() { this.updateInstance('positionOffset'); this.updateInstance('direction'); this.updateInstance('scale'); this.updateInstance('rotation'); var clone = GameLib.Component.prototype.cloneInstance.call(this); clone.position = this.parentParticleEngine.position.instance.clone(); clone.material = this.mesh.materials[0].instance.clone(); clone.visible = true; if (this.positionOffsetType === GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT) { clone.position.add(this.positionOffset.instance); } var addX = 1; var addY = 1; var addZ = 1; if (this.positionOffsetType === GameLib.D3.Particle.POSITION_OFFSET_TYPE_RANDOM) { addX = GameLib.Utils.GetRandomIntInclusive(1,2); addY = GameLib.Utils.GetRandomIntInclusive(1,2); addZ = GameLib.Utils.GetRandomIntInclusive(1,2); if (addX === 1) { clone.position.x += Math.random() * this.positionOffset.x; } else { clone.position.x -= Math.random() * this.positionOffset.x; } if (addY === 1) { clone.position.y -= Math.random() * this.positionOffset.y; } else { clone.position.y += Math.random() * this.positionOffset.y; } if (addZ === 1) { clone.position.z -= Math.random() * this.positionOffset.z; } else { clone.position.z += Math.random() * this.positionOffset.z; } } clone.userData.direction = this.direction.clone(); if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT) { /** * Nothing to do */ } else if ( this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM || this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED ) { addX = GameLib.Utils.GetRandomIntInclusive(1,2); addY = GameLib.Utils.GetRandomIntInclusive(1,2); addZ = GameLib.Utils.GetRandomIntInclusive(1,2); clone.userData.direction.x = 0; clone.userData.direction.y = 0; clone.userData.direction.z = 0; if (addX === 1) { clone.userData.direction.x += Math.random() * this.direction.x; } else { clone.userData.direction.x -= Math.random() * this.direction.x; } if (addY === 1) { clone.userData.direction.y -= Math.random() * this.direction.y; } else { clone.userData.direction.y += Math.random() * this.direction.y; } if (addZ === 1) { clone.userData.direction.z -= Math.random() * this.direction.z; } else { clone.userData.direction.z += Math.random() * this.direction.z; } if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED) { clone.userData.direction.normalize(); } } else { throw new Error('not yet implemented') } if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_CONSTANT) { clone.scale.x += this.scale.x; clone.scale.y += this.scale.y; clone.scale.z += this.scale.z; } if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_RANDOM) { add = GameLib.Utils.GetRandomIntInclusive(1,2); if (add === 1) { clone.scale.x += Math.random() * this.scale.x; clone.scale.y += Math.random() * this.scale.y; clone.scale.z += Math.random() * this.scale.z; } else { clone.scale.x -= Math.random() * this.scale.x; clone.scale.y -= Math.random() * this.scale.y; clone.scale.z -= Math.random() * this.scale.z; } } if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y) { add = GameLib.Utils.GetRandomIntInclusive(1,2); var factor = Math.random() * this.scale.x; if (add === 1) { clone.scale.x += factor; clone.scale.y += factor; clone.scale.z += Math.random() * this.scale.z; } else { clone.scale.x -= factor; clone.scale.y -= factor; clone.scale.z -= Math.random() * this.scale.z; } } clone.userData.scale = this.scale.clone(); clone.userData.lifeTime = this.lifeTime; clone.userData.speedType = this.speedType; clone.userData.speed = this.speed; clone.userData.scene = this.mesh.parentScene.instance; clone.userData.elapsed = 0; clone.userData.scene.add(clone); return clone; }; /** * Converts a GameLib.D3.Particle to a new GameLib.D3.API.Particle * @returns {GameLib.D3.API.Particle} */ GameLib.D3.Particle.prototype.toApiObject = function() { return new GameLib.D3.API.Particle( this.id, this.name, this.lifeTime, this.elapsed, GameLib.Utils.IdOrNull(this.mesh), this.opacityType, this.opacityFactor, this.positionOffsetType, this.positionOffset.toApiObject(), this.positionOffsetFn, this.directionType, this.direction.toApiObject(), this.directionFn, this.speedType, this.speed, this.scaleType, this.scale.toApiObject(), this.scaleFn, this.rotationType, this.rotation.toApiObject(), this.rotationFn, GameLib.Utils.IdOrNull(this.parentParticleEngine), GameLib.Utils.IdOrNull(this.parentEntity) ); }; /** * Converts from an Object Particle to a GameLib.D3.Particle * @param graphics GameLib.GraphicsRuntime * @param objectParticle Object * @returns {GameLib.D3.Particle} * @constructor */ GameLib.D3.Particle.FromObject = function(graphics, objectParticle) { var apiParticle = GameLib.D3.API.Particle.FromObject(objectParticle); return new GameLib.D3.Particle( graphics, apiParticle ); };