TrackedObjectRef
The TrackedObjectRef interface provides a stable reference to a Three.js object for use in devtools. It contains identification and location information that persists across scene updates.
Overview
typescript
import type { TrackedObjectRef } from '@3lens/core';
// Get a reference for an object
const ref: TrackedObjectRef = probe.getObjectRef(mesh);
console.log(ref.debugId); // "obj_abc123xyz" - stable ID
console.log(ref.threeUuid); // "550e8400-e29b..." - Three.js UUID
console.log(ref.type); // "Mesh"
console.log(ref.name); // "PlayerModel"
console.log(ref.path); // "/Scene/World/Player/PlayerModel"1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Interface Definition
typescript
interface TrackedObjectRef {
/**
* Stable debug ID for the devtool.
* Format: "obj_" + random alphanumeric string
* Example: "obj_abc123xyz"
*/
debugId: string;
/**
* Three.js UUID from object.uuid
* Standard UUID v4 format
*/
threeUuid: string;
/**
* Object type (from object.type or constructor name)
* Examples: "Mesh", "Group", "Scene", "PerspectiveCamera"
*/
type: string;
/**
* Object name (from object.name property)
* Undefined if object has no name set
*/
name?: string;
/**
* Scene path showing object's position in hierarchy
* Format: "/Parent/Child/Object"
*/
path?: string;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Properties
debugId
A stable identifier generated by 3Lens for internal tracking.
typescript
// Generated format
const debugId = 'obj_' + Math.random().toString(36).substring(2, 11);
// Example: "obj_k7m2p9xyz"1
2
3
2
3
Key characteristics:
- Unique within a session
- Stable across scene updates (same object keeps same ID)
- Used for devtools UI references
- Not persisted between page reloads
threeUuid
The UUID from the Three.js object:
typescript
const mesh = new THREE.Mesh(geometry, material);
console.log(mesh.uuid); // "550e8400-e29b-41d4-a716-446655440000"
const ref = observer.getObjectRef(mesh);
console.log(ref.threeUuid === mesh.uuid); // true1
2
3
4
5
2
3
4
5
Note: Three.js UUIDs can change if objects are cloned or recreated.
type
Object type for identification and icon display:
typescript
// Common types
| Type | Object Class |
|------|--------------|
| "Scene" | THREE.Scene |
| "Group" | THREE.Group |
| "Mesh" | THREE.Mesh |
| "SkinnedMesh" | THREE.SkinnedMesh |
| "InstancedMesh" | THREE.InstancedMesh |
| "Line" | THREE.Line, LineSegments |
| "Points" | THREE.Points |
| "Sprite" | THREE.Sprite |
| "PerspectiveCamera" | THREE.PerspectiveCamera |
| "OrthographicCamera" | THREE.OrthographicCamera |
| "DirectionalLight" | THREE.DirectionalLight |
| "PointLight" | THREE.PointLight |
| "SpotLight" | THREE.SpotLight |
| "AmbientLight" | THREE.AmbientLight |
| "HemisphereLight" | THREE.HemisphereLight |
| "RectAreaLight" | THREE.RectAreaLight |
| "Object3D" | THREE.Object3D (base) |
| "Bone" | THREE.Bone |
| "LOD" | THREE.LOD |1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
name
Optional user-defined name:
typescript
const mesh = new THREE.Mesh(geometry, material);
mesh.name = 'PlayerCharacter';
const ref = observer.getObjectRef(mesh);
console.log(ref.name); // "PlayerCharacter"
// Unnamed object
const unnamed = new THREE.Mesh(geometry, material);
const ref2 = observer.getObjectRef(unnamed);
console.log(ref2.name); // undefined1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
path
Hierarchical path in the scene graph:
typescript
// Scene structure:
// Scene
// └── World
// └── Characters
// └── Player
const ref = observer.getObjectRef(player);
console.log(ref.path); // "/Scene/World/Characters/Player"1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
See Scene Path Computation for details.
ID Comparison
| Property | Purpose | Stability | Format |
|---|---|---|---|
debugId | Devtools tracking | Session-stable | obj_* |
threeUuid | Three.js internal | Object lifetime | UUID v4 |
path | Human navigation | Changes with hierarchy | /path/like |
Usage Examples
Finding Objects by Reference
typescript
// Store reference from UI selection
let selectedRef: TrackedObjectRef | null = null;
function onTreeItemClick(ref: TrackedObjectRef) {
selectedRef = ref;
highlightObject(ref.debugId);
}
// Later: find the actual Three.js object
function getSelectedObject(): THREE.Object3D | null {
if (!selectedRef) return null;
return probe.findObjectByDebugId(selectedRef.debugId);
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Building Selection State
typescript
interface SelectionState {
ref: TrackedObjectRef;
object: THREE.Object3D;
boundingBox: THREE.Box3;
}
function selectObject(ref: TrackedObjectRef): SelectionState | null {
const object = probe.findObjectByDebugId(ref.debugId);
if (!object) return null;
const boundingBox = new THREE.Box3().setFromObject(object);
return { ref, object, boundingBox };
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Display Formatting
typescript
function formatObjectLabel(ref: TrackedObjectRef): string {
if (ref.name) {
return `${ref.name} (${ref.type})`;
}
return `<${ref.type}>`;
}
function getObjectIcon(ref: TrackedObjectRef): string {
const iconMap: Record<string, string> = {
'Scene': '🎬',
'Group': '📁',
'Mesh': '🔷',
'SkinnedMesh': '🦴',
'InstancedMesh': '🔶',
'PerspectiveCamera': '📷',
'OrthographicCamera': '📐',
'DirectionalLight': '☀️',
'PointLight': '💡',
'SpotLight': '🔦',
'AmbientLight': '🌤️',
};
return iconMap[ref.type] || '📦';
}
// Usage
const label = formatObjectLabel(ref);
const icon = getObjectIcon(ref);
// Display: "🔷 PlayerModel (Mesh)"1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Comparing References
typescript
function isSameObject(a: TrackedObjectRef, b: TrackedObjectRef): boolean {
// Use debugId for reliable comparison
return a.debugId === b.debugId;
}
function isObjectInList(ref: TrackedObjectRef, list: TrackedObjectRef[]): boolean {
return list.some((item) => item.debugId === ref.debugId);
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Serialization for State Persistence
typescript
// References are plain objects - safe to serialize
const state = {
selectedObjectId: selectedRef?.debugId,
expandedPaths: expandedRefs.map((r) => r.debugId),
};
localStorage.setItem('devtools-state', JSON.stringify(state));
// Restore - note that debugIds are session-specific
// so restoration only works within the same session1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Extended Metadata
For framework integration, use ObjectMeta which extends TrackedObjectRef:
typescript
interface ObjectMeta extends TrackedObjectRef {
/** Module/library ID (for Nx/ngLib support) */
moduleId?: string;
/** Framework component ID (e.g., 'React:HealthBar#123') */
componentId?: string;
/** Logical entity ID if registered */
entityId?: string;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
React Integration Example
typescript
// In React component
useDevtoolEntity({
label: 'HealthBar',
objects: [healthBarMesh],
componentId: 'React:HealthBar#' + componentId,
moduleId: '@myapp/ui',
});
// The object's metadata will include:
// {
// debugId: "obj_abc123",
// threeUuid: "...",
// type: "Mesh",
// name: "HealthBar",
// path: "/Scene/UI/HealthBar",
// componentId: "React:HealthBar#42",
// moduleId: "@myapp/ui"
// }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Related
- SceneObserver - Creates TrackedObjectRef instances
- SceneNode - Contains TrackedObjectRef in
refproperty - Scene Path Computation - How
pathis calculated - Logical Entities - Extended metadata with
ObjectMeta