# -*- coding: utf-8 -*-
"""
UTc! module: src.obstacles

Purpose
=======
 Provides resources for establishing in-game obstacles.
 
Legal
=====
 All code, unless otherwise indicated, is original, and subject to the
 terms of the GPLv3, which is provided in COPYING.
 
 (C) Neil Tallim, 2009
"""
import ode
import OpenGL.GL as GL

import gameobjects

import rendering.rendering as rendering

_SPHERE_POLY_CAP = 1000.0 #: The distance against which sphere polygon counts should be capped.

class _Obstacle(gameobjects.GameObject):
	"""
	An abstract representation of in-game obstacles.
	"""
	_colour = None #: The colour of this obstacle.
	_ode_geom = None #: The ODE geometry of this obstacle.
	
	def __init__(self, ode_space, position, rotation, colour):
		"""
		Initialises the ODE presence, position, rotation, and colour of this
		obstacle.
		
		@type ode_space: ode.SpaceBase
		@param ode_space: The ODE space in which this obstacle will reside.
		@type position: sequence(3)
		@param position: The (x, y, z) co-ordinates of this obstacle in game-space.
		@type rotation: sequence(3)|sequence(9)|None
		@param rotation: See L{src.gameobjects.GameObject.__init__}.
		@type colour: sequence(3)
		@param colour: The (r, g, b) colour of this obstacle.
		"""
		gameobjects.GameObject.__init__(self, rotation)
		self._colour = colour
		self.setPosition(position)
		self._setODE(ode_space)
		self._ode_geom.tank_chan = None
		self._ode_geom.parent = self
		self._ode_geom.setPosition(position)
		
	def render(self):
		"""
		Displays this obstacle in visual space, if it is logical to do so.
		"""
		if self._render:
			self._show()
			
class Box(_Obstacle):
	"""
	A representation of in-game box obstacles.
	"""
	_dimensions = None #: The dimensions of this box.
	
	def __init__(self, ode_space, position, rotation, dimensions, colour):
		"""
		Initialises the dimensions of this box.
		
		@type ode_space: ode.SpaceBase
		@param ode_space: The ODE space in which this obstacle will reside.
		@type position: sequence(3)
		@param position: The (x, y, z) co-ordinates of this obstacle in game-space.
		@type rotation: sequence(3)|sequence(9)|None
		@param rotation: See L{src.gameobjects.GameObject.__init__}.
		@type dimensions: sequence(3)
		@param dimensions: The (x, y, z) lengths of this box.
		@type colour: sequence(3)
		@param colour: The (r, g, b) colour of this obstacle.
		"""
		self._dimensions = dimensions
		_Obstacle.__init__(self, ode_space, position, rotation, colour)
		
	def _setODE(self, ode_space):
		"""
		Sets the ODE GeomBox that defines this box in game-space.
		
		@type ode_space: ode.SpaceBase
		@param ode_space: The ODE space in which this box will reside.
		"""
		self._ode_geom = ode.GeomBox(ode_space, self._dimensions)
		self._ode_geom.setRotation(self._rotation_matrix)
		
	def _show(self):
		"""
		Displays this box in visual space.
		"""
		GL.glPushMatrix()
		GL.glShadeModel(GL.GL_FLAT)
		rendering.renderCube((self._pos_x, self._pos_y, self._pos_z), self._rotation_matrix, self._dimensions, self._colour)
		GL.glPopMatrix()
		
class Sphere(_Obstacle):
	"""
	A representation of in-game sphere obstacles.
	"""
	_radius = None #: The rasius of this sphere.
	
	def __init__(self, ode_space, position, rotation, radius, colour):
		"""
		Initialises the radius of this sphere.
		
		@type ode_space: ode.SpaceBase
		@param ode_space: The ODE space in which this obstacle will reside.
		@type position: sequence(3)
		@param position: The (x, y, z) co-ordinates of this obstacle in game-space.
		@type rotation: sequence(3)|sequence(9)|None
		@param rotation: See L{src.gameobjects.GameObject.__init__}.
		@type radius: float
		@param radius: The radius of this sphere.
		@type colour: sequence(3)
		@param colour: The (r, g, b) colour of this obstacle.
		"""
		self._radius = radius
		_Obstacle.__init__(self, ode_space, position, rotation, colour)
		
	def _setODE(self, ode_space):
		"""
		Sets the ODE GeomSphere that defines this sphere in game-space.
		
		@type ode_space: ode.SpaceBase
		@param ode_space: The ODE space in which this sphere will reside.
		"""
		self._ode_geom = ode.GeomSphere(ode_space, self._radius)
		
	def _show(self):
		"""
		Displays this sphere in visual space.
		"""
		GL.glPushMatrix()
		GL.glShadeModel(GL.GL_SMOOTH)
		slices = stacks = 10
		if self._camera_offset_z > _SPHERE_POLY_CAP:
			slices = stacks = 4
		rendering.renderSphere((self._pos_x, self._pos_y, self._pos_z), self._rotation_matrix, self._radius, slices, stacks, self._colour)
		GL.glPopMatrix()
		