Skip to content

Commit

Permalink
568 entity cleanup fix (#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelthatsit authored Apr 9, 2024
1 parent 528cb8a commit a1d7780
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 22 deletions.
8 changes: 4 additions & 4 deletions dist/mr.js

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions src/core/MRApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,22 @@ export class MRApp extends MRElement {
this.maskingSystem = new MaskingSystem();
});

this.addEventListener('new-entity', (event) => {
this.addEventListener('entityadded', (event) => {
for (const system of this.systems) {
system._onNewEntity(event.target);
}
});

document.addEventListener('entityremoved', async (event) => {
for (const system of this.systems) {
system._entityRemoved(event.detail.entity);
}

while (event.detail.entity.object3D.parent) {
event.detail.entity.object3D.removeFromParent();
}
});

// Call `eventUpdate` on all systems if any of the global events are triggered
for (const eventType of GLOBAL_UPDATE_EVENTS) {
document.addEventListener(eventType, (event) => {
Expand Down Expand Up @@ -453,7 +463,7 @@ export class MRApp extends MRElement {
* @description Removing an entity as an object in this MRApp engine's scene.
* @param {MREntity} entity - the entity to be removed.
*/
remove(entity) {
removeEntity(entity) {
this.origin.remove(entity.object3D);
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/MRElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class MRElement extends HTMLElement {
* @description Removing an entity as a sub-object of this entity.
* @param {object} entity - the entity to be removed.
*/
remove(entity) {}
removeEntity(entity) {}

// TODO: find alternative solution. This breaks with the switch to asychronous entity initialization
// /**
Expand Down
20 changes: 10 additions & 10 deletions src/core/MREntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,12 @@ export class MREntity extends MRElement {
if (mrjsUtils.physics.initialized) {
await this.connected();
this.loadAttributes();
this.dispatchEvent(new CustomEvent('new-entity', { bubbles: true }));
this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));
} else {
document.addEventListener('engine-started', async (event) => {
await this.connected();
this.loadAttributes();
this.dispatchEvent(new CustomEvent('new-entity', { bubbles: true }));
this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));
});
}
}
Expand All @@ -423,13 +423,13 @@ export class MREntity extends MRElement {
* @description The disconnectedCallback function that runs whenever this entity component becomes disconnected from something else.
*/
disconnectedCallback() {
while (this.object3D.parent) {
this.object3D.removeFromParent();
}

if (this.physics) {
mrjsUtils.physics.world.removeRigidBody(this.physics.body);
}
document.dispatchEvent(
new CustomEvent('entityremoved', {
detail: {
entity: this,
},
})
);

this.environment = null;
this.observer.disconnect();
Expand Down Expand Up @@ -524,7 +524,7 @@ export class MREntity extends MRElement {
* @description Removing an entity as a sub-object of this entity.
* @param {MREntity} entity - the entity to be removed.
*/
remove(entity) {
removeEntity(entity) {
this.object3D.remove(entity.object3D);
}

Expand Down
20 changes: 20 additions & 0 deletions src/core/MRSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ export class MRSystem {
*/
onNewEntity(entity) {}

/**
* @function
* @description internal function, called when a new entity is added to the scene
* @param {MREntity} entity - the entity being added.
*/
_entityRemoved(entity) {
if (!this.registry.has(entity)) {
return;
}
this.registry.delete(entity);
this.entityRemoved(entity);
}

/**
* @function
* @description Called when a new entity is added to the scene
* @param {MREntity} entity - the entity being added.
*/
entityRemoved(entity) {}

/**
* @function
* @description (async) Called when the entity component is initialized
Expand Down
30 changes: 28 additions & 2 deletions src/core/componentSystems/BoundaryVisibilitySystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MRPanelEntity } from 'mrjs/core/entities/MRPanelEntity';
* @description Observe a target MRDivEntity and make the associated object visible only if it is in visible position in a root MRDivEntity
* @param {MRDivEntity} root - the root object being compared against
* @param {MRDivEntity} target - the target object for which we're determining visiblity.
* @returns {IntersectionObserver} - an observer for tracking visiblity
*/
const observe = (root, target) => {
// TODO: Callback is fired asynchronously so no guaranteed to be called immediately when the
Expand Down Expand Up @@ -37,6 +38,7 @@ const observe = (root, target) => {
}
);
observer.observe(target);
return observer;
};

/**
Expand All @@ -52,6 +54,7 @@ export class BoundaryVisibilitySystem extends MRSystem {
constructor() {
super(false);
this.observedEntities = new WeakSet();
this.observers = new Map();
}

/**
Expand All @@ -73,18 +76,41 @@ export class BoundaryVisibilitySystem extends MRSystem {
}

this.observedEntities.add(child);
observe(entity, child);

this.observers.set(child, observe(entity, child));
});
} else if (!this.observedEntities.has(entity) && entity instanceof MRDivEntity) {
// There is a chance that a child entity is added after parent panel addition.
// Check registered panels and set up the observer if panels are found in parents.
for (const panel of this.registry) {
if (panel.contains(entity)) {
this.observedEntities.add(entity);
observe(panel, entity);
this.observers.set(child, observe(panel, entity));
break;
}
}
}
}

/**
* @function
* @description Called when an entity is removed from the scene.
* @param {object} entity - the entity being added.
*/
_entityRemoved(entity) {
if (entity instanceof MRPanelEntity) {
this.registry.delete(entity);
entity.traverse((child) => {
if (this.observedEntities.has(child)) {
this.observedEntities.delete(child);
this.observers.get(child).unobserve(child);
this.observers.delete(child);
}
});
} else if (this.observedEntities.has(entity)) {
this.observedEntities.delete(entity);
this.observers.get(entity).unobserve(entity);
this.observers.delete(entity);
}
}
}
10 changes: 10 additions & 0 deletions src/core/componentSystems/PhysicsSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@ export class PhysicsSystem extends MRSystem {
}
}

/**
* @function
* @description when an entity is removed, remove and destroy it's physics body
* @param {MREntity} entity - the removed entity
*/
entityRemoved(entity) {
mrjsUtils.physics.world.removeRigidBody(entity.physics.body);
entity.physics.body = null;
}

/**
* @function
* @description Initializes the rigid body used by the physics part of the entity
Expand Down
4 changes: 2 additions & 2 deletions src/core/entities/MRDivEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ export class MRDivEntity extends MREntity {
* @description Removing an entity as a sub-object of this panel (for example an mr-model, button, etc).
* @param {MREntity} entity - the entity to be removed added.
*/
remove(entity) {
removeEntity(entity) {
// `this` must have `mr-panel` as its closest parent entity for threejs to handle positioning appropriately.
let panel = this.closest('mr-panel');
if (panel && entity instanceof MRDivEntity) {
panel.remove(entity);
panel.removeEntity(entity);
} else {
this.object3D.remove(entity.object3D);
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/entities/MRPanelEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class MRPanelEntity extends MRDivEntity {
* @description Remove an entity as a sub-object of this entity.
* @param {MREntity} entity - the entity to be removed.
*/
remove(entity) {
removeEntity(entity) {
this.panel.remove(entity.object3D);
}

Expand Down

0 comments on commit a1d7780

Please sign in to comment.