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

178 lines
3.8 KiB
JavaScript
Raw Normal View History

2019-03-20 20:15:04 -05:00
import {compose} 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-20 20:15:04 -05:00
import {Image} from '../image';
import {Sprite} from '../sprite';
2019-03-20 20:15:04 -05:00
const decorate = compose(
2019-03-23 23:24:18 -05:00
StateProperty('currentImage', {
2019-03-20 20:15:04 -05:00
track: true,
}),
);
2019-04-16 13:30:15 -05:00
export class Pictured extends decorate(Trait) {
2019-03-20 20:15:04 -05:00
static defaultParams() {
return {
images: {},
};
}
static defaultState() {
return {
currentImage: 'initial',
};
}
2019-03-20 23:23:34 -05:00
initialize() {
this._images = this.params.get('images').toJS();
2019-03-20 23:23:34 -05:00
this.sprites = undefined;
}
destroy() {
if (this.sprites) {
for (const key in this.sprites) {
this.hideImage(key);
const sprite = this.sprites[key];
2019-04-30 17:11:41 -05:00
sprite.image.destroy();
2019-03-20 23:23:34 -05:00
sprite.destroy();
}
}
}
2019-03-20 20:15:04 -05:00
hideImage(key) {
if (!this.sprites) {
return;
}
const sprite = this.sprites[key];
if (!sprite) {
return;
}
this.entity.container.removeChild(sprite);
}
loadImagesIfPossible() {
if (!this.entity.container) {
return;
}
if (this.sprites) {
return;
}
// Load all images.
2019-04-16 13:30:15 -05:00
const imagePromises = [];
2019-03-20 20:15:04 -05:00
this.sprites = {};
for (const key in this._images) {
const {uri} = this._images[key];
2019-04-16 13:30:15 -05:00
const imagePromise = Image.load(uri).then((image) => {
2019-03-20 21:58:14 -05:00
const sprite = this.sprites[key] = new Sprite(image);
// Calculate any offset.
sprite.position = this.offsetFor(key);
2019-03-20 21:58:14 -05:00
// Set current image upfront.
2019-03-20 20:15:04 -05:00
const isCurrentImage = key === this.entity.currentImage;
if (isCurrentImage) {
this.showImage(key);
}
});
2019-04-16 13:30:15 -05:00
imagePromises.push(imagePromise);
2019-03-20 20:15:04 -05:00
}
2019-04-16 13:30:15 -05:00
Promise.all(imagePromises).then((images) => {
// Bounding box update.
this.entity.updateVisibleBoundingBox();
2019-04-19 16:49:41 -05:00
this.setSpriteScale();
2019-04-16 13:30:15 -05:00
});
2019-03-20 20:15:04 -05:00
}
offsetFor(key) {
if (!this._images[key] || !this._images[key].offset) {
return [0, 0];
}
return this._images[key].offset;
}
2019-04-19 16:49:41 -05:00
setSpriteScale() {
if (!this.sprites) {
return;
}
const rawScale = this.entity.rawVisibleScale;
for (const key in this.sprites) {
const sprite = this.sprites[key];
sprite.scale = rawScale;
}
}
2019-03-20 20:15:04 -05:00
showImage(key) {
if (!this.sprites) {
return;
}
const sprite = this.sprites[key];
if (!sprite) {
return;
}
this.entity.container.addChild(sprite);
}
sizeFor(key) {
if (!this._images[key] || !this._images[key].size) {
return [0, 0];
}
return this._images[key].size;
}
hooks() {
return {
visibleAabbs: () => {
const key = this.entity.currentImage;
const image = this._images[key];
if (!image) {
return [0, 0, 0, 0];
}
const viewPosition = this.offsetFor(key);
2019-04-11 12:20:24 -05:00
const position = Vector.add(this.entity.position, viewPosition);
2019-04-19 16:49:41 -05:00
const size = this.sizeFor(key);
const rectangle = Rectangle.compose(position, size);
const expanded = Rectangle.expand(
rectangle,
Vector.sub(Vector.mul(size, this.entity.rawVisibleScale), size),
);
return expanded;
},
}
}
2019-03-20 20:15:04 -05:00
listeners() {
return {
2019-03-20 20:15:04 -05:00
currentImageChanged: (oldKey) => {
// Bounding box update.
2019-04-16 13:30:15 -05:00
this.entity.updateVisibleBoundingBox();
2019-03-20 20:15:04 -05:00
// Only client/graphics.
if (!this.sprites) {
return;
}
// Swap the image.
this.hideImage(oldKey);
this.showImage(this.entity.currentImage);
},
2019-04-19 16:49:41 -05:00
2019-04-19 17:09:48 -05:00
visibleScaleChanged: () => {
2019-04-19 16:49:41 -05:00
this.setSpriteScale();
},
traitAdded: (type) => {
2019-03-20 20:15:04 -05:00
if (-1 === [
2019-04-14 18:42:13 -05:00
'visible',
2019-03-20 20:15:04 -05:00
'pictured',
].indexOf(type)) {
2019-03-20 20:15:04 -05:00
return;
}
this.loadImagesIfPossible();
},
2019-03-20 20:15:04 -05:00
};
}
}