Modification for Non-loop Animation

A forum to store posts deemed exceptionally wise and useful
Post Reply
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Modification for Non-loop Animation

Post by Electron »

I'm not sure if anyone else has found it annoying, but I disliked the fact that after a call to setFrameLoop the animation would endlessly loop. To have it not loop one would have to use lots of timers to kepp track of where all your animations were. Messy. Here's how I modified the engine to fix this.

1) add the following lines to CAnimatedMeshSceneNode.h

Code: Select all

private:
//I added the following for no-loop option
bool loop;      //stores whether the current animation should be looped
void (*onAnimEnd) (IAnimatedMeshSceneNode*);  /*pointer to user created function for notification of animation ending*/
public:
//added for no-loop option
virtual void setLoopState(bool _loop);
//also added for no-loop option
virtual void setLoopCallback(void(*_onAnimEnd)(IAnimatedMeshSceneNode*));
THE LAST TWO LINES GO ON THE SAME LINE

2) replace getFrameNr in CAnimatedMeshSceneNode.cpp with

Code: Select all

inline s32 CAnimatedMeshSceneNode::getFrameNr()
{
	s32 frame = 0;

	frame = StartFrame + ((s32)((os::Timer::getTime() - BeginFrameTime)* (FramesPerSecond/1000.0f)));
	
	if (frame > EndFrame) /*if our set frame loop has passed the last frame */
	{
       if (loop==false)//if set to not loop animation
       {
       setFrameLoop(EndFrame,EndFrame);  //stop animation
       if(onAnimEnd)
       {
       (*onAnimEnd) ((IAnimatedMeshSceneNode*)this);   /*notify user that animation ended. Pass pointer to this scenenode*/
       }
       frame=EndFrame;
       }
       else //if loop set (default)
       {
       frame=StartFrame;//go to beginning
       BeginFrameTime=os::Timer::getTime(); //set this as begining
       }
	}


	return frame;
}
3) add the following two functions to CAnimatedMeshSceneNode.cpp

Code: Select all

void CAnimatedMeshSceneNode::setLoopState(bool _loop)
{
    loop=_loop;  //set wether or not to loop animation
}

void CAnimatedMeshSceneNode::setLoopCallback(void(*_onAnimEnd)(IAnimatedMeshSceneNode*))
{
    onAnimEnd=_onAnimEnd; //set the callback to call when not looping and have reached end of animation
}
4) and so we can actually use these functions from a program,add to IAnimatedMeshSceneNode.h the following

Code: Select all

virtual void setLoopCallback (void(*_onAnimEnd)(IAnimatedMeshSceneNode*))=0;
virtual void setLoopState(bool _loop)=0;
5) add a couple lines to the constructor to initialize out new variables to 0

It's all really quite simple, though it took me a while because I messed up my include paths and was including a different set of irrlicht headers than I was compiling (took me hours to figure that one out :oops: )
I just finished it yesterday and haven't really tested it, so there may be bugs. I think it might crash if younever set a callback function, though that's easy to fix.
Last edited by Electron on Tue Jul 06, 2004 8:35 pm, edited 2 times in total.
qwe
Posts: 112
Joined: Sun Dec 28, 2003 12:54 am
Location: Oregon, USA

Post by qwe »

you may want to enclose your code in [ code ] tags to make it more readable :wink:
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

good point :D

BTW, switching animations when one ends seems a little jerky right now. I'll need to work on that.
bOOtix

Callback

Post by bOOtix »

Hi!
Thanks for your code which help me a lot.
I've just one question. I've compiled your modification, It compile very well.
So I'm using these property in my code.
So my question is, how to use the callback function ?
Because I don't understand what should I put in parameter of

Code: Select all

CAnimatedMeshSceneNode::setLoopCallback(void(*_onAnimEnd)(IAnimatedMeshSceneNode*))
I have written my callback function to detect which anim the program has to play, but I don't understand the type/syntaxe

Is it like that:

Code: Select all

model2->setLoopCallback(SelectAnim);
or that

Code: Select all

model2->setLoopCallback(&SelectAnim);
what must return my selectanim function ???
It's a pointer on function...
So I don't understand this part of your code. could you explain me please?
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

Both of the two ways you showed should work fine, it worked for me either using the & or not. If you are unfamiliar with function pointers I suggest you look here. It's where I learned about them.http://www.function-pointer.org/

your SelectAnim function must have a return type of void and accept 1 parameter of type IAnimatedMeshSceneNode* for example

Code: Select all

 void SelectAnim (IAnimatedMeshSceneNode* node)
{
     //do stuff with the node
}
either way to set that callback will work. To quote a pdf on that site "It’s optional to use the address operator & in front of the function’s
name."

When the getFrameNr() function is called and it determines that the next frame would be the starting frame and you have set it to not loop by calling setLoopState(false) it calls your function, passing it the this pointer.

I hope this is all clear now. When I get a chance I'm going to see if I can fix jerkiness when I switch animations
bOOtix

Post by bOOtix »

Ok it works well thanks for your answer. I think this code should be added to the official engine....
Post Reply