Remap GUI object hitboxes to new viewport?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
dart_theg
Posts: 68
Joined: Sun Dec 29, 2024 3:13 am

Remap GUI object hitboxes to new viewport?

Post by dart_theg »

I wanted to make my irrlicht game use a letterboxed viewport for resizing, but I don't know how to remap the GUI button hitboxes to match. Visually they appear the same, but their actual hitboxes are wrong. (Button placed top left of screen and having the viewport moved to the right will have them not matched up)
CuteAlien
Admin
Posts: 9971
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Remap GUI object hitboxes to new viewport?

Post by CuteAlien »

Hm, I don't have a test right now, so not sure which steps exactly are necessary for this case. But what I do in my project is first to call IVideoDriver::OnResize with the new dimension (not sure if that is really needed or just some artifact from the past, but it shouldn't hurt). I do that before calling setViewPort.
And to move the gui I set the root element to the new area, like guiEnv->getRootGUIElement()->setRelativePosition(area);

That should be enough for UI. But there is also still a bug in Irrlicht which I didn't dare fixing yet (complicated stuff and mixed with some other viewport troubles on Android...). And that's when you use the collision system. It only cares about width/height of the viewport - and ignores the offset to the top-left.
So currently I use workaround functions there:

Code: Select all

irr::core::position2di getScreenCoordinatesFrom3DPositionFixed(irr::scene::ISceneManager * sceneManager, const irr::core::vector3df& pos, irr::scene::ICameraSceneNode * camera, bool useViewport)
{
	irr::scene::ISceneCollisionManager * collMan = sceneManager->getSceneCollisionManager();
	irr::core::position2di result = collMan->getScreenCoordinatesFrom3DPosition(pos, camera, useViewport);
	if ( useViewport )
	{
		// TODO: WORKAROUND - Irrlicht only uses width/height from viewport but ignores upper-left corner. 
		result += sceneManager->getVideoDriver()->getViewPort().UpperLeftCorner;
	}
	return result;
}

irr::core::line3df getRayFromScreenCoordinatesFixed(irr::scene::ISceneManager * sceneManager, const irr::core::position2di& cursorPos, const irr::scene::ICameraSceneNode* camera)
{
	// TODO: WORKAROUND - Irrlicht only uses width/height from viewport but ignores if it's not starting at upper-left corner. But fixing might break other stuff - will have to work on this at some point.
	const irr::core::position2di cursorPosWithViewport(cursorPos - sceneManager->getVideoDriver()->getViewPort().UpperLeftCorner);
	return sceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(cursorPosWithViewport, camera);
}

irr::scene::ISceneNode* getSceneNodeFromScreenCoordinatesBBFixed(irr::scene::ISceneManager * sceneManager, const irr::core::position2di& pos, irr::s32 idBitMask, bool noDebugObjects, irr::scene::ISceneNode* root)
{
	const irr::core::line3df ln = getRayFromScreenCoordinatesFixed(sceneManager, pos);

	if ( ln.start == ln.end )
		return 0;

	return sceneManager->getSceneCollisionManager()->getSceneNodeFromRayBB(ln, idBitMask, noDebugObjects, root);
}
Note that the workarounds might breaks some day if I do the real fix (but unlikely to happen anytime soon)
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