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';
|
2019-04-10 21:02:15 -05:00
|
|
|
import {Rectangle, Vector} from '@avocado/math';
|
2019-03-18 20:07:05 -05:00
|
|
|
|
2019-04-14 20:33:52 -05:00
|
|
|
import {Container} from '../container';
|
|
|
|
import {hasGraphics} from '../has-graphics';
|
2019-06-05 20:19:12 -05:00
|
|
|
import {TraitVisiblePacket} from '../packets/trait-visible.packet';
|
2019-04-14 20:33:52 -05:00
|
|
|
|
2019-04-19 19:39:14 -05:00
|
|
|
const AUTO_ZINDEX = 1 << 16;
|
|
|
|
|
2019-03-18 20:07:05 -05:00
|
|
|
const decorate = compose(
|
2019-04-11 23:49:37 -05:00
|
|
|
StateProperty('isVisible', {
|
|
|
|
track: true,
|
|
|
|
}),
|
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';
|
|
|
|
}
|
|
|
|
|
2019-05-06 04:03:43 -05:00
|
|
|
constructor(entity, params, state) {
|
|
|
|
super(entity, params, state);
|
2019-03-19 10:40:59 -05:00
|
|
|
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);
|
|
|
|
}
|
2019-05-13 21:07:51 -05:00
|
|
|
this._container.isVisible = this.state.isVisible;
|
2019-03-19 10:40:59 -05:00
|
|
|
}
|
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;
|
2019-05-13 21:07:51 -05:00
|
|
|
const scale = this.state.visibleScale;
|
|
|
|
this._visibleScale = [scale[0], scale[1]];
|
|
|
|
this.onZIndexChanged(this.state.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-06-05 20:19:12 -05:00
|
|
|
acceptPacket(packet) {
|
|
|
|
if (packet instanceof TraitVisiblePacket) {
|
|
|
|
this.entity.isVisible = packet.data.isVisible;
|
|
|
|
this.entity.opacity = packet.data.opacity / 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-18 20:07:05 -05:00
|
|
|
get container() {
|
|
|
|
return this._container;
|
|
|
|
}
|
|
|
|
|
2019-05-06 04:03:43 -05:00
|
|
|
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-06-05 20:19:12 -05:00
|
|
|
packetsForUpdate() {
|
|
|
|
const packets = [];
|
|
|
|
if (this.isDirty) {
|
|
|
|
packets.push(new TraitVisiblePacket({
|
|
|
|
isVisible: this.entity.isVisible,
|
|
|
|
opacity: Math.floor(this.entity.opacity * 255),
|
|
|
|
}, this.entity));
|
|
|
|
this.makeClean();
|
|
|
|
}
|
|
|
|
return packets;
|
|
|
|
}
|
|
|
|
|
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) {
|
2019-05-13 21:07:51 -05:00
|
|
|
this.entity.visibleScale = scale;
|
2019-04-19 16:49:41 -05:00
|
|
|
}
|
|
|
|
|
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() {
|
2019-05-13 21:07:51 -05:00
|
|
|
return this.state.visibleScale[0];
|
2019-04-19 17:09:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
set visibleScaleX(x) {
|
|
|
|
this.rawVisibleScale = [x, this.visibleScaleY];
|
|
|
|
}
|
|
|
|
|
|
|
|
get visibleScaleY() {
|
2019-05-13 21:07:51 -05:00
|
|
|
return this.state.visibleScale[1];
|
2019-04-19 17:09:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2019-04-11 23:49:37 -05:00
|
|
|
|
|
|
|
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-11 23:49:37 -05:00
|
|
|
},
|
|
|
|
|
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;
|
2019-05-13 21:07:51 -05:00
|
|
|
this._visibleScale = [scale[0], scale[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
|
|
|
|
2019-05-06 04:03:43 -05:00
|
|
|
zIndexChanged: (old, zIndex) => {
|
|
|
|
this.onZIndexChanged(zIndex);
|
2019-04-19 19:39:14 -05:00
|
|
|
},
|
|
|
|
|
2019-04-11 23:49:37 -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() {
|
2019-05-08 23:54:30 -05:00
|
|
|
const visibleAabb = Rectangle.translated(
|
2019-05-01 21:35:38 -05:00
|
|
|
this._rawVisibleAabb,
|
|
|
|
this.entity.position
|
|
|
|
);
|
2019-05-08 23:54:30 -05:00
|
|
|
this.entity.visibleAabb[0] = visibleAabb[0];
|
|
|
|
this.entity.visibleAabb[1] = visibleAabb[1];
|
|
|
|
this.entity.visibleAabb[2] = visibleAabb[2];
|
|
|
|
this.entity.visibleAabb[3] = visibleAabb[3];
|
2019-05-08 18:10:50 -05:00
|
|
|
this.entity.emit('visibleAabbChanged');
|
2019-05-01 21:35:38 -05:00
|
|
|
}
|
|
|
|
|
2019-04-23 16:56:47 -05:00
|
|
|
tick(elapsed) {
|
2019-04-22 21:07:30 -05:00
|
|
|
if (AVOCADO_SERVER) {
|
|
|
|
if (this.scheduledBoundingBoxUpdate) {
|
|
|
|
// Collect all bounding boxes.
|
2019-05-01 20:07:55 -05:00
|
|
|
const visibleAabbs = this.entity.invokeHookFlat(
|
|
|
|
'visibleAabbs'
|
2019-04-22 21:07:30 -05:00
|
|
|
);
|
2019-05-01 20:07:55 -05:00
|
|
|
if (0 === visibleAabbs.length) {
|
2019-05-08 18:10:50 -05:00
|
|
|
this._rawVisibleAabb = [0, 0, 0, 0];
|
2019-04-22 21:07:30 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
let unifiedBoundingBox = [0, 0, 0, 0];
|
2019-05-01 20:07:55 -05:00
|
|
|
for (let i = 0; i < visibleAabbs.length; ++i) {
|
|
|
|
const visibleAabb = visibleAabbs[i];
|
2019-04-22 21:07:30 -05:00
|
|
|
unifiedBoundingBox = Rectangle.united(
|
|
|
|
unifiedBoundingBox,
|
2019-05-01 20:07:55 -05:00
|
|
|
visibleAabb,
|
2019-04-22 21:07:30 -05:00
|
|
|
);
|
|
|
|
}
|
2019-05-01 21:35:38 -05:00
|
|
|
this._rawVisibleAabb = unifiedBoundingBox;
|
2019-04-16 13:30:15 -05:00
|
|
|
}
|
2019-05-08 18:10:50 -05:00
|
|
|
this.translateVisibleAabb();
|
|
|
|
this.scheduledBoundingBoxUpdate = false;
|
2019-04-16 13:30:15 -05:00
|
|
|
}
|
|
|
|
}
|
2019-04-12 13:05:30 -05:00
|
|
|
}
|
2019-03-18 20:07:05 -05:00
|
|
|
|
2019-04-12 13:05:30 -05:00
|
|
|
}
|