# Author: Kwasi Mensah (kmensah@andrew.cmu.edu)
# Date: 8/02/2005
#
# This is meant to be a simple example of how to draw a cube
# using Panda's new Geom Interface. Quads arent directly supported 
# since they get broken down to trianlges anyway.
#

from direct.directbase import DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
from panda3d.core import lookAt
from panda3d.core import PerspectiveLens
from panda3d.core import CardMaker
from panda3d.core import Fog
from panda3d.core import Light, Spotlight, DirectionalLight, AmbientLight, PointLight
from panda3d.core import TextNode
from panda3d.core import Geom, GeomTriangles, GeomVertexWriter
from panda3d.core import GeomVertexFormat, GeomVertexData
from panda3d.core import Vec3, Vec4, Point3,BitMask32
from panda3d.core import Texture, GeomNode

from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay


import sys, os, time
from blocks import Cube
import terrain
import octree


#base.disableMouse()
base.camera.setPos(0, -30, 0)

title = OnscreenText(text="Panda 3d Cube world demo",
		   style=1, fg=(1,1,1,1),
		   pos=(0.5,-0.95), scale = .07)
escapeEvent = OnscreenText( 
 			 text="2: Turn on light",
 			 style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
			 align=TextNode.ALeft, scale = .05)
spaceEvent = OnscreenText( 
 			 text="d: Toggle Delete mode",
 			 style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
			 align=TextNode.ALeft, scale = .05)
upDownEvent = OnscreenText( 
 			 text="Mouse1: Delete cube",
 			 style=1, fg=(1,1,1,1), pos=(-1.3, 0.85),
			 align=TextNode.ALeft, scale = .05)
upDownEvent = OnscreenText( 
 			 text="f: Toggle Fog",
 			 style=1, fg=(1,1,1,1), pos=(-1.3, 0.80),
			 align=TextNode.ALeft, scale = .05)


#cube = Cube(0,0,0,'grass')
#cube2 = Cube(0,0,1,'grass')
#ube3 = Cube(0,0,2,'grass')
#ube4 = Cube(0,0,3,'metal')


#cubes.append(cube)
#cubes.append(cube2)

class MyTapper(DirectObject):
	def __init__(self):
		self.gs = 32
		self.buttons = {'zoom':0}
		self.testTexture=loader.loadTexture("maps/envir-reeds.png")
		#self.accept("1", self.toggleTex)
		self.accept("2", self.toggleLights)
		self.accept("d", self.delnode)
		self.accept("f", self.toggleFog)
		self.fog = False
		self.myfog = Fog("mainfog")
		self.myfog.setColor(.8,.8,.8)
		self.myfog.setExpDensity(.05)


		self.deltoggle = False


		self.accept("+", self.setKey, ['zoom',1])
		self.accept("+-up", self.setKey, ['zoom',0])
		self.accept("-", self.setKey, ['zoom',-1])
		self.accept("--up", self.setKey, ['zoom',0])
		self.accept("mouse1", self.deletehighlighted)
		
		self.LightsOn=False

		self.dlight = PointLight('dlight')
		self.dlight.setColor(Vec4(.8,.8,.5,1))
		#self.dlight.setShadowCaster(True, self.gs,self.gs)
		self.dlnp = render.attachNewNode(self.dlight)
		#self.dlnp.setHpr(-60,-60,0)
		self.dlnp.setPos(0,100,100)
		

		ambientLight = AmbientLight( "ambientLight" )
		ambientLight.setColor( Vec4(.4, .4, .4, 1) )
		render.setLight(render.attachNewNode(ambientLight))

		self.gameTask = taskMgr.add(self.gameLoop, "gameloop")
		self.gameTask.last = 0
		
		#mouse stuff

		#any other collision detection system with a traverser and a handler
		self.picker = CollisionTraverser()            #Make a traverser
		self.pq     = CollisionHandlerQueue()         #Make a handler
		#Make a collision node for our picker ray
		self.pickerNode = CollisionNode('mouseRay')
		#Attach that node to the camera since the ray will need to be positioned
		#relative to it
		self.pickerNP = camera.attachNewNode(self.pickerNode)
		#Everything to be picked will use bit 1. This way if we were doing other
		#collision we could seperate it
		self.pickerNode.setFromCollideMask(BitMask32.bit(1))
		self.pickerRay = CollisionRay()               #Make our ray
		self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
		#Register the ray as something that can cause collisions
		self.picker.addCollider(self.pickerNP, self.pq)
		#self.picker.showCollisions(render)
		self.highlighted = None


		self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')

		print "Generating Terrain..."
		ter = terrain.gen(self.gs,self.gs,32)
		self.cubes = []
		i = 0
		l = len(ter)
		treesize = self.gs*self.gs*32
		self.otree = octree.Octree(treesize)

		for blk in ter:
			print "\r %.2f%% done making blocks" % (1.0*i/l),
			i+= 1
			c = Cube(*blk)
			c.settree(self.otree)
			self.otree.insert(c.position,c)
			self.cubes.append(c)

		self.cubeRoot = render.attachNewNode("cubeRoot")

		i = 0
		for c in self.cubes:
			print "\r %.2f%% done riticulating splines" % (1.0*i/l),
			i+= 1
			result = c.checkneighbors()
			if result:
				c.show(self.cubeRoot)





	def delnode(self):
		self.deltoggle = not self.deltoggle

	def setKey(self,key,val): self.buttons[key] = val

	def zoom(self,time,mult=10):
		if self.buttons['zoom']:
			delta = (0,self.buttons['zoom']*time*mult,0)
			base.camera.setPos(base.camera.getPos() + delta)

	def toggleLights(self):
		self.LightsOn=not(self.LightsOn)
		
		if self.LightsOn:
			#render.setShaderAuto()
			render.setLight(self.dlnp)
		else:
			render.setLightOff(self.dlnp)


	def toggleFog(self):
		self.fog = not(self.fog)
		
		if self.fog:
			render.setFog(self.myfog)
		else:
			render.clearFog()



	def gameLoop(self,task):
		dt = task.time - task.last
		task.last = task.time
		self.zoom(dt)
		return task.cont

	def mouseTask(self,task):

		if base.mouseWatcherNode.hasMouse():
			mpos = base.mouseWatcherNode.getMouse()
			self.pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
			self.picker.traverse(self.cubeRoot)
			if self.pq.getNumEntries() > 0:
				self.pq.sortEntries()
				entry = self.pq.getEntry(0)
				#print dir(entry)
				#entry.getIntoNodePath().getParent().setColor(HIGHLIGHTCOLOR)
				(x,y,z) = entry.getIntoNodePath().getParent().getPos()
				c = self.otree.search((x, y, z))
				if c:
					if self.highlighted != c:
						if self.highlighted:
							self.highlighted.dehighlight()
						self.highlighted = c
						c.highlight()
		if self.deltoggle and self.highlighted:
			self.deletehighlighted()

		return task.cont
		
	def deletehighlighted(self):
		if self.highlighted:
			self.highlighted.dehighlight()
			self.highlighted.remove()
			self.highlighted = None

		
			
			

t=MyTapper()

run()





