/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.controllers.desktop; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Graphics.GraphicsType; import com.badlogic.gdx.controllers.ControlType; import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.ControllerListener; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.desktop.ois.Ois; import com.badlogic.gdx.controllers.desktop.ois.OisJoystick; import com.badlogic.gdx.controllers.desktop.ois.OisJoystick.OisPov; import com.badlogic.gdx.controllers.desktop.ois.OisListener; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.GdxRuntimeException; import java.awt.Component; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import javax.swing.SwingUtilities; /** @author Nathan Sweet */ public class OisControllers { final DesktopControllerManager manager; long hwnd = getWindowHandle(); Ois ois = new Ois(hwnd); OisController[] controllers; private static final boolean IS_MAC = System.getProperty("os.name").toLowerCase().contains("mac"); private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); private static final long CHECK_FOR_LOST_WINDOW_HANDLE_INTERVAL = 1000000000L; // in nanoseconds. 1000000000 == 1 second public OisControllers (final DesktopControllerManager manager) { this.manager = manager; ArrayList<OisJoystick> joysticks = ois.getJoysticks(); controllers = new OisController[joysticks.size()]; for (int i = 0, n = joysticks.size(); i < n; i++) { OisJoystick joystick = joysticks.get(i); controllers[i] = new OisController(joystick); manager.controllers.add(controllers[i]); } new Runnable() { private long lastCheckForLostWindowHandleTime; public void run () { // we won't do the rather heavy check for a lost window handle each and every frame, but rather each second only long now = System.nanoTime(); if (now - lastCheckForLostWindowHandleTime > CHECK_FOR_LOST_WINDOW_HANDLE_INTERVAL) { lastCheckForLostWindowHandleTime = now; long newWindowHandle = getWindowHandle(); if (hwnd != newWindowHandle) { hwnd = newWindowHandle; ois = new Ois(newWindowHandle); ArrayList<OisJoystick> joysticks = ois.getJoysticks(); controllers = new OisController[joysticks.size()]; manager.controllers.clear(); for (int i = 0, n = joysticks.size(); i < n; i++) { OisJoystick joystick = joysticks.get(i); controllers[i] = new OisController(joystick); manager.controllers.add(controllers[i]); } } } ois.update(); Gdx.app.postRunnable(this); } }.run(); } /** @author Nathan Sweet */ class OisController implements Controller { private final OisJoystick joystick; final Array<ControllerListener> listeners = new Array(); public OisController (OisJoystick joystick) { this.joystick = joystick; joystick.setListener(new OisListener() { public void buttonReleased (OisJoystick joystick, int buttonIndex) { Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).buttonUp(OisController.this, buttonIndex); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).buttonUp(OisController.this, buttonIndex); } public void buttonPressed (OisJoystick joystick, int buttonIndex) { Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).buttonDown(OisController.this, buttonIndex); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).buttonDown(OisController.this, buttonIndex); } public void axisMoved (OisJoystick joystick, int axisIndex, float value) { Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).axisMoved(OisController.this, axisIndex, value); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).axisMoved(OisController.this, axisIndex, value); } public void povMoved (OisJoystick joystick, int povIndex, OisPov ignored) { PovDirection value = getPov(povIndex); Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).povMoved(OisController.this, povIndex, value); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).povMoved(OisController.this, povIndex, value); } public void xSliderMoved (OisJoystick joystick, int sliderIndex, boolean value) { Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).xSliderMoved(OisController.this, sliderIndex, value); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).xSliderMoved(OisController.this, sliderIndex, value); } public void ySliderMoved (OisJoystick joystick, int sliderIndex, boolean value) { Array<ControllerListener> allListeners = manager.listeners; for (int ii = 0, nn = allListeners.size; ii < nn; ii++) allListeners.get(ii).ySliderMoved(OisController.this, sliderIndex, value); for (int ii = 0, nn = listeners.size; ii < nn; ii++) listeners.get(ii).ySliderMoved(OisController.this, sliderIndex, value); } }); } public boolean getButton (int buttonIndex) { return joystick.isButtonPressed(buttonIndex); } public float getAxis (int axisIndex) { return joystick.getAxis(axisIndex); } public PovDirection getPov (int povIndex) { OisPov pov = joystick.getPov(povIndex); switch (pov) { case Centered: return PovDirection.center; case East: return PovDirection.east; case North: return PovDirection.north; case NorthEast: return PovDirection.northEast; case NorthWest: return PovDirection.northWest; case South: return PovDirection.south; case SouthEast: return PovDirection.southEast; case SouthWest: return PovDirection.southWest; case West: return PovDirection.west; } return null; // Impossible. } public boolean getSliderX (int sliderIndex) { return joystick.getSliderX(sliderIndex); } public boolean getSliderY (int sliderIndex) { return joystick.getSliderY(sliderIndex); } public Vector3 getAccelerometer (int accelerometerIndex) { throw new GdxRuntimeException("Invalid accelerometer index: " + accelerometerIndex); } public void setAccelerometerSensitivity (float sensitivity) { } public int getControlCount (ControlType type) { switch (type) { case button: return joystick.getButtonCount(); case axis: return joystick.getAxisCount(); case slider: return joystick.getSliderCount(); case pov: return joystick.getPovCount(); } return 0; } public void addListener (ControllerListener listener) { listeners.add(listener); } public void removeListener (ControllerListener listener) { listeners.removeValue(listener, true); } public String getName () { return joystick.getName(); } public String toString () { return joystick.getName(); } } /** Returns the window handle from LWJGL needed by OIS. */ static public long getWindowHandle () { // don't need a window handle for Mac OS X if (IS_MAC) { return 0; } try { if (Gdx.graphics.getType() == GraphicsType.JGLFW) return (Long)Gdx.graphics.getClass().getDeclaredMethod("getWindow").invoke(null); if (Gdx.graphics.getType() == GraphicsType.LWJGL) { if (Gdx.app.getClass().getName().equals("com.badlogic.gdx.backends.lwjgl.LwjglCanvas")) { Class canvasClass = Class.forName("com.badlogic.gdx.backends.lwjgl.LwjglCanvas"); Object canvas = canvasClass.getDeclaredMethod("getCanvas").invoke(Gdx.app); return (Long)invokeMethod(invokeMethod(SwingUtilities.windowForComponent((Component)canvas), "getPeer"), "getHWnd"); } Class displayClass = Class.forName("org.lwjgl.opengl.Display"); Method getImplementation = displayClass.getDeclaredMethod("getImplementation", new Class[0]); getImplementation.setAccessible(true); Object display = getImplementation.invoke(null, (Object[])null); Field field = display.getClass().getDeclaredField(IS_WINDOWS ? "hwnd" : "parent_window"); field.setAccessible(true); return (Long)field.get(display); } } catch (Exception ex) { throw new RuntimeException("Unable to get window handle.", ex); } return 0; } static private Object invokeMethod (Object object, String methodName) throws Exception { for (Method m : object.getClass().getMethods()) if (m.getName().equals(methodName)) return m.invoke(object); throw new RuntimeException("Could not find method '" + methodName + "' on class: " + object.getClass()); } }