Joystick Event Handler

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

Uh - probably, sorry, I'm not familiar with the code right now. But please write a complete patch. Test it. Document the function. And check if other platforms are involved. If they are then maybe mention in the function documentation that the function might not work on all platforms (or even better make it work on all platforms, but generally fine to have one for a start and just comment it). Maybe also think a bit about if there are any problems when you close & restart the device.

You already seem to have a use-case for testing. I'd have to write one first myself (and totally not too lazy to dust of my joypad...).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
netpipe
Posts: 669
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Joystick Event Handler

Post by netpipe »

i only used the joystick demo from 1.8.4

on line 190 // if(joystickInfo.size() > 0)
// {
comment out that and run it with no joysticks attached to see what i noticed the cursor gets wild data and goes off screen.

line 214 add printf("%f",moveHorizontal); helps debug the numbers

seems like its just extra overhead after checking if any are attached to keep the joystick system active(probably to detect newly attached gamepads). i will try and get a patch soon.

if a controller got detached it would make weird numbers and read as connected still i think but could be wrong.(update it seems to show it as connected still) the numbers only read 0 though and replugging it does not reconnect it.

after looking closer it seems to do it without even activating the joysticks those random values should just be 0
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

Are you sure it's the joystick that gets wild? If no joystick is connected that arrow thingy in that example follows the mouse-pointer. That one tripped me up last time I checked that example and I spend a while debugging until I realized what was going on. I think I even changed it somewhat in trunk (still follows mouse, but now only when it moves I think).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
netpipe
Posts: 669
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Joystick Event Handler

Post by netpipe »

yes i get what i thought were stray floats with no joystick connected but the arrow flys off in same direction every time

-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-0.6662190.882839-


in the joystick polling code maybe it can check if the joystick is still connected/reconnected.

joystickInfo.size() is not always easily available and passing the array pointer seems to be tricky when registering other camera nodes
Last edited by netpipe on Tue Jun 21, 2022 1:38 pm, edited 4 times in total.
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
netpipe
Posts: 669
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Joystick Event Handler

Post by netpipe »

Code: Select all

/** Example 019 Mouse and Joystick

This tutorial builds on example 04.Movement which showed how to
handle keyboard events in Irrlicht.  Here we'll handle mouse events
and joystick events, if you have a joystick connected and a device
that supports joysticks.  These are currently Windows, Linux and SDL
devices.
*/

#ifdef _MSC_VER
// We'll define this to stop MSVC complaining about sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif

#include <irrlicht.h>
#include "driverChoice.h"

using namespace irr;

/*
Just as we did in example 04.Movement, we'll store the latest state of the
mouse and the first joystick, updating them as we receive events.
*/
class MyEventReceiver : public IEventReceiver
{
public:
	// We'll create a struct to record info on the mouse state
	struct SMouseState
	{
		core::position2di Position;
		bool LeftButtonDown;
		SMouseState() : LeftButtonDown(false) { }
	} MouseState;

	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember the mouse state
		if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
		{
			switch(event.MouseInput.Event)
			{
			case EMIE_LMOUSE_PRESSED_DOWN:
				MouseState.LeftButtonDown = true;
				break;

			case EMIE_LMOUSE_LEFT_UP:
				MouseState.LeftButtonDown = false;
				break;

			case EMIE_MOUSE_MOVED:
				MouseState.Position.X = event.MouseInput.X;
				MouseState.Position.Y = event.MouseInput.Y;
				break;

			default:
				// We won't use the wheel
				break;
			}
		}

		// The state of each connected joystick is sent to us
		// once every run() of the Irrlicht device.  Store the
		// state of the first joystick, ignoring other joysticks.
		// This is currently only supported on Windows and Linux.
		if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT
			&& event.JoystickEvent.Joystick == 0)
		{
			JoystickState = event.JoystickEvent;
		}

		return false;
	}

	const SEvent::SJoystickEvent & GetJoystickState(void) const
	{
		return JoystickState;
	}

	const SMouseState & GetMouseState(void) const
	{
		return MouseState;
	}


	MyEventReceiver()
	{
	}

private:
	SEvent::SJoystickEvent JoystickState;
};


/*
The event receiver for keeping the pressed keys is ready, the actual responses
will be made inside the render loop, right before drawing the scene. So lets
just create an irr::IrrlichtDevice and the scene node we want to move. We also
create some other additional scene nodes, to show that there are also some
different possibilities to move and animate scene nodes.
*/
int main()
{
	// ask user for driver
	video::E_DRIVER_TYPE driverType=driverChoiceConsole();
	if (driverType==video::EDT_COUNT)
		return 1;

	// create device
	MyEventReceiver receiver;

	IrrlichtDevice* device = createDevice(driverType,
			core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);

	if (device == 0)
		return 1; // could not create selected driver.


	core::array<SJoystickInfo> joystickInfo;
//	if(device->activateJoysticks(joystickInfo))
//	{
//		std::cout << "Joystick support is enabled and " << joystickInfo.size() << " joystick(s) are present." << std::endl;
//
//		for(u32 joystick = 0; joystick < joystickInfo.size(); ++joystick)
//		{
//			std::cout << "Joystick " << joystick << ":" << std::endl;
//			std::cout << "\tName: '" << joystickInfo[joystick].Name.c_str() << "'" << std::endl;
//			std::cout << "\tAxes: " << joystickInfo[joystick].Axes << std::endl;
//			std::cout << "\tButtons: " << joystickInfo[joystick].Buttons << std::endl;
//
//			std::cout << "\tHat is: ";
//
//			switch(joystickInfo[joystick].PovHat)
//			{
//			case SJoystickInfo::POV_HAT_PRESENT:
//				std::cout << "present" << std::endl;
//				break;
//
//			case SJoystickInfo::POV_HAT_ABSENT:
//				std::cout << "absent" << std::endl;
//				break;
//
//			case SJoystickInfo::POV_HAT_UNKNOWN:
//			default:
//				std::cout << "unknown" << std::endl;
//				break;
//			}
//		}
//	}
//	else
//	{
//		std::cout << "Joystick support is not enabled." << std::endl;
//	}

	core::stringw tmp = L"Irrlicht Joystick Example (";
	tmp += joystickInfo.size();
	tmp += " joysticks)";
	device->setWindowCaption(tmp.c_str());

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	/*
	We'll create an arrow mesh and move it around either with the joystick axis/hat,
	or make it follow the mouse pointer. */
	scene::ISceneNode * node = smgr->addMeshSceneNode(
		smgr->addArrowMesh( "Arrow",
				video::SColor(255, 255, 0, 0),
				video::SColor(255, 0, 255, 0),
				16,16,
				2.f, 1.3f,
				0.1f, 0.6f
				)
		);
	node->setMaterialFlag(video::EMF_LIGHTING, false);

	scene::ICameraSceneNode * camera = smgr->addCameraSceneNode();
	camera->setPosition(core::vector3df(0, 0, -10));

	// As in example 04, we'll use framerate independent movement.
	u32 then = device->getTimer()->getTime();
	const f32 MOVEMENT_SPEED = 5.f;

	while(device->run())
	{
		// Work out a frame delta time.
		const u32 now = device->getTimer()->getTime();
		const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
		then = now;

		bool movedWithJoystick = false;
		core::vector3df nodePosition = node->getPosition();

//		if(joystickInfo.size() > 0)
//		{
			f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right
			f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up.

			const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState();

			// We receive the full analog range of the axes, and so have to implement our
			// own dead zone.  This is an empirical value, since some joysticks have more
			// jitter or creep around the center point than others.  We'll use 5% of the
			// range as the dead zone, but generally you would want to give the user the
			// option to change this.
			const f32 DEAD_ZONE = 0.05f;

			moveHorizontal =
				(f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_X] / 32767.f;
			if(fabs(moveHorizontal) < DEAD_ZONE)
				moveHorizontal = 0.f;

			printf("%f",moveHorizontal);

			moveVertical =
				(f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_Y] / -32767.f;
			if(fabs(moveVertical) < DEAD_ZONE)
				moveVertical = 0.f;

			printf("%f",moveVertical);

//			 POV hat info is only currently supported on Windows, but the value is
//			 guaranteed to be 65535 if it's not supported, so we can check its range.
			const u16 povDegrees = joystickData.POV / 100;
			if(povDegrees < 360)
			{
				if(povDegrees > 0 && povDegrees < 180)
					moveHorizontal = 1.f;
				else if(povDegrees > 180)
					moveHorizontal = -1.f;

				if(povDegrees > 90 && povDegrees < 270)
					moveVertical = -1.f;
				else if(povDegrees > 270 || povDegrees < 90)
					moveVertical = +1.f;
			}

			if(!core::equals(moveHorizontal, 0.f) || !core::equals(moveVertical, 0.f))
			{
				nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal;
				nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical;
				movedWithJoystick = true;
			}
//		}

		// If the arrow node isn't being moved with the joystick, then have it follow the mouse cursor.
		if(!movedWithJoystick)
		{
			// Create a ray through the mouse cursor.
			core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
				receiver.GetMouseState().Position, camera);

			// And intersect the ray with a plane around the node facing towards the camera.
			core::plane3df plane(nodePosition, core::vector3df(0, 0, -1));
			core::vector3df mousePosition;
			if(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition))
			{
				// We now have a mouse position in 3d space; move towards it.
				core::vector3df toMousePosition(mousePosition - nodePosition);
				const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime;

				if(toMousePosition.getLength() <= availableMovement)
					nodePosition = mousePosition; // Jump to the final position
				else
					nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it
			}
		}

		node->setPosition(nodePosition);

		// Turn lighting on and off depending on whether the left mouse button is down.
		node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown);

		driver->beginScene(true, true, video::SColor(255,113,113,133));
		smgr->drawAll(); // draw the 3d scene
		driver->endScene();
	}

	/*
	In the end, delete the Irrlicht device.
	*/
	device->drop();

	return 0;
}

/*
**/
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

You did see what I wrote? That the arrow flys toward mouse pointer when there is no joystick?
In 1.8 it did that as soon as joystick was not moved for a few seconds I think (slightly better in trunk).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
netpipe
Posts: 669
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Joystick Event Handler

Post by netpipe »

yes, in the example i posted it will not follow mouse at all. the joystick axis values are random each time but stay fixed for some reason instead of only reading 0's to make it more compatible.

we can get rid of the check in the main loop // if(joystickInfo.size() > 0) because there is already one inside irrlicht to poll the joystick if any of them are active.
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

Ah OK. I wondered why you had posted the example, didn't realize it was modified. I'll take a look tomorrow if I can reproduce it (I'm not on Windows right now).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
netpipe
Posts: 669
Joined: Fri Jun 06, 2008 12:50 pm
Location: Edmonton, Alberta, Canada
Contact:

Re: Joystick Event Handler

Post by netpipe »

Amiga still ? it was for linux but the way patches are made it could be for both.
Live long and phosphor!
-- https://github.com/netpipe/Luna Game Engine Status 95%
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

Hehe, nope, never been on Amiga. Was on Linux (my after-work system). I just thought your joystick trouble was on Windows. It's on Linux?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Joystick Event Handler

Post by CuteAlien »

If you remove the "if(joystickInfo.size() > 0)" it won't work. All you have then is an uninitialized JoystickState variable which is never updated because no events arrive. Unfortunately event variables are not initialized (that would need another constructor which takes in the event-type, I could add that, but I can't remove the old one without breaking all code out there). Thought even if initialized it shouldn't be just set to 0 as the POV should be set to 65535.
So you could do something like:

Code: Select all

	MyEventReceiver()
	{
		memset(&JoystickState, 0, sizeof JoystickState);
		JoystickState.POV = 65535;
	}
But still - don't remove the size check.

edit: A deactivateJoysticks patch probably still makes sense.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply