Problem with delegate in MyGui

daro2189

16-04-2012 08:56:05

Hello. I try connect mygui (3.2) with ogre (1.7.4).
I'm using basic ogre framework and after integration mygui window display good just like button, but when i want to add delegate to button
after click nothing happens. (to integrate I'm using http://www.ogre3d.org/tikiwiki/MyGUI+quickstart) or somethimes is crash when use different delegate.

Code looks almost the same as in basic ogre framework, I just add code from tutorial.

After add this line nothing happens: (of course I change class pointer and method)
// set callback
button->eventMouseButtonClick += MyGUI::newDelegate(CLASS_POINTER, &CLASS_NAME::METHOD_NAME);


and after add this line is crash:
// set callback to button pressed
button->eventMouseButtonPressed += MyGUI::newDelegate(CLASS_POINTER, &CLASS_NAME::METHOD_NAME);


Could somebody help me?

Altren

16-04-2012 09:21:10

Do you actually using same method, or two different methods? Because it won't even compile, since this delegates require different arguments.
Could you try to debug your application and see where exactly it crashes? There are no easy ways to make delegate crash without raising assert with clear description what's wrong.

daro2189

16-04-2012 10:02:00

Unfortunatelly I don't have code right now, but in evening I will add code.
I think it crashed after you clicked to button and in delegate loop.

I using same and two different.

daro2189

19-04-2012 22:08:46

Sorry for my late.
Error is in this function:

void operator()( MYGUI_PARAMS )
{
ListDelegateIterator iter = mListDelegates.begin();
while (iter != mListDelegates.end())
{
if (nullptr == (*iter))
{
iter = mListDelegates.erase(iter);
}
else
{
(*iter)->invoke( MYGUI_ARGS ); //in this line my application crash
++iter;
}
}
}

function is from file: MyGUI_DelegateImplement.h

And this is communicate:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

Can someone help??

Transporter

15-05-2012 09:12:56

This is a tricky bug. There should be error handling invoid operator()( MYGUI_PARAMS )
{
ListDelegateIterator iter = mListDelegates.begin();
while (iter != mListDelegates.end())
{
if (nullptr == (*iter))
{
iter = mListDelegates.erase(iter);
}
else
{
(*iter)->invoke( MYGUI_ARGS );
++iter;
}
}
}


I can reproduce it using Advanced Ogre Framework.

void MenuState::enter()
{
OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering MenuState...");

m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "MenuSceneMgr");
m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));

m_pCamera = m_pSceneMgr->createCamera("MenuCam");
m_pCamera->setPosition(Vector3(0, 25, -50));
m_pCamera->lookAt(Vector3(0, 0, 0));
m_pCamera->setNearClipDistance(1);

m_pCamera->setAspectRatio(Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) /
Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));

OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);

m_pPlatform = new MyGUI::OgrePlatform();
m_pPlatform->initialise(OgreFramework::getSingletonPtr()->m_pRenderWnd, m_pSceneMgr, "MyGUI");
m_pGUI = new MyGUI::Gui();
m_pGUI->initialise();

MyGUI::ButtonPtr button1 = m_pGUI->createWidget<MyGUI::Button>("Button", 10, 10, 200, 30, MyGUI::Align::Center, "Main", "EnterBtn");
button1->setCaption("Run");
button1->eventMouseButtonClick += MyGUI::newDelegate(this, &MenuState::buttonHit);

MyGUI::ButtonPtr button2 = m_pGUI->createWidget<MyGUI::Button>("Button", 10, button1->getBottom() + 10, 200, 30, MyGUI::Align::Center, "Main", "ExitBtn");
button2->setCaption("Close");
button2->eventMouseButtonClick += MyGUI::newDelegate(this, &MenuState::buttonHit);

createScene();
}

void MenuState::exit()
{
OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving MenuState...");

m_pGUI->shutdown();
delete m_pGUI;
m_pGUI = NULL;
m_pPlatform->shutdown();
delete m_pPlatform;
m_pPlatform = NULL;

m_pSceneMgr->destroyCamera(m_pCamera);
if(m_pSceneMgr)
OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
}

void MenuState::update(Ogre::Real timeSinceLastFrame)
{
m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;

if(m_bQuit == true)
{
shutdown();
return;
}
}

void MenuState::buttonHit(MyGUI::WidgetPtr button)
{
if(button->getName() == "ExitBtn")
m_bQuit = true;
else if(button->getName() == "EnterBtn")
changeAppState(findByName("SimulationState"));
}


This error is appearing running a direct command to destroy the GUI. That means changeAppState(findByName("SimulationState"));is a bad idea in a delegate function. The function destroys the list in background which is the reason for that exception. You can use any other command to destroy the GUI in this function to create the exception. If you use a small workaround to handle the button events in update function, it's working:

void MenuState::enter()
{
OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering MenuState...");

m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "MenuSceneMgr");
m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));

m_pCamera = m_pSceneMgr->createCamera("MenuCam");
m_pCamera->setPosition(Vector3(0, 25, -50));
m_pCamera->lookAt(Vector3(0, 0, 0));
m_pCamera->setNearClipDistance(1);

m_pCamera->setAspectRatio(Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) /
Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));

OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);

m_pPlatform = new MyGUI::OgrePlatform();
m_pPlatform->initialise(OgreFramework::getSingletonPtr()->m_pRenderWnd, m_pSceneMgr, "MyGUI");
m_pGUI = new MyGUI::Gui();
m_pGUI->initialise();

MyGUI::ButtonPtr button1 = m_pGUI->createWidget<MyGUI::Button>("Button", 10, 10, 200, 30, MyGUI::Align::Center, "Main", "EnterBtn");
button1->setCaption("Run");
button1->eventMouseButtonClick += MyGUI::newDelegate(this, &MenuState::buttonHit);

MyGUI::ButtonPtr button2 = m_pGUI->createWidget<MyGUI::Button>("Button", 10, button1->getBottom() + 10, 200, 30, MyGUI::Align::Center, "Main", "ExitBtn");
button2->setCaption("Close");
button2->eventMouseButtonClick += MyGUI::newDelegate(this, &MenuState::buttonHit);

createScene();
}

void MenuState::exit()
{
OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving MenuState...");

m_pGUI->shutdown();
delete m_pGUI;
m_pGUI = NULL;
m_pPlatform->shutdown();
delete m_pPlatform;
m_pPlatform = NULL;

m_pSceneMgr->destroyCamera(m_pCamera);
if(m_pSceneMgr)
OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
}

void MenuState::update(Ogre::Real timeSinceLastFrame)
{
m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;

if(m_strButtonHit.size() > 1)
{
if(m_strButtonHit == "ExitBtn")
{
shutdown();
return;
}
else if(m_strButtonHit == "EnterBtn")
changeAppState(findByName("SimulationState"));
m_strButtonHit.clear();
}
}


void MenuState::buttonHit(MyGUI::WidgetPtr button)
{
m_strButtonHit = button->getName();
}

Remove m_bQuit and add m_strButtonHit.