//
// 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 "StopParticleAffector.h"
//needs test !
#include "CCallbackParticleEmitter.h"
#include "IParticleRingEmitter.h"
#include "CParticleRingEmitter.h"
#include "CParticleSphereEmitter.h"
#include "CParticleMeshEmitter.h"
#include "CParticleRotationAffector.h"
//#include "CParticleEmitterManager.h"
#include "CParticleCollisionAffector.h"
#include "CParticleSpinAffector.h"
#include "CParticleAttractionAffector.h"
#include "CParticleAlignAffector.h"
#include "CParticleScaleAffector.h"
#include "CParticleBounceAffector.h"
#include "IParticleSystemExtSceneNode.h"
/* ////////////////////////////////////////////////////////////////////////////
global variables
*/

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



/****h* Particles
* NAME
*    Particlesystem
* DESCRIPTION
*   A particle system  for creating snow, fire, exlosions, smoke...
*   You can use this ParticleSystem with ease
*
* EXAMPLE
*   ToDo
*
****
*/


/* ////////////////////////////////////////////////////////////////////////////
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"
{

/* ////////////////////////////////////////////////////////////////////////////
PARTICLE FUNCTIONS
*/
/* ----------------------------------------------------------------------------
set the size of a particle in the particle system
*/
/****f* Particles/IrrSetParticleSize
* NAME
*    IrrSetParticleSize - set the size of a particle in the particle system
* SYNOPSIS
*    IrrSetParticleSize(*particleSystem.l, x.f, y.f)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
* FUNCTION
*   set the size of a particle in the particle system
* EXAMPLE
*   none
* RESULT
*   nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetParticleSize(*particleSystem.l, x.f, y.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetParticleSize( IParticleSystemSceneNode* ps, float x, float y )
{
	ps->setParticleSize(dimension2d<f32>(x,y));
}

/* ----------------------------------------------------------------------------
create an emitter that can be added to a particle system
*/
/*
STATIC_EXPORT void * DLL_EXPORT IrrAddParticleEmitterFreeBasic( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER prop )
{
	IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d<f32>(prop.min_box_x,prop.min_box_y,prop.min_box_z,prop.max_box_x,prop.max_box_y,prop.max_box_z),
		core::vector3df(prop.direction_x,prop.direction_y,prop.direction_z),
		prop.min_paritlcles_per_second,prop.max_paritlcles_per_second,
		video::SColor(0,prop.min_start_color_red,prop.min_start_color_green,prop.min_start_color_blue),
		video::SColor(0,prop.max_start_color_red,prop.max_start_color_green,prop.max_start_color_blue),
		prop.min_lifetime,prop.max_lifetime,
		prop.max_angle_degrees );

	ps->setEmitter(em);
	em->drop();
	return (void *)em;
}
*/

/* ----------------------------------------------------------------------------
create an emitter that can be added to a particle system
*/
/****f* Particles/IrrAddParticleEmitter
* NAME
*    IrrAddParticleEmitter - Add an ParticleEmitter
* SYNOPSIS
*    *emitter.l = IrrAddParticleEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   *properties.IRR_PARTICLE_EMITTER  - Pointer t a filled Structure
* FUNCTION
*   Adds a Emitter to the ParticleSystem.
*   You have to fill the Structure IRR_PARTICLE_EMITTER to define the behavior of the Emitter.
*   (This is while it s are too many Parameters to make it as parameters)
* EXAMPLE
*   Define explosionEmitter.IRR_PARTICLE_EMITTER
*   With explosionEmitter
*       \min_box_x = -2
*       \min_box_y = 0
*       \min_box_z = -2
*       \max_box_x = 2
*       \max_box_y = 1
*       \max_box_z = 2
*       \direction_x = 0.006
*       \direction_y = 0.06
*       \direction_z = 0.006
*       \min_paritlcles_per_second = 60
*       \max_paritlcles_per_second = 80
*       \min_start_color_red = 255
*       \min_start_color_green = 255
*       \min_start_color_blue = 255
*       \max_start_color_red = 255
*       \max_start_color_green = 255
*       \max_start_color_blue = 255
*       \min_lifetime = 500
*       \max_lifetime = 700
*       \max_angle_degrees = 359
*   EndWith
*
*   ; finally we add this particle emitting object to the particle system
*   *em.l = IrrAddParticleEmitter( *ParticlesNode, @explosionEmitter )
*
* RESULT
*    A pointer to a Emitter.
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleEmitter(*particleSystem.l,  *properties.IRR_PARTICLE_EMITTER)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddParticleEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER* prop )
{
	IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d<f32>(prop->min_box_x,prop->min_box_y,prop->min_box_z,prop->max_box_x,prop->max_box_y,prop->max_box_z),
		core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
		prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
		video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
		video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
		prop->min_lifetime,prop->max_lifetime,
		prop->max_angle_degrees );

	ps->setEmitter(em);
	em->drop();
	return (void *)em;
}


/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetParticleEmitter(*particleSystem.l,  *emitter)
*/
STATIC_EXPORT void * DLL_EXPORT IrrSetParticleEmitter( IParticleSystemSceneNode* ps, IParticleEmitter* em )
{
    if (ps)
    {
        ps->setEmitter(em);
        em->drop();
        return (void *)em;
    }
    return NULL;
}

/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrCreateParticleEmitter(*particleSystem.l,  *properties.IRR_PARTICLE_EMITTER)
*/
STATIC_EXPORT void * DLL_EXPORT IrrCreateParticleEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER* prop )
{
	IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d<f32>(prop->min_box_x,prop->min_box_y,prop->min_box_z,prop->max_box_x,prop->max_box_y,prop->max_box_z),
		core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
		prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
		video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
		video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
		prop->min_lifetime,prop->max_lifetime,
		prop->max_angle_degrees );
    return (void*) em;
}

/****f* Particles/IrrAddFadeOutParticleAffector
* NAME
*    IrrAddFadeOutParticleAffector - Add an affector to the particle system to fade the particles out
* SYNOPSIS
*    *affector.l = IrrAddFadeOutParticleAffector(*particleSystem.l, alpha.l, red.l, green.l, blue.l, timeNeededToFadeOut.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   alpha.l,red.l,green.l,blue.l    - target Color
*   timeNeededToFadeOut.l           - How much time in milliseconds should the affector need to change the color to the targetColor.
* FUNCTION
*   Adds a fade out particle affector. This affector modifies the color of every particle and and reaches the final
*   color when the particle dies. This affector looks really good, if the #IRR_EMT_TRANSPARENT_VERTEX_ALPHA material
*   is used and the targetColor is (0,0,0,0): Particles are fading out into void with this setting.
** EXAMPLE
*   *affector.l = IrrAddFadeOutParticleAffector(*ps,0,0,0,0,1000)
*
* RESULT
*    A pointer to a Affector.
*
* HISTORY
*   Changed in Version 1.05 by M.Taupitz - add Parameter for TargetColor and Fadeout-Time
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddFadeOutParticleAffector(*particleSystem.l, alpha.l=0, red.l=0, green.l=0, blue.l=0, timeNeededToFadeOut.l=1000)
*/

STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddFadeOutParticleAffector( IParticleSystemSceneNode* ps, u32 a, u32 r, u32 g, u32 b, u32  timeNeededToFadeOut)
{
	IParticleAffector* paf = ps->createFadeOutParticleAffector(SColor(a,r,g,b),timeNeededToFadeOut);
	ps->addAffector(paf);
	paf->drop();
	return paf;
}

/****f* Particles/IrrAddGravityParticleAffector
* NAME
*    IrrAddGravityParticleAffector - Add an affector to the particle system to alter their position with gravity
* SYNOPSIS
*    *affector.l = IrrAddGravityParticleAffector(*particleSystem.l, x.f, y.f, z.f, timeForceLost.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle System (Object)
*   x.f,y.f,z.f         - Direction and force of gravity
*   timeForceLost.l     - Time in milli seconds when the force of the emitter is totally lost and
*                         the particle does not move any more. This is the time where gravity fully
*                         affects the particle.
* FUNCTION
*   Adds a gravity affector. This affector modifies the direction of the particle. It assumes that
*   the particle is fired out of the emitter with huge force, but is loosing this after some time
*   and is catched by the gravity then. This affector is ideal for creating things like fountains.
** EXAMPLE
*   *affector.l = IrrAddGravityParticleAffector(*ps,0,0,0,0,1000)
*
* RESULT
*    A pointer to a Affector.
*
* HISTORY
*   Changed in Version 1.05 by M.Taupitz - add Parameter for timeForceLost
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddGravityParticleAffector(*particleSystem.l, x.f=0.0, y.f=-0.03, z.f=0.0, timeForceLost.l = 1000)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddGravityParticleAffector( IParticleSystemSceneNode* ps, float x, float y, float z, u32 timeForceLost )
{
	IParticleAffector* paf = ps->createGravityAffector(vector3df(x,y,z),timeForceLost);
	ps->addAffector(paf);
	paf->drop();
	return paf;
}


/****f* Particles/IrrAddStopParticleAffector
* NAME
*    IrrAddStopParticleAffector - Add an affector to the particle system to stop emitting
* SYNOPSIS
*    *affector.l = IrrAddStopParticleAffector(*particleSystem.l, timeWhenStop.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle System (Object)
*   timeWhenStop.l      - Time in milli seconds when to stop emitting
* FUNCTION
*   Adds a stop emit affector. This affector stop the emitting after a number of milli seconds.
** EXAMPLE
*   *affector.l = IrrAddGravityParticleAffector(*ps,0,0,0,0,1000)
*
* RESULT
*    A pointer to a Affector.
*
* HISTORY
*   Added in Version 1.05 by M.Taupitz
*
* NOTES
*   This Affector follows the Idea of vitek in the Irrlicht-Forum.
*   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=15605&highlight=emitter
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddStopParticleAffector(*particleSystem.l, timeWhenStop.l)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddStopParticleAffector( IParticleSystemSceneNode* ps, u32 timeWhen)
{
    u32 when = device->getTimer()->getTime() + timeWhen;
	IParticleAffector* paf = new StopParticleAffector(ps,smgr,when);
	ps->addAffector(paf);
	paf->drop();
	return paf;
}


/****f* Particles/IrrRemoveAffectors
* NAME
*    IrrRemoveAffectors - Remove all Affectors
* SYNOPSIS
*    IrrRemoveAffectors(*particleSystem.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle System (Object)
* FUNCTION
*   Remove all effectors from this particle system
** EXAMPLE
*   IrrRemoveAffectors(*ps,0,0,0,0,1000)
* RESULT
*    nothing
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrRemoveAffectors(*particleSystem.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrRemoveAffectors( IParticleSystemSceneNode* ps )
{
	ps->removeAllAffectors();
}


/* ***f* Particles/IrrAddParticleCallbackEmitter
* NAME
*    IrrAddParticleCallbackEmitter - get the ID of this node
* SYNOPSIS
*    *emitter.l = IrrAddParticleCallbackEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, *callbackfunction.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   *properties.l       - a Pointer to Structure, where the Emitter-Properties are stored (IRR_PARTICLE_EMITTER)
*   *callbackfunction.l - a Pointer to Function, that emits the Particle.
* FUNCTION
*   This Function 'wraps' the a Emitter, that is used by a ParticleSystem. It enables you
*   to get the control of the emitting of Partiocle. This could be usefull if you need
*   special Particle-Emitter-Types (e.g. a Ring or a Sphere or whatever you want.
*   The Callback-Function gets three Parameter, a Pointer to a IRR_SPARTICLE-Structure.
*   The function fills them out, and return #True if the Particle should be added. Then
*   the amount to emit, and the actual number of the emitting-loop.
* EXAMPLE
*   ProcedureCDLL  emitterCallback(*particle.IRR_SPARTICLE, amount.l, number.l)
*       ... modify or set Particle
*       ... amount ist the overall count of Particles
*       ... number is the actual number of this Particle
*       ProcedureReturn #True
*   EndProcedure
*
*   *emitter.l = IrrAddParticleCallbackEmitter(*ps,@prop,@emitterCallback())
*
* RESULT
*    A pointer to a Emitter.
*
* NOTES
*   At the moment is this Feature untested ! Use it with Care !!!
*
* HISTORY
*   Added in Version 1.05 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleCallbackEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, *callbackfunction.l)



STATIC_EXPORT void * DLL_EXPORT IrrAddParticleCallbackEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER* prop, ParticleEmitterCallbackPtr callback )
{

    IParticleEmitter* em = new CCallbackParticleEmitter(
        callback,
        core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
		prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
		video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
		video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
		prop->min_lifetime,prop->max_lifetime,
		prop->max_angle_degrees );
	ps->setEmitter(em);
	em->drop();
	return (void *)em;

}

*/

/****f* Particles/IrrAddParticleRingEmitter
* NAME
*    IrrAddParticleRingEmitter - Add a Ring-Particle-Emitter
* SYNOPSIS
*    *emitter.l = IrrAddParticleRingEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f, thickness.f)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   *properties.l       - a Pointer to Structure, where the Emitter-Properties are stored (IRR_PARTICLE_EMITTER)
*   center_x,y,z.f      - center of the Ring
*   radius.f            - radius of the Ring
*   thickness.f         - thickness of the Ring
* FUNCTION
*   Adds a Emitter to the ParticleSystem.
*   You have to fill the Structure IRR_PARTICLE_EMITTER to define the behavior of the Emitter.
*   (This is while it s are too many Parameters to make it as parameters)
* RESULT
*    A pointer to a Emitter.
*
* NOTES
*   This Emitter is Taken from the Spintz-Engine (based on Irrlicht)
*
* HISTORY
*   Added in Version 1.06 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleRingEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f, thickness.f)
*/


STATIC_EXPORT void * DLL_EXPORT IrrAddParticleRingEmitter( IParticleSystemSceneNode* ps,
                                        IRR_PARTICLE_EMITTER* prop,
                                        f32 center_x,f32 center_y,f32 center_z,
                                        f32 radius,
                                        f32 ringThickness )
{

    IParticleEmitter* em = ps->createRingEmitter( //new CParticleRingEmitter(
            vector3df(center_x, center_y, center_z),
            radius, ringThickness,
            core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
            prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
            video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
            video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
            prop->min_lifetime,prop->max_lifetime,
            prop->max_angle_degrees );
    if (em!= NULL && ps != NULL)
    {
        ps->setEmitter(em);
        em->drop();
        return (void *)em;
    }
    return NULL;
}


/****f* Particles/IrrAddParticleCylinderEmitter
* NAME
*    IrrAddParticleCylinderEmitter - Add a Cylinder-Particle-Emitter
* SYNOPSIS
*    *emitter.l = IrrAddParticleCylinderEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f, normal_x.f, normal_y.f, normal_z.f, outlineOnly.l)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   *properties.l       - a Pointer to Structure, where the Emitter-Properties are stored (IRR_PARTICLE_EMITTER)
*   center_x,y,z.f      - center of the Cylinder
*   radius.f            - radius of the Cylinder
*   normal_x,y,z.f      - normals of the Cylinder
*   oulineOnly.l        - (boolean)
* FUNCTION
*   Adds a Emitter to the ParticleSystem.
*   You have to fill the Structure IRR_PARTICLE_EMITTER to define the behavior of the Emitter.
*   (This is while it s are too many Parameters to make it as parameters)
* RESULT
*    A pointer to a Emitter.
*
* HISTORY
*   Added in Version 1.06 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleCylinderEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f, normal_x.f, normal_y.f, normal_z.f, length.f, outlineOnly.l)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddParticleCylinderEmitter( IParticleSystemSceneNode* ps,
                                        IRR_PARTICLE_EMITTER* prop,
                                        f32 center_x,f32 center_y,f32 center_z,
                                        f32 radius,
                                        f32 normal_x, f32 normal_y, f32 normal_z,
                                        f32 length,
                                        bool outlineOnly
                                    )
{

    IParticleEmitter* em = ps->createCylinderEmitter( //new CParticleRingEmitter(
            vector3df(center_x, center_y, center_z),
            radius,
            vector3df(normal_x, normal_y, normal_z),
            length,
            outlineOnly,
            core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
            prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
            video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
            video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
            prop->min_lifetime,prop->max_lifetime,
            prop->max_angle_degrees );
    if (em!= NULL && ps != NULL)
    {
        ps->setEmitter(em);
        em->drop();
        return (void *)em;
    }
    return NULL;
}



/****f* Particles/IrrAddParticleSphereEmitter
* NAME
*    IrrAddParticleSphereEmitter - Add a Sphere-Particle-Emitter
* SYNOPSIS
*    *emitter.l = IrrAddParticleSphereEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle-System (Object)
*   *properties.l       - a Pointer to Structure, where the Emitter-Properties are stored (IRR_PARTICLE_EMITTER)
*   center_x,y,z.f      - center of the Sphere
*   radius.f            - radius of the Sphere
* FUNCTION
*   Adds a Emitter to the ParticleSystem.
*   You have to fill the Structure IRR_PARTICLE_EMITTER to define the behavior of the Emitter.
*   (This is while it s are too many Parameters to make it as parameters)
* RESULT
*    A pointer to a Emitter.
* NOTES
*   This Emitter is Taken from the Spintz-Engine (based on Irrlicht)
* HISTORY
*   Added in Version 1.06 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleSphereEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddParticleSphereEmitter( IParticleSystemSceneNode* ps,
                                        IRR_PARTICLE_EMITTER* prop,
                                        f32 center_x,f32 center_y,f32 center_z,
                                        f32 radius )
{

    IParticleEmitter* em = ps->createSphereEmitter( //new CParticleSphereEmitter(
            vector3df(center_x, center_y, center_z),
            radius,
            core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
            prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
            video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
            video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
            prop->min_lifetime,prop->max_lifetime,
            prop->max_angle_degrees );
    if (em!= NULL && ps != NULL)
    {
        ps->setEmitter(em);
        em->drop();
        return (void *)em;
    }
    return NULL;
}




/****f* Particles/IrrAddRotationParticleAffector
* NAME
*    IrrAddRotationParticleAffector - Add an affector to rotate the particle around a pivot
* SYNOPSIS
*    *affector.l = IrrAddStopParticleAffector(*particleSystem.l, speedX.f,speedY.f,speedZ.f, pivotX.f, pivotY.f, pivotZ.f)
* INPUTS
*   *particleSystem.l   - a Pointer to a Particle System (Object)
*   speedY.f,SpeedY.f,speedZ.f - Speed and direction
*   pivotX.f,pivotY.f,pivotZ.f - Pivot-Point
* FUNCTION
*   Rotates the Particles around a point
* RESULT
*    A pointer to a Affector.
*
* HISTORY
*   Added in Version 1.06 by M.Taupitz
*
* NOTES
*   This Affector is Taken from the Spintz-Engine (based on Irrlicht)
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddRotationParticleAffector(*particleSystem.l, speedX.f,speedY.f,speedZ.f, pivotX.f, pivotY.f, pivotZ.f)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddRotationParticleAffector( IParticleSystemSceneNode* ps,
                                                                            f32 speedX, f32 speedY, f32 speedZ,
                                                                            f32 pivotX, f32 pivotY, f32 pivotZ
                                                                            )
{



	IParticleAffector* paf = ps->createRotationAffector( //new CParticleRotationAffector(
                            vector3df(speedY,speedY,speedZ), vector3df(pivotX,pivotY,pivotZ));
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddCollisionParticleAffector(*particleSystem.l, planeX.f, planeY.f, planeZ.f, normalX.f, normalY.f, normalZ.f)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddCollisionParticleAffector( IParticleSystemSceneNode* ps,
                                                                            f32 planeX, f32 planeY, f32 planeZ,
                                                                            f32 normalX, f32 normalY, f32 normalZ
                                                                         )
{



	IParticleAffector* paf = new CParticleCollisionAffector(plane3df(planeX,planeY,planeZ, normalX, normalY,normalZ));
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}


/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
# PBIMPORT:IrrRingAffectorSetRadius(*affector, newRadius.f,)
*/
STATIC_EXPORT void DLL_EXPORT IrrRingEmitterSetRadius( IParticleRingEmitter* af,
                                                                            f32 newRadius)
{
    if (af)
        af->setRadius(newRadius);
}

STATIC_EXPORT void DLL_EXPORT IrrRingEmitterGetRadius( IParticleRingEmitter* af,
                                                                            f32 &radius)
{
    if (af)
        radius = af->getRadius();
}


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
# PBIMPORT:IrrAddParticleMeshEmitter(*particlesystem,*properties.IRR_PARTICLE_EMITTER, *mesh,  everyMeshVertex.l=#False)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddParticleMeshEmitter( IParticleSystemSceneNode* ps,
                                        IRR_PARTICLE_EMITTER* prop,
                                        IMesh* mesh,
                                        bool everyMeshVertex
                                        )
{

    IParticleEmitter* em = ps->createMeshEmitter(
            mesh,
            true,
            core::vector3df(prop->direction_x,prop->direction_y,prop->direction_z),
            100.0f,
            -1,
            everyMeshVertex,
            prop->min_paritlcles_per_second,prop->max_paritlcles_per_second,
            video::SColor(0,prop->min_start_color_red,prop->min_start_color_green,prop->min_start_color_blue),
            video::SColor(0,prop->max_start_color_red,prop->max_start_color_green,prop->max_start_color_blue),
            prop->min_lifetime,prop->max_lifetime,
            prop->max_angle_degrees );


    if (em!= NULL && ps != NULL)
    {
        ps->setEmitter(em);
        em->drop();
        return (void *)em;
    }
    return NULL;
}




STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddSpinParticleAffector( IParticleSystemSceneNode* ps,
                                                                            f32 speed)
{



	IParticleAffector* paf = new CParticleSpinAffector(speed);
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddAttractionParticleAffector(*particlesystem, pointX.f, pointY.f, pointZ.f, speed.f, attract.l, affectX.l, affectY.l, affectZ.l)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddAttractionParticleAffector( IParticleSystemSceneNode* ps,
                                                                                f32 pX, f32 pY, f32 pZ,
                                                                                f32 speed, bool attract,
                                                                                bool affectX, bool affectY, bool affectZ)
{

	IParticleAffector* paf = ps->createAttractionAffector( //new CParticleAttractionAffector(
                                    vector3df(pX,pY,pZ), speed, attract, affectX, affectY, affectZ);
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}

/*
	virtual IParticleAttractionAffector* createAttractionAffector(
		const core::vector3df& point, f32 speed = 1.0f, bool attract = true,
		bool affectX = true, bool affectY = true, bool affectZ = true) = 0;
*/


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddAlignParticleAffector(*particlesystem, offset.f)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddAlignParticleAffector( IParticleSystemSceneNode* ps, f32 offset)
{

	IParticleAffector* paf = new CParticleAlignAffector(offset);
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddScaleParticleAffector(*particlesystem, scaleTo.f)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddScaleParticleAffector( IParticleSystemSceneNode* ps, f32 scaleTo)
{

	IParticleAffector* paf = new CParticleScaleAffector(scaleTo);
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}


/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddBounceParticleAffector(*particleSystem.l, planeX.f, planeY.f, planeZ.f, normalX.f, normalY.f, normalZ.f, bounce.f)
*/
STATIC_EXPORT IParticleAffector* DLL_EXPORT IrrAddBounceParticleAffector( IParticleSystemSceneNode* ps,
                                                                            f32 planeX, f32 planeY, f32 planeZ,
                                                                            f32 normalX, f32 normalY, f32 normalZ,
                                                                            f32 bounce
                                                                         )
{

	IParticleAffector* paf = new CParticleBounceAffector(ps, smgr, plane3df(planeX,planeY,planeZ, normalX, normalY,normalZ),bounce);
	if (paf != NULL && ps != NULL)
    {
        ps->addAffector(paf);
        paf->drop();
        return paf;
    }
    return NULL;
}







/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrCreateParticleSystemExt(*emitter, delay_min.l, delay_max.l, rotate_min.f, rotate_max.f, scale_min.f, sclae_max.f, weight_min.f, weight_max.f, init_delay.l, rotate_speed_min.f, rotate_speed_max.f)
*/

STATIC_EXPORT void* DLL_EXPORT IrrCreateParticleSystemExt( IParticleEmitter* emitter,u32 delay_min , u32 delay_max ,f32 rotate_min, f32 rotate_max ,
                                                            f32 scale_min, f32 scale_max, f32 weight_min, f32 weight_max, u32 init_delay, f32 rotate_speed_min, f32 rotate_speed_max)
{
	IParticleSystemExtSceneNode* psext = smgr->addParticleSystemExtSceneNode(false);

    if (psext)
    {
        psext->setInitialDelay(init_delay);
        psext->setScaleRange(scale_min,scale_max);
        psext->setRotationRange(rotate_min,rotate_max);
        psext->setRotationSpeedRange(rotate_speed_min,rotate_speed_max);
        psext->setWeightRange(weight_min,weight_max);
        psext->setEmitterDelayTimes(delay_min,delay_max);
        psext->setEmitter(emitter);
    }
    return (void*)psext;



/*
    virtual void setInitialDelay(u32 delay_time);

    virtual const IParticleEmitter* getEmitter();

    virtual void setScaleRange(f32 scale_min, f32 scale_max);

    virtual void setRotationRange(f32 rotate_min, f32 rotate_max);

    virtual void setRotationSpeedRange(f32 rotate_speed_min, f32 rotate_speed_max);

    virtual void setWeightRange(f32 weight_min, f32 weight_max);

    virtual void setEmitterDelayTimes(u32 delay_time_min, u32 delay_time_max);

    */
/*
    IParticleEmitter* em = new CParticleEmitterManager(emitter, delay_min, delay_max,
                                                            rotate_min, rotate_max,
                                                            scale_min, scale_max,
                                                            weight_min, weight_max,
                                                            init_delay,  rotate_speed_min,  rotate_speed_max);
    return em;
*/
}




/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetInitalDelay(*particlesystemext,initial_dealy.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetInitalDelay( IParticleSystemExtSceneNode* psext, u32 initial_delay)
{
    if (psext)
        psext->setInitialDelay(initial_delay);
}


/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetScaleRange(*particlesystemext,scale_min.f, scale_max.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetScaleRange( IParticleSystemExtSceneNode* psext, f32 scale_min, f32 scale_max)
{
    if (psext)
        psext->setScaleRange(scale_min,scale_max);
}

/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetRotationRange(*particlesystemext,rotate_min.f, rotate_max.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetRotationRange( IParticleSystemExtSceneNode* psext, f32 rotate_min, f32 rotate_max)
{
    if (psext)
        psext->setRotationRange(rotate_min,rotate_max);
}

/**
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetRotationSpeedRange(*particlesystemext,rotate_speed_min.f, rotate_speed_max.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetRotationSpeedRange( IParticleSystemExtSceneNode* psext, f32 rotate_speed_min, f32 rotate_speed_max)
{
    if (psext)
        psext->setRotationSpeedRange(rotate_speed_min,rotate_speed_max);
}

/*
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetWeightRange(*particlesystemext,weight_min.f, weight_max.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetWeightRange( IParticleSystemExtSceneNode* psext, f32 weight_min, f32 weight_max)
{
    if (psext)
        psext->setWeightRange(weight_min,weight_max);
}

/*
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrPSExtSetEmitterDelayTimes(*particlesystemext,delay_min.l, delay_max.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrPSExtSetEmitterDelayTimes( IParticleSystemExtSceneNode* psext, u32 delay_min, u32 delay_max)
{
    if (psext)
        psext->setEmitterDelayTimes(delay_min,delay_max);
}




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