wait

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.
Seraph
Posts: 68
Joined: Wed Oct 21, 2009 5:58 pm

wait

Post by Seraph »

i want to set the visibility of a node after 2 seconds, is possible? (the program mustn't be stopped, therefore no sleep... )
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Yea it's possible.

But I believe it will have to be your own construct.

There is no in-built option to delay settings with a timer.

You need to poll the time, and do it yourself when the time occurs, inside the main loop I guess.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Seraph
Posts: 68
Joined: Wed Oct 21, 2009 5:58 pm

Post by Seraph »

Code: Select all

u32 now = device->getTimer()->getTime();  
static u32 last = now;
if(now>(last+2000)){}
:? the problem is that the function is called one time... any ideas?
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Umm.. not sure if I understand, but what I meant was that you'll have to do it in a loop, such as the main application loop.
Because you don't want to sleep or stop the app, so you need to check over and over again until it is the correct time.

Code: Select all

while(device->run())
{
    //! Do something.... 
    u32 last = device->getTimer()->getTime(); 

    if( device->getTimer()->getTime() > (last+2000) )
    {
        
    }
}
But it doesn't really make sense like that because the "last" time will be reset every loop.

It sounds like you need some sort of class to update your nodes.
Like a node manager. Give it an update function which performs whatever you want (after 2 seconds).
Any nodes that you want updated after 2 seconds, just add them to the node manager list (array) and also add the time when you added them.

In the update function, check each node in the list and check if it has been waiting at least 2 seconds, then do what you want with it and remove it from the node manager class once it's been updated.

So then you just need to call the update function in the main loop.

Get it?
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Brainsaw
Posts: 1177
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

I wrote some little code for removing GUI elements after a specified time. I created a structure holding the "time to remove" and a pointer to the element to remove and add the to a list. In the main loop I iterate over this list every frame and remove elements if necessary. I am currently at work so I don't have the project here, but maybe you get the idea.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

@Brainsaw

Yep, basically exactly the same as what I said.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Brainsaw
Posts: 1177
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

OK, now I got the code. I use it to toggle elements, because some need to be hidden and others need to be shown.

Code: Select all

class GUIElementToToggle {
  public:
    GUIElementToToggle(IGUIElement *pElement, u32 iTime, bool bVisible) {
      m_pElement=pElement;
      m_iRemoveTime=iTime;
      m_bVisible=bVisible;

      printf("element \"%s\" marked for %s at %i\n",stringc(pElement->getToolTipText()).c_str(),bVisible?"showing":"hiding",iTime);
    }
    IGUIElement *m_pElement;
    u32 m_iRemoveTime;
    bool m_bVisible;
};
Then you need a list of those objects:

Code: Select all

list<GUIElementToToggle *> m_lElementsToToggle;
and then, at some point of code that is reached every frame, you put

Code: Select all

    list<GUIElementToToggle *>::Iterator it;
    for (it=m_lElementsToToggle.begin(); it!=m_lElementsToToggle.end(); it++) {
      if (m_pTimer->getTime()>(*it)->m_iRemoveTime) {
        printf("%s element \"%s\" (%i)\n",(*it)->m_bVisible?"Showing":"Hiding",stringc((*it)->m_pElement->getToolTipText()).c_str(),m_pTimer->getTime());
        IGUIElement *pElement=(*it)->m_pElement;
        pElement->setVisible((*it)->m_bVisible);
        GUIElementToToggle *pToRemove=*it;
        m_lElementsToToggle.erase(it);
        delete pToRemove;
        break;
      }
    }
One drawback: only one element is shown/hidden per frame, but in my project I haven't yet seen any problems.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

Brainsaw wrote:One drawback: only one element is shown/hidden per frame, but in my project I haven't yet seen any problems.
That's because you have a call to "break" in the loop.
Don't break, do the whole list.
Yea?

Code: Select all

list<GUIElementToToggle *>::Iterator it;
u32 curTime = m_pTimer->getTime();
for (it=m_lElementsToToggle.begin(); it!=m_lElementsToToggle.end(); it++) 
{
      if (curTime > (*it)->m_iRemoveTime) 
      {
          printf("%s element "%s" (%i)\n",(*it)->m_bVisible?"Showing":"Hiding",stringc((*it)->m_pElement->getToolTipText()).c_str(),m_pTimer->getTime());
        IGUIElement *pElement=(*it)->m_pElement;
        pElement->setVisible((*it)->m_bVisible);
        GUIElementToToggle *pToRemove=*it;
        m_lElementsToToggle.erase(it);
        delete pToRemove;
      }
}
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hi,

You can use code similar to this:

Code: Select all

bool UpdateVisibleTimer = 1;
float VisibleTime = device->getTimer()->getTime();

while(device->run())
{
    if(UpdateVisibleTimer)
    {
        VisibleTime = device->getTimer()->getTime(); // Get time.
        UpdateVisibleTimer = 0; // Disable grab new time.
    }

    if(VisibleTime + 2000 < device->getTimer()->getTime())
    {
        // ...do something, eg:
        UpdateVisibleTimer = 1; // if You want start new time counter.
        Node->setVisible(false); // Hide Your node.
    }
}
Cheers,
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Writing a bunch of code like this in the main loop is not going to scale well, and will not be reusable.

If you want to avoid these defficiencies, you will probably want to create a generic timer queue or timer wheel. All it needs to do is keep track of operations to perform, and when to perform them.

Travis
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

vitek wrote:Writing a bunch of code like this in the main loop is not going to scale well, and will not be reusable.

If you want to avoid these defficiencies, you will probably want to create a generic timer queue or timer wheel. All it needs to do is keep track of operations to perform, and when to perform them.

Travis
Author of this thread need change bisibility parameter of node after 2 seconds, and idea which I show is very good for this problem and it can be reusable many times, he can create many eg. enumerations states etc. I don't know where You see the problem ;)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

@Nadro, Your code only updates one specific node.

It's not scalable.

Brainsaw already has the answer, he just needs to remove the "break"
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

One node only in this sample, but in Your game he should have some Entity Manager or similar, so he can call:

Code: Select all

for(ini i = 0; i < EntityManager->getEntitiesCount(); ++i)
{
     EntityManager->getEntity(i)->getNode()->setVisible(false);
}
You can do in this way what You want, so as I said this code is very good for this problem ;)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Post by randomMesh »

Nadro wrote:

Code: Select all

for(ini i = 0; i < EntityManager->getEntitiesCount(); ++i)
{
     EntityManager->getEntity(i)->getNode()->setVisible(false);
}
This would set all entities invisible at once. You could of course something do like this

Code: Select all

const unsigned int entCount = EntityManager->getEntitiesCount();
for(unsigned int i = 0; i < entCount; ++i)
{
     Entity* entity = EntityManager->getEntity(i);

     if (entity->getStartTime() + 2000 >= now)
           entity->getNode()->setVisible(false);
}
but this still is very inflexible.

Like suggested before i'd go for something like this (pseudo code)

Code: Select all

enum E_WHAT_TODO
{
    EWT_INVISIBLE = 0,
};

struct S_ACTION
{
    irr::scene::ISceneNode* node;
    E_WHAT_TODO todo;
    irr::u32 when;
};

S_ACTION action;
action.node = someNode;
action.todo = EWT_INVISIBLE;
action.when = now + 2000;

ActionManager am;
am.addAction(action);

while(device->run())
{
    <compute elapsed time>

    am.update(elapsed);

    driver->beginScene();
    smgr->drawAll();
    driver->endScene();
}

void ActionManager::update(elapsed)
{
    <process all stored actions, if any>
}
This seems far more flexible to me.
Might be overkill for the original posters application, but yeah, could be doable like this. :)
"Whoops..."
B@z
Posts: 876
Joined: Thu Jan 31, 2008 5:05 pm
Location: Hungary

Post by B@z »

but why dont make an animator?
you can check how the createDeleteAnimator made, you have to do the same, just not delete, but set it invisible
Image
Image
Post Reply