/Richter/Sprite.py
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
from Numeric import array

from util import *
import TexMan

LEFT = -1
BOTTOM = -1
CENTER = 0
RIGHT = 1
TOP = 1

class Sprite:
	frames = None
	frameno = 0
	animating = False
	anim_t = 0
	size = (0,0)
	displaylists = None

	showup = False
	showhitbox = False

	def __init__(self, file, position=(0,0), scale=1.0, rotation=0,
		     mirror=False, flip=False, color=(1.0,1.0,1.0,1.0),
		     framerate=0.0, gravity=(LEFT,BOTTOM)):

		self.frames = []
		d = None
		if type(file) == type([]):
			d = TexMan.load(file[0])
			self.frames.append(d['texture'])
			for f in file[1:]:
				self.frames.append(TexMan.load(f)['texture'])
		else:
			d = TexMan.load(file)
			self.frames.append(d['texture'])
		self.size = d['size']
		self.tsize = d['tsize']

		self.rotation = rotation
		self.mirror = mirror
		self.flip = flip
		self.color = color
		self.setFramerate(framerate)
		self.scale = scale
		self.position = position
		self.gravity = gravity

		self.fixHitbox()
		self.gen_displaylist()


	def gen_displaylist(self):
		if self.displaylists == None:
			n = glGenLists(len(self.frames))
			self.displaylists = range(n,n+len(self.frames))
		c = [0,0]
		for i in range(0,2):
			if self.gravity[i] == LEFT:
				c[i] = 0
			elif self.gravity[i] == CENTER:
				c[i] = -self.size[i]/2
			elif self.gravity[i] == RIGHT:
				c[i] = -self.size[i]
			else:
				print "Invalid gravity:",x
				c[i] = 0
		if self.mirror:
			c[0] -= self.tsize[0] - self.size[0]
		if self.flip:
			c[1] -= self.tsize[1] - self.size[1]
		vertexarray = array(
			((c[0],c[1],0),(c[0]+self.tsize[0],c[1],0),
			 (c[0]+self.tsize[0],c[1]+self.tsize[1],0),
			 (c[0],c[1]+self.tsize[1],0))
		,'f')
		if self.flip and self.mirror:
			texcoordarray = array(
				((1.0,1.0),(0.0,1.0),(0.0,0.0),(1.0,0.0))
			,'f')
		elif self.flip:
			texcoordarray = array(
				((0.0,1.0),(1.0,1.0),(1.0,0.0),(0.0,0.0))
			,'f')
		elif self.mirror:
			texcoordarray = array(
				((1.0,0.0),(0.0,0.0),(0.0,1.0),(1.0,1.0))
			,'f')
		else:
			texcoordarray = array(
				((0.0,0.0),(1.0,0.0),(1.0,1.0),(0.0,1.0))
			,'f')
		index = array((0,1,2,3),'i')
		for i in range(0,len(self.frames)):
			glNewList(self.displaylists[i], GL_COMPILE)
			glEnable(GL_TEXTURE_2D)
			glBindTexture(GL_TEXTURE_2D, self.frames[i])
			glColor4fv(self.color)
			glVertexPointer(3, GL_FLOAT, 0, vertexarray)
			glTexCoordPointer(2, GL_FLOAT, 0, texcoordarray)
			glDrawArrays(GL_QUADS, 0, 4)
			glEndList()


	def setPosition(self, x, y):
		self.position = (x,y)
		self.hitbox.topleft = (x + self.hitbox_offset[0], y + self.hitbox_offset[1])


	def setColor(self, r, g, b, a = 1.0):
		self.color = (r,g,b,a)
		self.gen_displaylist()


	def setScale(self, scale):
		self.scale = scale
		self.fixHitbox()


	def fixHitbox(self):
		self.hitbox_offset = [0,0]
		for i in range(0,2):
			if self.gravity[i] == -1:
				self.hitbox_offset[i] = 0
			elif self.gravity[i] == 0:
				self.hitbox_offset[i] = -(self.size[i] * self.scale) / 2
			elif self.gravity[i] == 1:
				self.hitbox_offset[i] = -(self.size[i] * self.scale)
		self.hitbox = pygame.Rect((self.position[0] + self.hitbox_offset[0], self.position[1] + self.hitbox_offset[1]), (self.size[0] * self.scale, self.size[1] * self.scale))


	def setGravity(self, xg, yg, genlist=True):
		if self.gravity != (xg,yg):
			self.gravity = (xg,yg)
			if genlist:
				self.gen_displaylist()
			self.fixHitbox()
		

	def setFramerate(self, rate):
		self.framerate = rate
		if self.framerate != 0.0:
			self.anim_period = int(1000/rate)
			if self.anim_t == 0:
				self.reset()
		else:
			self.stop()


	def reset(self):
		self.anim_t = pygame.time.get_ticks()
		self.frameno = 0


	def play(self):
		if len(self.frames) > 1:
			self.animating = True


	def stop(self):
		self.animating = False


	def draw(self):
		self.drawAt(self.position)


	def drawAt(self,pos):
		if self.animating:
			now = pygame.time.get_ticks()
			dt = now - self.anim_t
			if dt > self.anim_period:
				self.frameno = (self.frameno + int(dt / self.anim_period)) % len(self.frames)
				self.anim_t = now
		glPushMatrix()
		glTranslatef(pos[0], pos[1], 0.0)
		if self.rotation != 0:
			glRotatef(self.rotation, 0.0, 0.0, -1.0)
		if self.scale != 1.0:
			glScalef(self.scale, self.scale, 1.0)
		glCallList(self.displaylists[self.frameno])
		if self.showup:
			glDisable(GL_TEXTURE_2D)
			glColor3f(0.0, 0.0, 1.0)
			glBegin(GL_TRIANGLES)
			glVertex(-5, 0, 0)
			glVertex(0, 20, 0)
			glVertex(5, 0, 0)
			glEnd()
		glPopMatrix()
		if self.showhitbox:
			glDisable(GL_TEXTURE_2D)
			glColor3f(1.0, 1.0, 1.0)
			glBegin(GL_LINE_LOOP)
			glVertex(self.hitbox.left, self.hitbox.bottom, 0)
			glVertex(self.hitbox.left, self.hitbox.top, 0)
			glVertex(self.hitbox.right, self.hitbox.top, 0)
			glVertex(self.hitbox.right, self.hitbox.bottom, 0)
			glEnd()