1 | /** |
2 | * Copyright (c) 2006-2023 LOVE Development Team |
3 | * |
4 | * This software is provided 'as-is', without any express or implied |
5 | * warranty. In no event will the authors be held liable for any damages |
6 | * arising from the use of this software. |
7 | * |
8 | * Permission is granted to anyone to use this software for any purpose, |
9 | * including commercial applications, and to alter it and redistribute it |
10 | * freely, subject to the following restrictions: |
11 | * |
12 | * 1. The origin of this software must not be misrepresented; you must not |
13 | * claim that you wrote the original software. If you use this software |
14 | * in a product, an acknowledgment in the product documentation would be |
15 | * appreciated but is not required. |
16 | * 2. Altered source versions must be plainly marked as such, and must not be |
17 | * misrepresented as being the original software. |
18 | * 3. This notice may not be removed or altered from any source distribution. |
19 | **/ |
20 | |
21 | // LOVE |
22 | #include "wrap_Mouse.h" |
23 | #include "wrap_Cursor.h" |
24 | #include "common/config.h" |
25 | |
26 | #include "sdl/Mouse.h" |
27 | #include "filesystem/File.h" |
28 | |
29 | namespace love |
30 | { |
31 | namespace mouse |
32 | { |
33 | |
34 | #define instance() (Module::getInstance<Mouse>(Module::M_MOUSE)) |
35 | |
36 | int w_newCursor(lua_State *L) |
37 | { |
38 | Cursor *cursor = nullptr; |
39 | |
40 | if (lua_isstring(L, 1) || luax_istype(L, 1, love::filesystem::File::type) || luax_istype(L, 1, love::filesystem::FileData::type)) |
41 | luax_convobj(L, 1, "image" , "newImageData" ); |
42 | |
43 | love::image::ImageData *data = luax_checktype<love::image::ImageData>(L, 1); |
44 | int hotx = (int) luaL_optinteger(L, 2, 0); |
45 | int hoty = (int) luaL_optinteger(L, 3, 0); |
46 | |
47 | luax_catchexcept(L, [&](){ cursor = instance()->newCursor(data, hotx, hoty); }); |
48 | |
49 | luax_pushtype(L, cursor); |
50 | cursor->release(); |
51 | return 1; |
52 | } |
53 | |
54 | int w_getSystemCursor(lua_State *L) |
55 | { |
56 | const char *str = luaL_checkstring(L, 1); |
57 | Cursor::SystemCursor systemCursor; |
58 | |
59 | if (!Cursor::getConstant(str, systemCursor)) |
60 | return luax_enumerror(L, "system cursor type" , str); |
61 | |
62 | Cursor *cursor = 0; |
63 | luax_catchexcept(L, [&](){ cursor = instance()->getSystemCursor(systemCursor); }); |
64 | |
65 | luax_pushtype(L, cursor); |
66 | return 1; |
67 | } |
68 | |
69 | int w_setCursor(lua_State *L) |
70 | { |
71 | // Revert to the default system cursor if no argument is given. |
72 | if (lua_isnoneornil(L, 1)) |
73 | { |
74 | instance()->setCursor(); |
75 | return 0; |
76 | } |
77 | |
78 | Cursor *cursor = luax_checkcursor(L, 1); |
79 | instance()->setCursor(cursor); |
80 | return 0; |
81 | } |
82 | |
83 | int w_getCursor(lua_State *L) |
84 | { |
85 | Cursor *cursor = instance()->getCursor(); |
86 | |
87 | if (cursor) |
88 | luax_pushtype(L, cursor); |
89 | else |
90 | lua_pushnil(L); |
91 | |
92 | return 1; |
93 | } |
94 | |
95 | int w_isCursorSupported(lua_State *L) |
96 | { |
97 | luax_pushboolean(L, instance()->isCursorSupported()); |
98 | return 1; |
99 | } |
100 | |
101 | int w_getX(lua_State *L) |
102 | { |
103 | lua_pushnumber(L, instance()->getX()); |
104 | return 1; |
105 | } |
106 | |
107 | int w_getY(lua_State *L) |
108 | { |
109 | lua_pushnumber(L, instance()->getY()); |
110 | return 1; |
111 | } |
112 | |
113 | int w_getPosition(lua_State *L) |
114 | { |
115 | double x, y; |
116 | instance()->getPosition(x, y); |
117 | lua_pushnumber(L, x); |
118 | lua_pushnumber(L, y); |
119 | return 2; |
120 | } |
121 | |
122 | int w_setX(lua_State *L) |
123 | { |
124 | double x = luaL_checknumber(L, 1); |
125 | instance()->setX(x); |
126 | return 0; |
127 | } |
128 | |
129 | int w_setY(lua_State *L) |
130 | { |
131 | double y = luaL_checknumber(L, 1); |
132 | instance()->setY(y); |
133 | return 0; |
134 | } |
135 | |
136 | int w_setPosition(lua_State *L) |
137 | { |
138 | double x = luaL_checknumber(L, 1); |
139 | double y = luaL_checknumber(L, 2); |
140 | instance()->setPosition(x, y); |
141 | return 0; |
142 | } |
143 | |
144 | int w_isDown(lua_State *L) |
145 | { |
146 | bool istable = lua_istable(L, 1); |
147 | int num = istable ? (int) luax_objlen(L, 1) : lua_gettop(L); |
148 | |
149 | std::vector<int> buttons; |
150 | buttons.reserve(num); |
151 | |
152 | if (istable) |
153 | { |
154 | for (int i = 0; i < num; i++) |
155 | { |
156 | lua_rawgeti(L, 1, i + 1); |
157 | buttons.push_back((int) luaL_checkinteger(L, -1)); |
158 | lua_pop(L, 1); |
159 | } |
160 | } |
161 | else |
162 | { |
163 | for (int i = 0; i < num; i++) |
164 | buttons.push_back((int) luaL_checkinteger(L, i + 1)); |
165 | } |
166 | |
167 | luax_pushboolean(L, instance()->isDown(buttons)); |
168 | return 1; |
169 | } |
170 | |
171 | int w_setVisible(lua_State *L) |
172 | { |
173 | bool b = luax_checkboolean(L, 1); |
174 | instance()->setVisible(b); |
175 | return 0; |
176 | } |
177 | |
178 | int w_isVisible(lua_State *L) |
179 | { |
180 | luax_pushboolean(L, instance()->isVisible()); |
181 | return 1; |
182 | } |
183 | |
184 | int w_setGrabbed(lua_State *L) |
185 | { |
186 | bool b = luax_checkboolean(L, 1); |
187 | instance()->setGrabbed(b); |
188 | return 0; |
189 | } |
190 | |
191 | int w_isGrabbed(lua_State *L) |
192 | { |
193 | luax_pushboolean(L, instance()->isGrabbed()); |
194 | return 1; |
195 | } |
196 | |
197 | int w_setRelativeMode(lua_State *L) |
198 | { |
199 | bool relative = luax_checkboolean(L, 1); |
200 | luax_pushboolean(L, instance()->setRelativeMode(relative)); |
201 | return 1; |
202 | } |
203 | |
204 | int w_getRelativeMode(lua_State *L) |
205 | { |
206 | luax_pushboolean(L, instance()->getRelativeMode()); |
207 | return 1; |
208 | } |
209 | |
210 | // List of functions to wrap. |
211 | static const luaL_Reg functions[] = |
212 | { |
213 | { "newCursor" , w_newCursor }, |
214 | { "getSystemCursor" , w_getSystemCursor }, |
215 | { "setCursor" , w_setCursor }, |
216 | { "getCursor" , w_getCursor }, |
217 | { "isCursorSupported" , w_isCursorSupported }, |
218 | { "getX" , w_getX }, |
219 | { "getY" , w_getY }, |
220 | { "setX" , w_setX }, |
221 | { "setY" , w_setY }, |
222 | { "setPosition" , w_setPosition }, |
223 | { "isDown" , w_isDown }, |
224 | { "setVisible" , w_setVisible }, |
225 | { "isVisible" , w_isVisible }, |
226 | { "getPosition" , w_getPosition }, |
227 | { "setGrabbed" , w_setGrabbed }, |
228 | { "isGrabbed" , w_isGrabbed }, |
229 | { "setRelativeMode" , w_setRelativeMode }, |
230 | { "getRelativeMode" , w_getRelativeMode }, |
231 | { 0, 0 } |
232 | }; |
233 | |
234 | // Types for this module. |
235 | static const lua_CFunction types[] = |
236 | { |
237 | luaopen_cursor, |
238 | 0, |
239 | }; |
240 | |
241 | extern "C" int luaopen_love_mouse(lua_State *L) |
242 | { |
243 | Mouse *instance = instance(); |
244 | if (instance == nullptr) |
245 | { |
246 | luax_catchexcept(L, [&](){ instance = new love::mouse::sdl::Mouse(); }); |
247 | } |
248 | else |
249 | instance->retain(); |
250 | |
251 | WrappedModule w; |
252 | w.module = instance; |
253 | w.name = "mouse" ; |
254 | w.type = &Module::type; |
255 | w.functions = functions; |
256 | w.types = types; |
257 | |
258 | return luax_register_module(L, w); |
259 | } |
260 | |
261 | } // mouse |
262 | } // love |
263 | |