From 2a4e27e261b48fc5d8060e7aa733713970c4e388 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Tue, 7 Apr 2026 03:22:58 -0700 Subject: [PATCH] Added new DevTools (#30870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Chris Smoak Co-authored-by: Jasiel Guillén Co-authored-by: Claude Opus 4.6 (1M context) --- devtools/README.md | 98 +++++ devtools/background.js | 185 +++++++++ devtools/bridge.js | 630 +++++++++++++++++++++++++++++++ devtools/constants.js | 22 ++ devtools/content-script.js | 80 ++++ devtools/devtools.js | 13 + devtools/highlight.js | 194 ++++++++++ devtools/icons/128-dark.png | Bin 0 -> 4770 bytes devtools/icons/128-light.png | Bin 0 -> 4789 bytes devtools/index.html | 9 + devtools/manifest.json | 32 ++ devtools/panel/panel.css | 200 ++++++++++ devtools/panel/panel.html | 13 + devtools/panel/panel.js | 712 +++++++++++++++++++++++++++++++++++ devtools/screenshot.png | Bin 0 -> 867738 bytes 15 files changed, 2188 insertions(+) create mode 100644 devtools/README.md create mode 100644 devtools/background.js create mode 100644 devtools/bridge.js create mode 100644 devtools/constants.js create mode 100644 devtools/content-script.js create mode 100644 devtools/devtools.js create mode 100644 devtools/highlight.js create mode 100644 devtools/icons/128-dark.png create mode 100644 devtools/icons/128-light.png create mode 100644 devtools/index.html create mode 100644 devtools/manifest.json create mode 100644 devtools/panel/panel.css create mode 100644 devtools/panel/panel.html create mode 100644 devtools/panel/panel.js create mode 100644 devtools/screenshot.png diff --git a/devtools/README.md b/devtools/README.md new file mode 100644 index 00000000000000..e91db5a46e2d22 --- /dev/null +++ b/devtools/README.md @@ -0,0 +1,98 @@ +# Three.js DevTools Extension + +This Chrome DevTools extension provides debugging capabilities for Three.js applications. It allows you to inspect scenes, objects, materials, and renderers. + +## Installation + +1. **Development Mode**: + - Open Chrome and navigate to `chrome://extensions/` + - Enable "Developer mode" (toggle in the top-right corner) + - Click "Load unpacked" and select the `devtools` directory + - The extension will now be available in Chrome DevTools when inspecting pages that use Three.js + +2. **Usage**: + - Open Chrome DevTools on a page using Three.js (F12 or Right-click > Inspect) + - Click on the "Three.js" tab in DevTools + - The panel will automatically detect and display Three.js scenes and renderers found on the page. + +## Code Flow Overview + +### Extension Architecture + +The extension follows a standard Chrome DevTools extension architecture: + +1. **Background Script** (`background.js`): Manages the extension lifecycle and communication ports between the panel and content script. +2. **DevTools Script** (`devtools.js`): Creates the panel when the DevTools window opens. +3. **Panel UI** (`panel/panel.html`, `panel/panel.js`, `panel/panel.css`): The DevTools panel interface that displays the data. +4. **Content Script** (`content-script.js`): Injected into the web page. Relays messages between the background script and the bridge script. +5. **Bridge Script** (`bridge.js`): Injected into the page's main world via the manifest. Directly interacts with the Three.js instance, detects objects, gathers data, and communicates back via the content script. + +### Initialization Flow + +1. When a page loads, Chrome injects `bridge.js` into the page's main world (including iframes). +2. `bridge.js` creates the `window.__THREE_DEVTOOLS__` global object. +3. When the DevTools panel is opened, `panel.js` connects to `background.js` (`init`) and immediately requests the current state (`request-state`). +4. `background.js` relays the state request to `content-script.js`, which posts it to `bridge.js`. +5. `bridge.js` responds by sending back observed renderer data (`renderer` message) and batched scene data (`scene` message). +6. Three.js detects `window.__THREE_DEVTOOLS__` and sends registration/observation events to the bridge script as objects are created or the library initializes. + +### Bridge Operation (`bridge.js`) + +The bridge acts as the communication layer between the Three.js instance on the page and the DevTools panel: + +1. **Event Management**: Creates a custom event target (`DevToolsEventTarget`) to manage communication readiness and backlog events before the panel connects. +2. **Object Tracking**: + - `getObjectData()`: Extracts essential data (UUID, type, name, parent, children, etc.) from Three.js objects. + - Maintains a local map (`devTools.objects`) of all observed objects. + +3. **Initial Observation & Batching**: + - When Three.js sends an `observe` event (via `window.__THREE_DEVTOOLS__.dispatchEvent`): + - If it's a renderer, its data is collected and sent immediately via a `'renderer'` message. + - If it's a scene, the bridge traverses the entire scene graph, collects data for the scene and all descendants, stores them locally, and sends them to the panel in a single `'scene'` batch message. + +4. **State Request Handling**: + - When the panel sends `request-state` (on load/reload), the bridge iterates its known objects and sends back the current renderer data (`'renderer'`) and scene data (`'scene'` batch). + +5. **Message Handling**: + - Listens for messages from the panel (relayed via content script) like `request-state`. + +### Panel Interface (`panel/`) + +The panel UI provides the visual representation of the Three.js objects: + +1. **Tree View**: Displays hierarchical representation of scenes and objects. +2. **Renderer Details**: Shows properties and statistics for renderers in a collapsible section. + +## Key Features + +- **Scene Hierarchy Visualization**: Browse the complete scene graph. +- **Object Inspection**: View basic object properties (type, name). +- **Renderer Details**: View properties, render stats, and memory usage for `WebGLRenderer` instances. + +## Communication Flow + +1. **Panel ↔ Background ↔ Content Script**: Standard extension messaging for panel initialization and state requests (`init`, `request-state`). +2. **Three.js → Bridge**: Three.js detects `window.__THREE_DEVTOOLS__` and uses its `dispatchEvent` method (sending `'register'`, `'observe'`). +3. **Bridge → Content Script**: Bridge uses `window.postMessage` to send data (`'register'`, `'renderer'`, `'scene'`, `'update'`) to the content script. +4. **Content Script → Background**: Content script uses `chrome.runtime.sendMessage` to relay messages from the bridge to the background. +5. **Background → Panel**: Background script uses the established port connection (`port.postMessage`) to send data to the panel. + +## Key Components + +- **DevToolsEventTarget**: Custom event system with backlogging for async loading. +- **Object Observation & Batching**: Efficiently tracks and sends scene graph data. +- **Renderer Property Display**: Shows detailed statistics for renderers. + +## Integration with Three.js + +The extension relies on Three.js having built-in support for DevTools. When Three.js detects the presence of `window.__THREE_DEVTOOLS__`, it interacts with it, primarily by dispatching events. + +The bridge script listens for these events, organizes the data, and provides it to the DevTools panel. + +## Development + +To modify the extension: + +1. Edit the relevant files in the `devtools` directory. +2. Go to `chrome://extensions/`, find the unpacked extension, and click the reload icon. +3. Close and reopen DevTools on the inspected page to see your changes. \ No newline at end of file diff --git a/devtools/background.js b/devtools/background.js new file mode 100644 index 00000000000000..b40c2643ff8c66 --- /dev/null +++ b/devtools/background.js @@ -0,0 +1,185 @@ +/* global chrome */ + +importScripts( 'constants.js' ); + +// Map tab IDs to connections +const connections = new Map(); + +// Handle extension icon clicks in the toolbar +chrome.action.onClicked.addListener( ( tab ) => { + + // Send scroll-to-canvas message to the content script (no UUID = scroll to first canvas) + chrome.tabs.sendMessage( tab.id, { + name: MESSAGE_SCROLL_TO_CANVAS, + tabId: tab.id + } ).catch( () => { + + // Ignore error - tab might not have the content script injected + console.log( 'Could not send scroll-to-canvas message to tab', tab.id ); + + } ); + +} ); + +// Listen for connections from the devtools panel +chrome.runtime.onConnect.addListener( port => { + + let tabId; + + // Messages that should be forwarded to content script + const forwardableMessages = new Set( [ + MESSAGE_REQUEST_STATE, + MESSAGE_REQUEST_OBJECT_DETAILS, + MESSAGE_SCROLL_TO_CANVAS, + MESSAGE_HIGHLIGHT_OBJECT, + MESSAGE_UNHIGHLIGHT_OBJECT + ] ); + + // Listen for messages from the devtools panel + port.onMessage.addListener( message => { + + if ( message.name === MESSAGE_INIT ) { + + tabId = message.tabId; + connections.set( tabId, port ); + + } else if ( forwardableMessages.has( message.name ) && tabId ) { + + chrome.tabs.sendMessage( tabId, message ); + + } else if ( tabId === undefined ) { + + console.warn( 'Background: Message received from panel before init:', message ); + + } + + } ); + + // Clean up when devtools is closed + port.onDisconnect.addListener( () => { + + if ( tabId ) { + + connections.delete( tabId ); + + } + + } ); + +} ); + +// Listen for messages from the content script +chrome.runtime.onMessage.addListener( ( message, sender, sendResponse ) => { + + if ( message.scheme ) { + + chrome.action.setIcon( { + path: { + 128: `icons/128-${message.scheme}.png` + } + } ); + + } + + if ( sender.tab ) { + + const tabId = sender.tab.id; + + // If three.js is detected, show a badge + if ( message.name === MESSAGE_REGISTER && message.detail && message.detail.revision ) { + + const revision = String( message.detail.revision ); + const number = revision.replace( /\D+$/, '' ); + const isDev = revision.includes( 'dev' ); + + chrome.action.setBadgeText( { tabId: tabId, text: number } ).catch( () => { + + // Ignore error - tab might have been closed + + } ); + chrome.action.setBadgeTextColor( { tabId: tabId, color: '#ffffff' } ).catch( () => { + + // Ignore error - tab might have been closed + + } ); + chrome.action.setBadgeBackgroundColor( { tabId: tabId, color: isDev ? '#ff0098' : '#049ef4' } ).catch( () => { + + // Ignore error - tab might have been closed + + } ); + + } + + const port = connections.get( tabId ); + if ( port ) { + + // Forward the message to the devtools panel + try { + + port.postMessage( message ); + // Send immediate response to avoid "message channel closed" error + sendResponse( { received: true } ); + + } catch ( e ) { + + console.error( 'Error posting message to devtools:', e ); + // If the port is broken, clean up the connection + connections.delete( tabId ); + + } + + } + + } + + return false; // Return false to indicate synchronous handling + +} ); + +// Listen for page navigation events +chrome.webNavigation.onCommitted.addListener( details => { + + const { tabId, frameId } = details; + + // Clear badge on navigation, only for top-level navigation + if ( frameId === 0 ) { + + chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => { + + // Ignore error - tab might have been closed + + } ); + + } + + const port = connections.get( tabId ); + + if ( port ) { + + port.postMessage( { + id: MESSAGE_ID, + name: MESSAGE_COMMITTED, + frameId: frameId + } ); + + } + +} ); + +// Clear badge when a tab is closed +chrome.tabs.onRemoved.addListener( ( tabId ) => { + + chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => { + + // Ignore error - tab is already gone + + } ); + + // Clean up connection if it exists for the closed tab + if ( connections.has( tabId ) ) { + + connections.delete( tabId ); + + } + +} ); diff --git a/devtools/bridge.js b/devtools/bridge.js new file mode 100644 index 00000000000000..91f4057fe7db01 --- /dev/null +++ b/devtools/bridge.js @@ -0,0 +1,630 @@ +/** + * This script injected by the installed three.js developer + * tools extension. + */ + +( function () { + + const HIGHLIGHT_OVERLAY_DURATION = 1000; + + // Only initialize if not already initialized + if ( ! window.__THREE_DEVTOOLS__ ) { + + // Create our custom EventTarget with logging + class DevToolsEventTarget extends EventTarget { + + constructor() { + + super(); + this._ready = false; + this._backlog = []; + this.objects = new Map(); + + } + + addEventListener( type, listener, options ) { + + super.addEventListener( type, listener, options ); + + // If this is the first listener for a type, and we have backlogged events, + // check if we should process them + if ( type !== EVENT_DEVTOOLS_READY && this._backlog.length > 0 ) { + + this.dispatchEvent( new CustomEvent( EVENT_DEVTOOLS_READY ) ); + + } + + } + + dispatchEvent( event ) { + + if ( this._ready || event.type === EVENT_DEVTOOLS_READY ) { + + if ( event.type === EVENT_DEVTOOLS_READY ) { + + this._ready = true; + const backlog = this._backlog; + this._backlog = []; + backlog.forEach( e => super.dispatchEvent( e ) ); + + } + + return super.dispatchEvent( event ); + + } else { + + this._backlog.push( event ); + return false; // Return false to indicate synchronous handling + + } + + } + + reset() { + + + // Clear objects map + this.objects.clear(); + + // Clear backlog + this._backlog = []; + + // Reset ready state + this._ready = false; + + // Clear observed arrays + observedScenes.length = 0; + observedRenderers.length = 0; + + } + + } + + // Create and expose the __THREE_DEVTOOLS__ object + const devTools = new DevToolsEventTarget(); + Object.defineProperty( window, '__THREE_DEVTOOLS__', { + value: devTools, + configurable: false, + enumerable: true, + writable: false + } ); + + // Declare arrays for tracking observed objects + const observedScenes = []; + const observedRenderers = []; + const sceneObjectCountCache = new Map(); // Cache for object counts per scene + + // Shared tree traversal function + function traverseObjectTree( rootObject, callback, skipDuplicates = false ) { + + const processedUUIDs = skipDuplicates ? new Set() : null; + + function traverse( object ) { + + if ( ! object || ! object.uuid ) return; + + // Skip DevTools highlight objects + if ( object.name === '__THREE_DEVTOOLS_HIGHLIGHT__' ) return; + + // Skip if already processed (when duplicate prevention is enabled) + if ( processedUUIDs && processedUUIDs.has( object.uuid ) ) return; + if ( processedUUIDs ) processedUUIDs.add( object.uuid ); + + // Execute callback for this object + callback( object ); + + // Process children recursively + if ( object.children && Array.isArray( object.children ) ) { + + object.children.forEach( child => traverse( child ) ); + + } + + } + + traverse( rootObject ); + + } + + // Function to get renderer data + function getRendererData( renderer ) { + + try { + + const data = { + uuid: renderer.uuid || generateUUID(), + type: renderer.isWebGLRenderer ? 'WebGLRenderer' : 'WebGPURenderer', + name: '', + properties: getRendererProperties( renderer ), + canvasInDOM: renderer.domElement && document.contains( renderer.domElement ) + }; + return data; + + } catch ( error ) { + + console.warn( 'DevTools: Error getting renderer data:', error ); + return null; + + } + + } + + // Function to get object hierarchy + function getObjectData( obj ) { + + try { + + // Special case for WebGLRenderer + if ( obj.isWebGLRenderer === true || obj.isWebGPURenderer === true ) { + + return getRendererData( obj ); + + } + + // Special case for InstancedMesh + const type = obj.isInstancedMesh ? 'InstancedMesh' : obj.type || obj.constructor.name; + + // Get descriptive name for the object + let name = obj.name || type || obj.constructor.name; + if ( obj.isMesh ) { + + const geoType = obj.geometry ? obj.geometry.type : 'Unknown'; + const matType = obj.material ? + ( Array.isArray( obj.material ) ? + obj.material.map( m => m.type ).join( ', ' ) : + obj.material.type ) : + 'Unknown'; + if ( obj.isInstancedMesh ) { + + name = `${name} [${obj.count}]`; + + } + + name = `${name} ${geoType} ${matType}`; + + } + + const data = { + uuid: obj.uuid, + name: name, + type: type, + visible: obj.visible !== undefined ? obj.visible : true, + isScene: obj.isScene === true, + isObject3D: obj.isObject3D === true, + isCamera: obj.isCamera === true, + isLight: obj.isLight === true, + isMesh: obj.isMesh === true, + isInstancedMesh: obj.isInstancedMesh === true, + parent: obj.parent ? obj.parent.uuid : null, + children: obj.children ? obj.children.map( child => child.uuid ) : [] + }; + + return data; + + } catch ( error ) { + + console.warn( 'DevTools: Error getting object data:', error ); + return null; + + } + + } + + // Generate a UUID for objects that don't have one + function generateUUID() { + + const array = new Uint8Array( 16 ); + crypto.getRandomValues( array ); + array[ 6 ] = ( array[ 6 ] & 0x0f ) | 0x40; // Set version to 4 + array[ 8 ] = ( array[ 8 ] & 0x3f ) | 0x80; // Set variant to 10 + return [ ...array ].map( ( b, i ) => ( i === 4 || i === 6 || i === 8 || i === 10 ? '-' : '' ) + b.toString( 16 ).padStart( 2, '0' ) ).join( '' ); + + } + + // Listen for Three.js registration + devTools.addEventListener( EVENT_REGISTER, ( event ) => { + + dispatchEvent( EVENT_REGISTER, event.detail ); + + } ); + + // Listen for object observations + devTools.addEventListener( EVENT_OBSERVE, ( event ) => { + + const obj = event.detail; + if ( ! obj ) { + + console.warn( 'DevTools: Received observe event with null/undefined detail' ); + return; + + } + + // Generate UUID if needed + if ( ! obj.uuid ) { + + obj.uuid = generateUUID(); + + } + + // Skip if already registered (essential to prevent loops with batching) + if ( devTools.objects.has( obj.uuid ) ) { + + return; + + } + + if ( obj.isWebGLRenderer || obj.isWebGPURenderer ) { + + const data = getObjectData( obj ); + + if ( data ) { + + data.properties = getRendererProperties( obj ); + observedRenderers.push( obj ); + devTools.objects.set( obj.uuid, data ); + + dispatchEvent( EVENT_RENDERER, data ); + + } + + } else if ( obj.isScene ) { + + observedScenes.push( obj ); + + const batchObjects = []; + + traverseObjectTree( obj, ( currentObj ) => { + + const objectData = getObjectData( currentObj ); + if ( objectData ) { + + batchObjects.push( objectData ); + devTools.objects.set( currentObj.uuid, objectData ); // Update local cache during batch creation + + } + + }, true ); + + dispatchEvent( EVENT_SCENE, { sceneUuid: obj.uuid, objects: batchObjects } ); + + } + + } ); + + // Function to get renderer properties + function getRendererProperties( renderer ) { + + const parameters = renderer.getContextAttributes ? renderer.getContextAttributes() : {}; + + return { + width: renderer.domElement ? renderer.domElement.clientWidth : 0, + height: renderer.domElement ? renderer.domElement.clientHeight : 0, + alpha: parameters.alpha || false, + antialias: parameters.antialias || false, + outputColorSpace: renderer.outputColorSpace, + toneMapping: renderer.toneMapping, + toneMappingExposure: renderer.toneMappingExposure !== undefined ? renderer.toneMappingExposure : 1, + shadows: renderer.shadowMap ? renderer.shadowMap.enabled : false, + autoClear: renderer.autoClear, + autoClearColor: renderer.autoClearColor, + autoClearDepth: renderer.autoClearDepth, + autoClearStencil: renderer.autoClearStencil, + localClipping: renderer.localClippingEnabled, + physicallyCorrectLights: renderer.physicallyCorrectLights || false, // Assuming false is default if undefined + info: { + render: { + frame: renderer.info.render.frame, + calls: renderer.isWebGPURenderer ? renderer.info.render.drawCalls : renderer.info.render.calls, + triangles: renderer.info.render.triangles, + points: renderer.info.render.points, + lines: renderer.info.render.lines, + geometries: renderer.info.render.geometries, + sprites: renderer.info.render.sprites + }, + memory: { + geometries: renderer.info.memory.geometries, + textures: renderer.info.memory.textures, + programs: renderer.info.programs ? renderer.info.programs.length : 0, + renderLists: renderer.info.memory.renderLists, + renderTargets: renderer.info.memory.renderTargets + } + } + }; + + } + + + // Function to check if bridge is available + function checkBridgeAvailability() { + + const devToolsValue = window.__THREE_DEVTOOLS__; + + // If we have devtools and we're interactive or complete, trigger ready + if ( devToolsValue && ( document.readyState === 'interactive' || document.readyState === 'complete' ) ) { + + devTools.dispatchEvent( new CustomEvent( EVENT_DEVTOOLS_READY ) ); + + } + + } + + // Watch for readyState changes + document.addEventListener( 'readystatechange', () => { + + if ( document.readyState === 'loading' ) { + + devTools.reset(); + + } + + checkBridgeAvailability(); + + } ); + + // Check if THREE is in the global scope (Old versions) + window.addEventListener( 'load', () => { + + if ( window.THREE && window.THREE.REVISION ) { + + dispatchEvent( EVENT_REGISTER, { revision: window.THREE.REVISION } ); + + } + + } ); + + // Watch for page unload to reset state + window.addEventListener( 'beforeunload', () => { + + devTools.reset(); + + } ); + + // Listen for messages from the content script + window.addEventListener( 'message', function ( event ) { + + // Only accept messages from the same frame + if ( event.source !== window ) return; + + const message = event.data; + if ( ! message || message.id !== MESSAGE_ID ) return; + + // Handle request for initial state from panel + if ( message.name === MESSAGE_REQUEST_STATE ) { + + sendState(); + + } else if ( message.name === MESSAGE_REQUEST_OBJECT_DETAILS ) { + + sendObjectDetails( message.uuid ); + + } else if ( message.name === MESSAGE_SCROLL_TO_CANVAS ) { + + scrollToCanvas( message.uuid ); + + } else if ( message.name === MESSAGE_HIGHLIGHT_OBJECT ) { + + devTools.dispatchEvent( new CustomEvent( 'highlight-object', { detail: { uuid: message.uuid } } ) ); + + } else if ( message.name === MESSAGE_UNHIGHLIGHT_OBJECT ) { + + devTools.dispatchEvent( new CustomEvent( 'unhighlight-object' ) ); + + } + + } ); + + function sendState() { + + // Send current renderers + for ( const observedRenderer of observedRenderers ) { + + const data = getObjectData( observedRenderer ); + if ( data ) { + + data.properties = getRendererProperties( observedRenderer ); + dispatchEvent( EVENT_RENDERER, data ); + + } + + } + + // Send current scenes + for ( const observedScene of observedScenes ) { + + reloadSceneObjects( observedScene ); + + } + + } + + function findObjectInScenes( uuid ) { + + for ( const scene of observedScenes ) { + + // Check if we're looking for the scene itself + if ( scene.uuid === uuid ) return scene; + + const found = scene.getObjectByProperty( 'uuid', uuid ); + if ( found ) return found; + + } + + return null; + + } + + // Expose utilities for highlight.js in a clean namespace + devTools.utils = { + findObjectInScenes, + generateUUID + }; + + // Expose renderers array for highlight.js + devTools.renderers = observedRenderers; + + function createHighlightOverlay( targetElement ) { + + const overlay = document.createElement( 'div' ); + overlay.style.cssText = ` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 122, 204, 0.3); + pointer-events: none; + z-index: 999999; + `; + + // Position the overlay relative to the target + const parent = targetElement.parentElement || document.body; + + if ( getComputedStyle( parent ).position === 'static' ) { + + parent.style.position = 'relative'; + + } + + parent.appendChild( overlay ); + + // Auto-remove after duration + setTimeout( () => { + + if ( overlay.parentElement ) { + + overlay.parentElement.removeChild( overlay ); + + } + + }, HIGHLIGHT_OVERLAY_DURATION ); + + } + + function sendObjectDetails( uuid ) { + + const object = findObjectInScenes( uuid ); + + if ( object ) { + + const details = { + uuid: object.uuid, + type: object.type, + name: object.name, + position: { + x: object.position.x, + y: object.position.y, + z: object.position.z + }, + rotation: { + x: object.rotation.x, + y: object.rotation.y, + z: object.rotation.z + }, + scale: { + x: object.scale.x, + y: object.scale.y, + z: object.scale.z + } + }; + + dispatchEvent( EVENT_OBJECT_DETAILS, details ); + + } + + } + + function scrollToCanvas( uuid ) { + + let renderer = null; + + if ( uuid ) { + + // Find the renderer with the given UUID + renderer = observedRenderers.find( r => r.uuid === uuid ); + + } else { + + // If no UUID provided, find the first available renderer whose canvas is in the DOM + renderer = observedRenderers.find( r => r.domElement && document.body.contains( r.domElement ) ); + + } + + if ( renderer ) { + + // Scroll the canvas element into view + renderer.domElement.scrollIntoView( { + behavior: 'smooth', + block: 'center', + inline: 'center' + } ); + + // Add a brief blue overlay flash effect + createHighlightOverlay( renderer.domElement ); + + } + + } + + function dispatchEvent( name, detail ) { + + try { + + window.postMessage( { + id: MESSAGE_ID, + name: name, + detail: detail + }, '*' ); + + } catch ( error ) { + + // If we get an "Extension context invalidated" error, stop all monitoring + if ( error.message.includes( 'Extension context invalidated' ) ) { + + console.log( 'DevTools: Extension context invalidated, stopping monitoring' ); + devTools.reset(); + return; + + } + + console.warn( 'DevTools: Error dispatching event:', error ); + + } + + } + + // Function to manually reload scene objects + function reloadSceneObjects( scene ) { + + const batchObjects = []; + + traverseObjectTree( scene, ( object ) => { + + const objectData = getObjectData( object ); + if ( objectData ) { + + batchObjects.push( objectData ); // Add to batch + // Update or add to local cache immediately + devTools.objects.set( object.uuid, objectData ); + + } + + } ); + + // --- Caching Logic --- + const currentObjectCount = batchObjects.length; + const previousObjectCount = sceneObjectCountCache.get( scene.uuid ); + + if ( currentObjectCount !== previousObjectCount ) { + + // Dispatch the batch update for the panel + dispatchEvent( EVENT_SCENE, { sceneUuid: scene.uuid, objects: batchObjects } ); + // Update the cache + sceneObjectCountCache.set( scene.uuid, currentObjectCount ); + + } + + } + + } + +} )(); diff --git a/devtools/constants.js b/devtools/constants.js new file mode 100644 index 00000000000000..68f2b86d14d51f --- /dev/null +++ b/devtools/constants.js @@ -0,0 +1,22 @@ +// Shared protocol constants for Three.js DevTools + +var MESSAGE_ID = 'three-devtools'; + +// Chrome extension messages +var MESSAGE_INIT = 'init'; +var MESSAGE_REQUEST_STATE = 'request-state'; +var MESSAGE_REQUEST_OBJECT_DETAILS = 'request-object-details'; +var MESSAGE_SCROLL_TO_CANVAS = 'scroll-to-canvas'; +var MESSAGE_HIGHLIGHT_OBJECT = 'highlight-object'; +var MESSAGE_UNHIGHLIGHT_OBJECT = 'unhighlight-object'; +var MESSAGE_REGISTER = 'register'; +var MESSAGE_COMMITTED = 'committed'; + +// Bridge/DevTools events +var EVENT_REGISTER = 'register'; +var EVENT_OBSERVE = 'observe'; +var EVENT_RENDERER = 'renderer'; +var EVENT_SCENE = 'scene'; +var EVENT_OBJECT_DETAILS = 'object-details'; +var EVENT_DEVTOOLS_READY = 'devtools-ready'; +var EVENT_COMMITTED = 'committed'; diff --git a/devtools/content-script.js b/devtools/content-script.js new file mode 100644 index 00000000000000..744df0c609c9a3 --- /dev/null +++ b/devtools/content-script.js @@ -0,0 +1,80 @@ +/* global chrome */ + +// Constants +const MESSAGE_ID = 'three-devtools'; +const MESSAGE_REQUEST_STATE = 'request-state'; +const MESSAGE_REQUEST_OBJECT_DETAILS = 'request-object-details'; +const MESSAGE_SCROLL_TO_CANVAS = 'scroll-to-canvas'; +const MESSAGE_HIGHLIGHT_OBJECT = 'highlight-object'; +const MESSAGE_UNHIGHLIGHT_OBJECT = 'unhighlight-object'; + +// Helper to check if extension context is valid +function isExtensionContextValid() { + + try { + + chrome.runtime.getURL( '' ); + return true; + + } catch ( error ) { + + return false; + + } + +} + +// Unified message handler for window messages +function handleWindowMessage( event ) { + + // Only accept messages with the correct id + if ( ! event.data || event.data.id !== MESSAGE_ID ) return; + + // Determine source: 'main' for window, 'iframe' otherwise + const source = event.source === window ? 'main' : 'iframe'; + + if ( ! isExtensionContextValid() ) { + + console.warn( 'Extension context invalidated, cannot send message' ); + return; + + } + + event.data.source = source; + chrome.runtime.sendMessage( event.data ); + +} + +// Listener for messages from the background script (originating from panel) +function handleBackgroundMessage( message ) { + + const forwardableMessages = new Set( [ + MESSAGE_REQUEST_STATE, + MESSAGE_REQUEST_OBJECT_DETAILS, + MESSAGE_SCROLL_TO_CANVAS, + MESSAGE_HIGHLIGHT_OBJECT, + MESSAGE_UNHIGHLIGHT_OBJECT + ] ); + + if ( forwardableMessages.has( message.name ) ) { + + message.id = MESSAGE_ID; + window.postMessage( message, '*' ); + + } + +} + +// Add event listeners +window.addEventListener( 'message', handleWindowMessage, false ); +chrome.runtime.onMessage.addListener( handleBackgroundMessage ); + +// Icon color scheme +const isLightTheme = window.matchMedia( '(prefers-color-scheme: light)' ).matches; +chrome.runtime.sendMessage( { scheme: isLightTheme ? 'light' : 'dark' } ); +window.matchMedia( '(prefers-color-scheme: light)' ).onchange = event => { + + chrome.runtime.sendMessage( { scheme: event.matches ? 'light' : 'dark' } ); + +}; + diff --git a/devtools/devtools.js b/devtools/devtools.js new file mode 100644 index 00000000000000..30df66741ea65d --- /dev/null +++ b/devtools/devtools.js @@ -0,0 +1,13 @@ +try { + + chrome.devtools.panels.create( + 'Three.js', + null, + 'panel/panel.html' + ); + +} catch ( error ) { + + console.error( 'Failed to create Three.js panel:', error ); + +} diff --git a/devtools/highlight.js b/devtools/highlight.js new file mode 100644 index 00000000000000..34c9c2717f47bf --- /dev/null +++ b/devtools/highlight.js @@ -0,0 +1,194 @@ +/* global __THREE_DEVTOOLS__ */ + +// This script handles highlighting of Three.js objects in the 3D scene + +( function () { + + 'use strict'; + + let highlightObject = null; + + function cloneMaterial( material ) { + + // Skip MeshNormalMaterial + if ( material.isMeshNormalMaterial ) { + + return material; + + } + + // Handle ShaderMaterial and RawShaderMaterial + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { + + // Create new material of the same type + const cloned = new material.constructor(); + + // Override shaders with simple yellow output + const vertexShader = ` + ${ material.isRawShaderMaterial ? `attribute vec3 position; + uniform mat4 modelViewMatrix; + uniform mat4 projectionMatrix; + ` : '' }void main() { + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + } + `; + + const fragmentShader = ` + ${ material.isRawShaderMaterial ? `precision highp float; + ` : '' }void main() { + gl_FragColor = vec4( 1.0, 1.0, 0.0, 1.0 ); + } + `; + + cloned.vertexShader = vertexShader; + cloned.fragmentShader = fragmentShader; + + // Override with yellow wireframe settings + cloned.wireframe = true; + cloned.depthTest = false; + cloned.depthWrite = false; + cloned.transparent = true; + cloned.opacity = 1; + cloned.toneMapped = false; + cloned.fog = false; + + return cloned; + + } + + // Create new material of the same type + const cloned = new material.constructor(); + + // Set yellow color + if ( cloned.color ) { + + cloned.color.r = 1; + cloned.color.g = 1; + cloned.color.b = 0; + + } + + // If material has emissive, set it to yellow + if ( 'emissive' in cloned ) { + + cloned.emissive.r = 1; + cloned.emissive.g = 1; + cloned.emissive.b = 0; + + } + + // Enable wireframe if the material supports it + if ( 'wireframe' in cloned ) { + + cloned.wireframe = true; + + } + + // Render on top, ignoring depth + cloned.depthTest = false; + cloned.depthWrite = false; + cloned.transparent = true; + cloned.opacity = 1; + + // Disable tone mapping and fog + cloned.toneMapped = false; + cloned.fog = false; + + return cloned; + + } + + function highlight( uuid ) { + + const object = __THREE_DEVTOOLS__.utils.findObjectInScenes( uuid ); + if ( ! object ) { + + // Object not in scene (e.g., renderer) - hide highlight + if ( highlightObject ) highlightObject.visible = false; + return; + + } + + // Skip helpers, existing highlights, and objects without geometry + if ( object.type.includes( 'Helper' ) || object.name === '__THREE_DEVTOOLS_HIGHLIGHT__' || ! object.geometry ) { + + if ( highlightObject ) highlightObject.visible = false; + return; + + } + + // Remove old highlight if it exists + if ( highlightObject && highlightObject.parent ) { + + highlightObject.parent.remove( highlightObject ); + + } + + // Clone the object to preserve all properties (skeleton, bindMatrix, etc) + highlightObject = object.clone(); + highlightObject.name = '__THREE_DEVTOOLS_HIGHLIGHT__'; + + // Apply yellow wireframe material + if ( highlightObject.material ) { + + if ( Array.isArray( highlightObject.material ) ) { + + highlightObject.material = highlightObject.material.map( cloneMaterial ); + + } else { + + highlightObject.material = cloneMaterial( highlightObject.material ); + + } + + } + + // Disable shadows + highlightObject.castShadow = false; + highlightObject.receiveShadow = false; + + // Render on top of everything + highlightObject.renderOrder = Infinity; + + // Disable auto update before adding to scene + highlightObject.matrixAutoUpdate = false; + highlightObject.matrixWorldAutoUpdate = false; + + // Find the scene and add at root + let scene = object; + while ( scene.parent ) scene = scene.parent; + + scene.add( highlightObject ); + + // Reuse the matrixWorld from original object (after adding to scene) + highlightObject.matrixWorld = object.matrixWorld; + + // Make sure it's visible + highlightObject.visible = true; + + } + + function unhighlight() { + + if ( highlightObject ) { + + highlightObject.visible = false; + + } + + } + + // Listen for highlight events from bridge.js + __THREE_DEVTOOLS__.addEventListener( 'highlight-object', ( event ) => { + + highlight( event.detail.uuid ); + + } ); + + __THREE_DEVTOOLS__.addEventListener( 'unhighlight-object', () => { + + unhighlight(); + + } ); + +} )(); diff --git a/devtools/icons/128-dark.png b/devtools/icons/128-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..71d38580c79f2c1b38a230e8fb56d0c74788be2f GIT binary patch literal 4770 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 Ww=WNPP literal 0 HcmV?d00001 diff --git a/devtools/index.html b/devtools/index.html new file mode 100644 index 00000000000000..c83ce6457297b2 --- /dev/null +++ b/devtools/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/devtools/manifest.json b/devtools/manifest.json new file mode 100644 index 00000000000000..cb3aefb8e53e22 --- /dev/null +++ b/devtools/manifest.json @@ -0,0 +1,32 @@ +{ + "manifest_version": 3, + "name": "Three.js DevTools", + "version": "1.15", + "description": "Developer tools extension for Three.js", + "icons": { + "128": "icons/128-light.png" + }, + "action": {}, + "devtools_page": "index.html", + "background": { + "service_worker": "background.js" + }, + "content_scripts": [{ + "matches": [""], + "js": ["constants.js", "bridge.js", "highlight.js"], + "all_frames": true, + "run_at": "document_start", + "world": "MAIN", + "match_about_blank": true + }, { + "matches": [""], + "js": ["content-script.js"], + "all_frames": true, + "run_at": "document_start", + "match_about_blank": true + }], + "permissions": [ + "activeTab", + "webNavigation" + ] +} \ No newline at end of file diff --git a/devtools/panel/panel.css b/devtools/panel/panel.css new file mode 100644 index 00000000000000..3de915c501ed77 --- /dev/null +++ b/devtools/panel/panel.css @@ -0,0 +1,200 @@ +:root { + color-scheme: light dark; +} + +body { + background: light-dark( #fff, #333 ); + color: light-dark( #333, #e0e0e0 ); + margin: 0; + padding: 10px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: 12px; +} + +hr { + color: light-dark( #333, #e0e0e0 ); +} + +#scene-tree { + width: 100%; + height: 100%; + overflow: auto; +} + +.header { + padding: 8px 12px; + background: light-dark( #f5f5f5, #333 ); + border-radius: 4px; + margin-bottom: 16px; + font-family: monospace; + color: light-dark( #666, #aaa ); +} + .header a { + color: light-dark( #666, #aaa ); + text-decoration: none; + } + .header a:hover { + color: light-dark( #333, #e0e0e0 ); + } + +.section { + margin-bottom: 24px; +} + + .section h3 { + margin: 0 0 8px 0; + font-size: 11px; + text-transform: uppercase; + color: light-dark( #666, #aaa ); + font-weight: 500; + border-bottom: 1px solid light-dark( #eee, #444 ); + padding-bottom: 4px; + } + +.tree-item { + padding: 4px; + cursor: pointer; + display: flex; + align-items: center; +} +.tree-item:hover { + background: light-dark( #f0f0f0, #555 ); +} +.tree-item .icon { + margin-right: 4px; + opacity: 0.7; +} +.tree-item .label { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.tree-item .label .object-details { + color: #aaa; + margin-left: 4px; + font-weight: normal; +} +.tree-item .type { + margin-left: 8px; + opacity: 0.5; + font-size: 0.9em; +} + +.children { + margin-left: 0; +} + +/* Style for clickable renderer summary */ +.renderer-summary { + cursor: pointer; +} +.renderer-summary:hover { + background: light-dark( #f0f0f0, #555 ); +} + +/* Hide default details marker when using custom summary */ +details.renderer-container > summary.renderer-summary { /* Target summary */ + list-style: none; /* Hide default arrow */ + cursor: pointer; /* Make the summary div look clickable */ +} +details.renderer-container > summary.renderer-summary::-webkit-details-marker { + display: none; /* Hide default arrow in WebKit */ +} + +/* Style for the toggle icon */ +.toggle-icon::before { + content: '▶'; /* Default: collapsed */ + display: inline-block; + width: 1em; + margin-right: 2px; + opacity: 0.7; +} +details.renderer-container[open] > summary.renderer-summary .toggle-icon::before { + content: '▼'; /* Expanded */ +} + +/* Floating object details panel */ +.floating-details { + position: fixed; + z-index: 1000; + background: light-dark( #fff, #2a2a2a ); + border: 1px solid light-dark( #ccc, #555 ); + border-radius: 6px; + padding: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + max-width: 300px; + min-width: 200px; + font-size: 11px; + pointer-events: none; /* Prevent interfering with mouse interactions */ + opacity: 0; + transform: translateY(10px); + transition: opacity 0.2s ease, transform 0.2s ease; +} + +.floating-details.visible { + opacity: 1; + transform: translateY(0); +} + +.floating-details h4 { + margin: 8px 0 4px 0; + font-size: 10px; + text-transform: uppercase; + color: light-dark( #666, #aaa ); + border-bottom: 1px solid light-dark( #eee, #444 ); + padding-bottom: 2px; +} + +.floating-details .property-row { + margin-bottom: 1px; + font-size: 10px; +} + +/* Scroll to canvas button */ +.scroll-to-canvas-btn { + background: none; + border: none; + cursor: pointer; + font-size: 12px; + margin-left: 8px; + padding: 2px 4px; + border-radius: 3px; + opacity: 0.6; + transition: opacity 0.2s ease, background 0.2s ease; +} + +.scroll-to-canvas-btn:hover { + opacity: 1; + background: light-dark( rgba(0,0,0,0.1), rgba(255,255,255,0.1) ); +} + +.scroll-to-canvas-placeholder { + font-size: 12px; + margin-left: 8px; + padding: 2px 4px; + opacity: 0.3; +} + +/* Two-column layout for wide panel */ +@media (min-width: 1000px) { + .sections-container { + display: flex; + gap: 20px; + align-items: flex-start; + } + + .sections-container .section { + flex: 1; + margin-bottom: 0; + } + + /* Ensure sections have equal width */ + .sections-container .section:first-child { + min-width: 0; /* Allow flexbox to shrink */ + } + + .sections-container .section:last-child { + min-width: 0; /* Allow flexbox to shrink */ + } +} \ No newline at end of file diff --git a/devtools/panel/panel.html b/devtools/panel/panel.html new file mode 100644 index 00000000000000..dcc7b9027db56f --- /dev/null +++ b/devtools/panel/panel.html @@ -0,0 +1,13 @@ + + + + + Three.js DevTools + + + +
+ + + + \ No newline at end of file diff --git a/devtools/panel/panel.js b/devtools/panel/panel.js new file mode 100644 index 00000000000000..66411e17952c6f --- /dev/null +++ b/devtools/panel/panel.js @@ -0,0 +1,712 @@ +/* global chrome */ + +const CONNECTION_NAME = 'three-devtools'; +const STATE_POLLING_INTERVAL = 1000; + +// --- Utility Functions --- +function getObjectIcon( obj ) { + + if ( obj.isScene ) return '🌍'; + if ( obj.isCamera ) return '📷'; + if ( obj.isLight ) return '💡'; + if ( obj.isInstancedMesh ) return '🔸'; + if ( obj.isMesh ) return '🔷'; + if ( obj.type === 'Group' ) return '📁'; + return '📦'; + +} + +function createPropertyRow( label, value ) { + + const row = document.createElement( 'div' ); + row.className = 'property-row'; + row.style.display = 'flex'; + row.style.justifyContent = 'space-between'; + row.style.marginBottom = '2px'; + + const labelSpan = document.createElement( 'span' ); + labelSpan.className = 'property-label'; + labelSpan.textContent = `${label}`; + labelSpan.style.marginRight = '10px'; + labelSpan.style.whiteSpace = 'nowrap'; + + const valueSpan = document.createElement( 'span' ); + valueSpan.className = 'property-value'; + const displayValue = ( value === undefined || value === null ) + ? '–' + : ( typeof value === 'number' ? value.toLocaleString() : value ); + valueSpan.textContent = displayValue; + valueSpan.style.textAlign = 'right'; + + row.appendChild( labelSpan ); + row.appendChild( valueSpan ); + return row; + +} + +function createVectorRow( label, vector ) { + + const row = document.createElement( 'div' ); + row.className = 'property-row'; + row.style.marginBottom = '2px'; + + // Pad label to ensure consistent alignment + const paddedLabel = label.padEnd( 16, ' ' ); // Pad to 16 characters + const content = `${paddedLabel} ${vector.x.toFixed( 3 )}\t${vector.y.toFixed( 3 )}\t${vector.z.toFixed( 3 )}`; + row.textContent = content; + row.style.fontFamily = 'monospace'; + row.style.whiteSpace = 'pre'; + + return row; + +} + +// --- State --- +const state = { + revision: null, + scenes: new Map(), + renderers: new Map(), + objects: new Map(), + selectedObject: null +}; + +// Floating details panel +let floatingPanel = null; +let mousePosition = { x: 0, y: 0 }; + + +// Create a connection to the background page +const backgroundPageConnection = chrome.runtime.connect( { + name: CONNECTION_NAME +} ); + +// Initialize the connection with the inspected tab ID +backgroundPageConnection.postMessage( { + name: MESSAGE_INIT, + tabId: chrome.devtools.inspectedWindow.tabId +} ); + +// Request the initial state from the bridge script +backgroundPageConnection.postMessage( { + name: MESSAGE_REQUEST_STATE, + tabId: chrome.devtools.inspectedWindow.tabId +} ); + +// Function to scroll to canvas element +function scrollToCanvas( rendererUuid ) { + backgroundPageConnection.postMessage( { + name: MESSAGE_SCROLL_TO_CANVAS, + uuid: rendererUuid, + tabId: chrome.devtools.inspectedWindow.tabId + } ); +} + +const intervalId = setInterval( () => { + + backgroundPageConnection.postMessage( { + name: MESSAGE_REQUEST_STATE, + tabId: chrome.devtools.inspectedWindow.tabId + } ); + +}, STATE_POLLING_INTERVAL ); + +backgroundPageConnection.onDisconnect.addListener( () => { + + clearInterval( intervalId ); + clearState(); + +} ); + +// Function to request object details from the bridge +function requestObjectDetails( uuid ) { + backgroundPageConnection.postMessage( { + name: MESSAGE_REQUEST_OBJECT_DETAILS, + uuid: uuid, + tabId: chrome.devtools.inspectedWindow.tabId + } ); +} + +// Function to highlight object in 3D scene +function requestObjectHighlight( uuid ) { + backgroundPageConnection.postMessage( { + name: MESSAGE_HIGHLIGHT_OBJECT, + uuid: uuid, + tabId: chrome.devtools.inspectedWindow.tabId + } ); +} + +// Function to remove highlight from 3D scene +function requestObjectUnhighlight() { + backgroundPageConnection.postMessage( { + name: MESSAGE_UNHIGHLIGHT_OBJECT, + tabId: chrome.devtools.inspectedWindow.tabId + } ); +} + + +// Store renderer collapse states +const rendererCollapsedState = new Map(); + +// Static DOM elements (created once in initUI) +let renderersSection = null; +let scenesSection = null; +let sceneDirty = true; + +// Helper function to create properties column for renderer +function createRendererPropertiesColumn( props ) { + + const propsCol = document.createElement( 'div' ); + propsCol.className = 'properties-column'; + const propsTitle = document.createElement( 'h4' ); + propsTitle.textContent = 'Properties'; + propsCol.appendChild( propsTitle ); + propsCol.appendChild( createPropertyRow( 'Size', `${props.width}x${props.height}` ) ); + propsCol.appendChild( createPropertyRow( 'Alpha', props.alpha ) ); + propsCol.appendChild( createPropertyRow( 'Antialias', props.antialias ) ); + propsCol.appendChild( createPropertyRow( 'Output Color Space', props.outputColorSpace ) ); + propsCol.appendChild( createPropertyRow( 'Tone Mapping', props.toneMapping ) ); + propsCol.appendChild( createPropertyRow( 'Tone Mapping Exposure', props.toneMappingExposure ) ); + propsCol.appendChild( createPropertyRow( 'Shadows', props.shadows ? 'enabled' : 'disabled' ) ); + propsCol.appendChild( createPropertyRow( 'Auto Clear', props.autoClear ) ); + propsCol.appendChild( createPropertyRow( 'Auto Clear Color', props.autoClearColor ) ); + propsCol.appendChild( createPropertyRow( 'Auto Clear Depth', props.autoClearDepth ) ); + propsCol.appendChild( createPropertyRow( 'Auto Clear Stencil', props.autoClearStencil ) ); + propsCol.appendChild( createPropertyRow( 'Local Clipping', props.localClipping ) ); + propsCol.appendChild( createPropertyRow( 'Physically Correct Lights', props.physicallyCorrectLights ) ); + + return propsCol; + +} + +// Helper function to create stats column for renderer +function createRendererStatsColumn( info ) { + + const statsCol = document.createElement( 'div' ); + statsCol.className = 'stats-column'; + + // Render Stats + const renderTitle = document.createElement( 'h4' ); + renderTitle.textContent = 'Render Stats'; + statsCol.appendChild( renderTitle ); + statsCol.appendChild( createPropertyRow( 'Frame', info.render.frame ) ); + statsCol.appendChild( createPropertyRow( 'Draw Calls', info.render.calls ) ); + statsCol.appendChild( createPropertyRow( 'Triangles', info.render.triangles ) ); + statsCol.appendChild( createPropertyRow( 'Points', info.render.points ) ); + statsCol.appendChild( createPropertyRow( 'Lines', info.render.lines ) ); + + // Memory + const memoryTitle = document.createElement( 'h4' ); + memoryTitle.textContent = 'Memory'; + memoryTitle.style.marginTop = '10px'; + statsCol.appendChild( memoryTitle ); + statsCol.appendChild( createPropertyRow( 'Geometries', info.memory.geometries ) ); + statsCol.appendChild( createPropertyRow( 'Textures', info.memory.textures ) ); + statsCol.appendChild( createPropertyRow( 'Shader Programs', info.memory.programs ) ); + + return statsCol; + +} + +// Helper function to process scene batch updates +function processSceneBatch( sceneUuid, batchObjects ) { + + // 1. Identify UUIDs in the new batch + const newObjectUuids = new Set( batchObjects.map( obj => obj.uuid ) ); + + // 2. Identify current object UUIDs associated with this scene that are NOT renderers + const currentSceneObjectUuids = new Set(); + state.objects.forEach( ( obj, uuid ) => { + + // Use the _sceneUuid property we'll add below, or check if it's the scene root itself + if ( obj._sceneUuid === sceneUuid || uuid === sceneUuid ) { + + currentSceneObjectUuids.add( uuid ); + + } + + } ); + + // 3. Find UUIDs to remove (in current state for this scene, but not in the new batch) + const uuidsToRemove = new Set(); + currentSceneObjectUuids.forEach( uuid => { + + if ( ! newObjectUuids.has( uuid ) ) { + + uuidsToRemove.add( uuid ); + + } + + } ); + + // 4. Remove stale objects from state + uuidsToRemove.forEach( uuid => { + + state.objects.delete( uuid ); + // If a scene object itself was somehow removed (unlikely for root), clean up scenes map too + if ( state.scenes.has( uuid ) ) { + + state.scenes.delete( uuid ); + + } + + } ); + + // 5. Process the new batch: Add/Update objects and mark their scene association + batchObjects.forEach( objData => { + + objData._sceneUuid = sceneUuid; + state.objects.set( objData.uuid, objData ); + + if ( objData.isScene && objData.uuid === sceneUuid ) { + + state.scenes.set( objData.uuid, objData ); + + } + + } ); + + sceneDirty = true; + +} + +// Clear state when panel is reloaded +function clearState() { + + state.revision = null; + state.scenes.clear(); + state.renderers.clear(); + state.objects.clear(); + sceneDirty = true; + + // Hide floating panel + if ( floatingPanel ) { + + floatingPanel.classList.remove( 'visible' ); + + } + +} + +// Listen for messages from the background page +backgroundPageConnection.onMessage.addListener( function ( message ) { + + if ( message.id === MESSAGE_ID ) { + + handleThreeEvent( message ); + + } + +} ); + +function handleThreeEvent( message ) { + + switch ( message.name ) { + + case EVENT_REGISTER: + state.revision = message.detail.revision; + break; + + case EVENT_RENDERER: + const detail = message.detail; + state.renderers.set( detail.uuid, detail ); + state.objects.set( detail.uuid, detail ); + updateRenderers(); + break; + + case EVENT_OBJECT_DETAILS: + state.selectedObject = message.detail; + showFloatingDetails( message.detail ); + break; + + case EVENT_SCENE: + const { sceneUuid, objects: batchObjects } = message.detail; + processSceneBatch( sceneUuid, batchObjects ); + updateSceneTree(); + break; + + case EVENT_COMMITTED: + clearState(); + updateRenderers(); + updateSceneTree(); + break; + + } + +} + +function renderRenderer( obj, container ) { + + // Create
element as the main container + const detailsElement = document.createElement( 'details' ); + detailsElement.className = 'renderer-container'; + detailsElement.setAttribute( 'data-uuid', obj.uuid ); + + // Set initial state + detailsElement.open = rendererCollapsedState.get( obj.uuid ) || false; + + // Add toggle listener to save state + detailsElement.addEventListener( 'toggle', () => { + + rendererCollapsedState.set( obj.uuid, detailsElement.open ); + + } ); + + // Create the summary element (clickable header) - THIS IS THE FIRST CHILD + const summaryElem = document.createElement( 'summary' ); // USE tag + summaryElem.className = 'tree-item renderer-summary'; // Acts as summary + + // Update display name in the summary line + const props = obj.properties; + const details = [ `${props.width}x${props.height}` ]; + if ( props.info ) { + + details.push( `${props.info.render.calls} draws` ); + details.push( `${props.info.render.triangles.toLocaleString()} triangles` ); + + } + + const displayName = `${obj.type} ${details.join( ' ・ ' )}`; + + // Use toggle icon instead of paint icon + const scrollButton = obj.canvasInDOM ? + `` : + `󠀠🫥`; + summaryElem.innerHTML = ` + ${displayName} + ${obj.type} + ${scrollButton}`; + detailsElement.appendChild( summaryElem ); + + const propsContainer = document.createElement( 'div' ); + propsContainer.className = 'properties-list'; + // Adjust padding calculation if needed, ensure it's a number before adding + const summaryPaddingLeft = parseFloat( summaryElem.style.paddingLeft ) || 0; + propsContainer.style.paddingLeft = `${summaryPaddingLeft + 20}px`; // Indent further + + propsContainer.innerHTML = ''; // Clear placeholder + + if ( obj.properties ) { + + const props = obj.properties; + const info = props.info || { render: {}, memory: {} }; // Default empty objects if info is missing + + const gridContainer = document.createElement( 'div' ); + gridContainer.style.display = 'grid'; + gridContainer.style.gridTemplateColumns = 'repeat(auto-fit, minmax(200px, 1fr))'; // Responsive columns + gridContainer.style.gap = '10px 20px'; // Row and column gap + + gridContainer.appendChild( createRendererPropertiesColumn( props ) ); + gridContainer.appendChild( createRendererStatsColumn( info ) ); + propsContainer.appendChild( gridContainer ); + + } else { + + propsContainer.textContent = 'No properties available.'; + + } + + detailsElement.appendChild( propsContainer ); + + // Add click handler for scroll to canvas button + const scrollBtn = detailsElement.querySelector( '.scroll-to-canvas-btn' ); + if ( scrollBtn ) { + scrollBtn.addEventListener( 'click', ( event ) => { + event.preventDefault(); + event.stopPropagation(); + scrollToCanvas( obj.uuid ); + } ); + } + + container.appendChild( detailsElement ); // Append details to the main container + +} + +// Function to render an object and its children +function renderObject( obj, container, level = 0, parentInvisible = false ) { + + const icon = getObjectIcon( obj ); + let displayName = obj.name || obj.type; + + // Default rendering for other object types + const elem = document.createElement( 'div' ); + elem.className = 'tree-item'; + elem.style.paddingLeft = `${level * 20}px`; + elem.setAttribute( 'data-uuid', obj.uuid ); + + // Apply opacity for invisible objects or if parent is invisible + if ( obj.visible === false || parentInvisible ) { + + elem.style.opacity = '0.5'; + + } + + let labelContent = `${icon} + ${displayName} + ${obj.type}`; + + if ( obj.isScene ) { + + // Add object count for scenes + let objectCount = - 1; + function countObjects( uuid ) { + + const object = state.objects.get( uuid ); + if ( object && object.name !== '__THREE_DEVTOOLS_HIGHLIGHT__' ) { + + objectCount ++; // Increment count for the object itself + if ( object.children ) { + + object.children.forEach( childId => countObjects( childId ) ); + + } + + } + + } + + countObjects( obj.uuid ); + displayName = `${obj.name || obj.type} ${objectCount} objects`; + labelContent = `${icon} + ${displayName} + ${obj.type}`; + + } + + elem.innerHTML = labelContent; + + // Add mouseenter handler to request object details and highlight in 3D + elem.addEventListener( 'mouseenter', () => { + requestObjectDetails( obj.uuid ); + // Only highlight if object and all parents are visible + if ( obj.visible !== false && ! parentInvisible ) { + + requestObjectHighlight( obj.uuid ); + + } + } ); + + // Add mouseleave handler to remove 3D highlight + elem.addEventListener( 'mouseleave', () => { + requestObjectUnhighlight(); + } ); + + container.appendChild( elem ); + + // Handle children (excluding children of renderers, as properties are shown in details) + if ( ! obj.isRenderer && obj.children && obj.children.length > 0 ) { + + // Create a container for children + const childContainer = document.createElement( 'div' ); + childContainer.className = 'children'; + container.appendChild( childContainer ); + + // Get all children and sort them by type for better organization + const children = obj.children + .map( childId => state.objects.get( childId ) ) + .filter( child => child !== undefined && child.name !== '__THREE_DEVTOOLS_HIGHLIGHT__' ) + .sort( ( a, b ) => { + + const getTypeOrder = ( obj ) => { + if ( obj.isCamera ) return 1; + if ( obj.isLight ) return 2; + if ( obj.isGroup ) return 3; + if ( obj.isMesh ) return 4; + return 5; + }; + + const aOrder = getTypeOrder( a ); + const bOrder = getTypeOrder( b ); + + return aOrder - bOrder; + + } ); + + // Render each child + children.forEach( child => { + + renderObject( child, childContainer, level + 1, parentInvisible || obj.visible === false ); + + } ); + + } + +} + +// Build the static DOM shell (called once) +function initUI() { + + const container = document.getElementById( 'scene-tree' ); + + const header = document.createElement( 'div' ); + header.className = 'header'; + header.style.display = 'flex'; + header.style.justifyContent = 'space-between'; + + const miscSpan = document.createElement( 'span' ); + miscSpan.innerHTML = '+'; + + const manifest = chrome.runtime.getManifest(); + + const manifestVersionSpan = document.createElement( 'span' ); + manifestVersionSpan.textContent = `${manifest.version}`; + manifestVersionSpan.style.opacity = '0.5'; + + header.appendChild( miscSpan ); + header.appendChild( manifestVersionSpan ); + container.appendChild( header ); + + const sectionsContainer = document.createElement( 'div' ); + sectionsContainer.className = 'sections-container'; + container.appendChild( sectionsContainer ); + + renderersSection = document.createElement( 'div' ); + renderersSection.className = 'section'; + renderersSection.style.display = 'none'; + sectionsContainer.appendChild( renderersSection ); + + scenesSection = document.createElement( 'div' ); + scenesSection.className = 'section'; + scenesSection.style.display = 'none'; + sectionsContainer.appendChild( scenesSection ); + +} + +// Update only the renderers section +function updateRenderers() { + + if ( state.renderers.size > 0 ) { + + renderersSection.style.display = ''; + renderersSection.innerHTML = '

Renderers

'; + + state.renderers.forEach( renderer => { + + renderRenderer( renderer, renderersSection ); + + } ); + + } else { + + renderersSection.style.display = 'none'; + + } + +} + +// Rebuild the scene tree only when dirty +function updateSceneTree() { + + if ( ! sceneDirty ) return; + + sceneDirty = false; + + if ( state.scenes.size > 0 ) { + + scenesSection.style.display = ''; + scenesSection.innerHTML = '

Scenes

'; + + state.scenes.forEach( scene => { + + renderObject( scene, scenesSection ); + + } ); + + } else { + + scenesSection.style.display = 'none'; + + } + +} + +// Create floating details panel +function createFloatingPanel() { + + if ( floatingPanel ) return floatingPanel; + + floatingPanel = document.createElement( 'div' ); + floatingPanel.className = 'floating-details'; + document.body.appendChild( floatingPanel ); + + return floatingPanel; + +} + +// Show floating details panel +function showFloatingDetails( objectData ) { + + const panel = createFloatingPanel(); + + // Clear previous content + panel.innerHTML = ''; + + if ( objectData.position ) { + + panel.appendChild( createVectorRow( 'Position', objectData.position ) ); + + } + + if ( objectData.rotation ) { + + panel.appendChild( createVectorRow( 'Rotation', objectData.rotation ) ); + + } + + if ( objectData.scale ) { + + panel.appendChild( createVectorRow( 'Scale', objectData.scale ) ); + + } + + // Position panel near mouse + updateFloatingPanelPosition(); + + // Show panel + panel.classList.add( 'visible' ); + +} + +// Update floating panel position +function updateFloatingPanelPosition() { + + if ( ! floatingPanel || ! floatingPanel.classList.contains( 'visible' ) ) return; + + const offset = 15; // Offset from cursor + let x = mousePosition.x + offset; + let y = mousePosition.y + offset; + + // Prevent panel from going off-screen + const panelRect = floatingPanel.getBoundingClientRect(); + const maxX = window.innerWidth - panelRect.width - 10; + const maxY = window.innerHeight - panelRect.height - 10; + + if ( x > maxX ) x = mousePosition.x - panelRect.width - offset; + if ( y > maxY ) y = mousePosition.y - panelRect.height - offset; + + floatingPanel.style.left = `${Math.max( 10, x )}px`; + floatingPanel.style.top = `${Math.max( 10, y )}px`; + +} + +// Track mouse position +document.addEventListener( 'mousemove', ( event ) => { + + mousePosition.x = event.clientX; + mousePosition.y = event.clientY; + updateFloatingPanelPosition(); + +} ); + +// Hide panel when mouse leaves the tree area +document.addEventListener( 'mouseover', ( event ) => { + + if ( floatingPanel && ! event.target.closest( '.tree-item' ) ) { + + floatingPanel.classList.remove( 'visible' ); + + } + +} ); + +// Initial UI setup +initUI(); diff --git a/devtools/screenshot.png b/devtools/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8e81eba978f4b7be9281e4f7113a4607da5dde00 GIT binary patch literal 867738 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 w5osGYzf6-aC<=j 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