Select toolbar button or mesh from map

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.
Post Reply
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Select toolbar button or mesh from map

Post by tBane »

Hi!
I created a Toolbar, and map in my program.
I would like select button of Toolbar or mesh of map, but select both. How repair it ?

https://www.youtube.com/watch?v=zXnCM_n0RzI

Code: Select all

class MyEventReceiver : public IEventReceiver
{
public:
	bool KeyIsDown[KEY_KEY_CODES_COUNT];

	MyEventReceiver();
	virtual bool OnEvent(const SEvent&);
	virtual bool IsKeyDown(EKEY_CODE);
	bool OnMenuItemSelected(IGUIContextMenu* menu);
};

Code: Select all

bool MyEventReceiver::OnEvent(const SEvent& event)
{
	if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
	{
		switch (event.MouseInput.Event)
		{
		case EMIE_LMOUSE_PRESSED_DOWN:
			mousePress = true;
			break;

		case EMIE_LMOUSE_LEFT_UP:
			mousePress = 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;
		}
	}

	// Remember whether each key is down or up
	if (event.EventType == irr::EET_KEY_INPUT_EVENT)
	{
		KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
		return true;
	}

	if (event.EventType == EET_GUI_EVENT)
	{
		switch (event.GUIEvent.EventType)
		{
		// ...
		
		case EGET_BUTTON_CLICKED:
		{
			s32 id = event.GUIEvent.Caller->getID();

			if (id == BAR_BUTTON_WATER)
			{
				brushTerrain = terrainType::water;
				std::cout << "setted a water to paint" << std::endl;
			}
				
			if (id == BAR_BUTTON_BEACH)
			{
				brushTerrain = terrainType::beach;
				std::cout << "setted a beach to paint" << std::endl;
			}

			if (id == BAR_BUTTON_GRASS)
			{
				brushTerrain = terrainType::grass;
				std::cout << "setted a grass to paint" << std::endl;
			}

			if (id == BAR_BUTTON_ROCKS)
			{
				brushTerrain = terrainType::rocks;
				std::cout << "setted a rocks to paint" << std::endl;
			}

			if (id == BAR_BUTTON_HIGHLANDS)
			{
				brushTerrain = terrainType::highlands;
				std::cout << "setted a highlands to paint" << std::endl;
			}

			if (id == BAR_BUTTON_DARKNESS)
			{
				brushTerrain = terrainType::darkness;
				std::cout << "setted a darkness to paint" << std::endl;
			}

			if (id == BAR_BUTTON_SWAMP)
			{
				brushTerrain = terrainType::swamp;
				std::cout << "setted a swamp to paint" << std::endl;
			}

			if (id == BAR_BUTTON_DESERT)
			{
				brushTerrain = terrainType::desert;
				std::cout << "setted a desert to paint" << std::endl;
			}

			if (id == BAR_BUTTON_INCREASE)
			{
				if (brushSize < maxBrushSize)
					brushSize++;
			}

			if (id == BAR_BUTTON_DECREASE)
			{
				if (brushSize > 0)
					brushSize--;
			}
		}
		break;

		default:
			break;
		}
	}

	return false;
}

Code: Select all

void highlightingtHexTiles()
{
	// GET THE MOUSE POSITION
	position2d < s32 > mousePos = device->getCursorControl()->getPosition();

	// CALCULATE THE RAY TO COLLISION
	core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(mousePos, cam);

	// COLLISION
	core::vector3df intersection;
	core::triangle3df hitTriangle;
	scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

	scene::ISceneNode* selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay(ray, intersection, hitTriangle);

	// CLEAR OLD HIGHLIGHTED HEX TILES
	for (auto& t : highlightedHexTiles)
		t->meshBuffer->Material.MaterialType = EMT_SOLID;

	if (selectedSceneNode != nullptr)
	{
		vector2di tilePos = globalToHex(selectedSceneNode->getPosition().X, selectedSceneNode->getPosition().Z);
		
		highlightedHexTiles.clear();
		getNeighbours(highlightedHexTiles, hexMap->getHexTile(tilePos.X, tilePos.Y), brushSize);
		
		for (auto& t : highlightedHexTiles)
			t->meshBuffer->Material.MaterialType = EMT_TRANSPARENT_ADD_COLOR;
	}
}

void editHexTiles()
{
	for (auto& t : highlightedHexTiles)
		t->setTerrainType(brushTerrain);
}

Code: Select all

// ...
// UPDATE

// CAMERA POSITIONING
cam->setPosition(vector3df(cam_x, cam_y, cam_z));
cam->setTarget(vector3df(cam_x, 30, cam_z+50));

highlightingtHexTiles();

if(mousePress)
	editHexTiles();
// ...
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Select toolbar button or mesh from map

Post by CuteAlien »

You can use either IGUIEnvironment::getHovered or IGUIEnvironmnet::getRootGUIElement()->getElementFromPoint(mousePos) to find the element under the mouse (getHovered is cheaper, but is 1 frame behind).
Then check what gui element you receive. When no other gui-element is below muse it should return IGUIEnvironmnet::getRootGUIElement().
If so you can use the click - otherwise ignore it.
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
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Re: Select toolbar button or mesh from map

Post by tBane »

i dont know how use it ..

Code: Select all

highlightingtHexTiles();
if ( IGUIEnvironment::getRootGUIElement()->getElementFromPoint(mousePos) == nullptr && mousePress)
{
	editHexTiles();
}
this not works
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Re: Select toolbar button or mesh from map

Post by tBane »

Success.
I used

Code: Select all

// ...
highlightingtHexTiles();
if ( !terrainBar->isPointInside(mousePos) && mousePress)
{
	editHexTiles();
}
// ...
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Select toolbar button or mesh from map

Post by CuteAlien »

Yeah, doesn't return nullptr, but getRootGUIElement() (which is basically the GUIEnvironment itself).
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
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Re: Select toolbar button or mesh from map

Post by tBane »

Hello.
I'm trying to rebuild the GUIisHover() function, which tells whether a GUI element has been selected, into a more substantive form, i.e. each button in the event will set the value of the GUIisSelected variable to inform the program about that the GUI element has been selected. However, despite my attempts, the code does not execute as expected. I don't know where I went wrong.


function GUIisHover():

Code: Select all

bool GUIisHover()
{

	if (menu->isPointInside(mousePos))
		return true;

	if (worldMenu->isPointInside(mousePos))
		return true;

	if (helpMenu->isPointInside(mousePos))
		return true;

	if (terrainBar->isPointInside(mousePos))
		return true;

	if (openDialog != nullptr)
		return true;

	return false;
}
Code buttons:

Code: Select all

case EGET_BUTTON_CLICKED:
{
	GUIisSelected = true;
	s32 buttonID = event.GUIEvent.Caller->getID();
	
	switch (buttonID)
	{
		case BUTTON_WATER:
			brushTerrain = terrainType::water;
			std::cout << "setted a water to paint" << std::endl;
			GUIisSelected = true;
			break;

		case BUTTON_BEACH:
			brushTerrain = terrainType::beach;
			std::cout << "setted a beach to paint" << std::endl;
			GUIisSelected = true;
			break;
// ... etc
main loop of program

Code: Select all

while (device->run())
{
	if (device->isWindowActive())
	{
		// MOUSE POSITION
		mousePos = device->getCursorControl()->getPosition();

		// EVENTS
		if (receiver.IsKeyDown(irr::KEY_ESCAPE))	// if press ESCAPE then exit
		{
			device->drop();
			return 0;
		}

		if (receiver.IsKeyDown(irr::KEY_KEY_A) || receiver.IsKeyDown(irr::KEY_LEFT))	cam_x -= 1.0f;
		if (receiver.IsKeyDown(irr::KEY_KEY_D) || receiver.IsKeyDown(irr::KEY_RIGHT))	cam_x += 1.0f;
		if (receiver.IsKeyDown(irr::KEY_KEY_W) || receiver.IsKeyDown(irr::KEY_UP))		cam_z += 1.0f;
		if (receiver.IsKeyDown(irr::KEY_KEY_S) || receiver.IsKeyDown(irr::KEY_DOWN))	cam_z -= 1.0f;
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// UPDATE


		// CAMERA POSITIONING
		cam->setPosition(vector3df(cam_x, cam_y, cam_z));
		cam->setTarget(vector3df(cam_x, 30, cam_z+50));

		highlightHexTiles();

		if( !GUIisSelected && mousePress)	// EDIT TILES
			editHexTiles();


		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// RENDER
		driver->beginScene(true, true, SColor(clear_a, clear_r, clear_g, clear_b));														// clear screen
			smgr->drawAll();																												// render scene
			driver->draw2DImage(TWTexture, position2d<s32>(0, screenHeight - 128 - 20), rect<s32>(0, 0, 128, 128));							// render TW Logo
			boldFont->draw(L"TW World Editor v0.5", recti(20, screenHeight - 20, 100, screenHeight), SColor(255, 128, 48, 48), true, true);	// render text on bottom
			GUI->drawAll();																													// render GUI
			position2d<s32> m = device->getCursorControl()->getPosition();																	// render cursor
		driver->endScene();																												// render submit

		// FPS
		int currentFPS = driver->getFPS();
		core::stringw str = L"FPS: ";
		str += currentFPS;
		device->setWindowCaption(str.c_str());

		GUIisSelected = false;

	}
	else
		device->yield();	// if window is inactive not use CPU

}
Last edited by tBane on Thu Feb 29, 2024 7:18 pm, edited 1 time in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Select toolbar button or mesh from map

Post by CuteAlien »

Problem is likely that EGET_BUTTON_CLICKED is send on EMIE_LMOUSE_LEFT_UP (and not mouse-down). By that time you have already clicked your editHexTiles().

I'd really recommend to use (guiEnv->getHovered() == guiEnv->getRootGUIElement()) to check if no other gui element was clicked. Then you don't have to do that one-by-one but every gui-element will make this false (and if you want to allow some - then add those, they are usually more rare).
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
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Re: Select toolbar button or mesh from map

Post by tBane »

when i use if(GUI->getHovered() == GUI->getRootGUIElement()), then window collisioning with cursor and no cant do anything.

I don't understand why the GUIisHover() function works and the GUIisSelected bool doesn't work.

Code: Select all

if (!GUIisHover())
{
	highlightHexTiles();
	if(mousePress)
		editHexTiles();
}

Code: Select all

if( !GUIisSelected )
{
    highlightHexTiles();
    if( mousePress )
         editHexTiles();
   
}
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Select toolbar button or mesh from map

Post by CuteAlien »

GUIisSelected only updates on mouse-up so it's set when you *release* the mouse button. But you want to know if it's pressed. Your mousePress is true *before* GUIisSelected is set. GUIisHover on the other hand checks where the mouse is.

So left-mouse-click-down: GUIisSelected is false. mousePress is true.
Then left-mouse-clickup: GUIisSelected is true. mousePress if false.
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
tBane
Posts: 33
Joined: Wed Feb 21, 2024 2:25 pm
Location: Poland

Re: Select toolbar button or mesh from map

Post by tBane »

how to check in event the GUI has hover ?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Select toolbar button or mesh from map

Post by CuteAlien »

Why not use your GUIisHover function when it works? Those checks are cheap, so speed shouldn't be a worry.
You can pass the gui environment to your event-receiver then you can use every function from it in there.
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