You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

170 lines
3.8 KiB

import { OrbitControls } from '../../controls/OrbitControls.js';
import { ViewHelper } from '../../helpers/ViewHelper.js';
import { Element, LabelElement, SelectInput } from '../../libs/flow.module.js';
import { BaseNode } from '../core/BaseNode.js';
import { MeshBasicNodeMaterial, ConstNode } from 'three/nodes';
import { WebGLRenderer, PerspectiveCamera, Scene, Mesh, DoubleSide, SphereGeometry, BoxGeometry, PlaneGeometry, TorusKnotGeometry } from 'three';
const nullValue = new ConstNode( 0 );
const sceneDict = {};
const getScene = ( name ) => {
let scene = sceneDict[ name ];
if ( scene === undefined ) {
scene = new Scene();
if ( name === 'box' ) {
const box = new Mesh( new BoxGeometry( 1.3, 1.3, 1.3 ) );
scene.add( box );
} else if ( name === 'sphere' ) {
const sphere = new Mesh( new SphereGeometry( 1, 32, 16 ) );
scene.add( sphere );
} else if ( name === 'plane' || name === 'sprite' ) {
const plane = new Mesh( new PlaneGeometry( 2, 2 ) );
scene.add( plane );
} else if ( name === 'torus' ) {
const torus = new Mesh( new TorusKnotGeometry( .7, .1, 100, 16 ) );
scene.add( torus );
}
sceneDict[ name ] = scene;
}
return scene;
};
export class PreviewEditor extends BaseNode {
constructor() {
const width = 300;
const height = 300;
super( 'Preview', 0, null, height );
const material = new MeshBasicNodeMaterial();
material.colorNode = nullValue;
material.side = DoubleSide;
material.transparent = true;
const previewElement = new Element();
previewElement.dom.style[ 'padding-top' ] = 0;
previewElement.dom.style[ 'padding-bottom' ] = 0;
previewElement.dom.style[ 'padding-left' ] = 0;
previewElement.dom.style[ 'padding-right' ] = '14px';
const sceneInput = new SelectInput( [
{ name: 'Box', value: 'box' },
{ name: 'Sphere', value: 'sphere' },
{ name: 'Plane', value: 'plane' },
{ name: 'Sprite', value: 'sprite' },
{ name: 'Torus', value: 'torus' }
], 'box' );
const inputElement = new LabelElement( 'Input' ).setInput( 4 ).onConnect( () => {
material.colorNode = inputElement.getLinkedObject() || nullValue;
material.dispose();
}, true );
const canvas = document.createElement( 'canvas' );
canvas.style.position = 'absolute';
previewElement.dom.append( canvas );
previewElement.setHeight( height );
previewElement.dom.addEventListener( 'wheel', e => e.stopPropagation() );
const renderer = new WebGLRenderer( {
canvas,
alpha: true
} );
renderer.autoClear = false;
renderer.setSize( width, height, true );
renderer.setPixelRatio( window.devicePixelRatio );
const camera = new PerspectiveCamera( 45, width / height, 0.1, 100 );
camera.aspect = width / height;
camera.updateProjectionMatrix();
camera.position.set( - 2, 2, 2 );
camera.lookAt( 0, 0, 0 );
const controls = new OrbitControls( camera, previewElement.dom );
controls.enableKeys = false;
controls.update();
const viewHelper = new ViewHelper( camera, previewElement.dom );
this.sceneInput = sceneInput;
this.viewHelper = viewHelper;
this.material = material;
this.camera = camera;
this.renderer = renderer;
this.add( inputElement )
.add( new LabelElement( 'Object' ).add( sceneInput ) )
.add( previewElement );
}
setEditor( editor ) {
super.setEditor( editor );
this.updateAnimationRequest();
}
updateAnimationRequest() {
if ( this.editor !== null ) {
requestAnimationFrame( () => this.update() );
}
}
update() {
const { viewHelper, material, renderer, camera, sceneInput } = this;
this.updateAnimationRequest();
const sceneName = sceneInput.getValue();
const scene = getScene( sceneName );
const mesh = scene.children[ 0 ];
mesh.material = material;
if ( sceneName === 'sprite' ) {
mesh.lookAt( camera.position );
}
renderer.clear();
renderer.render( scene, camera );
viewHelper.render( renderer );
}
}