import poser, Numeric import os, tkFileDialog, gzip import ScrolledText,tkFont from Tkinter import * scene = poser.Scene() def make_proxy(): """Saves and loads a blank cr2 so pose can be applied if no figure exists in the scene""" lines = ['{\n', 'version\n', '\t{\n', '\tnumber 5\n', '\t}\n', '\n', 'actor BODY:9\n', '\t{\n', '\n', '\t}\n', 'actor hip:9\n', '\t{\n', '\n', '\t}\n', 'actor BODY:9\n', '\t{\n', '\tname temp\n', '\toff\n', '\tbend 1\n', '\tdynamicsLock\t\t1\n', '\thidden\t\t0\n', '\taddToMenu\t1\n', '\tincludeInDepthCue\t\t0\n', '\tparent UNIVERSE\n', '\tchannels\n', '\t\t{\n', '\t\tvalueParm 1\n', '\t\t\t{\n', '\t\t\tname 1\n', '\t\t\thidden 0\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\tlin\n', '\t\t\t\t}\n', '\t\t\t}\n', '\t\tvalueParm 2\n', '\t\t\t{\n', '\t\t\tname 2\n', '\t\t\thidden 0\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\tlin\n', '\t\t\t\t}\n', '\t\t\t}\n', '\t\tvalueParm 3\n', '\t\t\t{\n', '\t\t\tname 3\n', '\t\t\thidden 0\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\tlin\n', '\t\t\t\t}\n', '\t\t\t}\n', '\t\t}\n', '\tendPoint 0 0.735952 0.25\n', '\torigin 0 0.441 0\n', '\torientation 0 0 0\n', '\tdisplayOrigin\t\t0\n', '\tdisplayMode USEPARENT\n', '\tcustomMaterial\t0\n', '\t}\n', 'actor hip:9\n', '\t{\n', '\tname GetStringRes(1024,6)\n', '\ton\n', '\tbend 1\n', '\tdynamicsLock\t\t1\n', '\thidden\t\t0\n', '\taddToMenu\t1\n', '\tcastsShadow\t\t1\n', '\tincludeInDepthCue\t\t1\n', '\tparent BODY:9\n', '\tchannels\n', '\t\t{\n', '\t\ttaperY taper\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,1)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.04\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\tzOffsetA zOffset\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,38)\n', '\t\t\tinitValue -0.005\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue -0.005\n', '\t\t\t}\n', '\t\tyOffsetA yOffset\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,37)\n', '\t\t\tinitValue 0.393\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue 0.393\n', '\t\t\t}\n', '\t\txOffsetA xOffset\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,36)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue 0\n', '\t\t\t}\n', '\t\tscale scale\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,5)\n', '\t\t\tinitValue 1\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin 0.1\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 1\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\tscaleX xScale\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,6)\n', '\t\t\tinitValue 1\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin 0.1\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 1\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\tscaleY yScale\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,7)\n', '\t\t\tinitValue 1\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin 0.1\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 1\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\tscaleZ zScale\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,8)\n', '\t\t\tinitValue 1\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin 0.1\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 1\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\trotateY yrot\n', '\t\t\t{\n', '\t\t\tname yrot\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -360000\n', '\t\t\tmax 360000\n', '\t\t\ttrackingScale 1\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\trotateZ zrot\n', '\t\t\t{\n', '\t\t\tname zrot\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -360000\n', '\t\t\tmax 360000\n', '\t\t\ttrackingScale 1\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\trotateX xrot\n', '\t\t\t{\n', '\t\t\tname xrot\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -360000\n', '\t\t\tmax 360000\n', '\t\t\ttrackingScale 1\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\txOffsetB xTranB\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,33)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue 0\n', '\t\t\t}\n', '\t\tyOffsetB yTranB\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,34)\n', '\t\t\tinitValue -0.393\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue -0.393\n', '\t\t\t}\n', '\t\tzOffsetB zTranB\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,35)\n', '\t\t\tinitValue 0.005\n', '\t\t\thidden 1\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.004\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 1\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\tstaticValue 0.005\n', '\t\t\t}\n', '\t\ttranslateX xtran\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,12)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.001\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\ttranslateY ytran\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,13)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.001\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\ttranslateZ ztran\n', '\t\t\t{\n', '\t\t\tname GetStringRes(1028,14)\n', '\t\t\tinitValue 0\n', '\t\t\thidden 0\n', '\t\t\tforceLimits 0\n', '\t\t\tmin -100000\n', '\t\t\tmax 100000\n', '\t\t\ttrackingScale 0.001\n', '\t\t\tkeys\n', '\t\t\t\t{\n', '\t\t\t\tstatic 0\n', '\t\t\t\tk 0 0\n', '\t\t\t\t}\n', '\t\t\tinterpStyleLocked 0\n', '\t\t\t}\n', '\t\t}\n', '\tendPoint 0 0.293 -0.005\n', '\torigin 0 0.393 -0.005\n', '\torientation 0 0 0\n', '\tdisplayOrigin\t\t0\n', '\tdisplayMode USEPARENT\n', '\tcustomMaterial\t0\n', '\tlocked 0\n', '\tbackfaceCull 0\n', '\tvisibleInReflections 1\n', '\tvisibleInRender 1\n', '\tdisplacementBounds 0\n', '\tshadingRate 0.2\n', '\tsmoothPolys 1\n', '\t}\n', 'figure\n', '\t{\n', '\tname temp\n', '\troot BODY:9\n', '\taddChild hip:9\n', '\tBODY:9\n', '\tdefaultPick BODY:9\n', '\tdisplayOn 1\n', '\tallowsBending 0\n', '\tfigureType 1217\n', '\torigFigureType 1217\n', '\tcanonType 8\n', '\tdisplayMode USEPARENT\n', '\t}\n', '}\n'] path = os.path.normpath(os.path.join(os.path.dirname(poser.AppLocation()),"blank.cr2")) if os.path.exists(path): # Don't overwrite an existing file! count = 0 splitname = os.path.splitext(path) while os.path.exists(path): path = "%s_%s%s" %(splitname[0],count,splitname[1]) count += 1 cr2file = open(path,"w") for line in lines: cr2file.write(line) cr2file.close() scene.LoadLibraryFigure(path) os.remove(path) def make_pose(act,geompath,geomtype): """Assemble the geometry-insertion pose""" fig = act.ItsFigure() name = act.InternalName() fignum = "" if fig: if name.find(":") != -1: fignum = ":%s" %(name.split(":")[1]) actnames = [i.InternalName() for i in fig.Actors()] weld_to = [0 for i in fig.Actors()] # Parent and other actors to which actor is welded weld_from = [0 for i in fig.Actors()] # Weld goals: children of body part actor for act2 in fig.Actors(): if act2.Geometry(): if act2.InternalName() == name: for wa in act2.WeldGoalActors(): weld_from[actnames.index(wa.InternalName())] = 1 else: for wa in act2.WeldGoalActors(): if wa.InternalName() == name: weld_to[actnames.index(act2.InternalName())] = 1 else: # This shouldn't happen; objFileGeom should always be sent for props geomtype = "objFileGeom" pose = "{\nversion\n\t{\n\tnumber %s\n\t}\n" %(poser.Version()) # Header if geomtype == "geomHandlerGeom": pose += "figureResFile %s\n" %(geompath) # Need the base figure geometry listing to restore body part pose += "actor %s\n\t{\n\tstorageOffset 0 0 0\n" %(name.replace(fignum,"")) if geomtype == "geomHandlerGeom": pose += "\t%s 13 %s\n" %(geomtype,name.replace(fignum,"")) if geomtype == "objFileGeom": pose += "\t%s 0 0 %s\n" %(geomtype,geompath) pose += "\t}\n" if fig: # All of this is for weld handling, which apparently may not always necessary, but can be. for ai in range(len(actnames)): if weld_to[ai] or weld_from[ai] or actnames[ai] == name: pose += "actor %s\n\t{\n\n\t}\n" %(actnames[ai].replace(fignum,"")) pose += "figure\n\t{\n" for ai in range(len(actnames)): if weld_to[ai]: if actnames[ai] != name: pose += "\tweld %s\n" %(actnames[ai].replace(fignum,"")) pose += "\t%s\n" %(name.replace(fignum,"")) if weld_from[ai]: if actnames[ai] != name: pose += "\tweld %s\n" %(name.replace(fignum,"")) pose += "\t%s\n" %(actnames[ai].replace(fignum,"")) pose += "\t}\n" else: pose += "actor %s\n\t{\n\n\t}\n" %(name) pose += "}" app.scrollT.delete(1.0,END) app.scrollT.insert(END,pose) def geom_data(geom,path,compress): """Gather the geometry data for the objstring""" sets = [i for i in geom.Sets()] polys = [[p.Start(),p.NumVertices()] for p in geom.Polygons()] verts = [[i.X(),i.Y(),i.Z()] for i in geom.Vertices()] has_UVs,tverts = UVs(geom) if not has_UVs: tverts = planar_map(verts) tsets = [i for i in geom.TexSets()] tpolys = [[p.Start(),p.NumVertices()] for p in geom.Polygons()] objstring = make_objstring(geom,verts,polys,sets,tverts,tpolys,tsets) save_obj(objstring,path,compress) def b_box_ock(vertpos): """ create bounding boxes """ minX = 1000000.0; maxX = -1000000.0 minY = 1000000.0; maxY = -1000000.0 minZ = 1000000.0; maxZ = -1000000.0 for i in range(len(vertpos)): tx = vertpos[i][0] ty = vertpos[i][1] tz = vertpos[i][2] if tx < minX: minX = tx if tx > maxX: maxX = tx if ty < minY: minY = ty if ty > maxY: maxY = ty if tz < minZ: minZ = tz if tz > maxZ: maxZ = tz return [minX,maxX,minY,maxY,minZ,maxZ] def planar_map(verts): """Create a planar map if there are no UVs. Uses z axis.""" bbox = b_box_ock(verts) minx = bbox[0] maxx = bbox[1] sizex = maxx - minx miny = bbox[2] maxy = bbox[3] sizey = maxy - miny tverts = [[] for i in range(len(verts))] for vi in range(len(verts)): vert = verts[vi] u = (vert[0] - minx)/sizex v = (vert[1] - miny)/sizey tverts[vi] = [u,v] return tverts def UVs(geom,remap=0): """ Organize the UV data into a Numeric array """ if remap: return 0,[] try: uvverts = [i for i in geom.TexVertices()] except: return 0,[] 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 1,uvs def make_objstring(geom,verts,polys,sets,tverts,tpolys,tsets,preview=0): """ Format geometry data for .obj/GeomCustom export. Uses local verts, not world verts. Function uses arrays built in in_box() because we may be adding new UV data if it wasn't already present. Writes out the most minimal obj possible, hopefully.... """ objstring = "" for vert in verts: objstring += "v %.5f %.5f %.5f\n" %(vert[0],vert[1],vert[2]) for tvert in tverts: objstring += "vt %.5f %.5f\n" %(tvert[0],tvert[1]) gline = "" usemtl = "Preview" if not geom.Groups(): objstring += "g %s\n" %(gline) for pi in range(len(polys)): poly = geom.Polygon(pi) groups = poly.Groups() if groups: gstring = "" for gi in range(len(groups)): gstring += groups[gi] if gi < len(groups)-1: gstring += " " if gline != gstring: objstring += "g %s\n" %(gstring) gline = gstring mat = poly.MaterialName() if mat != usemtl: objstring += "usemtl %s\n" %(mat) usemtl = mat s = polys[pi][0] l = polys[pi][1] poly = [v for v in sets[s:s+l]] s = tpolys[pi][0] l = tpolys[pi][1] tpoly = [v for v in tsets[s:s+l]] fstring = "f " for i in range(l): fstring += "%s/%s" %(poly[i]+1,tpoly[i]+1) # Obj format indexes from 1, not 0 if i < l-1: fstring += " " if pi < len(polys)-1: fstring += "\n" objstring += fstring if preview: app.scrollT.insert(END,objstring) return objstring def save_obj(objstring,path,compress): """Save the .obj file""" if compress: out = gzip.GzipFile(path,"wb") else: out = open(path,"w") out.write(objstring) out.close() def gzip_data(dataPath,replace=0,swap_ext=1): """ Compress or decompress file, with option to replace. """ try: compressed = check_gzip(dataPath) if swap_ext: path,ext = dataPath.split(".") if ext == "vwt": dataPath = "%s.vwz" %(path) if ext == "vwz": dataPath = "%s.vwt" %(path) if compressed: f = gzip.GzipFile(dataPath) else: f = open(dataPath,"r") g = f.read() f.close() if not replace: dataPath = protect_naming(dataPath) if compressed: f = open(dataPath,"w") else: f = gzip.GzipFile(dataPath,"wb") f.write(g) f.close() except: print "gzip_data() error: could not process selected file." return def protect_naming(path): """Ensure unique file naming to avoid overwriting anything.""" folder = os.path.dirname(path) filename = os.path.basename(path) name,ext = filename.split(".") if os.path.exists(path): num = 0 newname = "%s_%s.%s" %(name,num,ext) while os.path.exists(os.path.join(folder,newname)): num += 1 newname = "%s_%s.%s" %(name,num,ext) return os.path.normpath(os.path.join(folder,newname)) else: return path root = Tk() class App: def __init__(self, master): self.master = master master.title("Replace geomCustom 2a") self.gzVar = IntVar() self.gzVar.set(0) self.delVar = IntVar() self.delVar.set(1) self.act = scene.CurrentActor() self.geom = self.act.Geometry() self.act_type = "body part" if self.act.IsProp(): self.act_type = "prop" self.errorflag = 0 self.runflag = 0 self.geomtype = "" self.basepath = "Runtime:Geometries:" self.posepath = os.path.dirname(poser.AppLocation()) self.geompath = os.path.normpath(os.path.join(self.posepath,self.basepath.replace(":",os.sep))) self.font = tkFont.Font(family="courier new", size=9, weight=NORMAL) self.metamasterFrame = Frame(self.master) self.metamasterFrame.grid(row=0,column=0) self.masterFrame = Frame(self.metamasterFrame) self.masterFrame.grid(row=1,column=0) self.displayFrame = Frame(self.metamasterFrame) self.displayFrame.grid(row=2,column=0) self.mixFrame = Frame(self.masterFrame,borderwidth=2,relief=RIDGE) self.mixFrame.grid(row=1,column=3) self.buttonFrame = Frame(self.mixFrame,borderwidth=2) self.buttonFrame.grid(row=1,column=0) self.quitFrame = Frame(self.mixFrame,borderwidth=3) self.quitFrame.grid(row=2,column=0) self.checkFrame = Frame(self.mixFrame,borderwidth=2) self.checkFrame.grid(row=3,column=0) # --- Entries --- self.pathEntry = Entry(self.displayFrame, width=117) self.pathEntry.insert(0,"") self.pathEntry.grid(row=1,column=0) # --- Listboxes --- self.statusEntry = Listbox(self.displayFrame, height=4, width=117, selectmode=SINGLE,exportselection=0) # Status bar self.statusEntry.grid( row=2, column=0) # --- ScrolledText --- self.scrollT = ScrolledText.ScrolledText(self.displayFrame,background="white",height=25,width=98,undo=TRUE,font=self.font) self.scrollT.grid(row=3,column=0) # --- Checkboxes --- self.gzCheck = Checkbutton(self.checkFrame,text="Compress Files", variable=self.gzVar) self.gzCheck.grid(row = 1, column = 0) self.delCheck = Checkbutton(self.checkFrame,text="Delete Pose When Done", variable=self.delVar,command=self.deltoggle) self.delCheck.grid(row = 1, column = 1) # --- Buttons --- self.buttonRun = Button(self.buttonFrame, text="Export .obj", command=self.handleExport) self.buttonRun.grid(row=0, column=0) self.buttonRun = Button(self.buttonFrame, text="Browse for .obj", command=self.handleExternal) self.buttonRun.grid(row=0, column=1) self.buttonRun = Button(self.buttonFrame, text="Restore base geometry", command=self.handleRestore) self.buttonRun.grid(row=0, column=2) self.buttonRun = Button(self.quitFrame, text="Preview pose", command=self.handleText) self.buttonRun.grid(row=1, column=0) self.buttonRun = Button(self.quitFrame, text="Apply pose", command=self.handleRun) self.buttonRun.grid(row=1, column=1) self.buttonPath = Button(self.quitFrame, text="Change pose path", command=self.handlePath) self.buttonPath.grid(row=1, column=2) self.buttonQuit = Button(self.quitFrame, text="Quit", command=self.die) self.buttonQuit.grid(row=1, column=3) if self.act.GeomFileName(): self.path_update(self.act.GeomFileName()) else: self.path_update(self.geompath) self.geomtype,line = self.get_geom_current() self.status_update("Ready. Current actor is %s %s. %s" %(self.act_type,self.act.Name(),line),0) self.status_update("No errors.",1) self.status_update("Pose path: %s" %(self.posepath),2) self.status_update("Pose will be removed at end of run.",3) def path_update(self,path): """Displays the current geometry path for objFileGeom or geomHandlerGeom""" path = os.path.normpath(path) path = path.replace(os.sep,":") if path.find("Runtime:") != -1: path = ":Runtime:%s" %(path.split("Runtime:")[1]) else: self.status_update("Error: Selected geometry path is not inside Runtime. Pose will not work properly.",1) self.errorflag = 1 # Prevent script from running a pose which won't work with relative path self.pathEntry.delete(0,END) self.pathEntry.insert(0,path) #self.pathEntry.index(len(self.basepath)-1) # self.pathEntry.update() def status_update(self,message,line): """Displays entertaining messages pertaining to the process.""" self.statusEntry.delete(line) self.statusEntry.insert(line,message) self.statusEntry.update() def deltoggle(self): delfile = self.delVar.get() if not delfile: self.status_update("Pose will not be removed at end of run.",3) else: self.status_update("Pose will be removed at end of run.",3) def die(self): """Ends the script""" root.destroy() root.quit() def get_geom_current(self): """Gets the geometry handling of the actor at script start. Absolutely unnecessary, but interesting, perhaps.""" if not self.act.GeomFileName(): return "geomCustom","Current geom handling is geomCustom." if self.act.ItsFigure(): if self.act.GeomFileName() != self.act.ItsFigure().GeomFileName(): return "objFileGeom","Current geom handling is objFileGeom." else: return "geomHandlerGeom","Current geom handling is geomHandlerGeom." else: return "objFileGeom","Current geom handling is objFileGeom." def handleExport(self): """Exports current actor geom (with groups) and sets up new obj as objFileGeom listing""" init = "Untitled.obj" types = [(".obj files", "*.obj *.OBJ")] compress = self.gzVar.get() if compress: init = "Untitled.obz" types = [(".obz files", "*.obz *.OBZ")] path = tkFileDialog.asksaveasfilename(initialdir=self.geompath,initialfile=init,filetypes=types) if path: self.geompath = path self.path_update(self.geompath) geom_data(self.geom,self.geompath,compress) self.status_update("Pose will use objFileGeom with path for %s %s" %(self.act_type,self.act.Name()),0) self.geomtype = "objFileGeom" def handleExternal(self): """Sets objFileGeom listing for actor""" init = "Untitled.obj" types = [(".obj files", "*.obj *.OBJ *.obz *.OBZ")] path = tkFileDialog.askopenfilename(initialdir=self.geompath,initialfile=init,filetypes=types) if path: if not os.path.exists(path): self.status_update("Error: No file at selected geometry path location. No action taken.",1) return self.geompath = path self.path_update(self.geompath) self.status_update("Pose will use objFileGeom with path for %s %s" %(self.act_type,self.act.Name()),0) self.geomtype = "objFileGeom" def handleRestore(self): """Restores geomHandlerGeom listing for body part actor""" fig = self.act.ItsFigure() if not fig: # This only works with body part actors self.status_update("Error: Selected actor is not a body part. No action taken.",1) return path = fig.GeomFileName() self.geompath = path self.path_update(self.geompath) self.status_update("Pose will use geomHandlerGeom for %s %s" %(self.act_type,self.act.Name()),0) self.geomtype = "geomHandlerGeom" def handleText(self): """ Assembles the pose and sends it to the scrolled text preview """ make_pose(self.act,self.geompath,self.geomtype) self.runflag = 1 def handlePath(self): path = tkFileDialog.askdirectory(initialdir=self.posepath) if path: self.posepath = path self.status_update("Pose path: %s" %(self.posepath),2) if path.find("Runtime:") == -1 and path != os.path.dirname(poser.AppLocation()): self.status_update("Error: Poser may have trouble locating a pose which is outside of Runtime and not in the Poser application folder.",1) def handleRun(self): """ Writes the pose from the preview. Allows the potential for hand-editing by user, prior to write. """ if not self.errorflag: if self.runflag: delfile = self.delVar.get() compress = self.gzVar.get() ext = ".pz2" if compress: ext = ".pzz" path = os.path.join(os.path.normpath(self.posepath),"%s%s" %(self.act.Name(),ext)) path = protect_naming(path) if compress: out = gzip.GzipFile(path,"wb") else: out = open(path,"w") out.write(self.scrollT.get(1.0,END)) out.close() delfig = 0 if not len(scene.Figures()): delfig = 1 make_proxy() self.status_update("Pose path: %s" %(path),2) scene.LoadLibraryPose(path) path = os.path.normpath(path) if delfile: os.remove(path) if delfig: scene.DeleteCurrentFigure() scene.SelectActor(self.act) self.geomtype,line = self.get_geom_current() # Check the effect the pose had and refresh the display. self.status_update("Done. Current actor is %s %s. %s" %(self.act_type,self.act.Name(),line),0) else: self.status_update("Must preview a pose before applying it.",0) else: self.status_update("Error: Selected geometry path is not inside Runtime. Run cancelled.",1) app = App(root) root.mainloop()