1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:          $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/input/mouse/impl.d)
6  * Documentation:
7  * Coverage:
8 **/
9 module liberty.input.mouse.impl;
10 
11 import bindbc.glfw;
12 
13 import liberty.core.platform;
14 import liberty.core.window;
15 import liberty.math.vector;
16 import liberty.input.mouse.constants;
17 
18 /**
19  *
20 **/
21 final class Mouse {
22   private {
23     bool[MOUSE_BUTTONS] buttonsState;
24     Vector2F position;
25     Vector2F previousPosition;
26     Vector2F lastPosition;
27     CursorType cursorType;
28   }
29 
30   /**
31    * Returns true if mouse button was just pressed in an event loop.
32   **/
33   bool isButtonDown(MouseButton button)  {
34     return isButtonHold(button) && !buttonsState[button];
35   }
36 
37   /**
38    * Returns true if mouse button was just released in an event loop.
39   **/
40   bool isButtonUp(MouseButton button)  {
41     return !isButtonHold(button) && buttonsState[button];
42   }
43 
44   /**
45    * Returns true if mouse button is still pressed in an event loop.
46    * Use case: shooting something.
47   **/
48   bool isButtonHold(MouseButton button)  {
49     return glfwGetMouseButton(Platform.getWindow().getHandle(), button) == GLFW_PRESS;
50   }
51 
52   /**
53    * Returns true if mouse button has no input action in an event loop.
54   **/
55   bool isButtonNone(MouseButton button)  {
56     return glfwGetMouseButton(Platform.getWindow().getHandle(), button) == GLFW_RELEASE;
57   }
58 
59   /**
60    *
61   **/
62   bool isUnfolding(MouseButton button, MouseAction action)  {
63     final switch (action) with (MouseAction) {
64       case NONE:
65         return isButtonNone(button);
66       case DOWN:
67         return isButtonDown(button);
68       case UP:
69         return isButtonUp(button);
70       case HOLD:
71         return isButtonHold(button);
72     }
73   }
74 
75   /**
76    * Returns a 2d vector containing mouse position in the current window.
77    * You can choose what window to test with the given argument.
78   **/
79   Vector2F getPostion(Window window = Platform.getWindow())  {
80     double x, y;
81     glfwGetCursorPos(window.getHandle(), &x, &y);
82     return Vector2F(cast(float)x, cast(float)y);
83   }
84   
85   /**
86    * Returns a 2d vector containing previous mouse position.
87   **/
88   Vector2F getPreviousPostion()   {
89     return previousPosition;
90   }
91 
92   /**
93    * Returns a 2d vector containing last mouse position.
94   **/
95   Vector2F getLastPostion()   {
96     return lastPosition;
97   }
98 
99   /**
100    * Returns true if mouse cursor is moving left.
101   **/
102   bool isMovingLeft()   const {
103     return lastPosition.x > position.x;
104   }
105 
106   /**
107    * Returns true if mouse cursor is moving right.
108   **/
109   bool isMovingRight()   const {
110     return lastPosition.x < position.x;
111   }
112 
113   /**
114    * Returns true if mouse cursor is moving up.
115   **/
116   bool isMovingUp()   const {
117     return lastPosition.y > position.y;
118   }
119 
120   /**
121    * Returns true if mouse cursor is moving down.
122   **/
123   bool isMovingDown()   const {
124     return lastPosition.y < position.y;
125   }
126 
127   /**
128    * Returns true if mouse cursor is moving.
129   **/
130   bool isMoving()   const {
131     return lastPosition != position;
132   }
133 
134   /**
135    * Returns true if mouse cursor is staying.
136   **/
137   bool isStaying()   const {
138     return lastPosition == position;
139   }
140 
141   /**
142    * Returns true if mouse cursor was moving left.
143   **/
144   bool wasMovingLeft()   const {
145     return previousPosition.x > position.x;
146   }
147 
148   /**
149    * Returns true if mouse cursor was moving right.
150   **/
151   bool wasMovingRight()   const {
152     return previousPosition.x < position.x;
153   }
154 
155   /**
156    * Returns true if mouse cursor was moving up.
157   **/
158   bool wasMovingUp()   const {
159     return previousPosition.y > position.y;
160   }
161 
162   /**
163    * Returns true if mouse cursor was moving down.
164   **/
165   bool wasMovingDown()   const {
166     return previousPosition.y < position.y;
167   }
168 
169   /**
170    * Set current cursor type.
171    * For available options see $(D CursorType).
172   **/
173   void setCursorType(CursorType cursorType, Window window = Platform.getWindow())  {
174     glfwSetInputMode(window.getHandle(), GLFW_CURSOR, cursorType);
175     this.cursorType = cursorType;
176   }
177 
178   /**
179    * Returns the type of the cursor.
180    * For available returned values see $(D CursorType).
181   **/
182   CursorType getCursorType()   {
183     return cursorType;
184   }
185 
186   package(liberty.input) void update()  {
187     static foreach (i; 0..MOUSE_BUTTONS)
188       buttonsState[i] = isButtonHold(cast(MouseButton)i);
189   }
190 
191   package(liberty.input) Mouse setPosition(Vector2F position)   {
192     this.position = position;
193     return this;
194   }
195 
196   package(liberty.input) Mouse setPreviousPostion(Vector2F position)   {
197     previousPosition = position;
198     return this;
199   }
200 
201   package(liberty.input) Mouse setLastPosition(Vector2F position)   {
202     lastPosition = position;
203     return this;
204   }
205 }