110 lines
2.6 KiB
JavaScript
110 lines
2.6 KiB
JavaScript
import {Vector} from '@avocado/math';
|
|
|
|
import {Shape} from './shape';
|
|
import {shapeFromJSON} from './index';
|
|
|
|
export class ShapeList extends Shape {
|
|
|
|
constructor() {
|
|
super();
|
|
this._shapes = [];
|
|
this.on('shapesChanged', () => {
|
|
this._shapes.forEach((shape) => {
|
|
shape.off('aabbChanged');
|
|
shape.on('aabbChanged', () => {
|
|
this.emit('aabbChanged');
|
|
});
|
|
});
|
|
});
|
|
this.on('originChanged', (oldOrigin) => {
|
|
this._shapes.forEach((shape) => {
|
|
shape.emit('parentOriginChanged', oldOrigin, this.origin);
|
|
});
|
|
});
|
|
this.on('rotationChanged', (oldRotation) => {
|
|
this._shapes.forEach((shape) => {
|
|
shape.emit('parentRotationChanged', oldRotation, this.rotation);
|
|
});
|
|
});
|
|
this.on('scaleChanged', (oldScale) => {
|
|
this._shapes.forEach((shape) => {
|
|
shape.emit('parentScaleChanged', oldScale, this.scale);
|
|
});
|
|
});
|
|
}
|
|
|
|
*[Symbol.iterator]() {
|
|
for (const shape of this._shapes) {
|
|
yield shape;
|
|
}
|
|
}
|
|
|
|
get aabb() {
|
|
if (0 === this._shapes.length) {
|
|
return [0, 0, 0, 0];
|
|
}
|
|
const min = [Infinity, Infinity];
|
|
const max = [-Infinity, -Infinity];
|
|
for (const shape of this._shapes) {
|
|
const aabb = shape.aabb;
|
|
min[0] = aabb[0] < min[0] ? aabb[0] : min[0];
|
|
min[1] = aabb[1] < min[1] ? aabb[1] : min[1];
|
|
max[0] = aabb[0] > max[0] ? aabb[0] : max[0];
|
|
max[1] = aabb[1] > max[1] ? aabb[1] : max[1];
|
|
}
|
|
return Rectangle.translated(
|
|
[min[0], min[1], max[0] - min[0], max[1] - min[1]],
|
|
this.position
|
|
);
|
|
}
|
|
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
if (json.shapes) {
|
|
const shapes = [];
|
|
json.shapes.forEach((shape) => {
|
|
shapes.push(shapeFromJSON(shape));
|
|
});
|
|
this._shapes = shapes;
|
|
this.emit('shapesChanged');
|
|
}
|
|
return this;
|
|
}
|
|
|
|
addShape(shape) {
|
|
this._shapes.push(shape);
|
|
this.emit('shapesChanged');
|
|
}
|
|
|
|
intersects(list) {
|
|
if (0 === this._shapes.length) {
|
|
return false;
|
|
}
|
|
if (!Rectangle.intersects(this.aabb, list.aabb)) {
|
|
return false;
|
|
}
|
|
// TODO: Quadtrees?
|
|
for (const shape of this._shapes) {
|
|
for (const otherShape of list._shapes) {
|
|
if (Rectangle.intersects(
|
|
Rectangle.translated(shape.aabb, this.position),
|
|
Rectangle.translated(otherShape.aabb, otherShape.position)
|
|
)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
...super.toJSON(),
|
|
type: 'list',
|
|
shapes: this._shapes.map((shape) => {
|
|
return shape.toJSON();
|
|
}),
|
|
}
|
|
}
|
|
|
|
} |