import poser import Numeric, os import tkFileDialog,tkMessageBox from ArrayPrinter import * from Tkinter import * from Tkinter import _cnfmerge scene = poser.Scene() root = Tk() def run(): d = Dialog(None, {'title': 'Geometry from lists', 'text': 'What do you want to do?', 'bitmap': '', 'default': 0, 'strings': ('Cancel','Export lists','Create from lists','Make Tri Copy') } ) what = d.num d.quit() del d if not what: root.destroy() return if what == 1: lists = saveLists() del lists return elif what == 2: readlists() return elif what == 3: lists = saveLists(tris=1) del lists return class Dialog(Widget): """From lib-tk.Dialog.py""" def __init__(self, master=None, cnf={}, **kw): cnf = _cnfmerge((cnf, kw)) self.widgetName = '__dialog__' Widget._setup(self, master, cnf) self.num = self.tk.getint( self.tk.call( 'tk_dialog', self._w, cnf['title'], cnf['text'], cnf['bitmap'], cnf['default'], *cnf['strings'])) try: Widget.destroy(self) except TclError: pass def destroy(self): pass #=============================================================================================== # vertexPos() #=============================================================================================== def vertexPos(geom,worldspace=1,multiple=1.0): """ Pre-fetch vertex coordinates for faster access. Returns a Numeric array of vert coords by vert indices Send worldspace=0 keyword when calling function, to use localspace """ numVerts = geom.NumVertices() verts = [[0.0,0.0,0.0] for i in range(numVerts)] verts = Numeric.array(verts,Numeric.Float) for i in range(numVerts): if worldspace: v = geom.WorldVertex(i) else: v = geom.Vertex(i) verts[i] = [v.X(),v.Y(),v.Z()] return verts class Geom: def __init__(self,act,vertpos,gtype,*args,**kws): if act == None or vertpos == None: return None self.verts = vertpos self.mats1 = [] self.mats2 = [] if not kws.has_key("geom"): geom = act.Geometry() else: geom = kws["geom"] if "geom" in args: self.geom = act.Geometry() self.polyverts(geom,geom.Polygons()) if gtype == "UV": self.polyverts(geom,geom.TexPolygons(),UV=1) self.triverts(geom.Polygons(),puv=self.puvverts,tracking=1) if "tris" in args: self.vertuvs(geom,self.tverts,self.tuvverts) else: self.vertuvs(geom,self.pverts,self.puvverts) #-----polygon lists------------------------------------------------------- def polyverts(self,geom,polys,UV=0): """ vertices by polygon - this is the Sets() list broken down by polygon index. Returns a list of Numeric arrays """ if UV: self.puvverts = [] gset = geom.TexSets() else: self.pverts = [] gset = geom.Sets() for p in polys: if UV: l = p.NumTexVertices() else: l = p.NumVertices() s = p.Start() e = s + l vl = Numeric.array([v for v in gset[s:e]],Numeric.Int) if UV: self.puvverts.append(vl) else: self.pverts.append(vl) def triverts(self,polys,matlist=[],puv=[],tracking=0): """ polygons broken into triangles. returns: self.tverts = list of new tri-polys as Numeric array polys is a list of Geometry().Polygons() matlist is a materials selection list, returned by app (or a blank list) self.tmats is materials indices by tri indices puv is self.puvverts (or a blank list) self.tuvverts is texvertices by tri """ self.tverts = [] if matlist != []: self.tmats = [] if puv != []: self.tuvverts = [] if tracking: self.p2t = [[] for i in range(len(self.pverts))] tv = 0 # Keep count of new tri indices for p_i in range(len(self.pverts)): p = self.pverts[p_i] for t_i in range(1,len(p)-1): # Number of tris per poly will be number of verts in poly, minus 2 self.tverts.append([p[0],p[t_i],p[t_i+1]]) # Add the new triangles if tracking: self.p2t[p_i].append(tv) if matlist != []: self.tmats.append(polys[p_i].MaterialIndex()) if puv: self.tuvverts.append([puv[p_i][0],puv[p_i][t_i],puv[p_i][t_i+1]]) tv += 1 self.tverts = Numeric.array(self.tverts,Numeric.Int) if tracking: self.t2p = [0 for i in range(len(self.tverts))] self.t2p = Numeric.array(self.t2p,Numeric.Int) for i in range(len(self.p2t)): for j in self.p2t[i]: self.t2p[j] = i self.p2t = [Numeric.array(self.p2t[i],Numeric.Int) for i in range(len(self.p2t))] if puv: self.tuvverts = Numeric.array(self.tuvverts,Numeric.Int) def vertuvs(self,geom,pgons,uvgons): """ Returns a Numeric array of vert indices to texvert indices for the geom pgons is pverts or tverts uvgons is puvverts or tuvverts Do not mix use of tris and polys! """ self.vuvverts = [[] for i in range(geom.NumVertices())] screen = [[] for i in range(geom.NumVertices())] for i in range(len(pgons)): for j in range(len(pgons[i])): if not uvgons[i][j] in screen[pgons[i][j]]: self.vuvverts[pgons[i][j]].append([uvgons[i][j],[i]]) screen[pgons[i][j]].append(uvgons[i][j]) #self.uvverts = Numeric.array(self.vuvverts,Numeric.Int) def geom_polys(self,geom,pgons,uvgons=[]): """ Organize existing lists into Numeric array format used by PoserPython to add a new geometry UV handling requires that self.vuvverts be defined. This will not end up copying over groups Materials groups will have to be added after the prop is generated pgons is pverts or tverts uvgons is puvverts or tuvverts """ self.gpolys = [] pos = 0 for p in pgons: self.gpolys.append([pos,len(p)]) pos += len(p) self.gsets = [] for pv in pgons: for v in pv: self.gsets.append(v) # self.verts should be used for gverts self.gpolys = Numeric.array(self.gpolys,Numeric.Int) self.gsets = Numeric.array(self.gsets,Numeric.Int) if uvgons != []: self.gtpolys = [] pos = 0 for uv in uvgons: self.gtpolys.append([pos,len(uv)]) pos += len(uv) self.gtsets = [] for p in uvgons: for uv in p: self.gtsets.append(uv) self.gtverts = [[0,0] for i in range(geom.NumTexVertices())] # The PoserPython manual is incorrect: the gtverts array is UV coords, not vertex coords. # See geom.bucky.py for the only example of which I know. self.gtpolys = Numeric.array(self.gtpolys,Numeric.Int) self.gtsets = Numeric.array(self.gtsets,Numeric.Int) self.gtverts = Numeric.array(self.gtverts,Numeric.Float) def readlists(): path = tkFileDialog.askopenfilename(initialdir=os.path.dirname(poser.AppLocation()),filetypes=[("Text files", "*.txt *.TXT")], initialfile="GeomLists.txt",title="Specify list file from which to build") root.destroy() if path: g = g_from_lists(path) newgeom = poser.NewGeometry() if g.have_UVs: newgeom.AddGeneralMesh(g.gpolys,g.gsets,g.verts,g.gtpolys,g.gtsets,g.gtverts) else: newgeom.AddGeneralMesh(g.gpolys,g.gsets,g.verts) if g.have_mats: for mat in g.matnames: newgeom.AddMaterialName(mat) for p_i in range(len(g.mats)): poly = newgeom.Polygon(p_i) poly.SetMaterialIndex(g.mats[p_i]) newprop = scene.CreatePropFromGeom(newgeom,"GeomLists_prop") scene.SelectActor(newprop) del g class g_from_lists(object): def __init__(self,path): self.have_mats = 0 self.have_UVs = 0 self.matnames = [] self.gtpolys = [] execfile(path) if self.matnames: self.have_mats = 1 if self.gtpolys: self.have_UVs = 1 class saveLists: def __init__(self,tris=0): if tris: self.makeLists2() else: self.path = tkFileDialog.asksaveasfilename(initialdir=os.path.dirname(poser.AppLocation()),filetypes=[("Text files", "*.txt *.TXT")], initialfile="GeomLists.txt",title="Specify save name for lists") self.usemats = tkMessageBox.askyesno(title="Include materials?",message="Include materials in lists?") root.destroy() self.makeLists() def UVs(self,geom): """ Organize the UV data into a Numeric array """ try: uvverts = [i for i in geom.TexVertices()] except: return [] uvs = [[] for i in range(geom.NumTexVertices())] for i in range(len(uvverts)): tv = uvverts[i] uvs[i] = [tv.U(),tv.V()] uvs = Numeric.array(uvs,Numeric.Float) uvverts = [] return uvs def exportlist(self,alist,name,depth=0,export=1,num=1,numtype="int",replace=0): # """ Export a list or array in a form that can be pasted into Python code for external testing. self.exportlist(self.verts,"self.verts") self.exportlist(self.edges,"self.edges",depth=1) """ array = type(Numeric.array([0,0],Numeric.Int)) skip = 1 if num: if isinstance(alist,array): if numtype == "float": tmpstr = array2string(alist,precision=6,separator=',') tmpstr = tmpstr.replace(',]',']').replace(']\n','],\n') skip = 0 if skip: if depth: if isinstance(alist[0][0],array): alist = [[list(j[i]) for i in range(len(j)) if isinstance(j,array)] for j in alist] if isinstance(alist[0],array): alist = [list(alist[i]) for i in range(len(alist)) if isinstance(alist[i],array)] if isinstance(alist,array): alist = list(alist) if export: liststr = "" if num: liststr = "Numeric.array(" if skip: tmpstr = str(alist) count = 0 for i in range(len(tmpstr)): if skip: if tmpstr[i] == " " and count >= 75: liststr += "\\\n" count = 0 liststr += tmpstr[i] if skip: count += 1 if num: if numtype == "int": liststr += ",Numeric.Int)" if numtype == "float": liststr += ",Numeric.Float)" path = self.path if not os.path.exists(path) or replace: temp = open(path,"w") else: temp = open(path,"a") temp.write("self.%s = %s\n\n#==== END %s ====\n\n" %(name,liststr,name)) temp.close() else: return alist def makeLists(self): """Organize data to send to export lists""" a = scene.CurrentActor() gtverts = self.UVs(a.Geometry()) if gtverts: g = Geom(a,vertexPos(a.Geometry()),"UV","geom") g.geom_polys(a.Geometry(),g.pverts,uvgons=g.puvverts) else: g = Geom(a,vertexPos(a.Geometry()),"geom") g.geom_polys(a.Geometry(),g.pverts) self.exportlist(g.verts,"verts",numtype="float",replace=1) self.exportlist(g.gpolys,"gpolys") self.exportlist(g.gsets,"gsets") if gtverts: self.exportlist(gtverts,"gtverts",numtype="float") self.exportlist(g.gtpolys,"gtpolys") self.exportlist(g.gtsets,"gtsets") if self.usemats: matnames = ["Preview"] for poly in g.geom.Polygons(): # We only want material names present in the current actor if not poly.MaterialName() in matnames: matnames.append(poly.MaterialName()) mats = [matnames.index(poly.MaterialName()) for poly in g.geom.Polygons()] # New geom will have Preview as first index if len(matnames) > 1: matnames.remove("Preview") if matnames != []: self.exportlist(matnames,"matnames",num=0) self.exportlist(mats,"mats",num=0) del g def makeLists2(self,tris=1): """Builds a copy of the current actor, using Numeric arrays and The Poser geometry API. Used here to build a triangulated copy.""" a = scene.CurrentActor() gtverts = self.UVs(a.Geometry()) if gtverts: if tris: g = Geom(a,vertexPos(a.Geometry()),"UV","tris","geom") g.geom_polys(a.Geometry(),g.tverts,uvgons=g.tuvverts) g.geom_polys(a.Geometry(),g.tverts) else: g = Geom(a,vertexPos(a.Geometry()),"UV","geom") g.geom_polys(a.Geometry(),g.pverts,uvgons=g.puvverts) g.geom_polys(a.Geometry(),g.pverts) else: if tris: g = Geom(a,vertexPos(a.Geometry()),"tris","geom") g.triverts(g.geom.Polygons()) g.geom_polys(a.Geometry(),g.tverts) else: g = Geom(a,vertexPos(a.Geometry()),"geom") g.geom_polys(a.Geometry(),g.pverts) matnames = ["Preview"] for poly in g.geom.Polygons(): # We only want material names present in the current actor if not poly.MaterialName() in matnames: matnames.append(poly.MaterialName()) if gtverts: if tris: mats = [-1 for i in g.tverts] for p_i in range(len(g.p2t)): name = g.geom.Polygon(p_i).MaterialName() for i in g.p2t[p_i]: mats[i] = matnames.index(name) else: mats = [matnames.index(poly.MaterialName()) for poly in g.geom.Polygons()] else: mats = [matnames.index(poly.MaterialName()) for poly in g.geom.Polygons()] matnames.remove("Preview") # newly created mesh will have Preview as first listed material newgeom = poser.NewGeometry() if gtverts: newgeom.AddGeneralMesh(g.gpolys,g.gsets,g.verts,g.gtpolys,g.gtsets,gtverts) else: newgeom.AddGeneralMesh(g.gpolys,g.gsets,g.verts) for mat in matnames: newgeom.AddMaterialName(mat) for p_i in range(len(mats)): poly = newgeom.Polygon(p_i) poly.SetMaterialIndex(mats[p_i]) newprop = scene.CreatePropFromGeom(newgeom,"newprop") scene.SelectActor(newprop) del g run()