API Docs for:
Show:

File: ../src/input.js


/**
* Input is a static class used to read the input state (keyboard, mouse, gamepad, etc)
*
* @class Input
* @namespace LS
* @constructor
*/
var Input = {
	mapping: {

		//xbox
		A_BUTTON: 0,
		B_BUTTON: 1,
		X_BUTTON: 2,
		Y_BUTTON: 3,
		LB_BUTTON: 4,
		RB_BUTTON: 5,
		BACK_BUTTON: 6,
		START_BUTTON: 7,
		LS_BUTTON: 8,
		RS_BUTTON: 9,

		LX: 0,
		LY: 1,
		RX: 2,
		RY: 3,
		TRIGGERS: 4,
		LEFT_TRIGGER: 4,
		RIGHT_TRIGGER: 5,

		//generic
		JUMP:0,
		FIRE:1,

		//mouse
		LEFT:0,
		MIDDLE:1,
		RIGHT:2
	},

	LEFT_MOUSE_BUTTON: 1,
	MIDDLE_MOUSE_BUTTON: 2,
	RIGHT_MOUSE_BUTTON: 3,

	Keyboard: [],
	Keyboard_previous: [],

	Mouse: {},
	Gamepads: [],

	//used for GUI elements
	last_mouse: null,
	last_click: null,
	current_click: null,
	current_key: null,
	keys_buffer: [], //array of keys that have been pressed from the last frame

	//_mouse_event_offset: [0,0],
	_last_frame: -1, //internal

	init: function()
	{
		this.Keyboard = gl.keys;
		this.Mouse = gl.mouse;
		this.Gamepads = gl.getGamepads();
	},

	reset: function()
	{
		this.Gamepads = gl.gamepads = []; //force reset so they send new events 
	},

	update: function()
	{
		//copy prev keys state
		for(var i = 0, l = this.Keyboard.length; i < l; ++i)
			this.Keyboard_previous[i] = this.Keyboard[i];

		//copy prev mouse state (this is only necessary if the update is not called from litegl main loop)
		this.Mouse.last_buttons = this.Mouse.buttons;

		//capture gamepads snapshot
		this.Gamepads = gl.getGamepads();
	},

	/**
	* returns true is the key is pressed now
	*
	* @method isKeyPressed
	* @param {Number} key_code
	* @return {boolean}
	*/
	isKeyPressed: function(key_code)
	{
		return !!this.Keyboard[ key_code ];
	},

	/**
	* returns true is the key was pressed between previous frame and now
	*
	* @method wasKeyPressed
	* @param {Number} key_code as in https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Browser_compatibility
	* @return {boolean}
	*/
	wasKeyPressed: function(key_code)
	{
		return this.Keyboard[ key_code ] && !this.Keyboard_previous[ key_code ];
	},

	/**
	* returns true is the mouse button is pressed now
	*
	* @method isMouseButtonPressed
	* @param {Number} button could be "left","middle","right" or GL.LEFT_MOUSE_BUTTON, GL.MIDDLE_MOUSE_BUTTON, GL.RIGHT_MOUSE_BUTTON
	* @return {boolean}
	*/
	isMouseButtonPressed: function(button)
	{
		var num = 0;
		if(button && button.constructor === String)
			num = this.mapping[button];
		else
			num = button;
		if(button === undefined)
			return false;

		return this.Mouse.isButtonPressed(num);
	},

	/**
	* returns true is the mouse button was pressed between previous frame and now
	*
	* @method wasMouseButtonPressed
	* @param {Number} button could be "left","middle","right" or GL.LEFT_MOUSE_BUTTON, GL.MIDDLE_MOUSE_BUTTON, GL.RIGHT_MOUSE_BUTTON
	* @return {boolean}
	*/
	wasMouseButtonPressed: function(button)
	{
		var num = 0;
		if(button && button.constructor === String)
			num = this.mapping[button];
		else
			num = button;
		if(button === undefined)
			return false;

		return this.Mouse.wasButtonPressed(num);
	},

	/**
	* locks the mouse (to use with first person view cameras) so when the mouse moves, the cameras moves
	*
	* @method lockMouse
	* @param {Boolean} v if true, the camera is locked, otherwise unlocked
	* @return {boolean}
	*/
	lockMouse: function(v)
	{
		if(v)
			gl.canvas.requestPointerLock();
		else
			document.exitPointerLock();
	},

	//called from LS.Player when onmouse
	//returns true if the event was blocked
	onMouse: function(e)
	{
		this.last_mouse = e;

		this.Mouse.mousex = e.mousex;
		this.Mouse.mousey = e.mousey;

		//save it in case we need to know where was the last click
		if(e.type == "mousedown")
		{
			this.current_click = e;
			LS.triggerCoroutines( "click", e );
		}
		else if(e.type == "mouseup")
			this.current_click = null;

		//we test if this event should be sent to the components or it was blocked by the GUI
		return LS.GUI.testEventInBlockedArea(e);
	},

	//called from LS.Player when onkey
	onKey: function(e)
	{
		if(e.type == "keydown")
		{
			this.current_key = e;
			if( LS.Renderer._frame != this._last_frame )
			{
				this.keys_buffer.length = 0;
				LS.Renderer._frame = this._last_frame;
			}
			if( this.keys_buffer.length < 10 ) //safety first!
				this.keys_buffer.push(e);
		}
		else
			this.current_key = null;
	},

	/**
	* returns if the mouse is inside the rect defined by x,y, width,height
	*
	* @method isMouseInRect
	* @param {Number} x x coordinate of the mouse in canvas coordinates 
	* @param {Number} y y coordinate of the mouse in canvas coordinates (0 is bottom)
	* @param {Number} width rectangle width in pixels
	* @param {Number} height rectangle height in pixels
	* @param {boolean} flip [optional] if you want to flip the y coordinate
	* @return {boolean}
	*/
	isMouseInRect: function( x, y, width, height, flip_y )
	{
		return this.Mouse.isInsideRect(x,y,width,height,flip_y);
	},

	isEventInRect: function( e, area, offset )
	{
		var offsetx = 0;
		var offsety = 0;
		if(offset)
		{
			offsetx = offset[0];
			offsety = offset[1];
		}
		return ( (e.mousex - offsetx) >= area[0] && (e.mousex - offsetx) < (area[0] + area[2]) && (e.mousey - offsety) >= area[1] && (e.mousey - offsety) < (area[1] + area[3]) );
	},

	/**
	* Returns a gamepad snapshot if it is connected
	*
	* @method getGamepad
	* @param {Number} index the index of the gamepad
	* @return {Object} gamepad snapshot with all the info
	*/
	getGamepad: function(index)
	{
		index = index || 0;
		return this.Gamepads[index];
	},

	/**
	* Returns a gamepad snapshot if it is connected
	*
	* @method getGamepadAxis
	* @param {Number} index the index of the gamepad
	* @param {String} name the name of the axis (also you could specify the number)
	* @param {boolean} raw [optional] if you want the data unfiltered
	* @return {Number} axis value from -1 to 1
	*/
	getGamepadAxis: function(index, name, raw)
	{
		var gamepad = this.Gamepads[index];
		if(!gamepad)
			return 0;

		var num = 0;
		if(name && name.constructor === String)
			num = this.mapping[name];
		else
			num = name;
		if(num === undefined)
			return 0;
		var v = gamepad.axes[num];
		if(!raw && v > -0.1 && v < 0.1 ) //filter
			return 0;
		return v;
	},

	/**
	* Returns if the given button of the specified gamepad is pressed
	*
	* @method isGamepadButtonPressed
	* @param {Number} index the index of the gamepad
	* @param {String} name the name of the button "A","B","X","Y","LB","RB","BACK","START","LS","RS" (also you could specify the number)
	* @return {Boolean} if the button is pressed
	*/
	isGamepadButtonPressed: function(input, name)
	{
		var gamepad = this.Gamepads[input];
		if(!gamepad)
			return null;

		var num = 0;
		if(name && name.constructor === String)
			num = this.mapping[name];
		else
			num = name;
		if(num === undefined)
			return 0;
		var button = gamepad.buttons[num];
		return button && button.pressed;
	},

	/**
	* Returns a Promise that will be fulfilled when the user clicks the screen
	* @method mouseClick
	* @return {Promise} 
	*/
	mouseClick: function()
	{
		return new Promise(function(resolve){
			LS.addWaitingCoroutine( resolve, "click" );
		});
	}
};


Object.defineProperty( MouseEvent.prototype, "getRay", { value: function(){
		//get camera under position
		var camera = LS.Renderer.getCameraAtPosition( this.mousex, this.mousey, LS.Renderer._visible_cameras );
		if(!camera)
			return null;
		//get ray
		return camera.getRay( this.mousex, this.mousey );
	},
	enumerable: false 
});

LS.Input = Input;