diff --git a/src/core/asset/interfaces/IAssetData.ts b/src/core/asset/interfaces/IAssetData.ts index b374e33d..df67309f 100644 --- a/src/core/asset/interfaces/IAssetData.ts +++ b/src/core/asset/interfaces/IAssetData.ts @@ -4,6 +4,7 @@ import { IAssetAlias } from './IAssetAlias'; import { IAssetDimension } from './IAssetDimension'; import { IAssetPalette } from './IAssetPalette'; import { IPlanetSystem } from './IPlanetSystem'; +import { IParticleSystem } from './particlesystem'; import { ISpritesheet } from './spritesheet'; import { IAssetVisualizationData } from './visualization'; @@ -16,7 +17,8 @@ export interface IAssetData { credits?: string; soundSample?: { id?: number, noPitch?: boolean }; action?: { link?: string, startState?: number }; - planetSystem?: IPlanetSystem; + planetSystems?: IPlanetSystem[]; + particleSystems?: IParticleSystem[]; spritesheet?: ISpritesheet; dimensions?: IAssetDimension; directions?: number[]; diff --git a/src/core/asset/interfaces/IPlanetSystem.ts b/src/core/asset/interfaces/IPlanetSystem.ts index fd5a8732..16acf871 100644 --- a/src/core/asset/interfaces/IPlanetSystem.ts +++ b/src/core/asset/interfaces/IPlanetSystem.ts @@ -1,6 +1,11 @@ -import { IPlanetSystemObject } from './IPlanetSystemObject'; - export interface IPlanetSystem { - objects?: IPlanetSystemObject[]; + id?: number; + name?: string; + parent?: string; + radius?: number; + arcSpeed?: number; + arcOffset?: number; + blend?: number; + height?: number; } diff --git a/src/core/asset/interfaces/IPlanetSystemObject.ts b/src/core/asset/interfaces/IPlanetSystemObject.ts deleted file mode 100644 index 0d3bdc5f..00000000 --- a/src/core/asset/interfaces/IPlanetSystemObject.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface IPlanetSystemObject -{ - id?: number; - name?: string; - parent?: string; - radius?: number; - arcSpeed?: number; - arcOffset?: number; - blend?: number; - height?: number; -} diff --git a/src/core/asset/interfaces/index.ts b/src/core/asset/interfaces/index.ts index f2f81b76..88559df8 100644 --- a/src/core/asset/interfaces/index.ts +++ b/src/core/asset/interfaces/index.ts @@ -5,6 +5,5 @@ export * from './IAssetData'; export * from './IAssetDimension'; export * from './IAssetPalette'; export * from './IPlanetSystem'; -export * from './IPlanetSystemObject'; export * from './spritesheet'; export * from './visualization'; diff --git a/src/core/asset/interfaces/particlesystem/IParticleSystem.ts b/src/core/asset/interfaces/particlesystem/IParticleSystem.ts new file mode 100644 index 00000000..871f5f37 --- /dev/null +++ b/src/core/asset/interfaces/particlesystem/IParticleSystem.ts @@ -0,0 +1,11 @@ +import { IParticleSystemEmitter } from './IParticleSystemEmitter'; + +export interface IParticleSystem +{ + size?: number; + canvasId?: number; + offsetY?: number; + blend?: number; + bgColor?: string; + emitters?: IParticleSystemEmitter[]; +} diff --git a/src/core/asset/interfaces/particlesystem/IParticleSystemEmitter.ts b/src/core/asset/interfaces/particlesystem/IParticleSystemEmitter.ts new file mode 100644 index 00000000..fa175e2c --- /dev/null +++ b/src/core/asset/interfaces/particlesystem/IParticleSystemEmitter.ts @@ -0,0 +1,15 @@ +import { IParticleSystemParticle } from './IParticleSystemParticle'; +import { IParticleSystemSimulation } from './IParticleSystemSimulation'; + +export interface IParticleSystemEmitter +{ + id?: number; + name?: string; + spriteId?: number; + maxNumParticles?: number; + particlesPerFrame?: number; + burstPulse?: number; + fuseTime?: number; + simulation?: IParticleSystemSimulation; + particles?: IParticleSystemParticle[]; +} diff --git a/src/core/asset/interfaces/particlesystem/IParticleSystemParticle.ts b/src/core/asset/interfaces/particlesystem/IParticleSystemParticle.ts new file mode 100644 index 00000000..99281fa1 --- /dev/null +++ b/src/core/asset/interfaces/particlesystem/IParticleSystemParticle.ts @@ -0,0 +1,7 @@ +export interface IParticleSystemParticle +{ + isEmitter?: boolean; + lifeTime?: number; + fade?: boolean; + frames?: string[]; +} diff --git a/src/core/asset/interfaces/particlesystem/IParticleSystemSimulation.ts b/src/core/asset/interfaces/particlesystem/IParticleSystemSimulation.ts new file mode 100644 index 00000000..fef400c0 --- /dev/null +++ b/src/core/asset/interfaces/particlesystem/IParticleSystemSimulation.ts @@ -0,0 +1,9 @@ +export interface IParticleSystemSimulation +{ + force?: number; + direction?: number; + gravity?: number; + airFriction?: number; + shape?: string; + energy?: number; +} diff --git a/src/core/asset/interfaces/particlesystem/index.ts b/src/core/asset/interfaces/particlesystem/index.ts new file mode 100644 index 00000000..428f6fc9 --- /dev/null +++ b/src/core/asset/interfaces/particlesystem/index.ts @@ -0,0 +1,4 @@ +export * from './IParticleSystem'; +export * from './IParticleSystemEmitter'; +export * from './IParticleSystemParticle'; +export * from './IParticleSystemSimulation'; diff --git a/src/nitro/avatar/geometry/Vector3D.ts b/src/nitro/avatar/geometry/Vector3D.ts index 4bdc821d..4afba81d 100644 --- a/src/nitro/avatar/geometry/Vector3D.ts +++ b/src/nitro/avatar/geometry/Vector3D.ts @@ -71,6 +71,13 @@ this._z = (this._z * k); } + public scaleBy(value: number): void + { + this._x *= value; + this._y *= value; + this._z *= value; + } + public length(): number { return Math.sqrt((((this._x * this._x) + (this._y * this._y)) + (this._z * this._z))); diff --git a/src/nitro/communication/messages/parser/handshake/AuthenticationParser.ts b/src/nitro/communication/messages/parser/handshake/AuthenticationParser.ts deleted file mode 100644 index c4dd3d1b..00000000 --- a/src/nitro/communication/messages/parser/handshake/AuthenticationParser.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { IMessageDataWrapper } from '../../../../../core/communication/messages/IMessageDataWrapper'; -import { IMessageParser } from '../../../../../core/communication/messages/IMessageParser'; - -export class AuthenticationParser implements IMessageParser -{ - private _sso: string; - - public flush(): boolean - { - this._sso = null; - return true; - } - - public parse(wrapper: IMessageDataWrapper): boolean - { - if(!wrapper) return false; - - this._sso = wrapper.readString(); - - return true; - } - - public get sso(): string - { - return this._sso; - } -} diff --git a/src/nitro/communication/messages/parser/handshake/index.ts b/src/nitro/communication/messages/parser/handshake/index.ts deleted file mode 100644 index 88f562dc..00000000 --- a/src/nitro/communication/messages/parser/handshake/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AuthenticationParser'; diff --git a/src/nitro/room/object/RoomObjectVariable.ts b/src/nitro/room/object/RoomObjectVariable.ts index 28d1b35a..72c475e0 100644 --- a/src/nitro/room/object/RoomObjectVariable.ts +++ b/src/nitro/room/object/RoomObjectVariable.ts @@ -102,6 +102,7 @@ export class RoomObjectVariable public static FURNITURE_CLOTHING_BOY: string = 'furniture_clothing_boy'; public static FURNITURE_CLOTHING_GIRL: string = 'furniture_clothing_girl'; public static FURNITURE_PLANETSYSTEM_DATA: string = 'furniture_planetsystem_data'; + public static FURNITURE_FIREWORKS_DATA: string = 'furniture_fireworks_data'; public static PET_PALETTE_INDEX: string = 'pet_palette_index'; public static PET_COLOR: string = 'pet_color'; public static PET_HEAD_ONLY: string = 'pet_head_only'; diff --git a/src/nitro/room/object/logic/furniture/FurnitureFireworksLogic.ts b/src/nitro/room/object/logic/furniture/FurnitureFireworksLogic.ts index a32b2767..dbb8f3a0 100644 --- a/src/nitro/room/object/logic/furniture/FurnitureFireworksLogic.ts +++ b/src/nitro/room/object/logic/furniture/FurnitureFireworksLogic.ts @@ -1,6 +1,67 @@ +import { IAssetData } from '../../../../../core'; +import { IParticleSystem } from '../../../../../core/asset/interfaces/particlesystem'; +import { RoomObjectEvent } from '../../../../../room/events/RoomObjectEvent'; +import { RoomSpriteMouseEvent } from '../../../../../room/events/RoomSpriteMouseEvent'; +import { IRoomGeometry } from '../../../../../room/utils/IRoomGeometry'; +import { MouseEventType } from '../../../../ui/MouseEventType'; +import { RoomObjectStateChangedEvent } from '../../../events/RoomObjectStateChangedEvent'; +import { RoomObjectVariable } from '../../RoomObjectVariable'; import { FurnitureLogic } from './FurnitureLogic'; export class FurnitureFireworksLogic extends FurnitureLogic { + public getEventTypes(): string[] + { + const types = [ RoomObjectStateChangedEvent.STATE_CHANGE ]; -} \ No newline at end of file + return this.mergeTypes(super.getEventTypes(), types); + } + + public initialize(asset: IAssetData): void + { + super.initialize(asset); + + if(asset.particleSystems && asset.particleSystems.length) + { + this.object.model.setValue(RoomObjectVariable.FURNITURE_FIREWORKS_DATA, asset.particleSystems); + } + } + + public mouseEvent(event: RoomSpriteMouseEvent, geometry: IRoomGeometry): void + { + if(!event|| !geometry || !this.object) return; + + let objectEvent: RoomObjectEvent = null; + + switch(event.type) + { + case MouseEventType.DOUBLE_CLICK: + switch(event.spriteTag) + { + case 'start_stop': + objectEvent = new RoomObjectStateChangedEvent(RoomObjectStateChangedEvent.STATE_CHANGE, this.object, 1); + break; + case 'reset': + objectEvent = new RoomObjectStateChangedEvent(RoomObjectStateChangedEvent.STATE_CHANGE, this.object, 2); + break; + } + + if(this.eventDispatcher && objectEvent) + { + this.eventDispatcher.dispatchEvent(objectEvent); + + return; + } + break; + } + + super.mouseEvent(event, geometry); + } + + public useObject(): void + { + if(!this.object || !this.eventDispatcher) return; + + this.eventDispatcher.dispatchEvent(new RoomObjectStateChangedEvent(RoomObjectStateChangedEvent.STATE_CHANGE, this.object, 0)); + } +} diff --git a/src/nitro/room/object/logic/furniture/FurniturePlanetSystemLogic.ts b/src/nitro/room/object/logic/furniture/FurniturePlanetSystemLogic.ts index 185267f3..bb44309d 100644 --- a/src/nitro/room/object/logic/furniture/FurniturePlanetSystemLogic.ts +++ b/src/nitro/room/object/logic/furniture/FurniturePlanetSystemLogic.ts @@ -8,9 +8,9 @@ export class FurniturePlanetSystemLogic extends FurnitureLogic { super.initialize(asset); - if(asset.planetSystem) + if(asset.planetSystems) { - this.object.model.setValue(RoomObjectVariable.FURNITURE_PLANETSYSTEM_DATA, asset.planetSystem); + this.object.model.setValue(RoomObjectVariable.FURNITURE_PLANETSYSTEM_DATA, asset.planetSystems); } } } diff --git a/src/nitro/room/object/visualization/data/ParticleSystemParticle.ts b/src/nitro/room/object/visualization/data/ParticleSystemParticle.ts new file mode 100644 index 00000000..2c603ad7 --- /dev/null +++ b/src/nitro/room/object/visualization/data/ParticleSystemParticle.ts @@ -0,0 +1,9 @@ +import { IGraphicAsset } from '../../../../../room'; + +export interface ParticleSystemParticle +{ + isEmitter?: boolean; + lifeTime?: number; + fade?: boolean; + frames?: IGraphicAsset[]; +} diff --git a/src/nitro/room/object/visualization/data/index.ts b/src/nitro/room/object/visualization/data/index.ts index 095daabe..22cf0066 100644 --- a/src/nitro/room/object/visualization/data/index.ts +++ b/src/nitro/room/object/visualization/data/index.ts @@ -10,5 +10,6 @@ export * from './ColorData'; export * from './DirectionalOffsetData'; export * from './DirectionData'; export * from './LayerData'; +export * from './ParticleSystemParticle'; export * from './PetSizeData'; export * from './SizeData'; diff --git a/src/nitro/room/object/visualization/furniture/FurnitureDynamicThumbnailVisualization.ts b/src/nitro/room/object/visualization/furniture/FurnitureDynamicThumbnailVisualization.ts index a4d3ff31..34636fee 100644 --- a/src/nitro/room/object/visualization/furniture/FurnitureDynamicThumbnailVisualization.ts +++ b/src/nitro/room/object/visualization/furniture/FurnitureDynamicThumbnailVisualization.ts @@ -11,6 +11,7 @@ export class FurnitureDynamicThumbnailVisualization extends FurnitureThumbnailVi super(); this._cachedUrl = null; + this._hasOutline = true; } protected updateModel(scale: number): boolean diff --git a/src/nitro/room/object/visualization/furniture/FurnitureFireworksVisualization.ts b/src/nitro/room/object/visualization/furniture/FurnitureFireworksVisualization.ts index f23c2316..366a352b 100644 --- a/src/nitro/room/object/visualization/furniture/FurnitureFireworksVisualization.ts +++ b/src/nitro/room/object/visualization/furniture/FurnitureFireworksVisualization.ts @@ -1,6 +1,111 @@ +import { AdvancedMap, NitroLogger } from '../../../../../core'; +import { IParticleSystem } from '../../../../../core/asset/interfaces/particlesystem'; +import { RoomObjectVariable } from '../../RoomObjectVariable'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; +import { FurnitureParticleSystem } from './FurnitureParticleSystem'; export class FurnitureFireworksVisualization extends FurnitureAnimatedVisualization { + private _particleSystems: AdvancedMap; + private _currentParticleSystem: FurnitureParticleSystem; -} \ No newline at end of file + public dispose():void + { + super.dispose(); + + this._currentParticleSystem = null; + + if(this._particleSystems) + { + for(const particleSystem of this._particleSystems.getValues()) particleSystem.dispose(); + + this._particleSystems = null; + } + } + + protected updateObject(scale: number, direction: number): boolean + { + if(super.updateObject(scale, direction)) + { + if(!this._particleSystems) + { + this._Str_18684(); + + if(this._particleSystems) this._currentParticleSystem = this._particleSystems.getValue(scale); + + else NitroLogger.log(('ERROR Particle systems could not be read! ' + this.object.type)); + } + else + { + if((scale !== this._scale) || (this._particleSystems.getValue(scale) !== this._currentParticleSystem)) + { + const particleSystem = this._particleSystems.getValue(scale); + + particleSystem._Str_17988(this._currentParticleSystem); + + if(this._currentParticleSystem) this._currentParticleSystem.reset(); + + this._currentParticleSystem = particleSystem; + } + } + + return true; + } + + return false; + } + + protected updateSprites(scale: number, update: boolean, animation: number):void + { + super.updateSprites(scale, update, animation); + + if(this._currentParticleSystem) this._currentParticleSystem.updateSprites(); + } + + protected updateAnimation(scale: number): number + { + if(this._currentParticleSystem) this._currentParticleSystem.updateAnimation(); + + return super.updateAnimation(scale); + } + + protected setAnimation(id: number):void + { + if(this._currentParticleSystem) this._currentParticleSystem.setAnimation(id); + + super.setAnimation(id); + } + + protected getLayerYOffset(scale: number, direction: number, layerId: number): number + { + if(this._currentParticleSystem && this._currentParticleSystem.controlsSprite(layerId)) + { + return this._currentParticleSystem.getLayerYOffset(scale, direction, layerId); + } + + return super.getLayerYOffset(scale, direction, layerId); + } + + private _Str_18684(): boolean + { + if(!this.object || !this.object.model) return false; + + const fireworksData = this.object.model.getValue(RoomObjectVariable.FURNITURE_FIREWORKS_DATA); + + if(!fireworksData || !fireworksData.length) return false; + + this._particleSystems = new AdvancedMap(); + + for(const particleData of fireworksData) + { + const size = particleData.size; + const particleSystem = new FurnitureParticleSystem(this); + + particleSystem.parseData(particleData); + + this._particleSystems.add(size, particleSystem); + } + + return true; + } +} diff --git a/src/nitro/room/object/visualization/furniture/FurnitureParticleSystem.ts b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystem.ts new file mode 100644 index 00000000..91e47c58 --- /dev/null +++ b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystem.ts @@ -0,0 +1,344 @@ +import { RenderTexture, Texture } from '@pixi/core'; +import { AlphaFilter } from '@pixi/filter-alpha'; +import { Graphics } from '@pixi/graphics'; +import { Matrix } from '@pixi/math'; +import { AdvancedMap, NitroPoint, NitroSprite } from '../../../../../core'; +import { IParticleSystem } from '../../../../../core/asset/interfaces/particlesystem'; +import { IGraphicAsset, IRoomObjectSprite } from '../../../../../room'; +import { Vector3D } from '../../../../avatar'; +import { Nitro } from '../../../../Nitro'; +import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; +import { FurnitureParticleSystemEmitter } from './FurnitureParticleSystemEmitter'; + +export class FurnitureParticleSystem +{ + private _emitters: AdvancedMap; + private _visualization: FurnitureAnimatedVisualization; + private _size: number; + private _canvasId: number = -1; + private _offsetY: number; + private _currentEmitter: FurnitureParticleSystemEmitter; + private _canvasTexture: RenderTexture; + private _roomSprite: IRoomObjectSprite; + private _hasIgnited: boolean = false; + private _centerX: number = 0; + private _centerY: number = 0; + private _scaleMultiplier: number = 1; + private _blackOverlay: Graphics; + private _blackOverlayAlphaTransform: AlphaFilter; + private _particleColorTransform: AlphaFilter; + private _identityMatrix: Matrix; + private _translationMatrix: Matrix; + private _blend: number = 1; + private _bgColor: number = 0xFF000000; + private _emptySprite: NitroSprite; + private _isDone: boolean = false; + + constructor(visualization: FurnitureAnimatedVisualization) + { + this._emitters = new AdvancedMap(); + this._visualization = visualization; + this._blackOverlayAlphaTransform = new AlphaFilter(); + this._blackOverlayAlphaTransform.alpha = 1; + this._particleColorTransform = new AlphaFilter(); + this._identityMatrix = new Matrix(); + this._translationMatrix = new Matrix(); + } + + public dispose(): void + { + for(const emitter of this._emitters.getValues()) emitter.dispose(); + + this._emitters = null; + + if(this._canvasTexture) + { + this._canvasTexture.destroy(); + this._canvasTexture = null; + } + + if(this._blackOverlay) + { + this._blackOverlay.destroy(); + this._blackOverlay = null; + } + + if(this._emptySprite) + { + this._emptySprite.destroy(); + this._emptySprite = null; + } + + this._blackOverlayAlphaTransform = null; + this._particleColorTransform = null; + this._identityMatrix = null; + this._translationMatrix = null; + } + + public reset(): void + { + if(this._currentEmitter) this._currentEmitter.reset(); + + this._currentEmitter = null; + this._hasIgnited = false; + this._isDone = false; + + this.updateCanvas(); + } + + public setAnimation(id: number): void + { + if(this._currentEmitter) this._currentEmitter.reset(); + + this._currentEmitter = this._emitters.getValue(id); + this._hasIgnited = false; + this._isDone = false; + + this.updateCanvas(); + } + + private updateCanvas(): void + { + if(!this._currentEmitter || (this._canvasId === -1)) return; + + this._roomSprite = this._visualization.getSprite(this._canvasId); + + if(this._roomSprite && this._roomSprite.texture) + { + if((this._roomSprite.width <= 1) || (this._roomSprite.height <= 1)) return; + + if(this._canvasTexture && ((this._canvasTexture.width !== this._roomSprite.width) || (this._canvasTexture.height !== this._roomSprite.height))) this._canvasTexture = null; + + if(!this._canvasTexture) + { + this._canvasTexture = RenderTexture.create({ + width: this._roomSprite.width, + height: this._roomSprite.height + }); + } + + if(!this._emptySprite) + { + this._emptySprite = new NitroSprite(Texture.WHITE); + + this._emptySprite.tint = this._bgColor; + } + + this._centerX = -(this._roomSprite.offsetX); + this._centerY = -(this._roomSprite.offsetY); + this._roomSprite.texture = this._canvasTexture; + } + } + + public getLayerYOffset(scale: number, direction: number, layerId: number): number + { + if(this._currentEmitter && (this._currentEmitter.roomObjectSpriteId === layerId)) + { + return this._currentEmitter.y * this._scaleMultiplier; + } + + return 0; + } + + public controlsSprite(k: number): boolean + { + if(this._currentEmitter) return this._currentEmitter.roomObjectSpriteId == k; + + return false; + } + + public updateSprites(): void + { + if(!this._currentEmitter || !this._roomSprite) return; + + if(this._canvasTexture && (this._roomSprite.texture !== this._canvasTexture)) + { + this._roomSprite.texture = this._canvasTexture; + } + + if(this._hasIgnited) + { + if(this._currentEmitter.roomObjectSpriteId >= 0) this._visualization.getSprite(this._currentEmitter.roomObjectSpriteId).visible = false; + } + } + + public updateAnimation(): void + { + if(!this._currentEmitter || !this._roomSprite || this._isDone) return; + + const k = 10; + + if(!this._hasIgnited && this._currentEmitter.hasIgnited) this._hasIgnited = true; + + const offsetY = (this._offsetY * this._scaleMultiplier); + + this._currentEmitter.update(); + + if(this._hasIgnited) + { + if(this._currentEmitter.roomObjectSpriteId >= 0) + { + this._visualization.getSprite(this._currentEmitter.roomObjectSpriteId).visible = false; + } + + if(!this._canvasTexture) this.updateCanvas(); + + if(this._blackOverlayAlphaTransform.alpha === 1) + { + this._emptySprite.filters = null; + + Nitro.instance.renderer.render(this._emptySprite, { + renderTexture: this._canvasTexture, + clear: true + }); + } + else + { + this._emptySprite.filters = [ this._blackOverlayAlphaTransform ]; + + Nitro.instance.renderer.render(this._emptySprite, { + renderTexture: this._canvasTexture, + transform: this._identityMatrix, + clear: true + }); + } + + for(const particle of this._currentEmitter.particles) + { + const tx = (this._centerX + ((((particle.x - particle.z) * k) / 10) * this._scaleMultiplier)); + const ty = ((this._centerY - offsetY) + ((((particle.y + ((particle.x + particle.z) / 2)) * k) / 10) * this._scaleMultiplier)); + const asset = particle.getAsset(); + + if(asset) + { + const texture = asset.texture; + + if(particle.fade && (particle.alphaMultiplier < 1)) + { + this._translationMatrix.identity(); + this._translationMatrix.translate((tx + asset.offsetX), (ty + asset.offsetY)); + + const sprite = new NitroSprite(texture); + + this._particleColorTransform.alpha = particle.alphaMultiplier; + + sprite.filters = [ this._particleColorTransform ]; + + Nitro.instance.renderer.render(sprite, { + renderTexture: this._canvasTexture, + transform: this._translationMatrix, + clear: false + }); + } + else + { + const point = new NitroPoint((tx + asset.offsetX), (ty + asset.offsetY)); + + const sprite = new NitroSprite(texture); + + sprite.x = point.x; + sprite.y = point.y; + + Nitro.instance.renderer.render(sprite, { + renderTexture: this._canvasTexture, + clear: false + }); + } + } + else + { + const sprite = new NitroSprite(Texture.WHITE); + + sprite.tint = 0xFFFFFF; + sprite.x = (tx - 1); + sprite.y = (ty - 1); + sprite.width = 2; + sprite.height = 2; + + Nitro.instance.renderer.render(sprite, { + renderTexture: this._canvasTexture, + clear: false + }); + } + } + + if(!this._currentEmitter.particles.length) + { + this._isDone = true; + + return; + } + } + } + + public parseData(particleSystem: IParticleSystem): void + { + this._size = particleSystem.size; + this._canvasId = ((particleSystem.canvasId !== undefined) ? particleSystem.canvasId : -1); + this._offsetY = ((particleSystem.offsetY !== undefined) ? particleSystem.offsetY : 10); + this._scaleMultiplier = (this._size / 64); + this._blend = ((particleSystem.blend !== undefined) ? particleSystem.blend : 1); + this._blend = Math.min(this._blend, 1); + + this._blackOverlayAlphaTransform.alpha = this._blend; + + const bgColor = ((particleSystem.bgColor !== undefined) ? particleSystem.bgColor : '0'); + + this._bgColor = (parseInt(bgColor, 16) || 0x000000); + + if(!particleSystem.emitters || !particleSystem.emitters.length) return; + + for(const emitter of particleSystem.emitters) + { + const emitterId = emitter.id; + const emitterName = emitter.name; + const emitterSpriteId = emitter.spriteId; + + const particleEmitter = new FurnitureParticleSystemEmitter(emitterName, emitterSpriteId); + + this._emitters.add(emitterId, particleEmitter); + + const maxNumParticles = emitter.maxNumParticles; + const particlesPerFrame = emitter.particlesPerFrame; + const burstPulse = ((emitter.burstPulse !== undefined) ? emitter.burstPulse : 1); + const fuseTime = emitter.fuseTime; + const simulationForce = emitter.simulation.force; + const simulationDirection = emitter.simulation.direction; + const simulationGravity = emitter.simulation.gravity; + const simulationAirFriction = emitter.simulation.airFriction; + const simulationShape = emitter.simulation.shape; + const simulationEnergy = emitter.simulation.energy; + + for(const particle of emitter.particles) + { + const lifeTime = particle.lifeTime; + const isEmitter = (particle.isEmitter || false); + const fade = (particle.fade || false); + + const frames: IGraphicAsset[] = []; + + for(const name of particle.frames) frames.push(this._visualization.asset.getAsset(name)); + + particleEmitter.configureParticle(lifeTime, isEmitter, frames, fade); + } + + particleEmitter.setup(maxNumParticles, particlesPerFrame, simulationForce, new Vector3D(0, simulationDirection, 0), simulationGravity, simulationAirFriction, simulationShape, simulationEnergy, fuseTime, burstPulse); + } + } + + public _Str_17988(particleSystem: FurnitureParticleSystem): void + { + let emitterId = 0; + + if(particleSystem._emitters && particleSystem._currentEmitter) + { + emitterId = particleSystem._emitters.getKey(particleSystem._emitters.getValues().indexOf(particleSystem._currentEmitter)); + } + + this.setAnimation(emitterId); + + if(this._currentEmitter) this._currentEmitter.copyStateFrom(particleSystem._currentEmitter, (particleSystem._size / this._size)); + + this._canvasTexture = null; + } +} diff --git a/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemEmitter.ts b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemEmitter.ts index 32d33419..918610f0 100644 --- a/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemEmitter.ts +++ b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemEmitter.ts @@ -1,5 +1,6 @@ -import { GraphicAsset } from '../../../../../room/object/visualization/utils/GraphicAsset'; +import { IGraphicAsset } from '../../../../../room'; import { Vector3D } from '../../../../avatar/geometry/Vector3D'; +import { ParticleSystemParticle } from '../data'; import { FurnitureParticleSystemParticle } from './FurnitureParticleSystemParticle'; export class FurnitureParticleSystemEmitter extends FurnitureParticleSystemParticle @@ -15,7 +16,7 @@ export class FurnitureParticleSystemEmitter extends FurnitureParticleSystemParti private _gravity: number; private _airFriction: number; private _explosionShape: string; - private _particleConfigurations: { [index: string]: any }[]; + private _particleConfigurations: ParticleSystemParticle[]; private _particles: FurnitureParticleSystemParticle[]; private _maxNumberOfParticles: number; private _particlesPerFrame: number; @@ -24,14 +25,15 @@ export class FurnitureParticleSystemEmitter extends FurnitureParticleSystemParti private _energy: number = 1; private _hasIgnited: boolean = false; private _burstPulse: number = 1; + private _emitterDirection: Vector3D; - constructor(k: string='', _arg_2: number=-1) + constructor(name: string = '', spriteId: number = -1) { super(); this._particles = []; - this._name = k; - this._roomObjectSpriteId = _arg_2; + this._name = name; + this._roomObjectSpriteId = spriteId; this._particleConfigurations = []; } @@ -40,205 +42,204 @@ export class FurnitureParticleSystemEmitter extends FurnitureParticleSystemParti for(const k of this._particles) k.dispose(); this._particles = null; - this._direction = null; this._particleConfigurations = null; super.dispose(); } - public setup(k: number, _arg_2: number, _arg_3: number, _arg_4: Vector3D, _arg_5: number, _arg_6: number, _arg_7: string, _arg_8: number, _arg_9: number, _arg_10: number): void + public setup(maxNumOfParticles: number, particlesPerFrame: number, force: number, direction: Vector3D, gravity: number, airFriction: number, explosionShape: string, energy: number, fuseTime: number, burstPulse: number): void { - this._maxNumberOfParticles = k; - this._particlesPerFrame = _arg_2; - this._force = _arg_3; - this._direction = _arg_4; - this._direction.normalize(); - this._gravity = _arg_5; - this._airFriction = _arg_6; - this._explosionShape = _arg_7; - this._fuseTime = _arg_9; - this._energy = _arg_8; - this._burstPulse = _arg_10; + this._maxNumberOfParticles = maxNumOfParticles; + this._particlesPerFrame = particlesPerFrame; + this._force = force; + this._emitterDirection = direction; + this._emitterDirection.normalize(); + this._gravity = gravity; + this._airFriction = airFriction; + this._explosionShape = explosionShape; + this._fuseTime = fuseTime; + this._energy = energy; + this._burstPulse = burstPulse; this.reset(); } public reset(): void { - let k:FurnitureParticleSystemParticle; - for(const k of this._particles) k.dispose(); + for(const particle of this._particles) particle.dispose(); + this._particles = []; this._emittedParticles = 0; this._hasIgnited = false; - this.init(0, 0, 0, this._direction, this._force, this._timeStep, this._fuseTime, true); + + this.init(0, 0, 0, this._emitterDirection, this._force, this._timeStep, this._fuseTime, true); } - public copyStateFrom(k:FurnitureParticleSystemEmitter, _arg_2: number): void + public copyStateFrom(emitter: FurnitureParticleSystemEmitter, scale: number): void { - super.copy(k, _arg_2); - this._force = k._force; - this._direction = k._direction; - this._gravity = k._gravity; - this._airFriction = k._airFriction; - this._explosionShape = k._explosionShape; - this._fuseTime = k._fuseTime; - this._energy = k._energy; - this._burstPulse = k._burstPulse; - this._timeStep = k._timeStep; - this._hasIgnited = k._hasIgnited; + super.copy(emitter, scale); + + this._force = emitter._force; + this._emitterDirection = emitter._emitterDirection; + this._gravity = emitter._gravity; + this._airFriction = emitter._airFriction; + this._explosionShape = emitter._explosionShape; + this._fuseTime = emitter._fuseTime; + this._energy = emitter._energy; + this._burstPulse = emitter._burstPulse; + this._timeStep = emitter._timeStep; + this._hasIgnited = emitter._hasIgnited; } - public configureParticle(k: number, _arg_2: boolean, _arg_3: GraphicAsset[], _arg_4: boolean): void + public configureParticle(lifeTIme: number, isEmitter: boolean, frames: IGraphicAsset[], fade: boolean): void { - const _local_5 = []; - _local_5['lifeTime'] = k; - _local_5['isEmitter'] = _arg_2; - _local_5['frames'] = _arg_3; - _local_5['fade'] = _arg_4; - this._particleConfigurations.push(_local_5); + const particle: ParticleSystemParticle = {}; + + particle.lifeTime = lifeTIme; + particle.isEmitter = isEmitter; + particle.frames = frames; + particle.fade = fade; + + this._particleConfigurations.push(particle); } protected ignite(): void { this._hasIgnited = true; - if((this._emittedParticles < this._maxNumberOfParticles)) + + if(this._emittedParticles < this._maxNumberOfParticles) { - if(this.age > 1) - { - this.releaseParticles(this, this.direction); - } + if(this.age > 1) this.releaseParticles(this, this.direction); } } - private releaseParticles(k:FurnitureParticleSystemParticle, _arg_2: Vector3D = null): void + private releaseParticles(particle: FurnitureParticleSystemParticle, direction: Vector3D = null): void { - if(!_arg_2) _arg_2 = new Vector3D(); + if(!direction) direction = new Vector3D(); - const _local_3 = new Vector3D(); - const _local_5 = this.getRandomParticleConfiguration(); + const newDirection = new Vector3D(); + const randomParticle = this.getRandomParticleConfiguration(); - let _local_10 = 0; + let i = 0; - while(_local_10 < this._particlesPerFrame) + while(i < this._particlesPerFrame) { switch(this._explosionShape) { case FurnitureParticleSystemEmitter.CONE: - _local_3.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); - _local_3.y = -(Math.random() + 1); - _local_3.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.y = -(Math.random() + 1); + newDirection.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); break; case FurnitureParticleSystemEmitter.PLANE: - _local_3.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); - _local_3.y = 0; - _local_3.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.y = 0; + newDirection.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); break; case FurnitureParticleSystemEmitter.SPHERE: - _local_3.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); - _local_3.y = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); - _local_3.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.x = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.y = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); + newDirection.z = ((this.randomBoolean(0.5)) ? Math.random() : -(Math.random())); break; } - _local_3.normalize(); + newDirection.normalize(); - const _local_4 = new FurnitureParticleSystemParticle(); + const newParticle = new FurnitureParticleSystemParticle(); - let _local_6 = 0; - let _local_7 = false; - let _local_8 = false; - let _local_9: GraphicAsset[] = []; + let lifeTime = 0; + let isEmitter = false; + let fade = false; + let frames: IGraphicAsset[] = []; - if(_local_5) + if(randomParticle) { - _local_6 = Math.floor(((Math.random() * _local_5['lifeTime']) + 10)); - _local_7 = _local_5['isEmitter']; - _local_9 = _local_5['frames']; - _local_8 = _local_5['fade']; + lifeTime = Math.floor(((Math.random() * randomParticle.lifeTime) + 10)); + isEmitter = randomParticle.isEmitter; + frames = randomParticle.frames; + fade = randomParticle.fade; } else { - _local_6 = Math.trunc(Math.floor(((Math.random() * 20) + 10))); - _local_7 = false; - _local_9 = []; + lifeTime = Math.trunc(Math.floor(((Math.random() * 20) + 10))); + isEmitter = false; + frames = []; } - _local_4.init(k.x, k.y, k.z, _local_3, this._energy, this._timeStep, _local_6, _local_7, _local_9, _local_8); + newParticle.init(particle.x, particle.y, particle.z, newDirection, this._energy, this._timeStep, lifeTime, isEmitter, frames, fade); - this._particles.push(_local_4); + this._particles.push(newParticle); this._emittedParticles++; - _local_10++; + i++; } } - private getRandomParticleConfiguration() + private getRandomParticleConfiguration(): ParticleSystemParticle { - const k: number = Math.trunc(Math.floor((Math.random() * this._particleConfigurations.length))); - return this._particleConfigurations[k]; + const index: number = Math.trunc(Math.floor((Math.random() * this._particleConfigurations.length))); + + return this._particleConfigurations[index]; } public update(): void { super.update(); + this.accumulateForces(); this.verlet(); this.satisfyConstraints(); - if(((!(this.isAlive)) && (this._emittedParticles < this._maxNumberOfParticles))) + + if(!this.isAlive && (this._emittedParticles < this._maxNumberOfParticles)) { - if((this.age % this._burstPulse) == 0) - { - this.releaseParticles(this, this.direction); - } + if((this.age % this._burstPulse) === 0) this.releaseParticles(this, this.direction); } } public verlet(): void { - let _local_2:FurnitureParticleSystemParticle; - let _local_3: number; - let _local_4: number; - let _local_5: number; - if(((this.isAlive) || (this._emittedParticles < this._maxNumberOfParticles))) + if(this.isAlive || (this._emittedParticles < this._maxNumberOfParticles)) { - _local_3 = this.x; - _local_4 = this.y; - _local_5 = this.z; + const x = this.x; + const y = this.y; + const z = this.z; + this.x = (((2 - this._airFriction) * this.x) - ((1 - this._airFriction) * this.lastX)); this.y = ((((2 - this._airFriction) * this.y) - ((1 - this._airFriction) * this.lastY)) + ((this._gravity * this._timeStep) * this._timeStep)); this.z = (((2 - this._airFriction) * this.z) - ((1 - this._airFriction) * this.lastZ)); - this.lastX = _local_3; - this.lastY = _local_4; - this.lastZ = _local_5; + this.lastX = x; + this.lastY = y; + this.lastZ = z; } - const k: FurnitureParticleSystemParticle[] = []; - for(const _local_2 of this._particles) + const particles: FurnitureParticleSystemParticle[] = []; + + for(const particle of this._particles) { - _local_2.update(); - _local_3 = _local_2.x; - _local_4 = _local_2.y; - _local_5 = _local_2.z; - _local_2.x = (((2 - this._airFriction) * _local_2.x) - ((1 - this._airFriction) * _local_2.lastX)); - _local_2.y = ((((2 - this._airFriction) * _local_2.y) - ((1 - this._airFriction) * _local_2.lastY)) + ((this._gravity * this._timeStep) * this._timeStep)); - _local_2.z = (((2 - this._airFriction) * _local_2.z) - ((1 - this._airFriction) * _local_2.lastZ)); - _local_2.lastX = _local_3; - _local_2.lastY = _local_4; - _local_2.lastZ = _local_5; - if(((_local_2.y > 10) || (!(_local_2.isAlive)))) - { - k.push(_local_2); - } + particle.update(); + + const x = particle.x; + const y = particle.y; + const z = particle.z; + particle.x = (((2 - this._airFriction) * particle.x) - ((1 - this._airFriction) * particle.lastX)); + particle.y = ((((2 - this._airFriction) * particle.y) - ((1 - this._airFriction) * particle.lastY)) + ((this._gravity * this._timeStep) * this._timeStep)); + particle.z = (((2 - this._airFriction) * particle.z) - ((1 - this._airFriction) * particle.lastZ)); + particle.lastX = x; + particle.lastY = y; + particle.lastZ = z; + + if((particle.y > 10) || !particle.isAlive) particles.push(particle); } - for(const _local_2 of k) + + for(const particle of particles) { - if(_local_2.isEmitter) + if(particle.isEmitter) { // } - this._particles.splice(this._particles.indexOf(_local_2), 1); + this._particles.splice(this._particles.indexOf(particle), 1); - _local_2.dispose(); + particle.dispose(); } } diff --git a/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemParticle.ts b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemParticle.ts index 75a1b4d3..aa26c464 100644 --- a/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemParticle.ts +++ b/src/nitro/room/object/visualization/furniture/FurnitureParticleSystemParticle.ts @@ -1,4 +1,4 @@ -import { GraphicAsset } from '../../../../../room/object/visualization/utils/GraphicAsset'; +import { IGraphicAsset } from '../../../../../room'; import { Vector3D } from '../../../../avatar/geometry/Vector3D'; export class FurnitureParticleSystemParticle @@ -10,51 +10,47 @@ export class FurnitureParticleSystemParticle private _lastY: number; private _lastZ: number; private _hasMoved: boolean = false; - protected _direction: Vector3D; + private _particleDirection: Vector3D; private _age: number = 0; private _lifeTime: number; private _isEmitter: boolean = false; private _fade: boolean = false; private _fadeTime: number; private _alphaMultiplier: number = 1; - private _frames: GraphicAsset[]; + private _frames: IGraphicAsset[]; - public init(k: number, _arg_2: number, _arg_3: number, _arg_4: Vector3D, _arg_5: number, _arg_6: number, _arg_7: number, _arg_8: boolean = false, _arg_9: GraphicAsset[] = null, _arg_10: boolean = false): void + public init(x: number, y: number, z: number, direction: Vector3D, energy: number, timeStep: number, lifeTime: number, isEmitter: boolean = false, frames: IGraphicAsset[] = null, fade: boolean = false): void { - this._x = k; - this._y = _arg_2; - this._z = _arg_3; - this._direction = new Vector3D(_arg_4.x, _arg_4.y, _arg_4.z); + this._x = x; + this._y = y; + this._z = z; + this._particleDirection = new Vector3D(direction.x, direction.y, direction.z); + this._particleDirection.scaleBy(energy); - this._direction.x *= _arg_5; - this._direction.y *= _arg_5; - this._direction.z *= _arg_5; - - this._lastX = (this._x - (this._direction.x * _arg_6)); - this._lastY = (this._y - (this._direction.y * _arg_6)); - this._lastZ = (this._z - (this._direction.z * _arg_6)); + this._lastX = (this._x - (this._particleDirection.x * timeStep)); + this._lastY = (this._y - (this._particleDirection.y * timeStep)); + this._lastZ = (this._z - (this._particleDirection.z * timeStep)); this._age = 0; this._hasMoved = false; - this._lifeTime = _arg_7; - this._isEmitter = _arg_8; - this._frames = _arg_9; - this._fade = _arg_10; + this._lifeTime = lifeTime; + this._isEmitter = isEmitter; + this._frames = frames; + this._fade = fade; this._alphaMultiplier = 1; this._fadeTime = (0.5 + (Math.random() * 0.5)); } public dispose(): void { - this._direction = null; + this._particleDirection = null; } public update(): void { this._age++; - if(this._age == this._lifeTime) - { - this.ignite(); - } + + if(this._age === this._lifeTime) this.ignite(); + if(this._fade) { if((this._age / this._lifeTime) > this._fadeTime) @@ -64,7 +60,7 @@ export class FurnitureParticleSystemParticle } } - public getAsset(): GraphicAsset + public getAsset(): IGraphicAsset { if(((this._frames) && (this._frames.length > 0))) { @@ -89,7 +85,7 @@ export class FurnitureParticleSystemParticle public get direction(): Vector3D { - return this._direction; + return this._particleDirection; } public get age(): number @@ -112,9 +108,9 @@ export class FurnitureParticleSystemParticle return this._x; } - public set x(k: number) + public set x(x: number) { - this._x = k; + this._x = x; } public get y(): number @@ -122,9 +118,9 @@ export class FurnitureParticleSystemParticle return this._y; } - public set y(k: number) + public set y(y: number) { - this._y = k; + this._y = y; } public get z(): number @@ -132,9 +128,9 @@ export class FurnitureParticleSystemParticle return this._z; } - public set z(k: number) + public set z(z: number) { - this._z = k; + this._z = z; } public get lastX(): number @@ -142,10 +138,10 @@ export class FurnitureParticleSystemParticle return this._lastX; } - public set lastX(k: number) + public set lastX(y: number) { this._hasMoved = true; - this._lastX = k; + this._lastX = y; } public get lastY(): number @@ -164,10 +160,10 @@ export class FurnitureParticleSystemParticle return this._lastZ; } - public set lastZ(k: number) + public set lastZ(z: number) { this._hasMoved = true; - this._lastZ = k; + this._lastZ = z; } public get hasMoved(): boolean @@ -180,21 +176,21 @@ export class FurnitureParticleSystemParticle return [ this._x, this._y, this._z ].toString(); } - public copy(k:FurnitureParticleSystemParticle, _arg_2: number): void + public copy(particle: FurnitureParticleSystemParticle, scale: number): void { - this._x = (k._x * _arg_2); - this._y = (k._y * _arg_2); - this._z = (k._z * _arg_2); - this._lastX = (k._lastX * _arg_2); - this._lastY = (k._lastY * _arg_2); - this._lastZ = (k._lastZ * _arg_2); - this._hasMoved = k.hasMoved; - this._direction = k._direction; - this._age = k._age; - this._lifeTime = k._lifeTime; - this._isEmitter = k._isEmitter; - this._fade = k._fade; - this._fadeTime = k._fadeTime; - this._alphaMultiplier = k._alphaMultiplier; + this._x = (particle._x * scale); + this._y = (particle._y * scale); + this._z = (particle._z * scale); + this._lastX = (particle._lastX * scale); + this._lastY = (particle._lastY * scale); + this._lastZ = (particle._lastZ * scale); + this._hasMoved = particle.hasMoved; + this._particleDirection = particle._particleDirection; + this._age = particle._age; + this._lifeTime = particle._lifeTime; + this._isEmitter = particle._isEmitter; + this._fade = particle._fade; + this._fadeTime = particle._fadeTime; + this._alphaMultiplier = particle._alphaMultiplier; } } diff --git a/src/nitro/room/object/visualization/furniture/FurniturePartyBeamerVisualization.ts b/src/nitro/room/object/visualization/furniture/FurniturePartyBeamerVisualization.ts index 8e4799c6..48700a1d 100644 --- a/src/nitro/room/object/visualization/furniture/FurniturePartyBeamerVisualization.ts +++ b/src/nitro/room/object/visualization/furniture/FurniturePartyBeamerVisualization.ts @@ -1,6 +1,160 @@ +import { NitroPoint } from '../../../../../core'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; export class FurniturePartyBeamerVisualization extends FurnitureAnimatedVisualization { + private static UPDATE_INTERVAL: number = 2; + private static AREA_DIAMETER_SMALL: number = 15; + private static AREA_DIAMETER_LARGE: number = 31; + private static ANIM_SPEED_FAST: number = 2; + private static ANIM_SPEED_SLOW: number = 1; -} \ No newline at end of file + private _animPhaseIndex: number[]; + private _animDirectionIndex: number[]; + private _animSpeedIndex: number[]; + private _animFactorIndex: number[]; + private _animOffsetIndex: NitroPoint[]; + + constructor() + { + super(); + + this._animOffsetIndex = []; + } + + protected updateAnimation(scale: number): number + { + if(!this._animSpeedIndex) this.initItems(scale); + + let sprite = this.getSprite(2); + + if(sprite) this._animOffsetIndex[0] = this.getNewPoint(scale, 0); + + sprite = this.getSprite(3); + + if(sprite) this._animOffsetIndex[1] = this.getNewPoint(scale, 1); + + return super.updateAnimation(scale); + } + + private getNewPoint(scale: number, layerId: number): NitroPoint + { + let diameter = 0; + + let animationPhase: number = this._animPhaseIndex[layerId]; + let animationDirection: number = this._animDirectionIndex[layerId]; + + const animationSpeed: number = this._animSpeedIndex[layerId]; + const animationFactor: number = this._animFactorIndex[layerId]; + + let _local_7 = 1; + + if(scale == 32) + { + diameter = FurniturePartyBeamerVisualization.AREA_DIAMETER_SMALL; + _local_7 = 0.5; + } + else + { + diameter = FurniturePartyBeamerVisualization.AREA_DIAMETER_LARGE; + } + + const _local_9: number = (animationPhase + (animationDirection * animationSpeed)); + + if(Math.abs(_local_9) >= diameter) + { + if(animationDirection > 0) + { + animationPhase = (animationPhase - (_local_9 - diameter)); + } + else + { + animationPhase = (animationPhase + (-(diameter) - _local_9)); + } + + animationDirection = -(animationDirection); + + this._animDirectionIndex[layerId] = animationDirection; + } + + const _local_10: number = ((diameter - Math.abs(animationPhase)) * animationFactor); + + let _local_11: number = ((animationDirection * Math.sin(Math.abs((animationPhase / 4)))) * _local_10); + + if(animationDirection > 0) + { + _local_11 = (_local_11 - _local_10); + } + else + { + _local_11 = (_local_11 + _local_10); + } + + animationPhase = (animationPhase + ((animationDirection * animationSpeed) * _local_7)); + + this._animPhaseIndex[layerId] = animationPhase; + + if(Math.trunc(_local_11) == 0) this._animFactorIndex[layerId] = this.getRandomAmplitudeFactor(); + + return new NitroPoint(animationPhase, _local_11); + } + + private initItems(scale: number):void + { + let diameter: number; + + if(scale === 32) + { + diameter = FurniturePartyBeamerVisualization.AREA_DIAMETER_SMALL; + } + else + { + diameter = FurniturePartyBeamerVisualization.AREA_DIAMETER_LARGE; + } + + this._animPhaseIndex = []; + this._animPhaseIndex.push(((Math.random() * diameter) * 1.5)); + this._animPhaseIndex.push(((Math.random() * diameter) * 1.5)); + + this._animDirectionIndex = []; + this._animDirectionIndex.push(1); + this._animDirectionIndex.push(-1); + + this._animSpeedIndex = []; + this._animSpeedIndex.push(FurniturePartyBeamerVisualization.ANIM_SPEED_FAST); + this._animSpeedIndex.push(FurniturePartyBeamerVisualization.ANIM_SPEED_SLOW); + + this._animFactorIndex = []; + this._animFactorIndex.push(this.getRandomAmplitudeFactor()); + this._animFactorIndex.push(this.getRandomAmplitudeFactor()); + } + + protected getLayerXOffset(scale: number, direction: number, layerId: number): number + { + if((layerId === 2) || (layerId === 3)) + { + if(this._animOffsetIndex.length == 2) + { + return this._animOffsetIndex[(layerId - 2)].x; + } + } + return super.getLayerXOffset(scale, direction, layerId); + } + + protected getLayerYOffset(scale: number, direction: number, layerId: number): number + { + if((layerId === 2) || (layerId === 3)) + { + if(this._animOffsetIndex.length == 2) + { + return this._animOffsetIndex[(layerId - 2)].y; + } + } + return super.getLayerYOffset(scale, direction, layerId); + } + + private getRandomAmplitudeFactor(): number + { + return ((Math.random() * 30) / 100) + 0.15; + } +} diff --git a/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualization.ts b/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualization.ts index bcf8c7e0..d312f3cb 100644 --- a/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualization.ts +++ b/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualization.ts @@ -1,6 +1,135 @@ +import { IPlanetSystem } from '../../../../../core'; +import { Vector3d } from '../../../../../room'; +import { RoomObjectVariable } from '../../RoomObjectVariable'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; +import { FurniturePlanetSystemVisualizationPlanetObject } from './FurniturePlanetSystemVisualizationPlanetObject'; export class FurniturePlanetSystemVisualization extends FurnitureAnimatedVisualization { + private _planetIndex: FurniturePlanetSystemVisualizationPlanetObject[]; + private _planetNameIndex: string[]; + private _offsetArray: Vector3d[]; + private _rootPosition: Vector3d; -} \ No newline at end of file + constructor() + { + super(); + + this._offsetArray = []; + this._rootPosition = new Vector3d(); + } + + public dispose():void + { + if(this._planetIndex) + { + while(this._planetIndex.length > 0) + { + const planet = this._planetIndex.shift(); + + planet.dispose(); + } + } + + this._planetIndex = null; + this._planetNameIndex = null; + } + + protected updateAnimation(scale: number): number + { + if(!this._planetIndex && (this.spriteCount > 0)) + { + if(!this.processPlanets()) return 0; + } + + if(this._planetIndex) + { + for(const planet of this._planetIndex) planet.update(this._offsetArray, this._rootPosition, scale); + + return super.updateAnimation(scale); + } + + return 0; + } + + protected getLayerXOffset(scale: number, direction: number, layerId: number): number + { + if(this._offsetArray[layerId]) + { + return this._offsetArray[layerId].x; + } + + return super.getLayerXOffset(scale, direction, layerId); + } + + protected getLayerYOffset(scale: number, direction: number, layerId: number): number + { + if(this._offsetArray[layerId]) + { + return this._offsetArray[layerId].y; + } + + return super.getLayerYOffset(scale, direction, layerId); + } + + protected getLayerZOffset(scale: number, direction: number, layerId: number): number + { + if(this._offsetArray[layerId]) + { + return this._offsetArray[layerId].z; + } + + return super.getLayerZOffset(scale, direction, layerId); + } + + private processPlanets(): boolean + { + if(!this.object || !this.object.model) return; + + const planetSystems = this.object.model.getValue(RoomObjectVariable.FURNITURE_PLANETSYSTEM_DATA); + + if(!planetSystems) return false; + + this._planetIndex = []; + this._planetNameIndex = []; + + for(const planet of planetSystems) + { + const sprite = this.getSprite(planet.id); + + if(sprite) + { + this.addPlanet(planet.name, planet.id, planet.parent, (planet.radius || 0), (planet.arcSpeed || 0), (planet.arcOffset || 0), (planet.height || 0)); + } + } + + return true; + } + + private addPlanet(name: string, index: number, parentName: string, radius: number, arcSpeed: number, arcOffset: number, height: number):void + { + if(!this._planetIndex) return; + + const planet = new FurniturePlanetSystemVisualizationPlanetObject(name, index, radius, arcSpeed, arcOffset, height); + const existingPlanet = this.getPlanet(parentName); + + if(existingPlanet) existingPlanet.addChild(planet); + else + { + this._planetIndex.push(planet); + this._planetNameIndex.push(name); + } + } + + private getPlanet(name: string): FurniturePlanetSystemVisualizationPlanetObject + { + for(const planet of this._planetIndex) + { + if(planet.name === name) return planet; + + if(planet.hasChild(name)) return planet.getChild(name); + } + + return null; + } +} diff --git a/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualizationPlanetObject.ts b/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualizationPlanetObject.ts new file mode 100644 index 00000000..b3bad212 --- /dev/null +++ b/src/nitro/room/object/visualization/furniture/FurniturePlanetSystemVisualizationPlanetObject.ts @@ -0,0 +1,91 @@ +import { Vector3d } from '../../../../../room'; + +export class FurniturePlanetSystemVisualizationPlanetObject +{ + private static SYSTEM_TEMPO: number = 30; + + private _name: string; + private _index: number; + private _radius: number; + private _arcSpeed: number; + private _arcOffset: number; + private _height: number; + private _position: number; + private _positionVector: Vector3d; + private _children: FurniturePlanetSystemVisualizationPlanetObject[]; + + constructor(name: string, index: number, radius: number, arcSpeed: number, arcOffset: number, height: number) + { + this._name = name; + this._index = index; + this._radius = radius; + this._arcSpeed = (((arcSpeed * Math.PI) * 2) / 360); + this._arcOffset = (((arcOffset * Math.PI) * 2) / 360); + this._height = height; + this._position = 0; + this._positionVector = new Vector3d(0, 0, 0); + this._children = []; + } + + public dispose():void + { + while(this._children.length > 0) + { + const child = this._children.shift(); + + child.dispose(); + } + } + + public update(offsets: Vector3d[], rootPosition: Vector3d, scale: number):void + { + this._position = (this._position + (this._arcSpeed / FurniturePlanetSystemVisualizationPlanetObject.SYSTEM_TEMPO)); + + offsets[this._index] = this.getPositionVector(rootPosition, scale); + + for(const child of this._children) child.update(offsets, this._positionVector, scale); + } + + public getPositionVector(position: Vector3d, scale: number): Vector3d + { + const cos = (this._radius * Math.cos((this._position + this._arcOffset))); + const sine = (this._radius * Math.sin((this._position + this._arcOffset))); + + this._positionVector.x = ((cos - sine) * (scale / 2)); + this._positionVector.y = ((((sine + cos) * (scale / 2)) * 0.5) - (this._height * (scale / 2))); + this._positionVector.z = -(Math.trunc(((4 * (cos + sine)) - 0.7))); + + if(position) this._positionVector.add(position); + + return this._positionVector; + } + + public addChild(planetObject: FurniturePlanetSystemVisualizationPlanetObject):void + { + if(this._children.indexOf(planetObject) >= 0) return; + + this._children.push(planetObject); + } + + public hasChild(name: string): boolean + { + return !!this.getChild(name); + } + + public getChild(name: string): FurniturePlanetSystemVisualizationPlanetObject + { + for(const child of this._children) + { + if(child.name === name) return child; + + if(child.hasChild(name)) return child.getChild(name); + } + + return null; + } + + public get name(): string + { + return this._name; + } +} diff --git a/src/nitro/room/object/visualization/furniture/FurnitureThumbnailVisualization.ts b/src/nitro/room/object/visualization/furniture/FurnitureThumbnailVisualization.ts index 319bd5e6..cdde344b 100644 --- a/src/nitro/room/object/visualization/furniture/FurnitureThumbnailVisualization.ts +++ b/src/nitro/room/object/visualization/furniture/FurnitureThumbnailVisualization.ts @@ -1,6 +1,6 @@ import { Resource, Texture } from '@pixi/core'; -import { Matrix, Rectangle } from '@pixi/math'; -import { NitroSprite } from '../../../../../core'; +import { Matrix } from '@pixi/math'; +import { NitroRectangle, NitroSprite } from '../../../../../core'; import { IGraphicAsset } from '../../../../../room/object/visualization/utils/IGraphicAsset'; import { TextureUtils } from '../../../../../room/utils/TextureUtils'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; @@ -13,6 +13,7 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat private _thumbnailImageNormal: Texture; private _thumbnailDirection: number; private _thumbnailChanged: boolean; + protected _hasOutline: boolean; constructor() { @@ -22,6 +23,7 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat this._thumbnailImageNormal = null; this._thumbnailDirection = -1; this._thumbnailChanged = false; + this._hasOutline = false; } public get hasThumbnailImage(): boolean @@ -92,7 +94,7 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat private generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture { - const _local_3 = 1.1; + const scale = 1.1; const matrix = new Matrix(); const _local_5 = (asset.width / texture.width); @@ -102,7 +104,7 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat matrix.a = _local_5; matrix.b = (-0.5 * _local_5); matrix.c = 0; - matrix.d = (_local_5 * _local_3); + matrix.d = (_local_5 * scale); matrix.tx = 0; matrix.ty = ((0.5 * _local_5) * texture.width); break; @@ -111,7 +113,7 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat matrix.a = _local_5; matrix.b = (0.5 * _local_5); matrix.c = 0; - matrix.d = (_local_5 * _local_3); + matrix.d = (_local_5 * scale); matrix.tx = 0; matrix.ty = 0; break; @@ -126,9 +128,14 @@ export class FurnitureThumbnailVisualization extends FurnitureAnimatedVisualizat const sprite = new NitroSprite(texture); + if(this._hasOutline) + { + // + } + sprite.transform.setFromMatrix(matrix); - return TextureUtils.generateTexture(sprite, new Rectangle(0, 0, asset.width, asset.height)); + return TextureUtils.generateTexture(sprite, new NitroRectangle(0, 0, (asset.width + 2), (asset.height + 2))); } protected getSpriteAssetName(scale: number, layerId: number): string diff --git a/src/nitro/room/object/visualization/furniture/index.ts b/src/nitro/room/object/visualization/furniture/index.ts index 90ac7a0c..33e62c57 100644 --- a/src/nitro/room/object/visualization/furniture/index.ts +++ b/src/nitro/room/object/visualization/furniture/index.ts @@ -17,6 +17,7 @@ export * from './FurnitureGuildIsometricBadgeVisualization'; export * from './FurnitureHabboWheelVisualization'; export * from './FurnitureMannequinVisualization'; export * from './FurnitureMannequinVisualizationData'; +export * from './FurnitureParticleSystem'; export * from './FurnitureParticleSystemEmitter'; export * from './FurnitureParticleSystemParticle'; export * from './FurniturePartyBeamerVisualization';