# Author: Shao Zhang and Phil Saltzman
# Last Updated: 4/20/2005
#
# This tutorial shows how to take an existing particle effect taken from a
# .ptf file and run it in a general Panda project. See readme.txt for more
# information on creating particle effects

import direct.directbase.DirectStart
from pandac.PandaModules import BaseParticleEmitter,BaseParticleRenderer
from pandac.PandaModules import PointParticleFactory,SpriteParticleRenderer
from pandac.PandaModules import LinearNoiseForce,DiscEmitter
from pandac.PandaModules import LightAttrib,TextNode
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import Point3,Vec3,Vec4
from direct.particles.Particles import Particles
from direct.particles.ParticleEffect import ParticleEffect
from direct.particles.ForceGroup import ForceGroup
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import sys

class World(DirectObject):
	def __init__(self):
    #Standard title and instruction text
		self.title = OnscreenText(
      text="Panda3D: Tutorial - Particles",
      style=1, fg=(1,1,1,1), pos=(0.9,-0.95), scale = .07)
		self.escapeEvent = OnscreenText(
			text="ESC: Quit",
			style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
			align=TextNode.ALeft, scale = .05)

    #More standard initialization
		self.accept('escape', sys.exit)
		base.disableMouse()
		camera.setPos(0,-20,2)
		base.setBackgroundColor( 0, 0, 0 )

		#This command is required for Panda to render particles
		base.enableParticles()
		
		self.t = loader.loadModel("models/teapot")
		self.t.setPos(0,10,0)
		self.t.reparentTo(render)

		self.setupLights()

		###Start of the code from steam.ptf
    #This first line was added to create the particle effect. p changed to
    #self.p in the following lines to match
		self.p = ParticleEffect() 
		self.p.reset()
    #These positions were modified to line up with the spout of the teapot
		self.p.setPos(3.000, 0.000, 2.250)
		self.p.setHpr(0.000, 0.000, 0.000)
		self.p.setScale(1.000, 1.000, 1.000)
		p0 = Particles('particles-1')
		# Particles parameters
		p0.setFactory("PointParticleFactory")
		p0.setRenderer("SpriteParticleRenderer")
		p0.setEmitter("DiscEmitter")
		p0.setPoolSize(10000)
		p0.setBirthRate(0.2500)
		p0.setLitterSize(20)
		p0.setLitterSpread(0)
		p0.setSystemLifespan(0.0000)
		p0.setLocalVelocityFlag(1)
		p0.setSystemGrowsOlderFlag(0)
		# Factory parameters
		p0.factory.setLifespanBase(8.0000)
		p0.factory.setLifespanSpread(0.0000)
		p0.factory.setMassBase(1.0000)
		p0.factory.setMassSpread(0.0000)
		p0.factory.setTerminalVelocityBase(400.0000)
		p0.factory.setTerminalVelocitySpread(0.0000)
		# Point factory parameters
		# Renderer parameters
		p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT)
		p0.renderer.setUserAlpha(0.10)
		# Sprite parameters
    ###'steam' changed to 'steam.png' in the ptf because the panel does not
    ###export texture names correctly
		p0.renderer.setTexture(loader.loadTexture('steam.png'))
		p0.renderer.setColor(Vec4(1.00, 1.00, 1.00, 1.00))
		p0.renderer.setXScaleFlag(1)
		p0.renderer.setYScaleFlag(1)
		p0.renderer.setAnimAngleFlag(0)
		p0.renderer.setInitialXScale(0.0025)
		p0.renderer.setFinalXScale(0.0400)
		p0.renderer.setInitialYScale(0.0025)
		p0.renderer.setFinalYScale(0.0400)
		p0.renderer.setNonanimatedTheta(0.0000)
		p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PPNOBLEND)
		p0.renderer.setAlphaDisable(0)
		# Emitter parameters
		p0.emitter.setEmissionType(BaseParticleEmitter.ETEXPLICIT)
		p0.emitter.setAmplitude(1.0000)
		p0.emitter.setAmplitudeSpread(0.7500)
		p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 1.0000))
		p0.emitter.setExplicitLaunchVector(Vec3(0.0000, 0.0000, 0.0000))
		p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000))
		# Disc parameters
		p0.emitter.setRadius(0.1)
		self.p.addParticles(p0)
		f0 = ForceGroup('vertex')
		# Force parameters
		force0 = LinearNoiseForce(0.1500, 0)
		force0.setActive(1)
    ###Added because the panel forgot to export it
		force0.setVectorMasks(True, True, False) 
		f0.addForce(force0)
		self.p.addForceGroup(f0)

    ##Start the particle system above
		#sets particles to birth relative to the teapot, but to render at toplevel
		self.p.start(self.t)

	#Setup lighting
	def setupLights(self):
		lAttrib = LightAttrib.makeAllOff()
		ambientLight = AmbientLight( "ambientLight" )
		ambientLight.setColor( Vec4(.4, .4, .35, 1) )
		lAttrib = lAttrib.addLight( ambientLight )
		directionalLight = DirectionalLight( "directionalLight" )
		directionalLight.setDirection( Vec3( 0, 8, -2.5 ) )
		directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) )
		lAttrib = lAttrib.addLight( directionalLight )
		#set lighting on teapot so steam doesn't get affected
		self.t.attachNewNode( directionalLight.upcastToPandaNode() ) 
		self.t.attachNewNode( ambientLight.upcastToPandaNode() ) 
		self.t.node().setAttrib( lAttrib )

w = World()
run()

		
		
	

