##"import sropengl" replaces "import OpenGL.TK". The main 
##differences are: 
##1. The camera always looks at an object of attention, tracking it when either or both are moving. 
##2. Methods Xmove, Ymove, and Zmove now implement motions of the camera. 
##3. As a consequence of the new camera system, self.distance is zero: the camera is at its own 
##origin. This is only of interest if compared to the way it was before.  srOpengl is subclassed by 
##Renderer, in another file ('render.py'), which adds keypress dispatching.


from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.Tk import RawOpengl
from att_obj import *

class srOpengl(RawOpengl):

  def __init__(self, master=None, cnf={}, **kw):
    """\
    Create an opengl widget.
    Arrange for redraws when the window is exposed or when
    it changes size."""

    #Widget.__init__(self, master, 'togl', cnf, kw)
    apply(RawOpengl.__init__, (self, master, cnf), kw)
    self.initialised = 0

    # Current coordinates of the mouse.
    self.xmouse = 0
    self.ymouse = 0

    # Where we are centering.
    self.camera_x = 0.0
    self.camera_y = 0.0
    self.camera_z = 0.0

    # The _back color
    self.r_back = 1.
    self.g_back = 0.
    self.b_back = 1.

    # Where the eye is
    self.distance = 0.0
    
    world = Att_Obj((0,0,0))
    self.object_of_attention = world

    # Field of view in y direction
    self.fovy = 90.0

    # Position of clipping planes.
    self.near = 0.1
    self.far = 1000.0

    # Is the widget allowed to autospin?
    self.autospin_allowed = 0

    # Is the widget currently autospinning?
    self.autospin = 0

    # Basic bindings for the virtual trackball
    self.bind('<Map>', self.tkMap)
    self.bind('<Expose>', self.tkExpose)
    self.bind('<Configure>', self.tkExpose)
    #self.bind('<Shift-Button-1>', self.tkHandlePick)
    #self.bind('<Button-1><ButtonRelease-1>', self.tkHandlePick)
    self.bind('<Button-1>', self.tkRecordMouse)
    self.bind('<B1-Motion>', self.Xmove)
    self.bind('<Button-2>', self.tkRecordMouse)
    self.bind('<B2-Motion>', self.Ymove)
    #self.bind('<ButtonRelease-2>', self.tkAutoSpin)
    self.bind('<Button-3>', self.tkRecordMouse)
    self.bind('<B3-Motion>', self.Zmove)

  def help(self):
    """Help for the widget."""

    import Dialog
    d = Dialog.Dialog(None, {'title': 'Viewer help',
			     'text':
			     'Button-1: Translate\n'
			     'Button-2: Rotate\n'
			     'Button-3: Zoom\n'
			     'Reset: Resets transformation to identity\n',
			     'bitmap': 'questhead',
			     'default': 0,
			     'strings': ('Done', 'Ok')})

  def activate(self):
    self.tk.call(self._w, 'makecurrent')


  def basic_lighting(self):
    self.activate()
    light_position = (1, 1, 1, 0);
    glLightf(GL_LIGHT0, GL_POSITION, light_position);
    light_position = (-1, 0, 0, 0);
    glLightf(GL_LIGHT1, GL_POSITION, light_position);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity()

  def report_opengl_errors(message = "OpenGL error:"):
    while 1:
      err_value = glGetError()
      if not err_value: break     
      print message, gluErrorString(err_value)

  def set_background(self, r, g, b):
    self.r_back = r
    self.g_back = g
    self.b_back = b
    self.tkRedraw()

  def position_camera(self, x, y, z):
    self.camera_x = x
    self.camera_y = y
    self.camera_z = z
    self.tkRedraw()

  def reset(self):
    """Reset rotation matrix for this widget."""

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity()
    self.tkRedraw()

  def tkRecordMouse(self, event):
    self.xmouse = event.x
    self.ymouse = event.y

  def Zmove(self, event):
    self.camera_z = self.camera_z + 0.1 * (event.y - self.ymouse)
    self.tkRedraw()
    self.tkRecordMouse(event)

  def Xmove(self, event):
    self.camera_x = self.camera_x + .1*(event.x - self.xmouse)
    self.tkRedraw()
    self.tkRecordMouse(event)

  def Ymove(self, event):
    self.camera_y = self.camera_y + .1*(event.x - self.xmouse)
    self.tkRedraw()
    self.tkRecordMouse(event)

  def tkRedraw(self, *dummy):
    if not (self.initialised):
        return
    self.activate()
    glPushMatrix()			
    self.update_idletasks()
    w = self.winfo_width()
    h = self.winfo_height()
    glViewport(0, 0, w, h)
    glClearColor(self.r_back, self.g_back, self.b_back, 0.)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity()
##    glLoadMatrix(identity(4))  ## gives same result
    gluPerspective(self.fovy, float(w)/float(h), self.near, self.far)
    gluLookAt(self.camera_x, self.camera_y, self.camera_z,
             self.object_of_attention.worldposition[0], self.object_of_attention.worldposition[1], self.object_of_attention.worldposition[2],0., 0., 1.)
    self.object_of_attention.it = 1
    glMatrixMode(GL_MODELVIEW)
    self.redraw(self)
    glFlush()				# Tidy up
    glPopMatrix()			# Restore the matrix

    self.tk.call(self._w, 'swapbuffers')

  def tkMap(self, *dummy):
   self.tkExpose()

  def tkExpose(self, *dummy):
    self.activate()
    if not self.initialised:
      self.basic_lighting()
      self.initialised = 1
    self.tkRedraw()

  def tkPrint(self, file):
    self.activate()

    
