Anlegen vom Raum-Scanner
This commit is contained in:
95
node_modules/three/examples/jsm/inspector/ui/Graph.js
generated
vendored
Normal file
95
node_modules/three/examples/jsm/inspector/ui/Graph.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
export class Graph {
|
||||
|
||||
constructor( maxPoints = 512 ) {
|
||||
|
||||
this.maxPoints = maxPoints;
|
||||
this.lines = {};
|
||||
this.limit = 0;
|
||||
this.limitIndex = 0;
|
||||
|
||||
this.domElement = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
|
||||
this.domElement.setAttribute( 'class', 'graph-svg' );
|
||||
|
||||
}
|
||||
|
||||
addLine( id, color ) {
|
||||
|
||||
const path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
|
||||
path.setAttribute( 'class', 'graph-path' );
|
||||
path.style.stroke = `var(${color})`;
|
||||
path.style.fill = `var(${color})`;
|
||||
this.domElement.appendChild( path );
|
||||
|
||||
this.lines[ id ] = { path, color, points: [] };
|
||||
|
||||
}
|
||||
|
||||
addPoint( lineId, value ) {
|
||||
|
||||
const line = this.lines[ lineId ];
|
||||
if ( ! line ) return;
|
||||
|
||||
line.points.push( value );
|
||||
if ( line.points.length > this.maxPoints ) {
|
||||
|
||||
line.points.shift();
|
||||
|
||||
}
|
||||
|
||||
if ( value > this.limit ) {
|
||||
|
||||
this.limit = value;
|
||||
this.limitIndex = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resetLimit() {
|
||||
|
||||
this.limit = 0;
|
||||
this.limitIndex = 0;
|
||||
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
const svgWidth = this.domElement.clientWidth;
|
||||
const svgHeight = this.domElement.clientHeight;
|
||||
if ( svgWidth === 0 ) return;
|
||||
|
||||
const pointStep = svgWidth / ( this.maxPoints - 1 );
|
||||
|
||||
for ( const id in this.lines ) {
|
||||
|
||||
const line = this.lines[ id ];
|
||||
|
||||
let pathString = `M 0,${ svgHeight }`;
|
||||
for ( let i = 0; i < line.points.length; i ++ ) {
|
||||
|
||||
const x = i * pointStep;
|
||||
const y = svgHeight - ( line.points[ i ] / this.limit ) * svgHeight;
|
||||
pathString += ` L ${ x },${ y }`;
|
||||
|
||||
}
|
||||
|
||||
pathString += ` L ${( line.points.length - 1 ) * pointStep},${ svgHeight } Z`;
|
||||
|
||||
const offset = svgWidth - ( ( line.points.length - 1 ) * pointStep );
|
||||
line.path.setAttribute( 'transform', `translate(${ offset }, 0)` );
|
||||
line.path.setAttribute( 'd', pathString );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if ( this.limitIndex ++ > this.maxPoints ) {
|
||||
|
||||
this.resetLimit();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
170
node_modules/three/examples/jsm/inspector/ui/Item.js
generated
vendored
Normal file
170
node_modules/three/examples/jsm/inspector/ui/Item.js
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
export class Item {
|
||||
|
||||
constructor( ...data ) {
|
||||
|
||||
this.children = [];
|
||||
this.isOpen = true;
|
||||
this.childrenContainer = null;
|
||||
this.parent = null;
|
||||
this.domElement = document.createElement( 'div' );
|
||||
this.domElement.className = 'list-item-wrapper';
|
||||
this.itemRow = document.createElement( 'div' );
|
||||
this.itemRow.className = 'list-item-row';
|
||||
|
||||
this.userData = {};
|
||||
|
||||
this.data = data;
|
||||
this.data.forEach( ( cellData ) => {
|
||||
|
||||
const cell = document.createElement( 'div' );
|
||||
cell.className = 'list-item-cell';
|
||||
if ( cellData instanceof HTMLElement ) {
|
||||
|
||||
cell.appendChild( cellData );
|
||||
|
||||
} else {
|
||||
|
||||
cell.append( String( cellData ) );
|
||||
|
||||
}
|
||||
|
||||
this.itemRow.appendChild( cell );
|
||||
|
||||
} );
|
||||
|
||||
this.domElement.appendChild( this.itemRow );
|
||||
|
||||
// Bindings
|
||||
|
||||
this.onItemClick = this.onItemClick.bind( this );
|
||||
|
||||
}
|
||||
|
||||
onItemClick( e ) {
|
||||
|
||||
if ( e.target.closest( 'button, a, input, label' ) ) return;
|
||||
|
||||
this.toggle();
|
||||
|
||||
}
|
||||
|
||||
add( item, index = this.children.length ) {
|
||||
|
||||
if ( item.parent !== null ) {
|
||||
|
||||
item.parent.remove( item );
|
||||
|
||||
}
|
||||
|
||||
item.parent = this;
|
||||
|
||||
this.children.splice( index, 0, item );
|
||||
|
||||
this.itemRow.classList.add( 'collapsible' );
|
||||
|
||||
if ( ! this.childrenContainer ) {
|
||||
|
||||
this.childrenContainer = document.createElement( 'div' );
|
||||
this.childrenContainer.className = 'list-children-container';
|
||||
this.childrenContainer.classList.toggle( 'closed', ! this.isOpen );
|
||||
this.domElement.appendChild( this.childrenContainer );
|
||||
this.itemRow.addEventListener( 'click', this.onItemClick );
|
||||
|
||||
}
|
||||
|
||||
this.childrenContainer.insertBefore(
|
||||
item.domElement,
|
||||
this.childrenContainer.children[ index ] || null
|
||||
);
|
||||
|
||||
this.updateToggler();
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
remove( item ) {
|
||||
|
||||
const index = this.children.indexOf( item );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
this.children.splice( index, 1 );
|
||||
this.childrenContainer.removeChild( item.domElement );
|
||||
|
||||
item.parent = null;
|
||||
|
||||
if ( this.children.length === 0 ) {
|
||||
|
||||
this.itemRow.classList.remove( 'collapsible' );
|
||||
this.itemRow.removeEventListener( 'click', this.onItemClick );
|
||||
|
||||
this.childrenContainer.remove();
|
||||
this.childrenContainer = null;
|
||||
|
||||
}
|
||||
|
||||
this.updateToggler();
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
updateToggler() {
|
||||
|
||||
const firstCell = this.itemRow.querySelector( '.list-item-cell:first-child' );
|
||||
let toggler = this.itemRow.querySelector( '.item-toggler' );
|
||||
|
||||
if ( this.children.length > 0 ) {
|
||||
|
||||
if ( ! toggler ) {
|
||||
|
||||
toggler = document.createElement( 'span' );
|
||||
toggler.className = 'item-toggler';
|
||||
firstCell.prepend( toggler );
|
||||
|
||||
}
|
||||
|
||||
if ( this.isOpen ) {
|
||||
|
||||
this.itemRow.classList.add( 'open' );
|
||||
|
||||
}
|
||||
|
||||
} else if ( toggler ) {
|
||||
|
||||
toggler.remove();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
||||
this.isOpen = ! this.isOpen;
|
||||
this.itemRow.classList.toggle( 'open', this.isOpen );
|
||||
|
||||
if ( this.childrenContainer ) {
|
||||
|
||||
this.childrenContainer.classList.toggle( 'closed', ! this.isOpen );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
close() {
|
||||
|
||||
if ( this.isOpen ) {
|
||||
|
||||
this.toggle();
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
75
node_modules/three/examples/jsm/inspector/ui/List.js
generated
vendored
Normal file
75
node_modules/three/examples/jsm/inspector/ui/List.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
export class List {
|
||||
|
||||
constructor( ...headers ) {
|
||||
|
||||
this.headers = headers;
|
||||
this.children = [];
|
||||
this.domElement = document.createElement( 'div' );
|
||||
this.domElement.className = 'list-container';
|
||||
this.domElement.style.padding = '10px';
|
||||
this.id = `list-${Math.random().toString( 36 ).substr( 2, 9 )}`;
|
||||
this.domElement.dataset.listId = this.id;
|
||||
|
||||
this.gridStyleElement = document.createElement( 'style' );
|
||||
this.domElement.appendChild( this.gridStyleElement );
|
||||
|
||||
const headerRow = document.createElement( 'div' );
|
||||
headerRow.className = 'list-header';
|
||||
this.headers.forEach( headerText => {
|
||||
|
||||
const headerCell = document.createElement( 'div' );
|
||||
headerCell.className = 'list-header-cell';
|
||||
headerCell.textContent = headerText;
|
||||
headerRow.appendChild( headerCell );
|
||||
|
||||
} );
|
||||
this.domElement.appendChild( headerRow );
|
||||
|
||||
}
|
||||
|
||||
setGridStyle( gridTemplate ) {
|
||||
|
||||
this.gridStyleElement.textContent = `
|
||||
[data-list-id="${this.id}"] > .list-header,
|
||||
[data-list-id="${this.id}"] .list-item-row {
|
||||
grid-template-columns: ${gridTemplate};
|
||||
}
|
||||
`;
|
||||
|
||||
}
|
||||
|
||||
add( item ) {
|
||||
|
||||
if ( item.parent !== null ) {
|
||||
|
||||
item.parent.remove( item );
|
||||
|
||||
}
|
||||
|
||||
item.domElement.classList.add( 'header-wrapper', 'section-start' );
|
||||
item.parent = this;
|
||||
|
||||
this.children.push( item );
|
||||
this.domElement.appendChild( item.domElement );
|
||||
|
||||
}
|
||||
|
||||
remove( item ) {
|
||||
|
||||
const index = this.children.indexOf( item );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
this.children.splice( index, 1 );
|
||||
this.domElement.removeChild( item.domElement );
|
||||
|
||||
item.parent = null;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
1975
node_modules/three/examples/jsm/inspector/ui/Profiler.js
generated
vendored
Normal file
1975
node_modules/three/examples/jsm/inspector/ui/Profiler.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1613
node_modules/three/examples/jsm/inspector/ui/Style.js
generated
vendored
Normal file
1613
node_modules/three/examples/jsm/inspector/ui/Style.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
233
node_modules/three/examples/jsm/inspector/ui/Tab.js
generated
vendored
Normal file
233
node_modules/three/examples/jsm/inspector/ui/Tab.js
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Tab class
|
||||
* @param {string} title - The title of the tab
|
||||
* @param {Object} options - Options for the tab
|
||||
* @param {boolean} [options.allowDetach=true] - Whether the tab can be detached into a separate window
|
||||
* @param {boolean} [options.builtin=false] - Whether the tab should appear in the profiler-toggle button
|
||||
* @param {string} [options.icon] - SVG icon HTML for the builtin button
|
||||
*
|
||||
* @example
|
||||
* // Create a tab that can be detached (default behavior)
|
||||
* const tab1 = new Tab('My Tab');
|
||||
*
|
||||
* // Create a tab that cannot be detached
|
||||
* const tab2 = new Tab('Fixed Tab', { allowDetach: false });
|
||||
*
|
||||
* // Create a builtin tab that appears in the profiler-toggle
|
||||
* const tab3 = new Tab('Builtin Tab', { builtin: true });
|
||||
*
|
||||
* // Create a builtin tab with custom icon
|
||||
* const tab4 = new Tab('Settings', { builtin: true, icon: '<svg>...</svg>' });
|
||||
*
|
||||
* // Control builtin tab visibility
|
||||
* tab3.showBuiltin(); // Show the builtin button and mini-content
|
||||
* tab3.hideBuiltin(); // Hide the builtin button and mini-content
|
||||
*/
|
||||
export class Tab {
|
||||
|
||||
constructor( title, options = {} ) {
|
||||
|
||||
this.id = title.toLowerCase();
|
||||
this.button = document.createElement( 'button' );
|
||||
this.button.className = 'tab-btn';
|
||||
this.button.textContent = title;
|
||||
|
||||
this.content = document.createElement( 'div' );
|
||||
this.content.id = `${this.id}-content`;
|
||||
this.content.className = 'profiler-content';
|
||||
|
||||
this.isActive = false;
|
||||
this.isVisible = true;
|
||||
this.isDetached = false;
|
||||
this.detachedWindow = null;
|
||||
this.allowDetach = options.allowDetach !== undefined ? options.allowDetach : true;
|
||||
this.builtin = options.builtin !== undefined ? options.builtin : false;
|
||||
this.icon = options.icon || null;
|
||||
this.builtinButton = null; // Reference to the builtin button in profiler-toggle
|
||||
this.miniContent = null; // Reference to the mini-panel content container
|
||||
this.profiler = null; // Reference to the profiler instance
|
||||
this.onVisibilityChange = null; // Callback for visibility changes
|
||||
|
||||
}
|
||||
|
||||
setActive( isActive ) {
|
||||
|
||||
this.button.classList.toggle( 'active', isActive );
|
||||
this.content.classList.toggle( 'active', isActive );
|
||||
|
||||
this.isActive = isActive;
|
||||
|
||||
}
|
||||
|
||||
show() {
|
||||
|
||||
this.content.style.display = '';
|
||||
this.button.style.display = '';
|
||||
|
||||
this.isVisible = true;
|
||||
|
||||
// Show detached window if tab is detached
|
||||
if ( this.isDetached && this.detachedWindow ) {
|
||||
|
||||
this.detachedWindow.panel.style.display = '';
|
||||
|
||||
}
|
||||
|
||||
// Notify profiler of visibility change
|
||||
if ( this.onVisibilityChange ) {
|
||||
|
||||
this.onVisibilityChange();
|
||||
|
||||
}
|
||||
|
||||
this.showBuiltin();
|
||||
|
||||
}
|
||||
|
||||
hide() {
|
||||
|
||||
this.content.style.display = 'none';
|
||||
this.button.style.display = 'none';
|
||||
|
||||
this.isVisible = false;
|
||||
|
||||
// Hide detached window if tab is detached
|
||||
if ( this.isDetached && this.detachedWindow ) {
|
||||
|
||||
this.detachedWindow.panel.style.display = 'none';
|
||||
|
||||
}
|
||||
|
||||
// Notify profiler of visibility change
|
||||
if ( this.onVisibilityChange ) {
|
||||
|
||||
this.onVisibilityChange();
|
||||
|
||||
}
|
||||
|
||||
this.hideBuiltin();
|
||||
|
||||
}
|
||||
|
||||
showBuiltin() {
|
||||
|
||||
if ( ! this.builtin ) return;
|
||||
|
||||
// Show the builtin-tabs-container
|
||||
if ( this.profiler && this.profiler.builtinTabsContainer ) {
|
||||
|
||||
this.profiler.builtinTabsContainer.style.display = '';
|
||||
|
||||
}
|
||||
|
||||
// Show the button
|
||||
if ( this.builtinButton ) {
|
||||
|
||||
this.builtinButton.style.display = '';
|
||||
|
||||
}
|
||||
|
||||
// Show and activate the mini-panel with content
|
||||
if ( this.miniContent && this.profiler ) {
|
||||
|
||||
// Hide all other mini-panel contents
|
||||
this.profiler.miniPanel.querySelectorAll( '.mini-panel-content' ).forEach( content => {
|
||||
|
||||
content.style.display = 'none';
|
||||
|
||||
} );
|
||||
|
||||
// Remove active state from all builtin buttons
|
||||
this.profiler.builtinTabsContainer.querySelectorAll( '.builtin-tab-btn' ).forEach( btn => {
|
||||
|
||||
btn.classList.remove( 'active' );
|
||||
|
||||
} );
|
||||
|
||||
// Activate this tab's button
|
||||
if ( this.builtinButton ) {
|
||||
|
||||
this.builtinButton.classList.add( 'active' );
|
||||
|
||||
}
|
||||
|
||||
// Move content to mini-panel if not already there
|
||||
if ( ! this.miniContent.firstChild ) {
|
||||
|
||||
const actualContent = this.content.querySelector( '.list-scroll-wrapper' ) || this.content.firstElementChild;
|
||||
|
||||
if ( actualContent ) {
|
||||
|
||||
this.miniContent.appendChild( actualContent );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Show the mini-panel and content
|
||||
this.miniContent.style.display = 'block';
|
||||
this.profiler.miniPanel.classList.add( 'visible' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hideBuiltin() {
|
||||
|
||||
if ( ! this.builtin ) return;
|
||||
|
||||
// Hide the button
|
||||
if ( this.builtinButton ) {
|
||||
|
||||
this.builtinButton.style.display = 'none';
|
||||
|
||||
}
|
||||
|
||||
// Hide the mini-panel content
|
||||
if ( this.miniContent ) {
|
||||
|
||||
this.miniContent.style.display = 'none';
|
||||
|
||||
// Move content back to main panel
|
||||
if ( this.miniContent.firstChild ) {
|
||||
|
||||
this.content.appendChild( this.miniContent.firstChild );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Deactivate button
|
||||
if ( this.builtinButton ) {
|
||||
|
||||
this.builtinButton.classList.remove( 'active' );
|
||||
|
||||
}
|
||||
|
||||
// Hide mini-panel if no content is visible
|
||||
if ( this.profiler ) {
|
||||
|
||||
const hasVisibleContent = Array.from( this.profiler.miniPanel.querySelectorAll( '.mini-panel-content' ) )
|
||||
.some( content => content.style.display !== 'none' );
|
||||
|
||||
if ( ! hasVisibleContent ) {
|
||||
|
||||
this.profiler.miniPanel.classList.remove( 'visible' );
|
||||
|
||||
}
|
||||
|
||||
// Hide the builtin-tabs-container if all builtin buttons are hidden
|
||||
const hasVisibleBuiltinButtons = Array.from( this.profiler.builtinTabsContainer.querySelectorAll( '.builtin-tab-btn' ) )
|
||||
.some( btn => btn.style.display !== 'none' );
|
||||
|
||||
if ( ! hasVisibleBuiltinButtons ) {
|
||||
|
||||
this.profiler.builtinTabsContainer.style.display = 'none';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
439
node_modules/three/examples/jsm/inspector/ui/Values.js
generated
vendored
Normal file
439
node_modules/three/examples/jsm/inspector/ui/Values.js
generated
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
import { EventDispatcher } from 'three';
|
||||
|
||||
class Value extends EventDispatcher {
|
||||
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
this.domElement = document.createElement( 'div' );
|
||||
this.domElement.className = 'param-control';
|
||||
|
||||
this._onChangeFunction = null;
|
||||
|
||||
this.addEventListener( 'change', ( e ) => {
|
||||
|
||||
// defer to avoid issues when changing multiple values in the same call stack
|
||||
|
||||
requestAnimationFrame( () => {
|
||||
|
||||
if ( this._onChangeFunction ) this._onChangeFunction( e.value );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
setValue( /*val*/ ) {
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
dispatchChange() {
|
||||
|
||||
this.dispatchEvent( { type: 'change', value: this.getValue() } );
|
||||
|
||||
}
|
||||
|
||||
onChange( callback ) {
|
||||
|
||||
this._onChangeFunction = callback;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueNumber extends Value {
|
||||
|
||||
constructor( { value = 0, step = 0.1, min = - Infinity, max = Infinity } ) {
|
||||
|
||||
super();
|
||||
|
||||
this.input = document.createElement( 'input' );
|
||||
this.input.type = 'number';
|
||||
this.input.value = value;
|
||||
this.input.step = step;
|
||||
this.input.min = min;
|
||||
this.input.max = max;
|
||||
this.input.addEventListener( 'change', this._onChangeValue.bind( this ) );
|
||||
this.domElement.appendChild( this.input );
|
||||
this.addDragHandler();
|
||||
|
||||
}
|
||||
|
||||
_onChangeValue() {
|
||||
|
||||
const value = parseFloat( this.input.value );
|
||||
const min = parseFloat( this.input.min );
|
||||
const max = parseFloat( this.input.max );
|
||||
|
||||
if ( value > max ) {
|
||||
|
||||
this.input.value = max;
|
||||
|
||||
} else if ( value < min ) {
|
||||
|
||||
this.input.value = min;
|
||||
|
||||
} else if ( isNaN( value ) ) {
|
||||
|
||||
this.input.value = min;
|
||||
|
||||
}
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
}
|
||||
|
||||
addDragHandler() {
|
||||
|
||||
let isDragging = false;
|
||||
let startY, startValue;
|
||||
|
||||
this.input.addEventListener( 'mousedown', ( e ) => {
|
||||
|
||||
isDragging = true;
|
||||
startY = e.clientY;
|
||||
startValue = parseFloat( this.input.value );
|
||||
document.body.style.cursor = 'ns-resize';
|
||||
|
||||
} );
|
||||
|
||||
document.addEventListener( 'mousemove', ( e ) => {
|
||||
|
||||
if ( isDragging ) {
|
||||
|
||||
const deltaY = startY - e.clientY;
|
||||
const step = parseFloat( this.input.step ) || 1;
|
||||
const min = parseFloat( this.input.min );
|
||||
const max = parseFloat( this.input.max );
|
||||
|
||||
let stepSize = step;
|
||||
|
||||
if ( ! isNaN( max ) && isFinite( min ) ) {
|
||||
|
||||
stepSize = ( max - min ) / 100;
|
||||
|
||||
}
|
||||
|
||||
const change = deltaY * stepSize;
|
||||
|
||||
let newValue = startValue + change;
|
||||
newValue = Math.max( min, Math.min( newValue, max ) );
|
||||
|
||||
const precision = ( String( step ).split( '.' )[ 1 ] || [] ).length;
|
||||
this.input.value = newValue.toFixed( precision );
|
||||
|
||||
this.input.dispatchEvent( new Event( 'input' ) );
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
document.addEventListener( 'mouseup', () => {
|
||||
|
||||
if ( isDragging ) {
|
||||
|
||||
isDragging = false;
|
||||
document.body.style.cursor = 'default';
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
setValue( val ) {
|
||||
|
||||
this.input.value = val;
|
||||
|
||||
return super.setValue( val );
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
return parseFloat( this.input.value );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueCheckbox extends Value {
|
||||
|
||||
constructor( { value = false } ) {
|
||||
|
||||
super();
|
||||
|
||||
const label = document.createElement( 'label' );
|
||||
label.className = 'custom-checkbox';
|
||||
|
||||
const checkbox = document.createElement( 'input' );
|
||||
checkbox.type = 'checkbox';
|
||||
checkbox.checked = value;
|
||||
this.checkbox = checkbox;
|
||||
|
||||
const checkmark = document.createElement( 'span' );
|
||||
checkmark.className = 'checkmark';
|
||||
|
||||
label.appendChild( checkbox );
|
||||
label.appendChild( checkmark );
|
||||
this.domElement.appendChild( label );
|
||||
|
||||
checkbox.addEventListener( 'change', () => {
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
setValue( val ) {
|
||||
|
||||
this.checkbox.value = val;
|
||||
|
||||
return super.setValue( val );
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
return this.checkbox.checked;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueSlider extends Value {
|
||||
|
||||
constructor( { value = 0, min = 0, max = 1, step = 0.01 } ) {
|
||||
|
||||
super();
|
||||
|
||||
this.slider = document.createElement( 'input' );
|
||||
this.slider.type = 'range';
|
||||
this.slider.min = min;
|
||||
this.slider.max = max;
|
||||
this.slider.step = step;
|
||||
|
||||
const numberValue = new ValueNumber( { value, min, max, step } );
|
||||
this.numberInput = numberValue.input;
|
||||
this.numberInput.style.flexBasis = '80px';
|
||||
this.numberInput.style.flexShrink = '0';
|
||||
|
||||
this.slider.value = value;
|
||||
|
||||
this.domElement.append( this.slider, this.numberInput );
|
||||
|
||||
this.slider.addEventListener( 'input', () => {
|
||||
|
||||
this.numberInput.value = this.slider.value;
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
} );
|
||||
|
||||
numberValue.addEventListener( 'change', () => {
|
||||
|
||||
this.slider.value = parseFloat( this.numberInput.value );
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
setValue( val ) {
|
||||
|
||||
this.slider.value = val;
|
||||
this.numberInput.value = val;
|
||||
|
||||
return super.setValue( val );
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
return parseFloat( this.slider.value );
|
||||
|
||||
}
|
||||
|
||||
step( value ) {
|
||||
|
||||
this.slider.step = value;
|
||||
this.numberInput.step = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueSelect extends Value {
|
||||
|
||||
constructor( { options = [], value = '' } ) {
|
||||
|
||||
super();
|
||||
|
||||
const select = document.createElement( 'select' );
|
||||
|
||||
const createOption = ( name, optionValue ) => {
|
||||
|
||||
const optionEl = document.createElement( 'option' );
|
||||
optionEl.value = name;
|
||||
optionEl.textContent = name;
|
||||
|
||||
if ( optionValue == value ) optionEl.selected = true;
|
||||
|
||||
select.appendChild( optionEl );
|
||||
|
||||
return optionEl;
|
||||
|
||||
};
|
||||
|
||||
if ( Array.isArray( options ) ) {
|
||||
|
||||
options.forEach( opt => createOption( opt, opt ) );
|
||||
|
||||
} else {
|
||||
|
||||
Object.entries( options ).forEach( ( [ key, value ] ) => createOption( key, value ) );
|
||||
|
||||
}
|
||||
|
||||
this.domElement.appendChild( select );
|
||||
|
||||
//
|
||||
|
||||
select.addEventListener( 'change', () => {
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
} );
|
||||
|
||||
this.options = options;
|
||||
this.select = select;
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
const options = this.options;
|
||||
|
||||
if ( Array.isArray( options ) ) {
|
||||
|
||||
return options[ this.select.selectedIndex ];
|
||||
|
||||
} else {
|
||||
|
||||
return options[ this.select.value ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueColor extends Value {
|
||||
|
||||
constructor( { value = '#ffffff' } ) {
|
||||
|
||||
super();
|
||||
|
||||
const colorInput = document.createElement( 'input' );
|
||||
colorInput.type = 'color';
|
||||
colorInput.value = this._getColorHex( value );
|
||||
this.colorInput = colorInput;
|
||||
|
||||
this._value = value;
|
||||
|
||||
colorInput.addEventListener( 'input', () => {
|
||||
|
||||
const colorValue = colorInput.value;
|
||||
|
||||
if ( this._value.isColor ) {
|
||||
|
||||
this._value.setHex( parseInt( colorValue.slice( 1 ), 16 ) );
|
||||
|
||||
} else {
|
||||
|
||||
this._value = colorValue;
|
||||
|
||||
}
|
||||
|
||||
this.dispatchChange();
|
||||
|
||||
} );
|
||||
|
||||
this.domElement.appendChild( colorInput );
|
||||
|
||||
}
|
||||
|
||||
_getColorHex( color ) {
|
||||
|
||||
if ( color.isColor ) {
|
||||
|
||||
color = color.getHex();
|
||||
|
||||
}
|
||||
|
||||
if ( typeof color === 'number' ) {
|
||||
|
||||
color = `#${ color.toString( 16 ) }`;
|
||||
|
||||
} else if ( color[ 0 ] !== '#' ) {
|
||||
|
||||
color = '#' + color;
|
||||
|
||||
}
|
||||
|
||||
return color;
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
||||
let value = this._value;
|
||||
|
||||
if ( typeof value === 'string' ) {
|
||||
|
||||
value = parseInt( value.slice( 1 ), 16 );
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ValueButton extends Value {
|
||||
|
||||
constructor( { text = 'Button', value = () => {} } ) {
|
||||
|
||||
super();
|
||||
|
||||
const button = document.createElement( 'button' );
|
||||
button.textContent = text;
|
||||
button.onclick = value;
|
||||
this.domElement.appendChild( button );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Value, ValueNumber, ValueCheckbox, ValueSlider, ValueSelect, ValueColor, ValueButton };
|
||||
56
node_modules/three/examples/jsm/inspector/ui/utils.js
generated
vendored
Normal file
56
node_modules/three/examples/jsm/inspector/ui/utils.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
export function createValueSpan( id = null ) {
|
||||
|
||||
const span = document.createElement( 'span' );
|
||||
span.className = 'value';
|
||||
|
||||
if ( id !== null ) span.id = id;
|
||||
|
||||
return span;
|
||||
|
||||
}
|
||||
|
||||
export function setText( element, text ) {
|
||||
|
||||
const el = element instanceof HTMLElement ? element : document.getElementById( element );
|
||||
|
||||
if ( el && el.textContent !== text ) {
|
||||
|
||||
el.textContent = text;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function getText( element ) {
|
||||
|
||||
const el = element instanceof HTMLElement ? element : document.getElementById( element );
|
||||
|
||||
return el ? el.textContent : null;
|
||||
|
||||
}
|
||||
|
||||
export function splitPath( fullPath ) {
|
||||
|
||||
const lastSlash = fullPath.lastIndexOf( '/' );
|
||||
|
||||
if ( lastSlash === - 1 ) {
|
||||
|
||||
return {
|
||||
path: '',
|
||||
name: fullPath.trim()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const path = fullPath.substring( 0, lastSlash ).trim();
|
||||
const name = fullPath.substring( lastSlash + 1 ).trim();
|
||||
|
||||
return { path, name };
|
||||
|
||||
}
|
||||
|
||||
export function splitCamelCase( str ) {
|
||||
|
||||
return str.replace( /([a-z0-9])([A-Z])/g, '$1 $2' ).trim();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user