fix: visibleBoundingBox optimizations
This commit is contained in:
parent
1b35fc4215
commit
570054c610
|
@ -31,8 +31,7 @@ export class Listed extends Trait {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const quadTree = list.quadTree;
|
if (!this.entity.is('visible')) {
|
||||||
if (!('visibleBoundingBox' in this.entity)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const aabb = this.entity.visibleBoundingBox;
|
const aabb = this.entity.visibleBoundingBox;
|
||||||
|
@ -45,6 +44,7 @@ export class Listed extends Trait {
|
||||||
const points = Rectangle.toPoints(expandedAabb);
|
const points = Rectangle.toPoints(expandedAabb);
|
||||||
this.quadTreeNodes = points.map((point) => [...point, this.entity]);
|
this.quadTreeNodes = points.map((point) => [...point, this.entity]);
|
||||||
// Add points to quad tree.
|
// Add points to quad tree.
|
||||||
|
const quadTree = list.quadTree;
|
||||||
for (const node of this.quadTreeNodes) {
|
for (const node of this.quadTreeNodes) {
|
||||||
quadTree.add(node);
|
quadTree.add(node);
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,7 @@ export class Listed extends Trait {
|
||||||
listeners() {
|
listeners() {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
visibleBoundingBoxesUpdated: () => {
|
visibleBoundingBoxChanged: () => {
|
||||||
this.resetQuadTreeNodes();
|
|
||||||
},
|
|
||||||
|
|
||||||
positionChanged: () => {
|
|
||||||
this.resetQuadTreeNodes();
|
this.resetQuadTreeNodes();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ const decorate = compose(
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
class PicturedBase extends Trait {
|
export class Pictured extends decorate(Trait) {
|
||||||
|
|
||||||
static defaultParams() {
|
static defaultParams() {
|
||||||
return {
|
return {
|
||||||
|
@ -28,8 +28,6 @@ class PicturedBase extends Trait {
|
||||||
initialize() {
|
initialize() {
|
||||||
this._images = this.params.get('images').toJS();
|
this._images = this.params.get('images').toJS();
|
||||||
this.sprites = undefined;
|
this.sprites = undefined;
|
||||||
// Bounding box update.
|
|
||||||
this.entity.emit('visibleBoundingBoxesUpdated');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -61,10 +59,11 @@ class PicturedBase extends Trait {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Load all images.
|
// Load all images.
|
||||||
|
const imagePromises = [];
|
||||||
this.sprites = {};
|
this.sprites = {};
|
||||||
for (const key in this._images) {
|
for (const key in this._images) {
|
||||||
const {uri} = this._images[key];
|
const {uri} = this._images[key];
|
||||||
Image.load(uri).then((image) => {
|
const imagePromise = Image.load(uri).then((image) => {
|
||||||
const sprite = this.sprites[key] = new Sprite(image);
|
const sprite = this.sprites[key] = new Sprite(image);
|
||||||
// Calculate any offset.
|
// Calculate any offset.
|
||||||
sprite.position = this.viewPositionFor(key);
|
sprite.position = this.viewPositionFor(key);
|
||||||
|
@ -74,7 +73,12 @@ class PicturedBase extends Trait {
|
||||||
this.showImage(key);
|
this.showImage(key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
imagePromises.push(imagePromise);
|
||||||
}
|
}
|
||||||
|
Promise.all(imagePromises).then((images) => {
|
||||||
|
// Bounding box update.
|
||||||
|
this.entity.updateVisibleBoundingBox();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetFor(key) {
|
offsetFor(key) {
|
||||||
|
@ -133,7 +137,7 @@ class PicturedBase extends Trait {
|
||||||
return {
|
return {
|
||||||
currentImageChanged: (oldKey) => {
|
currentImageChanged: (oldKey) => {
|
||||||
// Bounding box update.
|
// Bounding box update.
|
||||||
this.entity.emit('visibleBoundingBoxesUpdated');
|
this.entity.updateVisibleBoundingBox();
|
||||||
// Only client/graphics.
|
// Only client/graphics.
|
||||||
if (!this.sprites) {
|
if (!this.sprites) {
|
||||||
return;
|
return;
|
||||||
|
@ -155,5 +159,3 @@ class PicturedBase extends Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Pictured extends decorate(PicturedBase) {}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {compose} from '@avocado/core';
|
import {compose} from '@avocado/core';
|
||||||
import {StateProperty, Trait} from '@avocado/entity';
|
import {StateProperty, Trait} from '@avocado/entity';
|
||||||
import {Rectangle, Vector} from '@avocado/math';
|
import {Rectangle, Vector} from '@avocado/math';
|
||||||
|
import {Property} from '@avocado/mixins';
|
||||||
|
|
||||||
import {Container} from '../container';
|
import {Container} from '../container';
|
||||||
import {hasGraphics} from '../has-graphics';
|
import {hasGraphics} from '../has-graphics';
|
||||||
|
@ -9,6 +10,13 @@ const decorate = compose(
|
||||||
StateProperty('isVisible', {
|
StateProperty('isVisible', {
|
||||||
track: true,
|
track: true,
|
||||||
}),
|
}),
|
||||||
|
Property('visibleBoundingBox', {
|
||||||
|
default: [0, 0, 0, 0],
|
||||||
|
emit: function (...args) {
|
||||||
|
this.entity.emit(...args);
|
||||||
|
},
|
||||||
|
track: true,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export class Visible extends decorate(Trait) {
|
export class Visible extends decorate(Trait) {
|
||||||
|
@ -30,8 +38,8 @@ export class Visible extends decorate(Trait) {
|
||||||
this._container = new Container();
|
this._container = new Container();
|
||||||
this._container.isVisible = this.entity.isVisible;
|
this._container.isVisible = this.entity.isVisible;
|
||||||
}
|
}
|
||||||
|
this.scheduledBoundingBoxUpdate = true;
|
||||||
this.trackPosition = this.params.get('trackPosition');
|
this.trackPosition = this.params.get('trackPosition');
|
||||||
this._visibleBoundingBox = [0, 0, 0, 0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -44,27 +52,6 @@ export class Visible extends decorate(Trait) {
|
||||||
return this._container;
|
return this._container;
|
||||||
}
|
}
|
||||||
|
|
||||||
get visibleBoundingBox() {
|
|
||||||
if (Rectangle.isNull(this._visibleBoundingBox)) {
|
|
||||||
// Collect all bounding boxes.
|
|
||||||
const visibleBoundingBoxes = this.entity.invokeHookFlat(
|
|
||||||
'visibleBoundingBoxes'
|
|
||||||
);
|
|
||||||
if (0 === visibleBoundingBoxes.length) {
|
|
||||||
return [0, 0, 0, 0];
|
|
||||||
}
|
|
||||||
let unifiedBoundingBox = [0, 0, 0, 0];
|
|
||||||
for (const visibleBoundingBox of visibleBoundingBoxes) {
|
|
||||||
unifiedBoundingBox = Rectangle.united(
|
|
||||||
unifiedBoundingBox,
|
|
||||||
visibleBoundingBox,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this._visibleBoundingBox = unifiedBoundingBox;
|
|
||||||
}
|
|
||||||
return this._visibleBoundingBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldSynchronizePosition() {
|
shouldSynchronizePosition() {
|
||||||
return this._container && this.trackPosition;
|
return this._container && this.trackPosition;
|
||||||
}
|
}
|
||||||
|
@ -84,9 +71,9 @@ export class Visible extends decorate(Trait) {
|
||||||
this.entity.container.visible = this.entity.isVisible;
|
this.entity.container.visible = this.entity.isVisible;
|
||||||
},
|
},
|
||||||
|
|
||||||
visibleBoundingBoxesUpdated: () => {
|
positionChanged: () => {
|
||||||
this._visibleBoundingBox = [0, 0, 0, 0];
|
this.scheduledBoundingBoxUpdate = true;
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
if (this.shouldSynchronizePosition()) {
|
if (this.shouldSynchronizePosition()) {
|
||||||
|
@ -103,10 +90,40 @@ export class Visible extends decorate(Trait) {
|
||||||
return listeners;
|
return listeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
methods() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
updateVisibleBoundingBox: () => {
|
||||||
|
this.scheduledBoundingBoxUpdate = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
if (this.shouldSynchronizePosition()) {
|
if (this.shouldSynchronizePosition()) {
|
||||||
this.synchronizePosition();
|
this.synchronizePosition();
|
||||||
}
|
}
|
||||||
|
if (this.scheduledBoundingBoxUpdate) {
|
||||||
|
// Collect all bounding boxes.
|
||||||
|
const visibleBoundingBoxes = this.entity.invokeHookFlat(
|
||||||
|
'visibleBoundingBoxes'
|
||||||
|
);
|
||||||
|
if (0 === visibleBoundingBoxes.length) {
|
||||||
|
this.visibleBoundingBox = [0, 0, 0, 0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let unifiedBoundingBox = [0, 0, 0, 0];
|
||||||
|
for (const visibleBoundingBox of visibleBoundingBoxes) {
|
||||||
|
unifiedBoundingBox = Rectangle.united(
|
||||||
|
unifiedBoundingBox,
|
||||||
|
visibleBoundingBox,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.visibleBoundingBox = unifiedBoundingBox;
|
||||||
|
this.scheduledBoundingBoxUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class AnimatedBase extends Trait {
|
||||||
animation.direction = this.entity.direction;
|
animation.direction = this.entity.direction;
|
||||||
});
|
});
|
||||||
// Bounding box update.
|
// Bounding box update.
|
||||||
this.entity.emit('visibleBoundingBoxesUpdated');
|
this.entity.updateVisibleBoundingBox();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ class AnimatedBase extends Trait {
|
||||||
oldAnimation.reset();
|
oldAnimation.reset();
|
||||||
}
|
}
|
||||||
// Bounding box update.
|
// Bounding box update.
|
||||||
this.entity.emit('visibleBoundingBoxesUpdated');
|
this.entity.updateVisibleBoundingBox();
|
||||||
// Only client/graphics.
|
// Only client/graphics.
|
||||||
if (!this.animationViews) {
|
if (!this.animationViews) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user