Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class SimpleOutlinePass extends Pass {
* source meshes, their `attributes`, and their `index` belong to
* fragments and are never mutated here.
*/
private _outlinedTiles = new Map<THREE.Mesh, OutlinedTileProxy>();
private _outlinedTiles = new Map<string, OutlinedTileProxy>();
private _nextId = 1;
private _maxThickness = 2;

Expand Down Expand Up @@ -327,6 +327,11 @@ export class SimpleOutlinePass extends Pass {
if (name === DEFAULT_GROUP) return;
const group = this._groups.get(name);
if (!group) return;
for (const [key, target] of this._outlinedTiles) {
if (target.groupName !== name) continue;
target.proxy.removeFromParent();
this._outlinedTiles.delete(key);
}
while (group.container.children.length) {
group.container.children[0].removeFromParent();
}
Expand Down Expand Up @@ -385,21 +390,13 @@ export class SimpleOutlinePass extends Pass {
let group = this._groups.get(groupName);
if (!group) group = this.addGroup(groupName);

const existing = this._outlinedTiles.get(tile);
const key = this.getOutlinedTileKey(tile, groupName);
const existing = this._outlinedTiles.get(key);
if (existing) {
// Reuse the proxy shell; rebuild geometry groups against the new
// chunks, and re-home it if the group changed.
const proxy = existing.proxy;
const proxyGeom = proxy.geometry;
proxyGeom.clearGroups();
this.fillProxyGroups(proxyGeom, chunks);
if (existing.groupName !== groupName) {
proxy.removeFromParent();
// Material must stay as a single-element array; see comment below.
proxy.material = [group.material];
group.container.add(proxy);
existing.groupName = groupName;
}
return;
}

Expand All @@ -423,7 +420,7 @@ export class SimpleOutlinePass extends Pass {
proxy.matrixWorld.copy(tile.matrixWorld);

group.container.add(proxy);
this._outlinedTiles.set(tile, { source: tile, proxy, groupName });
this._outlinedTiles.set(key, { source: tile, proxy, groupName });
}

/**
Expand All @@ -440,15 +437,31 @@ export class SimpleOutlinePass extends Pass {
* The proxy's tiny BufferGeometry wrapper (just metadata) is left to
* GC. Attributes and index belong to fragments.
*/
detachOutlinedTile(tile: THREE.Mesh) {
const target = this._outlinedTiles.get(tile);
if (!target) return;
target.proxy.removeFromParent();
this._outlinedTiles.delete(tile);
detachOutlinedTile(tile: THREE.Mesh, groupName?: string) {
if (groupName !== undefined) {
const key = this.getOutlinedTileKey(tile, groupName);
const target = this._outlinedTiles.get(key);
if (!target) return;
target.proxy.removeFromParent();
this._outlinedTiles.delete(key);
return;
}

for (const [key, target] of this._outlinedTiles) {
if (target.source !== tile) continue;
target.proxy.removeFromParent();
this._outlinedTiles.delete(key);
}
}

hasOutlinedTile(tile: THREE.Mesh) {
return this._outlinedTiles.has(tile);
hasOutlinedTile(tile: THREE.Mesh, groupName?: string) {
if (groupName !== undefined) {
return this._outlinedTiles.has(this.getOutlinedTileKey(tile, groupName));
}
for (const target of this._outlinedTiles.values()) {
if (target.source === tile) return true;
}
return false;
}

/**
Expand Down Expand Up @@ -626,6 +639,10 @@ export class SimpleOutlinePass extends Pass {
}
}

private getOutlinedTileKey(tile: THREE.Mesh, groupName: string) {
return `${groupName}:${tile.uuid}`;
}

// ---------------------------------------------------------------------------
// Internals
// ---------------------------------------------------------------------------
Expand Down
16 changes: 8 additions & 8 deletions packages/front/src/fragments/Outliner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export class Outliner extends OBC.Component implements OBC.Disposable {
}
}

this.detachAll(group);
this.detachAll(group, name);
this._groups.delete(name);

if (this.world) {
Expand Down Expand Up @@ -311,15 +311,15 @@ export class Outliner extends OBC.Component implements OBC.Disposable {
if (!state) return;
state.map = {};
state.activeStyles.clear();
this.detachAll(state);
this.detachAll(state, group);
if (group === DEFAULT_GROUP) this.cleanPoints();
return;
}

for (const [, state] of this._groups) {
for (const [name, state] of this._groups) {
state.map = {};
state.activeStyles.clear();
this.detachAll(state);
this.detachAll(state, name);
}
this.cleanPoints();
}
Expand Down Expand Up @@ -537,7 +537,7 @@ export class Outliner extends OBC.Component implements OBC.Disposable {
for (const [modelId, prev] of previouslyAttached) {
const next = nextAttached.get(modelId) ?? new Set<THREE.Mesh>();
for (const tile of prev) {
if (!next.has(tile)) pass.detachOutlinedTile(tile);
if (!next.has(tile)) pass.detachOutlinedTile(tile, name);
}
}

Expand All @@ -548,14 +548,14 @@ export class Outliner extends OBC.Component implements OBC.Disposable {
* Detach every proxy this group has attached and clear the tracking
* map. Used by `clean` and `remove`.
*/
private detachAll(state: OutlineGroupState) {
private detachAll(state: OutlineGroupState, group = DEFAULT_GROUP) {
if (!this.world) {
state.attached = new Map();
return;
}
const pass = this.getRenderer().postproduction.outlinePass;
for (const [, tiles] of state.attached) {
for (const tile of tiles) pass.detachOutlinedTile(tile);
for (const tile of tiles) pass.detachOutlinedTile(tile, group);
}
state.attached = new Map();
}
Expand All @@ -576,7 +576,7 @@ export class Outliner extends OBC.Component implements OBC.Disposable {
for (const [groupName, state] of this._groups) {
const localIds = state.map[modelId];
if (localIds && localIds.size > 0) {
void this.updateGroup(groupName);
this.updateGroup(groupName).catch(() => undefined);
}
}
};
Expand Down