//
// Irrlicht Wrapper for Imperative Languages
// Frank Dodd (2006)
//
// Additional Work
// Michael Taupitz (2006)
//
// This wrapper DLL encapsulates a sub-set of the features of the powerful
// Irrlicht 3D Graphics Engine exposing the Object Oriented architecture and
// providing a functional 3D SDK for languages that are not object oriented.
//
// This source was created with the help of the great examples in the Irrlicht
// SDK and the excellent Irrlicht documentation. This software was developed
// using the GCC compiler and Code::Blocks IDE
//

/* ////////////////////////////////////////////////////////////////////////////
includes
*/
#include "irrlichtwrapper.h"
#include "CCallbackAnimator.h"

/* ////////////////////////////////////////////////////////////////////////////
global variables
*/

/* ////////////////////////////////////////////////////////////////////////////
external variables
*/
extern IrrlichtDevice *device;
extern IVideoDriver* driver;
extern ISceneManager* smgr;
extern IGUIEnvironment* guienv;


/* ////////////////////////////////////////////////////////////////////////////
Global Function Declarations

all of the below functions are declared as C functions and are exposed without
any mangled names so that they can be easily imported into imperative
languages like FreeBasic
*/
extern "C"
{

/* ////////////////////////////////////////////////////////////////////////////
NODE ANIMATION FUNCTIONS
*/

/****h* Animation
* NAME
*    Animation-Functions
* DESCRIPTION
*   In this Section are several Functions to use animated Meshes (MD2)
*   You can start a 'Standard'-Animation, or animations by Name.
*
****
*/

/****f* Animation/IrrSetNodeAnimationRange
* NAME
*    IrrSetNodeAnimationRange - set the frames to playback in the animation
* SYNOPSIS
*    IrrSetNodeAnimationRange(*node.l, iStart.l, iEnd.l)
* INPUTS
*   *node.l         - pointer to a 'Animated' scene node.
*   iStart.l        - Start frame number of the loop
*   iEnd.l          - End frame number of the loop
* FUNCTION
*   Sets the frame numbers between the animation is looped.
*   The default is 0 - MaximalFrameCount of the mesh
* EXAMPLE
*   IrrSetNodeAnimationRange(*node.l, 0,10)
* RESULT
*    Returns true if successful, false if not.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetNodeAnimationRange(*node.l, iStart.l, iEnd.l)
*/
STATIC_EXPORT bool DLL_EXPORT IrrSetNodeAnimationRange ( IAnimatedMeshSceneNode* node, int iStart, int iEnd )
{
    // set the animation loop in the object
    return node->setFrameLoop(iStart, iEnd);
}

/****f* Animation/IrrPlayNodeMD2Animation
* NAME
*    IrrPlayNodeMD2Animation - Starts a default MD2 animation
* SYNOPSIS
*    IrrPlayNodeMD2Animation(*node.l, iAnimation.l)
* INPUTS
*   *node.l         - pointer to a 'Animated' scene node.
*   iAnimation.l    - An MD2 animation type, which should be played, for example #IRR_EMAT_STAND for the standing animation
* FUNCTION
*   Starts a default MD2 animation. With this method it is easily possible to
*   start a Run, Attack, Die or whatever animation, if the mesh contained in this
*   scene node is a md2 mesh. Otherwise, nothing happenes.
* EXAMPLE
*   IrrPlayNodeMD2Animation(*node.l, #IRR_EMAT_ATTACK)
* RESULT
*    Returns true if successful, false if not.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPlayNodeMD2Animation(*node.l, iAnimation.l)
*/
STATIC_EXPORT bool DLL_EXPORT IrrPlayNodeMD2Animation ( IAnimatedMeshSceneNode* node, EMD2_ANIMATION_TYPE iAnimation)
{
/*
    EMD2_ANIMATION_TYPE  animationtable[] = {
        EMAT_STAND,
        EMAT_RUN,
        EMAT_ATTACK,
        EMAT_PAIN_A,
        EMAT_PAIN_B,
        EMAT_PAIN_C,
        EMAT_JUMP,
        EMAT_FLIP,
        EMAT_SALUTE,
        EMAT_FALLBACK,
        EMAT_WAVE,
        EMAT_POINT,
        EMAT_CROUCH_STAND,
        EMAT_CROUCH_WALK,
        EMAT_CROUCH_ATTACK,
        EMAT_CROUCH_PAIN,
        EMAT_CROUCH_DEATH,
        EMAT_DEATH_FALLBACK,
        EMAT_DEATH_FALLFORWARD,
        EMAT_DEATH_FALLBACKSLOW,
        EMAT_BOOM
    };

    // play the selected animation sequence
	return node->setMD2Animation(animationtable[iAnimation]);
*/
	return node->setMD2Animation(iAnimation);
}

/****f* Animation/IrrPlayNodeMD2AnimationByName
* NAME
*    IrrPlayNodeMD2AnimationByName - Starts a named MD2 animation
* SYNOPSIS
*    IrrPlayNodeMD2AnimationByName(*node.l, animationName.s)
* INPUTS
*   *node.l         - pointer to a 'Animated' scene node.
*   animationName.s - Name of the animation
* FUNCTION
*   Starts a named Animation of the MD2-Mesh
* EXAMPLE
*   IrrPlayNodeMD2AnimationByName(*node.l, "MyNamedAnim")
* RESULT
*    Returns #False if the mesh in the scene node is not a md2 mesh,
*    or no animation with this name could be found.
* HISTORY
*   Added in Version 1.05 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPlayNodeMD2AnimationByName(*node.l, animationName.p-ascii)
*/
STATIC_EXPORT bool DLL_EXPORT IrrPlayNodeMD2AnimationByName ( IAnimatedMeshSceneNode* node, const c8* animationName)
{
    return node->setMD2Animation(animationName);
}


/****f* Animation/IrrSetNodeAnimationSpeed
* NAME
*    IrrSetNodeAnimationSpeed - set the playback animation speed
* SYNOPSIS
*    IrrSetNodeAnimationSpeed(*node.l, framesPerSecond.l)
* INPUTS
*   *node.l             - pointer to a 'Animated' scene node.
*   framesPerSecond.l   - Frames per second played
* FUNCTION
*   Starts a named Animation of the MD2-Mesh
* EXAMPLE
*   IrrSetNodeAnimationSpeed(*node.l, 10)
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetNodeAnimationSpeed(*node.l, framesPerSecond.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetNodeAnimationSpeed ( IAnimatedMeshSceneNode* node, int iSpeed )
{
    // set the speed of playback in the animation
    node->setAnimationSpeed(iSpeed);
}

/****f* Animation/IrrGetNodeAnimationFrame
* NAME
*    IrrGetNodeAnimationFrame - Returns the current displayed frame number.
* SYNOPSIS
*    frameNr.l = IrrGetNodeAnimationFrame(*node.l)
* INPUTS
*   *node.l             - pointer to a 'Animated' scene node.
* FUNCTION
*   get the current frame number being played in the animation
* EXAMPLE
*   frameNr.l = IrrGetNodeAnimationFrame(*node.l)
* RESULT
*    current frame number
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetNodeAnimationFrame(*node.l)
*/
STATIC_EXPORT unsigned int DLL_EXPORT IrrGetNodeAnimationFrame ( IAnimatedMeshSceneNode* node )
{
    // set the speed of playback in the animation
    return node->getFrameNr();
}

/****f* Animation/IrrSetNodeAnimationFrame
* NAME
*    IrrSetNodeAnimationFrame - Sets the current frame number
* SYNOPSIS
*    IrrSetNodeAnimationFrame(*node.l,frameNr.l)
* INPUTS
*   *node.l             - pointer to a 'Animated' scene node.
*   frameNr.l           - Number of the frame to let the animation be started from.
*                         The frame number must be a valid frame number of the Mesh used by this scene node.
* FUNCTION
*   Sets the current frame number. From now on the animation
*   is played from this frame.
* EXAMPLE
*   IrrGetNodeAnimationFrame(*node.l)
* RESULT
*    nothing
* HISTORY
*   Added in Version 1.05 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetNodeAnimationFrame(*node.l,frameNr.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetNodeAnimationFrame ( IAnimatedMeshSceneNode* node, s32 iFrameNr )
{
    node->setCurrentFrame(iFrameNr);
}

/****f* Animation/IrrSetNodeAnimationLooped
* NAME
*    IrrSetNodeAnimationLooped - Sets looping mode
* SYNOPSIS
*    IrrSetNodeAnimationLooped(*node.l,bLooped.l)
* INPUTS
*   *node.l             - pointer to a 'Animated' scene node.
*   bLooped.l           - If set to #False, animations will not be played looped
* FUNCTION
*   Sets looping mode which is on by default.
* EXAMPLE
*   IrrSetNodeAnimationLooped(*node.l,#False)
* RESULT
*    nothing
* HISTORY
*   Added in Version 1.05 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetNodeAnimationLooped(*node.l,bLooped.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetNodeAnimationLooped ( IAnimatedMeshSceneNode* node, bool bLooped )
{
    node->setLoopMode(bLooped);
}

/* ////////////////////////////////////////////////////////////////////////////
ANIMATOR FUNCTIONS
*/

/****h* Animators
* NAME
*    Animator-Functions
* DESCRIPTION
*   In this Section are several Functions to add animators.
*   Animators animates a scene node. Can animate position, rotation, material, and so on.
*   A scene node animator is able to animate a scene node in a very simple way. It may
*   change its position, rotation, scale and/or material. There are lots of animators to
*   choose from.
*   But you can also use a Callback-Animator, to use this animator-functionality also
*   from PureBasic. It enables you to make your own Animators, maybe to make a Animator,
*   that only follws another node, or face to it.... It is agreat feature, and i hope you
*   will use it.
*
****
*/

/****f* Animators/IrrAddCollisionAnimator
* NAME
*    IrrAddCollisionAnimator - Adds a collision animator to a node
* SYNOPSIS
*    *animator.l = IrrAddCollisionAnimator(*irr_selector.l, *irr_node.l, radiusx.f, radiusy.f, radiusz.f,gravityx.f,gravityy.f,gravityz.f,offsetx.f,offsety.f,offsetz.f)
* INPUTS
*   *irr_selector.l     - represents a selection of triangles in the scene, this is usually all of
*                         the triangles in a map For instance. Please refer to the section on collision
*                         for further details of how To obtain this object.
*   *irr_node.l         - refers to a node you have added to the scene.
*   radiusx.f, radiusy.f, radiusx.f  - Define an ellipsoid that defines the area of collision
*                                      this eliptical shape allows the collision detection To slide
*                                      the object up steps and even ladders. If you make it too big
*                                      you might be too large to get through a doorway but if you make
*                                      it too small you may not be able to climb steps. You should play
*                                      with these values and find the best ones for your scene.
*   gravityx.f, gravityy.f, gravityz.f - work together to specify the force that is applied to the node To make it drop
*                                        to the ground. Other values could be used to simulate wind effects.
*   offsetx.f, offsety.f, offsetz.f    - are used To offset the node by a specific distance from the center of the collision,
*                                        as the center of the object and the size of your collision ellipsoid vary you can use
*                                        this To adjust the position of the node and to bring it into contact with the ground.
* FUNCTION
*   This adds a collision animator to a node that applies collision detection and gravity
*   to the object. The collision detection will stop the object penetrating through a surface
*   in the objects it is colliding against and will also press it against the surface using gravity.
* EXAMPLE
*   *CollisionAnimator.l = IrrAddCollisionAnimator( *MapCollision, *CameraNode, 30.0,30.0,30.0, 0.0,-3.0,0.0,  0.0,50.0,0.0 )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddCollisionAnimator(*irr_selector.l, *irr_node.l, radiusx.f, radiusy.f, radiusz.f,gravityx.f,gravityy.f,gravityz.f,offsetx.f,offsety.f,offsetz.f)
*/
STATIC_EXPORT void *DLL_EXPORT IrrAddCollisionAnimator(
                                        ITriangleSelector* selector,
                                        ISceneNode* node,
                                        float radiusx, float radiusy, float radiusz,
                                        float gravityx, float gravityy, float gravityz,
                                        float offsetx, float offsety, float offsetz )
{
    node->setTriangleSelector(selector);

	scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
		selector, node, core::vector3df(radiusx,radiusy,radiusz),
		core::vector3df(gravityx,gravityy,gravityz),
		core::vector3df(offsetx,offsety,offsetz));
	node->addAnimator(anim);
	anim->drop();
	return (void *)anim;
}


/****f* Animators/IrrAddDeleteAnimator
* NAME
*    IrrAddDeleteAnimator - deletes the node after the specified number of milliseconds
* SYNOPSIS
*    *animator.l = IrrAddDeleteAnimator(*irr_node.l, delete_after_n_milliseconds.l)
* INPUTS
*   *irr_node.l                   - refers to a node you have added to the scene.
*   delete_after_n_milliseconds.l - time when to delete.
* FUNCTION
*   This animator deletes the node it is attached to after the specified number
*   of milliseconds (1/1000ths of a second). You could use this animator to delete
*   a falling rock For example, all you would need to do is attach the delete
*   animator, a movement animator and then forget about it.
* EXAMPLE
*   *DeleteAnimator.l = IrrAddDeleteAnimator( *RockNode, 3000 )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddDeleteAnimator(*irr_node.l, delete_after_n_milliseconds.l)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddDeleteAnimator( ISceneNode* node, int delete_after )
{
    scene::ISceneNodeAnimator* anim = smgr->createDeleteAnimator( delete_after );
	node->addAnimator(anim);
	anim->drop();
	return (void *)anim;
}

/* ----------------------------------------------------------------------------
add a fly-in-circle animator to a node
*/

/****f* Animators/IrrAddFlyCircleAnimator
* NAME
*    IrrAddFlyCircleAnimator - fly circular path.
* SYNOPSIS
*    *animator.l = IrrAddFlyCircleAnimator(*irr_node.l,centre_x.f,centre_y.f,centre_z.f, radius.f, speed.f, dirX.f, dirY.f, dirZ.f)
* INPUTS
*   *irr_node.l                      - refers to a node you have added to the scene.
*   centre_x.f,centre_y.f,centre_z.f - define the center of the circular path.
*   radius.f                         - defines the radius of the path
*   speed.f                          - defines the rate the node moves around the circular path
*   dirX.f,dirY.f.dirZ.f             - defines the direction of the rotation
* FUNCTION
*   This animator moves the node it is attached to in a circular path.
* EXAMPLE
*   *CircleAnimator.l = IrrAddFlyCircleAnimator( *PowerNode, 0,0,0 50, 20 )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddFlyCircleAnimator(*irr_node.l,centre_x.f,centre_y.f,centre_z.f, radius.f, speed.f=0.0001, dirX.f=0.0, dirY.f=1.0, dirZ.f=0.0)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddFlyCircleAnimator(
                                        ISceneNode* node,
                                        float x, float y, float z,
                                        float radius, float speed,
                                        float dirX, float dirY, float dirZ )
{
    scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(
            core::vector3df(x,y,z), radius, speed, vector3df(dirX,dirY,dirZ));
	node->addAnimator(anim);
	anim->drop();
	return (void *)anim;
}

/****f* Animators/IrrAddFlyStraightAnimator
* NAME
*    IrrAddFlyStraightAnimator - fly straight path.
* SYNOPSIS
*    *animator.l = IrrAddFlyStraightAnimator(*irr_node.l, start_x.f,start_y.f, start_z.f, end_x.f,end_y.f,end_z.f,time_to_complete.l,loop_path.l)
* INPUTS
*   *irr_node.l                   - refers to a node you have added to the scene.
*   start_x.f,start_y.f,start_z.f - specify the start point of the path.
*   end_x.f,end_y.f,end_z.f       - specify the end point of the path.
*   end_x.f,end_y.f,end_z.f       - specify the end point of the path.
*   time_to_complete.l            - Time to complete specifies the number of milliseconds the animator will take
*                                   to move the node from the start to the end point
*   loop_path.l                   - determines if the node will be moved from the start to the end and then stopped
*                                   or whether the animation will be looped (#True or #False)
* FUNCTION
*   This animator makes the node it is attached to move in a straight line from the start to
*   the Endpoint. It would be useful for objects moving on a conveyor belt For example.
* EXAMPLE
*   *FlyAnimator.l = IrrAddFlyStraightAnimator( *AnimatedBox, 0,50,-300, 0,50,300, 3000, #True )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddFlyStraightAnimator(*irr_node.l, start_x.f,start_y.f, start_z.f, end_x.f,end_y.f,end_z.f,time_to_complete.l,loop_path.l)
*/
STATIC_EXPORT void *DLL_EXPORT IrrAddFlyStraightAnimator(
                                        ISceneNode* node,
                                        float sx, float sy, float sz,
                                        float ex, float ey, float ez,
                                        unsigned int uitime, bool loop )
{
    scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(
            core::vector3df(sx,sy,sz),
            core::vector3df(ex,ey,ez),
            uitime,
            loop
    );
	node->addAnimator(anim);
	anim->drop();
	return (void *)anim;
}


/****f* Animators/IrrAddRotationAnimator
* NAME
*    IrrAddRotationAnimator - rotate node
* SYNOPSIS
*    *animator.l = IrrAddRotationAnimator(*irr_node.l, x.f,y.f,z.f)
* INPUTS
*   *irr_node.l                   - refers to a node you have added to the scene.
*   x.f,y.f,z.f                   - Specifies the speed of the animation
* FUNCTION
*   This animator makes the node it is attached to spin around.
* EXAMPLE
*   *RotationAnimator.l = IrrAddRotationAnimator( *DisplayCaseNode, 0, 0.1, 0 )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddRotationAnimator(*irr_node.l, x.f,y.f,z.f)
*/
STATIC_EXPORT void *DLL_EXPORT IrrAddRotationAnimator( ISceneNode* node, float x, float y, float z )
{
    scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
            core::vector3df(x,y,z));
	node->addAnimator(anim);
	anim->drop();
	return (void *)anim;
}

/****f* Animators/IrrAddSplineAnimator
* NAME
*    IrrAddSplineAnimator - add a spline animator to a node
* SYNOPSIS
*    *animator.l = IrrAddSplineAnimator(*irr_node.l, array_size.l,*x.f,*y.f,*z.f,time_to_start.l,speed.f,tightness.f)
* INPUTS
*   *irr_node.l     - refers to a node you have added to the scene.
*   array_size.l    - specifies how many points there are in your spline motion.
*   *f.f,*y.f,*z.f  - The three arrays X, Y And Z containing co-ordinates are passed as a pointer therefore you should ensure that the array is the correct size otherwise unpredictable results will be obtained.
*   time_to_start.l - specifies the number of milliseconds that must pass before the animation starts.
*   speed.f         - defines the rate the node moves along the spline curve.
*   tightness.f     - specifies how tightly the curve is tied to the points (0 is angular And 1 is very loose).
* FUNCTION
*   This is one of the more difficult to set up of the animators but is very natural looking and powerful.
*   A spline is a curved line that passes through or close to a list of co-ordinates, creating a smooth flight.
*   This animator needs a list of coordinates stored in three arrays, one array each for the X, Y and Z locations
*   of all the points. A good way to get co-ordinates for these arrays is to load in the camera position example
*   program and move your camera to a point and write down its co-ordinates.
* EXAMPLE
*   #SPLINE_POINTS = 4
*   Dim SplineX.f(#SPLINE_POINTS)
*   Dim SplineY.f(#SPLINE_POINTS)
*   Dim SplineZ.f(#SPLINE_POINTS)
*   SplineX(0) = -100 : SplineY((0) =   50 : SplineZ((0) =    0
*   SplineX(1) =    0 : SplineY((1) =  100 : SplineZ((1) = -100
*   SplineX(2) =  100 : SplineY((2) =   50 : SplineZ((2) =    0
*   SplineX(3) =    0 : SplineY((3) =  100 : SplineZ((3) =  100
*   *SplineAnimator.l = IrrAddSplineAnimator( *CameraNode, #SPLINE_POINTS, @SplineX(0), @SplineY(0), @SplineZ(0), 0, 0.5, 1)
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddSplineAnimator(*irr_node.l, array_size.l,*x.f,*y.f,*z.f,time_to_start.l,speed.f,tightness.f)
*/
STATIC_EXPORT void *DLL_EXPORT IrrAddSplineAnimator( ISceneNode* node, int iPoints,
                                    float *x, float *y, float *z,
                                    int time, float speed, float tightness )
{
    core::array<core::vector3df> points;
    for ( int loop = 0; loop < iPoints; loop++ )
    {
        points.push_back(core::vector3df(x[loop], y[loop], z[loop]));
    }

    scene::ISceneNodeAnimator* anim = smgr->createFollowSplineAnimator(
            time, points, speed, tightness);
    node->addAnimator(anim);
    anim->drop();
	return (void *)anim;
}

/****f* Animators/IrrAddTextureAnimator
* NAME
*    IrrAddTextureAnimator - add a texture animator to a node
* SYNOPSIS
*    *animator.l = IrrAddTextureAnimator( *irr_node.l, iTextures.l,*texArray.l,speed.l,loop.l )
* INPUTS
*   *irr_node.l - refers to a node you have added to the scene.
*   iTextures   - number of texture in the Array.
*   *texArray.l - pointer to the Array of Textures. You have to ensure that the size and content
*                 of the Array is valid. It is not checked !
*   speed.l     - Time in milliseconds, how long any texture in the list should be visible.
*   loop.l      - If set to #False, the last texture remains set, and the animation stops. If set to #True, the animation restarts with the first texture.
* FUNCTION
*   Add a texture animator , which switches the textures of the target scene node based on a list of textures.
* EXAMPLE
*   *TextureAnimator.l = IrrAddTextureAnimator( *irr_node.l, 4,*texArray.l,200,#True )
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddTextureAnimator( *irr_node.l, iTextures.l,*texArray.l,speed.l,loop.l )
*/
STATIC_EXPORT void *DLL_EXPORT IrrAddTextureAnimator( ISceneNode* node, int iTextures,
                                    int* texArray,
                                    int speed, bool loop )
{
    core::array<ITexture*> textures;
    for ( int l = 0; l < iTextures; l++ )
    {
        textures.push_back((ITexture*)texArray[l]);
    }

    scene::ISceneNodeAnimator* anim = smgr->createTextureAnimator( textures,speed,loop);
    node->addAnimator(anim);
    anim->drop();
	return (void *)anim;
}


/****f* Animators/IrrAddCallbackAnimator
* NAME
*    IrrAddCallbackAnimator - add a callback animator to a node
* SYNOPSIS
*    *animator.l = IrrAddCallbackAnimator(*irr_node.l, *callback.l, *userdata.l)
* INPUTS
*   *irr_node.l - refers to a node you have added to the scene.
*   *callback.l - refers to a Callback-Function. see below !
*   *userdata.l - refers to a Userdefined Data, to store with this Animator.
* FUNCTION
*   The Callback-Animator gives you a very powerfull, and also very flexible point to change
*   move or animate a node. This Animator-Callback is called befor the Node is drawn. So
*   you can change e.g. the Size or position. But keep in Mind, that this Animator is called
*   very often. So make sure to put no timexpensive calculation in the callback.
*
* EXAMPLE
*
*   ;; Here is a simple Structure to keep some Userdatas for the Node
*   Structure CBDataStruct
*       name.s
*   EndStructure
*
*   ; Here is the Callback-Function. Please make sure, that you allways
*   ; get Two parameters. The First is the most important. It is that SceneNode where
*   ; you attached the CallBack-Animator. The Second Parameter is usefull to keep some
*   ; Information with the Animator/SceneNode.
*
*   ProcedureC.l AnimatorCallback(*scene_node.l, *userdata.CBDataStruct)
*       ; here we get the actual Rotation of that node.
*       IrrGetNodeRotation(*scene_node,@x.f,@y.f,@z.f)
*       y+0.2        ; We let it rotate against the Y-Axis.
*       If y >= 360  ;Okay, more the 360 degrees are not possible....
*           y=0
*       EndIf
*
*       ;And now we set the new Rotation for that Node
*       IrrSetNodeRotation(*scene_node,x,y,z)
*
*       ;For example, we Debug out the Name of that Node
*       Debug("Userdata="+*userdata\name)
*
*       ;We Also can Debug out the Name of the Node !
*       Debug("Animator-Callback from " + PeekS(IrrGetNodeName(*scene_node)))
*
*       ;We should try to return allways #True. If you return #False, the
*       ;Animator will destroyed.
*       ProcedureReturn #True;
*   EndProcedure
*
*   ;define the Userdata
*   mydata.CBDataStruct
*
*   ;set a Value to my Userdata
*   mydata\name = "Hi, i'm a Callback !"
*
*   ;Attach a Callback animator to a node
*   *animator.l = IrrAddCallbackAnimator(*node, @AnimatorCallback(), @
* RESULT
*    pointer to a Irrlicht-Animator.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddCallbackAnimator(*irr_node.l, *callback.l, userdata.l = #Null)
*/

STATIC_EXPORT void *DLL_EXPORT IrrAddCallbackAnimator( ISceneNode* node, AnimatorCallbackPtr callBack,  u32 userdata)
{
    scene::ISceneNodeAnimator* anim = new CCallbackAnimator(callBack,device->getTimer()->getRealTime(),userdata);
    node->addAnimator(anim);
    anim->drop();
	return (void *)anim;
}

/****f* Animators/IrrRemoveAnimator
* NAME
*    IrrRemoveAnimator - remove an animator from a node
* SYNOPSIS
*    IrrRemoveAnimator(*irr_node.l, *irr_animator.l)
* INPUTS
*   *irr_node.l     - refers to a node you have added to the scene.
*   *irr_animator.l - refers to a animator you have added to the node.
* FUNCTION
*   This removes an animator from a node. Stopping the animation or cleaning an animator up so you can apply a new one.
* EXAMPLE
*   *TextureAnimator.l = IrrAddTextureAnimator( *irr_node.l, 4,*texArray.l,200,#True )
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrRemoveAnimator(*irr_node.l, *irr_animator.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrRemoveAnimator( ISceneNode* node, ISceneNodeAnimator *  anim )
{
    node->removeAnimator ( anim );
}


/* ////////////////////////////////////////////////////////////////////////////
all of the above functions are declared as C functions and are exposed without
any mangled names
*/
}
