#!BPY
""" Released under the Blender Artistic Licence (BAL)
Name: 'Load/Save VertCols'
Blender: 235
Group: 'Object'
Tooltip: 'Save a mesh's vertex colors in a tga file for archiving.'
"""
__author__ = "pat"
__version__ = "1.4b - 10/17/05 -"
__email__ = ('Author, pat:psycho3d*de')
__url__ = ("Author's website, www.psycho3d.de")
__bpydoc__ ="""\
This script can save or load a mesh's vertex color to/from a raw .tga file.
There are some scripts that use vertcols for different things, fiber is
probably the most famous one. This script gives you the possibility to
exchange a mesh's vertcols, backup them or eg. view only the red part by
painting the mesh black and importing red only.
Buttons:
Per Vertex: When inactive the mesh's vertcols will be saved per face, resulting in bigger files. You only need to deactivate this if your vertcols are not shared between faces.
Remember Path: The script generates an ini file inside your .blend, saving all your options and, if chosen, the path (not filename) you last used to save or load. When inactive, the script will default to Blender's 'datadir'.
Select Object: Used to change the script's active object, no need to restart the script.
Import XXX: Select to import this color. The inactive colors will not be affected on import. This does not affect exporting.
Hotkeys:
Q: [Q]uit
"""
import math
from Blender import Get, NMesh
from Blender import Text as TexT
from Blender.Object import GetSelected
from Blender.Draw import *
from Blender.BGL import *
from Blender.Window import FileSelector, Theme
##############################
btnPath = Create(Get("datadir"))
useRed = Create(1)
useGreen = Create(1)
useBlue = Create(1)
colPerVert = Create(1)
savePath = Create(0)
message = ""
ob = None
##############################
#load settings
def init():
global btnPath, useRed, useGreen, useBlue, colPerVert, savePath
try:
t = TexT.Get("vertcols.ini").asLines()
except NameError:
pass
else:
useRed.val = int(t[0])
useGreen.val = int(t[1])
useBlue.val = int(t[2])
colPerVert.val = int(t[3])
savePath.val = int(t[4])
if savePath.val:
btnPath.val = t[5].strip()
t = None
#save settings
def saveini():
global btnPath, useRed, useGreen, useBlue, colPerVert, savePath
try:
t = TexT.Get("vertcols.ini")
except NameError:
t = TexT.New("vertcols.ini")
t.clear()
print useRed.val
t.write(str(useRed.val) + "\n")
t.write(str(useGreen.val) + "\n")
t.write(str(useBlue.val) + "\n")
t.write(str(colPerVert.val) + "\n")
t.write(str(savePath.val) + "\n")
if savePath.val:
pos=btnPath.val.rfind("\\")
if pos == -1:
pos=btnPath.val.rfind("/")
t.write(str(btnPath.val[:pos+1]) + "\n")
##############################
#select active object
def getObject():
global ob, message
try:
ob = None #to avoid errors
ob = GetSelected()[0]
if ob.getType() == "Mesh":
message = "The script now works on: %s" % ob.name
else:
message = "Active object is not a mesh! Select a mesh and click \"Select Object\"."
ob = None
except IndexError:
message = "No object active! Select a mesh and click \"Select Object\"."
Redraw()
##############################
#saves 24-bit raw tga
def write_tgafile(path):
global message
if ob == None:
message = "No object active! Select a mesh and click \"Select Object\"."
else:
#update our nmesh
me = ob.getData()
#get all vertcols
facelist = me.faces
collist = []
message = "Vertex colors saved"
##########################################
if colPerVert.val == 1:
for v in me.verts:
collist.append(NMesh.Col())
for f in facelist:
try:
collist[f.v[0].index] = f.col[0]
except IndexError:
message = "Active object has no vertex colors!"
else:
collist[f.v[1].index] = f.col[1]
collist[f.v[2].index] = f.col[2]
try:
collist[f.v[3].index] = f.col[3]
except IndexError:
pass
if message != "Active object has no vertex colors!":
#write tga
try:
f = open(path, 'wb')
except IOError:
message = "Error while trying to write file!"
else:
header = []
for t in range(18):
header.append(chr(0))
header[2] = chr(2)
sizeX = int(math.sqrt(len(collist)))
sizeY = int(len(collist) / sizeX) + 1
header[13] = chr(sizeX / 256)
header[12] = chr(sizeX % 256)
header[15] = chr(sizeY / 256)
header[14] = chr(sizeY % 256)
header[16] = chr(24)
for t in header:
f.write(t)
del header
size = sizeX * sizeY
x = 0
while x < size:
try:
f.write(chr(collist[x].b))
f.write(chr(collist[x].g))
f.write(chr(collist[x].r))
except IndexError:
f.write(chr(0))
f.write(chr(0))
f.write(chr(0))
x += 1
f.close()
##########################################
else:
for f in facelist:
try:
collist.append(f.col[0].b)
except IndexError:
message = "Active object has no vertex colors!"
else:
collist.append(f.col[0].g)
collist.append(f.col[0].r)
collist.append(f.col[1].b)
collist.append(f.col[1].g)
collist.append(f.col[1].r)
collist.append(f.col[2].b)
collist.append(f.col[2].g)
collist.append(f.col[2].r)
collist.append(f.col[3].b)
collist.append(f.col[3].g)
collist.append(f.col[3].r)
if message != "Active object has no vertex colors!":
#write tga
try:
f = open(path, 'wb')
except IOError:
message = "Error while trying to write file!"
else:
header = []
for t in range(18):
header.append(chr(0))
header[2] = chr(2)
sizeX = int(math.sqrt(len(collist) / 3))
sizeY = int(len(collist) / 3 / sizeX) + 1
header[13] = chr(sizeX / 256)
header[12] = chr(sizeX % 256)
header[15] = chr(sizeY / 256)
header[14] = chr(sizeY % 256)
header[16] = chr(24)
for t in header:
f.write(t)
size = sizeX * sizeY * 3 #r,g and b values
x = 0
while x < size:
try:
f.write(chr(collist[x]))
x += 1
except IndexError:
f.write(chr(0))
x += 1
f.close()
Redraw()
##############################
#reads 24-bit raw tga
def read_tgafile(path):
global message, ob
if ob == None:
message = "No object active! Select a mesh and click \"Select Object\"."
else:
try:
f = open(path, 'rb')
except IOError:
message = "Error while trying to open file!"
else:
header = f.read(18)
if header[2] != chr(2):
message = "Input format should be 24-bit raw tga"
f.close()
else:
data = f.read()
f.close()
#apply vertcols to mesh
me = ob.getData()
pos = 0
facelist = me.faces
red = useRed.val
green = useGreen.val
blue = useBlue.val
######################################
message = "Vertex colors loaded"
if colPerVert.val == 1:
collist = []
while pos < len(data)-2:
print len(data), pos
collist.append( NMesh.Col( ord(data[pos + 2]), ord(data[pos + 1]), ord(data[pos]) ) )
pos += 3
for f in facelist:
try:
if blue == 1: f.col[0].b = collist[f.v[0].index].b
if green == 1: f.col[0].g = collist[f.v[0].index].g
if red == 1: f.col[0].r = collist[f.v[0].index].r
if blue == 1: f.col[1].b = collist[f.v[1].index].b
if green == 1: f.col[1].g = collist[f.v[1].index].g
if red == 1: f.col[1].r = collist[f.v[1].index].r
if blue == 1: f.col[2].b = collist[f.v[2].index].b
if green == 1: f.col[2].g = collist[f.v[2].index].g
if red == 1: f.col[2].r = collist[f.v[2].index].r
try:
if blue == 1: f.col[3].b = collist[f.v[3].index].b
if green == 1: f.col[3].g = collist[f.v[3].index].g
if red == 1: f.col[3].r = collist[f.v[3].index].r
except IndexError:
if blue == 1: f.col[3].b = 0.
if green == 1: f.col[3].g = 0.
if red == 1: f.col[3].r = 0.
except IndexError:
message = "Object must have VertCol or TexFace button active in EditButtons"
######################################
else:
for f in facelist:
try:
if blue == 1: f.col[0].b = ord(data[pos])
if green == 1: f.col[0].g = ord(data[pos + 1])
if red == 1: f.col[0].r = ord(data[pos + 2])
if blue == 1: f.col[1].b = ord(data[pos + 3])
if green == 1: f.col[1].g = ord(data[pos + 4])
if red == 1: f.col[1].r = ord(data[pos + 5])
if blue == 1: f.col[2].b = ord(data[pos + 6])
if green == 1: f.col[2].g = ord(data[pos + 7])
if red == 1: f.col[2].r = ord(data[pos + 8])
if blue == 1: f.col[3].b = ord(data[pos + 9])
if green == 1: f.col[3].g = ord(data[pos + 10])
if red == 1: f.col[3].r = ord(data[pos + 11])
except IndexError:
message = "Object must have VertCol or TexFace button active in EditButtons"
pos += 12
me.update()
Redraw()
##############################
def gui():
global btnPath, savePath, useRed, useGreen, useBlue, colPerVert
col = Theme.Get()[0].get("buts").back
glClearColor(col[0]/255., col[1]/255., col[2]/255., col[3]/255.)
glClear(GL_COLOR_BUFFER_BIT)
col = Theme.Get()[0].get("buts").text_hi
glColor3f(col[0]/255., col[1]/255., col[2]/255.)
Button("Select Object", 5, 190, 10, 100, 20, "Change the object the script works on")
Button("Load", 3, 10, 150, 80, 20, "Load vertex colors from the tga and apply it to the mesh")
Button("Save", 4, 210, 150, 80, 20, "Save the meshs vertex colors to the tga")
useRed = Toggle("Import Red", 2, 10, 120, 93, 20, useRed.val, "Toggle import of red vertex color")
useGreen = Toggle("Import Green", 2, 103, 120, 94, 20, useGreen.val, "Toggle import of green vertex color")
useBlue = Toggle("Import Blue", 2, 197, 120, 93, 20, useBlue.val, "Toggle import of blue vertex color")
colPerVert = Toggle("Per Vertex", 2, 110, 150, 80, 20, colPerVert.val, "Load and save vertex colors per vertex or per face (per face will create bigger files)")
Button("Exit", 1, 10, 10, 100, 20, "This one should explain itself :)")
Button("Fileselector", 6, 10, 90, 100, 20, "Show fileselector to select filename")
savePath = Toggle("Remember Path", 2, 190, 90, 100, 20, savePath.val, "Remember path or use Blender's datadir")
btnPath = String("Path: ", 2, 10, 60, 280, 20, btnPath.val, 255, "Path of the file to load and save")
glRasterPos2i(132, 15)
Text("by pat")
glRasterPos2i(10, 40)
Text(message)
def event(evt, val):
if (evt == QKEY and not val):
saveini()
Exit()
def f(filename):
global btnPath
btnPath.val = filename
Redraw()
def bevent(evt):
global btnPath
if (evt == 1):
saveini()
Exit()
elif (evt == 3): read_tgafile(btnPath.val.strip())
elif (evt == 4): write_tgafile(btnPath.val.strip())
elif (evt == 5): getObject()
elif (evt == 6): FileSelector(f, "Select file or path", btnPath.val)
init()
getObject()
Register(gui, event, bevent)