org.newdawn.slick.Input Maven / Gradle / Ivy
package org.newdawn.slick; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import org.lwjgl.LWJGLException; import org.lwjgl.input.Controller; import org.lwjgl.input.Controllers; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; import org.newdawn.slick.util.Log; /** * A wrapped for all keyboard, mouse and controller input * * @author kevin */ public class Input { /** The controller index to pass to check all controllers */ public static final int ANY_CONTROLLER = -1; /** The maximum number of buttons on controllers */ private static final int MAX_BUTTONS = 100; /** */ public static final int KEY_ESCAPE = 0x01; /** */ public static final int KEY_1 = 0x02; /** */ public static final int KEY_2 = 0x03; /** */ public static final int KEY_3 = 0x04; /** */ public static final int KEY_4 = 0x05; /** */ public static final int KEY_5 = 0x06; /** */ public static final int KEY_6 = 0x07; /** */ public static final int KEY_7 = 0x08; /** */ public static final int KEY_8 = 0x09; /** */ public static final int KEY_9 = 0x0A; /** */ public static final int KEY_0 = 0x0B; /** */ public static final int KEY_MINUS = 0x0C; /* - on main keyboard */ /** */ public static final int KEY_EQUALS = 0x0D; /** */ public static final int KEY_BACK = 0x0E; /* backspace */ /** */ public static final int KEY_TAB = 0x0F; /** */ public static final int KEY_Q = 0x10; /** */ public static final int KEY_W = 0x11; /** */ public static final int KEY_E = 0x12; /** */ public static final int KEY_R = 0x13; /** */ public static final int KEY_T = 0x14; /** */ public static final int KEY_Y = 0x15; /** */ public static final int KEY_U = 0x16; /** */ public static final int KEY_I = 0x17; /** */ public static final int KEY_O = 0x18; /** */ public static final int KEY_P = 0x19; /** */ public static final int KEY_LBRACKET = 0x1A; /** */ public static final int KEY_RBRACKET = 0x1B; /** */ public static final int KEY_RETURN = 0x1C; /* Enter on main keyboard */ /** */ public static final int KEY_ENTER = 0x1C; /* Enter on main keyboard */ /** */ public static final int KEY_LCONTROL = 0x1D; /** */ public static final int KEY_A = 0x1E; /** */ public static final int KEY_S = 0x1F; /** */ public static final int KEY_D = 0x20; /** */ public static final int KEY_F = 0x21; /** */ public static final int KEY_G = 0x22; /** */ public static final int KEY_H = 0x23; /** */ public static final int KEY_J = 0x24; /** */ public static final int KEY_K = 0x25; /** */ public static final int KEY_L = 0x26; /** */ public static final int KEY_SEMICOLON = 0x27; /** */ public static final int KEY_APOSTROPHE = 0x28; /** */ public static final int KEY_GRAVE = 0x29; /* accent grave */ /** */ public static final int KEY_LSHIFT = 0x2A; /** */ public static final int KEY_BACKSLASH = 0x2B; /** */ public static final int KEY_Z = 0x2C; /** */ public static final int KEY_X = 0x2D; /** */ public static final int KEY_C = 0x2E; /** */ public static final int KEY_V = 0x2F; /** */ public static final int KEY_B = 0x30; /** */ public static final int KEY_N = 0x31; /** */ public static final int KEY_M = 0x32; /** */ public static final int KEY_COMMA = 0x33; /** */ public static final int KEY_PERIOD = 0x34; /* . on main keyboard */ /** */ public static final int KEY_SLASH = 0x35; /* / on main keyboard */ /** */ public static final int KEY_RSHIFT = 0x36; /** */ public static final int KEY_MULTIPLY = 0x37; /* * on numeric keypad */ /** */ public static final int KEY_LMENU = 0x38; /* left Alt */ /** */ public static final int KEY_SPACE = 0x39; /** */ public static final int KEY_CAPITAL = 0x3A; /** */ public static final int KEY_F1 = 0x3B; /** */ public static final int KEY_F2 = 0x3C; /** */ public static final int KEY_F3 = 0x3D; /** */ public static final int KEY_F4 = 0x3E; /** */ public static final int KEY_F5 = 0x3F; /** */ public static final int KEY_F6 = 0x40; /** */ public static final int KEY_F7 = 0x41; /** */ public static final int KEY_F8 = 0x42; /** */ public static final int KEY_F9 = 0x43; /** */ public static final int KEY_F10 = 0x44; /** */ public static final int KEY_NUMLOCK = 0x45; /** */ public static final int KEY_SCROLL = 0x46; /* Scroll Lock */ /** */ public static final int KEY_NUMPAD7 = 0x47; /** */ public static final int KEY_NUMPAD8 = 0x48; /** */ public static final int KEY_NUMPAD9 = 0x49; /** */ public static final int KEY_SUBTRACT = 0x4A; /* - on numeric keypad */ /** */ public static final int KEY_NUMPAD4 = 0x4B; /** */ public static final int KEY_NUMPAD5 = 0x4C; /** */ public static final int KEY_NUMPAD6 = 0x4D; /** */ public static final int KEY_ADD = 0x4E; /* + on numeric keypad */ /** */ public static final int KEY_NUMPAD1 = 0x4F; /** */ public static final int KEY_NUMPAD2 = 0x50; /** */ public static final int KEY_NUMPAD3 = 0x51; /** */ public static final int KEY_NUMPAD0 = 0x52; /** */ public static final int KEY_DECIMAL = 0x53; /* . on numeric keypad */ /** */ public static final int KEY_F11 = 0x57; /** */ public static final int KEY_F12 = 0x58; /** */ public static final int KEY_F13 = 0x64; /* (NEC PC98) */ /** */ public static final int KEY_F14 = 0x65; /* (NEC PC98) */ /** */ public static final int KEY_F15 = 0x66; /* (NEC PC98) */ /** */ public static final int KEY_KANA = 0x70; /* (Japanese keyboard) */ /** */ public static final int KEY_CONVERT = 0x79; /* (Japanese keyboard) */ /** */ public static final int KEY_NOCONVERT = 0x7B; /* (Japanese keyboard) */ /** */ public static final int KEY_YEN = 0x7D; /* (Japanese keyboard) */ /** */ public static final int KEY_NUMPADEQUALS = 0x8D; /* = on numeric keypad (NEC PC98) */ /** */ public static final int KEY_CIRCUMFLEX = 0x90; /* (Japanese keyboard) */ /** */ public static final int KEY_AT = 0x91; /* (NEC PC98) */ /** */ public static final int KEY_COLON = 0x92; /* (NEC PC98) */ /** */ public static final int KEY_UNDERLINE = 0x93; /* (NEC PC98) */ /** */ public static final int KEY_KANJI = 0x94; /* (Japanese keyboard) */ /** */ public static final int KEY_STOP = 0x95; /* (NEC PC98) */ /** */ public static final int KEY_AX = 0x96; /* (Japan AX) */ /** */ public static final int KEY_UNLABELED = 0x97; /* (J3100) */ /** */ public static final int KEY_NUMPADENTER = 0x9C; /* Enter on numeric keypad */ /** */ public static final int KEY_RCONTROL = 0x9D; /** */ public static final int KEY_NUMPADCOMMA = 0xB3; /* , on numeric keypad (NEC PC98) */ /** */ public static final int KEY_DIVIDE = 0xB5; /* / on numeric keypad */ /** */ public static final int KEY_SYSRQ = 0xB7; /** */ public static final int KEY_RMENU = 0xB8; /* right Alt */ /** */ public static final int KEY_PAUSE = 0xC5; /* Pause */ /** */ public static final int KEY_HOME = 0xC7; /* Home on arrow keypad */ /** */ public static final int KEY_UP = 0xC8; /* UpArrow on arrow keypad */ /** */ public static final int KEY_PRIOR = 0xC9; /* PgUp on arrow keypad */ /** */ public static final int KEY_LEFT = 0xCB; /* LeftArrow on arrow keypad */ /** */ public static final int KEY_RIGHT = 0xCD; /* RightArrow on arrow keypad */ /** */ public static final int KEY_END = 0xCF; /* End on arrow keypad */ /** */ public static final int KEY_DOWN = 0xD0; /* DownArrow on arrow keypad */ /** */ public static final int KEY_NEXT = 0xD1; /* PgDn on arrow keypad */ /** */ public static final int KEY_INSERT = 0xD2; /* Insert on arrow keypad */ /** */ public static final int KEY_DELETE = 0xD3; /* Delete on arrow keypad */ /** */ public static final int KEY_LWIN = 0xDB; /* Left Windows key */ /** */ public static final int KEY_RWIN = 0xDC; /* Right Windows key */ /** */ public static final int KEY_APPS = 0xDD; /* AppMenu key */ /** */ public static final int KEY_POWER = 0xDE; /** */ public static final int KEY_SLEEP = 0xDF; /** A helper for left ALT */ public static final int KEY_LALT = KEY_LMENU; /** A helper for right ALT */ public static final int KEY_RALT = KEY_RMENU; /** Control index */ private static final int LEFT = 0; /** Control index */ private static final int RIGHT = 1; /** Control index */ private static final int UP = 2; /** Control index */ private static final int DOWN = 3; /** Control index */ private static final int BUTTON1 = 4; /** Control index */ private static final int BUTTON2 = 5; /** Control index */ private static final int BUTTON3 = 6; /** Control index */ private static final int BUTTON4 = 7; /** Control index */ private static final int BUTTON5 = 8; /** Control index */ private static final int BUTTON6 = 9; /** Control index */ private static final int BUTTON7 = 10; /** Control index */ private static final int BUTTON8 = 11; /** Control index */ private static final int BUTTON9 = 12; /** Control index */ private static final int BUTTON10 = 13; /** The left mouse button indicator */ public static final int MOUSE_LEFT_BUTTON = 0; /** The right mouse button indicator */ public static final int MOUSE_RIGHT_BUTTON = 1; /** The middle mouse button indicator */ public static final int MOUSE_MIDDLE_BUTTON = 2; /** True if the controllers system has been initialised */ private static boolean controllersInited = false; /** The list of controllers */ private static ArrayList controllers = new ArrayList(); /** The last recorded mouse x position */ private int lastMouseX; /** The last recorded mouse y position */ private int lastMouseY; /** THe state of the mouse buttons */ protected boolean[] mousePressed = new boolean[10]; /** THe state of the controller buttons */ private boolean[][] controllerPressed = new boolean[100][MAX_BUTTONS]; /** The character values representing the pressed keys */ protected char[] keys = new char[1024]; /** True if the key has been pressed since last queries */ protected boolean[] pressed = new boolean[1024]; /** The time since the next key repeat to be fired for the key */ protected long[] nextRepeat = new long[1024]; /** The control states from the controllers */ private boolean[][] controls = new boolean[10][MAX_BUTTONS+10]; /** True if the event has been consumed */ protected boolean consumed = false; /** A list of listeners to be notified of input events */ protected HashSet allListeners = new HashSet(); /** The listeners to notify of key events */ protected ArrayList keyListeners = new ArrayList(); /** The listener to add */ protected ArrayList keyListenersToAdd = new ArrayList(); /** The listeners to notify of mouse events */ protected ArrayList mouseListeners = new ArrayList(); /** The listener to add */ protected ArrayList mouseListenersToAdd = new ArrayList(); /** The listener to nofiy of controller events */ protected ArrayList controllerListeners = new ArrayList(); /** The current value of the wheel */ private int wheel; /** The height of the display */ private int height; /** True if the display is active */ private boolean displayActive = true; /** True if key repeat is enabled */ private boolean keyRepeat; /** The initial delay for key repeat starts */ private int keyRepeatInitial; /** The interval of key repeat */ private int keyRepeatInterval; /** True if the input is currently paused */ private boolean paused; /** The scale to apply to screen coordinates */ private float scaleX = 1; /** The scale to apply to screen coordinates */ private float scaleY = 1; /** The offset to apply to screen coordinates */ private float xoffset = 0; /** The offset to apply to screen coordinates */ private float yoffset = 0; /** The delay before determining a single or double click */ private int doubleClickDelay = 250; /** The timer running out for a single click */ private long doubleClickTimeout = 0; /** The clicked x position */ private int clickX; /** The clicked y position */ private int clickY; /** The clicked button */ private int clickButton; /** The x position location the mouse was pressed */ private int pressedX = -1; /** The x position location the mouse was pressed */ private int pressedY = -1; /** The pixel distance the mouse can move to accept a mouse click */ private int mouseClickTolerance = 5; /** * Disables support for controllers. This means the jinput JAR and native libs * are not required. */ public static void disableControllers() { controllersInited = true; } /** * Create a new input with the height of the screen * * @param height The height of the screen */ public Input(int height) { init(height); } /** * Set the double click interval, the time between the first * and second clicks that should be interpreted as a * double click. * * @param delay The delay between clicks */ public void setDoubleClickInterval(int delay) { doubleClickDelay = delay; } /** * Set the pixel distance the mouse can move to accept a mouse click. * Default is 5. * * @param mouseClickTolerance The number of pixels. */ public void setMouseClickTolerance (int mouseClickTolerance) { this.mouseClickTolerance = mouseClickTolerance; } /** * Set the scaling to apply to screen coordinates * * @param scaleX The scaling to apply to the horizontal axis * @param scaleY The scaling to apply to the vertical axis */ public void setScale(float scaleX, float scaleY) { this.scaleX = scaleX; this.scaleY = scaleY; } /** * Set the offset to apply to the screen coodinates * * @param xoffset The offset on the x-axis * @param yoffset The offset on the y-axis */ public void setOffset(float xoffset, float yoffset) { this.xoffset = xoffset; this.yoffset = yoffset; } /** * Reset the transformation being applied to the input to the default */ public void resetInputTransform() { setOffset(0, 0); setScale(1, 1); } /** * Add a listener to be notified of input events * * @param listener The listener to be notified */ public void addListener(InputListener listener) { addKeyListener(listener); addMouseListener(listener); addControllerListener(listener); } /** * Add a key listener to be notified of key input events * * @param listener The listener to be notified */ public void addKeyListener(KeyListener listener) { keyListenersToAdd.add(listener); } /** * Add a key listener to be notified of key input events * * @param listener The listener to be notified */ private void addKeyListenerImpl(KeyListener listener) { if (keyListeners.contains(listener)) { return; } keyListeners.add(listener); allListeners.add(listener); } /** * Add a mouse listener to be notified of mouse input events * * @param listener The listener to be notified */ public void addMouseListener(MouseListener listener) { mouseListenersToAdd.add(listener); } /** * Add a mouse listener to be notified of mouse input events * * @param listener The listener to be notified */ private void addMouseListenerImpl(MouseListener listener) { if (mouseListeners.contains(listener)) { return; } mouseListeners.add(listener); allListeners.add(listener); } /** * Add a controller listener to be notified of controller input events * * @param listener The listener to be notified */ public void addControllerListener(ControllerListener listener) { if (controllerListeners.contains(listener)) { return; } controllerListeners.add(listener); allListeners.add(listener); } /** * Remove all the listeners from this input */ public void removeAllListeners() { removeAllKeyListeners(); removeAllMouseListeners(); removeAllControllerListeners(); } /** * Remove all the key listeners from this input */ public void removeAllKeyListeners() { allListeners.removeAll(keyListeners); keyListeners.clear(); } /** * Remove all the mouse listeners from this input */ public void removeAllMouseListeners() { allListeners.removeAll(mouseListeners); mouseListeners.clear(); } /** * Remove all the controller listeners from this input */ public void removeAllControllerListeners() { allListeners.removeAll(controllerListeners); controllerListeners.clear(); } /** * Add a listener to be notified of input events. This listener * will get events before others that are currently registered * * @param listener The listener to be notified */ public void addPrimaryListener(InputListener listener) { removeListener(listener); keyListeners.add(0, listener); mouseListeners.add(0, listener); controllerListeners.add(0, listener); allListeners.add(listener); } /** * Remove a listener that will no longer be notified * * @param listener The listen to be removed */ public void removeListener(InputListener listener) { removeKeyListener(listener); removeMouseListener(listener); removeControllerListener(listener); } /** * Remove a key listener that will no longer be notified * * @param listener The listen to be removed */ public void removeKeyListener(KeyListener listener) { keyListeners.remove(listener); if (!mouseListeners.contains(listener) && !controllerListeners.contains(listener)) { allListeners.remove(listener); } } /** * Remove a controller listener that will no longer be notified * * @param listener The listen to be removed */ public void removeControllerListener(ControllerListener listener) { controllerListeners.remove(listener); if (!mouseListeners.contains(listener) && !keyListeners.contains(listener)) { allListeners.remove(listener); } } /** * Remove a mouse listener that will no longer be notified * * @param listener The listen to be removed */ public void removeMouseListener(MouseListener listener) { mouseListeners.remove(listener); if (!controllerListeners.contains(listener) && !keyListeners.contains(listener)) { allListeners.remove(listener); } } /** * Initialise the input system * * @param height The height of the window */ void init(int height) { this.height = height; lastMouseX = getMouseX(); lastMouseY = getMouseY(); } /** * Get the character representation of the key identified by the specified code * * @param code The key code of the key to retrieve the name of * @return The name or character representation of the key requested */ public static String getKeyName(int code) { return Keyboard.getKeyName(code); } /** * Check if a particular key has been pressed since this method * was last called for the specified key * * @param code The key code of the key to check * @return True if the key has been pressed */ public boolean isKeyPressed(int code) { if (pressed[code]) { pressed[code] = false; return true; } return false; } /** * Check if a mouse button has been pressed since last call * * @param button The button to check * @return True if the button has been pressed since last call */ public boolean isMousePressed(int button) { if (mousePressed[button]) { mousePressed[button] = false; return true; } return false; } /** * Check if a controller button has been pressed since last * time * * @param button The button to check for (note that this includes directional controls first) * @return True if the button has been pressed since last time */ public boolean isControlPressed(int button) { return isControlPressed(button, 0); } /** * Check if a controller button has been pressed since last * time * * @param controller The index of the controller to check * @param button The button to check for (note that this includes directional controls first) * @return True if the button has been pressed since last time */ public boolean isControlPressed(int button, int controller) { if (controllerPressed[controller][button]) { controllerPressed[controller][button] = false; return true; } return false; } /** * Clear the state for isControlPressed method. This will reset all * controls to not pressed */ public void clearControlPressedRecord() { for (int i=0;i
method. This will * resort in all keys returning that they haven't been pressed, until * they are pressed again */ public void clearKeyPressedRecord() { Arrays.fill(pressed, false); } /** * Clear the state for theisKeyPressed isMousePressed
method. This will * resort in all mouse buttons returning that they haven't been pressed, until * they are pressed again */ public void clearMousePressedRecord() { Arrays.fill(mousePressed, false); } /** * Check if a particular key is down * * @param code The key code of the key to check * @return True if the key is down */ public boolean isKeyDown(int code) { return Keyboard.isKeyDown(code); } /** * Get the absolute x position of the mouse cursor within the container * * @return The absolute x position of the mouse cursor */ public int getAbsoluteMouseX() { return Mouse.getX(); } /** * Get the absolute y position of the mouse cursor within the container * * @return The absolute y position of the mouse cursor */ public int getAbsoluteMouseY() { return height - Mouse.getY(); } /** * Get the x position of the mouse cursor * * @return The x position of the mouse cursor */ public int getMouseX() { return (int) ((Mouse.getX() * scaleX)+xoffset); } /** * Get the y position of the mouse cursor * * @return The y position of the mouse cursor */ public int getMouseY() { return (int) (((height-Mouse.getY()) * scaleY)+yoffset); } /** * Check if a given mouse button is down * * @param button The index of the button to check (starting at 0) * @return True if the mouse button is down */ public boolean isMouseButtonDown(int button) { return Mouse.isButtonDown(button); } /** * Check if any mouse button is down * * @return True if any mouse button is down */ private boolean anyMouseDown() { for (int i=0;i<3;i++) { if (Mouse.isButtonDown(i)) { return true; } } return false; } /** * Get a count of the number of controlles available * * @return The number of controllers available */ public int getControllerCount() { try { initControllers(); } catch (SlickException e) { throw new RuntimeException("Failed to initialise controllers"); } return controllers.size(); } /** * Get the number of axis that are avaiable on a given controller * * @param controller The index of the controller to check * @return The number of axis available on the controller */ public int getAxisCount(int controller) { return ((Controller) controllers.get(controller)).getAxisCount(); } /** * Get the value of the axis with the given index * * @param controller The index of the controller to check * @param axis The index of the axis to read * @return The axis value at time of reading */ public float getAxisValue(int controller, int axis) { return ((Controller) controllers.get(controller)).getAxisValue(axis); } /** * Get the name of the axis with the given index * * @param controller The index of the controller to check * @param axis The index of the axis to read * @return The name of the specified axis */ public String getAxisName(int controller, int axis) { return ((Controller) controllers.get(controller)).getAxisName(axis); } /** * Check if the controller has the left direction pressed * * @param controller The index of the controller to check * @return True if the controller is pressed to the left */ public boolean isControllerLeft(int controller) { if (controller >= getControllerCount()) { return false; } if (controller == ANY_CONTROLLER) { for (int i=0;i= getControllerCount()) { return false; } if (controller == ANY_CONTROLLER) { for (int i=0;i 0.5f || ((Controller) controllers.get(controller)).getPovX() > 0.5f; } /** * Check if the controller has the up direction pressed * * @param controller The index of the controller to check * @return True if the controller is pressed to the up */ public boolean isControllerUp(int controller) { if (controller >= getControllerCount()) { return false; } if (controller == ANY_CONTROLLER) { for (int i=0;i = getControllerCount()) { return false; } if (controller == ANY_CONTROLLER) { for (int i=0;i 0.5f || ((Controller) controllers.get(controller)).getPovY() > 0.5f; } /** * Check if controller button is pressed * * @param controller The index of the controller to check * @param index The index of the button to check * @return True if the button is pressed */ public boolean isButtonPressed(int index, int controller) { if (controller >= getControllerCount()) { return false; } if (controller == ANY_CONTROLLER) { for (int i=0;i = 3) && (controller.getButtonCount() < MAX_BUTTONS)) { controllers.add(controller); } } Log.info("Found "+controllers.size()+" controllers"); for (int i=0;i doubleClickTimeout) { doubleClickTimeout = 0; } } this.height = height; Iterator allStarts = allListeners.iterator(); while (allStarts.hasNext()) { ControlledInputReciever listener = (ControlledInputReciever) allStarts.next(); listener.inputStarted(); } while (Keyboard.next()) { if (Keyboard.getEventKeyState()) { int eventKey = resolveEventKey(Keyboard.getEventKey(), Keyboard.getEventCharacter()); keys[eventKey] = Keyboard.getEventCharacter(); pressed[eventKey] = true; nextRepeat[eventKey] = System.currentTimeMillis() + keyRepeatInitial; consumed = false; for (int i=0;i = 0) { if (Mouse.getEventButtonState()) { consumed = false; mousePressed[Mouse.getEventButton()] = true; pressedX = (int) (xoffset + (Mouse.getEventX() * scaleX)); pressedY = (int) (yoffset + ((height-Mouse.getEventY()) * scaleY)); for (int i=0;i nextRepeat[i]) { nextRepeat[i] = System.currentTimeMillis() + keyRepeatInterval; consumed = false; for (int j=0;j = BUTTON1) { return isButtonPressed((index-BUTTON1), controllerIndex); } throw new RuntimeException("Unknown control index"); } /** * Pauses the polling and sending of input events. */ public void pause() { paused = true; // Reset all polling arrays clearKeyPressedRecord(); clearMousePressedRecord(); clearControlPressedRecord(); } /** * Resumes the polling and sending of input events. */ public void resume() { paused = false; } /** * Notify listeners that the mouse button has been clicked * * @param button The button that has been clicked * @param x The location at which the button was clicked * @param y The location at which the button was clicked * @param clickCount The number of times the button was clicked (single or double click) */ private void fireMouseClicked(int button, int x, int y, int clickCount) { consumed = false; for (int i=0;i