Sidebar.Material.MapProperty.js 5.8 KB

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