1 module pixelperfectengine.system.input.types;
2 
3 /// Key modifiers used by the engine.
4 public enum KeyModifier : ubyte {
5 	None		= 0x00,
6 	Shift		= 0x01,
7 	Ctrl		= 0x02,
8 	Alt			= 0x04,
9 	GUI			= 0x08,
10 	NumLock		= 0x10,
11 	CapsLock	= 0x20,
12 	ScrollLock	= 0x40,
13 	LockKeys	= NumLock | CapsLock | ScrollLock,
14 	Mode		= 0x80,
15 	All			= 0xFF,
16 }
17 /// Modifier flags for joystick stuff, e.g. axes.
18 public enum JoyModifier : ubyte {
19 	Button		= 0x00,
20 	DPad		= 0x04,
21 	Axis		= 0x08,
22 	
23 }
24 /**
25  * Determines input device types.
26  * Currently 0-3 are used, 4-7 is reserved for future use.
27  */
28 public enum Devicetype : ubyte {
29 	Keyboard	= 0,
30 	Joystick	= 1,	///Also used for gamepads, wheels, etc., that can be interpreted as such
31 	Mouse		= 2,
32 	Touchscreen	= 3
33 }
34 /**
35  * Keys used during text input.
36  * Multiple enter and backspace keys are not threated as different entities in this case.
37  */
38 public enum TextInputKey {
39 	init,
40 	Enter		= 1,
41 	Escape		= 2,
42 	Backspace	= 3,
43 	CursorUp	= 4,
44 	CursorDown	= 5,
45 	CursorLeft	= 6,
46 	CursorRight	= 7,
47 	Insert		= 8,
48 	Delete		= 9,
49 	Home		= 10,
50 	End			= 11,
51 	PageUp		= 12,
52 	PageDown	= 13
53 }
54 /**
55  * Mouse Buttons that are numbered by the engine.
56  */
57 public enum MouseButton : ubyte {
58 	Left		= 1,
59 	Mid			= 2,
60 	Right		= 3,
61 	Next		= 4,
62 	Previous	= 5
63 }
64 /**
65  * Mouse Button flags.
66  */
67 public enum MouseButtonFlags : uint {
68 	Left		= 1 << 0,
69 	Mid			= 1 << 1,
70 	Right		= 1 << 2,
71 	Next		= 1 << 3,
72 	Previous	= 1 << 4
73 }
74 /**
75  * Button states.
76  */
77 public enum ButtonState : ubyte {
78 	Released	= 0,
79 	Pressed		= 1
80 }
81 /**
82  * Converts key modifier codes from SDL to the engine's own
83  */
84 public ubyte keyModConv(ushort input) @nogc pure nothrow @safe {
85 	import sdl.keycode;
86 	ubyte result;
87 	if (input & KMOD_SHIFT) result |= KeyModifier.Shift;
88 	if (input & KMOD_CTRL) result |= KeyModifier.Ctrl;
89 	if (input & KMOD_ALT) result |= KeyModifier.Alt;
90 	if (input & KMOD_GUI) result |= KeyModifier.GUI;
91 	if (input & KMOD_NUM) result |= KeyModifier.NumLock;
92 	if (input & KMOD_CAPS) result |= KeyModifier.CapsLock;
93 	if (input & KMOD_MODE) result |= KeyModifier.Mode;
94 	return result;
95 }
96 
97 /**
98  * Stores an easy to lookup code for input bindings in integer format.
99  * Keybindings should be stored in the configuration file as a human-readable format, as this struct
100  * might change in the future if more things need to be added
101  */
102 public struct BindingCode {
103 	/**
104 	 * The basis for all comparison.
105 	 * bits 0-8: Button/axis number.
106 	 * bits 9-16: Modifier flags.
107 	 * bits 17-19: Device type ID.
108 	 * bits 20-23: Device number.
109 	 * bits 24-31: Extended area.
110 	 */
111 	uint base;
112 	/**
113 	 * Modifier flags.
114 	 * bits 0-8: Unused.
115 	 * bits 9-16: Keymod ignore.
116 	 * bits 17-31: Unused.
117 	 */
118 	uint flags;
119 	///Standard CTOR
120 	this(uint base) @nogc @safe pure nothrow {
121 		this.base = base;
122 	}
123 	///CTOR with individual values
124 	this(ushort _buttonNum, ubyte _modifierFlags, ubyte _deviceTypeID, ubyte _deviceNum, ubyte _keymodIgnore = 0) 
125 			@nogc @safe pure nothrow {
126 		buttonNum = _buttonNum;
127 		modifierFlags = _modifierFlags;
128 		deviceTypeID = _deviceTypeID;
129 		deviceNum = _deviceNum;
130 		keymodIgnore = _keymodIgnore;
131 	}
132 	/// Returns the button number portion of the code.
133 	@property ushort buttonNum() @nogc @safe pure nothrow const {
134 		return cast(ushort)(base & 0x1_FF);
135 	}
136 	/// Sets the button number portion of the code.
137 	@property ushort buttonNum(ushort val) @nogc @safe pure nothrow {
138 		base &= ~0x00_00_01_FF;
139 		base |= val & 0x1_FF;
140 		return cast(ushort)(base & 0x1_FF);
141 	}
142 	/// Returns the modifier flag portion of the code.
143 	@property ubyte modifierFlags() @nogc @safe pure nothrow const {
144 		return cast(ubyte)(base >>> 9);
145 	}
146 	/// Sets the modifier flag portion of the code.
147 	@property ubyte modifierFlags(ubyte val) @nogc @safe pure nothrow {
148 		base &= ~0x00_01_FE_00;
149 		base |= val << 9;
150 		return cast(ubyte)(base >>> 9);
151 	}
152 	/// Returns the keymod ignore code.
153 	@property ubyte keymodIgnore() @nogc @safe pure nothrow const {
154 		return cast(ubyte)(flags >>> 9);
155 	}
156 	/// Sets the keymod ignore code.
157 	@property ubyte keymodIgnore(ubyte val) @nogc @safe pure nothrow {
158 		flags &= ~0x00_01_FE_00;
159 		flags |= val << 9;
160 		return cast(ubyte)(flags >>> 9);
161 	}
162 	/// Returns the device type ID portion of the code.
163 	@property ubyte deviceTypeID() @nogc @safe pure nothrow const {
164 		return cast(ubyte)((base >>> 17) & 0b0000_0111);
165 	}
166 	/// Sets the device type ID portion of the code.
167 	@property ubyte deviceTypeID(ubyte val) @nogc @safe pure nothrow {
168 		base &= ~0x00_0E_00_00;
169 		base |= (val & 0b0000_0111) << 17;
170 		return cast(ubyte)((base >>> 17) & 0b0000_0111);
171 	}
172 	/// Returns the device type ID portion of the code.
173 	@property ubyte deviceNum() @nogc @safe pure nothrow const {
174 		return cast(ubyte)((base >>> 20) & 0x0f);
175 	}
176 	/// Sets the device type ID portion of the code.
177 	@property ubyte deviceNum(ubyte val) @nogc @safe pure nothrow {
178 		base &= ~0x00_F0_00_00;
179 		base |= (val & 0x0f) << 20;
180 		return cast(ubyte)((base >>> 20) & 0x0f);
181 	}
182 	///Returns the extended area value.
183 	@property ubyte extArea() @nogc @safe pure nothrow const {
184 		return cast(ubyte)(base >> 24);
185 	}
186 	///Sets the extended area value.
187 	@property ubyte extArea(ubyte val) @nogc @safe pure nothrow {
188 		base &= ~0xFF_00_00_00;
189 		base |= val << 24;
190 		return cast(ubyte)(base >> 24);
191 	}
192 	///Returns the keymod ignore flags
193 	///Return whether the binding code is a joy axis
194 	@property bool isJoyAxis() @nogc @safe pure nothrow {
195 		return deviceTypeID == Devicetype.Joystick && modifierFlags == JoyModifier.Axis;
196 	}
197 	int opCmp(const BindingCode other) @nogc @safe pure nothrow const {
198 		const uint baseLH = base | flags | other.flags;
199 		const uint baseRH = other.base | flags | other.flags;
200 		if(baseLH > baseRH) return 1;
201 		else if(baseLH < baseRH) return -1;
202 		else return 0;
203 	}
204 	bool opEquals(const BindingCode other) @nogc @safe pure nothrow const {
205 		const uint baseLH = base | flags | other.flags;
206 		const uint baseRH = other.base | flags | other.flags;
207 		return baseLH == baseRH;
208 	}
209 }
210 /**
211  * Defines a single Input Binding.
212  */
213 public struct InputBinding {
214 	uint		code;			///Code being sent out to the target, should be a MurmurhashV3/32 code.
215 	uint		flags;			///Stores additional properties of the input binding.
216 	float[2]	deadzone;		///The deadzone, if the binding is an axis.
217 	static enum IS_AXIS_AS_BUTTON = 1<<0;	///If set in the flags field, then it treats the axis as a button.
218 	///Default CTOR
219 	this(uint code, uint flags = 0, float[2] deadzone = [0.0, 0.0]) @nogc @safe pure nothrow {
220 		this.code = code;
221 		this.flags = flags;
222 		this.deadzone = deadzone;
223 	}
224 	///CTOR that creates code from string
225 	this(string code, uint flags = 0, float[2] deadzone = [0.0, 0.0]) @nogc @safe pure nothrow {
226 		import collections.commons : defaultHash;
227 		this.code = defaultHash(code);
228 		this.flags = flags;
229 		this.deadzone = deadzone;
230 	}
231 	int opCmp(const InputBinding other) const @nogc @safe pure nothrow {
232 		if (code > other.code) return 1;
233 		else if (code < other.code) return -1;
234 		else return 0;
235 	}
236 
237 	int opCmp(const uint other) const @nogc @safe pure nothrow {
238 		if (code > other) return 1;
239 		else if (code < other) return -1;
240 		else return 0;
241 	}
242 }	
243 /**
244  * Common values for mouse events.
245  */
246 public struct MouseEventCommons {
247 	uint			timestamp;		///Timestamp of the event
248 	uint			windowID;		///Identifies the window where the event originated
249 	uint			mouseID;		///Identifies the mouse that generated the event
250 }
251 /**
252  * Packs mouseclick event information into a single struct.
253  */
254 public struct MouseClickEvent {
255 	import std.bitmanip : bitfields;
256 	int				x;				///X position of where the event happened
257 	int				y;				///Y position of where the event happened
258 	ubyte			button;			///The button that generated the event
259 	ubyte			clicks;			///The amount of clicks
260 	bool			state;			///Button state. Might be replaced in the future with flags.
261 }
262 /**
263  * Packs mousewheel event information into a single struct.
264  */
265 public struct MouseWheelEvent {
266 	int				x;				///Horizontal scrolling
267 	int				y;				///Vertical scrolling
268 }
269 /**
270  * Packs mousemotion event information into a single struct.
271  */
272 public struct MouseMotionEvent {
273 	uint			buttonState;	///State of the buttons
274 	int				x;				///Horizontal position of the cursor
275 	int				y;				///Vertical position of the cursor
276 	int				relX;			///Horizontal amount of mouse movement
277 	int				relY;			///Vertical amount of mouse movement
278 }