[SOLVED] Trays GUI not working properly after Scene switch Topic is solved

Problems building or running the engine, queries about how to use features etc.
Post Reply
macskay
Gnoblar
Posts: 4
Joined: Mon Jan 14, 2019 12:08 pm

[SOLVED] Trays GUI not working properly after Scene switch

Post by macskay »

Ogre Version: 1.11.5
Operating System: Windows 10
Render System: OpenGL

Hello there,
I'm trying to switch from a MainMenu Scene to an Options scene using the Trays GUI. I have set the MainMenu
Scene up the following way:

Code: Select all

void MainMenu::setup()
{
	Ogre::SceneManager* sceneManager = game.getRoot()->createSceneManager();

	sceneManager->addRenderQueueListener(game.getOverlaySystem());
	Ogre::RTShader::ShaderGenerator* shadergen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
	shadergen->addSceneManager(sceneManager);

	trayManager = std::make_shared<OgreBites::TrayManager>("MenuTrayManager", game.getRenderWindow(), this);

	Ogre::Light* light = sceneManager->createLight("MenuLight");
	Ogre::SceneNode* lightNode = sceneManager->getRootSceneNode()->createChildSceneNode();
	lightNode->setPosition(0, 10, 15);
	lightNode->attachObject(light);

	Ogre::SceneNode* camNode = sceneManager->getRootSceneNode()->createChildSceneNode();
	camNode->setPosition(0, 0, 15);
	camNode->lookAt(Ogre::Vector3(0, 0, -1), Ogre::Node::TS_PARENT);

	Ogre::Camera* cam = sceneManager->createCamera("MenuCam");
	cam->setNearClipDistance(5); 	
	cam->setAutoAspectRatio(true);
	camNode->attachObject(cam);

	trayManager->showCursor();
	trayManager->createButton(OgreBites::TL_CENTER, "NewGame", "New Game", 0.2f*game.getRenderWindow()->getWidth());
	trayManager->createButton(OgreBites::TL_CENTER, "Options", "Options", 0.2f*game.getRenderWindow()->getWidth());
	trayManager->createButton(OgreBites::TL_CENTER, "Exit", "Exit Game");
	trayManager->showBackdrop("Background");
	trayManager->showAll();

	game.getRenderWindow()->addViewport(cam)->setOverlaysEnabled(true);
	game.addInputListener(trayManager.get());
}
This works quite fine and I got the Buttons working. When clicking Options the following Exit function of my MainMenu Scene is triggered:

Code: Select all

void MainMenu::exit()
{
	game.getRenderWindow()->removeAllViewports();
	game.getRenderWindow()->removeAllListeners();
	std::map<Ogre::String, Ogre::SceneManager*> sceneManagers = game.getRoot()->getSceneManagers();
	for (std::map<Ogre::String, Ogre::SceneManager*>::iterator it = sceneManagers.begin(); it != sceneManagers.end(); ++it)
	{
		Ogre::RTShader::ShaderGenerator::getSingletonPtr()->removeSceneManager(it->second);
		it->second->clearScene();
		game.getRoot()->destroySceneManager(it->second);
	}
	game.removeInputListener(trayManager.get());
}
and a similar setup function as above (but only with one simple button) of the Options Scene is called.
The scene switches and is set up, that is I can see the new scene, however I can not press the button in this scene. See the following setup fuinction of the Options Scene:

Code: Select all

void Options::setup()
{
	Ogre::SceneManager* sceneManager = game.getRoot()->createSceneManager();

	sceneManager->addRenderQueueListener(game.getOverlaySystem());
	Ogre::RTShader::ShaderGenerator* shadergen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
	shadergen->addSceneManager(sceneManager);

	trayManager = std::make_shared<OgreBites::TrayManager>("OptionsTrayManager", game.getRenderWindow(), this);

	Ogre::Light* light = sceneManager->createLight("OptionsLight");
	Ogre::SceneNode* lightNode = sceneManager->getRootSceneNode()->createChildSceneNode();
	lightNode->setPosition(0, 10, 15);
	lightNode->attachObject(light);

	Ogre::SceneNode* camNode = sceneManager->getRootSceneNode()->createChildSceneNode();
	camNode->setPosition(0, 0, 15);
	camNode->lookAt(Ogre::Vector3(0, 0, -1), Ogre::Node::TS_PARENT);

	Ogre::Camera* cam = sceneManager->createCamera("OptionsCam");
	cam->setNearClipDistance(5); 	
	cam->setAutoAspectRatio(true);
	camNode->attachObject(cam);

	trayManager->createButton(OgreBites::TL_CENTER, "ex", "RenderSystem");
	trayManager->showBackdrop("Background");
	trayManager->showCursor();

	game.getRenderWindow()->addViewport(cam)->setOverlaysEnabled(true);
	game.addInputListener(trayManager.get());
}
For completion purposes I'll also post how I change the Scene:

First this is the function called when pressing the Options button:

Code: Select all

void MainMenu::buttonHit(OgreBites::Button* button)
{
	if (button->getName() == "Exit")
		game.exit();
	else if (button->getName() == "NewGame")
		game.queueChangeOfState(GameScene::GS_NEWGAME);
	else if (button->getName() == "Options")
		game.queueChangeOfState(GameScene::GS_OPTIONS);
}
And this is the queueChangeOfState function within my game singleton, the class where my gameloop lives.

Code: Select all

void Game::queueChangeOfState(GameScene newScene)
{
	stateToChangeTo = newScene;
}
The gameloop does the following. update and render call the current game state's update and render functions.
All gamestates, such as Options and MainMenu are descendant to an astract GameState class. So what I have is a shared pointer to a GameState variable.:

Code: Select all

void MyGame::mainloop()
{
	while (isRunning())
	{
		update(deltaTime);
		render(deltaTime);
		getRoot()->renderOneFrame();

		if (getStateToChangeTo() != GameScene::GS_NONE)
		{
			changeToState(getStateToChangeTo());
			resetStateToChangeTo();
		}
	}
}
So when stateToChangeTo is something other than GS_NONE it changes to that gameState by calling the cahngeToState function:

Code: Select all

void MyGame::changeToState(GameScene newScene)
{
	if (getGameState())
	{
		getGameState()->exit();
		getGameState().reset();
	}

	setGameState(getGameStatePointer(newScene));
	getGameState()->setup();
}
Eventuall if there was gameState already active, which holds true when coming from another gameState, this gameState will exit() and then the pointer will be reset. After that it will set the new gameState to the one
chosen and call its setup method.

So the odd thing is, that the switching seems to work (more or less correctly) as I can see the new scene. However the input seems to be off, as for example the Trays Cursor is only shown when moving the mouse, and the hovering effect, when mousing over the Button in the scene only shows when moving the mouse. I thought it might have something to do with the old state still interefering somehow, so I tried to clear all sceneManagers from the Ogre::Root, but that didn't seem to work. I figure there is something not reset, which should've been.

What I tested is, when directly launching into the Options Menu upon game start the input is recognized correctly, so there must be something off with the change of scenes, but I can't seem to figure out what it is. I'll append a webm of the behaviour to futher illustrate my point. Any help is appreciated.

https://imgur.com/a/JuxduKW
Last edited by macskay on Mon Jan 21, 2019 8:35 pm, edited 1 time in total.
User avatar
EricB
Bronze Sponsor
Bronze Sponsor
Posts: 360
Joined: Fri Apr 09, 2010 5:28 am
Location: Florida
x 213
Contact:

Re: Trays GUI not working properly after Scene switch

Post by EricB »

I am not too familiar with trays, but I would stick print messages in just about every function and see what is being called when. It sounds like you have something over riding something else, and your code ends up in the wrong place. For example, clicking the mouse is going to your menu buttons function instead of the options buttons function. Or maybe TrayManager not being cleared properly or something.

Beyond that sort of guerilla debugging, I am not seeing anything sticking out odd in your code. Someone else with a bit more tray experience will have to chime in.
Image
macskay
Gnoblar
Posts: 4
Joined: Mon Jan 14, 2019 12:08 pm

Re: Trays GUI not working properly after Scene switch

Post by macskay »

Phew, I got it working after some time debugging. All hail breakpoints. :mrgreen:

I found that I had this little nasty thing hanging around

Code: Select all

void Game::resetStateToChangeTo()
{
	stateToChangeTo == GameScene::GS_NONE;
}
So I didn't actually reset my stateToChangeTo the following always executed within my mainloop

Code: Select all

if (getStateToChangeTo() != GameScene::GS_NONE)
{
    changeToState(getStateToChangeTo());
    resetStateToChangeTo();
}
This forced the program to re-"setup" my scene on every update(). Actually changing the stateToChangeTo to set the variable to GS_NONE instead of doing a boolean comparison fixed everything. Always the small things, right?

Thanks for the help anyway!
Post Reply