#!BPY

"""
Name: 'Image Browser'
Blender: 234
Group: 'UV'
Tooltip: 'Image Browser'
"""

from Blender import *
from Blender.BGL import *

scrollOffset = 0
thumbXY = 100 # Thumbnail size
rectList = [] # [[x,y,w,h, image], [x,y,w,h, image],]
sortMode = Draw.Create(0)
buttonHeight = 20

# takes a rect (x,y,width, height) and draws a opengl quad
def rect2quad(theRect): # Turn a pygame rect in an opengl style quad.
  glTexCoord2f(0.0, 1.0)# Bottom Left Of The Texture and Quad
  glVertex2f(theRect[0], theRect[1] + theRect[3] )	
  glTexCoord2f(1.0, 1.0)# Bottom Right Of The Texture and Quad
  glVertex2f( theRect[0]+theRect[2], theRect[1] + theRect[3])	
  glTexCoord2f(1.0, 0.0)# Top Right Of The Texture and Quad
  glVertex2f(theRect[0]+theRect[2], theRect[1])	
  glTexCoord2f(0.0, 0.0)# Top Left Of The Texture and Quad
  glVertex2f(theRect[0],  theRect[1])	

# Blender funcs
def error(str):
	Draw.PupMenu('ERROR%t|'+str)

def getActScriptWinRect():
  area = Window.GetAreaSize()
  area = (area[0]-1, area[1]-1)
  for scrInfo in Window.GetScreenInfo(Window.Types['SCRIPT'], 'win', ''):
    if scrInfo['vertices'][2]-scrInfo['vertices'][0] == area[0]:
      if scrInfo['vertices'][3]-scrInfo['vertices'][1] == area[1]:
        return scrInfo['vertices']
  return None

def getRelMousePos(winRect):
  mco = Window.GetMouseCoords()
  if mco[0] > winRect[0]:
    if mco[1] > winRect[1]:
      if mco[0] < winRect[0] + winRect[2]:
        if mco[1] < winRect[1] + winRect[3]:
          return (mco[0] - winRect[0], mco[1] - winRect[1])
  return None




def getMesh():
  selection = Object.GetSelected()
  if len(selection) == 0:
    error('No object selected')
    return None
  object = Object.GetSelected()[0]
  if object.getType() != 'Mesh':
    error('Not a mesh')
    return None
  mesh = object.getData()
  return mesh

# Face funcs
def setFaces(img):
  mesh = getMesh()
  if mesh != None:
    for f in mesh.getSelectedFaces(0):
      f.mode |= NMesh.FaceModes['TEX']
      f.image = img
    mesh.update(0)

def pointInRect(pt, rect):
  if pt[0] > rect[0]:
    if pt[1] > rect[1]:
      if pt[0] < rect[0]+rect[2]:
        if pt[1] < rect[1]+rect[3]:
          return True
  return False

def getMouseImage():
  global rectList
  relativeMouseCo = getRelMousePos(getActScriptWinRect())
  if relativeMouseCo != None:
    for rect in rectList:
      if pointInRect(relativeMouseCo, rect):
        return rect[4]
  return None

# Edits the image extarnally
def edit(img):
  try:
    def stripFileFromPath(file):
      while file[-1] != '/':
        file = file[0:-1]
      return file
    
    import os
    
    imageFileName = img.getFilename()
    
    # Account for the file name containing ///
    if imageFileName[0:2] == '//':
      filename = Blender.Get('filename')
      filename = stripFileFromPath(filename)
      imageFileName = filename + imageFileName[2:]
    
    os.system('gimp-remote -e ' + '"' + imageFileName + '"')
  except:
    error('could not edit image')


def imageMenu(): # Riht click menu
  img = getMouseImage()
  if img != None:
    result = Draw.PupMenu(img.name + "%t|Edit in the Gimp|Reload")
    if result == 1:
      edit(img)
    elif result == 2:
      img.reload()
      Window.RedrawAll()


# LMB Clicked- What have we hit, select it- act apon it.
def selectImage():
  image = getMouseImage()
  if image != None:
    setFaces(image) # rect[4] is the image
  Window.RedrawAll()

def getSortedImages():
  # mode
  # 0 = No order
  # 1 = alpha numeric
  # 2 = loaded first, (then alpha numeric)
  # 3 = size
  
  global sortMode
  # Alpha Numeric
  if sortMode.val == 0:
    # get a list of names
    ImageNames = []
    for img in Image.Get():
      ImageNames.append(img.name)
    ImageNames.sort()
    
    imageList = []
    for imgName in ImageNames:
      for img in Image.Get():
        if imgName == img.name:
          imageList.append(img)
          break
    return imageList

      # Loaded, then Alpha      
      # Alpha Numeric
  elif sortMode.val == 1:
    # get a list of names
    ImageLoadedNames = []
    ImageNotLoadedNames = []
    
    for img in Image.Get():
      if img.getBindCode() == 0:
        ImageNotLoadedNames.append(img.name)
      else:
        ImageLoadedNames.append(img.name)
        
    ImageNotLoadedNames.sort()
    ImageLoadedNames.sort()
    
    imageLoadedList = []
    imageNotLoadedList = []
    for imgName in ImageNotLoadedNames:
      for img in Image.Get():
        if imgName == img.name:
          imageNotLoadedList.append(img)
          break
          
    for imgName in ImageLoadedNames:
      for img in Image.Get():
        if imgName == img.name:
          imageLoadedList.append(img)
          break
    return imageLoadedList + imageNotLoadedList
    




def draw_thumbnails():
  global rectList, scrollOffset, thumbXY, sortMode
  thumbXY = Window.GetAreaSize()[0]
  glClearColor(0.0, 0.0, 0.0, 0.0)
  glClear(GL_COLOR_BUFFER_BIT)         # use it to clear the color buffer
  glEnable(GL_TEXTURE_2D) #We can the bitmap textures (not just a flat box)
  # glEnable(GL_BLEND) # Enable Alpha blending.
  # glEnable(GL_DEPTH_TEST) # Renders the front faces first SANE, Wont work for alpha, USe ordered alphas instead.
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Blending function, Like photoshop layer blending. This seems to be normal- no strange effects.
  glColor3f(1,1,1)
  
  imageNum = 0
  rectList = []
  for img in getSortedImages()[scrollOffset:]:
    
    rectList.append((0,buttonHeight+(imageNum*thumbXY),thumbXY,thumbXY, img))
      
    # break if the screen is too small (scroll)
    if Window.GetAreaSize()[1] < rectList[-1][1] + rectList[-1][3]:
      break
    
    
    if img.getBindCode() == 0: # image is loaded into OpenGL memory      
      # NOT LOADED, DRAW NAME.
      rectList[-1]
      glColor3f(1,1,1)
      glRasterPos2i(rectList[-1][0],rectList[-1][1]+(rectList[-1][3]/2))
      Draw.Text(img.filename.split(sys.sep)[-1]) 
      
    else:
      # DRAW OPENGL IMAGE
      glBindTexture(GL_TEXTURE_2D, img.getBindCode()) # SET THE ACTIVE OPENGL TEXTURE INDEX		
      
      glBegin(GL_QUADS) # Start QUADS
      rect2quad(rectList[-1]) # REct and ZPOS
      glEnd()
    
    imageNum+=1
    
    sortMode = Draw.Toggle('loaded first', 1024, 0, 0, thumbXY, buttonHeight, sortMode.val, 'Loaded first')
    # Draw menu
    #name = "Sort order %t|First Entry %x1|Second Entry %x2|Third Entry %x3"
    #sortMode = Draw.Menu(name, 2, 60, 120, 200, buttonHeight, sortMode.val, "Just a test menu.")
 
 
def handle_button_event(evt):
	#print evt
	if evt == 999:
		Draw.Redraw(1) 

def ev(evt, val):                      # event callback for Draw.Register()
  global scrollOffset, thumbXY, rectList
  if evt == Draw.ESCKEY or evt == Draw.QKEY:
    Draw.Exit()
  #~ elif not val: return
  elif evt == Draw.LEFTMOUSE:
    selectImage()
  #~ elif evt == Draw.MIDDLEMOUSE: G = 1 - G
  elif evt == Draw.RIGHTMOUSE:
    imageMenu()
  elif evt == Draw.WHEELUPMOUSE:
    scrollOffset+= abs(len(rectList)-3) +1
    Draw.Redraw(1) 
  elif evt == Draw.WHEELDOWNMOUSE:
    scrollOffset-= abs(len(rectList)-3) +1
    if scrollOffset < 0:
      scrollOffset = 0
    Draw.Redraw(1) 
    
  elif evt == Draw.PADMINUS:
    thumbXY -=1
    if thumbXY < 20:
      thumbXY = 20
    Draw.Redraw(1) 
  elif evt == Draw.PADPLUSKEY:
    thumbXY +=1
    if thumbXY > 200:
      thumbXY = 200
    Draw.Redraw(1) 

Draw.Register(draw_thumbnails, ev, handle_button_event)