import {compose} from '@avocado/core'; import {hasGraphics, Container} from '@avocado/graphics'; import {Rectangle, Vector} from '@avocado/math'; import {StateProperty, Trait} from '../trait'; const decorate = compose( ); class GraphicalBase extends Trait { static defaultParams() { return { trackPosition: true, }; } initialize() { if (hasGraphics) { this._container = new Container(); } this.trackPosition = this.params.get('trackPosition'); } destroy() { if (this._container) { this._container.destroy(); } } get container() { return this._container; } get graphicalBoundingBox() { // Collect all bounding boxes. const graphicalBoundingBoxes = this.entity.invokeHookFlat( 'graphicalBoundingBoxes' ); if (0 === graphicalBoundingBoxes.length) { return [0, 0, 0, 0]; } let unifiedBoundingBox = [0, 0, 0, 0]; for (const graphicalBoundingBox of graphicalBoundingBoxes) { unifiedBoundingBox = Rectangle.united( unifiedBoundingBox, graphicalBoundingBox, ); } return unifiedBoundingBox; } shouldSynchronizePosition() { return this.entity.container && this.trackPosition; } synchronizePosition() { if (!('position' in this.entity)) { return; } this.entity.container.position = Vector.round(this.entity.position); this.entity.container.zIndex = this.entity.y; } listeners() { const listeners = {}; if (this.shouldSynchronizePosition()) { listeners.traitAdded = (type) => { if (-1 === [ 'graphical', 'positioned', ].indexOf(type)) { return; } this.synchronizePosition(); }; listeners.positionChanged = () => { this.synchronizePosition(); }; } return listeners; } } export class Graphical extends decorate(GraphicalBase) {}