-
-
Notifications
You must be signed in to change notification settings - Fork 35.9k
Added new DevTools #30870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Added new DevTools #30870
Conversation
We can now show the object transforms. Screen.Recording.2025-07-13.at.5.44.41.PM_.mov |
This is amazing! |
Some times is not easy to see where in the page the renderer is... Screen.Recording.2025-07-18.at.12.08.59.PM.mov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a new and simpler Three.js DevTools extension for Chrome, providing debugging capabilities for Three.js applications. The extension creates a DevTools panel that allows inspection of scenes, objects, and renderers with real-time updates and interactive features like canvas scrolling and floating object details.
Key changes include:
- Complete Chrome extension architecture with background script, content script, and DevTools panel
- Bridge script for direct Three.js integration and object monitoring
- Interactive UI with collapsible renderer details and floating object inspection panels
Reviewed Changes
Copilot reviewed 10 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
File | Description |
---|---|
devtools/panel/panel.js | Main panel JavaScript implementing UI rendering, object hierarchy display, and floating details functionality |
devtools/panel/panel.html | Simple HTML structure for the DevTools panel |
devtools/panel/panel.css | Comprehensive styling with light/dark theme support and responsive design |
devtools/manifest.json | Chrome extension manifest defining permissions and entry points |
devtools/index.html | DevTools page entry point |
devtools/devtools.js | Script to create the Three.js panel in Chrome DevTools |
devtools/content-script.js | Content script handling bridge injection and message relay |
devtools/bridge.js | Bridge script for Three.js integration and object observation |
devtools/background.js | Background service worker managing extension lifecycle and communications |
devtools/README.md | Comprehensive documentation of extension architecture and usage |
let objectCount = - 1; | ||
function countObjects( uuid ) { | ||
|
||
const object = state.objects.get( uuid ); | ||
if ( object ) { | ||
|
||
objectCount ++; // Increment count for the object itself |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting the object count at -1 and incrementing is confusing. Consider starting at 0 and adjusting the logic or adding a comment explaining why -1 is used as the initial value.
let objectCount = - 1; | |
function countObjects( uuid ) { | |
const object = state.objects.get( uuid ); | |
if ( object ) { | |
objectCount ++; // Increment count for the object itself | |
let objectCount = 0; | |
function countObjects( uuid ) { | |
const object = state.objects.get( uuid ); | |
if ( object ) { | |
objectCount++; // Increment count for the object itself |
Copilot uses AI. Check for mistakes.
function generateUUID() { | ||
|
||
const array = new Uint8Array( 16 ); | ||
crypto.getRandomValues( array ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generateUUID function doesn't handle cases where crypto.getRandomValues might not be available (e.g., in insecure contexts). Consider adding error handling or a fallback method.
crypto.getRandomValues( array ); | |
try { | |
if (crypto && typeof crypto.getRandomValues === 'function') { | |
crypto.getRandomValues( array ); | |
} else { | |
// Fallback to Math.random for insecure contexts | |
for (let i = 0; i < array.length; i++) { | |
array[i] = Math.floor(Math.random() * 256); | |
} | |
} | |
} catch (error) { | |
// Fallback in case of unexpected errors | |
for (let i = 0; i < array.length; i++) { | |
array[i] = Math.floor(Math.random() * 256); | |
} | |
} |
Copilot uses AI. Check for mistakes.
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( '' ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UUID generation logic is complex and hard to read. Consider breaking this into multiple lines or using a more readable approach with clear variable names for better maintainability.
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( '' ); | |
// Generate 16 random bytes | |
const randomBytes = new Uint8Array( 16 ); | |
crypto.getRandomValues( randomBytes ); | |
// Set the UUID version to 4 (0100 in binary) | |
const versionByte = ( randomBytes[ 6 ] & 0x0f ) | 0x40; | |
randomBytes[ 6 ] = versionByte; | |
// Set the UUID variant to 10 (binary) | |
const variantByte = ( randomBytes[ 8 ] & 0x3f ) | 0x80; | |
randomBytes[ 8 ] = variantByte; | |
// Convert bytes to hexadecimal and format as UUID | |
const uuid = randomBytes.map( ( byte, index ) => { | |
const hex = byte.toString( 16 ).padStart( 2, '0' ); | |
return ( index === 4 || index === 6 || index === 8 || index === 10 ? '-' : '' ) + hex; | |
} ).join( '' ); | |
return uuid; |
Copilot uses AI. Check for mistakes.
header.style.justifyContent = 'space-between'; // Align items left and right | ||
|
||
const miscSpan = document.createElement( 'span' ); | ||
miscSpan.innerHTML = '<a href="https://docs.google.com/forms/d/e/1FAIpQLSdw1QcgXNiECYiPx6k0vSQRiRe0FmByrrojV4fgeL5zzXIiCw/viewform?usp=preview" target="_blank">+</a>'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using innerHTML with external URLs could pose security risks. Consider using textContent and addEventListener instead of inline HTML with external links.
miscSpan.innerHTML = '<a href="https://docs.google.com/forms/d/e/1FAIpQLSdw1QcgXNiECYiPx6k0vSQRiRe0FmByrrojV4fgeL5zzXIiCw/viewform?usp=preview" target="_blank">+</a>'; | |
const link = document.createElement('a'); | |
link.href = 'https://docs.google.com/forms/d/e/1FAIpQLSdw1QcgXNiECYiPx6k0vSQRiRe0FmByrrojV4fgeL5zzXIiCw/viewform?usp=preview'; | |
link.target = '_blank'; | |
link.textContent = '+'; | |
miscSpan.appendChild(link); |
Copilot uses AI. Check for mistakes.
function traverseForBatch( currentObj ) { | ||
|
||
if ( ! currentObj || ! currentObj.uuid || processedUUIDs.has( currentObj.uuid ) ) return; | ||
processedUUIDs.add( currentObj.uuid ); | ||
|
||
const objectData = getObjectData( currentObj ); | ||
if ( objectData ) { | ||
|
||
batchObjects.push( objectData ); | ||
devTools.objects.set( currentObj.uuid, objectData ); // Update local cache during batch creation | ||
|
||
} | ||
|
||
// Process children | ||
if ( currentObj.children && Array.isArray( currentObj.children ) ) { | ||
|
||
currentObj.children.forEach( child => traverseForBatch( child ) ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recursive traverseForBatch function could cause stack overflow for deeply nested scene graphs. Consider implementing an iterative approach using a stack or queue for better performance and safety.
function traverseForBatch( currentObj ) { | |
if ( ! currentObj || ! currentObj.uuid || processedUUIDs.has( currentObj.uuid ) ) return; | |
processedUUIDs.add( currentObj.uuid ); | |
const objectData = getObjectData( currentObj ); | |
if ( objectData ) { | |
batchObjects.push( objectData ); | |
devTools.objects.set( currentObj.uuid, objectData ); // Update local cache during batch creation | |
} | |
// Process children | |
if ( currentObj.children && Array.isArray( currentObj.children ) ) { | |
currentObj.children.forEach( child => traverseForBatch( child ) ); | |
function traverseForBatch( rootObj ) { | |
const stack = [ rootObj ]; // Initialize stack with the root object | |
while ( stack.length > 0 ) { | |
const currentObj = stack.pop(); // Pop the next object to process | |
if ( ! currentObj || ! currentObj.uuid || processedUUIDs.has( currentObj.uuid ) ) continue; | |
processedUUIDs.add( currentObj.uuid ); | |
const objectData = getObjectData( currentObj ); | |
if ( objectData ) { | |
batchObjects.push( objectData ); | |
devTools.objects.set( currentObj.uuid, objectData ); // Update local cache during batch creation | |
} | |
// Add children to the stack for processing | |
if ( currentObj.children && Array.isArray( currentObj.children ) ) { | |
stack.push( ...currentObj.children ); | |
} |
Copilot uses AI. Check for mistakes.
Description
Started a new and simpler Three.js DevTools.