MeshEditor.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { NumberInput, StringInput, LabelElement } from '../../libs/flow.module.js';
  2. import { BaseNode } from '../core/BaseNode.js';
  3. import { Mesh, MathUtils, Vector3 } from 'three';
  4. export class MeshEditor extends BaseNode {
  5. constructor( mesh = null ) {
  6. if ( mesh === null ) {
  7. mesh = new Mesh();
  8. }
  9. super( 'Mesh', 1, mesh );
  10. this.material = null;
  11. this.defaultMaterial = null;
  12. this.defaultPosition = new Vector3();
  13. this.defaultRotation = new Vector3();
  14. this.defaultScale = new Vector3( 100, 100, 100 );
  15. this._initTags();
  16. this._initTransform();
  17. this._initMaterial();
  18. this.updateDefault();
  19. this.update();
  20. this.onValidElement = () => {};
  21. }
  22. setEditor( editor ) {
  23. if ( this.editor ) {
  24. this._restoreDefault();
  25. }
  26. super.setEditor( editor );
  27. if ( editor ) {
  28. const name = this.nameInput.getValue();
  29. const mesh = editor.scene.getObjectByName( name );
  30. this.value = mesh;
  31. this.updateDefault();
  32. this.update();
  33. }
  34. return this;
  35. }
  36. get mesh() {
  37. return this.value;
  38. }
  39. _initMaterial() {
  40. const materialElement = new LabelElement( 'Material' ).setInputColor( 'forestgreen' ).setInput( 1 );
  41. materialElement.onValid( ( source, target, stage ) => {
  42. const object = target.getObject();
  43. if ( object && object.isMaterial !== true ) {
  44. if ( stage === 'dragged' ) {
  45. const name = target.node.getName();
  46. this.editor.tips.error( `"${name}" is not a Material.` );
  47. }
  48. return false;
  49. }
  50. } ).onConnect( () => {
  51. this.material = materialElement.getLinkedObject() || this.defaultMaterial;
  52. this.update();
  53. } );
  54. this.add( materialElement );
  55. }
  56. _initTags() {
  57. this.nameInput = new StringInput( this.mesh.name ).setReadOnly( true )
  58. .onChange( () => this.mesh.name = this.nameInput.getValue() );
  59. this.add( new LabelElement( 'Name' ).add( this.nameInput ) );
  60. }
  61. _initTransform() {
  62. const update = () => this.update();
  63. const posX = new NumberInput().setTagColor( 'red' ).onChange( update );
  64. const posY = new NumberInput().setTagColor( 'green' ).onChange( update );
  65. const posZ = new NumberInput().setTagColor( 'blue' ).onChange( update );
  66. const rotationStep = 1;
  67. const rotX = new NumberInput().setTagColor( 'red' ).setStep( rotationStep ).onChange( update );
  68. const rotY = new NumberInput().setTagColor( 'green' ).setStep( rotationStep ).onChange( update );
  69. const rotZ = new NumberInput().setTagColor( 'blue' ).setStep( rotationStep ).onChange( update );
  70. const scaleX = new NumberInput( 100 ).setTagColor( 'red' ).setStep( rotationStep ).onChange( update );
  71. const scaleY = new NumberInput( 100 ).setTagColor( 'green' ).setStep( rotationStep ).onChange( update );
  72. const scaleZ = new NumberInput( 100 ).setTagColor( 'blue' ).setStep( rotationStep ).onChange( update );
  73. this.add( new LabelElement( 'Position' ).add( posX ).add( posY ).add( posZ ) )
  74. .add( new LabelElement( 'Rotation' ).add( rotX ).add( rotY ).add( rotZ ) )
  75. .add( new LabelElement( 'Scale' ).add( scaleX ).add( scaleY ).add( scaleZ ) );
  76. this.posX = posX;
  77. this.posY = posY;
  78. this.posZ = posZ;
  79. this.rotX = rotX;
  80. this.rotY = rotY;
  81. this.rotZ = rotZ;
  82. this.scaleX = scaleX;
  83. this.scaleY = scaleY;
  84. this.scaleZ = scaleZ;
  85. }
  86. update() {
  87. const mesh = this.mesh;
  88. if ( mesh ) {
  89. const { position, rotation, scale } = mesh;
  90. position.x = this.posX.getValue();
  91. position.y = this.posY.getValue();
  92. position.z = this.posZ.getValue();
  93. rotation.x = MathUtils.degToRad( this.rotX.getValue() );
  94. rotation.y = MathUtils.degToRad( this.rotY.getValue() );
  95. rotation.z = MathUtils.degToRad( this.rotZ.getValue() );
  96. scale.x = this.scaleX.getValue() / 100;
  97. scale.y = this.scaleY.getValue() / 100;
  98. scale.z = this.scaleZ.getValue() / 100;
  99. mesh.material = this.material || this.defaultMaterial;
  100. }
  101. }
  102. updateDefault() {
  103. const { material, position, rotation, scale } = this.mesh;
  104. this.defaultMaterial = material;
  105. this.defaultPosition = position.clone();
  106. this.defaultRotation = new Vector3( MathUtils.radToDeg( rotation.x ), MathUtils.radToDeg( rotation.y ), MathUtils.radToDeg( rotation.z ) );
  107. this.defaultScale = scale.clone().multiplyScalar( 100 );
  108. this._restoreDefault();
  109. }
  110. _restoreDefault() {
  111. const position = this.defaultPosition;
  112. const rotation = this.defaultRotation;
  113. const scale = this.defaultScale;
  114. this.posX.setValue( position.x );
  115. this.posY.setValue( position.y );
  116. this.posZ.setValue( position.z );
  117. this.rotX.setValue( rotation.x );
  118. this.rotY.setValue( rotation.y );
  119. this.rotZ.setValue( rotation.z );
  120. this.scaleX.setValue( scale.x );
  121. this.scaleY.setValue( scale.y );
  122. this.scaleZ.setValue( scale.z );
  123. this.mesh.material = this.defaultMaterial;
  124. }
  125. }