PreviewEditor.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  2. import { ViewHelper } from 'three/addons/helpers/ViewHelper.js';
  3. import { Element, LabelElement, SelectInput } from 'flow';
  4. import { BaseNodeEditor } from '../BaseNodeEditor.js';
  5. import { MeshBasicNodeMaterial, vec4 } from 'three/nodes';
  6. import { PerspectiveCamera, Scene, Mesh, DoubleSide, SphereGeometry, BoxGeometry, PlaneGeometry, TorusKnotGeometry } from 'three';
  7. import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
  8. import { setInputAestheticsFromType } from '../DataTypeLib.js';
  9. const sceneDict = {};
  10. const getScene = ( name ) => {
  11. let scene = sceneDict[ name ];
  12. if ( scene === undefined ) {
  13. scene = new Scene();
  14. if ( name === 'box' ) {
  15. const box = new Mesh( new BoxGeometry( 1.3, 1.3, 1.3 ) );
  16. scene.add( box );
  17. } else if ( name === 'sphere' ) {
  18. const sphere = new Mesh( new SphereGeometry( 1, 32, 16 ) );
  19. scene.add( sphere );
  20. } else if ( name === 'plane' || name === 'sprite' ) {
  21. const plane = new Mesh( new PlaneGeometry( 2, 2 ) );
  22. scene.add( plane );
  23. } else if ( name === 'torus' ) {
  24. const torus = new Mesh( new TorusKnotGeometry( .7, .1, 100, 16 ) );
  25. scene.add( torus );
  26. }
  27. sceneDict[ name ] = scene;
  28. }
  29. return scene;
  30. };
  31. export class PreviewEditor extends BaseNodeEditor {
  32. constructor() {
  33. const width = 300;
  34. const height = 300;
  35. super( 'Preview', null, width );
  36. const material = new MeshBasicNodeMaterial();
  37. material.colorNode = vec4( 0, 0, 0, 1 );
  38. material.side = DoubleSide;
  39. material.transparent = true;
  40. const previewElement = new Element();
  41. previewElement.dom.style[ 'padding-top' ] = 0;
  42. previewElement.dom.style[ 'padding-bottom' ] = 0;
  43. previewElement.dom.style[ 'padding-left' ] = 0;
  44. previewElement.dom.style[ 'padding-right' ] = '14px';
  45. const sceneInput = new SelectInput( [
  46. { name: 'Box', value: 'box' },
  47. { name: 'Sphere', value: 'sphere' },
  48. { name: 'Plane', value: 'plane' },
  49. { name: 'Sprite', value: 'sprite' },
  50. { name: 'Torus', value: 'torus' }
  51. ], 'box' );
  52. const inputElement = setInputAestheticsFromType( new LabelElement( 'Input' ), 'Color' ).onConnect( () => {
  53. material.colorNode = inputElement.getLinkedObject() || vec4( 0, 0, 0, 1 );
  54. material.dispose();
  55. }, true );
  56. const canvas = document.createElement( 'canvas' );
  57. canvas.style.position = 'absolute';
  58. previewElement.dom.append( canvas );
  59. previewElement.setHeight( height );
  60. previewElement.dom.addEventListener( 'wheel', e => e.stopPropagation() );
  61. const renderer = new WebGPURenderer( {
  62. canvas,
  63. alpha: true,
  64. antialias: true
  65. } );
  66. renderer.autoClear = false;
  67. renderer.setSize( width, height, true );
  68. renderer.setPixelRatio( window.devicePixelRatio );
  69. const camera = new PerspectiveCamera( 45, width / height, 0.1, 100 );
  70. camera.aspect = width / height;
  71. camera.updateProjectionMatrix();
  72. camera.position.set( - 2, 2, 2 );
  73. camera.lookAt( 0, 0, 0 );
  74. const controls = new OrbitControls( camera, previewElement.dom );
  75. controls.enableKeys = false;
  76. controls.update();
  77. const viewHelper = new ViewHelper( camera, previewElement.dom );
  78. this.sceneInput = sceneInput;
  79. this.viewHelper = viewHelper;
  80. this.material = material;
  81. this.camera = camera;
  82. this.renderer = renderer;
  83. this.add( inputElement )
  84. .add( new LabelElement( 'Object' ).add( sceneInput ) )
  85. .add( previewElement );
  86. }
  87. setEditor( editor ) {
  88. super.setEditor( editor );
  89. this.updateAnimationRequest();
  90. }
  91. updateAnimationRequest() {
  92. if ( this.editor !== null ) {
  93. requestAnimationFrame( () => this.update() );
  94. }
  95. }
  96. async update() {
  97. const { viewHelper, material, renderer, camera, sceneInput } = this;
  98. this.updateAnimationRequest();
  99. const sceneName = sceneInput.getValue();
  100. const scene = getScene( sceneName );
  101. const mesh = scene.children[ 0 ];
  102. mesh.material = material;
  103. if ( sceneName === 'sprite' ) {
  104. mesh.lookAt( camera.position );
  105. }
  106. await renderer.clearAsync();
  107. await renderer.renderAsync( scene, camera );
  108. viewHelper.render( renderer );
  109. }
  110. }