//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
namespace BansheeEngine
{
///
/// Contains data about a button input event.
///
public struct ButtonEvent
{
internal ButtonCode buttonCode;
internal int deviceIdx;
///
/// Creates a new button input event. For runtime use only.
///
/// Button code this event is referring to.
/// Index of the device that the event originated from.
internal ButtonEvent(ButtonCode buttonCode, int deviceIdx)
{
this.buttonCode = buttonCode;
this.deviceIdx = deviceIdx;
}
///
/// Button code this event is referring to.
///
public ButtonCode Button { get { return buttonCode; } }
///
/// Index of the device that the event originated from.
///
public int DeviceIndex { get { return deviceIdx; } }
///
/// Query is the pressed button a keyboard button.
///
public bool IsKeyboard { get { return ((int)buttonCode & 0xC0000000) == 0; }}
///
/// Query is the pressed button a mouse button.
///
public bool IsMouse { get { return ((int)buttonCode & 0x80000000) != 0; } }
///
/// Query is the pressed button a gamepad button.
///
public bool IsGamepad { get { return ((int)buttonCode & 0x40000000) != 0; } }
};
///
/// Pointer buttons. Generally these correspond to mouse buttons, but may be used in some form for touch input as well.
///
public enum PointerButton // Note: Must match C++ enum PointerEventButton
{
Left, Middle, Right, Count
};
///
/// Event that gets sent out when user interacts with the screen in some way, usually by moving the mouse cursor or
/// using touch input.
///
public struct PointerEvent
{
internal Vector2I _screenPos;
internal Vector2I _delta;
internal PointerButton _button;
internal bool _shift;
internal bool _control;
internal bool _alt;
internal float _mouseWheelScrollAmount;
///
/// Creates a new pointer event. For runtime use only.
///
/// Screen position where the input event occurred.
/// Change in movement since last sent event.
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
/// Is shift button on the keyboard being held down.
/// Is control button on the keyboard being held down.
/// Is alt button on the keyboard being held down.
/// If mouse wheel is being scrolled, what is the amount. Only relevant for
/// move events.
internal PointerEvent(Vector2I screenPos, Vector2I delta, PointerButton button,
bool shift, bool control, bool alt, float mouseWheelScrollAmount)
{
_screenPos = screenPos;
_delta = delta;
_button = button;
_shift = shift;
_control = control;
_alt = alt;
_mouseWheelScrollAmount = mouseWheelScrollAmount;
}
///
/// Screen position where the input event occurred.
///
public Vector2I ScreenPos { get { return _screenPos; } }
///
/// Change in movement since last sent event.
///
public Vector2I Delta { get { return _delta; } }
///
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
///
public PointerButton Button { get { return _button; } }
///
/// Is shift button on the keyboard being held down.
///
public bool Shift { get { return _shift; } }
///
/// Is control button on the keyboard being held down.
///
public bool Control { get { return _control; } }
///
/// Is alt button on the keyboard being held down.
///
public bool Alt { get { return _alt; } }
///
/// If mouse wheel is being scrolled, what is the amount. Only relevant for move events.
///
public float ScrollAmount { get { return _mouseWheelScrollAmount; } }
}
///
/// Event that gets sent out when user inputs some text. These events may be preceeded by normal button events if user
/// is typing on a keyboard.
///
public struct TextInputEvent
{
internal int textChar;
///
/// Creates a new text input event. For runtime use only.
///
/// Character the that was input.
internal TextInputEvent(int textChar)
{
this.textChar = textChar;
}
///
/// Character the that was input.
///
public int Char { get { return textChar; } }
}
///
/// Allows you to query and receive events from all connected input devices.
///
public static class Input
{
public delegate void ButtonEventDelegate(ButtonEvent ev);
public delegate void TextInputEventDelegate(TextInputEvent ev);
public delegate void PointerEventDelegate(PointerEvent ev);
///
/// Triggered when a button on any device is pressed.
///
public static event ButtonEventDelegate OnButtonDown;
///
/// Triggered when a button on any device is released.
///
public static event ButtonEventDelegate OnButtonUp;
///
/// Triggered when a textual character is entered.
///
public static event TextInputEventDelegate OnCharInput;
///
/// Triggered when the pointing device (mouse, touch) is moved.
///
public static event PointerEventDelegate OnPointerMoved;
///
/// Triggered when a button on the pointing device (mouse, touch) is pressed.
///
public static event PointerEventDelegate OnPointerPressed;
///
/// Triggered when a button on the pointing device (mouse, touch) is released.
///
public static event PointerEventDelegate OnPointerReleased;
///
/// Triggered when a button on the pointing device (mouse, touch) is pressed twice in rappid succession.
///
public static event PointerEventDelegate OnPointerDoubleClick;
///
/// Returns value of the specified input axis.
///
/// Type of axis to query.
/// Index of the device in case more than one is hooked up (0 - primary).
/// Value of the axis in range [-1.0, 1.0]. Canan be outside the range for devices with unbound axes
/// (for example mouse).
public static float GetAxisValue(InputAxis axis, int deviceIdx = 0)
{
return Internal_GetAxisValue(axis, deviceIdx);
}
///
/// Query if the provided button is currently being held (this frame or previous frames).
///
/// Code of the button to query.
/// Device to query the button on (0 - primary).
/// True if the button is held.
public static bool IsButtonHeld(ButtonCode code, int deviceIdx = 0)
{
return Internal_IsButtonHeld(code, deviceIdx);
}
///
/// Query if the provided button is currently being released (only true for one frame).
///
/// Code of the button to query.
/// Device to query the button on (0 - primary).
/// True if the button is being released.
public static bool IsButtonUp(ButtonCode code, int deviceIdx = 0)
{
return Internal_IsButtonUp(code, deviceIdx);
}
///
/// Query if the provided button is currently being pressed (only true for one frame).
///
/// Code of the button to query.
/// Device to query the button on (0 - primary).
/// True if the button is being pressed.
public static bool IsButtonDown(ButtonCode code, int deviceIdx = 0)
{
return Internal_IsButtonDown(code, deviceIdx);
}
///
/// Query if the provided pointer button is currently being held (this frame or previous frames).
///
/// Code of the button to query.
/// True if the button is being held.
public static bool IsPointerButtonHeld(PointerButton code)
{
return Internal_IsPointerButtonHeld(code);
}
///
/// Query if the provided pointer button is currently being being released (only true for one frame).
///
/// Code of the button to query.
/// True if the button is being released.
public static bool IsPointerButtonUp(PointerButton code)
{
return Internal_IsPointerButtonUp(code);
}
///
/// Query if the provided pointer button is currently being being pressed (only true for one frame).
///
/// Code of the button to query.
/// True if the button is being pressed.
public static bool IsPointerButtonDown(PointerButton code)
{
return Internal_IsPointerButtonDown(code);
}
///
/// Query has the left pointer button been double-clicked this frame.
///
/// True if double-click occurred.
public static bool IsPointerDoubleClicked()
{
return Internal_IsPointerDoubleClicked();
}
///
/// Returns position of the pointer (for example mouse cursor) relative to the screen.
///
public static Vector2I PointerPosition
{
get
{
Vector2I value;
Internal_GetPointerPosition(out value);
return value;
}
}
///
/// Returns difference between last and current pointer position.
///
public static Vector2I PointerDelta
{
get
{
Vector2I value;
Internal_GetPointerDelta(out value);
return value;
}
}
///
/// Triggered by runtime when a button is pressed.
///
/// Code of the pressed button.
/// Device the event originated from.
private static void Internal_TriggerButtonDown(ButtonCode code, int deviceIdx)
{
ButtonEvent ev = new ButtonEvent(code, deviceIdx);
if (OnButtonDown != null)
OnButtonDown(ev);
}
///
/// Triggered by runtime when a button is released.
///
/// Code of the released button.
/// Device the event originated from.
private static void Internal_TriggerButtonUp(ButtonCode code, int deviceIdx)
{
ButtonEvent ev = new ButtonEvent(code, deviceIdx);
if (OnButtonUp != null)
OnButtonUp(ev);
}
///
/// Triggered by runtime when character is input.
///
/// Code of input character.
private static void Internal_TriggerCharInput(int textChar)
{
TextInputEvent ev = new TextInputEvent(textChar);
if (OnCharInput != null)
OnCharInput(ev);
}
///
/// Triggers when some pointing device (mouse cursor, touch) moves.
///
/// Screen position where the input event occurred.
/// Change in movement since last sent event.
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
/// Is shift button on the keyboard being held down.
/// Is control button on the keyboard being held down.
/// Is alt button on the keyboard being held down.
/// If mouse wheel is being scrolled, what is the amount. Only relevant for
/// move events.
private static void Internal_TriggerPointerMove(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
bool ctrl, bool alt, float scrollAmount)
{
PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
if (OnPointerMoved != null)
OnPointerMoved(ev);
}
///
/// Triggers when some pointing device (mouse cursor, touch) button is pressed.
///
/// Screen position where the input event occurred.
/// Change in movement since last sent event.
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
/// Is shift button on the keyboard being held down.
/// Is control button on the keyboard being held down.
/// Is alt button on the keyboard being held down.
/// If mouse wheel is being scrolled, what is the amount. Only relevant for
/// move events.
private static void Internal_TriggerPointerPressed(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
bool ctrl, bool alt, float scrollAmount)
{
PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
if (OnPointerPressed != null)
OnPointerPressed(ev);
}
///
/// Triggers when some pointing device (mouse cursor, touch) button is released.
///
/// Screen position where the input event occurred.
/// Change in movement since last sent event.
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
/// Is shift button on the keyboard being held down.
/// Is control button on the keyboard being held down.
/// Is alt button on the keyboard being held down.
/// If mouse wheel is being scrolled, what is the amount. Only relevant for
/// move events.
private static void Internal_TriggerPointerReleased(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
bool ctrl, bool alt, float scrollAmount)
{
PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
if (OnPointerReleased != null)
OnPointerReleased(ev);
}
///
/// Triggers when some pointing device (mouse cursor, touch) button is double clicked.
///
/// Screen position where the input event occurred.
/// Change in movement since last sent event.
/// Button that triggered the pointer event. Might be irrelevant depending on event type.
/// (for example move events don't correspond to a button.
/// Is shift button on the keyboard being held down.
/// Is control button on the keyboard being held down.
/// Is alt button on the keyboard being held down.
/// If mouse wheel is being scrolled, what is the amount. Only relevant for
/// move events.
private static void Internal_TriggerPointerDoubleClick(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
bool ctrl, bool alt, float scrollAmount)
{
PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
if (OnPointerDoubleClick != null)
OnPointerDoubleClick(ev);
}
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern float Internal_GetAxisValue(InputAxis axis, int deviceIdx);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsButtonHeld(ButtonCode keyCode, int deviceIdx);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsButtonUp(ButtonCode keyCode, int deviceIdx);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsButtonDown(ButtonCode keyCode, int deviceIdx);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsPointerDoubleClicked();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsPointerButtonHeld(PointerButton keyCode);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsPointerButtonUp(PointerButton keyCode);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool Internal_IsPointerButtonDown(PointerButton keyCode);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_GetPointerPosition(out Vector2I position);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_GetPointerDelta(out Vector2I delta);
}
///
/// Contains all possible input buttons, including keyboard scan codes, mouse buttons and gamepad buttons.
///
public enum ButtonCode : uint // Note: Must match C++ enum ButtonCode
{
Unassigned = 0x00,
Escape = 0x01,
Num1 = 0x02,
Num2 = 0x03,
Num3 = 0x04,
Num4 = 0x05,
Num5 = 0x06,
Num6 = 0x07,
Num7 = 0x08,
Num8 = 0x09,
Num9 = 0x0A,
Num0 = 0x0B,
Minus = 0x0C,
Equals = 0x0D,
Back = 0x0E,
Tab = 0x0F,
Q = 0x10,
W = 0x11,
E = 0x12,
R = 0x13,
T = 0x14,
Y = 0x15,
U = 0x16,
I = 0x17,
O = 0x18,
P = 0x19,
LeftBracket = 0x1A,
RightBracket = 0x1B,
Return = 0x1C,
LeftControl = 0x1D,
A = 0x1E,
S = 0x1F,
D = 0x20,
F = 0x21,
G = 0x22,
H = 0x23,
J = 0x24,
K = 0x25,
L = 0x26,
Semicolon = 0x27,
Apostrophe = 0x28,
Grave = 0x29,
LeftShift = 0x2A,
Backslash = 0x2B,
Z = 0x2C,
X = 0x2D,
C = 0x2E,
V = 0x2F,
B = 0x30,
N = 0x31,
M = 0x32,
Comma = 0x33,
Period = 0x34,
Slash = 0x35,
RightShift = 0x36,
KeypadMultiply = 0x37,
LeftMenu = 0x38,
Space = 0x39,
CapsLock = 0x3A,
F1 = 0x3B,
F2 = 0x3C,
F3 = 0x3D,
F4 = 0x3E,
F5 = 0x3F,
F6 = 0x40,
F7 = 0x41,
F8 = 0x42,
F9 = 0x43,
F10 = 0x44,
NumLock = 0x45,
ScrollLock = 0x46,
Keypad7 = 0x47,
Keypad8 = 0x48,
Keypad9 = 0x49,
KeypadSubtract = 0x4A,
Keypad4 = 0x4B,
Keypad5 = 0x4C,
Keypad6 = 0x4D,
KeypadAdd = 0x4E,
Keypad1 = 0x4F,
Keypad2 = 0x50,
Keypad3 = 0x51,
Keypad0 = 0x52,
KeypadDecimal = 0x53,
F11 = 0x57,
F12 = 0x58,
F13 = 0x64,
F14 = 0x65,
F15 = 0x66,
KeypadEquals = 0x8D,
At = 0x91,
Colon = 0x92,
NumpadEnter = 0x9C,
RightControl = 0x9D,
KeypadComma = 0xB3,
KeypadDivide = 0xB5,
RightMenu = 0xB8,
Pause = 0xC5,
Home = 0xC7,
Up = 0xC8,
PageUp = 0xC9,
Left = 0xCB,
Right = 0xCD,
End = 0xCF,
Down = 0xD0,
PageDown = 0xD1,
Insert = 0xD2,
Delete = 0xD3,
LeftWindows = 0xDB,
RightWindows = 0xDC,
MouseLeft = 0x800000EE,
MouseRight = 0x800000EF,
MouseMiddle = 0x800000F0,
MouseBtn4 = 0x800000F1,
MouseBtn5 = 0x800000F2,
MouseBtn6 = 0x800000F3,
MouseBtn7 = 0x800000F4,
MouseBtn8 = 0x800000F5,
MouseBtn9 = 0x800000F6,
MouseBtn10 = 0x800000F7,
MouseBtn11 = 0x800000F8,
MouseBtn12 = 0x800000F9,
MouseBtn13 = 0x800000FA,
MouseBtn14 = 0x800000FB,
MouseBtn15 = 0x800000FC,
MouseBtn16 = 0x800000FD,
GamepadA = 0x4000010F,
GamepadB = 0x40000110,
GamepadX = 0x40000111,
GamepadY = 0x40000112,
GamepadLB = 0x40000113,
GamepadRB = 0x40000114,
GamepadLS = 0x40000115,
GamepadRS = 0x40000116,
GamepadBack = 0x40000117,
GamepadStart = 0x40000118,
GamepadDPadLeft = 0x40000119,
GamepadDPadRight = 0x4000011A,
GamepadDPadUp = 0x4000011B,
GamepadDPatDown = 0x4000011C,
GamepadBtn1 = 0x4000011D,
GamepadBtn2 = 0x4000011E,
GamepadBtn3 = 0x4000011F,
GamepadBtn4 = 0x40000120,
GamepadBtn5 = 0x40000121,
GamepadBtn6 = 0x40000122,
GamepadBtn7 = 0x40000123,
GamepadBtn8 = 0x40000124,
GamepadBtn9 = 0x40000125,
GamepadBtn10 = 0x40000126,
GamepadBtn11 = 0x40000127,
GamepadBtn12 = 0x40000128,
GamepadBtn13 = 0x40000129,
GamepadBtn14 = 0x4000012A,
GamepadBtn15 = 0x4000012B,
GamepadBtn16 = 0x4000012C,
Count = 249,
NumKeys = 203, // IMPORTANT: Make sure to update these if you modify the values above
NumMouseButtons = 16,
NumGamepadButtons = 30,
};
///
/// Available types of input axes.
///
public enum InputAxis // Note: Must match C++ enum InputBox
{
MouseX,
MouseY,
MouseZ,
LeftStickX,
LeftStickY,
RightStickX,
RightStickY,
LeftTrigger,
RightTrigger,
Count // Keep at end
};
}