Page 1 of 2

Chaining Animations?

Posted: Tue Aug 23, 2011 3:48 pm
by thoma91
Hi! Is there a way to chain animations in Irrlicht?

With this code, the node walks until it takes a hit, then comes the second animation, and when it finishes, the node just stands still:

Code: Select all

 
node->setLoopMode(true);
node->setFrameLoop(0,24);
if(...){
node->setLoopMode(false);
node->setFrameLoop(272,288);}
 
With this code, when I want the node to return to walking after the hit, the hit taking animation does not happen, it walks all the time.

Code: Select all

 
node->setLoopMode(true);
node->setFrameLoop(0,24);
if(...){
node->setLoopMode(false);
node->setFrameLoop(272,288);
node->setLoopMode(true);
node->setFrameLoop(0,24);
}
 
How could this be solved?

Re: Chaining Animations?

Posted: Tue Aug 23, 2011 4:29 pm
by serengeor
if(...){
node->setLoopMode(false);
node->setFrameLoop(272,288);
node->setLoopMode(true);
node->setFrameLoop(0,24);
}
the animations don't go into some sort of queue AFAIK, so if you set it to one and at the same time change to other it would use the last one only, you have to think of something better. Maybe a callback for when animation ends, if irrlicht supports them.

Re: Chaining Animations?

Posted: Tue Aug 23, 2011 5:25 pm
by thoma91
Sorry, it did not work. The result is just the same.
Any other ideas?

Re: Chaining Animations?

Posted: Tue Aug 23, 2011 6:00 pm
by serengeor
thoma91 wrote:Sorry, it did not work. The result is just the same.
Any other ideas?
What did not work? I just quoted your own code and explained why it shouldn't work.
You either have to set up some callbacks somehow or check every frame if it finished it's animation and start the other one.

Re: Chaining Animations?

Posted: Tue Aug 23, 2011 6:10 pm
by thoma91
Sorry, I was inaccurate. I meant I tried to use a callback function, but it did not work.

Re: Chaining Animations?

Posted: Tue Aug 23, 2011 6:48 pm
by serengeor
thoma91 wrote:Sorry, I was inaccurate. I meant I tried to use a callback function, but it did not work.
Well, you should post it here how you tried and say where it fails.

Re: Chaining Animations?

Posted: Wed Aug 24, 2011 7:37 am
by thoma91
Here's the code:
(I also set an intermediate function, for rotating the node a bit between the two moves. unfortunately this didn't change nothing, the first animation does not happen.)

Code: Select all

 
...
void enemymove2()
{
        printf("enemymove2 started\n");
        node->setLoopMode(true);
        int i;
        for (i = 0; i < 25; ++i){
            node->setFrameLoop(i,i);
            printf("Frame %d drawn\n",i);
            }
}
 
void enemymove()
{
        printf("enemymove started\n");
        node->setRotation(core::vector3df(0,-96,0));
        printf("rotation ok\n");
        enemymove2();
}
 
 
void loading(void incomingFuncName())
{
     printf("loading started\n");
     incomingFuncName();
}
 
 
bool shoot()
{
...
 
if(...){
        node->setLoopMode(false);
        int i;
        for (i = 272; i < 17; ++i){
            node->setFrameLoop(i,i);
            printf("Frame %d drawn\n",i);
        }
 
        printf("functioncall\n");
        loading(enemymove);
}
 
And this is what i get on the console:

Code: Select all

 
functioncall
loading started
enemymove started
rotation ok
enemymove2 started
Frame 0 drawn
...
Frame 24 drawn
 
So anyone got an idea how should I change animations in Irrlicht?

Re: Chaining Animations?

Posted: Wed Aug 24, 2011 8:15 am
by teto
I think there will be a more efficient way to deal with animations in 1.8 (you need a lot of user code to get something nice right now).

Did you look at:
virtual void irr::scene::IAnimatedMeshSceneNode::setAnimationEndCallback ( IAnimationEndCallBack * callback = 0 )

It keeps getting called until a new animation is set.

Re: Chaining Animations?

Posted: Wed Aug 24, 2011 9:16 am
by serengeor
thoma91 wrote:Here's the code:
(I also set an intermediate function, for rotating the node a bit between the two moves. unfortunately this didn't change nothing, the first animation does not happen.)

Code: Select all

 
...
void enemymove2()
{
        printf("enemymove2 started\n");
        node->setLoopMode(true);
        int i;
        for (i = 0; i < 25; ++i){
            node->setFrameLoop(i,i);
            printf("Frame %d drawn\n",i);
            }
}
 
void enemymove()
{
        printf("enemymove started\n");
        node->setRotation(core::vector3df(0,-96,0));
        printf("rotation ok\n");
        enemymove2();
}
 
 
void loading(void incomingFuncName())
{
     printf("loading started\n");
     incomingFuncName();
}
 
 
bool shoot()
{
...
 
if(...){
        node->setLoopMode(false);
        int i;
        for (i = 272; i < 17; ++i){
            node->setFrameLoop(i,i);
            printf("Frame %d drawn\n",i);
        }
 
        printf("functioncall\n");
        loading(enemymove);
}
 
And this is what i get on the console:

Code: Select all

 
functioncall
loading started
enemymove started
rotation ok
enemymove2 started
Frame 0 drawn
...
Frame 24 drawn
 
So anyone got an idea how should I change animations in Irrlicht?
You just rewrote the same thing that you did before just with functions :?

When I was talking about callbacks I meant something like this: http://irrlicht.sourceforge.net/docu/cl ... e48393f1bd

Re: Chaining Animations?

Posted: Wed Aug 24, 2011 9:21 am
by Ravi08
Hi, not sure if this will help but i used it in the past, i used it for something else but could work for you.

Code: Select all

int newAnim = 0;
int currentAnim = 0;
 
if(newAnim != currentAnim)
{
      currentAnim = newAnim;
      if(currentAnim == 1)
      {
           node->setFrameLoop(0,0);
           node->setAnimationSpeed(0);
      }
      if(currentAnim == 2)
      {
           node->setFrameLoop(1,40);
           node->setAnimationSpeed(10);
      }
      if(currentAnim == 3)
      {
           node->setFrameLoop(43,93);
           node->setAnimationSpeed(10);
      }
}
You have to select when and where you change the value of newAnim, ie change it to 1 when standing, 2 for walk and 3 for shot.

Re: Chaining Animations?

Posted: Fri Aug 26, 2011 2:53 pm
by thoma91
Hi!
Thanks for the answers, but none of them works for me.
Maybe it's my fault, perhaps you could try your recommendations at home if you've got time.
(setAnimationEndCallback(0); does nothing for me)

I could only achieve this:

Code: Select all

 
int currentAnim = 0;
...
void enemyReact()
{
if(currentAnim == 0){
        // hit-taking animation
        node->setLoopMode(false);
        node->setFrameLoop(272,288);
        currentAnim++;
}
else if(currentAnim == 1){
        // walking animation
        node->setLoopMode(true);
        node->setFrameLoop(0,24);
        currentAnim=0;
}
}
 
The enemyReact function is called when the enemy takes hit.
For the first hit, the hit-taking animation runs, then the enemy stops.
For the second hit, it just starts walking again.
The third is like the first,etc,until it dies. The dying animation works well.

But this isn't the right way, because I want the walking anim right after one hit-taking anim.

But ANYHOW I call the walking animation after the other animation, the first one gets ignored. It's kinda frustrating..
Isn't here someone who experienced or dealt with this before?

Re: Chaining Animations?

Posted: Fri Aug 26, 2011 5:18 pm
by Ravi08
Hi, sorry im no expert on this but il try, first the code i posted works for me. What i use it for is to do walking animation and saluting animation. (1 = standing, 2 = walk, 3 = salute) Now the way i use it is like this: when player presses forward newAnim becomes 2, when player needs to salute newAnim is 3 and other times newAnim is 1, might not be best way but its simple.

If you posted the whole file i wouldn't mind having a closer look but thats up to you.

Lastly i believe "setAnimationEndCallback" requires the node to be in non looped mode, not 100% check the doc.

Re: Chaining Animations?

Posted: Fri Aug 26, 2011 10:23 pm
by serengeor
Ravi08 wrote:Hi, sorry im no expert on this but il try, first the code i posted works for me. What i use it for is to do walking animation and saluting animation. (1 = standing, 2 = walk, 3 = salute) Now the way i use it is like this: when player presses forward newAnim becomes 2, when player needs to salute newAnim is 3 and other times newAnim is 1, might not be best way but its simple.
He has a problem with playing one animation after another, not identifying/naming the animations.
thoma91 wrote: Maybe it's my fault, perhaps you could try your recommendations at home if you've got time.
(setAnimationEndCallback(0); does nothing for me)
I could but I won't, you need to read some c++ tutorials and learn how to read API doc if you're serious about this. I can't help someone who doesn't want to help himself :wink:

Re: Chaining Animations?

Posted: Fri Aug 26, 2011 11:59 pm
by sudi
Here is a simple example on how you could do it

CAnimationController.h

Code: Select all

 
#ifndef CANIMATIONCONTROLLER_H
#define CANIMATIONCONTROLLER_H
 
#include <IAnimatedMeshSceneNode.h>
#include <irrMap.h>
 
class CAnimationController : public irr::scene::IAnimationEndCallBack
{
public:
    struct Animation
    {
        Animation()
        {
            name = "";
            start = 0;
            end = 1;
            looping = false;
        }
        Animation(const irr::c8* n, const irr::u32& s, const irr::u32& e, const bool& loop)
        {
            name = n;
            start = s;
            end = e;
            looping = loop;
        }
        Animation(const Animation& other)
        {
            name = other.name;
            start = other.start;
            end = other.end;
            looping = other.looping;
        }
 
        irr::core::stringc name;
        irr::u32 start;
        irr::u32 end;
        bool looping;
    };
 
    CAnimationController();
    virtual ~CAnimationController();
 
    void setAnimatedMeshNode(irr::scene::IAnimatedMeshSceneNode* node);
 
    void addAnimation(const irr::c8* name, const irr::u32& start, const irr::u32& end, const bool& loop = false);
 
    void playAnimation(const irr::c8* name);
 
    void OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode* node);
protected:
    void setAnimation(const Animation& anim);
 
    irr::core::map<irr::core::stringc, Animation> animations;
    Animation currentAnimation;
    Animation nextAnimation;
    irr::scene::IAnimatedMeshSceneNode*animatedNnode;
    bool animationRunning;
    bool hasNext;
};
 
#endif // CANIMATIONCONTROLLER_H
 
CAnimationController.cpp

Code: Select all

#include "CAnimationController.h"
 
CAnimationController::CAnimationController()
{
    animatedNnode = 0;
    animationRunning = false;
    hasNext = false;
}
 
CAnimationController::~CAnimationController()
{
    if (animatedNnode)
    {
        animatedNnode->setAnimationEndCallback(0);
        animatedNnode->drop();
    }
    animatedNnode = 0;
}
 
void CAnimationController::OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode *node)
{
    animationRunning = false;
    if ((hasNext || currentAnimation.looping) && animatedNnode)
    {
        if (hasNext)
            setAnimation(nextAnimation);
        else
            setAnimation(currentAnimation);
        hasNext = false;
    }
}
 
void CAnimationController::addAnimation(const irr::c8 *name, const irr::u32 &start, const irr::u32 &end, const bool& loop)
{
    animations[name] = Animation(name, start, end, loop);
}
 
void CAnimationController::setAnimatedMeshNode(irr::scene::IAnimatedMeshSceneNode *node)
{
    if (animatedNnode == node)
        return;
 
    if (animatedNnode)
    {
        animatedNnode->setAnimationEndCallback(0);
        animatedNnode->drop();
    }
 
    animatedNnode = node;
 
    if (animatedNnode)
    {
        animatedNnode->grab();
 
        currentAnimation.start = 0;
        currentAnimation.end = animatedNnode->getEndFrame(); //There is no way to get the actual frame count...
 
        animatedNnode->setAnimationEndCallback(this);
    }
}
 
void CAnimationController::playAnimation(const irr::c8 *name)
{
    if (animations.find(name) == 0)
        return;
 
    printf("change Animation to %s\n", name);
 
    if (animationRunning)
    {
        nextAnimation = animations[name];
        hasNext = true;
    }
    else
        setAnimation(animations[name]);
}
 
void CAnimationController::setAnimation(const Animation& anim)
{
    currentAnimation = anim;
    animatedNnode->setFrameLoop(currentAnimation.start, currentAnimation.end);
    animatedNnode->setCurrentFrame(currentAnimation.start);
    animatedNnode->setLoopMode(false);
    animationRunning = true;
}

main.cpp

Code: Select all

#include "CAnimationController.h"
#include <irrlicht.h>
 
struct events : irr::IEventReceiver
{
    bool OnEvent(const irr::SEvent& event)
    {
        if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
        {
            if (event.KeyInput.Key == irr::KEY_KEY_Q)
            {
                controller.playAnimation("idle");
            }
            else if (event.KeyInput.Key == irr::KEY_KEY_W)
            {
                controller.playAnimation("crouch");
            }
            else if (event.KeyInput.Key == irr::KEY_KEY_E)
            {
                controller.playAnimation("stand");
            }
            else if (event.KeyInput.Key == irr::KEY_ESCAPE)
            {
                device->closeDevice();
            }
        }
        return false;
    }
    CAnimationController controller;
    irr::IrrlichtDevice* device;
};
 
int main()
{
    irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL);
 
    irr::scene::IAnimatedMeshSceneNode* dwarf = device->getSceneManager()->addAnimatedMeshSceneNode(device->getSceneManager()->getMesh("../lib/irrlicht-1.7.2/media/dwarf.x")); //change to fit your media path
    dwarf->setMaterialFlag(irr::video::EMF_LIGHTING, false);
    dwarf->setLoopMode(false);
 
    printf("Total frames: %i\n", dwarf->getEndFrame());
 
    device->getSceneManager()->addCameraSceneNodeFPS();
 
    events event;
 
    event.device = device;
 
    event.controller.setAnimatedMeshNode(dwarf);
 
    printf("!!!Total frames: %i\n", dwarf->getEndFrame());
 
    event.controller.addAnimation("crouch", 0, 20);
    event.controller.addAnimation("idle", 21, 30, true);
    event.controller.addAnimation("stand", 31, 54);
 
    device->setEventReceiver(&event);
 
    while (device->run())
    {
        device->getVideoDriver()->beginScene();
        device->getSceneManager()->drawAll();
        device->getVideoDriver()->endScene();
    }
 
    device->drop();
 
    return 0;
}

Re: Chaining Animations?

Posted: Sun Aug 28, 2011 2:59 pm
by thoma91
Thank you Sudi for your example, but it's still not, what I'm looking for.
This changes animations by pressing keys.
I need automatic change, after one animation is finished/played.
The problem is, when I set up a second animation, the first one gets ignored.
Even if there's an if condition before it, like this:

Code: Select all

 
int something=0;
...
void reaction()
{
if(something==0)
{
        node->setLoopMode(false);
        node->setFrameLoop(272,288);
        ++something;
        reaction();
}
else if(something==1)
{
        node->setLoopMode(true);
        node->setFrameLoop(0,24);
        --something;
}
}
...
bool shoot()
{
...
if(...){        // takes hit
reaction();
}
...
 
So the first animation has to be played, before the second could start, but only the second one is played.
Sudi, and others: could you help me solving this?