/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 Sri Harsha Chilakapati
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.shc.silenceengine.backend.lwjgl;
import com.shc.silenceengine.backend.lwjgl.glfw.GLFW3;
import com.shc.silenceengine.backend.lwjgl.glfw.Window;
import com.shc.silenceengine.core.SilenceEngine;
import com.shc.silenceengine.events.ControllerConnectionEvent;
import com.shc.silenceengine.input.Controller;
import com.shc.silenceengine.input.InputDevice;
import com.shc.silenceengine.input.Mouse;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import static com.shc.silenceengine.input.Keyboard.*;
import static com.shc.silenceengine.input.Mouse.*;
import static org.lwjgl.glfw.GLFW.*;
/**
* @author Sri Harsha Chilakapati
*/
class LwjglInputDevice extends InputDevice
{
private final Map<Integer, Integer> keyMap = new HashMap<>();
private final Map<Integer, Integer> mouseMap = new HashMap<>();
LwjglInputDevice()
{
Window window = ((LwjglDisplayDevice) SilenceEngine.display).window;
window.setKeyCallback((window1, key, scanCode, action, mods) ->
postKeyEvent(translateKeyCode(key), action != GLFW_RELEASE));
window.setMouseButtonCallback((window1, button, action, mods) ->
postMouseEvent(translateMouseCode(button), action != GLFW_RELEASE));
window.setCursorPositionCallback((window1, xPos, yPos) ->
{
Mouse.dx = (int) (xPos - Mouse.x);
Mouse.dy = (int) (yPos - Mouse.y);
Mouse.x = (int) xPos;
Mouse.y = (int) yPos;
});
window.setScrollCallback((window1, xOffset, yOffset) ->
{
int dsx = (int) xOffset;
int dsy = (int) yOffset;
// To normalize between 0 and 1
Mouse.deltaScrollX = dsx > 0 ? 1 : dsx == 0 ? 0 : -1;
Mouse.deltaScrollY = dsy > 0 ? 1 : dsy == 0 ? 0 : -1;
});
window.setCharacterModsCallback((window1, codePoint, mods) ->
postTextEvent(Character.toChars(codePoint)));
GLFW3.setJoystickCallback(this::postControllerConnectionEvent);
createKeyMap();
createMouseMap();
}
static void pollControllers()
{
for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; i++)
{
if (glfwJoystickPresent(i))
{
if (!Controller.states[i].connected)
((LwjglInputDevice) SilenceEngine.input).postControllerConnectionEvent(i, true);
ByteBuffer buttons = glfwGetJoystickButtons(i);
while (buttons.hasRemaining())
{
final boolean down = buttons.get() == 1;
SilenceEngine.input.postControllerButtonEvent(i, buttons.position() - 1, down, down ? 1 : 0);
}
FloatBuffer axes = glfwGetJoystickAxes(i);
while (axes.hasRemaining())
SilenceEngine.input.postControllerAxisEvent(i, axes.position(), axes.get());
}
else
{
if (Controller.states[i].connected)
((LwjglInputDevice) SilenceEngine.input).postControllerConnectionEvent(i, false);
}
}
}
private void postControllerConnectionEvent(int joystick, boolean connected)
{
ControllerConnectionEvent event = new ControllerConnectionEvent();
event.controllerConnected = connected;
event.isControllerIdeal = false;
event.controllerName = glfwGetJoystickName(joystick);
event.axisMapping = new Controller.Mapping();
event.buttonMapping = new Controller.Mapping();
event.numButtons = connected ? glfwGetJoystickButtons(joystick).capacity() : 0;
event.numAxes = connected ? glfwGetJoystickAxes(joystick).capacity() : 0;
postControllerConnectionEvent(joystick, event);
}
private void createMouseMap()
{
mouseMap.put(GLFW_MOUSE_BUTTON_1, BUTTON_1);
mouseMap.put(GLFW_MOUSE_BUTTON_2, BUTTON_2);
mouseMap.put(GLFW_MOUSE_BUTTON_3, BUTTON_3);
mouseMap.put(GLFW_MOUSE_BUTTON_4, BUTTON_4);
mouseMap.put(GLFW_MOUSE_BUTTON_5, BUTTON_5);
mouseMap.put(GLFW_MOUSE_BUTTON_6, BUTTON_6);
mouseMap.put(GLFW_MOUSE_BUTTON_7, BUTTON_7);
mouseMap.put(GLFW_MOUSE_BUTTON_8, BUTTON_8);
}
private void createKeyMap()
{
// Escape key
keyMap.put(GLFW_KEY_ESCAPE, KEY_ESCAPE);
// Function keys
keyMap.put(GLFW_KEY_F1, KEY_F1);
keyMap.put(GLFW_KEY_F2, KEY_F2);
keyMap.put(GLFW_KEY_F3, KEY_F3);
keyMap.put(GLFW_KEY_F4, KEY_F4);
keyMap.put(GLFW_KEY_F5, KEY_F5);
keyMap.put(GLFW_KEY_F6, KEY_F6);
keyMap.put(GLFW_KEY_F7, KEY_F7);
keyMap.put(GLFW_KEY_F8, KEY_F8);
keyMap.put(GLFW_KEY_F9, KEY_F9);
keyMap.put(GLFW_KEY_F10, KEY_F10);
keyMap.put(GLFW_KEY_F11, KEY_F11);
keyMap.put(GLFW_KEY_F12, KEY_F12);
// Number keys
keyMap.put(GLFW_KEY_0, KEY_0);
keyMap.put(GLFW_KEY_1, KEY_1);
keyMap.put(GLFW_KEY_2, KEY_2);
keyMap.put(GLFW_KEY_3, KEY_3);
keyMap.put(GLFW_KEY_4, KEY_4);
keyMap.put(GLFW_KEY_5, KEY_5);
keyMap.put(GLFW_KEY_6, KEY_6);
keyMap.put(GLFW_KEY_7, KEY_7);
keyMap.put(GLFW_KEY_8, KEY_8);
keyMap.put(GLFW_KEY_9, KEY_9);
// Symbol keys
keyMap.put(GLFW_KEY_GRAVE_ACCENT, KEY_BACKTICK);
keyMap.put(GLFW_KEY_MINUS, KEY_UNDERSCORE);
keyMap.put(GLFW_KEY_EQUAL, KEY_EQUALS);
keyMap.put(GLFW_KEY_LEFT_BRACKET, KEY_LEFT_BRACE);
keyMap.put(GLFW_KEY_RIGHT_BRACKET, KEY_RIGHT_BRACE);
keyMap.put(GLFW_KEY_BACKSLASH, KEY_BACKWARD_SLASH);
keyMap.put(GLFW_KEY_SEMICOLON, KEY_SEMICOLON);
keyMap.put(GLFW_KEY_APOSTROPHE, KEY_DOUBLE_QUOTE);
keyMap.put(GLFW_KEY_COMMA, KEY_COMMA);
keyMap.put(GLFW_KEY_PERIOD, KEY_PERIOD);
keyMap.put(GLFW_KEY_SLASH, KEY_FORWARD_SLASH);
// Lock keys
keyMap.put(GLFW_KEY_NUM_LOCK, KEY_NUM_LOCK);
keyMap.put(GLFW_KEY_CAPS_LOCK, KEY_CAPS_LOCK);
keyMap.put(GLFW_KEY_SCROLL_LOCK, KEY_SCROLL_LOCK);
// Special keys
keyMap.put(GLFW_KEY_TAB, KEY_TAB);
keyMap.put(GLFW_KEY_BACKSPACE, KEY_BACKSPACE);
keyMap.put(GLFW_KEY_ENTER, KEY_ENTER);
keyMap.put(GLFW_KEY_LEFT_SHIFT, KEY_LEFT_SHIFT);
keyMap.put(GLFW_KEY_RIGHT_SHIFT, KEY_RIGHT_SHIFT);
keyMap.put(GLFW_KEY_LEFT_CONTROL, KEY_LEFT_CTRL);
keyMap.put(GLFW_KEY_RIGHT_CONTROL, KEY_RIGHT_CTRL);
keyMap.put(GLFW_KEY_LEFT_ALT, KEY_LEFT_ALT);
keyMap.put(GLFW_KEY_RIGHT_ALT, KEY_RIGHT_ALT);
keyMap.put(GLFW_KEY_LEFT_SUPER, KEY_LEFT_SUPER);
keyMap.put(GLFW_KEY_RIGHT_SUPER, KEY_RIGHT_SUPER);
keyMap.put(GLFW_KEY_INSERT, KEY_INSERT);
keyMap.put(GLFW_KEY_DELETE, KEY_DELETE);
keyMap.put(GLFW_KEY_HOME, KEY_HOME);
keyMap.put(GLFW_KEY_PAGE_DOWN, KEY_PAGEDOWN);
keyMap.put(GLFW_KEY_PAGE_UP, KEY_PAGEUP);
keyMap.put(GLFW_KEY_PRINT_SCREEN, KEY_PRINT_SCREEN);
keyMap.put(GLFW_KEY_PAUSE, KEY_PAUSE_BREAK);
// Keypad keys
keyMap.put(GLFW_KEY_KP_0, KEY_KP_0);
keyMap.put(GLFW_KEY_KP_1, KEY_KP_1);
keyMap.put(GLFW_KEY_KP_2, KEY_KP_2);
keyMap.put(GLFW_KEY_KP_3, KEY_KP_3);
keyMap.put(GLFW_KEY_KP_4, KEY_KP_4);
keyMap.put(GLFW_KEY_KP_5, KEY_KP_5);
keyMap.put(GLFW_KEY_KP_6, KEY_KP_6);
keyMap.put(GLFW_KEY_KP_7, KEY_KP_7);
keyMap.put(GLFW_KEY_KP_8, KEY_KP_8);
keyMap.put(GLFW_KEY_KP_9, KEY_KP_9);
keyMap.put(GLFW_KEY_KP_DIVIDE, KEY_KP_SLASH);
keyMap.put(GLFW_KEY_KP_MULTIPLY, KEY_KP_ASTERISK);
keyMap.put(GLFW_KEY_KP_SUBTRACT, KEY_KP_MINUS);
keyMap.put(GLFW_KEY_KP_ADD, KEY_KP_PLUS);
keyMap.put(GLFW_KEY_KP_ENTER, KEY_KP_ENTER);
keyMap.put(GLFW_KEY_KP_DECIMAL, KEY_KP_PERIOD);
// Arrow keys
keyMap.put(GLFW_KEY_UP, KEY_UP);
keyMap.put(GLFW_KEY_DOWN, KEY_DOWN);
keyMap.put(GLFW_KEY_LEFT, KEY_LEFT);
keyMap.put(GLFW_KEY_RIGHT, KEY_RIGHT);
// Alphabet keys
keyMap.put(GLFW_KEY_A, KEY_A);
keyMap.put(GLFW_KEY_B, KEY_B);
keyMap.put(GLFW_KEY_C, KEY_C);
keyMap.put(GLFW_KEY_D, KEY_D);
keyMap.put(GLFW_KEY_E, KEY_E);
keyMap.put(GLFW_KEY_F, KEY_F);
keyMap.put(GLFW_KEY_G, KEY_G);
keyMap.put(GLFW_KEY_H, KEY_H);
keyMap.put(GLFW_KEY_I, KEY_I);
keyMap.put(GLFW_KEY_J, KEY_J);
keyMap.put(GLFW_KEY_K, KEY_K);
keyMap.put(GLFW_KEY_L, KEY_L);
keyMap.put(GLFW_KEY_M, KEY_M);
keyMap.put(GLFW_KEY_N, KEY_N);
keyMap.put(GLFW_KEY_O, KEY_O);
keyMap.put(GLFW_KEY_P, KEY_P);
keyMap.put(GLFW_KEY_Q, KEY_Q);
keyMap.put(GLFW_KEY_R, KEY_R);
keyMap.put(GLFW_KEY_S, KEY_S);
keyMap.put(GLFW_KEY_T, KEY_T);
keyMap.put(GLFW_KEY_U, KEY_U);
keyMap.put(GLFW_KEY_V, KEY_V);
keyMap.put(GLFW_KEY_W, KEY_W);
keyMap.put(GLFW_KEY_X, KEY_X);
keyMap.put(GLFW_KEY_Y, KEY_Y);
keyMap.put(GLFW_KEY_Z, KEY_Z);
keyMap.put(GLFW_KEY_SPACE, KEY_SPACE);
}
private int translateKeyCode(int nativeCode)
{
Integer code = keyMap.get(nativeCode);
return (code == null) ? 0 : code;
}
private int translateMouseCode(int nativeCode)
{
Integer code = mouseMap.get(nativeCode);
return (code == null) ? 0 : code;
}
}