import {compose} from '@avocado/core'; import {StateProperty, Trait} from '@avocado/entity'; import {Rectangle, Vector} from '@avocado/math'; import {Container} from '../container'; import {hasGraphics} from '../has-graphics'; const decorate = compose( StateProperty('isVisible', { track: true, }), ); export class Visible extends decorate(Trait) { static defaultParams() { return { trackPosition: true, }; } static defaultState() { return { isVisible: true, }; } initialize() { if (hasGraphics) { this._container = new Container(); this._container.isVisible = this.entity.isVisible; } this.trackPosition = this.params.get('trackPosition'); this._visibleBoundingBox = [0, 0, 0, 0]; } destroy() { if (this._container) { this._container.destroy(); } } get container() { return this._container; } get visibleBoundingBox() { if (Rectangle.isNull(this._visibleBoundingBox)) { // Collect all bounding boxes. const visibleBoundingBoxes = this.entity.invokeHookFlat( 'visibleBoundingBoxes' ); if (0 === visibleBoundingBoxes.length) { return [0, 0, 0, 0]; } let unifiedBoundingBox = [0, 0, 0, 0]; for (const visibleBoundingBox of visibleBoundingBoxes) { unifiedBoundingBox = Rectangle.united( unifiedBoundingBox, visibleBoundingBox, ); } this._visibleBoundingBox = unifiedBoundingBox; } return this._visibleBoundingBox; } shouldSynchronizePosition() { return this._container && this.trackPosition; } synchronizePosition() { if (!this.entity.is('positioned')) { return; } this.entity.container.position = this.entity.position; this.entity.container.zIndex = this.entity.y; } listeners() { const listeners = { isVisibleChanged: () => { this.entity.container.visible = this.entity.isVisible; }, visibleBoundingBoxesUpdated: () => { this._visibleBoundingBox = [0, 0, 0, 0]; } }; if (this.shouldSynchronizePosition()) { listeners.traitAdded = (type) => { if (-1 === [ 'visible', 'positioned', ].indexOf(type)) { return; } this.synchronizePosition(); }; } return listeners; } tick(elapsed) { if (this.shouldSynchronizePosition()) { this.synchronizePosition(); } } }