chore: remove event listeners on shape destroy

This commit is contained in:
cha0s 2019-05-03 01:21:35 -05:00
parent 093b7d7572
commit 3e2e85faf3
7 changed files with 152 additions and 69 deletions

View File

@ -12,9 +12,7 @@ export class CircleShape extends decorate(Shape) {
constructor() { constructor() {
super(); super();
this.on('radiusChanged', () => { this.on('radiusChanged', this.onAabbChanged, this);
this.emit('aabbChanged');
});
} }
get aabb() { get aabb() {
@ -28,6 +26,11 @@ export class CircleShape extends decorate(Shape) {
]; ];
} }
destroy() {
super.destroy();
this.off('radiusChanged', this.onAabbChanged);
}
fromJSON(json) { fromJSON(json) {
super.fromJSON(json); super.fromJSON(json);
if (json.radius) { if (json.radius) {
@ -36,6 +39,10 @@ export class CircleShape extends decorate(Shape) {
return this; return this;
} }
onAabbChanged() {
this.emit('aabbChanged');
}
toJSON() { toJSON() {
return { return {
...super.toJSON(), ...super.toJSON(),

View File

@ -8,29 +8,22 @@ export class ShapeList extends Shape {
constructor() { constructor() {
super(); super();
this._shapes = []; this._shapes = [];
this.on('shapesChanged', () => { this.on('shapesChanged', this.onShapesChanged, this);
this._shapes.forEach((shape) => { this.on('originChanged', this.onOriginChanged, this);
shape.off('aabbChanged'); this.on('rotationChanged', this.onRotationChanged, this);
shape.on('aabbChanged', () => { this.on('scaleChanged', this.onScaleChanged, this);
this.emit('aabbChanged'); }
});
}); destroy() {
}); super.destroy();
this.on('originChanged', (oldOrigin) => { this.off('shapesChanged', this.onShapesChanged);
this._shapes.forEach((shape) => { this.off('originChanged', this.onOriginChanged);
shape.emit('parentOriginChanged', oldOrigin, this.origin); this.off('rotationChanged', this.onRotationChanged);
}); this.off('scaleChanged', this.onScaleChanged);
}); for (let i = 0; i < this._shapes.length; i++) {
this.on('rotationChanged', (oldRotation) => { const shape = this._shapes[i];
this._shapes.forEach((shape) => { shape.destroy();
shape.emit('parentRotationChanged', oldRotation, this.rotation); }
});
});
this.on('scaleChanged', (oldScale) => {
this._shapes.forEach((shape) => {
shape.emit('parentScaleChanged', oldScale, this.scale);
});
});
} }
*[Symbol.iterator]() { *[Symbol.iterator]() {
@ -58,6 +51,12 @@ export class ShapeList extends Shape {
); );
} }
addShape(shape) {
const oldShapes = [...this._shapes];
this._shapes.push(shape);
this.emit('shapesChanged', oldShapes, this._shapes);
}
fromJSON(json) { fromJSON(json) {
super.fromJSON(json); super.fromJSON(json);
if (json.shapes) { if (json.shapes) {
@ -65,17 +64,13 @@ export class ShapeList extends Shape {
json.shapes.forEach((shape) => { json.shapes.forEach((shape) => {
shapes.push(shapeFromJSON(shape)); shapes.push(shapeFromJSON(shape));
}); });
const oldShapes = [...this._shapes];
this._shapes = shapes; this._shapes = shapes;
this.emit('shapesChanged'); this.emit('shapesChanged', oldShapes, this._shapes);
} }
return this; return this;
} }
addShape(shape) {
this._shapes.push(shape);
this.emit('shapesChanged');
}
intersects(list) { intersects(list) {
if (0 === this._shapes.length) { if (0 === this._shapes.length) {
return false; return false;
@ -97,6 +92,37 @@ export class ShapeList extends Shape {
return false; return false;
} }
onChildAabbChanged() {
this.emit('aabbChanged');
}
onOriginChanged(oldOrigin) {
this._shapes.forEach((shape) => {
shape.emit('parentOriginChanged', oldOrigin, this.origin);
});
}
onRotationChanged(oldRotation) {
this._shapes.forEach((shape) => {
shape.emit('parentRotationChanged', oldRotation, this.rotation);
});
}
onScaleChanged(oldScale) {
this._shapes.forEach((shape) => {
shape.emit('parentScaleChanged', oldScale, this.scale);
});
}
onShapesChanged(oldShapes) {
oldShapes.forEach((shape) => {
shape.off('aabbChanged');
});
this._shapes.forEach((shape) => {
shape.on('aabbChanged', this.onChildAabbChanged, this);
});
}
toJSON() { toJSON() {
return { return {
...super.toJSON(), ...super.toJSON(),

View File

@ -16,18 +16,20 @@ export class PolygonShape extends Shape {
'rotationChanged', 'rotationChanged',
'scaleChanged', 'scaleChanged',
'verticesChanged', 'verticesChanged',
], () => { ], this.onRecalculateVertices, this);
const parentOrigin = this.parent ? this.parent.origin : [0, 0]; }
const origin = Vector.add(this.origin, parentOrigin);
const parentRotation = this.parent ? this.parent.rotation : 0; destroy() {
const rotation = this.rotation + parentRotation; super.destroy();
const parentScale = this.parent ? this.parent.scale : 1; this.off([
const scale = this.scale * parentScale; 'parentOriginChanged',
this._translatedVertices = this._vertices.map((vertice) => { 'parentRotationChanged',
return Vertice.translate(vertice, origin, rotation, scale); 'parentScaleChanged',
}); 'originChanged',
this.emit('aabbChanged'); 'rotationChanged',
}); 'scaleChanged',
'verticesChanged',
], this.onRecalculateVertices);
} }
*[Symbol.iterator]() { *[Symbol.iterator]() {
@ -62,6 +64,19 @@ export class PolygonShape extends Shape {
return this; return this;
} }
onRecalculateVertices() {
const parentOrigin = this.parent ? this.parent.origin : [0, 0];
const origin = Vector.add(this.origin, parentOrigin);
const parentRotation = this.parent ? this.parent.rotation : 0;
const rotation = this.rotation + parentRotation;
const parentScale = this.parent ? this.parent.scale : 1;
const scale = this.scale * parentScale;
this._translatedVertices = this._vertices.map((vertice) => {
return Vertice.translate(vertice, origin, rotation, scale);
});
this.emit('aabbChanged');
}
get vertices() { get vertices() {
return this._vertices; return this._vertices;
} }

View File

@ -14,18 +14,12 @@ export class RectangleShape extends decorate(PolygonShape) {
constructor() { constructor() {
super(); super();
this.on(['positionChanged', 'sizeChanged'], () => { this.on(['positionChanged', 'sizeChanged'], this.onVerticesChanged, this);
const halfSize = Vector.scale(this.size, 0.5); }
const width = this.width - 0.001;
const height = this.height - 0.001; destroy() {
const position = Vector.add(this.position, Vector.scale(halfSize, -1)); super.destroy();
this.vertices = [ this.off(['positionChanged', 'sizeChanged'], this.onVerticesChanged);
position,
Vector.add(position, [width, 0]),
Vector.add(position, [width, height]),
Vector.add(position, [0, height]),
];
});
} }
fromJSON(json) { fromJSON(json) {
@ -41,6 +35,19 @@ export class RectangleShape extends decorate(PolygonShape) {
return this; return this;
} }
onVerticesChanged() {
const halfSize = Vector.scale(this.size, 0.5);
const width = this.width - 0.001;
const height = this.height - 0.001;
const position = Vector.add(this.position, Vector.scale(halfSize, -1));
this.vertices = [
position,
Vector.add(position, [width, 0]),
Vector.add(position, [width, height]),
Vector.add(position, [0, height]),
];
}
toJSON() { toJSON() {
return { return {
...super.toJSON(), ...super.toJSON(),

View File

@ -12,15 +12,11 @@ export class ShapeView extends Renderable {
this.shape = shape; this.shape = shape;
if (shape instanceof PolygonShape) { if (shape instanceof PolygonShape) {
this.redrawPolygonLines(); this.redrawPolygonLines();
shape.on('aabbChanged', () => { shape.on('aabbChanged', this.onPolygonShapeAabbChanged, this);
this.redrawPolygonLines();
});
} }
if (shape instanceof CircleShape) { if (shape instanceof CircleShape) {
this.redrawCircle(); this.redrawCircle();
shape.on('aabbChanged', () => { shape.on('aabbChanged', this.onCircleShapeAabbChanged, this);
this.redrawCircle();
});
} }
if (shape instanceof ShapeList) { if (shape instanceof ShapeList) {
for (const child of shape) { for (const child of shape) {
@ -29,15 +25,36 @@ export class ShapeView extends Renderable {
} }
} }
this.container.position = shape.position; this.container.position = shape.position;
shape.on('positionChanged', () => { shape.on('positionChanged', this.onShapePositionChanged, this);
this.container.position = shape.position; }
})
destroy() {
super.destroy();
if (shape instanceof PolygonShape) {
this.shape.off('aabbChanged', this.onPolygonShapeAabbChanged);
}
if (shape instanceof CircleShape) {
this.shape.off('aabbChanged', this.onCircleShapeAabbChanged);
}
this.shape.off('aabbChanged', this.onShapePositionChanged);
} }
get internal() { get internal() {
return this.container.internal; return this.container.internal;
} }
onPolygonShapeAabbChanged() {
this.redrawPolygonLines();
}
onCircleShapeAabbChanged() {
this.redrawCircle();
}
onShapePositionChanged() {
this.container.position = shape.position;
}
redrawCircle() { redrawCircle() {
const primitives = new Primitives(); const primitives = new Primitives();
primitives.drawCircle( primitives.drawCircle(

View File

@ -30,15 +30,21 @@ export class Shape extends decorate(class {}) {
'originChanged', 'originChanged',
'rotationChanged', 'rotationChanged',
'scaleChanged', 'scaleChanged',
], () => { ], this.onAabbChanged, this);
this.emit('aabbChanged');
});
} }
get aabb() { get aabb() {
return [0, 0, 0, 0]; return [0, 0, 0, 0];
} }
destroy() {
this.off([
'originChanged',
'rotationChanged',
'scaleChanged',
], this.onAabbChanged);
}
fromJSON(json) { fromJSON(json) {
const keys = [ const keys = [
'origin', 'origin',
@ -54,6 +60,10 @@ export class Shape extends decorate(class {}) {
return this; return this;
} }
onAabbChanged() {
this.emit('aabbChanged');
}
toJSON() { toJSON() {
return { return {
origin: this.origin, origin: this.origin,

View File

@ -21,10 +21,11 @@ export class Shaped extends decorate(Trait) {
} }
destroy() { destroy() {
this._shape.destroy();
if (this.shapeView) { if (this.shapeView) {
this.shapeView.destroy(); this.shapeView.destroy();
this.shapeView = undefined;
} }
this.shapeView = undefined;
} }
get shape() { get shape() {