Home Reference Source

scripts/three/hud.js

import {EventDispatcher, Scene as ThreeScene, Geometry, Vector3, LineBasicMaterial, CylinderGeometry, MeshBasicMaterial, Mesh, SphereGeometry, Object3D, LineSegments} from 'three';

import {EVENT_ITEM_SELECTED, EVENT_ITEM_UNSELECTED} from '../core/events.js';

//As far as I understand the HUD is here to show a rotation control on every item
//If this idea is correct then it seriously sucks. A whole rendering to show just cones and lines as arrows?
export class HUD extends EventDispatcher
{
	constructor(three, scene)
	{
		super();
		this.three = three;
		if(!scene)
		{
			this.scene = new ThreeScene();
		}
			
		else
		{
			this.scene = scene;
		}
		
		this.selectedItem = null;
		
		this.rotating = false;
		this.mouseover = false;
		
		this.tolerance = 10;
		this.height = 5;
		this.distance = 20;
		
		this.color = '#ffffff';
		this.hoverColor = '#f1c40f';
		
		this.activeObject = null;
		
		var scope = this;
		this.itemselectedevent = (o) => {scope.itemSelected(o.item);};
		this.itemunselectedevent = () => {scope.itemUnselected();};
		
		this.init();
	}
	
	init() 
	{
//		this.three.itemSelectedCallbacks.add(itemSelected);
//		this.three.itemUnselectedCallbacks.add(itemUnselected);
		this.three.addEventListener(EVENT_ITEM_SELECTED, this.itemselectedevent);
		this.three.addEventListener(EVENT_ITEM_UNSELECTED, this.itemunselectedevent);
	}
	
	getScene() 
	{
		return this.scene;
	}

	getObject() 
	{
		return this.activeObject;
	}
	
	
	resetSelectedItem() 
	{
		this.selectedItem = null;
		if (this.activeObject) 
		{
			this.scene.remove(this.activeObject);
			this.activeObject = null;
		}
	}

	itemSelected(item) 
	{
		if (this.selectedItem != item) 
		{
			this.resetSelectedItem();
			if (item.allowRotate && !item.fixed) 
			{
				this.selectedItem = item;
				this.activeObject = this.makeObject(this.selectedItem);
				this.scene.add(this.activeObject);
			}
		}
	}

	itemUnselected() 
	{
		this.resetSelectedItem();
	}

	setRotating(isRotating) 
	{
		this.rotating = isRotating;
		this.setColor();
	}

	setMouseover(isMousedOver) 
	{
		this.mouseover = isMousedOver;
		this.setColor();
	}

	setColor() 
	{
		var scope = this;
		if (scope.activeObject) 
		{
			scope.activeObject.children.forEach((obj) => {obj.material.color.set(scope.getColor());});
		}
//		this.three.needsUpdate();
		scope.three.ensureNeedsUpdate();
	}

	getColor()
	{
		return (this.mouseover || this.rotating) ? this.hoverColor : this.color;
	}

	update() 
	{
		if (this.activeObject) 
		{
			this.activeObject.rotation.y = this.selectedItem.rotation.y;
			this.activeObject.position.x = this.selectedItem.position.x;
			this.activeObject.position.z = this.selectedItem.position.z;
		}
	}

	makeLineGeometry(item) 
	{
		var geometry = new Geometry();
		geometry.vertices.push(new Vector3(0, 0, 0),this.rotateVector(item));
		return geometry;
	}

	rotateVector(item) 
	{
		var vec = new Vector3(0, 0,Math.max(item.halfSize.x, item.halfSize.z) + 1.4 + this.distance);
		return vec;
	}

	makeLineMaterial() 
	{
		var mat = new LineBasicMaterial({color: this.getColor(),linewidth: 3});
		return mat;
	}

	makeCone(item) 
	{
		var coneGeo = new CylinderGeometry(5, 0, 10);
		var coneMat = new MeshBasicMaterial({color: this.getColor()});
		var cone = new Mesh(coneGeo, coneMat);
		cone.position.copy(this.rotateVector(item));
		cone.rotation.x = -Math.PI / 2.0;
		return cone;
	}

	makeSphere() 
	{
		var geometry = new SphereGeometry(4, 16, 16);
		var material = new MeshBasicMaterial({color: this.getColor()});
		var sphere = new Mesh(geometry, material);
		return sphere;
	}

	makeObject(item) 
	{
		var object = new Object3D();
		var line = new LineSegments(this.makeLineGeometry(item),this.makeLineMaterial(this.rotating));
		var cone = this.makeCone(item);
		var sphere = this.makeSphere(item);
		object.add(line);
		object.add(cone);
		object.add(sphere);
		object.rotation.y = item.rotation.y;
		object.position.x = item.position.x;
		object.position.z = item.position.z;
		object.position.y = this.height;
		return object;
	}
}