diff --git a/packages/outline/src/OutlineManager.ts b/packages/outline/src/OutlineManager.ts index a736af51..51045d1f 100644 --- a/packages/outline/src/OutlineManager.ts +++ b/packages/outline/src/OutlineManager.ts @@ -7,6 +7,7 @@ import { dependentComponents, Entity, Material, + Matrix, MeshRenderer, PrimitiveMesh, RenderTarget, @@ -41,6 +42,10 @@ export class OutlineManager extends Script { private _replaceColor: Color = new Color(1, 0, 0, 1); private _outlineEntities: Entity[] = []; + private _entityMap: Array<{ entity: Entity; parent: Entity; worldMatrix: Matrix }> = []; + private _materialMap: Array<{ renderer: MeshRenderer; material: Material }> = []; + private _renderers: MeshRenderer[] = []; + /** outline color. */ get color(): Color { return this._material.shaderData.getColor(OutlineManager._outlineColorProp); @@ -114,7 +119,9 @@ export class OutlineManager extends Script { * @param entity - The entity you wanna add. */ addEntity(entity: Entity) { - this._outlineEntities.push(entity); + if (this._outlineEntities.indexOf(entity) === -1) { + this._outlineEntities.push(entity); + } } /** @internal */ @@ -126,19 +133,32 @@ export class OutlineManager extends Script { const originalSolidColor = scene.background.solidColor; const originalBackgroundMode = scene.background.mode; const originalScene = this.engine.sceneManager.activeScene; - const parentMap = new Map(); - const materialMap = new Map(); + + const renderers = this._renderers; + const materialMap = this._materialMap; + const entityMap = this._entityMap; + materialMap.length = 0; + entityMap.length = 0; for (let i = 0, length = this._outlineEntities.length; i < length; i++) { const entity = this._outlineEntities[i]; - const renderers: MeshRenderer[] = []; - entity.getComponentsIncludeChildren(MeshRenderer, renderers); - parentMap.set(entity, entity.parent); + const originalWorldMatrix = entity.transform.worldMatrix.clone(); + const originalParent = entity.parent; + this._outlineRoot.addChild(entity); + entity.transform.worldMatrix = originalWorldMatrix; + + entityMap.push({ + entity, + parent: originalParent, + worldMatrix: originalWorldMatrix + }); + renderers.length = 0; + entity.getComponentsIncludeChildren(MeshRenderer, renderers); for (let j = 0; j < renderers.length; j++) { const renderer = renderers[j]; - materialMap.set(renderer, renderer.getMaterial()); + materialMap.push({ renderer, material: renderer.getMaterial() }); renderer.setMaterial(this._replaceMaterial); } } @@ -165,24 +185,27 @@ export class OutlineManager extends Script { scene.background.solidColor = originalSolidColor; scene.background.mode = originalBackgroundMode; - parentMap.forEach((parent, entity) => { + entityMap.forEach(({ entity, parent, worldMatrix }) => { if (!parent) { scene.addRootEntity(entity); } else { parent.addChild(entity); } + entity.transform.worldMatrix = worldMatrix; }); - materialMap.forEach((material, renderer) => { + materialMap.forEach(({ material, renderer }) => { renderer.setMaterial(material); }); } /** @internal */ onDestroy() { - this._outlineRoot.destroy(); - this._screenEntity.destroy(); + this._outlineScene.destroy(); this._renderTarget.getColorTexture().destroy(true); this._renderTarget.destroy(); + this._renderers = null; + this._entityMap = null; + this._materialMap = null; } }