Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions examples/jsm/inspector/Inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,6 @@ class Inspector extends RendererInspector {

this.parameters.show();

if ( this.parameters.isDetached === false ) {

this.profiler.setActiveTab( this.parameters.id );

}

}

return this.parameters.createGroup( name );
Expand Down
210 changes: 64 additions & 146 deletions examples/jsm/inspector/ui/Profiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ export class Profiler {
// Set initial position class
this.panel.classList.add( `position-${this.position}` );

if ( this.position === 'right' ) {

this.toggleButton.classList.add( 'position-right' );
this.miniPanel.classList.add( 'position-right' );

}

}

setupResizing() {
Expand Down Expand Up @@ -416,7 +423,12 @@ export class Profiler {

this.setupTabDragAndDrop( tab );

this.tabsContainer.appendChild( tab.button );
if ( ! tab.builtin ) {

this.tabsContainer.appendChild( tab.button );

}

this.contentWrapper.appendChild( tab.content );

// Apply the current visibility state to the DOM elements
Expand Down Expand Up @@ -473,89 +485,51 @@ export class Profiler {

e.stopPropagation(); // Prevent toggle panel from triggering

const isPanelVisible = this.panel.classList.contains( 'visible' );

if ( isPanelVisible ) {
// Toggle mini-panel for this tab
const isCurrentlyActive = miniContent.style.display !== 'none' && miniContent.children.length > 0;

// Panel is visible - navigate to tab
if ( ! tab.isVisible ) {

tab.show();

}
// Hide all other mini-panel contents
this.miniPanel.querySelectorAll( '.mini-panel-content' ).forEach( content => {

if ( tab.isDetached ) {
content.style.display = 'none';

// If tab is detached, just bring its window to front
if ( tab.detachedWindow ) {
} );

this.bringWindowToFront( tab.detachedWindow.panel );
// Remove active state from all builtin buttons
this.builtinTabsContainer.querySelectorAll( '.builtin-tab-btn' ).forEach( btn => {

}
btn.classList.remove( 'active' );

} else {
} );

// Activate the tab
this.setActiveTab( tab.id );
if ( isCurrentlyActive ) {

}
// Toggle off - hide mini-panel
this.miniPanel.classList.remove( 'visible' );
miniContent.style.display = 'none';

} else {

// Panel is hidden - toggle mini-panel for this tab
const isCurrentlyActive = miniContent.style.display !== 'none' && miniContent.children.length > 0;
// Toggle on - show mini-panel with this tab's content
builtinButton.classList.add( 'active' );

// Hide all other mini-panel contents
this.miniPanel.querySelectorAll( '.mini-panel-content' ).forEach( content => {

content.style.display = 'none';

} );
// Move actual content to mini-panel (not clone) if not already there
if ( ! miniContent.firstChild ) {

// Remove active state from all builtin buttons
this.builtinTabsContainer.querySelectorAll( '.builtin-tab-btn' ).forEach( btn => {
const actualContent = tab.content.querySelector( '.list-scroll-wrapper' ) || tab.content.firstElementChild;

btn.classList.remove( 'active' );

} );

if ( isCurrentlyActive ) {

// Toggle off - hide mini-panel and move content back
this.miniPanel.classList.remove( 'visible' );
miniContent.style.display = 'none';

// Move content back to main panel
if ( miniContent.firstChild ) {

tab.content.appendChild( miniContent.firstChild );

}

} else {

// Toggle on - show mini-panel with this tab's content
builtinButton.classList.add( 'active' );

// Move actual content to mini-panel (not clone) if not already there
if ( ! miniContent.firstChild ) {

const actualContent = tab.content.querySelector( '.list-scroll-wrapper' ) || tab.content.firstElementChild;

if ( actualContent ) {

miniContent.appendChild( actualContent );
if ( actualContent ) {

}
miniContent.appendChild( actualContent );

}

// Show after content is moved
miniContent.style.display = 'block';
this.miniPanel.classList.add( 'visible' );

}

// Show after content is moved
miniContent.style.display = 'block';
this.miniPanel.classList.add( 'visible' );

}

};
Expand Down Expand Up @@ -1471,87 +1445,11 @@ export class Profiler {
togglePanel() {

this.panel.classList.toggle( 'visible' );
this.toggleButton.classList.toggle( 'hidden' );
this.toggleButton.classList.toggle( 'panel-open' );
this.miniPanel.classList.toggle( 'panel-open' );

const isVisible = this.panel.classList.contains( 'visible' );

if ( isVisible ) {

// Save mini-panel state before hiding
this.savedMiniPanelState = {
isVisible: this.miniPanel.classList.contains( 'visible' ),
activeTabId: null,
contentMap: {}
};

// Find which tab was active in mini-panel
this.miniPanel.querySelectorAll( '.mini-panel-content' ).forEach( content => {

if ( content.style.display !== 'none' && content.firstChild ) {

// Find the tab that owns this content
Object.values( this.tabs ).forEach( tab => {

if ( tab.miniContent === content ) {

this.savedMiniPanelState.activeTabId = tab.id;
// Move content back to main panel
tab.content.appendChild( content.firstChild );

}

} );

}

} );

// Hide mini-panel temporarily
this.miniPanel.classList.remove( 'visible' );

// Hide all mini-panel contents
this.miniPanel.querySelectorAll( '.mini-panel-content' ).forEach( content => {

content.style.display = 'none';

} );

// Remove active state from builtin buttons
this.builtinTabsContainer.querySelectorAll( '.builtin-tab-btn' ).forEach( btn => {

btn.classList.remove( 'active' );

} );

} else {

// Restore mini-panel state when minimizing
if ( this.savedMiniPanelState && this.savedMiniPanelState.isVisible && this.savedMiniPanelState.activeTabId ) {

const tab = this.tabs[ this.savedMiniPanelState.activeTabId ];

if ( tab && tab.miniContent && tab.builtinButton ) {

// Restore mini-panel visibility
this.miniPanel.classList.add( 'visible' );
tab.miniContent.style.display = 'block';
tab.builtinButton.classList.add( 'active' );

// Move content back to mini-panel
const actualContent = tab.content.querySelector( '.list-scroll-wrapper, .profiler-content > *' );

if ( actualContent ) {

tab.miniContent.appendChild( actualContent );

}

}

}

}

this.detachedWindows.forEach( detachedWindow => {

if ( isVisible ) {
Expand Down Expand Up @@ -1598,6 +1496,8 @@ export class Profiler {
// Apply right position styles
this.panel.classList.remove( 'position-bottom' );
this.panel.classList.add( 'position-right' );
this.toggleButton.classList.add( 'position-right' );
this.miniPanel.classList.add( 'position-right' );
this.panel.style.bottom = '';
this.panel.style.top = '0';
this.panel.style.right = '0';
Expand Down Expand Up @@ -1626,6 +1526,8 @@ export class Profiler {
// Apply bottom position styles
this.panel.classList.remove( 'position-right' );
this.panel.classList.add( 'position-bottom' );
this.toggleButton.classList.remove( 'position-right' );
this.miniPanel.classList.remove( 'position-right' );
this.panel.style.top = '';
this.panel.style.right = '';
this.panel.style.bottom = '0';
Expand Down Expand Up @@ -1696,7 +1598,11 @@ export class Profiler {

try {

localStorage.setItem( 'profiler-layout', JSON.stringify( layout ) );
const savedData = localStorage.getItem( 'threejs-inspector' );
const data = JSON.parse( savedData || '{}' );

data.layout = layout;
localStorage.setItem( 'threejs-inspector', JSON.stringify( data ) );

} catch ( e ) {

Expand All @@ -1710,11 +1616,14 @@ export class Profiler {

try {

const savedLayout = localStorage.getItem( 'profiler-layout' );
const savedData = localStorage.getItem( 'threejs-inspector' );

if ( ! savedData ) return;

if ( ! savedLayout ) return;
const parsedData = JSON.parse( savedData );
const layout = parsedData.layout;

const layout = JSON.parse( savedLayout );
if ( ! layout ) return;

// Constrain detached tabs positions to current screen bounds
if ( layout.detachedTabs && layout.detachedTabs.length > 0 ) {
Expand Down Expand Up @@ -1827,6 +1736,8 @@ export class Profiler {

this.panel.classList.remove( 'position-bottom' );
this.panel.classList.add( 'position-right' );
this.toggleButton.classList.add( 'position-right' );
this.miniPanel.classList.add( 'position-right' );
this.panel.style.bottom = '';
this.panel.style.top = '0';
this.panel.style.right = '0';
Expand Down Expand Up @@ -1863,6 +1774,13 @@ export class Profiler {
// Update panel size after loading layout
this.updatePanelSize();

// Ensure initial open state applies to mini panel as well
if ( this.panel.classList.contains( 'visible' ) ) {

this.miniPanel.classList.add( 'panel-open' );

}

} catch ( e ) {

console.warn( 'Failed to load profiler layout:', e );
Expand Down
27 changes: 24 additions & 3 deletions examples/jsm/inspector/ui/Style.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,25 @@ export class Style {
font-family: var(--font-family);
}

#profiler-toggle.position-right.panel-open {
right: auto;
left: 15px;
border-radius: 6px 12px 12px 6px;
flex-direction: row-reverse;
}

#profiler-toggle.position-right.panel-open #builtin-tabs-container {
border-right: none;
border-left: 1px solid #262636;
}

#profiler-toggle:hover {
border-color: var(--accent-color);
}

#profiler-toggle.hidden {
opacity: 0;
pointer-events: none;
#profiler-toggle.panel-open #toggle-icon {
background-color: rgba(0, 170, 255, 0.2);
color: var(--accent-color);
}

#toggle-icon {
Expand All @@ -74,6 +86,10 @@ export class Style {
background-color: rgba(255, 255, 255, 0.05);
}

#profiler-toggle.panel-open:hover #toggle-icon {
background-color: rgba(0, 170, 255, 0.3);
}

.toggle-separator {
width: 1px;
background-color: var(--profiler-border);
Expand Down Expand Up @@ -166,6 +182,11 @@ export class Style {
transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

#profiler-mini-panel.position-right.panel-open {
right: auto;
left: 15px;
}

#profiler-mini-panel.visible {
display: block;
opacity: 1;
Expand Down