1
0
Mr.doob 10 сар өмнө
parent
commit
d43d66a4dc

+ 44 - 57
devtools/README.md

@@ -1,6 +1,6 @@
 # Three.js DevTools Extension
 # 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, manipulate visibility, and monitor rendering performance.
+This Chrome DevTools extension provides debugging capabilities for Three.js applications. It allows you to inspect scenes, objects, materials, and renderers.
 
 
 ## Installation
 ## Installation
 
 
@@ -13,7 +13,7 @@ This Chrome DevTools extension provides debugging capabilities for Three.js appl
 2. **Usage**:
 2. **Usage**:
    - Open Chrome DevTools on a page using Three.js (F12 or Right-click > Inspect)
    - Open Chrome DevTools on a page using Three.js (F12 or Right-click > Inspect)
    - Click on the "Three.js" tab in DevTools
    - Click on the "Three.js" tab in DevTools
-   - The panel will automatically detect and display Three.js scenes and renderers
+   - The panel will automatically detect and display Three.js scenes and renderers found on the page.
 
 
 ## Code Flow Overview
 ## Code Flow Overview
 
 
@@ -21,91 +21,78 @@ This Chrome DevTools extension provides debugging capabilities for Three.js appl
 
 
 The extension follows a standard Chrome DevTools extension architecture:
 The extension follows a standard Chrome DevTools extension architecture:
 
 
-1. **Background Script** (`background.js`): Manages the extension lifecycle and creates the DevTools panel
-2. **DevTools Script** (`devtools.js`): Creates the panel when the DevTools window opens
-3. **Content Script** (`content-script.js`): Injects the bridge into web pages and relays messages
-4. **Injected Bridge** (`inject.js` → `bridge.js`): Creates the communication layer between Three.js and DevTools
-5. **Panel UI** (`panel/*.js`, `panel/*.html`): The DevTools panel interface
+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 context by the content script. Directly interacts with the Three.js instance, detects objects, gathers data, and communicates back via the content script.
 
 
 ### Initialization Flow
 ### Initialization Flow
 
 
-1. When a page loads, `content-script.js` injects `inject.js`
-2. `inject.js` injects `bridge.js` into the page
-3. `bridge.js` creates the `__THREE_DEVTOOLS__` global object
-4. When Three.js loads, it detects this object and sends initialization events
+1. When a page loads, `content-script.js` injects `bridge.js` into the page.
+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-initial-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`)
 ### Bridge Operation (`bridge.js`)
 
 
-The bridge acts as the communication layer between Three.js and the DevTools panel:
-
-1. **Event Management**: Creates a custom event system to handle Three.js objects
-   - Uses `DevToolsEventTarget` to manage event listeners and backlog events
-   - Events include: `observe`, `update`, `remove`, `register`
+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**:
 2. **Object Tracking**:
-   - `getObjectData()`: Extracts essential data from Three.js objects
-   - Maintains a map of all observed objects (`devTools.objects`)
-   - Automatically tracks scenes, objects, materials, and renderers
-
-3. **Scene Observation**:
-   - When Three.js sends an `observe` event for a scene, the bridge:
-     - Records the scene in `__observed_scenes`
-     - Traverses all child objects to populate the object hierarchy
-     - Sets up monitoring to track changes
-
-4. **Renderer Monitoring**:
-   - For WebGLRenderer instances:
-     - Tracks renderer properties, dimensions and draw calls
-     - Updates statistics periodically
-     - Extracts WebGL context information
+   - `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-initial-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**:
 5. **Message Handling**:
-   - Listens for messages from the panel UI
-   - Processes commands like visibility toggling and scene traversal
+   - Listens for messages from the panel (relayed via content script) like `request-initial-state`.
 
 
 ### Panel Interface (`panel/`)
 ### Panel Interface (`panel/`)
 
 
 The panel UI provides the visual representation of the Three.js objects:
 The panel UI provides the visual representation of the Three.js objects:
 
 
-1. **Tree View**: Displays hierarchical representation of scenes and objects
-2. **Properties Panel**: Shows detailed properties of selected objects
-3. **Performance Monitoring**: Displays renderer statistics and WebGL information
+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
 ## Key Features
 
 
-- **Scene Hierarchy Visualization**: Browse the complete scene graph
-- **Object Inspection**: View mesh, material, and geometry properties
-- **Visibility Control**: Toggle visibility of scene objects
-- **Renderer Statistics**: Monitor draw calls, triangles, and memory usage
-- **WebGL Information**: View context and capabilities information
+- **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
 ## Communication Flow
 
 
-1. **Three.js → Bridge**: Three.js detects the `__THREE_DEVTOOLS__` object and sends events
-2. **Bridge → Content Script**: Bridge posts messages to window
-3. **Content Script → DevTools Panel**: Content script relays messages to the DevTools panel
-4. **DevTools Panel → Content Script**: Panel sends commands back via messaging
-5. **Content Script → Bridge**: Content script relays commands to the bridge
-6. **Bridge → Three.js**: Bridge manipulates Three.js objects directly
+1. **Panel ↔ Background ↔ Content Script**: Standard extension messaging for panel initialization and state requests (`init`, `request-initial-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
 ## Key Components
 
 
-- **DevToolsEventTarget**: Custom event system with backlogging for async loading
-- **Object Observation**: Tracks Three.js objects and their properties
-- **Scene Monitoring**: Periodically checks for changes in observed scenes
-- **WebGLRenderer Monitoring**: Tracks performance statistics for renderers
-- **Visibility Toggle**: Allows showing/hiding objects in the scene
+- **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
 ## 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 sends events about scenes, renderers, and other objects to the extension.
+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 then processes these events, organizes the data, and provides a clean interface for the DevTools panel to display and interact with.
+The bridge script listens for these events, organizes the data, and provides it to the DevTools panel.
 
 
 ## Development
 ## Development
 
 
 To modify the extension:
 To modify the extension:
 
 
-1. Edit the relevant files in the `devtools` directory
-2. Reload the extension in `chrome://extensions/` by clicking the refresh icon
-3. Reopen DevTools to see your changes
+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.

+ 0 - 61
devtools/bridge.js

@@ -224,7 +224,6 @@ if (!window.__THREE_DEVTOOLS__) {
 				observedRenderers.push(obj);
 				observedRenderers.push(obj);
 				devTools.objects.set(obj.uuid, data); // Store locally
 				devTools.objects.set(obj.uuid, data); // Store locally
 				dispatchEvent('renderer', data); // Send to panel as 'renderer'
 				dispatchEvent('renderer', data); // Send to panel as 'renderer'
-				startRendererMonitoring(obj);
 			}
 			}
 		} 
 		} 
 		// Handle Scenes via batch
 		// Handle Scenes via batch
@@ -254,7 +253,6 @@ if (!window.__THREE_DEVTOOLS__) {
 			
 			
 			// Dispatch the batch as 'scene'
 			// Dispatch the batch as 'scene'
 			dispatchEvent('scene', { sceneUuid: obj.uuid, objects: batchObjects });
 			dispatchEvent('scene', { sceneUuid: obj.uuid, objects: batchObjects });
-			startSceneMonitoring(obj); // Keep this if it holds scene-specific logic later
 		} 
 		} 
 		// Ignore other object types arriving directly via 'observe'? 
 		// Ignore other object types arriving directly via 'observe'? 
 		// They should be discovered via scene traversal.
 		// They should be discovered via scene traversal.
@@ -313,52 +311,6 @@ if (!window.__THREE_DEVTOOLS__) {
 		};
 		};
 	}
 	}
 
 
-	// Function to start renderer monitoring
-	function startRendererMonitoring(renderer) {
-		// Function to monitor renderer properties
-		function monitorRendererProperties() {
-			try {
-				const data = devTools.objects.get( renderer.uuid );
-				if ( ! data ) {
-					return;
-				}
-
-				const oldProperties = data.properties;
-				const newProperties = getRendererProperties( renderer );
-
-				// Compare relevant properties directly for changes
-				const changed = (
-					!oldProperties || // Update if old properties don't exist yet
-					oldProperties.width !== newProperties.width ||
-					oldProperties.height !== newProperties.height ||
-					oldProperties.drawingBufferWidth !== newProperties.drawingBufferWidth ||
-					oldProperties.drawingBufferHeight !== newProperties.drawingBufferHeight ||
-					JSON.stringify(oldProperties.info?.render) !== JSON.stringify(newProperties.info?.render) || // Compare render stats
-					JSON.stringify(oldProperties.info?.memory) !== JSON.stringify(newProperties.info?.memory) // Compare memory stats
-				);
-
-				if ( changed ) {
-					data.properties = newProperties;
-					dispatchEvent( 'update', data );
-				} else {
-				}
-
-			} catch ( error ) {
-
-				// If we get an "Extension context invalidated" error, stop monitoring
-				if ( error.message.includes( 'Extension context invalidated' ) ) {
-					devTools.reset();
-					return;
-				}
-
-				console.warn( 'DevTools: Error in renderer monitoring:', error );
-
-			}
-		}
-
-		// TODO: Trigger monitorRendererProperties some other way, e.g., on demand or via events?
-	}
-
 	// Start periodic renderer checks
 	// Start periodic renderer checks
 	// console.log('DevTools: Starting periodic renderer checks');
 	// console.log('DevTools: Starting periodic renderer checks');
 
 
@@ -522,19 +474,6 @@ if (!window.__THREE_DEVTOOLS__) {
 		}
 		}
 	}
 	}
 
 
-	// Function to start scene monitoring
-	function startSceneMonitoring(scene) {
-		// Keep track of known object UUIDs for this scene (excluding renderers)
-		const knownObjectUUIDs = new Set();
-		devTools.objects.forEach((obj, uuid) => {
-			if (!obj.isRenderer) {
-				knownObjectUUIDs.add(uuid);
-			}
-		});
-
-		// TODO: Trigger scene updates some other way?
-	}
-
 	// Function to manually reload scene objects
 	// Function to manually reload scene objects
 	function reloadSceneObjects(scene) {
 	function reloadSceneObjects(scene) {
 		// console.log('DevTools: Manually reloading scene objects for scene:', scene.uuid);
 		// console.log('DevTools: Manually reloading scene objects for scene:', scene.uuid);

+ 0 - 35
devtools/content-script.js

@@ -170,41 +170,6 @@ function handleIframeMessage( event ) {
 
 
 }
 }
 
 
-// Handle messages from devtools
-function handleDevtoolsMessage( message, sender, sendResponse ) {
-
-	// Forward traverse requests to both main page and iframes
-	if ( message.name === 'traverse' || message.name === 'reload-scene' || message.name === 'visibility' ) {
-
-		// console.log( 'Content script: Forwarding message to page:', message );
-		window.postMessage( message, '*' );
-
-		// Also try to forward to all iframes
-		const iframes = document.querySelectorAll( 'iframe' );
-		iframes.forEach( iframe => {
-
-			try {
-
-				iframe.contentWindow.postMessage( message, '*' );
-
-			} catch ( e ) {
-
-				// Ignore cross-origin iframe errors
-
-			}
-
-		} );
-
-		// Send immediate response to avoid "message channel closed" error
-		sendResponse( { received: true } );
-
-	}
-
-	// Return false to indicate synchronous handling
-	return false;
-
-}
-
 // Listener for messages forwarded from the background script (originating from panel)
 // Listener for messages forwarded from the background script (originating from panel)
 function handleBackgroundMessage( message, sender, sendResponse ) {
 function handleBackgroundMessage( message, sender, sendResponse ) {
 
 

+ 1 - 2
devtools/panel/panel.js

@@ -261,10 +261,9 @@ function updateRendererProperties(renderer, propsContainer) {
 // Function to get an object icon based on its type
 // Function to get an object icon based on its type
 function getObjectIcon(obj) {
 function getObjectIcon(obj) {
 	if (obj.isScene) return '🌍';
 	if (obj.isScene) return '🌍';
-	if (obj.isRenderer) return '🎨';
 	if (obj.isCamera) return '📷';
 	if (obj.isCamera) return '📷';
 	if (obj.isLight) return '💡';
 	if (obj.isLight) return '💡';
-	if (obj.isMesh) return obj.materialType === 'MeshBasicMaterial' ? '⬜' : '🔷';
+	if (obj.isMesh) return '🔷';
 	if (obj.type === 'Group') return '📁';
 	if (obj.type === 'Group') return '📁';
 	return '📦';
 	return '📦';
 }
 }

粤ICP备19079148号