Image browser

Iv had this script kicking around for a while, displays a list of images in your blend file. clicking on them assigns to selected faces of a mesh, mouse wheel to scroll.


#!BPY

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

global selectionState
imageProps = {} # imagename|{propDict}

from Blender import *
from Blender.BGL import *

import image_edit
reload(image_edit)

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

# Blender funcs
def error(str):
    Draw.PupMenu('ERROR%t|'+str)
    
def getSpaceRect():
    __UI_RECT__ = Buffer(GL_FLOAT, 4)
    glGetFloatv(GL_SCISSOR_BOX, __UI_RECT__) 
    __UI_RECT__ = __UI_RECT__.list
    return (int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2]), int(__UI_RECT__[3]))

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():
    try:
        return Scene.GetCurrent().getActiveObject().getData(mesh=1)
    except:
        return None

# Face funcs
def setFaces(img):
    TEXMODE= Mesh.FaceModes.TEX
    SEL= Mesh.FaceFlags.SELECT
    mesh = getMesh()
    if not mesh:
        return
    
    for f in mesh.faces:
        if f.flag & SEL:
            f.mode |= TEXMODE
            f.image = img

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


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


def imageMenu(): # Riht click menu
    img = getMouseImage()
    if img != None:
        result = Draw.PupMenu(img.name + "%t|Edit in the Gimp|Reload|Load|UnLoad")
        if result == 1:
            image_edit.edit(img)
        
        elif result == 2:
            img.reload()
            Window.RedrawAll()
        
        elif result == 3:
            try:
                img.glLoad()
                Draw.Redraw(1)
            except:
                error('Could not load ' + img.name)
        elif result == 4:
            try:
                img.glFree()      
            except:
                error('Could not unload' + img.name)
            
    #while Window.GetMouseButtons() != 0:
    #    print 'Hanging'
    #    sys.sleep(10)
        
# 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 getImageSize(i):
    try:
        size = i.size
        return size[0] * size[1]
    except:
        return 0

def getSortedImages():
    global imageProps, sortMode
    # mode
    # 1 = alpha numeric
    # 2 = loaded first, (then alpha numeric)
    # 3 = size
    
    
    

    imageList = [i for i in Image.Get() if not i.name.startswith('.')]
    
    for i in imageList:
        try:
            dummy = imageProps[i.name]
        except:
            imageProps[i.name] = {'sel':0}    
    
    
    # Alpha Numeric
    if sortMode.val == 0:
        pass
    elif sortMode.val == 1: # Name
        imageList.sort(lambda a,b: cmp(a.name, b.name))
    elif sortMode.val == 2: # Loaded, Name
        imageList.sort(lambda a,b: cmp((a.getBindCode()==0,a.name), (b.getBindCode()==0, b.name)) )    
    elif sortMode.val == 2: # Image size
        imageList.sort(lambda a,b: cmp((getImageSize(a), a.name), (getImageSize(b), b.name)) )
    
    return imageList



def draw_thumbnails():
    global rectList, scrollOffset, thumbXY, sortMode, imageProps
    areaSize = Window.GetAreaSize()
    thumbXY = min(areaSize[0], 128)
    # Clear the area
    glClearColor(1,1,1,1)
    
    # use it to clear the color buffer
    glClear(GL_COLOR_BUFFER_BIT)
    
    #We can the bitmap textures (not just a flat box)
    glEnable(GL_TEXTURE_2D)
    
    # Set opengl context
    glDisable(GL_LIGHTING)    
    
    glDisable(GL_TEXTURE_1D)
    glEnable(GL_TEXTURE_2D)
    
    glColor3f(0,0,0)
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    # Clear The Buffers
    
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Blending function, Like photoshop layer blending. This seems to be normal- no strange effects.
    
    rectList = []



    # Set opengl context
    glDisable(GL_LIGHTING)    
    
    glDisable(GL_TEXTURE_1D)
    glDisable(GL_TEXTURE_2D)
    
    glColor3f(1,1,1)
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    # Clear The Buffers
    
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)    
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    
    
    

    for index, img in enumerate(getSortedImages()):
        if index < scrollOffset:
            continue
        
        rectList.append((0,buttonHeight+buttonHeight+(((index-scrollOffset)*(thumbXY+buttonHeight))),thumbXY,thumbXY, img))
            
        # break if the screen is too small (scroll)
        if Window.GetAreaSize()[1] < rectList[-1][1] + rectList[-1][3]:
            break
        
        # Draw 
        try:
            size= img.size
            x= rectList[-1][0]
            y= rectList[-1][1]
            s= 1.0/max(size)
            zoom= s * rectList[-1][3]
            Draw.Image(img, x, y, zoom, zoom)
        except:
            pass
        
        
        #Draw.Toggle(img.filename.split(sys.sep)[-1], 1000 + index, rectList[-1][0], rectList[-1][1]-buttonHeight, thumbXY, buttonHeight, imageProps[img.name]['sel'], 'Select the image')
        Draw.Toggle(img.name, 1000 + index, rectList[-1][0], rectList[-1][1]-buttonHeight, thumbXY, buttonHeight, imageProps[img.name]['sel'], 'Select the image')
        
        # sortMode = Draw.Toggle('loaded first', 1024,` 0, 0, thumbXY, buttonHeight, sortMode.val, 'Loaded first')
        
        # Draw menu
        '''
        name = "Sort order %t|Alphabetical%x1|Loaded First %x2|Image Size%x3"
        sortMode = Draw.Menu(name, 6000, 0, areaSize[1]-buttonHeight, areaSize[0], buttonHeight, sortMode.val, "Just a test menu.")
        '''
 
 
def handle_button_event(evt):
    global imageProps
    #print evt
    if evt == 999:
        Draw.Redraw(1)
    if evt >= 1000 and evt <= 2000  : # Image Select
        print evt
        img = Image.Get()[evt-1000]
        if img != None:
            imageProps[img.name]['sel'] = not imageProps[img.name]['sel']
            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:
    
    elif evt == Draw.RIGHTMOUSE:
        imageMenu()
    elif evt == Draw.WHEELUPMOUSE:
        scrollOffset+= 1 # abs(len(rectList)-3)
        Draw.Redraw(1) 
        return
    elif evt == Draw.WHEELDOWNMOUSE:
        scrollOffset-= 1 # abs(len(rectList)-3)
        if scrollOffset < 0:
            scrollOffset = 0
        Draw.Redraw(1) 
        return
    """
    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)

Thanks, very usefull :wink:

Thanks cambo,

Very handy script. Saves lots of time.
I tested in 2.42a.
Loaded multiple texture images (.jpeg .png) into blender using a cube.
Then created a new cube (probably not nessesary).
In Object mode, UV face select mode,
Run the script.
Select a face first, then a image in the script window.
I mapped all 6 faces with different images.
It works well.
Also managed to do some uv\image window rotate & scale transforms.

Great script.
brendon.