import {Trait} from '@avocado/entity'; import {Vector} from '@avocado/math'; export default class Layered extends Trait { static behaviorTypes() { return { layer: { type: 'layer', label: 'Layer', }, removeFromLayer: { type: 'void', label: 'Remove from layer.', }, setIntoLayer: { type: 'void', label: 'Set into layer $1.', args: [ ['layer', { type: 'layer', }], ], }, }; } static type() { return 'layered'; } constructor(entity, params, state) { super(entity, params, state); this.entity.layer = null; this._tile = [0, 0]; this._tileOffset = [0, 0]; this.setCurrentTileFromLayer(); } destroy() { this.entity.removeFromLayer(); } get tile() { return this._tile; } get tileOffset() { return this._tileOffset; } onLayerTilesetChanged() { this.setCurrentTileFromLayer(); } setCurrentTileFromLayer() { const layer = this.entity.layer; if (!layer) { return; } if (!this.entity.is('positioned')) { return; } const tileset = layer.tileset; if (!tileset) { return; } const oldTile = Vector.copy(this._tile); this._tile = Vector.div( this.entity.position, tileset.tileSize, ); if (!Vector.equals(oldTile, this._tile)) { this.entity.emit('tileChanged', oldTile, this._tile); } const oldTileOffset = Vector.copy(this._tileOffset); this._tileOffset = Vector.mod( this.entity.position, tileset.tileSize, ); if (!Vector.equals(oldTileOffset, this._tileOffset)) { this.entity.emit('tileOffsetChanged', oldTileOffset, this._tileOffset); } } listeners() { return { positionChanged: () => { this.setCurrentTileFromLayer(); }, traitAdded: () => { this.setCurrentTileFromLayer(); }, } } methods() { return { removeFromLayer: () => { const layer = this.entity.layer; if (!layer) { return; } layer.off('tilesetChanged', this.onLayerTilesetChanged); this.entity.layer = null; this.entity.emit('removedFromLayer', layer); }, setIntoLayer: (layer) => { this.entity.layer = layer; layer.on('tilesetChanged', this.onLayerTilesetChanged, this); this.setCurrentTileFromLayer(); this.entity.emit('addedToLayer'); }, }; } }