Page 1 of 1

How to stop the IrrlichtDevice properly?

Posted: Tue Mar 27, 2007 2:51 pm
by ayman
Hi.

I want to stop the IrrlichtDevice, so that device->run() will result to false.
And I want to do this as a reaction of a key event.

EDIT: I tried the following inside the Example 04 (Movement).

I tried:

Code: Select all

...
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
          ...
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_Q: 
				device->closeDevice();   // <-- this is the line
				break;
...
... but this caused a crash.

Naturally device->drop(); resulted in an other crash. That was no surprise.

So, what's the trick?

Thanks in front.
Ayman

P.S.
I did search the forum, but didn't find an answer.

Posted: Tue Mar 27, 2007 4:22 pm
by BlindSide
You did not find an answer because closeDevice() should not cause it to crash. Something else is probably wrong, what does your application contain?

Posted: Tue Mar 27, 2007 7:01 pm
by hybrid
The problem is that device is an unvalid pointer.

Posted: Tue Mar 27, 2007 7:10 pm
by ayman
Thanks for telling me that, BlindSide.
But the problem remains the same. I just tried it with the original Movement Example 04.
I added only the three lines as mentioned above and I get a crash every time I hit "Q"-Key.

Code: Select all

...
		if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&&
			!event.KeyInput.PressedDown)
		{
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_Q: 				// added these three lines
				device->closeDevice();   // causes a crash. why?
				return true; 				// return false; crashes just the same. What does it do anyhow?

			case KEY_KEY_W:
			case KEY_KEY_S:
				{
					core::vector3df v = node->getPosition();
					v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
					node->setPosition(v);
				}
				return true;
			}
		}
...
Maybe it has something to do with my Dev-Cpp settings? But I can compile and run every example without any problems (using Irrlicht 1.3 with OpenGL or any Software Renderer; DX doesn't work with Dev-Cpp).
Also if I terminate with Alt+F4, every thing is ok.

Would anybody care trying to add these three lines to example-04 and see himself?

Thanks in front.
Ayman

Posted: Tue Mar 27, 2007 7:15 pm
by ayman
hybrid wrote:The problem is that device is an unvalid pointer.
Yes, that's what I thought too.

But it shouldn't, should it? Cause device is global and get's initialized right in the beginning. Same is with "node", that is used without a problem four lines below.

So if device can not be used here, how should I handle a termination key stroke?

Regards
Ayman

Posted: Tue Mar 27, 2007 7:22 pm
by Acki
Maybe the problem is within your main loop...
please show it to us, too... ;)

Posted: Tue Mar 27, 2007 7:29 pm
by vitek
Works fine for me. You are probably making the classic mistake of naming a global variable the same as a local variable, like this...

Code: Select all

IrrlichtDevice* device = 0;

int main()
{
  IrrlichtDevice* device = createDevice(...);

  //...
If you do this, the global device will not get initialized. To avoid problems like this, most people use special notation to indicate the scope of the variable. As an example, you could prepend a g_ to your global variable names. Any variable that is global would have a g_ at the beginning, and anything that is local would not.

Also, this has been mentioned many times before, but you should avoid globals if you can. The following would be a better way to do the same thing without using a global device pointer.

Code: Select all

class MyEventReceiver : public IEventReceiver
{
public:
  MyEventReceiver()
    : Device(0)
  {
  }

  virtual bool OnEvent(SEvent event)
  {
    if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
        event.KeyInput.PressedDown)
    {
      switch(event.KeyInput.Key)
      {
        case KEY_KEY_Q:
          if (Device)
            Device->closeDevice();
          Device = 0;
          return true;

        default:
          return false;
      }
    }

    return false;
  }

  void setDevice(IrrlichtDevice* device)
  {
    if (Device)
      Device->setEventReceiver(0);

    Device = device;

    if (Device)
      Device->setEventReceiver(this);
  }

private:
  IrrlichtDevice* Device;
};

// in main...
  IrrlichtDevice* device =
    createDevice(driverType, core::dimension2d<s32>(1024, 768));

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

  MyEventReceiver receiver;
  receiver.setDevice(device);
Travis

Posted: Tue Mar 27, 2007 7:58 pm
by ayman
Thanks vitek/Travis!
That's it indeed. It works now :D

But I still have one related question:
Why is the value of "node" available in receiver.OnEvent() then?

I am still talking about the original examples/04.Movement.

"node" is initialized just the same as device:

Code: Select all

scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;
When the receiver is created ...

Code: Select all

	MyEventReceiver receiver;
... neither "node" is passed as an argument nor it is set to a local "node" variable by a setNode() method.

Shouldn't the same problem apply to node as it applies to device?

Best Regards
Ayman

Posted: Tue Mar 27, 2007 8:41 pm
by hybrid
node is set inside main(), but it does not declare a new variable. It uses the global variable for storing the value. That's no clean code, but it keeps the tutorials small (and the tutorials are for showing Irrlicht features, not for teaching good C++ style).