Home Reference Source

scripts/model/wall.js

import {EventDispatcher, Vector2} from 'three';
import {EVENT_ACTION,EVENT_MOVED,EVENT_DELETED} from '../core/events.js';
import {Configuration,configWallThickness,configWallHeight} from '../core/configuration.js';
import {Utils} from '../core/utils.js';


/** The default wall texture. */
export const defaultWallTexture = {url: 'rooms/textures/wallmap.png', stretch: true, scale: 0};

/**
 * A Wall is the basic element to create Rooms.
 *
 * Walls consists of two half edges.
 */
export class Wall extends EventDispatcher
{
	/**
	 * Constructs a new wall.
	 * @param start Start corner.
	 * @param end End corner.
	 */
	constructor(start, end)
	{
		super();
		this.start = start;
		this.end = end;
		this.name = 'wall';

		this.id = this.getUuid();

		this.start.attachStart(this);
		this.end.attachEnd(this);

		/** Front is the plane from start to end. */
		this.frontEdge = null;

		/** Back is the plane from end to start. */
		this.backEdge = null;

		/** */
		this.orphan = false;

		/** Items attached to this wall */
		this.items = [];

		/** */
		this.onItems = [];

		/** The front-side texture. */
		this.frontTexture = defaultWallTexture;

		/** The back-side texture. */
		this.backTexture = defaultWallTexture;

		/** Wall thickness. */
		this.thickness = Configuration.getNumericValue(configWallThickness);

		/** Wall height. */
		this.height = Configuration.getNumericValue(configWallHeight);

		/** Actions to be applied after movement. */
		this.moved_callbacks = null;

		/** Actions to be applied on removal. */
		this.deleted_callbacks = null;

		/** Actions to be applied explicitly. */
		this.action_callbacks = null;
	}

	getUuid()
	{
		return [this.start.id, this.end.id].join();
	}

	resetFrontBack()
	{
		this.frontEdge = null;
		this.backEdge = null;
		this.orphan = false;
	}

	snapToAxis(tolerance)
	{
		// order here is important, but unfortunately arbitrary
		this.start.snapToAxis(tolerance);
		this.end.snapToAxis(tolerance);
	}

	fireOnMove(func)
	{
		this.moved_callbacks.add(func);
	}

	fireOnDelete(func)
	{
		this.deleted_callbacks.add(func);
	}

	dontFireOnDelete(func)
	{
		this.deleted_callbacks.remove(func);
	}

	fireOnAction(func)
	{
		this.action_callbacks.add(func);
	}

	fireAction(action)
	{
		this.dispatchEvent({type:EVENT_ACTION, action: action});
		//this.action_callbacks.fire(action);
	}

	relativeMove(dx, dy)
	{
		this.start.relativeMove(dx, dy);
		this.end.relativeMove(dx, dy);
	}

	fireMoved()
	{
		this.dispatchEvent({type: EVENT_MOVED, position: null});
	}

	fireRedraw()
	{
		if (this.frontEdge)
		{
//			this.frontEdge.dispatchEvent({type: EVENT_REDRAW});
			this.frontEdge.dispatchRedrawEvent();
			//this.frontEdge.redrawCallbacks.fire();
		}
		if (this.backEdge)
		{
//			this.backEdge.dispatchEvent({type: EVENT_REDRAW});
			this.backEdge.dispatchRedrawEvent();
			//this.backEdge.redrawCallbacks.fire();
		}
	}

	getStart()
	{
		return this.start;
	}

	getEnd()
	{
		return this.end;
	}

	getStartX()
	{
		return this.start.getX();
	}

	getEndX()
	{
		return this.end.getX();
	}

	getStartY()
	{
		return this.start.getY();
	}

	getEndY()
	{
		return this.end.getY();
	}

	wallLength()
	{
		var start = this.getStart();
		var end = this.getEnd();
		return Utils.distance(start, end);
	}

	wallCenter()
	{
		return new Vector2((this.getStart().x + this.getEnd().x) / 2.0, (this.getStart().y + this.getEnd().y) / 2.0);
	}

	remove()
	{
		this.start.detachWall(this);
		this.end.detachWall(this);
		this.dispatchEvent({type:EVENT_DELETED, item: this});
		//this.deleted_callbacks.fire(this);
	}

	setStart(corner)
	{
		this.start.detachWall(this);
		corner.attachStart(this);
		this.start = corner;
		this.fireMoved();
	}

	setEnd(corner)
	{
		this.end.detachWall(this);
		corner.attachEnd(this);
		this.end = corner;
		this.fireMoved();
	}

	distanceFrom(point)
	{
		return Utils.pointDistanceFromLine(point, new Vector2(this.getStartX(), this.getStartY()), new Vector2(this.getEndX(), this.getEndY()));
	}

	/** Return the corner opposite of the one provided.
	 * @param corner The given corner.
	 * @returns The opposite corner.
	 */
	oppositeCorner(corner)
	{
		if (this.start === corner)
		{
			return this.end;
		}
		else if (this.end === corner)
		{
			return this.start;
		}
		else
		{
			console.log('Wall does not connect to corner');
			return null;
		}
	}

  getClosestCorner(point)
	{
			var startVector = new Vector2(this.start.x, this.start.y);
			var endVector = new Vector2(this.end.x, this.end.y);
      if(point.distanceTo(startVector) < 10)
			{
				return this.start;
			}
			else if(point.distanceTo(endVector) < 10)
			{
				return this.end;
			}
			return null;
	}

	updateAttachedRooms()
	{
		if(this.start != null)
		{
				this.start.updateAttachedRooms();
		}
		if(this.end)
		{
			this.end.updateAttachedRooms();
		}
	}
}