avocado-old/packages/graphics/traits/visible.trait.js
2019-04-19 17:09:48 -05:00

162 lines
3.4 KiB
JavaScript

import * as I from 'immutable';
import {compose} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {Rectangle, Vector} from '@avocado/math';
import {Property} from '@avocado/mixins';
import {Container} from '../container';
import {hasGraphics} from '../has-graphics';
const decorate = compose(
StateProperty('isVisible', {
track: true,
}),
Property('visibleBoundingBox', {
default: [0, 0, 0, 0],
emit: function (...args) {
this.entity.emit(...args);
},
track: true,
}),
StateProperty('visibleScale', {
track: true,
}),
);
export class Visible extends decorate(Trait) {
static defaultParams() {
return {
trackPosition: true,
};
}
static defaultState() {
return {
isVisible: true,
visibleScale: [1, 1],
};
}
initialize() {
if (hasGraphics) {
this._container = new Container();
this._container.isVisible = this.entity.isVisible;
}
this.scheduledBoundingBoxUpdate = true;
this.trackPosition = this.params.get('trackPosition');
}
destroy() {
if (this._container) {
this._container.destroy();
}
}
get container() {
return this._container;
}
get rawVisibleScale() {
const scale = this.entity.visibleScale;
return [scale.get(0), scale.get(1)];
}
set rawVisibleScale(scale) {
this.entity.visibleScale = I.List(scale);
}
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;
}
get visibleScaleX() {
return this.entity.visibleScale.get(0);
}
set visibleScaleX(x) {
this.rawVisibleScale = [x, this.visibleScaleY];
}
get visibleScaleY() {
return this.entity.visibleScale.get(1);
}
set visibleScaleY(y) {
this.rawVisibleScale = [this.visibleScaleX, y];
}
listeners() {
const listeners = {
isVisibleChanged: () => {
this.entity.container.visible = this.entity.isVisible;
},
positionChanged: () => {
this.scheduledBoundingBoxUpdate = true;
},
};
if (this.shouldSynchronizePosition()) {
listeners.traitAdded = (type) => {
if (-1 === [
'visible',
'positioned',
].indexOf(type)) {
return;
}
this.synchronizePosition();
};
}
return listeners;
}
methods() {
return {
updateVisibleBoundingBox: () => {
this.scheduledBoundingBoxUpdate = true;
},
}
}
tick(elapsed) {
if (this.shouldSynchronizePosition()) {
this.synchronizePosition();
}
if (this.scheduledBoundingBoxUpdate) {
// Collect all bounding boxes.
const visibleBoundingBoxes = this.entity.invokeHookFlat(
'visibleBoundingBoxes'
);
if (0 === visibleBoundingBoxes.length) {
this.visibleBoundingBox = [0, 0, 0, 0];
}
else {
let unifiedBoundingBox = [0, 0, 0, 0];
for (let i = 0; i < visibleBoundingBoxes.length; ++i) {
const visibleBoundingBox = visibleBoundingBoxes[i];
unifiedBoundingBox = Rectangle.united(
unifiedBoundingBox,
visibleBoundingBox,
);
}
this.visibleBoundingBox = unifiedBoundingBox;
this.scheduledBoundingBoxUpdate = false;
}
}
}
}