avocado-old/packages/topdown/tileset.resource.js
2019-09-16 21:52:08 -05:00

109 lines
2.2 KiB
JavaScript

import {compose, EventEmitter, Property} from '@avocado/core';
import {hasGraphics, Image} from '@avocado/graphics';
import {Rectangle, Vector} from '@avocado/math';
import {shapeFromJSON} from '@avocado/physics';
import {Resource} from '@avocado/resource';
const decorate = compose(
EventEmitter,
Property('image', {
track: true,
}),
Vector.Mixin('tileSize', 'tileWidth', 'tileHeight', {
default: [0, 0],
}),
);
export class Tileset extends decorate(Resource) {
constructor(json) {
super();
this._geometry = {};
this.subimages = [];
if ('undefined' !== typeof json) {
this.fromJSON(json);
}
}
destroy() {
this.subimages.forEach((subimage) => {
subimage.destroy();
});
this.subimages = [];
}
fromJSON(json) {
let promise;
if (json.geometry) {
for (const i in json.geometry) {
const shapeJSON = json.geometry[i];
this._geometry[i] = shapeFromJSON(shapeJSON);
}
}
if (json.tileSize) {
this.tileSize = json.tileSize;
}
if (hasGraphics && json.imageUri) {
Image.load(json.imageUri).then((image) => {
this.image = image;
});
}
}
geometry(index) {
return this._geometry[index];
}
get image() {
return super.image;
}
set image(image) {
this.recalculateSubimages(image);
super.image = image;
}
recalculateSubimages(image) {
if (!image) {
return;
}
const tileSize = this.tileSize;
if (Vector.isZero(tileSize)) {
return;
}
this.destroy();
const grid = Vector.div(image.size, tileSize);
const rectangle = Rectangle.compose([0, 0], tileSize);
for (let j = 0; j < grid[1]; ++j) {
for (let i = 0; i < grid[0]; ++i) {
const subimage = image.subimage(rectangle);
this.subimages.push(subimage);
rectangle[0] += tileSize[0];
}
rectangle[0] = 0;
rectangle[1] += tileSize[1];
}
}
subimage(index) {
return this.subimages[index];
}
get tileSize() {
return super.tileSize;
}
set tileSize(tileSize) {
super.tileSize = tileSize;
this.recalculateSubimages(this.image);
}
toJSON() {
return {
tileSize: this.tileSize,
imageUri: this.image.uri,
}
}
}