1 | var Viewport = function ( editor ) {
|
---|
2 |
|
---|
3 | var signals = editor.signals;
|
---|
4 |
|
---|
5 | var container = new UI.Panel();
|
---|
6 | container.setPosition( 'absolute' );
|
---|
7 |
|
---|
8 | var info = new UI.Text();
|
---|
9 | info.setPosition( 'absolute' );
|
---|
10 | info.setRight( '5px' );
|
---|
11 | info.setBottom( '5px' );
|
---|
12 | info.setFontSize( '12px' );
|
---|
13 | info.setColor( '#ffffff' );
|
---|
14 | info.setValue( 'objects: 0, vertices: 0, faces: 0' );
|
---|
15 | container.add( info );
|
---|
16 |
|
---|
17 | var scene = editor.scene;
|
---|
18 | var sceneHelpers = editor.sceneHelpers;
|
---|
19 |
|
---|
20 | var objects = [];
|
---|
21 |
|
---|
22 | // helpers
|
---|
23 |
|
---|
24 | var grid = new THREE.GridHelper( 500, 25 );
|
---|
25 | sceneHelpers.add( grid );
|
---|
26 |
|
---|
27 | //
|
---|
28 |
|
---|
29 | var camera = new THREE.PerspectiveCamera( 50, container.dom.offsetWidth / container.dom.offsetHeight, 1, 5000 );
|
---|
30 | camera.position.fromArray( editor.config.getKey( 'camera' ).position );
|
---|
31 | camera.lookAt( new THREE.Vector3().fromArray( editor.config.getKey( 'camera' ).target ) );
|
---|
32 |
|
---|
33 | //
|
---|
34 |
|
---|
35 | var selectionBox = new THREE.BoxHelper();
|
---|
36 | selectionBox.material.depthTest = false;
|
---|
37 | selectionBox.material.transparent = true;
|
---|
38 | selectionBox.visible = false;
|
---|
39 | sceneHelpers.add( selectionBox );
|
---|
40 |
|
---|
41 | var transformControls = new THREE.TransformControls( camera, container.dom );
|
---|
42 | transformControls.addEventListener( 'change', function () {
|
---|
43 |
|
---|
44 | controls.enabled = true;
|
---|
45 |
|
---|
46 | if ( transformControls.axis !== undefined ) {
|
---|
47 |
|
---|
48 | controls.enabled = false;
|
---|
49 |
|
---|
50 | }
|
---|
51 |
|
---|
52 | if ( editor.selected !== null ) {
|
---|
53 |
|
---|
54 | signals.objectChanged.dispatch( editor.selected );
|
---|
55 |
|
---|
56 | }
|
---|
57 |
|
---|
58 | } );
|
---|
59 | sceneHelpers.add( transformControls );
|
---|
60 |
|
---|
61 | // fog
|
---|
62 |
|
---|
63 | var oldFogType = "None";
|
---|
64 | var oldFogColor = 0xaaaaaa;
|
---|
65 | var oldFogNear = 1;
|
---|
66 | var oldFogFar = 5000;
|
---|
67 | var oldFogDensity = 0.00025;
|
---|
68 |
|
---|
69 | // object picking
|
---|
70 |
|
---|
71 | var ray = new THREE.Raycaster();
|
---|
72 | var projector = new THREE.Projector();
|
---|
73 |
|
---|
74 | // events
|
---|
75 |
|
---|
76 | var getIntersects = function ( event, object ) {
|
---|
77 |
|
---|
78 | var rect = container.dom.getBoundingClientRect();
|
---|
79 | x = ( event.clientX - rect.left ) / rect.width;
|
---|
80 | y = ( event.clientY - rect.top ) / rect.height;
|
---|
81 | var vector = new THREE.Vector3( ( x ) * 2 - 1, - ( y ) * 2 + 1, 0.5 );
|
---|
82 |
|
---|
83 | projector.unprojectVector( vector, camera );
|
---|
84 |
|
---|
85 | ray.set( camera.position, vector.sub( camera.position ).normalize() );
|
---|
86 |
|
---|
87 | if ( object instanceof Array ) {
|
---|
88 |
|
---|
89 | return ray.intersectObjects( object );
|
---|
90 |
|
---|
91 | }
|
---|
92 |
|
---|
93 | return ray.intersectObject( object );
|
---|
94 |
|
---|
95 | };
|
---|
96 |
|
---|
97 | var onMouseDownPosition = new THREE.Vector2();
|
---|
98 | var onMouseUpPosition = new THREE.Vector2();
|
---|
99 |
|
---|
100 | var onMouseDown = function ( event ) {
|
---|
101 |
|
---|
102 | event.preventDefault();
|
---|
103 |
|
---|
104 | var rect = container.dom.getBoundingClientRect();
|
---|
105 | x = (event.clientX - rect.left) / rect.width;
|
---|
106 | y = (event.clientY - rect.top) / rect.height;
|
---|
107 | onMouseDownPosition.set( x, y );
|
---|
108 |
|
---|
109 | document.addEventListener( 'mouseup', onMouseUp, false );
|
---|
110 |
|
---|
111 | };
|
---|
112 |
|
---|
113 | var onMouseUp = function ( event ) {
|
---|
114 |
|
---|
115 | var rect = container.dom.getBoundingClientRect();
|
---|
116 | x = (event.clientX - rect.left) / rect.width;
|
---|
117 | y = (event.clientY - rect.top) / rect.height;
|
---|
118 | onMouseUpPosition.set( x, y );
|
---|
119 |
|
---|
120 | if ( onMouseDownPosition.distanceTo( onMouseUpPosition ) == 0 ) {
|
---|
121 |
|
---|
122 | var intersects = getIntersects( event, objects );
|
---|
123 |
|
---|
124 | if ( intersects.length > 0 ) {
|
---|
125 |
|
---|
126 | var object = intersects[ 0 ].object;
|
---|
127 |
|
---|
128 | if ( object.userData.object !== undefined ) {
|
---|
129 |
|
---|
130 | // helper
|
---|
131 |
|
---|
132 | editor.select( object.userData.object );
|
---|
133 |
|
---|
134 | } else {
|
---|
135 |
|
---|
136 | editor.select( object );
|
---|
137 |
|
---|
138 | }
|
---|
139 |
|
---|
140 | } else {
|
---|
141 |
|
---|
142 | editor.select( null );
|
---|
143 |
|
---|
144 | }
|
---|
145 |
|
---|
146 | render();
|
---|
147 |
|
---|
148 | }
|
---|
149 |
|
---|
150 | document.removeEventListener( 'mouseup', onMouseUp );
|
---|
151 |
|
---|
152 | };
|
---|
153 |
|
---|
154 | var onDoubleClick = function ( event ) {
|
---|
155 |
|
---|
156 | var intersects = getIntersects( event, objects );
|
---|
157 |
|
---|
158 | if ( intersects.length > 0 && intersects[ 0 ].object === editor.selected ) {
|
---|
159 |
|
---|
160 | controls.focus( editor.selected );
|
---|
161 |
|
---|
162 | }
|
---|
163 |
|
---|
164 | };
|
---|
165 |
|
---|
166 | container.dom.addEventListener( 'mousedown', onMouseDown, false );
|
---|
167 | container.dom.addEventListener( 'dblclick', onDoubleClick, false );
|
---|
168 |
|
---|
169 | // controls need to be added *after* main logic,
|
---|
170 | // otherwise controls.enabled doesn't work.
|
---|
171 |
|
---|
172 | var controls = new THREE.EditorControls( camera, container.dom );
|
---|
173 | controls.center.fromArray( editor.config.getKey( 'camera' ).target )
|
---|
174 | controls.addEventListener( 'change', function () {
|
---|
175 |
|
---|
176 | transformControls.update();
|
---|
177 | signals.cameraChanged.dispatch( camera );
|
---|
178 |
|
---|
179 | } );
|
---|
180 |
|
---|
181 | // signals
|
---|
182 |
|
---|
183 | signals.themeChanged.add( function ( value ) {
|
---|
184 |
|
---|
185 | switch ( value ) {
|
---|
186 |
|
---|
187 | case 'css/light.css':
|
---|
188 | grid.setColors( 0x444444, 0x888888 );
|
---|
189 | clearColor = 0xaaaaaa;
|
---|
190 | break;
|
---|
191 | case 'css/dark.css':
|
---|
192 | grid.setColors( 0xbbbbbb, 0x888888 );
|
---|
193 | clearColor = 0x333333;
|
---|
194 | break;
|
---|
195 |
|
---|
196 | }
|
---|
197 |
|
---|
198 | renderer.setClearColor( clearColor );
|
---|
199 |
|
---|
200 | render();
|
---|
201 |
|
---|
202 | } );
|
---|
203 |
|
---|
204 | signals.transformModeChanged.add( function ( mode ) {
|
---|
205 |
|
---|
206 | transformControls.setMode( mode );
|
---|
207 |
|
---|
208 | } );
|
---|
209 |
|
---|
210 | signals.snapChanged.add( function ( dist ) {
|
---|
211 |
|
---|
212 | transformControls.setSnap( dist );
|
---|
213 |
|
---|
214 | } );
|
---|
215 |
|
---|
216 | signals.spaceChanged.add( function ( space ) {
|
---|
217 |
|
---|
218 | transformControls.setSpace( space );
|
---|
219 |
|
---|
220 | } );
|
---|
221 |
|
---|
222 | signals.rendererChanged.add( function ( type ) {
|
---|
223 |
|
---|
224 | container.dom.removeChild( renderer.domElement );
|
---|
225 |
|
---|
226 | renderer = new THREE[ type ]( { antialias: true } );
|
---|
227 | renderer.autoClear = false;
|
---|
228 | renderer.autoUpdateScene = false;
|
---|
229 | renderer.setClearColor( clearColor );
|
---|
230 | renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
|
---|
231 |
|
---|
232 | container.dom.appendChild( renderer.domElement );
|
---|
233 |
|
---|
234 | render();
|
---|
235 |
|
---|
236 | } );
|
---|
237 |
|
---|
238 | signals.sceneGraphChanged.add( function () {
|
---|
239 |
|
---|
240 | render();
|
---|
241 | updateInfo();
|
---|
242 |
|
---|
243 | } );
|
---|
244 |
|
---|
245 | signals.cameraChanged.add( function () {
|
---|
246 |
|
---|
247 | editor.config.setKey( 'camera', {
|
---|
248 | position: camera.position.toArray(),
|
---|
249 | target: controls.center.toArray()
|
---|
250 | } );
|
---|
251 |
|
---|
252 | render();
|
---|
253 |
|
---|
254 | } );
|
---|
255 |
|
---|
256 | signals.objectSelected.add( function ( object ) {
|
---|
257 |
|
---|
258 | selectionBox.visible = false;
|
---|
259 | transformControls.detach();
|
---|
260 |
|
---|
261 | if ( object !== null ) {
|
---|
262 |
|
---|
263 | if ( object.geometry !== undefined ) {
|
---|
264 |
|
---|
265 | selectionBox.update( object );
|
---|
266 | selectionBox.visible = true;
|
---|
267 |
|
---|
268 | }
|
---|
269 |
|
---|
270 | if ( object instanceof THREE.PerspectiveCamera === false ) {
|
---|
271 |
|
---|
272 | transformControls.attach( object );
|
---|
273 |
|
---|
274 | }
|
---|
275 |
|
---|
276 | }
|
---|
277 |
|
---|
278 | render();
|
---|
279 |
|
---|
280 | } );
|
---|
281 |
|
---|
282 | signals.objectAdded.add( function ( object ) {
|
---|
283 |
|
---|
284 | var materialsNeedUpdate = false;
|
---|
285 |
|
---|
286 | object.traverse( function ( child ) {
|
---|
287 |
|
---|
288 | if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
|
---|
289 |
|
---|
290 | objects.push( child );
|
---|
291 |
|
---|
292 | } );
|
---|
293 |
|
---|
294 | if ( materialsNeedUpdate === true ) updateMaterials();
|
---|
295 |
|
---|
296 | } );
|
---|
297 |
|
---|
298 | signals.objectChanged.add( function ( object ) {
|
---|
299 |
|
---|
300 | transformControls.update();
|
---|
301 |
|
---|
302 | if ( object !== camera ) {
|
---|
303 |
|
---|
304 | if ( object.geometry !== undefined ) {
|
---|
305 |
|
---|
306 | selectionBox.update( object );
|
---|
307 |
|
---|
308 | }
|
---|
309 |
|
---|
310 | if ( editor.helpers[ object.id ] !== undefined ) {
|
---|
311 |
|
---|
312 | editor.helpers[ object.id ].update();
|
---|
313 |
|
---|
314 | }
|
---|
315 |
|
---|
316 | updateInfo();
|
---|
317 |
|
---|
318 | }
|
---|
319 |
|
---|
320 | render();
|
---|
321 |
|
---|
322 | } );
|
---|
323 |
|
---|
324 | signals.objectRemoved.add( function ( object ) {
|
---|
325 |
|
---|
326 | var materialsNeedUpdate = false;
|
---|
327 |
|
---|
328 | object.traverse( function ( child ) {
|
---|
329 |
|
---|
330 | if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
|
---|
331 |
|
---|
332 | objects.splice( objects.indexOf( child ), 1 );
|
---|
333 |
|
---|
334 | } );
|
---|
335 |
|
---|
336 | if ( materialsNeedUpdate === true ) updateMaterials();
|
---|
337 |
|
---|
338 | } );
|
---|
339 |
|
---|
340 | signals.helperAdded.add( function ( object ) {
|
---|
341 |
|
---|
342 | objects.push( object.getObjectByName( 'picker' ) );
|
---|
343 |
|
---|
344 | } );
|
---|
345 |
|
---|
346 | signals.helperRemoved.add( function ( object ) {
|
---|
347 |
|
---|
348 | objects.splice( objects.indexOf( object.getObjectByName( 'picker' ) ), 1 );
|
---|
349 |
|
---|
350 | } );
|
---|
351 |
|
---|
352 | signals.materialChanged.add( function ( material ) {
|
---|
353 |
|
---|
354 | render();
|
---|
355 |
|
---|
356 | } );
|
---|
357 |
|
---|
358 | signals.fogTypeChanged.add( function ( fogType ) {
|
---|
359 |
|
---|
360 | if ( fogType !== oldFogType ) {
|
---|
361 |
|
---|
362 | if ( fogType === "None" ) {
|
---|
363 |
|
---|
364 | scene.fog = null;
|
---|
365 |
|
---|
366 | } else if ( fogType === "Fog" ) {
|
---|
367 |
|
---|
368 | scene.fog = new THREE.Fog( oldFogColor, oldFogNear, oldFogFar );
|
---|
369 |
|
---|
370 | } else if ( fogType === "FogExp2" ) {
|
---|
371 |
|
---|
372 | scene.fog = new THREE.FogExp2( oldFogColor, oldFogDensity );
|
---|
373 |
|
---|
374 | }
|
---|
375 |
|
---|
376 | updateMaterials();
|
---|
377 |
|
---|
378 | oldFogType = fogType;
|
---|
379 |
|
---|
380 | }
|
---|
381 |
|
---|
382 | render();
|
---|
383 |
|
---|
384 | } );
|
---|
385 |
|
---|
386 | signals.fogColorChanged.add( function ( fogColor ) {
|
---|
387 |
|
---|
388 | oldFogColor = fogColor;
|
---|
389 |
|
---|
390 | updateFog( scene );
|
---|
391 |
|
---|
392 | render();
|
---|
393 |
|
---|
394 | } );
|
---|
395 |
|
---|
396 | signals.fogParametersChanged.add( function ( near, far, density ) {
|
---|
397 |
|
---|
398 | oldFogNear = near;
|
---|
399 | oldFogFar = far;
|
---|
400 | oldFogDensity = density;
|
---|
401 |
|
---|
402 | updateFog( scene );
|
---|
403 |
|
---|
404 | render();
|
---|
405 |
|
---|
406 | } );
|
---|
407 |
|
---|
408 | signals.windowResize.add( function () {
|
---|
409 |
|
---|
410 | camera.aspect = container.dom.offsetWidth / container.dom.offsetHeight;
|
---|
411 | camera.updateProjectionMatrix();
|
---|
412 |
|
---|
413 | renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
|
---|
414 |
|
---|
415 | render();
|
---|
416 |
|
---|
417 | } );
|
---|
418 |
|
---|
419 | signals.playAnimations.add( function (animations) {
|
---|
420 |
|
---|
421 | function animate() {
|
---|
422 |
|
---|
423 | requestAnimationFrame( animate );
|
---|
424 |
|
---|
425 | for ( var i = 0; i < animations.length ; i ++ ) {
|
---|
426 |
|
---|
427 | animations[i].update(0.016);
|
---|
428 |
|
---|
429 | }
|
---|
430 |
|
---|
431 | render();
|
---|
432 | }
|
---|
433 |
|
---|
434 | animate();
|
---|
435 |
|
---|
436 | } );
|
---|
437 |
|
---|
438 | //
|
---|
439 |
|
---|
440 | var clearColor, renderer;
|
---|
441 |
|
---|
442 | if ( editor.config.getKey( 'renderer' ) !== undefined ) {
|
---|
443 |
|
---|
444 | renderer = new THREE[ editor.config.getKey( 'renderer' ) ]( { antialias: true } );
|
---|
445 |
|
---|
446 | } else {
|
---|
447 |
|
---|
448 | if ( System.support.webgl === true ) {
|
---|
449 |
|
---|
450 | renderer = new THREE.WebGLRenderer( { antialias: true } );
|
---|
451 |
|
---|
452 | } else {
|
---|
453 |
|
---|
454 | renderer = new THREE.CanvasRenderer();
|
---|
455 |
|
---|
456 | }
|
---|
457 |
|
---|
458 | }
|
---|
459 |
|
---|
460 | renderer.autoClear = false;
|
---|
461 | renderer.autoUpdateScene = false;
|
---|
462 | container.dom.appendChild( renderer.domElement );
|
---|
463 |
|
---|
464 | animate();
|
---|
465 |
|
---|
466 | //
|
---|
467 |
|
---|
468 | function updateInfo() {
|
---|
469 |
|
---|
470 | var objects = 0;
|
---|
471 | var vertices = 0;
|
---|
472 | var faces = 0;
|
---|
473 |
|
---|
474 | scene.traverse( function ( object ) {
|
---|
475 |
|
---|
476 | if ( object instanceof THREE.Mesh ) {
|
---|
477 |
|
---|
478 | objects ++;
|
---|
479 |
|
---|
480 | var geometry = object.geometry;
|
---|
481 |
|
---|
482 | if ( geometry instanceof THREE.Geometry ) {
|
---|
483 |
|
---|
484 | vertices += geometry.vertices.length;
|
---|
485 | faces += geometry.faces.length;
|
---|
486 |
|
---|
487 | } else if ( geometry instanceof THREE.BufferGeometry ) {
|
---|
488 |
|
---|
489 | vertices += geometry.attributes.position.array.length / 3;
|
---|
490 |
|
---|
491 | if ( geometry.attributes.index !== undefined ) {
|
---|
492 |
|
---|
493 | faces += geometry.attributes.index.array.length / 3;
|
---|
494 |
|
---|
495 | } else {
|
---|
496 |
|
---|
497 | faces += vertices / 3;
|
---|
498 |
|
---|
499 | }
|
---|
500 |
|
---|
501 | }
|
---|
502 |
|
---|
503 | }
|
---|
504 |
|
---|
505 | } );
|
---|
506 |
|
---|
507 | info.setValue( 'objects: ' + objects + ', vertices: ' + vertices + ', faces: ' + faces );
|
---|
508 |
|
---|
509 | }
|
---|
510 |
|
---|
511 | function updateMaterials() {
|
---|
512 |
|
---|
513 | editor.scene.traverse( function ( node ) {
|
---|
514 |
|
---|
515 | if ( node.material ) {
|
---|
516 |
|
---|
517 | node.material.needsUpdate = true;
|
---|
518 |
|
---|
519 | if ( node.material instanceof THREE.MeshFaceMaterial ) {
|
---|
520 |
|
---|
521 | for ( var i = 0; i < node.material.materials.length; i ++ ) {
|
---|
522 |
|
---|
523 | node.material.materials[ i ].needsUpdate = true;
|
---|
524 |
|
---|
525 | }
|
---|
526 |
|
---|
527 | }
|
---|
528 |
|
---|
529 | }
|
---|
530 |
|
---|
531 | } );
|
---|
532 |
|
---|
533 | }
|
---|
534 |
|
---|
535 | function updateFog( root ) {
|
---|
536 |
|
---|
537 | if ( root.fog ) {
|
---|
538 |
|
---|
539 | root.fog.color.setHex( oldFogColor );
|
---|
540 |
|
---|
541 | if ( root.fog.near !== undefined ) root.fog.near = oldFogNear;
|
---|
542 | if ( root.fog.far !== undefined ) root.fog.far = oldFogFar;
|
---|
543 | if ( root.fog.density !== undefined ) root.fog.density = oldFogDensity;
|
---|
544 |
|
---|
545 | }
|
---|
546 |
|
---|
547 | }
|
---|
548 |
|
---|
549 | function animate() {
|
---|
550 |
|
---|
551 | requestAnimationFrame( animate );
|
---|
552 |
|
---|
553 | }
|
---|
554 |
|
---|
555 | function render() {
|
---|
556 |
|
---|
557 | sceneHelpers.updateMatrixWorld();
|
---|
558 | scene.updateMatrixWorld();
|
---|
559 |
|
---|
560 | renderer.clear();
|
---|
561 | renderer.render( scene, camera );
|
---|
562 | renderer.render( sceneHelpers, camera );
|
---|
563 |
|
---|
564 | //console.trace();
|
---|
565 |
|
---|
566 | }
|
---|
567 |
|
---|
568 | return container;
|
---|
569 |
|
---|
570 | }
|
---|