Wrapper; Input; adding html5 gamepad support, still a few minor things to add (disconnect/reconnect like native) and initial event types for gamepad for native as well

This commit is contained in:
underscorediscovery
2014-01-26 21:55:16 -03:30
parent 6e7f85fb83
commit 143d25bb11
5 changed files with 317 additions and 21 deletions

View File

@@ -74,6 +74,12 @@ class InputHandler {
@:noCompletion public function update() {
//update any helper stuff
helper.update();
//remove any stale key pressed value
//unless it wasn't alive for a full frame yet,
//then flag it so that it may be
for(_value in key_value_pressed.keys()){
var _flag : Bool = key_value_pressed.get(_value);
@@ -85,6 +91,9 @@ class InputHandler {
} //each pressed_value
//remove any stale key released value
//unless it wasn't alive for a full frame yet,
//then flag it so that it may be
for(_value in key_value_released.keys()){
var _flag : Bool = key_value_released.get(_value);
@@ -486,12 +495,77 @@ class InputHandler {
//Gamepad
@:noCompletion public function lime_gamepadaxis(_event:Dynamic) : Void {
@:noCompletion public function lime_gamepadaxis( _event:Dynamic, ?_pass_through:Bool=false ) : Void {
if(lib.host.ongamepadaxis != null) {
lib.host.ongamepadaxis(_event);
}
var _gamepad_event = _event;
if(!_pass_through) {
_gamepad_event = {
raw : _event,
axis : _event.code,
value : (_event.value / 32767),
gamepad : _event.id
}
} //pass through
lib.host.ongamepadaxis( _gamepad_event );
} //lib.host.ongamepadaxis != null
} //lime_gamepadaxis
@:noCompletion public function lime_gamepadbuttondown( _event:Dynamic, ?_pass_through:Bool=false ) : Void {
if(lib.host.ongamepadbuttondown != null) {
var _gamepad_event = _event;
if(!_pass_through) {
_gamepad_event = {
raw : _event,
state : ButtonState.down,
value : 0,
button : _event.code,
gamepad : _event.id
};
}
lib.host.ongamepadbuttondown( _gamepad_event );
}
} //lime_gamepadbuttondown
@:noCompletion public function lime_gamepadbuttonup( _event:Dynamic, ?_pass_through:Bool=false ) : Void {
if(lib.host.ongamepadbuttonup != null) {
var _gamepad_event = _event;
if(!_pass_through) {
_gamepad_event = {
raw : _event,
state : ButtonState.up,
value : 1,
button : _event.code,
gamepad : _event.id
};
}
lib.host.ongamepadbuttonup( _gamepad_event );
}
} //lime_gamepadbuttonup
@:noCompletion public function lime_gamepadball(_event:Dynamic) : Void {
if(lib.host.ongamepadball != null) {
lib.host.ongamepadball(_event);
@@ -504,18 +578,6 @@ class InputHandler {
}
} //lime_gamepadhat
@:noCompletion public function lime_gamepadbuttondown(_event:Dynamic) : Void {
if(lib.host.ongamepadbuttondown != null) {
lib.host.ongamepadbuttondown(_event);
}
} //lime_gamepadbuttondown
@:noCompletion public function lime_gamepadbuttonup(_event:Dynamic) : Void {
if(lib.host.ongamepadbuttonup != null) {
lib.host.ongamepadbuttonup(_event);
}
} //lime_gamepadbuttonup
private static var efLeftDown = 0x0001;
private static var efShiftDown = 0x0002;
private static var efCtrlDown = 0x0004;
@@ -538,6 +600,11 @@ enum MouseState {
up;
}
enum ButtonState {
down;
up;
}
enum MouseButton {
move;
left;
@@ -586,5 +653,21 @@ typedef MouseEvent = {
typedef GamepadEvent = {
var raw : Dynamic;
var gamepad : Int;
}
typedef GamepadButtonEvent = {
var raw : Dynamic;
var gamepad : Int;
var button : Int;
var value : Float;
var state : ButtonState;
}
typedef GamepadAxisEvent = {
var raw : Dynamic;
var gamepad : Int;
var axis : Int;
var value : Float;
}

View File

@@ -1,5 +1,9 @@
package lime.helpers.html5;
import lime.InputHandler.GamepadEvent;
import lime.InputHandler.GamepadButtonEvent;
import lime.InputHandler.GamepadAxisEvent;
import lime.InputHandler.ButtonState;
import lime.InputHandler.MouseButton;
import lime.InputHandler.MouseState;
import lime.RenderHandler.BrowserLike;
@@ -19,13 +23,13 @@ class InputHelper {
public function startup() {
//right click on the canvas should be canceled on browser
lib.window_handle.addEventListener('contextmenu', on_contextmenu );
lib.window_handle.addEventListener('contextmenu', on_contextmenu );
//mouse events bind to the lime element only,
//maybe this should be adjusted for mousemove?
lib.window_handle.addEventListener('mousedown', on_mousedown);
lib.window_handle.addEventListener('mousemove', on_mousemove);
lib.window_handle.addEventListener('mouseup', on_mouseup);
lib.window_handle.addEventListener('mousedown', on_mousedown);
lib.window_handle.addEventListener('mousemove', on_mousemove);
lib.window_handle.addEventListener('mouseup', on_mouseup);
//there are two kinds of scroll across browser, we handle both
lib.window_handle.addEventListener('mousewheel', on_mousewheel);
@@ -35,8 +39,197 @@ class InputHelper {
js.Browser.document.addEventListener('keydown', on_keydown);
js.Browser.document.addEventListener('keyup', on_keyup);
//handle any gamepad information, if the browser supports it
startup_gamepads();
} //startup
@:noCompletion public function update() {
if(gamepads_supported) {
poll_gamepads();
}
}
function fail_gamepads() {
gamepads_supported = false;
trace("lime : Gamepads are not supported in this browser :(");
}
//if gamepads are supported, the method to get them will
//be stored in this variable for reuse
var gamepads_supported : Bool = false;
function startup_gamepads() {
active_gamepads = new Map();
gamepads_supported = (get_gamepad_list != null);
}
function poll_gamepads() {
var list = get_gamepad_list();
if(list != null) {
for(i in 0 ... list.length) {
if( untyped list[i] != null ) {
handle_gamepad( untyped list[i] );
}
}
}
} //poll_gamepads
//this will take some liberties for now
//because chrome and firefox share the same spec for
//the most part and all future implementations should
//follow spec too. If the spec changes we can adjust if needed
var active_gamepads : Map<Int, HTML5Gamepad>;
function handle_gamepad( _gamepad : Dynamic ) {
//disconnected gamepads we don't need
if(_gamepad == null) return;
//check if this gamepad exists already
if( !active_gamepads.exists( _gamepad.index ) ) {
//if not we add it to the list
active_gamepads.set( _gamepad.index, {
id : _gamepad.id,
index : _gamepad.index,
axes : cast _gamepad.axes,
buttons : cast _gamepad.buttons,
timestamp : _gamepad.timestamp
});
//fire an on connected event
// :todo:
} else {
//found in the list so we can update it if anything changed
var gamepad = active_gamepads.get(_gamepad.index);
//but only if the timestamp differs
if(gamepad.timestamp != _gamepad.timestamp) {
//update the id if it changed
if(gamepad.id != _gamepad.id) { gamepad.id = _gamepad.id; }
//update the timestamp
gamepad.timestamp = _gamepad.timestamp;
//we store the list of changed indices
//so we can call the handler functions with each
var axes_changed : Array<Int> = [];
var buttons_changed : Array<Int> = [];
//the last known values
var last_axes = gamepad.axes;
var last_buttons = gamepad.buttons;
//the new known values
var new_axes : Array<Float> = cast _gamepad.axes;
var new_buttons : Array<Int> = cast _gamepad.buttons;
//check for axes changes
var axis_index : Int = 0;
for(axis in new_axes) {
if(axis != last_axes[axis_index]) {
axes_changed.push(axis_index);
gamepad.axes[axis_index] = axis;
}
axis_index++;
} //axis in new_axes
//check for button changes
var button_index : Int = 0;
for(button in new_buttons) {
if(button != last_buttons[button_index]) {
buttons_changed.push(button_index);
gamepad.buttons[button_index] = button;
}
button_index++;
} //button in new_buttons
//now forward any axis changes to the wrapper
for(index in axes_changed) {
lib.input.lime_gamepadaxis({
raw : gamepad,
axis : index,
value : new_axes[index],
gamepad : gamepad.index
}, true);
} //for each axis changed
//then forward any button changes to the wrapper
for(index in buttons_changed) {
var _state = (new_buttons[index] == 0) ? ButtonState.up : ButtonState.down;
var _gamepad_event : GamepadButtonEvent = {
raw : gamepad,
state : _state,
value : new_buttons[index],
button : index,
gamepad : gamepad.index
};
if(_state == ButtonState.up) {
lib.input.lime_gamepadbuttonup( _gamepad_event, true );
} else {
lib.input.lime_gamepadbuttondown( _gamepad_event, true );
}
} //for each button change
} //timestamp changed
} //exists
} //handle_gamepad
//It's really early for gamepads in browser,
// but we can still support them where they exist
function get_gamepad_list() : Dynamic {
//Modernizr is used to detect gamepad support
var modernizr = untyped js.Browser.window.Modernizr;
if(modernizr != null) {
if(modernizr.gamepads == true) {
//try official api first
if( untyped js.Browser.navigator.getGamepads != null ) {
return untyped js.Browser.navigator.getGamepads();
}
//try newer webkit GetGamepads() function
if( untyped js.Browser.navigator.webkitGetGamepads != null ) {
return untyped js.Browser.navigator.webkitGetGamepads();
}
//if we make it here we failed support so fail out
fail_gamepads();
} else {
fail_gamepads();
}
} //modernizr != null
return null;
} //get_gamepad_list
function on_contextmenu( _event:Dynamic ) {
_event.preventDefault();
@@ -122,10 +315,12 @@ class InputHelper {
switch(lib.render.browser) {
case BrowserLike.chrome, BrowserLike.safari, BrowserLike.opera:
deltaX = untyped _event.webkitMovementX;
deltaY = untyped _event.webkitMovementY;
case BrowserLike.firefox:
deltaX = untyped _event.mozMovementX;
deltaY = untyped _event.mozMovementY;
@@ -205,3 +400,12 @@ class InputHelper {
} //on_keyup
} //InputHelper
typedef HTML5Gamepad = {
axes : Array<Float>,
index : Int,
buttons : Array<Int>,
id : String,
timestamp : Float
}

View File

@@ -12,7 +12,11 @@ class InputHelper {
} //new
public function startup() {
@:noCompletion public function startup() {
}
@:noCompletion public function update() {
}

View File

@@ -21,6 +21,7 @@
</style>
<script type="text/javascript" src="./lib/soundmanager/soundmanager2-nodebug-jsmin.js"></script>
<script type="text/javascript" src="./lib/modernizr.js"></script>
</head>

File diff suppressed because one or more lines are too long