فهرست منبع

Inspector: Added storage settings and info feature (#33571)

sunag 1 ماه پیش
والد
کامیت
aeb668f75f

+ 14 - 13
examples/jsm/inspector/Inspector.js

@@ -466,7 +466,7 @@ class Inspector extends RendererInspector {
 
 		if ( this.displayCycle.text.needsUpdate ) {
 
-			setText( this.profiler.toggleButton.querySelector('.fps-counter'), this.fps.toFixed() );
+			setText( this.profiler.toggleButton.querySelector( '.fps-counter' ), this.fps.toFixed() );
 
 			this.performance.updateText( this, frame );
 			this.memory.updateText( this );
@@ -498,25 +498,21 @@ class Inspector extends RendererInspector {
 
 	}
 
-	static getItem( id ) {
+}
 
-		console.warn( 'Inspector.getItem is deprecated. Use getItem directly instead.' );
-		return getItem( id );
+function getItem( id ) {
 
-	}
+	const data = JSON.parse( localStorage.getItem( 'threejs-inspector' ) || '{}' );
 
-	static setItem( id, state ) {
+	if ( data.version !== REVISION ||
+		 data.settings && ( data.settings.storage === 'url' && data.settings.url !== location.href ) ) {
 
-		console.warn( 'Inspector.setItem is deprecated. Use setItem directly instead.' );
-		setItem( id, state );
+		localStorage.removeItem( 'threejs-inspector' );
 
-	}
+		return {};
 
-}
-
-function getItem( id ) {
+	}
 
-	const data = JSON.parse( localStorage.getItem( 'threejs-inspector' ) || '{}' );
 	return data[ id ] || {};
 
 }
@@ -535,6 +531,11 @@ function setItem( id, state ) {
 
 	}
 
+	data.settings = data.settings || {};
+	data.settings.url = data.settings.url || location.href;
+	data.settings.storage = data.settings.storage || 'url';
+	data.version = REVISION;
+
 	localStorage.setItem( 'threejs-inspector', JSON.stringify( data ) );
 
 }

+ 88 - 2
examples/jsm/inspector/tabs/Parameters.js

@@ -66,16 +66,90 @@ class ParametersGroup {
 
 	}
 
+	_addInfo( editor, itemNode ) {
+
+		editor.info = ( text ) => {
+
+			let infoIcon = itemNode.querySelector( '.info-icon' );
+
+			if ( ! infoIcon ) {
+
+				infoIcon = document.createElement( 'span' );
+				infoIcon.className = 'info-icon';
+				infoIcon.textContent = 'i';
+
+				itemNode.appendChild( infoIcon );
+
+				infoIcon.addEventListener( 'mouseenter', () => {
+
+					const container = infoIcon.closest( '.three-inspector' ) || document.body;
+					let tooltip = container.querySelector( '.three-inspector-info-tooltip' );
+
+					if ( ! tooltip ) {
+
+						tooltip = document.createElement( 'div' );
+						tooltip.className = 'info-tooltip three-inspector-info-tooltip';
+						container.appendChild( tooltip );
+
+					}
+
+					const html = text.trim().replace( /### (.*?)(?:\r?\n|$)/g, '<h3>$1</h3>' )
+								   .replace( /\*\*(.*?)\*\*/g, '<strong>$1</strong>' )
+								   .replace( /\n/g, '<br/>' );
+
+					tooltip.innerHTML = html;
+
+					const rect = infoIcon.getBoundingClientRect();
+
+					tooltip.style.left = ( rect.left + rect.width / 2 ) + 'px';
+					tooltip.style.top = ( rect.top - 8 ) + 'px';
+
+					tooltip.style.opacity = '1';
+					tooltip.style.visibility = 'visible';
+
+				} );
+
+				infoIcon.addEventListener( 'mouseleave', () => {
+
+					const container = infoIcon.closest( '.three-inspector' ) || document.body;
+					const tooltip = container.querySelector( '.three-inspector-info-tooltip' );
+					if ( tooltip ) {
+
+						tooltip.style.opacity = '0';
+						tooltip.style.visibility = 'hidden';
+
+					}
+
+				} );
+
+			}
+
+			return editor;
+
+		};
+
+	}
+
 	_addParameter( object, property, editor, subItem ) {
 
 		editor.name = ( name ) => {
 
-			subItem.data[ 0 ].textContent = name;
+			if ( subItem.data[ 0 ].childNodes.length > 0 && subItem.data[ 0 ].firstChild.nodeType === 3 /* Node.TEXT_NODE */ ) {
+
+				subItem.data[ 0 ].firstChild.textContent = name;
+
+			} else {
+
+				subItem.data[ 0 ].insertBefore( document.createTextNode( name ), subItem.data[ 0 ].firstChild );
+
+			}
 
 			return editor;
 
 		};
 
+		this._addInfo( editor, subItem.data[ 0 ] );
+
 		editor.listen = () => {
 
 			const update = () => {
@@ -328,12 +402,24 @@ class ParametersGroup {
 
 		editor.name = ( name ) => {
 
-			editor.domElement.childNodes[ 0 ].textContent = name;
+			const buttonNode = editor.domElement.childNodes[ 0 ];
+
+			if ( buttonNode.childNodes.length > 0 && buttonNode.firstChild.nodeType === 3 /* Node.TEXT_NODE */ ) {
+
+				buttonNode.firstChild.textContent = name;
+
+			} else {
+
+				buttonNode.insertBefore( document.createTextNode( name ), buttonNode.firstChild );
+
+			}
 
 			return editor;
 
 		};
 
+		this._addInfo( editor, editor.domElement.childNodes[ 0 ] );
+
 		this._registerParameter( object, property, editor, subItem );
 
 		return editor;

+ 33 - 2
examples/jsm/inspector/tabs/Settings.js

@@ -43,7 +43,8 @@ function _loadState() {
 	_state = {
 		forceWebGL: settings.forceWebGL !== undefined ? settings.forceWebGL : false,
 		captureStackTrace: settings.captureStackTrace !== undefined ? settings.captureStackTrace : false,
-		activeExtensions: settings.activeExtensions !== undefined ? settings.activeExtensions : {}
+		activeExtensions: settings.activeExtensions !== undefined ? settings.activeExtensions : {},
+		storage: settings.storage !== undefined ? settings.storage : 'url'
 	};
 
 	if ( _state.forceWebGL ) {
@@ -67,7 +68,8 @@ function _saveState() {
 	setItem( 'settings', {
 		forceWebGL: _state.forceWebGL,
 		captureStackTrace: _state.captureStackTrace,
-		activeExtensions: _state.activeExtensions
+		activeExtensions: _state.activeExtensions,
+		storage: _state.storage
 	} );
 
 }
@@ -114,6 +116,35 @@ class Settings extends Parameters {
 
 		const extensionsGroup = this.createGroup( 'Extensions' );
 
+		const storageGroup = this.createGroup( 'Storage' );
+
+		const currentState = _loadState();
+
+		storageGroup.add( currentState, 'storage', { 'URL Session': 'url', 'Keep across Origin': 'origin' } )
+			.name( 'Save Settings' )
+			.onChange( () => {
+
+				_saveState();
+
+			} ).info( `
+Defines how the **Inspector** preferences and states are stored in the browser.
+
+**URL Session**
+Saves state based on the exact URL. It will reset the settings whenever the URL changes.
+
+**Keep across Origin**
+Shares the same state across any page within the current origin.` );
+
+		storageGroup.add( {
+			clear: () => {
+
+				localStorage.removeItem( 'threejs-inspector' );
+
+				location.reload();
+
+			}
+		}, 'clear' ).name( 'Clear Settings' );
+
 		this._getExtensions().then( extensions => {
 
 			for ( const extension of extensions ) {

+ 55 - 0
examples/jsm/inspector/ui/Style.js

@@ -288,6 +288,61 @@ export class Style {
 		cursor: pointer;
 	}
 
+	.info-icon {
+		display: inline-flex;
+		align-items: center;
+		justify-content: center;
+		width: 14px;
+		height: 14px;
+		border-radius: 50%;
+		background-color: rgba(255, 255, 255, 0.1);
+		color: var(--text-secondary);
+		font-size: 10px;
+		font-style: italic;
+		margin-left: 6px;
+		cursor: help;
+		position: relative;
+	}
+
+	.info-icon:hover {
+		background-color: var(--color-accent);
+		color: white;
+	}
+
+	.info-tooltip {
+		position: fixed;
+		transform: translate(-50%, -100%);
+		background-color: rgba(30, 30, 36, 0.95);
+		border: 1px solid var(--profiler-border);
+		border-radius: 6px;
+		padding: 10px 14px;
+		color: var(--text-primary);
+		font-size: 12px;
+		width: max-content;
+		max-width: 250px;
+		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
+		pointer-events: none;
+		opacity: 0;
+		visibility: hidden;
+		transition: opacity 0.2s, visibility 0.2s;
+		z-index: 999999;
+		font-style: normal;
+		font-family: var(--font-family);
+		text-align: left;
+		white-space: normal;
+	}
+
+	.info-tooltip h3 {
+		margin: 0 0 6px 0;
+		font-size: 13px;
+		color: var(--color-accent);
+	}
+
+	.info-tooltip strong {
+		font-weight: 600;
+		color: white;
+	}
+
 	/* Style adjustments for lil-gui look */
 	.mini-panel-content .item-row {
 		padding: 3px 8px;

粤ICP备19079148号