de.lessvoid.nifty.slick2d.input.AbstractSlickInputSystem Maven / Gradle / Ivy
package de.lessvoid.nifty.slick2d.input;
import de.lessvoid.nifty.NiftyInputConsumer;
import de.lessvoid.nifty.slick2d.input.events.*;
import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.Input;
import org.newdawn.slick.util.InputAdapter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* This is the abstract Input System implementation to connect the Input of Slick and Nifty.
*
* @author Martin Karing <[email protected]>
*/
@SuppressWarnings("AbstractClassExtendsConcreteClass")
public abstract class AbstractSlickInputSystem extends InputAdapter implements SlickInputSystem {
/**
* This constants holds the initial size of the storage list that holds the received input events.
*/
private static final int INPUT_EVENT_BUFFER_INIT_SIZE = 20;
/**
* The delta value is divided by this value in order to give Nifty nice values for the mouse wheel movement. Reducing
* this value will increase the speed the mouse wheel moves for Nifty.
*/
private static final int WHEEL_DELTA_CORRECTION = 120;
/**
* The list of buttons that got pressed and are still pressed.
*/
@Nonnull
private final List buttonPressedStack;
/**
* The input system that feeds this input system with data.
*/
@Nullable
private Input input = null;
/**
* The list of input events that was registered but yet not processed.
*/
@Nonnull
private final List inputEventList;
/**
* The input state used for the communication between the input events.
*/
@Nonnull
private final InputState inputState;
/**
* The currently active forwarding mode.
*/
private ForwardingMode forwardMode;
/**
* Prepare all required instances to work with this class.
*/
protected AbstractSlickInputSystem() {
inputEventList = new ArrayList(INPUT_EVENT_BUFFER_INIT_SIZE);
buttonPressedStack = new LinkedList();
inputState = new InputState();
forwardMode = ForwardingMode.none;
}
/**
* This is called by Nifty and used to poll the input events. In case the event is not handled by the NiftyGUI is send
* to the additional input event handler that is implemented by the {@link #handleInputEvent(InputEvent)} function.
*
* @param inputEventConsumer the input event consumer that is provided by Nifty, it will receive all events first
*/
@Override
public final void forwardEvents(@Nonnull final NiftyInputConsumer inputEventConsumer) {
while (!inputEventList.isEmpty()) {
final InputEvent currentEvent = inputEventList.remove(0);
if (!currentEvent.executeEvent(inputState)) {
continue;
}
final boolean isForwarded = currentEvent.isForwarded(forwardMode);
if (!isForwarded && currentEvent.sendToNifty(inputEventConsumer)) {
currentEvent.updateState(inputState, true);
} else {
handleInputEvent(currentEvent);
// Forwarding might just have been enabled again, if that is the case Nifty needs to know about the event
if (isForwarded && !currentEvent.isForwarded(forwardMode)) {
currentEvent.sendToNifty(inputEventConsumer);
currentEvent.updateState(inputState, true);
} else {
currentEvent.updateState(inputState, false);
}
}
}
}
/**
* This function is called in case a input event was not handled by the Nifty event consumer of the Nifty GUI.
*
* @param event the event that needs to be handled
*/
protected abstract void handleInputEvent(InputEvent event);
/**
* Check if the control key is pressed down. This function requires the {@link Input} instance that is used by Slick
* to be sent in order to work properly. Setting this instance is done by calling {@link #setInput(Input)}.
*
* @return {@code true} in case one of the control keys is done and the {@link Input} instance was set properly, else
* {@code false}
*/
private boolean isControlDown() {
return (input != null) && (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL));
}
/**
* Check if the shift key is pressed down. This function requires the {@link Input} instance that is used by Slick to
* be sent in order to work properly. Setting this instance is done by calling {@link #setInput(Input)}.
*
* @return {@code true} in case one of the shift keys is done and the {@link Input} instance was set properly, else
* {@code false}
*/
private boolean isShiftDown() {
return (input != null) && (input.isKeyDown(Input.KEY_LSHIFT) || input.isKeyDown(Input.KEY_RSHIFT));
}
@Override
public final void keyPressed(final int key, final char c) {
inputEventList.add(new KeyboardEventPressed(key, c, isShiftDown(), isControlDown()));
}
@Override
public final void keyReleased(final int key, final char c) {
inputEventList.add(new KeyboardEventReleased(key, c, isShiftDown(), isControlDown()));
}
@Override
public final void mouseClicked(final int button, final int x, final int y, final int clickCount) {
inputEventList.add(new MouseEventClicked(x, y, button, clickCount));
}
@Override
public final void mouseDragged(final int oldX, final int oldY, final int newX, final int newY) {
if (buttonPressedStack.isEmpty()) {
// drag started outside of the screen. Can't handle this one.
return;
}
final int lastButton = buttonPressedStack.get(buttonPressedStack.size() - 1);
inputEventList.add(new MouseEventDragged(lastButton, oldX, oldY, newX, newY));
}
@Override
public final void mouseMoved(final int oldX, final int oldY, final int newX, final int newY) {
inputEventList.add(new MouseEventMoved(oldX, oldY, newX, newY));
}
@Override
public final void mousePressed(final int button, final int x, final int y) {
inputEventList.add(new MouseEventPressed(x, y, button));
buttonPressedStack.add(button);
}
@Override
public final void mouseReleased(final int button, final int x, final int y) {
inputEventList.add(new MouseEventReleased(x, y, button));
buttonPressedStack.remove(Integer.valueOf(button));
}
/**
* {@inheritDoc}. This function requires the {@link Input} instance that is used by Slick to be sent in order to work
* properly. Setting this instance is done by calling {@link #setInput(Input)}.
*
* @throws IllegalStateException in case the {@link Input} was not set
*/
@Override
public final void mouseWheelMoved(final int change) {
if (input == null) {
throw new IllegalStateException("Can't generate mouse wheel events without a reference to the Input");
}
inputEventList.add(new MouseEventWheelMoved(input.getMouseX(), input.getMouseY(), change / WHEEL_DELTA_CORRECTION));
}
/**
* Enable the forwarding modes. This causes that some event are not send to the Nifty-GUI. Instead they are always
* forwarded to the second listener.
*
* @param mode the forwarding mode to enable
*/
protected final void enableForwardingMode(final ForwardingMode mode) {
if ((forwardMode == ForwardingMode.all) || (mode == ForwardingMode.none) || (mode == forwardMode)) {
return;
}
if (mode == ForwardingMode.all) {
forwardMode = ForwardingMode.all;
}
forwardMode = (forwardMode == ForwardingMode.none) ? mode : ForwardingMode.all;
}
/**
* Disable the forwarding mode. Once called the specified events are not send to the Nifty-GUI anymore.
*
* @param mode the forwarding mode that is supposed to be disabled
*/
protected final void disableForwardingMode(final ForwardingMode mode) {
if ((forwardMode == ForwardingMode.none) || (mode == ForwardingMode.none)) {
return;
}
if ((forwardMode == mode) || (mode == ForwardingMode.all)) {
forwardMode = ForwardingMode.none;
return;
}
if (forwardMode == ForwardingMode.all) {
forwardMode = (mode == ForwardingMode.mouse) ? ForwardingMode.keyboard : ForwardingMode.mouse;
}
}
/**
* Set the {@link Input} instance that is used by Slick to handle the user input. Some functions of this class require
* this instance to work properly. Calling this function will also make sure that the {@link Input} instance is
* configured properly so the GUI works as expected.
*
* @param newInput the {@link Input} instance
* @see #mouseWheelMoved(int)
* @see #isControlDown()
* @see #isShiftDown()
*/
@Override
public final void setInput(@Nullable final Input newInput) {
input = newInput;
if (input != null) {
input.enableKeyRepeat();
}
}
@Override
public final void setMousePosition(final int x, final int y) {
Mouse.setCursorPosition(x, y);
}
@Override
public void setResourceLoader(@Nonnull final NiftyResourceLoader resourceLoader) {
// no use for the resource loader
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy