@@ -20,7 +20,7 @@ function createPropertyRow(label, value) {
2020
2121 const labelSpan = document . createElement ( 'span' ) ;
2222 labelSpan . className = 'property-label' ;
23- labelSpan . textContent = `${ label } : ` ;
23+ labelSpan . textContent = `${ label } ` ;
2424 labelSpan . style . marginRight = '10px' ;
2525 labelSpan . style . whiteSpace = 'nowrap' ;
2626
@@ -37,14 +37,34 @@ function createPropertyRow(label, value) {
3737 return row ;
3838}
3939
40+ function createVectorRow ( label , vector ) {
41+ const row = document . createElement ( 'div' ) ;
42+ row . className = 'property-row' ;
43+ row . style . marginBottom = '2px' ;
44+
45+ // Pad label to ensure consistent alignment
46+ const paddedLabel = label . padEnd ( 16 , ' ' ) ; // Pad to 16 characters
47+ const content = `${ paddedLabel } ${ vector . x . toFixed ( 3 ) } \t${ vector . y . toFixed ( 3 ) } \t${ vector . z . toFixed ( 3 ) } ` ;
48+ row . textContent = content ;
49+ row . style . fontFamily = 'monospace' ;
50+ row . style . whiteSpace = 'pre' ;
51+
52+ return row ;
53+ }
54+
4055// --- State ---
4156const state = {
4257 revision : null ,
4358 scenes : new Map ( ) ,
4459 renderers : new Map ( ) ,
45- objects : new Map ( )
60+ objects : new Map ( ) ,
61+ selectedObject : null
4662} ;
4763
64+ // Floating details panel
65+ let floatingPanel = null ;
66+ let mousePosition = { x : 0 , y : 0 } ;
67+
4868
4969// Create a connection to the background page
5070const backgroundPageConnection = chrome . runtime . connect ( {
@@ -80,6 +100,15 @@ backgroundPageConnection.onDisconnect.addListener( () => {
80100
81101} ) ;
82102
103+ // Function to request object details from the bridge
104+ function requestObjectDetails ( uuid ) {
105+ backgroundPageConnection . postMessage ( {
106+ name : 'request-object-details' ,
107+ uuid : uuid ,
108+ tabId : chrome . devtools . inspectedWindow . tabId
109+ } ) ;
110+ }
111+
83112
84113// Store renderer collapse states
85114const rendererCollapsedState = new Map ( ) ;
@@ -98,6 +127,13 @@ function clearState() {
98127
99128 }
100129
130+ // Hide floating panel
131+ if ( floatingPanel ) {
132+
133+ floatingPanel . classList . remove ( 'visible' ) ;
134+
135+ }
136+
101137}
102138
103139// Listen for messages from the background page
@@ -139,6 +175,13 @@ function handleThreeEvent( message ) {
139175
140176 break ;
141177
178+ // Handle object details response
179+ case 'object-details' :
180+ state . selectedObject = message . detail ;
181+ console . log ( 'Panel: Received object details:' , message . detail ) ;
182+ showFloatingDetails ( message . detail ) ;
183+ break ;
184+
142185 // Handle a batch of objects for a specific scene
143186 case 'scene' :
144187 const { sceneUuid, objects : batchObjects } = message . detail ;
@@ -376,6 +419,13 @@ function renderObject( obj, container, level = 0 ) {
376419 }
377420
378421 elem . innerHTML = labelContent ;
422+
423+ // Add mouseover handler to request object details
424+ elem . addEventListener ( 'mouseover' , ( event ) => {
425+ event . stopPropagation ( ) ; // Prevent bubbling to parent elements
426+ requestObjectDetails ( obj . uuid ) ;
427+ } ) ;
428+
379429 container . appendChild ( elem ) ;
380430
381431 // Handle children (excluding children of renderers, as properties are shown in details)
@@ -477,8 +527,98 @@ function updateUI() {
477527
478528 }
479529
530+
480531}
481532
533+ // Create floating details panel
534+ function createFloatingPanel ( ) {
535+
536+ if ( floatingPanel ) return floatingPanel ;
537+
538+ floatingPanel = document . createElement ( 'div' ) ;
539+ floatingPanel . className = 'floating-details' ;
540+ document . body . appendChild ( floatingPanel ) ;
541+
542+ return floatingPanel ;
543+
544+ }
545+
546+ // Show floating details panel
547+ function showFloatingDetails ( objectData ) {
548+
549+ const panel = createFloatingPanel ( ) ;
550+
551+ // Clear previous content
552+ panel . innerHTML = '' ;
553+
554+ if ( objectData . position ) {
555+
556+ panel . appendChild ( createVectorRow ( 'Position' , objectData . position ) ) ;
557+
558+ }
559+
560+ if ( objectData . rotation ) {
561+
562+ panel . appendChild ( createVectorRow ( 'Rotation' , objectData . rotation ) ) ;
563+
564+ }
565+
566+ if ( objectData . scale ) {
567+
568+ panel . appendChild ( createVectorRow ( 'Scale' , objectData . scale ) ) ;
569+
570+ }
571+
572+ // Position panel near mouse
573+ updateFloatingPanelPosition ( ) ;
574+
575+ // Show panel
576+ panel . classList . add ( 'visible' ) ;
577+
578+ }
579+
580+ // Update floating panel position
581+ function updateFloatingPanelPosition ( ) {
582+
583+ if ( ! floatingPanel || ! floatingPanel . classList . contains ( 'visible' ) ) return ;
584+
585+ const offset = 15 ; // Offset from cursor
586+ let x = mousePosition . x + offset ;
587+ let y = mousePosition . y + offset ;
588+
589+ // Prevent panel from going off-screen
590+ const panelRect = floatingPanel . getBoundingClientRect ( ) ;
591+ const maxX = window . innerWidth - panelRect . width - 10 ;
592+ const maxY = window . innerHeight - panelRect . height - 10 ;
593+
594+ if ( x > maxX ) x = mousePosition . x - panelRect . width - offset ;
595+ if ( y > maxY ) y = mousePosition . y - panelRect . height - offset ;
596+
597+ floatingPanel . style . left = `${ Math . max ( 10 , x ) } px` ;
598+ floatingPanel . style . top = `${ Math . max ( 10 , y ) } px` ;
599+
600+ }
601+
602+ // Track mouse position
603+ document . addEventListener ( 'mousemove' , ( event ) => {
604+
605+ mousePosition . x = event . clientX ;
606+ mousePosition . y = event . clientY ;
607+ updateFloatingPanelPosition ( ) ;
608+
609+ } ) ;
610+
611+ // Hide panel when mouse leaves the tree area
612+ document . addEventListener ( 'mouseover' , ( event ) => {
613+
614+ if ( floatingPanel && ! event . target . closest ( '.tree-item' ) ) {
615+
616+ floatingPanel . classList . remove ( 'visible' ) ;
617+
618+ }
619+
620+ } ) ;
621+
482622// Initial UI update
483623clearState ( ) ;
484624updateUI ( ) ;
0 commit comments