;; ----------------------------------------------------------------------------
;; Irrlicht Wrapper For Imperative Languages - Purebasic Examples
;; IrrlichtWrapper and FreeBasic-Example by Frank Dodd (2006)
;; Improved IrrlichtWrapper - Michael Taupitz (2007)
;; PureBasic-Examples by Michael Taupitz (neotoma) & Marius Eckardt (Thalius) 
;; ----------------------------------------------------------------------------
;; Example 07: Particle System
;; This example creates a couple of simple particle systems To demonstrate
;; particle system effects
;; ----------------------------------------------------------------------------

;; ////////////////////////////////////////////////////////////////////////////
;; Include the Irr3D-Requester
XIncludeFile #PB_Compiler_Home + "Includes\IrrlichtWrapper_Include.pbi"


;EnableExplicit

;; ////////////////////////////////////////////////////////////////////////////
;; Global variables

Enumeration 
  #IRR_PART_PREMADE_DEFAULT
  #IRR_PART_PREMADE_RAIN 
EndEnumeration  
  
  
Enumeration  
  #IRR_EMITTERTYPE_POINT  
  #IRR_EMITTERTYPE_BOX  
  #IRR_EMITTERTYPE_RING
  #IRR_EMITTERTYPE_SPHERE
  #IRR_EMITTERTYPE_CYLINDER
  #IRR_EMITTERTYPE_MESH
EndEnumeration  
  
    
Structure sExtendedEmitter Extends IRR_PARTICLE_EMITTER
  emittertype.l
  
  delay_min.l         ;delay between emittings
  delay_max.l

  rotate_min.f        ;random start-rotation
  rotate_max.f

  rotate_speed_min.f  ;random rotationspeed
  rotate_speed_max.f

  scale_min.f         ;random scale
  scale_max.f

  weight_min.f        ;random weight
  weight_max.f        ;

  init_delay.f        ;initail delay befor the emitter starts
EndStructure 


Structure sGravityAffector
  gravity.IRR_VECTOR
  timeForceLost.l
EndStructure 

Structure sFadeoutAffector
  dummy.l
EndStructure 

Structure sCollisionAffector
  plane.IRR_VECTOR
  normal.IRR_VECTOR  
EndStructure 

Structure sAttractionAffector
  point.IRR_VECTOR
  speed.f
  attract.l     ;bool 
  affectX.l     ;bool 
  affectY.l     ;bool 
  affectZ.l     ;bool 
EndStructure 
  
Structure sRotationAffector
  speed.IRR_VECTOR
  point.IRR_VECTOR
EndStructure 

Structure sStopAffector
  when.l       ;when to stop emitting
EndStructure 

Structure sSpinAffector
  speed.l       ;
EndStructure 

Structure sAlignAffector  ;Align to Fall
  offset.f
EndStructure 

Structure sAffector
  affectortype.l
  StructureUnion
    gravity.sGravityAffector
    fadeout.sFadeoutAffector
    collision.sCollisionAffector
    attraction.sAttractionAffector
    rotation.sRotationAffector
    stop.sStopAffector
    spin.sSpinAffector
    align.sAlignAffector  
  EndStructureUnion
EndStructure

Structure sParticleSystem 
     
  emitter.sExtendedEmitter      

  sizex.f
  sizey.f      ; particle size   
  
  scalex.f
  scaley.f    ; .....    
  
  *material             ; material  
 
  center.IRR_VECTOR     ; used only by Ring and Sphere
  radius.f              ; radius used only by Ring and Sphere
  thickness.f           ; used only by Ring
  
  
  *mesh
  everyMeshVertex.l ; used only for MeshEmitter
  
  
  affectors.sAffector[10]  
  
 
EndStructure 

; Structure sParticleSytemBucket 
;   
; 
; EndStructure 


;;Structure sPParticle(


Procedure IrrParticlesSetBox(*p.sExtendedEmitter, min_x.f, min_y.f, min_z.f, max_x.f, max_y.f, max_z.f)
  With *p
    min_box_x = min_x
    min_box_y = min_y
    min_box_z = min_z

    max_box_x = max_x
    max_box_y = max_y
    max_box_z = max_z
  EndWith  
EndProcedure

Procedure IrrParticlesSetDirection(*p.sExtendedEmitter, x.f,y.f,z.f)
  With *p 
    direction_x = x
    direction_y = y
    direction_z = z
  EndWith
EndProcedure

Procedure IrrParticlesSetPPS(*p.sExtendedEmitter, min.l, max.l)
  With *p
    min_paritlcles_per_second = min
    max_paritlcles_per_second = max
  EndWith
EndProcedure

Procedure IrrParticlesSetMinColor(*p.sExtendedEmitter, r.l, g.l, b.l)
  With *p
    min_start_color_red = r
    min_start_color_green = g
    min_start_color_blue = b
  EndWith
EndProcedure

Procedure IrrParticlesSetMaxColor(*p.sExtendedEmitter, r.l, g.l, b.l)
  With *p
    max_start_color_red = r
    max_start_color_green = g
    max_start_color_blue = b
  EndWith
EndProcedure

Procedure IrrParticlesSetLifetime(*p.sExtendedEmitter, min.l, max.l)
  With *p
    min_lifetime = min
    max_lifetime = max
  EndWith
EndProcedure

Procedure IrrParticlesSetAngle(*p.sExtendedEmitter, max.f)
  With *p
    max_angle_degrees = max
  EndWith
EndProcedure






;  IrrAddParticleSphereEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f)
;   IrrAddParticleRingEmitter(*particleSystem.l, *properties.IRR_PARTICLE_EMITTER, center_x.f, center_y.f, center_z.f, radius.f, thickness.f)    
;   IrrAddParticleMeshEmitter(*particlesystem.l ,*properties.IRR_PARTICLE_EMITTER, *mesh.l ,  everyMeshVertex.l=#False)
; 
;   
;   IrrAddRotationParticleAffector(*particleSystem.l, speedX.f,speedY.f,speedZ.f, pivotX.f, pivotY.f, pivotZ.f)
; 
;   IrrAddCollisionParticleAffector(*particleSystem.l, planeX.f, planeY.f, planeZ.f, normalX.f, normalY.f, normalZ.f)


Procedure.l IrrParticlesCreate(premade.l = #IRR_PART_PREMADE_DEFAULT)
  




EndProcedure
  



; irrlicht objects
Define *ParticleTexture.irr_texture
Define *TestNodeTexture.irr_texture
Define SmokeParticles.irr_model
Define SmokeEmitter.IRR_PARTICLE_EMITTER
Define *ParticlesNode.irr_node
Define *TestNode.irr_node
Define *camera.irr_camera
Define *Particle.irr_node


Define *em.l  ; pointer to the Emitter


Procedure makeTheMeshEmitter()
  
Define MeshEmitter.IRR_PARTICLE_EMITTER  
  *Mesh = IrrGetMesh( "..\media\iw.ms3d" )
   *SceneNode = IrrAddMeshToScene( *Mesh )
; ; load a wall texture for our box
   *TestNodeTexture = IrrGetTexture( "..\media\wall.jpg" )
;   
;   ; apply the texture to the box
   IrrSetNodeMaterialTexture( *SceneNode, *TestNodeTexture, 0 )
  
  
  With MeshEmitter

    \min_box_x = -7
    \min_box_y = 0
    \min_box_z = -7
    \max_box_x = 7
    \max_box_y = 1
    \max_box_z = 7

    \direction_x = 0.0
    \direction_y = 0.2
    \direction_z = 0.0
    \min_paritlcles_per_second = 60
    \max_paritlcles_per_second = 60
    \min_start_color_red = 128
    \min_start_color_green = 128
    \min_start_color_blue = 128
    \max_start_color_red = 255
    \max_start_color_green = 255
    \max_start_color_blue = 255
    \min_lifetime = 1200
    \max_lifetime = 1200
    \max_angle_degrees = 0
   EndWith
  
  
  
  *pParticlesNode = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
   irrSetNodePosition(*pParticlesNode, 0,0,0)
   irrSetNodePosition(*SceneNode, 0,0,0)
   IrrSetNodeScale(*SceneNode,50,50,50)
   IrrSetNodeScale(*pParticlesNode,50,50,50)
  
  IrrSetParticleSize( *pParticlesNode, 15.0, 15.0 )  
  
  *pParticleTexture = IrrGetTexture( "..\media\Fire.bmp" )
  
  IrrSetNodeMaterialTexture( *pParticlesNode, *pParticleTexture, 0 )
  
  IrrSetNodeMaterialFlag( *pParticlesNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialFlag( *SceneNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  *staticMesh = IrrGetStaticFromMesh(*mesh)
  
  *em.l = IrrAddParticleMeshEmitter( *pParticlesNode, @MeshEmitter, *staticMesh, #False )
 IrrSetNodeMaterialType ( *pParticlesNode, #IRR_EMT_TRANSPARENT_ADD_COLOR  ) ; uncomment me... ;)
    
   IrrAddFadeOutParticleAffector( *pParticlesNode )
;   
;   IrrAddGravityParticleAffector ( *pParticlesNode, 0.00, -2.5, 0.0 )

;  IrrSetNodeAllMaterialEmissiveColor(*SceneNode,255,Random(255),Random(255),Random(255))
  IrrSetNodeAllMaterialEmissiveColor(*pParticlesNode,255,Random(255),Random(255),Random(255))

EndProcedure 


; -----------------------------------------------------------------------------
; To Start the Irrlicht-Device we use the Irr3DRequester, to make it more comfortable
; for the Users, and also easier to test different resolutions and devices.
 If  IrrStart( #IRR_EDT_DIRECT3D9, 640, 480, #IRR_WINDOWED, #IRR_NO_SHADOWS, #False)


  ; send the window caption
  IrrSetWindowCaption( "Example 07: Particle Systems" )
  
  ; this adds a small test node to the scene, a test node is a simple cube, that
  ; you can move and texture like any other object however there is another
  ; reason for adding this node. the particle system needs another node rendered
  ; onto the display to allow it to display material effects. this may be an issue
  ; with the wrapper that needs investigation
  *TestNode = IrrAddCubeSceneNode(10)
  
  ; load a wall texture for our box
  *TestNodeTexture = IrrGetTexture( "..\media\wall.jpg" )
  
  ; apply the texture to the box
  IrrSetNodeMaterialTexture( *TestNode, *TestNodeTexture, 0 )
  ; Switch Lighting off - as we have no lights in the scene anyway ..
  IrrSetNodeMaterialFlag( *TestNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  ; -*
  ; Exercise: Torchlike...
  ; This shows how Material flags affect the "Effect" of a Material
  ; Set our BoxNode Material to ADDITIVE Blending. 
  ; This will make the Smoke overdraw our Box : this Results in a "burn-like" Effect 
  ; for Example suitable for a Torch ( using the appropriate Textures and
  ; Emitter Settings for our Particles ). 
  ; Have fun! ;) ...
  ;
 IrrSetNodeMaterialType ( *TestNode, #IRR_EMT_TRANSPARENT_ADD_COLOR  ) ; uncomment me... ;)
  ; -*
  
  ; add a particle system to the irrlicht scene manager, a default emitter is not
  ; created as we will define out own. the particle system is blank at the moment
  *ParticlesNode = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  IrrSetParticleSize( *ParticlesNode, 15.0, 15.0 )
  
  ; here we define the particle emitter, a particle emitter is a mechanism that
  ; creates the particles over time and destroys them when their lifetime runs
  ; out. The parameters include: a box that defines the volume in which particles
  ; are created - the larger the box the more diffuse the particle cloud, a
  ; direction that determines where the particles drift off too, a range that
  ; defines hoe many particles will be generated each second, a colour range that
  ; determines a random tint that is applied to the particles, a range that
  ; determines the lifespan of the particles - the large the values the longer
  ; and larger (and slower) your particle cloud will be and finally an angle that 
  ; defines a cone around your direction that is the maximum deviation from the
  ; direction the particles can take - values here make your particles billow
  ; outward
  SmokeEmitter\min_box_x = -7
  SmokeEmitter\min_box_y = 0
  SmokeEmitter\min_box_z = -7
  SmokeEmitter\max_box_x = 7
  SmokeEmitter\max_box_y = 1
  SmokeEmitter\max_box_z = 7
  SmokeEmitter\direction_x = 0
  SmokeEmitter\direction_y = 0.06
  SmokeEmitter\direction_z = 0
  SmokeEmitter\min_paritlcles_per_second = 80
  SmokeEmitter\max_paritlcles_per_second = 100
  SmokeEmitter\min_start_color_red = 255
  SmokeEmitter\min_start_color_green = 255
  SmokeEmitter\min_start_color_blue = 255
  SmokeEmitter\max_start_color_red = 10
  SmokeEmitter\max_start_color_green = 12
  SmokeEmitter\max_start_color_blue = 14
  SmokeEmitter\min_lifetime = 800
  SmokeEmitter\max_lifetime = 2000
  SmokeEmitter\max_angle_degrees = 15
  
  ; finally we add this particle emitting object to the particle system
  *em.l = IrrAddParticleEmitter( *ParticlesNode, @SmokeEmitter )
  
  
  ; an affector is a mechanism that alters the particles over time, the fade out
  ; affector gradually fades the particles out so they are invisible when they
  ; are deleted this lets them smoothly vanish instead of poping out of existence
  IrrAddFadeOutParticleAffector( *ParticlesNode )
  
  ; another affector is the gravity affector, this adds a small amount of velocity
  ; to the particles each frame, although its called a gravity affector it can
  ; be used to push the particles in any direction so you can have drifting smoke
  ; bubbling fountains, etc ...
  IrrAddGravityParticleAffector ( *ParticlesNode, 0.05, 0.05, 0.0 )
  
  ; at the moment the particles are simple grey squares and before we apply a
  ; material to them we need to get the particle system as a scene node
  ;;ParticlesNode = SmokeParticles
  
  ; load a grey smoke like image for the particle
  *ParticleTexture = IrrGetTexture( "..\media\ParticleGrey.bmp" )
  
  ; apply the texture to the particles system, this texture will now be drawn
  ; across each particles surface
  IrrSetNodeMaterialTexture( *ParticlesNode, *ParticleTexture, 0 )
  
  ; out particle system is not affected by lighting so we make it self
  ; illuminating
  IrrSetNodeMaterialFlag( *ParticlesNode, #IRR_EMF_LIGHTING, #IRR_OFF )
  
  ; as the particle texture has black borders, each overlapping particle would
  ; draw this blackness ontop of one another as a sharp egde they would look like
  ; a lot of solid squares instead of the transparent gas effect we are trying
  ; to created. so here we change the material type of the node - instead of
  ; drawing the node solidly onto the screen it is added onto the colour
  ; underneath itself so black doesnt change the color and white would build up
  ; top of the existing color until it completly saturates the pixel
  IrrSetNodeMaterialType ( *ParticlesNode, #IRR_EMT_TRANSPARENT_ADD_COLOR  )
  
  IrrAddStopParticleAffector(*ParticlesNode, 1000)
  
  
  Define FireEmitter.IRR_PARTICLE_EMITTER

  ; add a particle system to the irrlicht scene manager, a default emitter is not
  ; created as we will define out own. the particle system is blank at the moment
  *Particle = IrrAddParticleSystemToScene( #IRR_NO_EMITTER )
  
  ; when the particle system starts it creates objects similar to billboards,
  ; this command specifies how large each of those particles will be
  IrrSetParticleSize( *Particle, 20.0, 20.0 )
  
  
  FireEmitter\min_box_x = -12
  FireEmitter\min_box_y = 0
  FireEmitter\min_box_z = -12
  FireEmitter\max_box_x = 12
  FireEmitter\max_box_y = 5
  FireEmitter\max_box_z = 12  


  FireEmitter\direction_x = 0.00
  FireEmitter\direction_y = 0.20
  FireEmitter\direction_z = 0.00
  FireEmitter\min_paritlcles_per_second = 100
  FireEmitter\max_paritlcles_per_second = 300
  FireEmitter\min_start_color_red = 255
  FireEmitter\min_start_color_green = 255
  FireEmitter\min_start_color_blue = 255
  FireEmitter\max_start_color_red = 0
  FireEmitter\max_start_color_green = 0
  FireEmitter\max_start_color_blue = 0
  FireEmitter\min_lifetime = 500
  FireEmitter\max_lifetime = 3000
  FireEmitter\max_angle_degrees = 25


; ring1ParticleSystem->createRingEmitter(
; 		center, 100.0f, 5.0f,
; 		core::vector3df( 0.0f, 0.0f, 0.0f ),
; 		800, 900,
; 		video::SColor( 0, 255, 255, 255 ), video::SColor( 0, 255, 255, 255 ),
; 		1500, 1500


; finally we add this particle emitting object to the particle system
; *em.l = IrrAddParticleRingEmitter( *Particle, @FireEmitter, 0,0,0, 100,20 )

*em = IrrAddParticleEmitter(*Particle, @FireEmitter);

 ; *em.l = IrrAddParticleSphereEmitter( *Particle, @FireEmitter, 0,0,0, 100 )

If *em = #Null
  Debug("Ring Problem")
EndIf

  IrrAddFadeOutParticleAffector( *Particle )
;  IrrAddRotationParticleAffector(*Particle, 50,0,0  ,0,0,0)
  IrrAddCollisionParticleAffector(*particle, 0,0.0,0, 0,1,0)
  IrrAddGravityParticleAffector ( *Particle, 0.00, -0.10, 0.00 )
  
  
  
  ; load a grey smoke like image for the particle
  *ParticleTexture = IrrGetTexture( "..\media\Fire.bmp" )
  IrrSetNodeMaterialTexture( *Particle, *ParticleTexture, 0 )
  IrrSetNodeMaterialFlag( *Particle, #IRR_EMF_LIGHTING, #IRR_OFF )
  IrrSetNodeMaterialType ( *Particle, #IRR_EMT_TRANSPARENT_ADD_COLOR  )


  IrrSetNodePosition( *Particle,0,00,0)

 IrrAddRotationAnimator( *Particle, 0, 0.1, 0 )

  makeTheMeshEmitter()
  

  IrrAddStopParticleAffector(*Particle, 1000)
  
  ; add a fixed position camera to the scene so we can view the particle system.
  ; the first three parameters are the cameras location, the second three
  ; parameters are where the camera is looking at
;  *camera = IrrAddCamera( 100,40,0, 0,40,0 )

  *camera = IrrAddFPSCamera()
  IrrSetNodePosition(*camera,100,40,0)
  
  ; -----------------------------------------------------------------------------
  ; while the irrlicht environment is still running
  While IrrRunning()
      ; clear the canvas to black to show the particles up better
      IrrBeginScene( 0, 0, 0 )
  
      ; draw the scene
      IrrDrawScene()
  
      ; end drawing the scene and display it
      IrrEndScene()
  Wend
  
  ; -----------------------------------------------------------------------------
  ; Stop the irrlicht engine and release resources
  IrrStop()
  
EndIf

End

; jaPBe Version=3.7.2.629
; Build=0
; FirstLine=23
; CursorPosition=44
; ExecutableFormat=Windows
; DontSaveDeclare
; IDE Options = PureBasic 4.10 Beta 3 (Windows - x86)
; ExecutableFormat = Console
; CursorPosition = 140
; FirstLine = 117
; Folding = --