avocado-old/packages/graphics/traits/visible.trait.js

227 lines
4.8 KiB
JavaScript
Raw Normal View History

2019-04-19 16:49:41 -05:00
import * as I from 'immutable';
2019-04-28 23:45:03 -05:00
import {compose, Property} from '@avocado/core';
2019-04-14 20:21:52 -05:00
import {StateProperty, Trait} from '@avocado/entity';
import {Rectangle, Vector} from '@avocado/math';
2019-03-18 20:07:05 -05:00
import {Container} from '../container';
import {hasGraphics} from '../has-graphics';
2019-04-19 19:39:14 -05:00
const AUTO_ZINDEX = 1 << 16;
2019-03-18 20:07:05 -05:00
const decorate = compose(
StateProperty('isVisible', {
track: true,
}),
Property('visibleAabb', {
2019-04-16 13:30:15 -05:00
default: [0, 0, 0, 0],
emit: function (...args) {
this.entity.emit(...args);
},
track: true,
2019-04-19 16:49:41 -05:00
}),
2019-04-19 17:23:01 -05:00
StateProperty('opacity', {
track: true,
}),
2019-04-19 16:49:41 -05:00
StateProperty('visibleScale', {
track: true,
}),
2019-04-19 19:39:14 -05:00
StateProperty('zIndex', {
track: true,
}),
2019-03-18 20:07:05 -05:00
);
2019-04-14 18:42:13 -05:00
export class Visible extends decorate(Trait) {
2019-03-18 20:07:05 -05:00
static defaultParams() {
return {
2019-04-21 05:07:15 -05:00
filter: undefined,
2019-03-18 20:07:05 -05:00
trackPosition: true,
};
}
2019-04-12 00:36:30 -05:00
static defaultState() {
return {
isVisible: true,
2019-04-19 17:23:01 -05:00
opacity: 1,
2019-04-19 16:49:41 -05:00
visibleScale: [1, 1],
2019-04-19 19:39:14 -05:00
zIndex: AUTO_ZINDEX,
2019-04-12 00:36:30 -05:00
};
}
2019-05-05 04:26:35 -05:00
static type() {
return 'visible';
}
constructor(entity, params, state) {
super(entity, params, state);
if (hasGraphics) {
this._container = new Container();
2019-05-04 14:06:47 -05:00
const filter = this.params.filter;
2019-04-21 05:07:15 -05:00
if (filter) {
this._container.setFilter(filter);
}
this._container.isVisible = this.state.get('isVisible');
}
2019-05-01 21:35:38 -05:00
this._rawVisibleAabb = [0, 0, 0, 0];
2019-04-16 13:30:15 -05:00
this.scheduledBoundingBoxUpdate = true;
2019-05-04 14:06:47 -05:00
this.trackPosition = this.params.trackPosition;
const scale = this.state.get('visibleScale');
2019-05-01 21:35:38 -05:00
this._visibleScale = [scale.get(0), scale.get(1)];
this.onZIndexChanged(this.state.get('zIndex'));
2019-03-18 20:07:05 -05:00
}
2019-03-20 23:23:34 -05:00
destroy() {
if (this._container) {
this._container.destroy();
}
}
2019-03-18 20:07:05 -05:00
get container() {
return this._container;
}
onZIndexChanged(zIndex) {
2019-04-19 19:39:14 -05:00
this._usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this._usingAutoZIndex) {
2019-04-19 19:48:35 -05:00
if (this._container) {
this._container.zIndex = zIndex;
}
2019-04-19 19:39:14 -05:00
}
}
2019-04-19 16:49:41 -05:00
get rawVisibleScale() {
2019-05-01 21:35:38 -05:00
return this._visibleScale;
2019-04-19 16:49:41 -05:00
}
set rawVisibleScale(scale) {
this.entity.visibleScale = I.List(scale);
}
2019-03-19 11:03:48 -05:00
synchronizePosition() {
2019-04-12 15:53:44 -05:00
if (!this.entity.is('positioned')) {
2019-03-19 11:48:46 -05:00
return;
2019-03-19 11:25:42 -05:00
}
2019-04-19 17:23:01 -05:00
if (!this._container) {
return;
}
this._container.position = this.entity.position;
2019-04-19 19:39:14 -05:00
if (this._usingAutoZIndex) {
2019-04-19 19:48:35 -05:00
if (this._container) {
this._container.zIndex = this.entity.y;
}
2019-04-19 19:39:14 -05:00
}
2019-03-19 11:03:48 -05:00
}
2019-04-19 17:09:48 -05:00
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];
}
2019-03-18 20:07:05 -05:00
listeners() {
2019-05-02 22:18:30 -05:00
return {
isVisibleChanged: () => {
2019-04-19 17:23:01 -05:00
if (!this._container) {
return;
}
this._container.visible = this.entity.isVisible;
},
opacityChanged: () => {
if (!this._container) {
return;
}
this._container.alpha = this.entity.opacity;
},
2019-04-16 13:30:15 -05:00
positionChanged: () => {
2019-05-01 21:35:38 -05:00
this.translateVisibleAabb();
},
2019-05-02 22:18:30 -05:00
traitAdded: (type) => {
if (-1 === [
'visible',
'positioned',
].indexOf(type)) {
return;
}
this.synchronizePosition();
},
2019-05-01 21:35:38 -05:00
visibleScaleChanged: () => {
const scale = this.entity.visibleScale;
this._visibleScale = [scale.get(0), scale.get(1)];
2019-05-02 23:32:56 -05:00
if (this._container) {
this._container.scale = this._visibleScale;
}
2019-04-16 13:30:15 -05:00
},
2019-04-16 09:26:01 -05:00
zIndexChanged: (old, zIndex) => {
this.onZIndexChanged(zIndex);
2019-04-19 19:39:14 -05:00
},
};
2019-03-18 20:07:05 -05:00
}
2019-04-16 13:30:15 -05:00
methods() {
return {
updateVisibleBoundingBox: () => {
this.scheduledBoundingBoxUpdate = true;
},
}
}
2019-04-23 16:56:47 -05:00
renderTick(elapsed) {
2019-05-02 22:18:30 -05:00
this.synchronizePosition();
2019-04-23 16:56:47 -05:00
}
2019-05-01 21:35:38 -05:00
translateVisibleAabb() {
this.visibleAabb = Rectangle.translated(
this._rawVisibleAabb,
this.entity.position
);
}
2019-04-23 16:56:47 -05:00
tick(elapsed) {
if (AVOCADO_SERVER) {
if (this.scheduledBoundingBoxUpdate) {
// Collect all bounding boxes.
const visibleAabbs = this.entity.invokeHookFlat(
'visibleAabbs'
);
if (0 === visibleAabbs.length) {
this.visibleAabb = [0, 0, 0, 0];
}
else {
let unifiedBoundingBox = [0, 0, 0, 0];
for (let i = 0; i < visibleAabbs.length; ++i) {
const visibleAabb = visibleAabbs[i];
unifiedBoundingBox = Rectangle.united(
unifiedBoundingBox,
visibleAabb,
);
}
2019-05-01 21:35:38 -05:00
this._rawVisibleAabb = unifiedBoundingBox;
this.translateVisibleAabb();
this.scheduledBoundingBoxUpdate = false;
2019-04-16 13:30:15 -05:00
}
}
}
}
2019-03-18 20:07:05 -05:00
}