[SOLVE]Problem with listening event

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
ayboangelus
Posts: 9
Joined: Thu Dec 11, 2008 12:02 am

[SOLVE]Problem with listening event

Post by ayboangelus »

Hi all, i have a problem, when my listening event is running, it crash.

I have this code:

Code: Select all

char character::draw()
{
    cEventReceiver eventReceiver;
    device->setEventReceiver(&eventReceiver);
    return 0;
}
and my listening event:

Code: Select all

#ifndef EVENEMENT_H_INCLUDED
#define EVENEMENT_H_INCLUDED

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

enum
{
        GUI_ID_VAL1,
        GUI_ID_VAL2,
        GUI_ID_VAL3
};

class cEventReceiver : public IEventReceiver
{
public:

	cEventReceiver() {}

        virtual bool OnEvent(const SEvent& event)
        {
                if (event.EventType == EET_GUI_EVENT)
                {
                        s32 id = event.GUIEvent.Caller->getID();
                        IGUIEnvironment* env = device->getGUIEnvironment();

                        if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
                        {
                                if (id == GUI_ID_VAL1 || id == GUI_ID_VAL2 || id == GUI_ID_VAL3)
                                { IDChar = IDperso; }
                        }
                }
                return false;
        }

private:
        int IDChar,IDperso;
        IrrlichtDevice *device;

};
#endif // EVENEMENT_H_INCLUDED
Thanks for your help.[/quote]
Last edited by ayboangelus on Sat Jan 03, 2009 11:31 pm, edited 1 time in total.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: Problem with listening event

Post by Seven »

I will take a crack at this one....

Code: Select all

char character::draw()
{
    cEventReceiver eventReceiver;
    device->setEventReceiver(&eventReceiver);
    return 0;
}
it appears that you are creating an eventreceiver every time you draw the character? so if you are running 30 frames per second, you are creating an event receiver and setting it to the device 30 times per second? That doesnt seem right :)


Code: Select all

class cEventReceiver : public IEventReceiver
{
public:

	cEventReceiver() {}

        virtual bool OnEvent(const SEvent& event)
        {
                if (event.EventType == EET_GUI_EVENT)
                {
                        s32 id = event.GUIEvent.Caller->getID();
                        IGUIEnvironment* env = device->getGUIEnvironment();

                        if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
                        {
                                if (id == GUI_ID_VAL1 || id == GUI_ID_VAL2 || id == GUI_ID_VAL3)
                                { IDChar = IDperso; }
                        }
                }
                return false;
        }

private:
        int IDChar,IDperso;
        IrrlichtDevice *device;

};
where do you set device to something valid?


I highly recommend that you get one of the tutorials off of the website to see how all of this is done.
ayboangelus
Posts: 9
Joined: Thu Dec 11, 2008 12:02 am

Post by ayboangelus »

I have try it, and get another but no succeed that's why i post there.

Need help for understand better.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

post all of your main.cpp file code for us to look at
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

He's already showed you the problem. You just didn't notice it...

Code: Select all

char character::draw() 
{ 
    cEventReceiver eventReceiver; 
    device->setEventReceiver(&eventReceiver); 
    return 0; 
} 
The problem is that he passes a pointer to his event receiver to the device, and then his event receiver goes out of scope and is destroyed. The device then attempts to send events to this defunct event receiver. Boom.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Post by Seven »

and he does it in the draw function every frame. he also tries to use an undefined private device inside the receiver. in the end, it looks like the entire code is a malfunction so again I must suggest that he go back to compiling the tutorials and learning from them.
ayboangelus
Posts: 9
Joined: Thu Dec 11, 2008 12:02 am

Post by ayboangelus »

i succed to make an exemple like tuto but when i put it in my code, it crash :(

if you want that's is the new code:

character.h

Code: Select all

#ifndef CHARACTER_H
#define CHARACTER_H
#include "Login.h"
#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;

struct SAppContext
{
        IrrlichtDevice *device;
};

// Define some values that we'll use to identify individual GUI controls.
enum
{
        GUI_ID_VAL1,
        GUI_ID_VAL2,
        GUI_ID_VAL3
};
class MyEventReceiver : public IEventReceiver
{
public:
        MyEventReceiver(SAppContext & context) : Context(context) { }

        virtual bool OnEvent(const SEvent& event)
        {
                if (event.EventType == EET_GUI_EVENT)
                {
                        s32 id = event.GUIEvent.Caller->getID();
                        IGUIEnvironment* env = Context.device->getGUIEnvironment();

                        if(event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
                        {
                                if (id == GUI_ID_VAL1 || id == GUI_ID_VAL2 || id == GUI_ID_VAL3)
                                {
                                IDChar = 11;
                                stringw temp = L" ";
                                temp += IDChar;
                                env->addStaticText(temp.c_str(),rect<s32>(380,700,670,750),false);
                                }
                                        return true;
                        }
                        return false;
                }

                return false;
        }

private:
        int IDChar, IDperso;
        SAppContext & Context;
};

class character
{
    public:
        character(IrrlichtDevice* Device);
        ~character();
        char draw();
        int IDChar, IDperso;
        int fonction() { return IDChar; }

    private:
        IrrlichtDevice* device;
        IVideoDriver *driver;
        ISceneManager *scenegraph;
        IGUIEnvironment *env;
        IGUIImage *img;
        IAnimatedMesh* modele;
        IAnimatedMeshSceneNode* Nmodele;
        IAnimatedMesh* modele2;
        IAnimatedMeshSceneNode* Nmodele2;
        IGUIEnvironment *gui;
};
#endif
character.cpp

Code: Select all

#include "character.h"
#include <iostream>
#include <fstream>

character::character(IrrlichtDevice* Device)
{
    device = Device;
    driver = device->getVideoDriver ();
    scenegraph = device->getSceneManager ();
    gui = scenegraph->getGUIEnvironment();
    env = device->getGUIEnvironment();

	scenegraph->addCameraSceneNode (0, core::vector3df (0,0,0), core::vector3df (50,0,0));

    IGUIImage *img = env->addImage(rect<s32>(0,0,1024,768));
    img->setImage(driver->getTexture("media/cadre.jpg"));

    int IDperso = 11;

    // Perso 1
    modele2 = scenegraph->getMesh("persos/11.x");
    Nmodele2 = scenegraph->addAnimatedMeshSceneNode(modele2);
    Nmodele2->setPosition(core::vector3df(150,-30,70));
    Nmodele2->setRotation(core::vector3df(0,80,0));
    Nmodele2->setMaterialFlag(video::EMF_LIGHTING, false);
    Nmodele2->setFrameLoop(0,0);
    Nmodele2->setMaterialTexture( 0, driver->getTexture("persos/dwarf.jpg") );

    // Perso 2
    modele = scenegraph->getMesh("persos/test/player.x");
    Nmodele = scenegraph->addAnimatedMeshSceneNode(modele);
    Nmodele->setPosition(core::vector3df(10.5,0.5,-0.5));
    Nmodele->setRotation(core::vector3df(0,-90,0));
    Nmodele->setMaterialFlag(video::EMF_LIGHTING, false);

    env->addButton(core::rect<s32>(190,600,330,650), 0, GUI_ID_VAL1, L"Selection");
    env->addButton(core::rect<s32>(460,600,600,650), 0, GUI_ID_VAL2, L"Selection");
    env->addButton(core::rect<s32>(740,600,880,650), 0, GUI_ID_VAL3, L"Selection");
    IGUIStaticText* choixperso = env->addStaticText(L"Choix du personnage",rect<s32>(380,700,670,750),false);

    SAppContext context;
    context.device = device;
    MyEventReceiver receiver(context);
    device->setEventReceiver(&receiver);
}
character::~character()
{
    scenegraph->clear();
    env->clear();
    gui->clear();
    driver->removeAllTextures();
}
char character::draw()
{
}

Thanks for your help. It do like i want on a classic program but when i want introduce it in mine, big crash without compiler error.

help me please :(
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Your code here has the same exact problem that it did before...

Code: Select all

character::character(IrrlichtDevice* Device) 
{
    // ...

    SAppContext context; 
    context.device = device; 
    MyEventReceiver receiver(context); 
    device->setEventReceiver(&receiver);
}
The MyEventReceiver object is created on the stack. When the function returns, the object is destroyed automatically. Since you've given the device a pointer to the event receiver, the device will send messages to the event receiver, but by the time an event is processed by the device, the receiver has already been destroyed.

You either need to declare the event receiver at a scope where it will not be deallocated until after the event receiver is dropped, or you need to allocate it on the heap.

Another thing to consider. You've put this code into the character constructor. If you create the receiver on the heap and you create multiple characters, you will leak the previous receiver.

Travis
ayboangelus
Posts: 9
Joined: Thu Dec 11, 2008 12:02 am

Post by ayboangelus »

Problem solve, have modify party of code and work well now, thanks for all
Post Reply