Rogue: Savage Rats, a retro-themed dungeon crawler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
rogue-savage-rats/src/mightypork/gamecore/input/InputSystem.java

266 lines
5.4 KiB

package mightypork.gamecore.input;
import mightypork.gamecore.core.events.UserQuitRequest;
import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.input.events.InputReadyEvent;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseMotionEvent;
import mightypork.utils.eventbus.clients.RootBusNode;
import mightypork.utils.interfaces.Updateable;
import mightypork.utils.math.constraints.vect.Vect;
import mightypork.utils.math.constraints.vect.var.VectVar;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
/**
* Input system
*
* @author Ondřej Hruška (MightyPork)
*/
public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
private static boolean inited = false;
/** Current mouse position */
private static final Vect mousePos = new Vect() {
@Override
public double x()
{
if (!Mouse.isInsideWindow()) return Integer.MIN_VALUE;
return Mouse.getX();
}
@Override
public double y()
{
if (!Mouse.isInsideWindow()) return Integer.MIN_VALUE;
// flip Y axis
return Display.getHeight() - Mouse.getY();
}
};
private final KeyBindingPool keybindings;
private final VectVar mouseMove = Vect.makeVar();
private final VectVar mouseLastPos = Vect.makeVar();
/**
* @param app app access
*/
public InputSystem(AppAccess app) {
super(app);
initDevices();
// global keybindings
keybindings = new KeyBindingPool();
addChildClient(keybindings);
getEventBus().send(new InputReadyEvent());
}
@Override
public final void deinit()
{
Mouse.destroy();
Keyboard.destroy();
}
private void initDevices()
{
if (inited) return;
inited = true;
try {
Mouse.create();
Keyboard.create();
Keyboard.enableRepeatEvents(false);
} catch (final LWJGLException e) {
throw new RuntimeException("Failed to initialize input devices.", e);
}
}
@Override
public final void bindKey(KeyStroke stroke, Edge edge, Runnable task)
{
keybindings.bindKey(stroke, edge, task);
}
@Override
public void unbindKey(KeyStroke stroke)
{
keybindings.unbindKey(stroke);
}
@Override
public synchronized void update(double delta)
{
// was destroyed or not initialized
if (!Display.isCreated()) return;
if (!Mouse.isCreated()) return;
if (!Keyboard.isCreated()) return;
Display.processMessages();
// sum the moves
mouseMove.reset();
mouseLastPos.reset();
boolean wasMouse = false;
while (Mouse.next()) {
onMouseEvent(mouseMove, mouseLastPos);
wasMouse = true;
}
if (wasMouse && !mouseMove.isZero()) {
getEventBus().send(new MouseMotionEvent(mouseLastPos, mouseMove));
}
while (Keyboard.next()) {
onKeyEvent();
}
if (Display.isCloseRequested()) {
getEventBus().send(new UserQuitRequest());
}
}
private void onMouseEvent(VectVar moveSum, VectVar lastPos)
{
final int button = Mouse.getEventButton();
final boolean down = Mouse.getEventButtonState();
final VectVar pos = Vect.makeVar(Mouse.getEventX(), Mouse.getEventY());
final VectVar move = Vect.makeVar(Mouse.getEventDX(), Mouse.getEventDY());
final int wheeld = Mouse.getEventDWheel();
// flip Y axis
pos.setY(Display.getHeight() - pos.y());
if (button != -1 || wheeld != 0) {
getEventBus().send(new MouseButtonEvent(pos.freeze(), button, down, wheeld));
}
moveSum.setTo(moveSum.add(move));
lastPos.setTo(pos);
}
private void onKeyEvent()
{
final int key = Keyboard.getEventKey();
final boolean down = Keyboard.getEventKeyState();
final char c = Keyboard.getEventCharacter();
getEventBus().send(new KeyEvent(key, c, down));
}
/**
* Get absolute mouse position. This vect is final and views at it can
* safely be made.
*
* @return mouse position
*/
public static Vect getMousePos()
{
return mousePos;
}
/**
* @return true if mouse is inside window.
*/
public static boolean isMouseInside()
{
return Mouse.isInsideWindow();
}
/**
* Trap mouse cursor in the window
*
* @param grab true to grab
*/
public static void grabMouse(boolean grab)
{
Mouse.setGrabbed(grab);
}
/**
* Check if key is down
*
* @param key key to check (constant from the {@link Keys} class)
* @return is down
*/
public static boolean isKeyDown(int key)
{
return Keyboard.isKeyDown(key);
}
/**
* Check mouse button state
*
* @param button button to test (0 left, 1 right, 2 middle)
* @return button is down
*/
public static boolean isMouseButtonDown(int button)
{
return Mouse.isButtonDown(button);
}
/**
* @return bit mask of active mod keys
*/
public static int getActiveModKeys()
{
int mods = 0;
if (Keyboard.isKeyDown(Keys.L_ALT) || Keyboard.isKeyDown(Keys.R_ALT)) {
mods |= Keys.MOD_ALT;
}
if (Keyboard.isKeyDown(Keys.L_SHIFT) || Keyboard.isKeyDown(Keys.R_SHIFT)) {
mods |= Keys.MOD_SHIFT;
}
if (Keyboard.isKeyDown(Keys.L_CONTROL) || Keyboard.isKeyDown(Keys.R_CONTROL)) {
mods |= Keys.MOD_CONTROL;
}
if (Keyboard.isKeyDown(Keys.L_META) || Keyboard.isKeyDown(Keys.R_META)) {
mods |= Keys.MOD_META;
}
return mods;
}
/**
* @return true if the system is initialized
*/
public static boolean isReady()
{
return inited;
}
}