2019-03-20 20:15:04 -05:00
|
|
|
import {compose} from '@avocado/core';
|
|
|
|
import {Image, Sprite} from '@avocado/graphics';
|
|
|
|
import {Vector} from '@avocado/math';
|
|
|
|
|
|
|
|
import {simpleState, Trait} from '../trait';
|
|
|
|
|
|
|
|
const decorate = compose(
|
|
|
|
simpleState('currentImage', {
|
|
|
|
track: true,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
|
|
|
class PicturedBase extends Trait {
|
|
|
|
|
|
|
|
static defaultParams() {
|
|
|
|
return {
|
|
|
|
images: {},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static defaultState() {
|
|
|
|
return {
|
|
|
|
currentImage: 'initial',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-03-20 23:23:34 -05:00
|
|
|
initialize() {
|
|
|
|
this.sprites = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
destroy() {
|
|
|
|
if (this.sprites) {
|
|
|
|
for (const key in this.sprites) {
|
|
|
|
this.hideImage(key);
|
|
|
|
const sprite = this.sprites[key];
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
const images = this.params.get('images');
|
|
|
|
// Load all images.
|
|
|
|
this.sprites = {};
|
|
|
|
for (const key in images) {
|
|
|
|
const {uri} = images[key];
|
|
|
|
Image.load(uri).then((image) => {
|
2019-03-20 21:58:14 -05:00
|
|
|
const sprite = this.sprites[key] = new Sprite(image);
|
|
|
|
// Calculate any offset.
|
|
|
|
const images = this.params.get('images');
|
|
|
|
const size = image.size;
|
|
|
|
const halfway = Vector.scale(size, -0.5);
|
|
|
|
const {offset} = images[key];
|
|
|
|
sprite.position = Vector.add(halfway, offset);
|
|
|
|
// Set current image upfront.
|
2019-03-20 20:15:04 -05:00
|
|
|
const isCurrentImage = key === this.entity.currentImage;
|
|
|
|
if (isCurrentImage) {
|
|
|
|
this.showImage(key);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
showImage(key) {
|
|
|
|
if (!this.sprites) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const sprite = this.sprites[key];
|
|
|
|
if (!sprite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.entity.container.addChild(sprite);
|
|
|
|
}
|
|
|
|
|
|
|
|
listeners() {
|
|
|
|
return {
|
|
|
|
currentImageChanged: (oldKey) => {
|
|
|
|
// Only client/graphics.
|
|
|
|
if (!this.sprites) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Swap the image.
|
|
|
|
this.hideImage(oldKey);
|
|
|
|
this.showImage(this.entity.currentImage);
|
|
|
|
},
|
|
|
|
traitAdded: (trait) => {
|
|
|
|
if (-1 === [
|
|
|
|
'graphical',
|
|
|
|
'pictured',
|
|
|
|
].indexOf(trait.constructor.type())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.loadImagesIfPossible();
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Pictured extends decorate(PicturedBase) {}
|