1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ags/engine/ac/mouse.h"
24 #include "ags/shared/ac/common.h"
25 #include "ags/shared/ac/character_info.h"
26 #include "ags/engine/ac/draw.h"
27 #include "ags/engine/ac/dynobj/script_mouse.h"
28 #include "ags/engine/ac/dynobj/script_system.h"
29 #include "ags/engine/ac/game_setup.h"
30 #include "ags/shared/ac/game_setup_struct.h"
31 #include "ags/engine/ac/game_state.h"
32 #include "ags/engine/ac/global_mouse.h"
33 #include "ags/engine/ac/global_screen.h"
34 #include "ags/engine/ac/sys_events.h"
35 #include "ags/engine/ac/system.h"
36 #include "ags/engine/ac/view_frame.h"
37 #include "ags/engine/debugging/debug_log.h"
38 #include "ags/shared/gui/gui_button.h"
39 #include "ags/shared/gui/gui_main.h"
40 #include "ags/engine/device/mouse_w32.h"
41 #include "ags/shared/ac/sprite_cache.h"
42 #include "ags/engine/gfx/graphics_driver.h"
43 #include "ags/engine/gfx/gfxfilter.h"
44 #include "ags/engine/platform/base/ags_platform_driver.h"
45 #include "ags/shared/debugging/out.h"
46 #include "ags/engine/script/script_api.h"
47 #include "ags/engine/script/script_runtime.h"
48 #include "ags/engine/ac/global_game.h"
49 #include "ags/plugins/ags_plugin.h"
50 #include "ags/globals.h"
51 
52 namespace AGS3 {
53 
54 using namespace AGS::Shared;
55 using namespace AGS::Engine;
56 
57 extern void ags_domouse(int str);
58 
59 // The mouse functions are static so the script doesn't pass
60 // in an object parameter
Mouse_SetVisible(int isOn)61 void Mouse_SetVisible(int isOn) {
62 	if (isOn)
63 		ShowMouseCursor();
64 	else
65 		HideMouseCursor();
66 }
67 
Mouse_GetVisible()68 int Mouse_GetVisible() {
69 	if (_GP(play).mouse_cursor_hidden)
70 		return 0;
71 	return 1;
72 }
73 
SetMouseBounds(int x1,int y1,int x2,int y2)74 void SetMouseBounds(int x1, int y1, int x2, int y2) {
75 	int xmax = game_to_data_coord(_GP(play).GetMainViewport().GetWidth()) - 1;
76 	int ymax = game_to_data_coord(_GP(play).GetMainViewport().GetHeight()) - 1;
77 	if ((x1 == 0) && (y1 == 0) && (x2 == 0) && (y2 == 0)) {
78 		x2 = xmax;
79 		y2 = ymax;
80 	} else {
81 		if (x1 < 0 || x1 > xmax || x2 < 0 || x2 > xmax || x1 > x2 || y1 < 0 || y1 > ymax || y2 < 0 || y2 > ymax || y1 > y2)
82 			debug_script_warn("SetMouseBounds: arguments are out of range and will be corrected: (%d,%d)-(%d,%d), range is (%d,%d)-(%d,%d)",
83 			                  x1, y1, x2, y2, 0, 0, xmax, ymax);
84 		x1 = Math::Clamp(x1, 0, xmax);
85 		x2 = Math::Clamp(x2, x1, xmax);
86 		y1 = Math::Clamp(y1, 0, ymax);
87 		y2 = Math::Clamp(y2, y1, ymax);
88 	}
89 
90 	debug_script_log("Mouse bounds constrained to (%d,%d)-(%d,%d)", x1, y1, x2, y2);
91 	data_to_game_coords(&x1, &y1);
92 	data_to_game_round_up(&x2, &y2);
93 
94 	_GP(play).mboundx1 = x1;
95 	_GP(play).mboundx2 = x2;
96 	_GP(play).mboundy1 = y1;
97 	_GP(play).mboundy2 = y2;
98 	_GP(mouse).SetMoveLimit(Rect(x1, y1, x2, y2));
99 }
100 
101 // mouse cursor functions:
102 // set_mouse_cursor: changes visual appearance to specified cursor
set_mouse_cursor(int newcurs)103 void set_mouse_cursor(int newcurs) {
104 	const int hotspotx = _GP(game).mcurs[newcurs].hotx, hotspoty = _GP(game).mcurs[newcurs].hoty;
105 	msethotspot(hotspotx, hotspoty);
106 
107 	// if it's same cursor and there's animation in progress, then don't assign a new pic just yet
108 	if (newcurs == _G(cur_cursor) && _GP(game).mcurs[newcurs].view >= 0 &&
109 	        (_G(mouse_frame) > 0 || _G(mouse_delay) > 0)) {
110 		return;
111 	}
112 
113 	// reset animation timing only if it's another cursor
114 	if (newcurs != _G(cur_cursor)) {
115 		_G(cur_cursor) = newcurs;
116 		_G(mouse_frame) = 0;
117 		_G(mouse_delay) = 0;
118 	}
119 
120 	// Assign new pic
121 	set_new_cursor_graphic(_GP(game).mcurs[newcurs].pic);
122 	delete _G(dotted_mouse_cursor);
123 	_G(dotted_mouse_cursor) = nullptr;
124 
125 	// If it's inventory cursor, draw hotspot crosshair sprite upon it
126 	if ((newcurs == MODE_USE) && (_GP(game).mcurs[newcurs].pic > 0) &&
127 	        ((_GP(game).hotdot > 0) || (_GP(game).invhotdotsprite > 0))) {
128 		// If necessary, create a copy of the cursor and put the hotspot
129 		// dot onto it
130 		_G(dotted_mouse_cursor) = BitmapHelper::CreateBitmapCopy(_G(mousecurs)[0]);
131 
132 		if (_GP(game).invhotdotsprite > 0) {
133 			draw_sprite_slot_support_alpha(_G(dotted_mouse_cursor),
134 			                               (_GP(game).SpriteInfos[_GP(game).mcurs[newcurs].pic].Flags & SPF_ALPHACHANNEL) != 0,
135 			                               hotspotx - _GP(game).SpriteInfos[_GP(game).invhotdotsprite].Width / 2,
136 			                               hotspoty - _GP(game).SpriteInfos[_GP(game).invhotdotsprite].Height / 2,
137 			                               _GP(game).invhotdotsprite);
138 		} else {
139 			putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty, MakeColor(_GP(game).hotdot));
140 
141 			if (_GP(game).hotdotouter > 0) {
142 				int outercol = MakeColor(_GP(game).hotdotouter);
143 
144 				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx + get_fixed_pixel_size(1), hotspoty, outercol);
145 				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty + get_fixed_pixel_size(1), outercol);
146 				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx - get_fixed_pixel_size(1), hotspoty, outercol);
147 				putpixel_compensate(_G(dotted_mouse_cursor), hotspotx, hotspoty - get_fixed_pixel_size(1), outercol);
148 			}
149 		}
150 		_G(mousecurs)[0] = _G(dotted_mouse_cursor);
151 		update_cached_mouse_cursor();
152 	}
153 }
154 
155 // set_default_cursor: resets visual appearance to current mode (walk, look, etc)
set_default_cursor()156 void set_default_cursor() {
157 	set_mouse_cursor(_G(cur_mode));
158 }
159 
160 // permanently change cursor graphic
ChangeCursorGraphic(int curs,int newslot)161 void ChangeCursorGraphic(int curs, int newslot) {
162 	if ((curs < 0) || (curs >= _GP(game).numcursors))
163 		quit("!ChangeCursorGraphic: invalid mouse cursor");
164 
165 	if ((curs == MODE_USE) && (_GP(game).options[OPT_FIXEDINVCURSOR] == 0))
166 		debug_script_warn("Mouse.ChangeModeGraphic should not be used on the Inventory cursor when the cursor is linked to the active inventory item");
167 
168 	_GP(game).mcurs[curs].pic = newslot;
169 	_GP(spriteset).Precache(newslot);
170 	if (curs == _G(cur_mode))
171 		set_mouse_cursor(curs);
172 }
173 
Mouse_GetModeGraphic(int curs)174 int Mouse_GetModeGraphic(int curs) {
175 	if ((curs < 0) || (curs >= _GP(game).numcursors))
176 		quit("!Mouse.GetModeGraphic: invalid mouse cursor");
177 
178 	return _GP(game).mcurs[curs].pic;
179 }
180 
ChangeCursorHotspot(int curs,int x,int y)181 void ChangeCursorHotspot(int curs, int x, int y) {
182 	if ((curs < 0) || (curs >= _GP(game).numcursors))
183 		quit("!ChangeCursorHotspot: invalid mouse cursor");
184 	_GP(game).mcurs[curs].hotx = data_to_game_coord(x);
185 	_GP(game).mcurs[curs].hoty = data_to_game_coord(y);
186 	if (curs == _G(cur_cursor))
187 		set_mouse_cursor(_G(cur_cursor));
188 }
189 
Mouse_ChangeModeView(int curs,int newview)190 void Mouse_ChangeModeView(int curs, int newview) {
191 	if ((curs < 0) || (curs >= _GP(game).numcursors))
192 		quit("!Mouse.ChangeModeView: invalid mouse cursor");
193 
194 	newview--;
195 
196 	_GP(game).mcurs[curs].view = newview;
197 
198 	if (newview >= 0) {
199 		precache_view(newview);
200 	}
201 
202 	if (curs == _G(cur_cursor))
203 		_G(mouse_delay) = 0;  // force update
204 }
205 
SetNextCursor()206 void SetNextCursor() {
207 	set_cursor_mode(find_next_enabled_cursor(_G(cur_mode) + 1));
208 }
209 
SetPreviousCursor()210 void SetPreviousCursor() {
211 	set_cursor_mode(find_previous_enabled_cursor(_G(cur_mode) - 1));
212 }
213 
214 // set_cursor_mode: changes mode and appearance
set_cursor_mode(int newmode)215 void set_cursor_mode(int newmode) {
216 	if ((newmode < 0) || (newmode >= _GP(game).numcursors))
217 		quit("!SetCursorMode: invalid cursor mode specified");
218 
219 	if (_GP(game).mcurs[newmode].flags & MCF_DISABLED) {
220 		find_next_enabled_cursor(newmode);
221 		return;
222 	}
223 	if (newmode == MODE_USE) {
224 		if (_G(playerchar)->activeinv == -1) {
225 			find_next_enabled_cursor(0);
226 			return;
227 		}
228 		update_inv_cursor(_G(playerchar)->activeinv);
229 	}
230 	_G(cur_mode) = newmode;
231 	set_default_cursor();
232 
233 	debug_script_log("Cursor mode set to %d", newmode);
234 }
235 
enable_cursor_mode(int modd)236 void enable_cursor_mode(int modd) {
237 	_GP(game).mcurs[modd].flags &= ~MCF_DISABLED;
238 	// now search the interfaces for related buttons to re-enable
239 	int uu, ww;
240 
241 	for (uu = 0; uu < _GP(game).numgui; uu++) {
242 		for (ww = 0; ww < _GP(guis)[uu].GetControlCount(); ww++) {
243 			if (_GP(guis)[uu].GetControlType(ww) != kGUIButton) continue;
244 			GUIButton *gbpt = (GUIButton *)_GP(guis)[uu].GetControl(ww);
245 			if (gbpt->ClickAction[kMouseLeft] != kGUIAction_SetMode) continue;
246 			if (gbpt->ClickData[kMouseLeft] != modd) continue;
247 			gbpt->SetEnabled(true);
248 		}
249 	}
250 }
251 
disable_cursor_mode(int modd)252 void disable_cursor_mode(int modd) {
253 	_GP(game).mcurs[modd].flags |= MCF_DISABLED;
254 	// now search the interfaces for related buttons to kill
255 	int uu, ww;
256 
257 	for (uu = 0; uu < _GP(game).numgui; uu++) {
258 		for (ww = 0; ww < _GP(guis)[uu].GetControlCount(); ww++) {
259 			if (_GP(guis)[uu].GetControlType(ww) != kGUIButton) continue;
260 			GUIButton *gbpt = (GUIButton *)_GP(guis)[uu].GetControl(ww);
261 			if (gbpt->ClickAction[kMouseLeft] != kGUIAction_SetMode) continue;
262 			if (gbpt->ClickData[kMouseLeft] != modd) continue;
263 			gbpt->SetEnabled(false);
264 		}
265 	}
266 	if (_G(cur_mode) == modd) find_next_enabled_cursor(modd);
267 }
268 
RefreshMouse()269 void RefreshMouse() {
270 	ags_domouse(DOMOUSE_NOCURSOR);
271 	_GP(scmouse).x = game_to_data_coord(_G(mousex));
272 	_GP(scmouse).y = game_to_data_coord(_G(mousey));
273 }
274 
SetMousePosition(int newx,int newy)275 void SetMousePosition(int newx, int newy) {
276 	const Rect &viewport = _GP(play).GetMainViewport();
277 
278 	if (newx < 0)
279 		newx = 0;
280 	if (newy < 0)
281 		newy = 0;
282 	if (newx >= viewport.GetWidth())
283 		newx = viewport.GetWidth() - 1;
284 	if (newy >= viewport.GetHeight())
285 		newy = viewport.GetHeight() - 1;
286 
287 	data_to_game_coords(&newx, &newy);
288 	_GP(mouse).SetPosition(Point(newx, newy));
289 	RefreshMouse();
290 }
291 
GetCursorMode()292 int GetCursorMode() {
293 	return _G(cur_mode);
294 }
295 
IsButtonDown(int which)296 int IsButtonDown(int which) {
297 	if ((which < 1) || (which > 3))
298 		quit("!IsButtonDown: only works with eMouseLeft, eMouseRight, eMouseMiddle");
299 	if (ags_misbuttondown(which - 1))
300 		return 1;
301 	return 0;
302 }
303 
IsModeEnabled(int which)304 int IsModeEnabled(int which) {
305 	return (which < 0) || (which >= _GP(game).numcursors) ? 0 :
306 	       which == MODE_USE ? _G(playerchar)->activeinv > 0 :
307 	       (_GP(game).mcurs[which].flags & MCF_DISABLED) == 0;
308 }
309 
Mouse_EnableControl(bool on)310 void Mouse_EnableControl(bool on) {
311 	bool should_control_mouse =
312 	    _GP(usetup).mouse_ctrl_when == kMouseCtrl_Always ||
313 	    (_GP(usetup).mouse_ctrl_when == kMouseCtrl_Fullscreen && (_GP(scsystem).windowed == 0));
314 	_GP(mouse).SetMovementControl(should_control_mouse & on);
315 	_GP(usetup).mouse_ctrl_enabled = on; // remember setting in config
316 }
317 
318 //=============================================================================
319 
GetMouseCursor()320 int GetMouseCursor() {
321 	return _G(cur_cursor);
322 }
323 
update_script_mouse_coords()324 void update_script_mouse_coords() {
325 	_GP(scmouse).x = game_to_data_coord(_G(mousex));
326 	_GP(scmouse).y = game_to_data_coord(_G(mousey));
327 }
328 
update_inv_cursor(int invnum)329 void update_inv_cursor(int invnum) {
330 
331 	if ((_GP(game).options[OPT_FIXEDINVCURSOR] == 0) && (invnum > 0)) {
332 		int cursorSprite = _GP(game).invinfo[invnum].cursorPic;
333 
334 		// Fall back to the inventory pic if no cursor pic is defined.
335 		if (cursorSprite == 0)
336 			cursorSprite = _GP(game).invinfo[invnum].pic;
337 
338 		_GP(game).mcurs[MODE_USE].pic = cursorSprite;
339 		// all cursor images must be pre-cached
340 		_GP(spriteset).Precache(cursorSprite);
341 
342 		if ((_GP(game).invinfo[invnum].hotx > 0) || (_GP(game).invinfo[invnum].hoty > 0)) {
343 			// if the hotspot was set (unfortunately 0,0 isn't a valid co-ord)
344 			_GP(game).mcurs[MODE_USE].hotx = _GP(game).invinfo[invnum].hotx;
345 			_GP(game).mcurs[MODE_USE].hoty = _GP(game).invinfo[invnum].hoty;
346 		} else {
347 			_GP(game).mcurs[MODE_USE].hotx = _GP(game).SpriteInfos[cursorSprite].Width / 2;
348 			_GP(game).mcurs[MODE_USE].hoty = _GP(game).SpriteInfos[cursorSprite].Height / 2;
349 		}
350 	}
351 }
352 
update_cached_mouse_cursor()353 void update_cached_mouse_cursor() {
354 	if (_G(mouseCursor) != nullptr)
355 		_G(gfxDriver)->DestroyDDB(_G(mouseCursor));
356 	_G(mouseCursor) = _G(gfxDriver)->CreateDDBFromBitmap(_G(mousecurs)[0], _G(alpha_blend_cursor) != 0);
357 }
358 
set_new_cursor_graphic(int spriteslot)359 void set_new_cursor_graphic(int spriteslot) {
360 	_G(mousecurs)[0] = _GP(spriteset)[spriteslot];
361 
362 	// It looks like spriteslot 0 can be used in games with version 2.72 and lower.
363 	// The NULL check should ensure that the sprite is valid anyway.
364 	if (((spriteslot < 1) && (_G(loaded_game_file_version) > kGameVersion_272)) || (_G(mousecurs)[0] == nullptr)) {
365 		if (_G(blank_mouse_cursor) == nullptr) {
366 			_G(blank_mouse_cursor) = BitmapHelper::CreateTransparentBitmap(1, 1, _GP(game).GetColorDepth());
367 		}
368 		_G(mousecurs)[0] = _G(blank_mouse_cursor);
369 	}
370 
371 	if (_GP(game).SpriteInfos[spriteslot].Flags & SPF_ALPHACHANNEL)
372 		_G(alpha_blend_cursor) = 1;
373 	else
374 		_G(alpha_blend_cursor) = 0;
375 
376 	update_cached_mouse_cursor();
377 }
378 
is_standard_cursor_enabled(int curs)379 bool is_standard_cursor_enabled(int curs) {
380 	if ((_GP(game).mcurs[curs].flags & MCF_DISABLED) == 0) {
381 		// inventory cursor, and they have an active item
382 		if (curs == MODE_USE) {
383 			if (_G(playerchar)->activeinv > 0)
384 				return true;
385 		}
386 		// standard cursor that's not disabled, go with it
387 		else if (_GP(game).mcurs[curs].flags & MCF_STANDARD)
388 			return true;
389 	}
390 	return false;
391 }
392 
find_next_enabled_cursor(int startwith)393 int find_next_enabled_cursor(int startwith) {
394 	if (startwith >= _GP(game).numcursors)
395 		startwith = 0;
396 	int testing = startwith;
397 	do {
398 		if (is_standard_cursor_enabled(testing)) break;
399 		testing++;
400 		if (testing >= _GP(game).numcursors) testing = 0;
401 	} while (testing != startwith);
402 
403 	if (testing != startwith)
404 		set_cursor_mode(testing);
405 
406 	return testing;
407 }
408 
find_previous_enabled_cursor(int startwith)409 int find_previous_enabled_cursor(int startwith) {
410 	if (startwith < 0)
411 		startwith = _GP(game).numcursors - 1;
412 	int testing = startwith;
413 	do {
414 		if (is_standard_cursor_enabled(testing)) break;
415 		testing--;
416 		if (testing < 0) testing = _GP(game).numcursors - 1;
417 	} while (testing != startwith);
418 
419 	if (testing != startwith)
420 		set_cursor_mode(testing);
421 
422 	return testing;
423 }
424 
425 
426 //=============================================================================
427 //
428 // Script API Functions
429 //
430 //=============================================================================
431 
432 // void  (int curs, int newslot)
Sc_ChangeCursorGraphic(const RuntimeScriptValue * params,int32_t param_count)433 RuntimeScriptValue Sc_ChangeCursorGraphic(const RuntimeScriptValue *params, int32_t param_count) {
434 	API_SCALL_VOID_PINT2(ChangeCursorGraphic);
435 }
436 
437 // void  (int curs, int x, int y)
Sc_ChangeCursorHotspot(const RuntimeScriptValue * params,int32_t param_count)438 RuntimeScriptValue Sc_ChangeCursorHotspot(const RuntimeScriptValue *params, int32_t param_count) {
439 	API_SCALL_VOID_PINT3(ChangeCursorHotspot);
440 }
441 
442 // void (int curs, int newview)
Sc_Mouse_ChangeModeView(const RuntimeScriptValue * params,int32_t param_count)443 RuntimeScriptValue Sc_Mouse_ChangeModeView(const RuntimeScriptValue *params, int32_t param_count) {
444 	API_SCALL_VOID_PINT2(Mouse_ChangeModeView);
445 }
446 
447 // void (int modd)
Sc_disable_cursor_mode(const RuntimeScriptValue * params,int32_t param_count)448 RuntimeScriptValue Sc_disable_cursor_mode(const RuntimeScriptValue *params, int32_t param_count) {
449 	API_SCALL_VOID_PINT(disable_cursor_mode);
450 }
451 
452 // void (int modd)
Sc_enable_cursor_mode(const RuntimeScriptValue * params,int32_t param_count)453 RuntimeScriptValue Sc_enable_cursor_mode(const RuntimeScriptValue *params, int32_t param_count) {
454 	API_SCALL_VOID_PINT(enable_cursor_mode);
455 }
456 
457 // int (int curs)
Sc_Mouse_GetModeGraphic(const RuntimeScriptValue * params,int32_t param_count)458 RuntimeScriptValue Sc_Mouse_GetModeGraphic(const RuntimeScriptValue *params, int32_t param_count) {
459 	API_SCALL_INT_PINT(Mouse_GetModeGraphic);
460 }
461 
462 // int (int which)
Sc_IsButtonDown(const RuntimeScriptValue * params,int32_t param_count)463 RuntimeScriptValue Sc_IsButtonDown(const RuntimeScriptValue *params, int32_t param_count) {
464 	API_SCALL_INT_PINT(IsButtonDown);
465 }
466 
467 // int (int which)
Sc_IsModeEnabled(const RuntimeScriptValue * params,int32_t param_count)468 RuntimeScriptValue Sc_IsModeEnabled(const RuntimeScriptValue *params, int32_t param_count) {
469 	API_SCALL_INT_PINT(IsModeEnabled);
470 }
471 
472 // void ();
Sc_SaveCursorForLocationChange(const RuntimeScriptValue * params,int32_t param_count)473 RuntimeScriptValue Sc_SaveCursorForLocationChange(const RuntimeScriptValue *params, int32_t param_count) {
474 	API_SCALL_VOID(SaveCursorForLocationChange);
475 }
476 
477 // void  ()
Sc_SetNextCursor(const RuntimeScriptValue * params,int32_t param_count)478 RuntimeScriptValue Sc_SetNextCursor(const RuntimeScriptValue *params, int32_t param_count) {
479 	API_SCALL_VOID(SetNextCursor);
480 }
481 
482 // void  ()
Sc_SetPreviousCursor(const RuntimeScriptValue * params,int32_t param_count)483 RuntimeScriptValue Sc_SetPreviousCursor(const RuntimeScriptValue *params, int32_t param_count) {
484 	API_SCALL_VOID(SetPreviousCursor);
485 }
486 
487 // void  (int x1, int y1, int x2, int y2)
Sc_SetMouseBounds(const RuntimeScriptValue * params,int32_t param_count)488 RuntimeScriptValue Sc_SetMouseBounds(const RuntimeScriptValue *params, int32_t param_count) {
489 	API_SCALL_VOID_PINT4(SetMouseBounds);
490 }
491 
492 // void  (int newx, int newy)
Sc_SetMousePosition(const RuntimeScriptValue * params,int32_t param_count)493 RuntimeScriptValue Sc_SetMousePosition(const RuntimeScriptValue *params, int32_t param_count) {
494 	API_SCALL_VOID_PINT2(SetMousePosition);
495 }
496 
497 // void ()
Sc_RefreshMouse(const RuntimeScriptValue * params,int32_t param_count)498 RuntimeScriptValue Sc_RefreshMouse(const RuntimeScriptValue *params, int32_t param_count) {
499 	API_SCALL_VOID(RefreshMouse);
500 }
501 
502 // void ()
Sc_set_default_cursor(const RuntimeScriptValue * params,int32_t param_count)503 RuntimeScriptValue Sc_set_default_cursor(const RuntimeScriptValue *params, int32_t param_count) {
504 	API_SCALL_VOID(set_default_cursor);
505 }
506 
507 // void (int newcurs)
Sc_set_mouse_cursor(const RuntimeScriptValue * params,int32_t param_count)508 RuntimeScriptValue Sc_set_mouse_cursor(const RuntimeScriptValue *params, int32_t param_count) {
509 	API_SCALL_VOID_PINT(set_mouse_cursor);
510 }
511 
512 // int ()
Sc_GetCursorMode(const RuntimeScriptValue * params,int32_t param_count)513 RuntimeScriptValue Sc_GetCursorMode(const RuntimeScriptValue *params, int32_t param_count) {
514 	API_SCALL_INT(GetCursorMode);
515 }
516 
517 // void (int newmode)
Sc_set_cursor_mode(const RuntimeScriptValue * params,int32_t param_count)518 RuntimeScriptValue Sc_set_cursor_mode(const RuntimeScriptValue *params, int32_t param_count) {
519 	API_SCALL_VOID_PINT(set_cursor_mode);
520 }
521 
522 // int ()
Sc_Mouse_GetVisible(const RuntimeScriptValue * params,int32_t param_count)523 RuntimeScriptValue Sc_Mouse_GetVisible(const RuntimeScriptValue *params, int32_t param_count) {
524 	API_SCALL_INT(Mouse_GetVisible);
525 }
526 
527 // void (int isOn)
Sc_Mouse_SetVisible(const RuntimeScriptValue * params,int32_t param_count)528 RuntimeScriptValue Sc_Mouse_SetVisible(const RuntimeScriptValue *params, int32_t param_count) {
529 	API_SCALL_VOID_PINT(Mouse_SetVisible);
530 }
531 
Sc_Mouse_Click(const RuntimeScriptValue * params,int32_t param_count)532 RuntimeScriptValue Sc_Mouse_Click(const RuntimeScriptValue *params, int32_t param_count) {
533 	API_SCALL_VOID_PINT(PluginSimulateMouseClick);
534 }
535 
Sc_Mouse_GetControlEnabled(const RuntimeScriptValue * params,int32_t param_count)536 RuntimeScriptValue Sc_Mouse_GetControlEnabled(const RuntimeScriptValue *params, int32_t param_count) {
537 	API_SCALL_BOOL(_GP(mouse).IsControlEnabled);
538 }
539 
Sc_Mouse_SetControlEnabled(const RuntimeScriptValue * params,int32_t param_count)540 RuntimeScriptValue Sc_Mouse_SetControlEnabled(const RuntimeScriptValue *params, int32_t param_count) {
541 	API_SCALL_VOID_PBOOL(Mouse_EnableControl);
542 }
543 
544 
Sc_Mouse_GetSpeed(const RuntimeScriptValue * params,int32_t param_count)545 RuntimeScriptValue Sc_Mouse_GetSpeed(const RuntimeScriptValue *params, int32_t param_count) {
546 	API_SCALL_FLOAT(_GP(mouse).GetSpeed);
547 }
548 
Sc_Mouse_SetSpeed(const RuntimeScriptValue * params,int32_t param_count)549 RuntimeScriptValue Sc_Mouse_SetSpeed(const RuntimeScriptValue *params, int32_t param_count) {
550 	ASSERT_VARIABLE_VALUE("Mouse::Speed");
551 	_GP(mouse).SetSpeed(params[0].FValue);
552 	return RuntimeScriptValue();
553 }
554 
RegisterMouseAPI()555 void RegisterMouseAPI() {
556 	ccAddExternalStaticFunction("Mouse::ChangeModeGraphic^2", Sc_ChangeCursorGraphic);
557 	ccAddExternalStaticFunction("Mouse::ChangeModeHotspot^3", Sc_ChangeCursorHotspot);
558 	ccAddExternalStaticFunction("Mouse::ChangeModeView^2", Sc_Mouse_ChangeModeView);
559 	ccAddExternalStaticFunction("Mouse::Click^1", Sc_Mouse_Click);
560 	ccAddExternalStaticFunction("Mouse::DisableMode^1", Sc_disable_cursor_mode);
561 	ccAddExternalStaticFunction("Mouse::EnableMode^1", Sc_enable_cursor_mode);
562 	ccAddExternalStaticFunction("Mouse::GetModeGraphic^1", Sc_Mouse_GetModeGraphic);
563 	ccAddExternalStaticFunction("Mouse::IsButtonDown^1", Sc_IsButtonDown);
564 	ccAddExternalStaticFunction("Mouse::IsModeEnabled^1", Sc_IsModeEnabled);
565 	ccAddExternalStaticFunction("Mouse::SaveCursorUntilItLeaves^0", Sc_SaveCursorForLocationChange);
566 	ccAddExternalStaticFunction("Mouse::SelectNextMode^0", Sc_SetNextCursor);
567 	ccAddExternalStaticFunction("Mouse::SelectPreviousMode^0", Sc_SetPreviousCursor);
568 	ccAddExternalStaticFunction("Mouse::SetBounds^4", Sc_SetMouseBounds);
569 	ccAddExternalStaticFunction("Mouse::SetPosition^2", Sc_SetMousePosition);
570 	ccAddExternalStaticFunction("Mouse::Update^0", Sc_RefreshMouse);
571 	ccAddExternalStaticFunction("Mouse::UseDefaultGraphic^0", Sc_set_default_cursor);
572 	ccAddExternalStaticFunction("Mouse::UseModeGraphic^1", Sc_set_mouse_cursor);
573 	ccAddExternalStaticFunction("Mouse::get_ControlEnabled", Sc_Mouse_GetControlEnabled);
574 	ccAddExternalStaticFunction("Mouse::set_ControlEnabled", Sc_Mouse_SetControlEnabled);
575 	ccAddExternalStaticFunction("Mouse::get_Mode", Sc_GetCursorMode);
576 	ccAddExternalStaticFunction("Mouse::set_Mode", Sc_set_cursor_mode);
577 	ccAddExternalStaticFunction("Mouse::get_Speed", Sc_Mouse_GetSpeed);
578 	ccAddExternalStaticFunction("Mouse::set_Speed", Sc_Mouse_SetSpeed);
579 	ccAddExternalStaticFunction("Mouse::get_Visible", Sc_Mouse_GetVisible);
580 	ccAddExternalStaticFunction("Mouse::set_Visible", Sc_Mouse_SetVisible);
581 }
582 
583 } // namespace AGS3
584