1 module evael.system.InputHandler;
2 
3 public import derelict.glfw3.glfw3;
4 
5 import std.traits : EnumMembers;
6 
7 import evael.system.Input;
8 
9 import evael.core.Game;
10 import evael.utils.Math;
11 
12 /**
13  * Input handler.
14  * Handle mouse movements and mouse buttons / keys states.
15  */
16 class InputHandler
17 {
18 	private Game m_game;
19 
20 	private bool[ [EnumMembers!(MouseButton)].length ] m_mouseButtonsStates;
21 
22 	private vec2 m_mousePosition;
23 	private bool m_mouseHasMoved;
24 	private bool m_mouseButtonClicked;
25 
26 	/**
27 	 * InputHandler constructor.
28 	 */
29 	@nogc
30 	public this(Game game) nothrow
31 	{
32 		this.m_game = game;
33 
34 		this.m_mouseButtonsStates = [false, false];
35 		this.m_mouseHasMoved = false;
36 		this.m_mouseButtonClicked = false;
37 	}
38 
39 	/**
40 	 * InputHandler destructor.
41 	 */
42 	public void dispose()
43 	{
44 
45 	}
46 
47 	/**
48 	 * Updates input states and triggers events.
49 	 */
50 	public void update()
51 	{
52 		if (this.m_mouseHasMoved)
53 		{
54 			this.m_game.currentGameState.onMouseMove(this.m_mousePosition);
55 			this.m_mouseHasMoved = false;
56 		}
57 
58 		if (this.m_mouseButtonClicked)
59 		{
60 			static bool[] lastMouseButtonsStates = [false, false];
61 
62 			bool isMouseButtonPressed;
63 			int enumIndex;
64 
65 			static foreach (e; [EnumMembers!(MouseButton)])
66 			{
67 				enumIndex = cast(int)e;
68 				isMouseButtonPressed = this.m_mouseButtonsStates[enumIndex];
69 
70 				if (isMouseButtonPressed != lastMouseButtonsStates[enumIndex])
71 				{
72 					if (isMouseButtonPressed)
73 					{
74 						this.m_game.currentGameState.onMouseClick(this.m_mousePosition, e);
75 					}
76 					else this.m_game.currentGameState.onMouseUp(this.m_mousePosition, e);
77 
78 					lastMouseButtonsStates[enumIndex] = isMouseButtonPressed;
79 				}
80 			}
81 
82 			this.m_mouseButtonClicked = false;
83 		}
84 	}
85 
86 	/**
87 	 * Checks if a specific mouse button is clicked.
88 	 * Params:
89 	 *      button : mouse button
90 	 */
91 	@nogc @safe
92 	public bool isMouseButtonClicked(in MouseButton button) pure nothrow
93 	{
94 		return this.m_mouseButtonsStates[button] == GLFW_PRESS;
95 	}
96 
97 	/**
98 	 * Checks if a specific key is pressed.
99 	 * Params:
100 	 *      key : key
101 	 */
102 	@nogc
103 	public bool isKeyPressed(in Key key) nothrow
104 	{
105 		return glfwGetKey(this.m_game.window.glfwWindow, key) == GLFW_PRESS;
106 	}
107 
108 	@nogc @safe
109 	extern(C) pure nothrow
110 	{
111 		/**
112 		 * Event called on mouse button click action.
113 		 * Params:
114 		 *		button : mouse button
115 		 *		action : press or release
116 		 */
117 		public void onMouseClick(GLFWwindow* window, int button, int action, int dunno)
118 		{
119 			this.m_mouseButtonsStates[button] = (action == GLFW_PRESS);
120 			this.m_mouseButtonClicked = true;
121 		}
122 
123 		/**
124 		 * Event called on mouse movement.
125 		 * Params:
126 		 *		x : x mouse coord
127 		 *		y : y moue coord
128 		 */
129 		public void onMouseMove(GLFWwindow* window, double x, double y)
130 		{
131 			this.m_mouseHasMoved = true;            
132 			this.m_mousePosition = vec2(x, y);
133 		}
134 	}
135 
136 	@nogc @safe
137 	@property pure nothrow
138 	{
139 		public ref const(vec2) mousePosition() const
140 		{
141 			return this.m_mousePosition;
142 		}
143 	}
144 }