Viewport.js 11.0 KB
Newer Older
1 2 3
var Viewport = function ( editor ) {

	var signals = editor.signals;
M
Mr.doob 已提交
4

M
Mr.doob 已提交
5 6
	var container = new UI.Panel();
	container.setPosition( 'absolute' );
M
Mr.doob 已提交
7

M
Mr.doob 已提交
8 9 10 11 12 13
	var info = new UI.Text();
	info.setPosition( 'absolute' );
	info.setRight( '5px' );
	info.setBottom( '5px' );
	info.setFontSize( '12px' );
	info.setColor( '#ffffff' );
14
	info.setValue( 'objects: 0, vertices: 0, faces: 0' );
M
Mr.doob 已提交
15 16
	container.add( info );

17 18 19
	var scene = editor.scene;
	var sceneHelpers = editor.sceneHelpers;

M
Mr.doob 已提交
20 21 22 23
	var objects = [];

	// helpers

M
Mr.doob 已提交
24
	var grid = new THREE.GridHelper( 500, 25 );
M
Mr.doob 已提交
25 26
	sceneHelpers.add( grid );

A
Aleksandar Rodic 已提交
27 28
	//

29
	var camera = new THREE.PerspectiveCamera( 50, 1, 1, 5000 );
M
Mr.doob 已提交
30 31
	camera.position.fromArray( editor.config.getKey( 'camera' ).position );
	camera.lookAt( new THREE.Vector3().fromArray( editor.config.getKey( 'camera' ).target ) );
32

A
Aleksandar Rodic 已提交
33
	//
M
Mr.doob 已提交
34

M
Mr.doob 已提交
35
	var selectionBox = new THREE.BoxHelper();
36 37
	selectionBox.material.depthTest = false;
	selectionBox.material.transparent = true;
M
Mr.doob 已提交
38
	selectionBox.visible = false;
39 40
	sceneHelpers.add( selectionBox );

41 42 43
	var transformControls = new THREE.TransformControls( camera, container.dom );
	transformControls.addEventListener( 'change', function () {

M
Mr.doob 已提交
44
		controls.enabled = true;
45

M
Mr.doob 已提交
46
		if ( transformControls.axis !== null ) {
M
Mr.doob 已提交
47 48 49 50 51

			controls.enabled = false;

		}

52
		render();
M
Mr.doob 已提交
53

54 55
	} );
	transformControls.addEventListener( 'objectChange', function () {
M
Mr.doob 已提交
56

57
		signals.objectChanged.dispatch( transformControls.object );
58 59

	} );
60
	sceneHelpers.add( transformControls );
A
alteredq 已提交
61

M
Mr.doob 已提交
62
	// fog
63

M
Mr.doob 已提交
64 65 66 67 68
	var oldFogType = "None";
	var oldFogColor = 0xaaaaaa;
	var oldFogNear = 1;
	var oldFogFar = 5000;
	var oldFogDensity = 0.00025;
69

70 71
	// object picking

72
	var ray = new THREE.Raycaster();
73
	var projector = new THREE.Projector();
74

75 76
	// events

77 78
	var getIntersects = function ( event, object ) {

M
Mr.doob 已提交
79
		var rect = container.dom.getBoundingClientRect();
80 81
		x = ( event.clientX - rect.left ) / rect.width;
		y = ( event.clientY - rect.top ) / rect.height;
82
		var vector = new THREE.Vector3( ( x ) * 2 - 1, - ( y ) * 2 + 1, 0.5 );
83 84 85 86 87 88 89

		projector.unprojectVector( vector, camera );

		ray.set( camera.position, vector.sub( camera.position ).normalize() );

		if ( object instanceof Array ) {

90
			return ray.intersectObjects( object );
91 92 93

		}

94
		return ray.intersectObject( object );
95 96 97

	};

M
Mr.doob 已提交
98 99 100
	var onMouseDownPosition = new THREE.Vector2();
	var onMouseUpPosition = new THREE.Vector2();

101
	var onMouseDown = function ( event ) {
102

M
Mr.doob 已提交
103 104
		event.preventDefault();

M
Mr.doob 已提交
105 106 107
		var rect = container.dom.getBoundingClientRect();
		x = (event.clientX - rect.left) / rect.width;
		y = (event.clientY - rect.top) / rect.height;
108
		onMouseDownPosition.set( x, y );
109

110
		document.addEventListener( 'mouseup', onMouseUp, false );
111

112
	};
113

114
	var onMouseUp = function ( event ) {
115

M
Mr.doob 已提交
116 117 118
		var rect = container.dom.getBoundingClientRect();
		x = (event.clientX - rect.left) / rect.width;
		y = (event.clientY - rect.top) / rect.height;
119
		onMouseUpPosition.set( x, y );
120

121
		if ( onMouseDownPosition.distanceTo( onMouseUpPosition ) == 0 ) {
M
Mr.doob 已提交
122

M
Mr.doob 已提交
123
			var intersects = getIntersects( event, objects );
M
Mr.doob 已提交
124

M
Mr.doob 已提交
125
			if ( intersects.length > 0 ) {
M
Mr.doob 已提交
126

M
Mr.doob 已提交
127 128
				var object = intersects[ 0 ].object;

129
				if ( object.userData.object !== undefined ) {
130

131 132
					// helper

133
					editor.select( object.userData.object );
M
Mr.doob 已提交
134

135 136 137
				} else {

					editor.select( object );
138

M
Mr.doob 已提交
139
				}
140

M
Mr.doob 已提交
141 142
			} else {

143
				editor.select( null );
M
Mr.doob 已提交
144

M
Mr.doob 已提交
145
			}
M
Mr.doob 已提交
146

M
Mr.doob 已提交
147
			render();
148

149 150
		}

M
Mr.doob 已提交
151
		document.removeEventListener( 'mouseup', onMouseUp );
152

153
	};
154

155 156
	var onDoubleClick = function ( event ) {

M
Mr.doob 已提交
157
		var intersects = getIntersects( event, objects );
158

M
Mr.doob 已提交
159
		if ( intersects.length > 0 && intersects[ 0 ].object === editor.selected ) {
160

M
Mr.doob 已提交
161
			controls.focus( editor.selected );
162

M
Mr.doob 已提交
163
		}
164 165 166

	};

167
	container.dom.addEventListener( 'mousedown', onMouseDown, false );
168
	container.dom.addEventListener( 'dblclick', onDoubleClick, false );
169

170 171 172
	// controls need to be added *after* main logic,
	// otherwise controls.enabled doesn't work.

M
Mr.doob 已提交
173
	var controls = new THREE.EditorControls( camera, container.dom );
M
Mr.doob 已提交
174
	controls.center.fromArray( editor.config.getKey( 'camera' ).target )
175
	controls.addEventListener( 'change', function () {
176

177
		transformControls.update();
178
		signals.cameraChanged.dispatch( camera );
179

180
	} );
181

182
	// signals
183

184 185 186 187
	signals.themeChanged.add( function ( value ) {

		switch ( value ) {

M
Mr.doob 已提交
188 189
			case 'css/light.css':
				grid.setColors( 0x444444, 0x888888 );
190
				clearColor = 0xaaaaaa;
M
Mr.doob 已提交
191 192 193
				break;
			case 'css/dark.css':
				grid.setColors( 0xbbbbbb, 0x888888 );
194
				clearColor = 0x333333;
M
Mr.doob 已提交
195
				break;
196 197

		}
198 199
		
		renderer.setClearColor( clearColor );
200 201 202 203 204

		render();

	} );

M
Mr.doob 已提交
205
	signals.transformModeChanged.add( function ( mode ) {
M
Mr.doob 已提交
206

207
		transformControls.setMode( mode );
A
Aleksandar Rodic 已提交
208 209 210 211 212

	} );

	signals.snapChanged.add( function ( dist ) {

213
		transformControls.setSnap( dist );
M
Mr.doob 已提交
214 215 216

	} );

217
	signals.spaceChanged.add( function ( space ) {
M
Mr.doob 已提交
218

219
		transformControls.setSpace( space );
M
Mr.doob 已提交
220 221 222

	} );

M
Mr.doob 已提交
223
	signals.rendererChanged.add( function ( type ) {
224

225
		container.dom.removeChild( renderer.domElement );
226

M
Mr.doob 已提交
227
		renderer = new THREE[ type ]( { antialias: true } );
228 229
		renderer.autoClear = false;
		renderer.autoUpdateScene = false;
230
		renderer.setClearColor( clearColor );
231
		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
M
Mr.doob 已提交
232

233
		container.dom.appendChild( renderer.domElement );
M
Mr.doob 已提交
234

235
		render();
M
Mr.doob 已提交
236

237
	} );
238

239 240 241 242 243 244 245
	signals.sceneGraphChanged.add( function () {

		render();
		updateInfo();

	} );

246 247
	var saveTimeout;

248 249
	signals.cameraChanged.add( function () {

250 251 252 253 254 255 256 257 258 259 260 261 262 263
		if ( saveTimeout !== undefined ) {

			clearTimeout( saveTimeout );

		}

		saveTimeout = setTimeout( function () {

			editor.config.setKey( 'camera', {
				position: camera.position.toArray(),
				target: controls.center.toArray()
			} );

		}, 1000 );
M
Mr.doob 已提交
264

265 266 267 268
		render();

	} );

M
Mr.doob 已提交
269
	signals.objectSelected.add( function ( object ) {
270

M
Mr.doob 已提交
271 272
		selectionBox.visible = false;
		transformControls.detach();
M
Mr.doob 已提交
273

M
Mr.doob 已提交
274
		if ( object !== null ) {
M
Mr.doob 已提交
275

276 277
			if ( object.geometry !== undefined &&
				 object instanceof THREE.Sprite === false ) {
M
Mr.doob 已提交
278 279 280 281 282 283

				selectionBox.update( object );
				selectionBox.visible = true;

			}

M
Mr.doob 已提交
284
			if ( object instanceof THREE.PerspectiveCamera === false ) {
M
Mr.doob 已提交
285

M
Mr.doob 已提交
286
				transformControls.attach( object );
M
Mr.doob 已提交
287 288 289 290

			}

		}
M
Mr.doob 已提交
291

292
		render();
M
Mr.doob 已提交
293 294 295

	} );

M
Mr.doob 已提交
296 297
	signals.objectAdded.add( function ( object ) {

298
		var materialsNeedUpdate = false;
299

300 301
		object.traverse( function ( child ) {

302 303
			if ( child instanceof THREE.Light ) materialsNeedUpdate = true;

304 305 306 307
			objects.push( child );

		} );

308 309
		if ( materialsNeedUpdate === true ) updateMaterials();

M
Mr.doob 已提交
310 311
	} );

312
	signals.objectChanged.add( function ( object ) {
313

314
		transformControls.update();
M
Mr.doob 已提交
315

316
		if ( object !== camera ) {
M
Mr.doob 已提交
317

318 319 320
			if ( object.geometry !== undefined ) {

				selectionBox.update( object );
M
Mr.doob 已提交
321

322
			}
M
Mr.doob 已提交
323

324
			if ( editor.helpers[ object.id ] !== undefined ) {
M
Mr.doob 已提交
325

326
				editor.helpers[ object.id ].update();
M
Mr.doob 已提交
327

328 329 330 331 332
			}

			updateInfo();

		}
333

334
		render();
335

M
Mr.doob 已提交
336 337 338 339
	} );

	signals.objectRemoved.add( function ( object ) {

340
		var materialsNeedUpdate = false;
M
Mr.doob 已提交
341

342
		object.traverse( function ( child ) {
M
Mr.doob 已提交
343

344 345 346
			if ( child instanceof THREE.Light ) materialsNeedUpdate = true;

			objects.splice( objects.indexOf( child ), 1 );
M
Mr.doob 已提交
347

348 349 350
		} );

		if ( materialsNeedUpdate === true ) updateMaterials();
351 352 353 354 355

	} );

	signals.helperAdded.add( function ( object ) {

M
Mr.doob 已提交
356
		objects.push( object.getObjectByName( 'picker' ) );
357 358 359 360 361

	} );

	signals.helperRemoved.add( function ( object ) {

M
Mr.doob 已提交
362
		objects.splice( objects.indexOf( object.getObjectByName( 'picker' ) ), 1 );
363

364 365
	} );

M
Mr.doob 已提交
366
	signals.materialChanged.add( function ( material ) {
367 368 369 370 371

		render();

	} );

M
Mr.doob 已提交
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	signals.fogTypeChanged.add( function ( fogType ) {

		if ( fogType !== oldFogType ) {

			if ( fogType === "None" ) {

				scene.fog = null;

			} else if ( fogType === "Fog" ) {

				scene.fog = new THREE.Fog( oldFogColor, oldFogNear, oldFogFar );

			} else if ( fogType === "FogExp2" ) {

				scene.fog = new THREE.FogExp2( oldFogColor, oldFogDensity );

			}

M
Mr.doob 已提交
390
			updateMaterials();
M
Mr.doob 已提交
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416

			oldFogType = fogType;

		}

		render();

	} );

	signals.fogColorChanged.add( function ( fogColor ) {

		oldFogColor = fogColor;

		updateFog( scene );

		render();

	} );

	signals.fogParametersChanged.add( function ( near, far, density ) {

		oldFogNear = near;
		oldFogFar = far;
		oldFogDensity = density;

		updateFog( scene );
417 418 419 420 421

		render();

	} );

422 423 424 425 426 427 428 429 430 431 432
	signals.windowResize.add( function () {

		camera.aspect = container.dom.offsetWidth / container.dom.offsetHeight;
		camera.updateProjectionMatrix();

		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );

		render();

	} );

433
	var animations = [];
434

435
	signals.playAnimation.add( function ( animation ) {
436

437
		animations.push( animation );
438

439
	} );
M
Mr.doob 已提交
440

441
	signals.stopAnimation.add( function ( animation ) {
442

443 444 445 446 447 448 449
		var index = animations.indexOf( animation );

		if ( index !== -1 ) {

			animations.splice( index, 1 );

		}
450 451

	} );
452

453 454
	//

455
	var clearColor, renderer;
456

M
Mr.doob 已提交
457
	if ( editor.config.getKey( 'renderer' ) !== undefined ) {
458

M
Mr.doob 已提交
459
		renderer = new THREE[ editor.config.getKey( 'renderer' ) ]( { antialias: true } );
460 461 462

	} else {

M
Mr.doob 已提交
463 464 465 466 467 468 469 470 471
		if ( System.support.webgl === true ) {

			renderer = new THREE.WebGLRenderer( { antialias: true } );

		} else {

			renderer = new THREE.CanvasRenderer();

		}
472 473 474

	}

M
Mr.doob 已提交
475
	renderer.autoClear = false;
476
	renderer.autoUpdateScene = false;
M
Mr.doob 已提交
477 478 479 480 481 482
	container.dom.appendChild( renderer.domElement );

	animate();

	//

M
Mr.doob 已提交
483 484 485 486 487 488 489 490 491 492 493
	function updateInfo() {

		var objects = 0;
		var vertices = 0;
		var faces = 0;

		scene.traverse( function ( object ) {

			if ( object instanceof THREE.Mesh ) {

				objects ++;
494 495 496 497 498 499 500 501 502 503

				var geometry = object.geometry;

				if ( geometry instanceof THREE.Geometry ) {

					vertices += geometry.vertices.length;
					faces += geometry.faces.length;

				} else if ( geometry instanceof THREE.BufferGeometry ) {

504
					vertices += geometry.attributes.position.array.length / 3;
505 506 507

					if ( geometry.attributes.index !== undefined ) {

508
						faces += geometry.attributes.index.array.length / 3;
509 510 511

					} else {

M
Mr.doob 已提交
512
						faces += geometry.attributes.position.array.length / 9;
513 514

					}
515 516

				}
M
Mr.doob 已提交
517 518 519 520 521 522 523 524 525

			}

		} );

		info.setValue( 'objects: ' + objects + ', vertices: ' + vertices + ', faces: ' + faces );

	}

M
Mr.doob 已提交
526
	function updateMaterials() {
M
Mr.doob 已提交
527

M
Mr.doob 已提交
528
		editor.scene.traverse( function ( node ) {
M
Mr.doob 已提交
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563

			if ( node.material ) {

				node.material.needsUpdate = true;

				if ( node.material instanceof THREE.MeshFaceMaterial ) {

					for ( var i = 0; i < node.material.materials.length; i ++ ) {

						node.material.materials[ i ].needsUpdate = true;

					}

				}

			}

		} );

	}

	function updateFog( root ) {

		if ( root.fog ) {

			root.fog.color.setHex( oldFogColor );

			if ( root.fog.near !== undefined ) root.fog.near = oldFogNear;
			if ( root.fog.far !== undefined ) root.fog.far = oldFogFar;
			if ( root.fog.density !== undefined ) root.fog.density = oldFogDensity;

		}

	}

M
Mr.doob 已提交
564 565 566 567
	function animate() {

		requestAnimationFrame( animate );

568 569 570 571 572 573
		// animations

		if ( THREE.AnimationHandler.animations.length > 0 ) {

			THREE.AnimationHandler.update( 0.016 );

M
Mr.doob 已提交
574 575 576 577 578 579 580 581 582 583 584 585
			for ( var i = 0, l = sceneHelpers.children.length; i < l; i ++ ) {

				var helper = sceneHelpers.children[ i ];

				if ( helper instanceof THREE.SkeletonHelper ) {

					helper.update();

				}

			}

586 587 588 589
			render();

		}

M
Mr.doob 已提交
590 591 592 593
	}

	function render() {

M
Mr.doob 已提交
594
		sceneHelpers.updateMatrixWorld();
M
Mr.doob 已提交
595
		scene.updateMatrixWorld();
596

M
Mr.doob 已提交
597
		renderer.clear();
M
Mr.doob 已提交
598
		renderer.render( scene, camera );
M
Mr.doob 已提交
599 600 601 602 603 604

		if ( renderer instanceof THREE.RaytracingRenderer === false ) {

			renderer.render( sceneHelpers, camera );

		}
M
Mr.doob 已提交
605 606 607 608 609 610

	}

	return container;

}