def renderIncomingNeck(self, visibility, song, pos, time, neckTexture):   #MFH - attempt to "scroll" an incoming guitar solo neck towards the player
    if not song:
      return
    if not song.readyToGo:
      return
    
    def project(beat):
      return 0.125 * beat / self.beatsPerUnit    # glorandwarf: was 0.12

    v            = visibility
    w            = self.boardWidth
    l            = self.boardLength

    #offset       = (pos - self.lastBpmChange) / self.currentPeriod + self.baseBeat 
    offset = 0

    z  = ((time - pos) / self.currentPeriod) / self.beatsPerUnit

    color = (1,1,1)

    glEnable(GL_TEXTURE_2D)
    if neckTexture:
      neckTexture.texture.bind()


    glBegin(GL_TRIANGLE_STRIP)
    glColor4f(color[0],color[1],color[2], 0)
    glTexCoord2f(0.0, project(offset - 2 * self.beatsPerUnit))
    #glVertex3f(-w / 2, 0, -2)
    glVertex3f(-w / 2, 0, z)   #point A
    glTexCoord2f(1.0, project(offset - 2 * self.beatsPerUnit))
    #glVertex3f( w / 2, 0, -2)
    glVertex3f( w / 2, 0, z)   #point B

    
    glColor4f(color[0],color[1],color[2], v)
    glTexCoord2f(0.0, project(offset - 1 * self.beatsPerUnit))
    #glVertex3f(-w / 2, 0, -1)
    glVertex3f(-w / 2, 0, z+1)   #point C
    glTexCoord2f(1.0, project(offset - 1 * self.beatsPerUnit))
    #glVertex3f( w / 2, 0, -1)
    glVertex3f( w / 2, 0, z+1)   #point D
    
    glTexCoord2f(0.0, project(offset + l * self.beatsPerUnit * .7))
    #glVertex3f(-w / 2, 0, l * .7)
    glVertex3f(-w / 2, 0, z+2+l * .7) #point E
    glTexCoord2f(1.0, project(offset + l * self.beatsPerUnit * .7))
    #glVertex3f( w / 2, 0, l * .7)
    glVertex3f( w / 2, 0, z+2+l * .7) #point F
    
    glColor4f(color[0],color[1],color[2], 0)
    glTexCoord2f(0.0, project(offset + l * self.beatsPerUnit))
    #glVertex3f(-w / 2, 0, l)
    glVertex3f(-w / 2, 0, z+2+l)    #point G
    glTexCoord2f(1.0, project(offset + l * self.beatsPerUnit))
    #glVertex3f( w / 2, 0, l)
    glVertex3f( w / 2, 0, z+2+l)    #point H
    glEnd()
    
    glDisable(GL_TEXTURE_2D)
  def drawBPM(self, visibility, song, pos):
    if not song:
      return
    if not song.readyToGo:
      return


    v            = visibility
    w            = self.boardWidth

    track = song.track[self.player]

    glEnable(GL_TEXTURE_2D)

    for time, event in track.getEvents(pos - self.currentPeriod * 2, pos + self.currentPeriod * self.beatsPerBoard):
      if not isinstance(event, Bars):
        continue   

      glPushMatrix()

      z  = ((time - pos) / self.currentPeriod) / self.beatsPerUnit
      z2 = ((time + event.length - pos) / self.currentPeriod) / self.beatsPerUnit

      if z > self.boardLength:
        f = (self.boardLength - z) / (self.boardLength * .2)
      elif z < 0:
        f = min(1, max(0, 1 + z2))
      else:
        f = 1.0
        
      if event.barType == 0: #half-beat
        sw  = 0.1 #width
        self.bpm_halfbeat.texture.bind()
      elif event.barType == 1: #beat
        sw  = 0.1 #width
        self.bpm_beat.texture.bind()
      elif event.barType == 2: #measure
        sw  = 0.1 #width
        self.bpm_measure.texture.bind()

      bpm_vtx  = array([[-(w / 2), 0,  z + sw],
                         [-(w / 2), 0,  z - sw],
                         [(w / 2), 0,  z + sw],
                         [(w / 2), 0,  z - sw]], dtype=float32)

      bpm_tex  = array([[0.0, 1.0],
                         [0.0, 0.0],
                         [1.0, 1.0],
                         [1.0, 0.0]], dtype=float32)

      bpm_col  = array([[1, 1, 1, v],
                         [1, 1, 1, v],
                         [1, 1, 1, v],
                         [1, 1, 1, v]], dtype=float32)

      cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=bpm_vtx, colors=bpm_col, texcoords=bpm_tex)

      glPopMatrix()

    glDisable(GL_TEXTURE_2D)
  def drawSideBars(self, visibility, song, pos):
    if not song:
      return
    if not song.readyToGo:
      return

    def project(beat):
      return 0.125 * beat / self.beatsPerUnit  # glorandwarf: was 0.12

    v            = visibility
    w            = self.boardWidth + 0.15
    l            = self.boardLength

    offset       = (pos - self.lastBpmChange) / self.currentPeriod + self.baseBeat 

    c = (1,1,1)

    board_tex  = array([[0.0, project(offset - 2 * self.beatsPerUnit)],
                         [1.0, project(offset - 2 * self.beatsPerUnit)],
                         [0.0, project(offset - 1 * self.beatsPerUnit)],
                         [1.0, project(offset - 1 * self.beatsPerUnit)],
                         [0.0, project(offset + l * self.beatsPerUnit * .7)],
                         [1.0, project(offset + l * self.beatsPerUnit * .7)],
                         [0.0, project(offset + l * self.beatsPerUnit)],
                         [1.0, project(offset + l * self.beatsPerUnit)]], dtype=float32)

    glEnable(GL_TEXTURE_2D)
    if self.theme == 2 and self.instrument.starPowerActive and self.oSideBars:
      self.oSideBars.texture.bind()
    else:
      self.sideBars.texture.bind()

    cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=self.sidebars_vtx, colors=self.board_col, texcoords=board_tex)
    
    glDisable(GL_TEXTURE_2D)
    
    if self.theme == 1:   
      if shaders.enable("sololight"):
        shaders.modVar("color",shaders.var["solocolor"])
        shaders.setVar("offset",(-3.5,-w/2))
        glBegin(GL_TRIANGLE_STRIP)
        glVertex3f(w / 2-1.0, 0.4, -2)
        glVertex3f(w / 2+1.0, 0.4, -2)
        glVertex3f(w / 2-1.0, 0.4, l)
        glVertex3f(w / 2+1.0, 0.4, l)
        glEnd()   
        shaders.setVar("offset",(-3.5,w/2))
        shaders.setVar("time",shaders.time()+0.5)
        glBegin(GL_TRIANGLE_STRIP)
        glVertex3f(-w / 2+1.0, 0.4, -2)
        glVertex3f(-w / 2-1.0, 0.4, -2)
        glVertex3f(-w / 2+1.0, 0.4, l)
        glVertex3f(-w / 2-1.0, 0.4, l)
        glEnd()  
        shaders.disable()
  def renderNeckMethod(self, visibility, offset, neck, alpha = False): #blazingamer: New neck rendering method
    
    def project(beat):
      return 0.125 * beat / self.beatsPerUnit    # glorandwarf: was 0.12
      
    if self.instrument.starPowerActive and self.theme == 0:#8bit
      color = self.engine.theme.spNoteColor #self.spColor #(.3,.7,.9)
    elif self.instrument.starPowerActive and self.theme == 1:
      color = self.engine.theme.spNoteColor #self.spColor #(.3,.7,.9)
    else:
      color = (1,1,1)

    v            = visibility
    l            = self.boardLength

    glEnable(GL_TEXTURE_2D)

    board_tex  = array([[0.0, project(offset - 2 * self.beatsPerUnit)],
                         [1.0, project(offset - 2 * self.beatsPerUnit)],
                         [0.0, project(offset - 1 * self.beatsPerUnit)],
                         [1.0, project(offset - 1 * self.beatsPerUnit)],
                         [0.0, project(offset + l * self.beatsPerUnit * .7)],
                         [1.0, project(offset + l * self.beatsPerUnit * .7)],
                         [0.0, project(offset + l * self.beatsPerUnit)],
                         [1.0, project(offset + l * self.beatsPerUnit)]], dtype=float32)
    
    #must be seperate for neck flashing.
    board_col  = array([[color[0],color[1],color[2], 0],
                             [color[0],color[1],color[2], 0],
                             [color[0],color[1],color[2], v],
                             [color[0],color[1],color[2], v],
                             [color[0],color[1],color[2], v],
                             [color[0],color[1],color[2], v],
                             [color[0],color[1],color[2], 0],
                             [color[0],color[1],color[2], 0]], dtype=float32)

    if alpha == True:
      glBlendFunc(GL_ONE, GL_ONE)
    neck.texture.bind()
    cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=self.board_vtx, colors=board_col, texcoords=board_tex)

    if alpha == True:
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
      
    glDisable(GL_TEXTURE_2D)
  def draw(self, color = (1, 1, 1, 1), rect = (0,1,0,1), lOffset = 0.0, rOffset = 0.0):
    with cmglPushedSpecificMatrix(GL_TEXTURE):
      with cmglPushedSpecificMatrix(GL_PROJECTION):

        with cmglMatrixMode(GL_PROJECTION):
          self.context.setProjection()

        with cmglPushedMatrix():
          glLoadIdentity()
          self._getEffectiveTransform().applyGL()

          glScalef(self.texture.pixelSize[0], self.texture.pixelSize[1], 1)
          glTranslatef(-.5, -.5, 0)
          glColor4f(*color)

          glEnable(GL_TEXTURE_2D)
          self.texture.bind()

          self.triangVtx[0,0] = 0.0-lOffset
          self.triangVtx[0,1] = 1.0
          self.triangVtx[1,0] = 1.0-rOffset
          self.triangVtx[1,1] = 1.0
          self.triangVtx[2,0] = 0.0+lOffset
          self.triangVtx[2,1] = 0.0
          self.triangVtx[3,0] = 1.0+rOffset
          self.triangVtx[3,1] = 0.0

          self.textriangVtx[0,0] = rect[0]
          self.textriangVtx[0,1] = rect[3]
          self.textriangVtx[1,0] = rect[1]
          self.textriangVtx[1,1] = rect[3]
          self.textriangVtx[2,0] = rect[0]
          self.textriangVtx[2,1] = rect[2]
          self.textriangVtx[3,0] = rect[1]
          self.textriangVtx[3,1] = rect[2]

          cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=self.triangVtx, texcoords=self.textriangVtx)

          glDisable(GL_TEXTURE_2D)
 def render(self, geomName = None):
   if geomName in self.fullGeoms:
     self.fullGeoms[geomName]()
     return
     
   # Prepare a new list for all the geometry
   if not self.geoms:
     for geom in self.doc.geometriesLibrary.items:
       self.geoms[geom.name] = cmglList()
       with self.geoms[geom.name]:
 
         for prim in geom.data.primitives:
           maxOffset = vertexOffset = normalOffset = 0
           vertexOffset = None
           normalOffset = None
           texcoordOffset = None
           vertices = None
           normals = None
           texcoords = None
 
           for input in prim.inputs:
             maxOffset = max(maxOffset, input.offset)
             if input.semantic == "VERTEX":
               vertexOffset = input.offset
               vertices = geom.data.FindSource(geom.data.vertices.FindInput("POSITION"))
               assert vertices.techniqueCommon.accessor.stride == 3
               vertices = self._unflatten(vertices.source.data, vertices.techniqueCommon.accessor.stride)
             elif input.semantic == "NORMAL":
               normalOffset = input.offset
               normals = geom.data.FindSource(input)
               normals = self._unflatten(normals.source.data, 3)
             elif input.semantic == "TEXCOORD":
               texcoordOffset = input.offset
               texcoords = geom.data.FindSource(input)
               texcoords = self._unflatten(texcoords.source.data, 2)
 
           if normalOffset is None:
             normals = geom.data.FindSource(geom.data.vertices.FindInput("NORMAL"))
             normals = self._unflatten(normals.source.data, 3)
             normalOffset = vertexOffset
 
           def drawElement(indices, offset, array, func):
             if offset is not None:
               func(*array[indices[offset]])
         
           if hasattr(prim, "polygons"):
             for poly in prim.polygons:
               glBegin(GL_POLYGON)
               for indices in self._unflatten(poly, maxOffset + 1):
                 drawElement(indices, normalOffset,   normals,   glNormal3f)
                 drawElement(indices, texcoordOffset, texcoords, glTexCoord2f)
                 drawElement(indices, vertexOffset,   vertices,  glVertex3f)
               glEnd()
           elif hasattr(prim, "triangles"):
            glBegin(GL_TRIANGLES)
            for indices in self._unflatten(prim.triangles, maxOffset + 1):
               drawElement(indices, normalOffset,   normals,   glNormal3f)
               drawElement(indices, texcoordOffset, texcoords, glTexCoord2f)
               drawElement(indices, vertexOffset,   vertices,  glVertex3f)
            glEnd()
     
   # Prepare a new display list for this particular geometry
   self.fullGeoms[geomName] = cmglList()
   with self.fullGeoms[geomName]:
   
     if self.geoms:
       # setup lights
       for scene in self.doc.visualScenesLibrary.items:
         for node in scene.nodes:
           for n, light in enumerate(node.iLights):
             if light.object:
               # TODO: hierarchical node transformation, other types of lights
               pos = [0.0, 0.0, 0.0, 1.0]
               for t in node.transforms:
                 if t[0] == "translate":
                   pos = t[1]
               self.setupLight(light.object, n, pos)
             
       # render geometry
       for scene in self.doc.visualScenesLibrary.items:
         for node in scene.nodes:
           if geomName is not None and node.name != geomName:
             continue
           for geom in node.iGeometries:
             if geom.object:
               #for mat in geom.bindMaterials:
               #  self.setupMaterial(mat)
               
               glPushMatrix()
               for t in node.transforms:
                 if t[0] == "translate":
                   glTranslatef(*t[1])
                 elif t[0] == "rotate":
                   glRotatef(t[1][3], t[1][0], t[1][1], t[1][2])
                 elif t[0] == "scale":
                   glScalef(*t[1])
               if geom.object.name in self.geoms:
                 self.geoms[geom.object.name]()
               glPopMatrix()
       glDisable(GL_LIGHTING)
       for n in range(8):
         glDisable(GL_LIGHT0 + n)
     
   # Render the new list
   self.render(geomName)
  def drawTrack(self, visibility, song, pos):
    if not song:
      return
    if not song.readyToGo:
      return

    def project(beat):
      return 0.125 * beat / self.beatsPerUnit    # glorandwarf: was 0.12

    if self.theme == 0 or self.theme == 1:
      size = 2
    else:
      size = 0

    v            = visibility
    w            = self.boardWidth
    l            = self.boardLength

    if self.staticStrings:
      offset       = 0
    else:
      offset       = (pos - self.lastBpmChange) / self.currentPeriod + self.baseBeat 

    track_tex  = array([[0.0, project(offset - 2 * self.beatsPerUnit)],
                         [1.0, project(offset - 2 * self.beatsPerUnit)],
                         [0.0, project(offset - 1 * self.beatsPerUnit)],
                         [1.0, project(offset - 1 * self.beatsPerUnit)],
                         [0.0, project(offset + l * self.beatsPerUnit * .7)],
                         [1.0, project(offset + l * self.beatsPerUnit * .7)],
                         [0.0, project(offset + l * self.beatsPerUnit)],
                         [1.0, project(offset + l * self.beatsPerUnit)]], dtype=float32)


    glEnable(GL_TEXTURE_2D)
    
    #MFH - logic to briefly display oFlash
    if self.theme == 2 and self.overdriveFlashCount < self.overdriveFlashCounts and self.oFlash:
      self.oFlash.texture.bind()
    elif self.theme == 2 and self.instrument.starPowerActive and self.oCenterLines:
      self.oCenterLines.texture.bind()
    else:
      self.centerLines.texture.bind()

      
    track_vtx       = array([[-w / 2, 0, -2+size],
                           [w / 2, 0, -2+size],
                           [-w / 2, 0, -1+size],
                           [w / 2, 0, -1+size],
                           [-w / 2, 0, l * .7],
                           [w / 2, 0, l * .7],
                           [-w / 2, 0, l],
                           [w / 2, 0, l]], dtype=float32)
    
    if self.staticStrings:    #MFH
      color = (1,1,1)
      track_col  = array([[color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], v],
                         [color[0],color[1],color[2], 0],
                         [color[0],color[1],color[2], 0]], dtype=float32)
      cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=track_vtx, colors=track_col, texcoords=track_tex)

    else:   #MFH: original moving strings

      cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=track_vtx, colors=self.board_col, texcoords=track_tex)

    glDisable(GL_TEXTURE_2D)
  def render(self, text, pos = (0, 0), rotate = 0, scale = DEFAULT_SCALE, shadowoffset = (.0022, .0005), align = LEFT, new = False):
    """
    Draw some text.

    @param text:      Text to draw
    @param pos:       Text coordinate tuple (x, y)
    @param rotate:    Angle to rotate text, in degrees
    @param scale:     Scale factor
    """
    # deufeufeu : new drawing relaying only on pygame.font.render
    #           : I know me miss special unicodes characters, but the gain
    #           : is really important.
    # evilynux : Use arrays to increase performance
    def drawSquare(w,h,tw,th):
        self.square_prim[1,0] = self.square_prim[3,0] = w
        self.square_prim[2,1] = self.square_prim[3,1] = h
        self.square_tex[0,1] = self.square_tex[1,1] = th
        self.square_tex[1,0] = self.square_tex[3,0] = tw
        cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=self.square_prim, texcoords=self.square_tex)

    if not text:
        return

    try:
        t,w,h = self.stringsCache.get(text)
    except KeyError:
        s = self.font.render(text, True, (255,255,255))
        t = Texture()
        t.setFilter(GL_LINEAR, GL_LINEAR)
        t.setRepeat(GL_CLAMP, GL_CLAMP)
        t.loadSurface(s, alphaChannel = True)
        del s
        w, h = self.font.size(text)
        self.stringsCache.add(text,(t,w,h))

    x, y = pos
    scale *= self.scale
    w, h = w*scale*self.aspectRatioFactor, h*scale
    if align == CENTER: #we have already done all the calculating. Why not add this? - akedrou
      x -= (w/2)
    elif align == RIGHT:
      x -= w
    y -= (h/2)
    tw,th = t.size
    glEnable(GL_TEXTURE_2D)
    with cmglPushedMatrix():
      if rotate:
        if not isinstance(rotate, tuple):
          glRotatef(rotate, 0, 0, 1.0)
        else:
          glRotatef(0, *rotate)
      glTranslatef(x,y,0)
      t.bind()
      if self.outline:
        with cmglPushedAttrib(GL_CURRENT_BIT):
          glColor4f(0, 0, 0, .25 * glGetDoublev(GL_CURRENT_COLOR)[3])

          blur = 2 * DEFAULT_SCALE
          for offset in [(-.7, -.7), (0, -1), (.7, -.7), (-1, 0),
                         (1, 0), (-.7, .7), (0, 1), (.7, .7)]:
            with cmglPushedMatrix():
              glTranslatef(blur * offset[0], blur * offset[1], 0)
              drawSquare(w,h,tw,th)

      if self.shadow:
        with cmglPushedAttrib(GL_CURRENT_BIT):
          glColor4f(0, 0, 0, 1)
          with cmglPushedMatrix():
            glTranslatef(shadowoffset[0], shadowoffset[1], 0)
            drawSquare(w,h,tw,th)

      drawSquare(w,h,tw,th)

    glDisable(GL_TEXTURE_2D)
  def textureSetup(self):
    # Free memory if we already allocated space for textures.
    if len(self.animTexs) > 0:
      glDeleteTextures(self.animTexs)

    self.animTexs = glGenTextures(len(self.animImgs))
    for texIdx, img in enumerate(self.animImgs):
      animSize = img.get_size()
      if img.get_alpha is None:
        color = "RGB"
        colorGL = GL_RGB
      else:
        color = "RGBA"
        colorGL = GL_RGBA
      
#       Log.debug("AnimationPlayer: Image %d format: %s (%dx%d)" % (texIdx, color, animSize[0], animSize[1]))
      glBindTexture(GL_TEXTURE_2D, self.animTexs[texIdx])
      surfaceData = pygame.image.tostring(img, color, True)
      # Linear filtering
      glTexImage2D(GL_TEXTURE_2D, 0, 3, animSize[0], animSize[1], 0, colorGL,
                   GL_UNSIGNED_BYTE, surfaceData)
      # MipMapping
#       gluBuild2DMipmaps(GL_TEXTURE_2D, colorGL,
#                         animSize[0], animSize[1], colorGL,
#                         GL_UNSIGNED_BYTE, surfaceData)
      glTexParameteri(GL_TEXTURE_2D, 
                      GL_TEXTURE_MAG_FILTER, GL_LINEAR)
      glTexParameteri(GL_TEXTURE_2D,
                      GL_TEXTURE_MIN_FILTER, GL_LINEAR)
      Log.debug("AnimationPlayer progress: %d%%" % \
                ( 100*(texIdx+1+len(self.animImgs)) / \
                  (2*len(self.animImgs)) ))

    # Resize animation (polygon) to respect resolution ratio
    # (The math is actually simple, take the time to draw it down if required)
    winRes = float(self.winWidth)/float(self.winHeight)
    animWidth = float(self.animImgs[0].get_size()[0])
    animHeight = float(self.animImgs[0].get_size()[1])
    animRes = animWidth/animHeight
    vtxX = 1.0
    vtxY = 1.0
    if winRes > animRes:
      r = float(self.winHeight)/animHeight
      vtxX = 1.0 - abs(self.winWidth-r*animWidth) / (float(self.winWidth))
    elif winRes < animRes:
      r = float(self.winWidth)/animWidth
      vtxY = 1.0 - abs(self.winHeight-r*animHeight) / (float(self.winHeight))

    # Vertices
    animVtx = array([[-vtxX,  vtxY],
                     [ vtxX, -vtxY],
                     [ vtxX,  vtxY],
                     [-vtxX,  vtxY],
                     [-vtxX, -vtxY],
                     [ vtxX, -vtxY]], dtype=float32)
    # Texture coordinates
    texCoord = array([[0.0, 1.0],
                      [1.0, 0.0],
                      [1.0, 1.0],
                      [0.0, 1.0],
                      [0.0, 0.0],
                      [1.0, 0.0]], dtype=float32)
    
    # Create a compiled OpenGL call list and do array-based drawing
    # Could have used GL_QUADS but IIRC triangles are recommended
    self.animList = cmglList()
    with self.animList:
      glEnable(GL_TEXTURE_2D)
      glColor3f(1., 1., 1.)
      cmglDrawArrays(GL_TRIANGLE_STRIP, vertices=animVtx, texcoords=texCoord)
      glDisable(GL_TEXTURE_2D)