1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.System.Mouse;
25 
26 private:
27 
28 import derelict.sdl2.types;
29 import derelict.sdl2.functions;
30 
31 import Dgame.Graphic.Surface;
32 import Dgame.Math.Vector2;
33 
34 public:
35 
36 /**
37  * Represent the Mouse
38  *
39  * Author: Randy Schuett (rswhite4@googlemail.com)
40  */
41 final abstract class Mouse {
42 public:
43     /**
44      * Supported mouse buttons
45      */
46     enum Button : ubyte {
47         Left = 1, /// 
48         Middle = 2, /// 
49         Right = 3, /// 
50         X1 = 4, /// 
51         X2 = 5, /// 
52         Other /// 
53     }
54 
55     /**
56      * Possible System cursors
57      */
58     enum SystemCursor {
59         Arrow = SDL_SYSTEM_CURSOR_ARROW, /// 
60         IBeam = SDL_SYSTEM_CURSOR_IBEAM, /// 
61         Wait = SDL_SYSTEM_CURSOR_WAIT, /// 
62         CrossHair = SDL_SYSTEM_CURSOR_CROSSHAIR, /// 
63         WaitArrow = SDL_SYSTEM_CURSOR_WAITARROW, /// 
64         SizeNWSE = SDL_SYSTEM_CURSOR_SIZENWSE, /// 
65         SizeNESW = SDL_SYSTEM_CURSOR_SIZENESW, /// 
66         SizeWE = SDL_SYSTEM_CURSOR_SIZEWE, /// 
67         SizeNS = SDL_SYSTEM_CURSOR_SIZENS, /// 
68         SizeAll = SDL_SYSTEM_CURSOR_SIZEALL, /// 
69         None = SDL_SYSTEM_CURSOR_NO, /// 
70         Hand = SDL_SYSTEM_CURSOR_HAND /// 
71     }
72 
73     /**
74      * The Cursor representation
75      */
76     alias Cursor = SDL_Cursor*;
77 
78     private static Cursor _cursor;
79 
80     @nogc
81     static ~this() nothrow {
82         if (_cursor)
83             SDL_FreeCursor(_cursor);
84     }
85     
86     /**
87      * Returns if the given button is pressed.
88      * 
89      * See: Mouse.Button
90      */
91     @nogc
92     static bool isPressed(Button btn) nothrow {
93         return (SDL_GetMouseState(null, null) & SDL_BUTTON(btn)) != 0;
94     }
95 
96     /**
97      * Returns the current cursor position
98      */
99     @nogc
100     static Vector2i getCursorPosition() nothrow {
101         int x, y;
102         SDL_GetMouseState(&x, &y);
103         
104         return Vector2i(x, y);
105     }
106 
107     /**
108      * Returns the relative cursor position.
109      * x and y are set to the mouse deltas since the last call
110      */
111     @nogc
112     static Vector2i getRelativeCursorPosition() nothrow {
113         int x, y;
114         SDL_GetRelativeMouseState(&x, &y);
115 
116         return Vector2i(x, y);
117     }
118 
119 static if (SDL_VERSION_ATLEAST(2, 0, 4)) {
120     /**
121      * Returns the global cursor position.
122      * x and y will be reported relative to the top-left of the Desktop
123      */
124     @nogc
125     static Vector2i getGlobalCursorPosition() nothrow {
126         int x, y;
127         SDL_GetGlobalMouseState(&x, &y);
128 
129         return Vector2i(x, y);
130     }
131 }
132 
133     /**
134      * Set the cursor position inside the window.
135      *
136      * Note: A call to this function generates a mouse motion event.
137      */
138     @nogc
139     static void setCursorPosition(int x, int y) nothrow {
140         SDL_Window* wnd = SDL_GetMouseFocus();
141         if (wnd)
142             SDL_WarpMouseInWindow(wnd, x, y);
143     }
144 
145     /**
146      * Set the cursor position inside the window.
147      *
148      * Note: A call to this function generates a mouse motion event.
149      */
150     @nogc
151     static void setCursorPosition(const Vector2i pos) nothrow {
152         Mouse.setCursorPosition(pos.x, pos.y);
153     }
154 
155 static if (SDL_VERSION_ATLEAST(2, 0, 4)) {
156     /**
157      * Set the cursor position in global screen space.
158      *
159      * Note: A call to this function generates a mouse motion event.
160      */
161     @nogc
162     static void setGlobalCursorPosition(int x, int y) nothrow {
163         SDL_WarpMouseGlobal(x, y);
164     }
165 
166     /**
167      * Set the cursor position in global screen space.
168      *
169      * Note: A call to this function generates a mouse motion event.
170      */
171     @nogc
172     static void setGlobalCursorPosition(const Vector2i pos) nothrow {
173         Mouse.setGlobalCursorPosition(pos.x, pos.y);
174     }
175 }
176 
177     /**
178      * Returns if the Relative mouse mode is enabled/supported.
179      */
180     @nogc
181     static bool hasRelativeMouse() nothrow {
182         return SDL_GetRelativeMouseMode() == SDL_TRUE;
183     }
184     
185     /**
186      * Tries to enable/disable the relative mouse mode.
187      * While the mouse is in relative mode, the cursor is hidden,
188      * and the driver will try to report continuous motion in the current Window.
189      * Only relative motion events will be delivered, the mouse position will not change.
190      */
191     @nogc
192     static bool enableRelativeMouse(bool enable) nothrow {
193         return SDL_SetRelativeMouseMode(enable) == 0;
194     }
195     
196     /**
197      * Enable or disable that the cursor is shown on the window.
198      */
199     @nogc
200     static void showCursor(bool enable) nothrow {
201         SDL_ShowCursor(enable);
202     }
203 
204 static if (SDL_VERSION_ATLEAST(2, 0, 4)) {
205     /**
206      * Capture the mouse and track input outside of an Window.
207      */
208     @nogc
209     static void captureCursor(bool enable) nothrow {
210         SDL_CaptureMouse(enable);
211     }
212 }
213 
214     /**
215      * Create a Surface cursor.
216      */
217     @nogc
218     static Cursor createCursor(ref Surface srfc, int hx, int hy) nothrow {
219         Cursor my_cursor = srfc.setAsCursorAt(hx, hy);
220         if (my_cursor && _cursor) {
221             SDL_FreeCursor(_cursor);
222             _cursor = my_cursor;
223         }
224 
225         return _cursor;
226     }
227 
228     /**
229      * Create a system cursor.
230      */
231     @nogc
232     static Cursor createCursor(SystemCursor cursor) nothrow {
233         Cursor my_cursor = SDL_CreateSystemCursor(cursor);
234         if (my_cursor && _cursor) {
235             SDL_FreeCursor(_cursor);
236             _cursor = my_cursor;
237         }
238 
239         return _cursor;
240     }
241 
242     /**
243      * Set the active cursor.
244      */
245     @nogc
246     static void setCursor(Cursor cursor) nothrow {
247         SDL_SetCursor(cursor);
248     }
249 
250     /**
251      * Returns the active cursor.
252      */
253     @nogc
254     static Cursor getCursor() nothrow {
255         return SDL_GetCursor();
256     }
257 
258     /**
259      * Get the default cursor.
260      */
261     @nogc
262     static Cursor getDefaultCursor() nothrow {
263         return SDL_GetDefaultCursor();
264     }
265 }