#!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)