Sidebar.Material.MapProperty.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import * as THREE from 'three';
  2. import { UICheckbox, UIDiv, UINumber, UIRow, UIText } from './libs/ui.js';
  3. import { UITexture } from './libs/ui.three.js';
  4. import { SetMaterialMapCommand } from './commands/SetMaterialMapCommand.js';
  5. import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
  6. import { SetMaterialRangeCommand } from './commands/SetMaterialRangeCommand.js';
  7. import { SetMaterialVectorCommand } from './commands/SetMaterialVectorCommand.js';
  8. function SidebarMaterialMapProperty( editor, property, name ) {
  9. const signals = editor.signals;
  10. const container = new UIRow();
  11. container.add( new UIText( name ).setWidth( '90px' ) );
  12. const enabled = new UICheckbox( false ).setMarginRight( '8px' ).onChange( onChange );
  13. container.add( enabled );
  14. const map = new UITexture( editor ).onChange( onMapChange );
  15. container.add( map );
  16. const mapType = property.replace( 'Map', '' );
  17. const colorMaps = [ 'map', 'emissiveMap', 'sheenColorMap', 'specularColorMap', 'envMap' ];
  18. let intensity;
  19. if ( property === 'aoMap' ) {
  20. intensity = new UINumber( 1 ).setWidth( '30px' ).setRange( 0, 1 ).onChange( onIntensityChange );
  21. container.add( intensity );
  22. }
  23. let scale;
  24. if ( property === 'bumpMap' || property === 'displacementMap' ) {
  25. scale = new UINumber().setWidth( '30px' ).onChange( onScaleChange );
  26. container.add( scale );
  27. }
  28. let scaleX, scaleY;
  29. if ( property === 'normalMap' || property === 'clearcoatNormalMap' ) {
  30. scaleX = new UINumber().setWidth( '30px' ).onChange( onScaleXYChange );
  31. container.add( scaleX );
  32. scaleY = new UINumber().setWidth( '30px' ).onChange( onScaleXYChange );
  33. container.add( scaleY );
  34. }
  35. let rangeMin, rangeMax;
  36. if ( property === 'iridescenceThicknessMap' ) {
  37. const range = new UIDiv().setMarginLeft( '3px' );
  38. container.add( range );
  39. const rangeMinRow = new UIRow().setMarginBottom( '0px' ).setStyle( 'min-height', '0px' );
  40. range.add( rangeMinRow );
  41. rangeMinRow.add( new UIText( 'min:' ).setWidth( '35px' ) );
  42. rangeMin = new UINumber().setWidth( '40px' ).onChange( onRangeChange );
  43. rangeMinRow.add( rangeMin );
  44. const rangeMaxRow = new UIRow().setMarginBottom( '6px' ).setStyle( 'min-height', '0px' );
  45. range.add( rangeMaxRow );
  46. rangeMaxRow.add( new UIText( 'max:' ).setWidth( '35px' ) );
  47. rangeMax = new UINumber().setWidth( '40px' ).onChange( onRangeChange );
  48. rangeMaxRow.add( rangeMax );
  49. // Additional settings for iridescenceThicknessMap
  50. // Please add conditional if more maps are having a range property
  51. rangeMin.setPrecision( 0 ).setRange( 0, Infinity ).setNudge( 1 ).setStep( 10 ).setUnit( 'nm' );
  52. rangeMax.setPrecision( 0 ).setRange( 0, Infinity ).setNudge( 1 ).setStep( 10 ).setUnit( 'nm' );
  53. }
  54. let object = null;
  55. let material = null;
  56. function onChange() {
  57. const newMap = enabled.getValue() ? map.getValue() : null;
  58. if ( material[ property ] !== newMap ) {
  59. if ( newMap !== null ) {
  60. const geometry = object.geometry;
  61. if ( geometry.hasAttribute( 'uv' ) === false ) console.warn( 'Geometry doesn\'t have uvs:', geometry );
  62. if ( property === 'envMap' ) newMap.mapping = THREE.EquirectangularReflectionMapping;
  63. }
  64. editor.execute( new SetMaterialMapCommand( editor, object, property, newMap, 0 /* TODO: currentMaterialSlot */ ) );
  65. }
  66. }
  67. function onMapChange( texture ) {
  68. if ( texture !== null ) {
  69. if ( colorMaps[ property ] !== undefined && texture.isDataTexture !== true && texture.colorSpace !== THREE.SRGBColorSpace ) {
  70. texture.colorSpace = THREE.SRGBColorSpace;
  71. material.needsUpdate = true;
  72. }
  73. }
  74. enabled.setDisabled( false );
  75. onChange();
  76. }
  77. function onIntensityChange() {
  78. if ( material[ `${ property }Intensity` ] !== intensity.getValue() ) {
  79. editor.execute( new SetMaterialValueCommand( editor, object, `${ property }Intensity`, intensity.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
  80. }
  81. }
  82. function onScaleChange() {
  83. if ( material[ `${ mapType }Scale` ] !== scale.getValue() ) {
  84. editor.execute( new SetMaterialValueCommand( editor, object, `${ mapType }Scale`, scale.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
  85. }
  86. }
  87. function onScaleXYChange() {
  88. const value = [ scaleX.getValue(), scaleY.getValue() ];
  89. if ( material[ `${ mapType }Scale` ].x !== value[ 0 ] || material[ `${ mapType }Scale` ].y !== value[ 1 ] ) {
  90. editor.execute( new SetMaterialVectorCommand( editor, object, `${ mapType }Scale`, value, 0 /* TODOL currentMaterialSlot */ ) );
  91. }
  92. }
  93. function onRangeChange() {
  94. const value = [ rangeMin.getValue(), rangeMax.getValue() ];
  95. if ( material[ `${ mapType }Range` ][ 0 ] !== value[ 0 ] || material[ `${ mapType }Range` ][ 1 ] !== value[ 1 ] ) {
  96. editor.execute( new SetMaterialRangeCommand( editor, object, `${ mapType }Range`, value[ 0 ], value[ 1 ], 0 /* TODOL currentMaterialSlot */ ) );
  97. }
  98. }
  99. function update() {
  100. if ( object === null ) return;
  101. if ( object.material === undefined ) return;
  102. material = object.material;
  103. if ( property in material ) {
  104. if ( material[ property ] !== null ) {
  105. map.setValue( material[ property ] );
  106. }
  107. enabled.setValue( material[ property ] !== null );
  108. enabled.setDisabled( map.getValue() === null );
  109. if ( intensity !== undefined ) {
  110. intensity.setValue( material[ `${ property }Intensity` ] );
  111. }
  112. if ( scale !== undefined ) {
  113. scale.setValue( material[ `${ mapType }Scale` ] );
  114. }
  115. if ( scaleX !== undefined ) {
  116. scaleX.setValue( material[ `${ mapType }Scale` ].x );
  117. scaleY.setValue( material[ `${ mapType }Scale` ].y );
  118. }
  119. if ( rangeMin !== undefined ) {
  120. rangeMin.setValue( material[ `${ mapType }Range` ][ 0 ] );
  121. rangeMax.setValue( material[ `${ mapType }Range` ][ 1 ] );
  122. }
  123. container.setDisplay( '' );
  124. } else {
  125. container.setDisplay( 'none' );
  126. }
  127. }
  128. //
  129. signals.objectSelected.add( function ( selected ) {
  130. object = selected;
  131. map.setValue( null );
  132. update();
  133. } );
  134. signals.materialChanged.add( update );
  135. return container;
  136. }
  137. export { SidebarMaterialMapProperty };