| Hey all, 
 Just spent a little while today adding gamepad support to the HTML5 target. It is currently on a pull request into official, but if you want to test it out or is not accepted into official then here it is below.
 
 Example:
 http://www.skn3.com/junk/gamepad/MonkeyGame.html
 
 In targets/html5/modules/native/html5game.js, make changes to the top of the file.
 
 You can see there are 2 blocks of code to add inbetween // --- start gamepad api by skn3 --------- and // --- end gamepad api by skn3 ---------
 
 
 var webglGraphicsSeq=1;
function BBHtml5Game( canvas ){
	BBGame.call( this );
	BBHtml5Game._game=this;
	this._canvas=canvas;
	this._loading=0;
	this._timerSeq=0;
	this._gl=null;
	
	if( CFG_OPENGL_GLES20_ENABLED=="1" ){
		//can't get these to fire!
		canvas.addEventListener( "webglcontextlost",function( event ){
			event.preventDefault();
//			print( "WebGL context lost!" );
		},false );
		canvas.addEventListener( "webglcontextrestored",function( event ){
			++webglGraphicsSeq;
//			print( "WebGL context restored!" );
		},false );
		var attrs={ alpha:false };
	
		this._gl=this._canvas.getContext( "webgl",attrs );
		if( !this._gl ) this._gl=this._canvas.getContext( "experimental-webgl",attrs );
		
		if( !this._gl ) this.Die( "Can't create WebGL" );
		
		gl=this._gl;
	}
	
	// --- start gamepad api by skn3 ---------
	this._gamepads = null;
	this._gamepadLookup = [-1,-1,-1,-1];//support 4 gamepads
	var that = this;
	window.addEventListener("gamepadconnected", function(e) {
		that.connectGamepad(e.gamepad);
	});
	
	window.addEventListener("gamepaddisconnected", function(e) {
		that.disconnectGamepad(e.gamepad);
	});
	
	//need to process already connected gamepads (before page was loaded)
	var gamepads = this.getGamepads();
	if (gamepads && gamepads.length > 0) {
		for(var index=0;index < gamepads.length;index++) {
			this.connectGamepad(gamepads[index]);
		}
	}
	// --- end gamepad api by skn3 ---------
}
BBHtml5Game.prototype=extend_class( BBGame );
BBHtml5Game.Html5Game=function(){
	return BBHtml5Game._game;
}
// --- start gamepad api by skn3 ---------
BBHtml5Game.prototype.getGamepads = function() {
	return navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : []);
}
BBHtml5Game.prototype.connectGamepad = function(gamepad) {
	if (!gamepad) {
		return false;
	}
	
	//check if this is a standard gamepad
	if (gamepad.mapping == "standard") {
		//yup so lets add it to an array of valid gamepads
		//find empty controller slot
		var slot = -1;
		for(var index = 0;index < this._gamepadLookup.length;index++) {
			if (this._gamepadLookup[index] == -1) {
				slot = index;
				break;
			}
		}
		
		//can we add this?
		if (slot != -1) {
			this._gamepadLookup[slot] = gamepad.index;
			
			//console.log("gamepad at html5 index "+gamepad.index+" mapped to monkey gamepad unit "+slot);
		}
	} else {
		console.log('Monkey has ignored gamepad at raw port #'+gamepad.index+' with unrecognised mapping scheme \''+gamepad.mapping+'\'.');
	}
}
BBHtml5Game.prototype.disconnectGamepad = function(gamepad) {
	if (!gamepad) {
		return false;
	}
	
	//scan all gamepads for matching index
	for(var index = 0;index < this._gamepadLookup.length;index++) {
		if (this._gamepadLookup[index] == gamepad.index) {
			//remove this gamepad
			this._gamepadLookup[index] = -1
			break;
		}
	}
}
BBHtml5Game.prototype.PollJoystick=function(port, joyx, joyy, joyz, buttons){
	//is this the first gamepad being polled
	if (port == 0) {
		//yes it is so we use the web api to get all gamepad info
		//we can then use this in subsequent calls to PollJoystick
		this._gamepads = this.getGamepads();
	}
	
	//dont bother processing if nothing to process
	if (!this._gamepads) {
	  return false;
	}
	
	//so use the monkey port to find the correct raw data
	var index = this._gamepadLookup[port];
	if (index == -1) {
		return false;
	}
	var gamepad = this._gamepads[index];
	if (!gamepad) {
		return false;
	}
	//so now process gamepad axis/buttons according to the standard mappings
	//https://w3c.github.io/gamepad/#remapping
	
	//left stick axis
	joyx[0] = gamepad.axes[0];
	joyy[0] = -gamepad.axes[1];
	
	//right stick axis
	joyx[1] = gamepad.axes[2];
	joyy[1] = -gamepad.axes[3];
	
	//triggers
	//emulate same functionality of GLFW
	joyz[0] = gamepad.buttons[6].value;
	joyz[1] = gamepad.buttons[7].value;
	
	//clear button states
	for(var index = 0;index <32;index++) {
		buttons[index] = false;
	}
	
	//map html5 "standard" mapping to monkeys joy codes
	/*
	Const JOY_A=0
	Const JOY_B=1
	Const JOY_X=2
	Const JOY_Y=3
	Const JOY_LB=4
	Const JOY_RB=5
	Const JOY_BACK=6
	Const JOY_START=7
	Const JOY_LEFT=8
	Const JOY_UP=9
	Const JOY_RIGHT=10
	Const JOY_DOWN=11
	Const JOY_LSB=12
	Const JOY_RSB=13
	Const JOY_MENU=14
	*/
	buttons[0] = gamepad.buttons[0] && gamepad.buttons[0].pressed;
	buttons[1] = gamepad.buttons[1] && gamepad.buttons[1].pressed;
	buttons[2] = gamepad.buttons[2] && gamepad.buttons[2].pressed;
	buttons[3] = gamepad.buttons[3] && gamepad.buttons[3].pressed;
	buttons[4] = gamepad.buttons[4] && gamepad.buttons[4].pressed;
	buttons[5] = gamepad.buttons[5] && gamepad.buttons[5].pressed;
	buttons[6] = gamepad.buttons[8] && gamepad.buttons[8].pressed;
	buttons[7] = gamepad.buttons[9] && gamepad.buttons[9].pressed;
	buttons[8] = gamepad.buttons[14] && gamepad.buttons[14].pressed;
	buttons[9] = gamepad.buttons[12] && gamepad.buttons[12].pressed;
	buttons[10] = gamepad.buttons[15] && gamepad.buttons[15].pressed;
	buttons[11] = gamepad.buttons[13] && gamepad.buttons[13].pressed;
	buttons[12] = gamepad.buttons[10] && gamepad.buttons[10].pressed;
	buttons[13] = gamepad.buttons[11] && gamepad.buttons[11].pressed;
	buttons[14] = gamepad.buttons[16] && gamepad.buttons[16].pressed;
	
	//success
	return true
}
// --- end gamepad api by skn3 ---------
 The code for the example uses mojo2 and is here:
 
 
Import mojo2
Function Main()
	New Game()
End
'app
Class Game Extends App
	Field canvas:Canvas
	
	Field stickLeft:Float[2]
	Field stickRight:Float[2]
	
	Field triggerLeft:float
	Field triggerRight:float
	
	Field buttons:Bool[JOY_MENU + 1]
	
	Method OnCreate()
		SetUpdateRate(60)
		canvas = New Canvas
	End
	Method OnUpdate()
		'update all states
		stickLeft[0] = JoyX(0)
		stickLeft[1] = JoyY(0)
		
		stickRight[0] = JoyX(1)
		stickRight[1] = JoyY(1)
		
		'have to do this (Max) otherwise GLFW seems to combine both triggers incorrectly!
		triggerLeft = Max(0.0, JoyZ(0))
		triggerRight = Max(0.0, JoyZ(1))
		
		For Local index:= JOY_A To JOY_MENU
			buttons[index] = JoyHit(index) Or JoyDown(index)
		Next
	End
	Method OnRender()
		canvas.Clear(0, 0, 0)
		
		Local padCenterX:= DeviceWidth() / 2.0
		Local padCenterY:= DeviceHeight() / 2.0
		
		'left stick
		DrawAnalog(canvas, padCenterX - 125, padCenterY - 50, 40, stickLeft[0], -stickLeft[1], buttons[JOY_LSB])
		
		'right stick
		DrawAnalog(canvas, padCenterX + 60, padCenterY + 50, 40, stickRight[0], -stickRight[1], buttons[JOY_RSB])
		
		'dpad
		DrawDPad(canvas, padCenterX - 100, padCenterY + 10, 80, buttons[JOY_UP], buttons[JOY_DOWN], buttons[JOY_LEFT], buttons[JOY_RIGHT])
		
		'left trigger
		DrawAxis(canvas, padCenterX - 165, padCenterY - 150, 80, 20, triggerLeft)
		
		'right trigger
		DrawAxis(canvas, padCenterX + 85, padCenterY - 150, 80, 20, triggerRight)
		
		'left shoulder
		DrawButton(canvas, padCenterX - 165, padCenterY - 120, 80, 20, buttons[JOY_LB])
		
		'right shoulder
		DrawButton(canvas, padCenterX + 85, padCenterY - 120, 80, 20, buttons[JOY_RB])
		
		'buttons
		Local buttonSize:= 30.0
		Local buttonCenterX:= padCenterX + 125
		Local buttonCenterY:= padCenterY - 50
		
		'a
		DrawButton(canvas, buttonCenterX, buttonCenterY + 40 - (buttonSize / 2.0), buttonSize / 2.0, buttons[JOY_A])
		'b
		DrawButton(canvas, buttonCenterX + 40 - (buttonSize / 2.0), buttonCenterY, buttonSize / 2.0, buttons[JOY_B])
				
		'x
		DrawButton(canvas, buttonCenterX - 40 + (buttonSize / 2.0), buttonCenterY, buttonSize / 2.0, buttons[JOY_X])
		
		'y
		DrawButton(canvas, buttonCenterX, buttonCenterY - 40 + (buttonSize / 2.0), buttonSize / 2.0, buttons[JOY_Y])
		
		'start
		DrawButton(canvas, padCenterX + buttonSize, buttonCenterY - (buttonSize / 4.0), buttonSize, buttonSize / 2.0, buttons[JOY_START])
		
		'back
		DrawButton(canvas, padCenterX - buttonSize - buttonSize, buttonCenterY - (buttonSize / 4.0), buttonSize, buttonSize / 2.0, buttons[JOY_BACK])
		
		'menu
		DrawButton(canvas, padCenterX, buttonCenterY, buttonSize * 0.75, buttons[JOY_MENU])
		
		
		canvas.Flush()
	End
End
'functions
Function DrawAxis:Void(canvas:Canvas, x:Float, y:float, width:Float, height:float, axis:float)
	canvas.SetColor(0.5, 0.5, 0.5)
	canvas.DrawRect(x, y, width, height)
		
	Local size:= Min(16.0, Max(2.0, width * 0.1))
	Local offset:= (width / 2.0) + (axis * ( (width - size) / 2.0)) - (size / 2.0)
		
	If offset >= 0 And offset < width
		canvas.SetColor(0.3, 0.3, 0.3)
		canvas.DrawRect(x + offset, y, size, height)
	EndIf
End
	
Function DrawDPad:Void(canvas:Canvas, x:Float, y:Float, size:Float, up:Bool, down:Bool, left:Bool, right:Bool)
	Local buttonSize:= size / 3.0
	Local buttonPadding:= Min(6.0, Max(2.0, size * 0.04))
		
	canvas.SetColor(0.5, 0.5, 0.5)
	canvas.DrawRect(x, y + buttonSize, size, buttonSize)
	canvas.DrawRect(x + buttonSize, y, buttonSize, size)
		
	canvas.SetColor(0.3, 0.3, 0.3)
	canvas.DrawRect(x + buttonSize, y + buttonSize, buttonSize, buttonSize)
		
	'up
	If up
		canvas.SetColor(0.0, 1.0, 0.0)
	Else
		canvas.SetColor(0.3, 0.3, 0.3)
	EndIf
	canvas.DrawRect(x + buttonSize + buttonPadding, y + buttonPadding, buttonSize - buttonPadding - buttonPadding, buttonSize - buttonPadding)
		
	'down
	If down
		canvas.SetColor(0.0, 1.0, 0.0)
	Else
		canvas.SetColor(0.3, 0.3, 0.3)
	EndIf
	canvas.DrawRect(x + buttonSize + buttonPadding, y + size - buttonSize, buttonSize - buttonPadding - buttonPadding, buttonSize - buttonPadding)
		
	'left
	If left
		canvas.SetColor(0.0, 1.0, 0.0)
	Else
		canvas.SetColor(0.3, 0.3, 0.3)
	EndIf
	canvas.DrawRect(x + buttonPadding, y + buttonSize + buttonPadding, buttonSize - buttonPadding, buttonSize - buttonPadding - buttonPadding)
		
	'right
	If right
		canvas.SetColor(0.0, 1.0, 0.0)
	Else
		canvas.SetColor(0.3, 0.3, 0.3)
	EndIf
	canvas.DrawRect(x + size - buttonSize, y + buttonSize + buttonPadding, buttonSize - buttonPadding, buttonSize - buttonPadding - buttonPadding)
End
	
Function DrawAnalog:Void(canvas:Canvas, x:Float, y:Float, radius:Float, axisX:Float, axisY:Float, pressed:Bool)
	Local padding:= Min(8.0, Max(1.0, radius * 0.1))
	
	canvas.SetColor(0.5, 0.5, 0.5)
	canvas.DrawCircle(x, y, radius)
	
	If pressed
		canvas.SetColor(0, 1.0, 0)
		canvas.DrawCircle(x, y, radius - padding)
	EndIf
	
	canvas.SetColor(0.3, 0.3, 0.3)
		
	Local length:= Sqrt( (axisX * axisX) + (axisY * axisY))
	Local size:= Min(19.0, Max(7.0, radius * 0.1))
	Local cursorX:Float
	Local cursorY:Float
		
	If length > 0
		Local ratio:Float
		If Abs(axisX) > Abs(axisY)
			ratio = Abs(axisX / 1.0) / length
		Else
			ratio = Abs(axisY / 1.0) / length
		EndIf
			
		cursorX = axisX * radius * ratio
		cursorY = axisY * radius * ratio
	EndIf
		
	DrawCross(canvas, x + cursorX - (size / 2.0), y + cursorY - (size / 2.0), size, size)
End
Function DrawCross:Void(canvas:Canvas, x:Float, y:Float, width:Float, height:Float, diagonal:Bool = True)
	' --- draw a cross ---
	If diagonal
		canvas.DrawLine(x, y, x + width, y + height)
		canvas.DrawLine(x + width, y, x, y + height)
	Else
		Local halfWidth:= width / 2.0
		Local halfHeight:= height / 2.0
		canvas.DrawLine(x + halfWidth, y, x + halfHeight, y + height)
		canvas.DrawLine(x, y + halfHeight, x + width, y + halfHeight)
	EndIf
End
	
Function DrawButton:Void(canvas:Canvas, x:Float, y:Float, radius:Float, pressed:Bool)
	Local padding:= Min(8.0, Max(1.0, radius * 0.1))
	
	canvas.SetColor(0.5, 0.5, 0.5)
	canvas.DrawCircle(x, y, radius)
	
	If pressed
		canvas.SetColor(0, 1.0, 0)
		canvas.DrawCircle(x, y, radius - padding)
	EndIf
End
Function DrawButton:Void(canvas:Canvas, x:Float, y:Float, width:Float, height:Float, pressed:Bool)
	Local padding:= Min(8.0, Max(1.0, width * 0.05))
	
	canvas.SetColor(0.5, 0.5, 0.5)
	canvas.DrawRect(x, y, width, height)
	
	If pressed
		canvas.SetColor(0, 1.0, 0)
		canvas.DrawRect(x + padding, y + padding, width - padding - padding, height - padding - padding)
	EndIf
End 
 
 |