All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.lessvoid.nifty.slick2d.input.AbstractSlickInputSystem Maven / Gradle / Ivy

There is a newer version: 1.4.3
Show newest version
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