Browse Source

Added new event callback love.mousemoved(x, y, xrel, yrel), where xrel and yrel are the amount of pixels moved since the last event. Added love.mouse.setRelative(bool relative) and love.mouse.isRelative. Resolves issue #470.

Enabling relative mouse mode will hide the cursor and let the system generate relative mouse move events while preventing the mouse from getting stuck at the edges of the screen (i.e. you can keep moving the mouse in one direction forever and the relative movement events will be generated accordingly.)

The reported absolute mouse position is not updated while relative mode is enabled, even while relative movement events are generated.
Alex Szpakowski 10 years ago
parent
commit
b4f2a9417a

+ 33 - 11
src/modules/event/sdl/Event.cpp

@@ -40,14 +40,14 @@ namespace sdl
 
 
 // SDL reports mouse coordinates in the window coordinate system in OS X, but
 // SDL reports mouse coordinates in the window coordinate system in OS X, but
 // we want them in pixel coordinates (may be different with high-DPI enabled.)
 // we want them in pixel coordinates (may be different with high-DPI enabled.)
-static void windowToPixelCoords(int *x, int *y)
+static void windowToPixelCoords(double *x, double *y)
 {
 {
 	window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
 	window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
 
 
 	if (window && x)
 	if (window && x)
-		*x = (int) window->toPixels(*x);
+		*x = window->toPixels(*x);
 	if (window && y)
 	if (window && y)
-		*y = (int) window->toPixels(*y);
+		*y = window->toPixels(*y);
 }
 }
 
 
 
 
@@ -112,7 +112,7 @@ Message *Event::convert(const SDL_Event &e) const
 
 
 	love::keyboard::Keyboard::Key key;
 	love::keyboard::Keyboard::Key key;
 	love::mouse::Mouse::Button button;
 	love::mouse::Mouse::Button button;
-	Variant *arg1, *arg2, *arg3;
+	Variant *arg1, *arg2, *arg3, *arg4;
 	const char *txt;
 	const char *txt;
 	std::map<SDL_Keycode, love::keyboard::Keyboard::Key>::const_iterator keyit;
 	std::map<SDL_Keycode, love::keyboard::Keyboard::Key>::const_iterator keyit;
 
 
@@ -169,15 +169,34 @@ Message *Event::convert(const SDL_Event &e) const
 		arg2->release();
 		arg2->release();
 		arg3->release();
 		arg3->release();
 		break;
 		break;
+	case SDL_MOUSEMOTION:
+		{
+			double x = (double) e.motion.x;
+			double y = (double) e.motion.y;
+			double xrel = (double) e.motion.xrel;
+			double yrel = (double) e.motion.yrel;
+			windowToPixelCoords(&x, &y);
+			windowToPixelCoords(&xrel, &yrel);
+			arg1 = new Variant(x);
+			arg2 = new Variant(y);
+			arg3 = new Variant(xrel);
+			arg4 = new Variant(yrel);
+			msg = new Message("mousemoved", arg1, arg2, arg3, arg4);
+			arg1->release();
+			arg2->release();
+			arg3->release();
+			arg4->release();
+		}
+		break;
 	case SDL_MOUSEBUTTONDOWN:
 	case SDL_MOUSEBUTTONDOWN:
 	case SDL_MOUSEBUTTONUP:
 	case SDL_MOUSEBUTTONUP:
 		if (buttons.find(e.button.button, button) && mouse::Mouse::getConstant(button, txt))
 		if (buttons.find(e.button.button, button) && mouse::Mouse::getConstant(button, txt))
 		{
 		{
-			int x = e.button.x;
-			int y = e.button.y;
+			double x = (double) e.button.x;
+			double y = (double) e.button.y;
 			windowToPixelCoords(&x, &y);
 			windowToPixelCoords(&x, &y);
-			arg1 = new Variant((double) x);
-			arg2 = new Variant((double) y);
+			arg1 = new Variant(x);
+			arg2 = new Variant(y);
 			arg3 = new Variant(txt, strlen(txt));
 			arg3 = new Variant(txt, strlen(txt));
 			msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
 			msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
 							  "mousepressed" : "mousereleased",
 							  "mousepressed" : "mousereleased",
@@ -195,11 +214,14 @@ Message *Event::convert(const SDL_Event &e) const
 				break;
 				break;
 
 
 			int mx, my;
 			int mx, my;
+			double dmx, dmy;
 			SDL_GetMouseState(&mx, &my);
 			SDL_GetMouseState(&mx, &my);
-			windowToPixelCoords(&mx, &my);
+			dmx = (double) mx;
+			dmy = (double) my;
+			windowToPixelCoords(&dmx, &dmy);
 
 
-			arg1 = new Variant((double) mx);
-			arg2 = new Variant((double) my);
+			arg1 = new Variant(dmx);
+			arg2 = new Variant(dmy);
 			arg3 = new Variant(txt, strlen(txt));
 			arg3 = new Variant(txt, strlen(txt));
 			msg = new Message("mousepressed", arg1, arg2, arg3);
 			msg = new Message("mousepressed", arg1, arg2, arg3);
 			arg1->release();
 			arg1->release();

+ 2 - 0
src/modules/mouse/Mouse.h

@@ -73,6 +73,8 @@ public:
 	virtual bool isVisible() const = 0;
 	virtual bool isVisible() const = 0;
 	virtual void setGrabbed(bool grab) = 0;
 	virtual void setGrabbed(bool grab) = 0;
 	virtual bool isGrabbed() const = 0;
 	virtual bool isGrabbed() const = 0;
+	virtual bool setRelative(bool relative) = 0;
+	virtual bool isRelative() const = 0;
 
 
 	static bool getConstant(const char *in, Button &out);
 	static bool getConstant(const char *in, Button &out);
 	static bool getConstant(Button in, const char  *&out);
 	static bool getConstant(Button in, const char  *&out);

+ 10 - 0
src/modules/mouse/sdl/Mouse.cpp

@@ -211,6 +211,16 @@ bool Mouse::isGrabbed() const
 		return false;
 		return false;
 }
 }
 
 
+bool Mouse::setRelative(bool relative)
+{
+	return SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
+}
+
+bool Mouse::isRelative() const
+{
+	return SDL_GetRelativeMouseMode() != SDL_FALSE;
+}
+
 } // sdl
 } // sdl
 } // mouse
 } // mouse
 } // love
 } // love

+ 2 - 0
src/modules/mouse/sdl/Mouse.h

@@ -64,6 +64,8 @@ public:
 	bool isVisible() const;
 	bool isVisible() const;
 	void setGrabbed(bool grab);
 	void setGrabbed(bool grab);
 	bool isGrabbed() const;
 	bool isGrabbed() const;
+	bool setRelative(bool relative);
+	bool isRelative() const;
 
 
 private:
 private:
 
 

+ 15 - 0
src/modules/mouse/wrap_Mouse.cpp

@@ -179,6 +179,19 @@ int w_isGrabbed(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_setRelative(lua_State *L)
+{
+	bool relative = luax_toboolean(L, 1);
+	luax_pushboolean(L, instance()->setRelative(relative));
+	return 1;
+}
+
+int w_isRelative(lua_State *L)
+{
+	luax_pushboolean(L, instance()->isRelative());
+	return 1;
+}
+
 // List of functions to wrap.
 // List of functions to wrap.
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
@@ -197,6 +210,8 @@ static const luaL_Reg functions[] =
 	{ "getPosition", w_getPosition },
 	{ "getPosition", w_getPosition },
 	{ "setGrabbed", w_setGrabbed },
 	{ "setGrabbed", w_setGrabbed },
 	{ "isGrabbed", w_isGrabbed },
 	{ "isGrabbed", w_isGrabbed },
+	{ "setRelative", w_setRelative },
+	{ "isRelative", w_isRelative },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

+ 2 - 0
src/modules/mouse/wrap_Mouse.h

@@ -45,6 +45,8 @@ int w_setVisible(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_setGrabbed(lua_State *L);
 int w_setGrabbed(lua_State *L);
 int w_isGrabbed(lua_State *L);
 int w_isGrabbed(lua_State *L);
+int w_setRelative(lua_State *L);
+int w_isRelative(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_mouse(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_mouse(lua_State *L);
 
 
 } // mouse
 } // mouse

+ 3 - 0
src/scripts/boot.lua

@@ -166,6 +166,9 @@ function love.createhandlers()
 		textedit = function (t,s,l)
 		textedit = function (t,s,l)
 			if love.textedit then return love.textedit(t,s,l) end
 			if love.textedit then return love.textedit(t,s,l) end
 		end,
 		end,
+		mousemoved = function (x,y,xrel,yrel)
+			if love.mousemoved then return love.mousemoved(x,y,xrel,yrel) end
+		end,
 		mousepressed = function (x,y,b)
 		mousepressed = function (x,y,b)
 			if love.mousepressed then return love.mousepressed(x,y,b) end
 			if love.mousepressed then return love.mousepressed(x,y,b) end
 		end,
 		end,

+ 8 - 0
src/scripts/boot.lua.h

@@ -285,6 +285,14 @@ const unsigned char boot_lua[] =
 	0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x28, 0x74, 0x2c, 0x73, 0x2c, 0x6c, 0x29, 0x20, 0x65, 
 	0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x28, 0x74, 0x2c, 0x73, 0x2c, 0x6c, 0x29, 0x20, 0x65, 
 	0x6e, 0x64, 0x0a,
 	0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
+	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x78, 0x72, 0x65, 0x6c, 0x2c, 0x79, 0x72, 
+	0x65, 0x6c, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 
+	0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
+	0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x78, 0x2c, 0x79, 0x2c, 
+	0x78, 0x72, 0x65, 0x6c, 0x2c, 0x79, 0x72, 0x65, 0x6c, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
 	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 
 	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 
 	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x29, 0x0a,
 	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72,