Home | History | Annotate | Download | only in support
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.controllers.gwt.support;
     18 
     19 import com.badlogic.gdx.utils.IntMap;
     20 import com.google.gwt.animation.client.AnimationScheduler;
     21 import com.google.gwt.core.client.JavaScriptObject;
     22 import com.google.gwt.core.client.JsArray;
     23 
     24 public class GamepadSupport {
     25 
     26 	private static Ticker ticker = new Ticker();
     27 
     28 	private static GamepadSupportListener listener;
     29 
     30 	private static IntMap<Gamepad> gamepads = new IntMap<Gamepad>();
     31 	private static IntMap<Gamepad> gamepadsTemp = new IntMap<Gamepad>();
     32 
     33 	public static void init(GamepadSupportListener listener) {
     34 		GamepadSupport.listener = listener;
     35 		nativeInit();
     36 	}
     37 
     38 	public static void startPolling() {
     39         consoleLog("startPolling");
     40 		ticker.start();
     41 	}
     42 
     43 	public static void stopPolling() {
     44 		ticker.stop();
     45 	}
     46 
     47 	public static void pollGamepads() {
     48 		JsArray<Gamepad> currentGamepads = nativePollGamepads();
     49 		if (currentGamepads != null) {
     50 			gamepadsTemp.clear();
     51 			gamepadsTemp.putAll(gamepads);
     52 			for (int i = 0, j = currentGamepads.length(); i < j; i++) {
     53 				Gamepad gamepad = currentGamepads.get(i);
     54 				if (gamepad != null) {
     55 					if (!gamepadsTemp.containsKey(gamepad.getIndex())) {
     56 						onGamepadConnect(gamepad);
     57 					}
     58 					gamepadsTemp.remove(gamepad.getIndex());
     59 				}
     60 			}
     61 			for (Gamepad gamepad : gamepadsTemp.values()) {
     62 				onGamepadDisconnect(gamepad);
     63 			}
     64 		}
     65 	}
     66 
     67 	public static void pollGamepadsStatus() {
     68 		for (Gamepad gamepad : gamepads.values()) {
     69 			if (gamepad.getPreviousTimestamp() != gamepad.getTimestamp()) {
     70 				fireGamepadUpdated(gamepad.getIndex());
     71 			}
     72 			gamepad.setPreviousTimestamp(gamepad.getTimestamp());
     73 		}
     74 	}
     75 
     76 	public static Gamepad getGamepad(int index) {
     77 		return gamepads.get(index);
     78 	}
     79 
     80 	private static void onGamepadConnect(Gamepad gamepad) {
     81 		consoleLog("onGamepadConnect: " + gamepad.getId());
     82 		gamepads.put(gamepad.getIndex(), gamepad);
     83 		fireGamepadConnected(gamepad.getIndex());
     84 	}
     85 
     86 	private static void onGamepadDisconnect(Gamepad gamepad) {
     87 		consoleLog("onGamepadDisconnect: " + gamepad.getId());
     88 		gamepads.remove(gamepad.getIndex());
     89 		fireGamepadDisconnected(gamepad.getIndex());
     90 	}
     91 
     92 	private static void fireGamepadConnected(int index) {
     93 		if (listener != null) {
     94 			listener.onGamepadConnected(index);
     95 		}
     96 	}
     97 
     98 	private static void fireGamepadDisconnected(int index) {
     99 		if (listener != null) {
    100 			listener.onGamepadDisconnected(index);
    101 		}
    102 	}
    103 
    104 	private static void fireGamepadUpdated(int index) {
    105 		if (listener != null) {
    106 			listener.onGamepadUpdated(index);
    107 		}
    108 	}
    109 
    110 	private static void handleGamepadConnect(GamepadEvent event) {
    111 		onGamepadConnect(event.getGamepad());
    112 	}
    113 	private static void handleGamepadDisconnect(GamepadEvent event) {
    114 		onGamepadDisconnect(event.getGamepad());
    115 	}
    116 
    117 	private static native void nativeInit() /*-{
    118         var gamepadSupportAvailable = !! navigator.getGamepads || !! navigator.webkitGetGamepads || !! navigator.webkitGamepads || (navigator.userAgent.indexOf('Firefox/') != -1);
    119         if (gamepadSupportAvailable) {
    120             $wnd.addEventListener('MozGamepadConnected', @com.badlogic.gdx.controllers.gwt.support.GamepadSupport::handleGamepadConnect(Lcom/badlogic/gdx/controllers/gwt/support/GamepadSupport$GamepadEvent;), false);
    121             $wnd.addEventListener('MozGamepadDisconnected', @com.badlogic.gdx.controllers.gwt.support.GamepadSupport::handleGamepadDisconnect(Lcom/badlogic/gdx/controllers/gwt/support/GamepadSupport$GamepadEvent;), false);
    122             if ( !! navigator.getGamepads || !! navigator.webkitGamepads || !! navigator.webkitGetGamepads) {
    123                 @com.badlogic.gdx.controllers.gwt.support.GamepadSupport::startPolling()();
    124             }
    125         }
    126 	}-*/;
    127 
    128 	private static native JsArray<Gamepad> nativePollGamepads() /*-{
    129 		return rawGamepads = (navigator.webkitGetGamepads && navigator.webkitGetGamepads()) || navigator.webkitGamepads;
    130 	}-*/;
    131 
    132 	public static native void consoleLog(String message) /*-{
    133 		$wnd.console.log(message);
    134 	}-*/;
    135 
    136 	private static class Ticker implements AnimationScheduler.AnimationCallback {
    137 
    138 		private boolean ticking = false;
    139 
    140 		public void start() {
    141 			if (!ticking) {
    142 				ticking = true;
    143 				AnimationScheduler.get().requestAnimationFrame(this);
    144 			}
    145 		}
    146 
    147 		public void stop() {
    148 			ticking = false;
    149 		}
    150 
    151 		@Override
    152 		public void execute(double timestamp) {
    153 			if (ticking) {
    154 				GamepadSupport.pollGamepads();
    155 				GamepadSupport.pollGamepadsStatus();
    156 				AnimationScheduler.get().requestAnimationFrame(this);
    157 			}
    158 		}
    159 	}
    160 
    161 	private static final class GamepadEvent extends JavaScriptObject {
    162 		protected GamepadEvent() {
    163 			// Required by GWT
    164 		}
    165 
    166 		public native Gamepad getGamepad() /*-{
    167 			return this.gamepad;
    168 		}-*/;
    169 	}
    170 }