Page 1 of 1

Creating an inherited class from ITimer?

Posted: Sun Feb 15, 2015 7:31 pm
by pandoragami
Hello all,

This question is more a programming question regarding virtuals and inheriting from the ITimer class. Basically I already know that I can use the device to get the Itimer (e.g. device->getTimer()) but what I would like to understand is how to inherit from the ITimer class directly like this.

Code: Select all

class timing: virtual public ITimer
{
    private:
 
    public:
 
    timing(){}
    ~timing(){}
    virtual ITimer* getTimer() = 0;
};
I did look at the code for the IrrlichtDevice.h to figure out how the device retrieves the timer but I get the error for the following code?

Code: Select all

 
C:\irrlicht_timer.cpp||In function 'int main()':|
C:\irrlicht_timer.cpp|92|error: cannot declare variable 'time' to be of abstract type 'timing'|
C:\irrlicht_timer.cpp|74|note:   because the following virtual functions are pure within 'timing':|
C:\irrlicht-1.7.2\include\ITimer.h|26|note:     virtual irr::u32 irr::ITimer::getRealTime() const|
C:\irrlicht-1.7.2\include\ITimer.h|33|note:     virtual irr::u32 irr::ITimer::getTime() const|
C:\irrlicht-1.7.2\include\ITimer.h|36|note:     virtual void irr::ITimer::setTime(irr::u32)|
C:\irrlicht-1.7.2\include\ITimer.h|42|note:     virtual void irr::ITimer::stop()|
C:\irrlicht-1.7.2\include\ITimer.h|48|note:     virtual void irr::ITimer::start()|
C:\irrlicht-1.7.2\include\ITimer.h|53|note:     virtual void irr::ITimer::setSpeed(irr::f32)|
C:\irrlicht-1.7.2\include\ITimer.h|58|note:     virtual irr::f32 irr::ITimer::getSpeed() const|
C:\irrlicht-1.7.2\include\ITimer.h|61|note:     virtual bool irr::ITimer::isStopped() const|
C:\irrlicht-1.7.2\include\ITimer.h|67|note:     virtual void irr::ITimer::tick()|
C:\irrlicht_timer.cpp|81|note:  virtual irr::ITimer* timing::getTimer()|

Here's the code

Code: Select all

 
#include <irrlicht.h>
#include <iostream>
 
using namespace irr;
 
class MyEventReceiver : public IEventReceiver
{
public:
 
    struct SMouseState
    {
        core::position2di Position;
        bool LeftButtonDown;
        SMouseState() : LeftButtonDown(false) { }
    } MouseState;
 
    virtual bool OnEvent(const SEvent& event)
    {
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
        if(event.EventType == EET_MOUSE_INPUT_EVENT)
        {
            switch(event.MouseInput.Event)
            {
            case EMIE_LMOUSE_PRESSED_DOWN:
                MouseState.LeftButtonDown = true;
                break;
 
            case EMIE_LMOUSE_LEFT_UP:
                MouseState.LeftButtonDown = false;
                break;
 
            case EMIE_MOUSE_MOVED:
                MouseState.Position.X = event.MouseInput.X;
                MouseState.Position.Y = event.MouseInput.Y;
                break;
 
            default:
 
                break;
            }
        }
 
        return false;
    }
 
    // This is used to check whether a key is being held down
    virtual bool IsKeyDown(EKEY_CODE keyCode) const
    {
        return KeyIsDown[keyCode];
    }
 
    const SMouseState & GetMouseState(void) const
    {
        return MouseState;
    }
 
    MyEventReceiver()
    {
        for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
            KeyIsDown[i] = false;
    }
 
private:
    // We use this array to store the current state of each key
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
 
class timing: virtual public ITimer
{
    private:
 
    public:
 
    timing(){}
    ~timing(){}
    virtual ITimer* getTimer() = 0;
};
 
 
MyEventReceiver receiver;
IrrlichtDevice* device = 0;
const int SCRX = 640;
const int SCRY = 480;
 
int main()
{
    timing time;
 
    device = createDevice( irr::video::EDT_OPENGL, core::dimension2d<u32>( SCRX, SCRY), 16, false, false, false, &receiver);
 
    if (device == 0)
        return 1;
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    gui::ICursorControl * cursor = device->getCursorControl();
 
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
 
    cursor->setVisible(false);
 
    int lastFPS = -1;
 
    while(device->run())
    if (device->isWindowActive())
    {
        driver->beginScene(true, true, video::SColor( 255, 0, 0, 0));
        smgr->drawAll();
        driver->endScene();
 
        int fps = driver->getFPS();
 
        if (lastFPS != fps)
        {
            core::stringw str = L"Irrlicht Text Node [";
            str += driver->getName();
            str += "] FPS:";
            str += fps;
 
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
        }
    }
 
    device->drop();
 
    return 0;
}

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 1:38 pm
by CuteAlien
Well, it's pretty much exactly what the error message says. It cannot cannot declare the variable 'time' of the class 'timing' because that is an abstract type. And timing is an abstract because a lot of virtual fuctions in timing are pure. It then goes on to list all function for which that is the case.
A function being pure means it looks like:

Code: Select all

 
class X
{
    virtual void MyFunction() = 0; // the = 0 makes it pure.
};
 
The idea behind pure functions is that it tells anyone who derives from such a class that this is pure interface and has no implementation. Which means you have to add an implementation.

So much for the theory. But you likely don't need that. You can't pass a timer back to Irrlicht so deriving from that is probably useless. If you need a timer then either write your own class - or use the a pointer to the Irrlicht timer in your class (here's an example where I do that: http://www.michaelzeilfelder.de/irrlicht.htm#Timer).

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 2:46 pm
by pandoragami
CuteAlien wrote:
So much for the theory. But you likely don't need that. You can't pass a timer back to Irrlicht so deriving from that is probably useless. If you need a timer then either write your own class - or use the a pointer to the Irrlicht timer in your class (here's an example where I do that: http://www.michaelzeilfelder.de/irrlicht.htm#Timer).

Looking at that code for the timer it looks just like the ITimer class inside Irrlicht; I guess I'm supposed to initialize it with the ITimer here

Code: Select all

Timer(irr::ITimer * irrlichtTimer_, bool startRunning_=false);  
By passing the returned pointer from the device?

Code: Select all

device->getTimer();

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 5:01 pm
by CuteAlien
Yeah, it looks similar to ITimer as it's basically a wrapper around it. And yes - that's the pointer you pass.

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 5:17 pm
by pandoragami
CuteAlien wrote:Yeah, it looks similar to ITimer as it's basically a wrapper around it. And yes - that's the pointer you pass.
But isn't that the same instance of the ITimer which implies that you would still have one timer for each Irrlicht device?

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 5:36 pm
by CuteAlien
I only use it to get the time. Time is time... short of creating another universe I can't do much about that :-) The difference it that this one can be started/stopped independent of each other.

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 8:45 pm
by pandoragami
CuteAlien wrote:I only use it to get the time. Time is time... short of creating another universe I can't do much about that :-) The difference it that this one can be started/stopped independent of each other.
But if you have only a single instance of ITimer and used one of the methods in the Timer wrapper you can only change that single ITimer object. Using start/stop would still only access the instance of that single ITimer object even if you have a hundred different wrappers e.g.

Code: Select all

Timer* instances[100];
Wouldn't an array of Timers only end up having the same functionality as a single device->getTimer pointer?

Re: Creating an inherited class from ITimer?

Posted: Mon Feb 16, 2015 9:43 pm
by CuteAlien
It's about virtual timers. The absolute time for all is the same, but this is not what this is about. This kind of time only updates on tick() (unless it's paused) - and it updates by a certain speed. The real time (aka ITimer) is only needed to compare to the time since the last tick() call. Take a look at the code - it's not that large.