Skip to content

feat(scene): make removeFromScene symetric with addToScene#337

Draft
RaananW wants to merge 12 commits into
masterfrom
raananw-symmetric-remove-from-scene
Draft

feat(scene): make removeFromScene symetric with addToScene#337
RaananW wants to merge 12 commits into
masterfrom
raananw-symmetric-remove-from-scene

Conversation

@RaananW

@RaananW RaananW commented Jun 29, 2026

Copy link
Copy Markdown
Member

Addresses the forum request: Make removeFromScene symmetric with addToScene.

Problem

addToScene accepts Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer, but removeFromScene only accepted a single Mesh. So an app could add a light/camera/loaded glTF AssetContainer but had no public, symmetric way to remove it — and loading then unloading a GLB leaked.

Changes

  • removeFromScene now accepts the same union as addToScene and dispatches by entity shape. The original mesh-removal logic is preserved verbatim as an internal helper.
  • AssetContainer removal undoes the add field-by-field: recurses entities, clears scene.camera if the container set it, unregisters animationGroups, and splices the per-container _beforeRender hook.
  • Leak fix: addToScene(scene, container) pushed an anonymous _beforeRender closure that was never removable. It is now stored as an @internal AssetContainer._beforeRenderHook so removal can splice it back out.
  • Light / camera / shadow-generator removal paths added. Removing a light also removes its attached shadow generator; shadow generators dispose their frame-graph task.
  • Idempotent — every path is safe to call more than once. Sub-trees unwind via child recursion.
  • Updated docs/lite/architecture/01-scene.md and added tests/lite/unit/remove-from-scene.test.ts.

Validation

  • pnpm build:lib clean; new unit test green.
  • pnpm test:bundle-size — all 205 ceilings pass (+~0.8 KB only on scenes that import removeFromScene; no ceiling changes).
  • pnpm test:parity — 418 pass. The 2 borderline failures (scene116, scene144 at MAD 0.0700043 vs 0.07) also fail on clean master and touch no removal code — pre-existing and unrelated.
  • Regenerated per-scene bundle manifests committed.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

removeFromScene now accepts the same union as addToScene
(Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer),
dispatching by shape. Removing an AssetContainer undoes the add: recurses
entities, clears the scene camera if it set it, unregisters animation groups,
and splices the per-container before-render hook (previously leaked). Lights,
cameras and shadow generators each get a removal path; all are idempotent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 29, 2026 15:09
@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

Potentially breaking changes detected. Removed or changed public API lines:

  • export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 873e78f3..10f9b03e 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4160,7 +4160,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes removeFromScene symmetric with addToScene by expanding it from “mesh-only removal” into a dispatcher that can remove lights, cameras, shadow generators, transform-node subtrees, and whole AssetContainers (including undoing addToScene(container)’s scene-side effects).

Changes:

  • Expand removeFromScene to accept the same union as addToScene and add removal logic for non-mesh entities and AssetContainer.
  • Fix addToScene(scene, container) to store the animation-group _beforeRender hook on the container so it can be removed later.
  • Add docs + unit test and regenerate per-scene bundle manifests.

Reviewed changes

Copilot reviewed 49 out of 49 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/lite/unit/remove-from-scene.test.ts Adds unit coverage for symmetry/idempotence scenarios (needs updates to match real shadow-generator shape).
packages/babylon-lite/src/scene/scene-remove.ts Implements multi-entity removeFromScene dispatch and AssetContainer removal logic (has issues around shadow-task disposal + parent detachment).
packages/babylon-lite/src/scene/scene-core.ts Stores the per-container _beforeRender hook so it can be removed during container unload.
packages/babylon-lite/src/asset-container.ts Adds @internal _beforeRenderHook field to enable symmetric add/remove.
docs/lite/architecture/01-scene.md Updates public API signatures to include Camera and documents removeFromScene.
lab/public/bundle/manifest/scene88.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene86.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene79.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene75.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene72.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene71.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene7.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene59.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene52.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene48.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene46.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene43.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene4.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene33.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene254.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene253.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene252.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene251.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene246.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene245.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene244.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene240.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene224.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene223.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene216.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene201.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene20.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene2.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene19.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene177.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene176.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene173.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene172.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene158.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene157.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene151.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene148.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene147.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene140.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene129.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene110.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene106.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene104.json Bundle manifest regen for updated runtime output.
lab/public/bundle/manifest/scene100.json Bundle manifest regen for updated runtime output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/babylon-lite/src/scene/scene-remove.ts Outdated
Comment thread packages/babylon-lite/src/scene/scene-remove.ts Outdated
Comment thread packages/babylon-lite/src/scene/scene-remove.ts Outdated
Comment thread tests/lite/unit/remove-from-scene.test.ts Outdated
@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 46 — Physics Constraints
scene46
55 KB 54 KB +1 KB
Scene 52 — HUD on 3D
scene52
58 KB 57 KB +1 KB
Scene 88 — NME LoopBlock
scene88
61 KB 60 KB +1 KB
Scene 106 — Prestep × Motion Types
scene106
52 KB 51 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 140 — NME PCF Alpha Discard Shadows
scene140
90 KB 89 KB +1 KB
Scene 151 — Manual Transform Animation
scene151
56 KB 55 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 251 — Animation Mask (Xbot walk, frozen legs)
scene251
90 KB 89 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

The API-report breaking-change gate diffs the generated api.md textually and
only recognized type-alias union widening and trailing-optional-parameter
additions as non-breaking. Widening a function PARAMETER's type to a union
superset that still includes the original type (e.g. removeFromScene's
'mesh: Mesh' -> 'entity: Mesh | LightBase | Camera | ...') is also
backward-compatible — existing callers still type-check — but was flagged as
breaking by default.

Add isNonBreakingParameterWidening, mirroring isNonBreakingUnionWidening: a
signature whose only change is one or more parameters widening to a union
superset (every prior top-level member still accepted) is additive. A genuine
type replacement (string -> Color3) or a dropped member stays breaking, and a
pure rename without widening stays breaking.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 873e78f3..10f9b03e 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4160,7 +4160,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

@sebavan sebavan changed the title feat(scene): make removeFromScene symmetric with addToScene feat(scene): make removeFromScene symetric with addToScene Jun 29, 2026

@sebavan sebavan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do without touching sizes ?

@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 46 — Physics Constraints
scene46
55 KB 54 KB +1 KB
Scene 52 — HUD on 3D
scene52
58 KB 57 KB +1 KB
Scene 88 — NME LoopBlock
scene88
61 KB 60 KB +1 KB
Scene 106 — Prestep × Motion Types
scene106
52 KB 51 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 140 — NME PCF Alpha Discard Shadows
scene140
90 KB 89 KB +1 KB
Scene 151 — Manual Transform Animation
scene151
56 KB 55 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 251 — Animation Mask (Xbot walk, frozen legs)
scene251
90 KB 89 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260629.9 - merge @ 317e265

- Dispose the shadow generator's render task at sg._shadowTaskState._task
  (not a non-existent sg._task) and null the state so removal is idempotent.
- Detach light/camera/scene-node parent links on removal so the push-based
  world-matrix child registry stops retaining/walking removed nodes (mirrors
  the mesh.parent = null already done for meshes).
- Strengthen the unit test to stub the real _shadowTaskState._task shape,
  assert the task is disposed exactly once, and assert parent detachment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 873e78f3..10f9b03e 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4160,7 +4160,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

@ryantrem

Copy link
Copy Markdown
Member

can we do without touching sizes ?

I was thinking about this as well. Right now, we basically have fixed code in scene-core.ts to deal with each entity type for add/remove. That means any time we add a new entity type, the code grows, even if you don't use that entity type. I wonder if a more "centralized dispatch" mechanism could make code smaller, where scene core would "dispatch" the add/remove operation to a callback per entity type, where the entity type itself is responsible for registering the dispatcher. Something like the first time an AssetContainer is constructed, statically register the dispatcher for what operation should be done for add/remove to/from scene. Something like that would not grow the bundle size with more entites added (or more functions like add/remove that need to operation on every entity type), but I'm not sure if the "centralized dispatch" code itself would be bigger than the current per-entity handling.

@bjsplat

bjsplat commented Jun 29, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 46 — Physics Constraints
scene46
55 KB 54 KB +1 KB
Scene 52 — HUD on 3D
scene52
58 KB 57 KB +1 KB
Scene 88 — NME LoopBlock
scene88
61 KB 60 KB +1 KB
Scene 106 — Prestep × Motion Types
scene106
52 KB 51 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 140 — NME PCF Alpha Discard Shadows
scene140
90 KB 89 KB +1 KB
Scene 151 — Manual Transform Animation
scene151
56 KB 55 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 251 — Animation Mask (Xbot walk, frozen legs)
scene251
90 KB 89 KB +1 KB

Decreases

Package Current Master Change
Scene 176 - MosquitoInAmber
scene176
58 KB 103 KB -45 KB
Scene 179 - Clustered Sponza Lights
scene179
46 KB 73 KB -27 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

RaananW and others added 2 commits July 1, 2026 15:24
…emove-from-scene

# Conflicts:
#	lab/public/bundle/manifest/scene104.json
#	lab/public/bundle/manifest/scene129.json
#	lab/public/bundle/manifest/scene147.json
#	lab/public/bundle/manifest/scene148.json
#	lab/public/bundle/manifest/scene151.json
#	lab/public/bundle/manifest/scene158.json
#	lab/public/bundle/manifest/scene176.json
#	lab/public/bundle/manifest/scene2.json
#	lab/public/bundle/manifest/scene223.json
#	lab/public/bundle/manifest/scene240.json
#	lab/public/bundle/manifest/scene244.json
#	lab/public/bundle/manifest/scene245.json
#	lab/public/bundle/manifest/scene246.json
#	lab/public/bundle/manifest/scene251.json
#	lab/public/bundle/manifest/scene253.json
#	lab/public/bundle/manifest/scene254.json
#	lab/public/bundle/manifest/scene33.json
#	lab/public/bundle/manifest/scene7.json
Rebuild bundle-scene manifests so committed sizes reflect the merged code.
All 205 bundle-size ceilings pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

…flaky scene14/scene9)

The merge-time manifest regeneration only introduced sub-1KB measurement
jitter (identical content-hashed chunks) plus a flaky scene14 collapse
(11MB remote GLB not finishing before readiness) and a scene9 collapse.
Since this change alters no bundle composition, restore all per-scene
manifests to master's stable values.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 105 — Character Controller + Moving Platform
scene105
103 KB 102 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
49 KB 48 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

… each)

scene129 and scene173 are the only measured scenes that call
removeFromScene, so the expanded dispatch logic legitimately ships in
their (non-content-hashed) entry chunks: scene129 82.9->83.9KB,
scene173 62.1->63.1KB. Verified reproducible across rebuilds; chunk
composition unchanged (4 chunks each). Other scenes keep master values
because the only other added code is a single addToScene assignment
(<0.1KB, below manifest rounding).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

1 similar comment
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

Deduplicate the repeated indexOf/splice bookkeeping into a spliceOut
helper, fold shadow-generator disposal into a shared
disposeShadowGenerator, and share the detach-parent + unwind-children
tail across the light/camera/shadow/node paths instead of repeating it
per branch. Behaviour and idempotency are unchanged (unit tests green);
scene129 83.9->83.7KB, scene173 63.1->62.9KB.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 105 — Character Controller + Moving Platform
scene105
103 KB 102 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
49 KB 48 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

CI's fresh rebuild flagged 5 stale per-scene manifests. Investigation shows
two distinct causes:

- scene223 (+0.8KB raw, 64.0->64.8): REAL growth from this PR. scene223 uses
  gizmos, which import removeFromScene to clean up their meshes; the symmetric
  removeFromScene rewrite is larger and drags in disposeMeshGpu/shadow helpers
  that gizmo-only scenes didn't previously bundle.

- scene105/157/227/45 (+0.1KB raw each): pre-existing master drift, NOT caused
  by this PR. A fresh build from master source already produces these values;
  the committed manifests were simply never regenerated after earlier library
  commits (same maintenance gap as the stale demos-manifest). The merge from
  master surfaced them via the full rebuild.

All five values reproduce CI's fresh rebuild exactly. Committing them is
required for validate-bundle-manifest to pass.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@RaananW RaananW force-pushed the raananw-symmetric-remove-from-scene branch from 4feb625 to 5f704e4 Compare July 1, 2026 16:10
@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 105 — Character Controller + Moving Platform
scene105
103 KB 102 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
49 KB 48 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index e51fe551..743280fd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 105 — Character Controller + Moving Platform
scene105
103 KB 102 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
49 KB 48 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 1, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260701.22 - merge @ a208b32

@RaananW RaananW enabled auto-merge (squash) July 2, 2026 08:54
RaananW and others added 2 commits July 2, 2026 10:56
…emove-from-scene

# Conflicts:
#	lab/public/bundle/manifest/scene129.json
Master's manifest regen (#) rebaselined all scenes with the smaller master
removeFromScene. Re-measuring the 9 scenes that bundle removeFromScene (direct
callers + gizmo scenes) on the merged tree shows 3 need the symmetric-rewrite
delta reapplied on top of the new baseline:
  scene129: 83.7 -> 83.8 raw
  scene47:  36.8 -> 36.9 gzip
  scene49:  35.0 -> 35.1 gzip

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bjsplat

bjsplat commented Jul 2, 2026

Copy link
Copy Markdown

API Changes

API Extractor detected public API changes for @babylonjs/lite.

No removed public API lines were detected; this appears to be additive.

API Extractor diff
diff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index b97f112d..244054de 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -4194,7 +4194,7 @@ export function removeBillboardSprite(handle: BillboardSpriteHandle): void;
 export function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void;
 
 // @public
-export function removeFromScene(scene: SceneContext, mesh: Mesh): void;
+export function removeFromScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void;
 
 // @public
 export function removeHierarchyInstance(pool: HierarchyInstancePool, index: number): void;

@bjsplat

bjsplat commented Jul 2, 2026

Copy link
Copy Markdown

Bundle Size Changes

Increases

Package Current Master Change
Scene 105 — Character Controller + Moving Platform
scene105
103 KB 102 KB +1 KB
Scene 129 — Gaussian Splatting GPU Picking
scene129
84 KB 83 KB +1 KB
Scene 157 — glTF Weighted Animation Blend
scene157
96 KB 95 KB +1 KB
Scene 173 - Navigation Dynamic Obstacles
scene173
63 KB 62 KB +1 KB
Scene 223 — Camera + Light Gizmos
scene223
65 KB 64 KB +1 KB
Scene 227 — Multi-Canvas (Same Scene)
scene227
49 KB 48 KB +1 KB

Sizes rounded to nearest KB. Run pnpm build:bundle-scenes locally to verify.

@bjsplat

bjsplat commented Jul 2, 2026

Copy link
Copy Markdown

Lab - Static Site

Open deployed site

Build 20260702.3 - merge @ e6585ab

@RaananW

RaananW commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

can we do without touching sizes ?

Was partly discussed. No, we can't but this is not functionality that will influence time to first frame. this is functionality that can be deferred. the average increase is 0.8kb (0.2 gzipped). I am not too happy about adding size as well.

@sebavan

sebavan commented Jul 2, 2026

Copy link
Copy Markdown
Member

Should we always defer it ?

@RaananW

RaananW commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

Should we always defer it ?

Won't help if we are measuring the way we do. not until we measure time-to-first-frame. I would prefer not to do that. We can cancel this PR if you feel like this is not the right approach

@ryantrem

ryantrem commented Jul 2, 2026

Copy link
Copy Markdown
Member

can we do without touching sizes ?

I was thinking about this as well. Right now, we basically have fixed code in scene-core.ts to deal with each entity type for add/remove. That means any time we add a new entity type, the code grows, even if you don't use that entity type. I wonder if a more "centralized dispatch" mechanism could make code smaller, where scene core would "dispatch" the add/remove operation to a callback per entity type, where the entity type itself is responsible for registering the dispatcher. Something like the first time an AssetContainer is constructed, statically register the dispatcher for what operation should be done for add/remove to/from scene. Something like that would not grow the bundle size with more entites added (or more functions like add/remove that need to operation on every entity type), but I'm not sure if the "centralized dispatch" code itself would be bigger than the current per-entity handling.

Are we confirmed an approach like this won't help?

@RaananW

RaananW commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

can we do without touching sizes ?

I was thinking about this as well. Right now, we basically have fixed code in scene-core.ts to deal with each entity type for add/remove. That means any time we add a new entity type, the code grows, even if you don't use that entity type. I wonder if a more "centralized dispatch" mechanism could make code smaller, where scene core would "dispatch" the add/remove operation to a callback per entity type, where the entity type itself is responsible for registering the dispatcher. Something like the first time an AssetContainer is constructed, statically register the dispatcher for what operation should be done for add/remove to/from scene. Something like that would not grow the bundle size with more entites added (or more functions like add/remove that need to operation on every entity type), but I'm not sure if the "centralized dispatch" code itself would be bigger than the current per-entity handling.

Are we confirmed an approach like this won't help?

I researched a bit (without implementing to be honest). it seems like the overhead of chunking the code will be bigger than the actual saving we have per entity. There are 5-6 lines of code per entity (excluding mesh, which is already there). I also can't see how we can implement this cleanly without making some function async, or, as i understand you suggest, asking the user to register what entities they might remove from the scene. It feels to me like a very cumbersome solution and a pain to the users. On the other hand, the functionality doesn't exist yet, so everything is possible.
Want me to try and implement this aproach?

@RaananW RaananW marked this pull request as draft July 2, 2026 19:44
auto-merge was automatically disabled July 2, 2026 19:44

Pull request was converted to draft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants