import poser import Numeric, time, os, gzip from Tkinter import * import tkFileDialog, tkMessageBox no_pyd = 0 # With this transfer script, we only use the .pyd minimally; there is an option to run without it. try: from _tdmt import * except: no_pyd = 1 if (poser.Version() < 7.0) and (not poser.IsPro()): no_pyd = 1 if os.name == 'mac': no_pyd = 1 scene = poser.Scene() root = Tk() do_print = 0 compressFiles = 0 FILE_VERSION = "1.0" FLT_EPSILON = 1.19209290e-07 # Classic TDMT def run2(dataPath,actS,actT,morphs,transfer=0): """ The pyd function FlipWeightIndexing() unfortunately won't help us here, as we don't have hitpoint objects to send to it. So we use the old TDMT code. """ startT = time.time() if os.path.exists(dataPath): windex,weights = read_file(dataPath,actT.Geometry().NumVertices(),actS.Geometry().NumVertices()) if windex == None: readerror("Datafile for selected actors was not found." "Meshes must be analysed before morphs can be copied.\n") return else: readerror("No data file found" "Meshes must be analysed before morphs can be copied.\n") return flipmap = flip_weights(actS, windex, weights) morphsD = {} # First, get the worldspace verts without morph and magnet deformations. for parm in actT.Parameters(): if parm.IsMorphTarget() or parm.TypeCode() == 49: #poser.kParmCodeDEFORMERPROP: morphsD[parm.Name()] = parm.Value() parm.SetValue(0.0) good = 0 if transfer: transfer_shape2(actS,actT,actS.Name(),windex,weights) figname = "" if actS.ItsFigure(): figname = actS.ItsFigure().Name() + " " app.status_update("Transferring shape of %s%s to %s" %(figname,actS.Name(),actT.Name())) else: for themorph in morphs: app.status_update("Transferring %s to %s" %(themorph[0],actT.Name())) yesno = transfer_morph(actS, actT, themorph, flipmap, samename=0) good += yesno for parmname in morphsD.keys(): # Restore the morph and deformer settings parm = actT.Parameter(parmname) parm.SetValue(morphsD[parmname]) morphsD = {} app.status_update("Done: transferred %s morphs of %s to %s in %s seconds." %(good,len(morphs),actS.Name(),time.time()-startT)) def transfer_shape2(a1,a2,name,windex,weights): """ Transfers the actual current worldspace shape """ if no_pyd: v1 = vertexPos(a1.Geometry(),worldspace=1) v2 = vertexPos(a2.Geometry(),worldspace=1) else: v1 = psrWorldVertexList(a1.Geometry()) #v2 = psrVertexList(a2.Geometry()) v2 = psrWorldVertexList(a2.Geometry()) morphName = unique_name(name,a2,"_shape") a2.SpawnTarget(morphName) parm = a2.Parameter(morphName) for vi in range(a2.Geometry().NumVertices()): if windex[vi]: if no_pyd: point = [0.0,0.0,0.0] else: point = Vector() for i in range(len(windex[vi])): win = windex[vi][i] vpos = v1[win] way = weights[vi][i] point[0] += vpos[0] * way point[1] += vpos[1] * way point[2] += vpos[2] * way if no_pyd: delta = [0.0,0.0,0.0] for i in range(3): delta[i] = point[i] - v2[vi][i] else: delta = point - v2[vi] if delta: parm.SetMorphTargetDelta(vi, delta[0], delta[1], delta[2]) 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 #====== Morph transfer (adapted from TDMT_Spanki.py ====================================== def readerror(message): app.status_update(message) #err = tkMessageBox.showinfo("Error reading datafile",message) def transfer_error(msg): app.status_update(msg) #=============================================================================================== # File-reading and morph creation (adapted from TDMT Classic with minimal necessary changes) - Original function by Spanki #=============================================================================================== def read_file(path,numverts,srcverts): if not os.path.exists(path): return None, None indices = [[] for i in range(numverts)] weights = weights = [[] for i in range(numverts)] ext = os.path.splitext(path)[1] if ext == ".vmf": thefile = open(path,"r") else: thefile = gzip.GzipFile(path) if thefile: lines = thefile.readlines() thefile.close() header_found = 0 for line in lines: c = line.replace('\n','').split(None) # Split line on white-space #----- First check for blank and/or comment lines if len(c) == 0 or c[0][0] == '#': continue #----- Check for header record if c[0] == 'TDMT_Matched': header_found = 1 if len(c) > 1: version = c[1] # If the script relies on some specific format of the file, it can do that test here if len(c) > 2: sv_count = int(c[2]) if len(c) > 3: dv_count = int(c[3]) if sv_count != srcverts or dv_count != numverts: readerror("Incompatible vertex counts!") return None,None # Maybe insert code to display ok/cancel dialog if vert counts don't match #----- Check for description/comment records elif c[0] == 'comment:': if header_found == 0: readerror("Error reading comment in\n%s" %(line)) return None,None if len(c) > 1: uc = line.split(': ') user_comment = uc[1] #----- Check for actors record elif c[0] == 'actors:': if header_found == 0: readerror("Error reading actors in\n%s" %(line)) return None,None if len(c) > 1: source_actor = c[1] if len(c) > 2: target_actor = c[2] # Do whatever is needed with actor names here (or store for later) elif c[0] == "w": # This section has been altered to allow reading of .vmf files vi = int(c[1]) numweights = int(c[2]) for i in range(numweights): indices[vi].append(int(c[i+3])) if c[0] == "w": for i in range(numweights): weights[vi].append(float(c[i+numweights+3])) return indices, weights else: return None, None #=============================================================================================== # flip_weights() # # This function flips the association of weighting data from being indexed by target mesh indices # to being indexed by source mesh indices. This removes the need for nested looping and scanning # when creating morphs. # (Function drawn from original TDMT code. Written by Spanki.) #=============================================================================================== def flip_weights(actSrc, windex, weights): """Unchanged from TDMT Classic. Written by Spanki.""" numSrcVerts = actSrc.Geometry().NumVertices() numDstVerts = len(windex) flipmap = [[] for i in range(numSrcVerts)] # This table holds lists of index/weight pairs for i in range(numDstVerts): for j in range(len(windex[i])): sndx = windex[i][j] if sndx != -1 and sndx < numSrcVerts: # Sanity check index value weight = weights[i][j] if abs(weight) > FLT_EPSILON: # Don't bother tracking 0.0 weights flipmap[sndx].append([i,weight]) return flipmap #=============================================================================================== # transfer_morph() # # Transfers the named morph of the source actor to the destination actor, based on the weighted # vertex correlation data. # (Function drawn from original TDMT code. Written by Spanki.) #=============================================================================================== def transfer_morph(actSrc, actDst, morphName, flipmap, samename=0): geomDst = actDst.Geometry() numDstVerts = geomDst.NumVertices() # Create an empty array to hold morph delta values dstDeltas = [[0.0,0.0,0.0] for i in range(numDstVerts)] havedeltas = 0 # see if we find any morph to create #------------------------------------------------------------------------------------- # Find the morph on source actor and build up morph delta table for destination actor #------------------------------------------------------------------------------------- for parm in actSrc.Parameters(): if (parm.IsMorphTarget()): if parm.Name() == morphName[0]: numSrcVerts = actSrc.Geometry().NumVertices() for sndx in range(numSrcVerts): (deltaX, deltaY, deltaZ) = parm.MorphTargetDelta(sndx) #--------------------------------------------------------------------- # Only some verts have morph deltas... #--------------------------------------------------------------------- if( deltaX or deltaY or deltaZ ): vmap = flipmap[sndx] # Get array of dst indices/weights for this src index for vm in vmap: tmorph = dstDeltas[vm[0]] # Get dst index weight = vm[1] # and weight tmorph[0] += weight * deltaX tmorph[1] += weight * deltaY tmorph[2] += weight * deltaZ havedeltas = 1 if havedeltas == 0: #print "============ Morph Creation Failed ==============" #print "Either that morph did not exist, or there was no" #print "valid vertex weightmap info for that area of the mesh." transfer_error("%s: Morph Creation Failed" %(morphName[0])) return 0 #------------------------------------------------------------------------------------- # Ok, we have some morph deltas for the destination actor, so spawn the morph and fill # out the deltas. Start by zeroing any existing morph dials... #------------------------------------------------------------------------------------- #================================================================================= # TODO: If there are magnets (deformers) on the mesh, we might want to (optionally) # set those to zero as well before spawning the morph below. # THIS IS NOW HANDLED IN THE run() FUNCTION. ZERO ONLY ONCE PER ACTOR. #================================================================================= if samename: # Control naming using a temp proxy name, then rename # This should try to account for pre-existing morph of same name.... actDst.SpawnTarget("_TDMT_newmorph") parm = actDst.Parameter("_TDMT_newmorph") parm.SetName(morphName[0]) parm.SetInternalName(morphName[1]) else: morphName[0] = unique_name(morphName[0],actDst,"") actDst.SpawnTarget(morphName[0]) parm = actDst.Parameter(morphName[0]) for i in range(numDstVerts): tmorph = dstDeltas[i] if no_pyd: # Will this affect performance? if abs(tmorph[0]) > FLT_EPSILON or abs(tmorph[1]) > FLT_EPSILON or abs(tmorph[2]) > FLT_EPSILON: parm.SetMorphTargetDelta(i, tmorph[0], tmorph[1], tmorph[2]) else: tmorph = Vector() + tmorph # Coerce into Vector format if tmorph: # Use pyd Vector validity testing parm.SetMorphTargetDelta(i, tmorph[0], tmorph[1], tmorph[2]) return 1 #=============================================================================================== # Path-handling functions #=============================================================================================== def geomPath(a1,a2,dataName,overwrite=0): """ Get the necessary actor and geometry file information, to construct the dataPath. """ gf1, name1 = get_geomfiles(a1) gf2, name2 = get_geomfiles(a2) dataPath = get_pathname(gf1,gf2,name1,name2,create=1,dataName=dataName) if not dataPath: return "" if not overwrite: dataPath = protect_naming(dataPath) return os.path.normpath(dataPath) def get_geomfiles(act): """ act.GeomFileName() will equal figure.GeomFileName() unless a figure actor uses GeomCustom (GeomFileName() == None) or has an external geometry listing in the.cr2. """ agf = act.GeomFileName() if agf: fig = act.ItsFigure() if fig: fgf = fig.GeomFileName() if fgf: if fgf == agf: return os.path.splitext(os.path.basename(fgf))[0],\ act.InternalName().split(":")[0].replace(" ","_") # Normal figure actor else: return os.path.splitext(os.path.basename(fgf))[0],\ "%s_ext" %(os.path.splitext(os.path.basename(agf))[0]) # Figure actor with external geom listing return os.path.splitext(os.path.basename(agf))[0],\ act.InternalName().split(":")[0].replace(" ","_") # Standard prop with external geom listing if act.IsBodyPart(): fgf = fig.GeomFileName() if fgf: #return os.path.splitext(os.path.basename(fgf))[0],\ #"%s_cust" %(act.InternalName().split(":")[0].replace(" ","_")) # Figure actor with GeomCustom return os.path.splitext(os.path.basename(fgf))[0],\ act.InternalName().split(":")[0].replace(" ","_") # Normal figure actor return os.path.join(os.path.dirname(poser.AppLocation()),"%s.obj" %(act.Name())),\ act.InternalName().split(":")[0].replace(" ","_") # Any other actor with GeomCustom use def get_pathname(g1,g2,a1,a2,create=1,dataName="full"): """ Get the path and file name for datafile, creating folders if needed. Some systems may require administrator access to create the directories. g1,g2 are GeomFileNames; a1,a2 are actor InternalNames. """ corr_folder = "matched" ext = ".vmf" if compressFiles: ext = ".vmz" pyfolder = os.path.join("Runtime","Python") pyfolder2 = os.path.join(pyfolder,"poserScripts") base = os.path.join(os.path.dirname(poser.AppLocation()),pyfolder2) if not os.path.exists(base): return "" scriptfolder = os.path.join(base,"TDMTfiles") if not os.path.exists(scriptfolder): try: os.mkdir(os.path.abspath(scriptfolder)) except: return "" scriptfolder2 = os.path.join(scriptfolder,corr_folder) # Changed to reflect new version number; PERSONAL USE if not os.path.exists(scriptfolder2): try: os.mkdir(os.path.abspath(scriptfolder2)) except: return "" geomfolder = os.path.join(scriptfolder2, "%s-%s" %(g1.replace(" ","_"),g2.replace(" ","_"))) if create: if not os.path.exists(geomfolder): try: os.mkdir(os.path.abspath(geomfolder)) except: return "" actfolder = os.path.join(geomfolder, "%s-%s" %(a1.replace(" ","_"),a2.replace(" ","_"))) if create: if not os.path.exists(actfolder): try: os.mkdir(os.path.abspath(actfolder)) except: return "" dataPath = os.path.abspath(os.path.join(actfolder,"%s%s" %(dataName,ext))) if not create: return dataPath # ? if os.path.exists(actfolder): return dataPath else: return "" #====== Compression handling (adapted from TDMT) ==================================== 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 check_gzip(dataPath): f = open(dataPath,"rb") magic = f.read(2) f.close() if magic == '\037\213': return 1 else: return 0 def protect_naming(path): 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.join(folder,newname) else: return path #=============================================================================================== #=============================================================================================== def unique_name(morphName,act,suffix,internal=0): """ Keep dial naming for the new morph from being automatically changed by Poser Used by transfer_morph, transfer_shape, inflate_normals, and the smoothing functions. """ #Morph dial names max out at 30 characters, after which Poser #won't recognize the dial as a morph (?!?) if len(morphName) >= 20 and suffix != "": morphName = morphName[0:12] if suffix != "" and morphName.find(suffix) == -1: morphName = "%s%s" %(morphName,suffix) # Check the dial name to avoid duplication if internal: parms = [p.InternalName() for p in act.Parameters()] else: parms = [p.Name() for p in act.Parameters()] if morphName in parms: temp = 1 while "%s_%i" %(morphName,temp) in parms: temp += 1 # Name the target morph dial morphName = "%s_%i" %(morphName,temp) return morphName #=============================================================================================== #=============================================================================================== class App: def __init__(self, master): self.master = master master.title("TDMT_Match_Transfer 1") self.figT = None self.actT = None self.actsS = {} self.basepath = "Runtime:Python:PoserScripts:TDMTfiles:" self.corrfolder = "matched:" self.dataPath = "Runtime:Python:PoserScripts:TDMTfiles:" self.browse_act = "" self.browsePath = "" self.transfer = 0 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.ListFrame = Frame(self.masterFrame,borderwidth=2,relief=RIDGE) self.ListFrame.grid(row=1,column=0) self.ListFrame2 = Frame(self.masterFrame,borderwidth=2,relief=RIDGE) self.ListFrame2.grid(row=1,column=1) self.morFrame = Frame(self.masterFrame,borderwidth=2,relief=RIDGE) self.morFrame.grid(row=1,column=2) self.mixFrame = Frame(self.masterFrame,borderwidth=2,relief=RIDGE) self.mixFrame.grid(row=1,column=3) self.pathFrame = Frame(self.mixFrame,borderwidth=2,relief=RIDGE) self.pathFrame.grid(row=0,column=0) self.morbuttonFrame = Frame(self.morFrame,borderwidth=2) self.morbuttonFrame.grid(row=3,column=1) self.checkFrame = Frame(self.mixFrame,borderwidth=2) self.checkFrame.grid(row=1,column=0) self.buttonFrame = Frame(self.mixFrame,borderwidth=2) self.buttonFrame.grid(row=2,column=0) self.quitFrame = Frame(self.mixFrame,borderwidth=3) self.quitFrame.grid(row=3,column=0) self.browseFrame = Frame(self.metamasterFrame,borderwidth=2,relief=RIDGE) browseText = "1) Select actor to which\n new .vwt files will\n apply.\n" browseText += "2) Click 'Select Folder'\n to browse for files.\n" self.browseLabel = Label(self.browseFrame, text=browseText , anchor=NW, justify=CENTER) # --- Listboxes --- self.listLabel = Label(self.ListFrame, text="Target Actor" , anchor=N, justify=LEFT) self.listLabel.grid(row=1, column=1) self.ListScroll = Scrollbar(self.ListFrame, orient=VERTICAL) # Target actor self.ListScroll.grid( row=2, column=0,sticky=N+S+E) self.List = Listbox(self.ListFrame, height=20, width=25, selectmode=SINGLE,exportselection=0, yscrollcommand=self.ListScroll.set) self.List.grid( row=2, column=1) self.ListScroll["command"] = self.List.yview self.listLabel2 = Label(self.ListFrame2, text="Source Actor" , anchor=N, justify=LEFT) self.listLabel2.grid(row=1, column=1) self.ListScroll2 = Scrollbar(self.ListFrame2, orient=VERTICAL) # Source actors self.ListScroll2.grid( row=2, column=0,sticky=N+S+E) self.List2 = Listbox(self.ListFrame2, height=20, width=25, selectmode=SINGLE,exportselection=0, yscrollcommand=self.ListScroll2.set) self.List2.grid( row=2, column=1) self.ListScroll2["command"] = self.List2.yview self.listLabel3 = Label(self.morFrame, text="Morph(s)" , anchor=N, justify=LEFT) self.listLabel3.grid(row=1, column=1) self.ListScroll3 = Scrollbar(self.morFrame, orient=VERTICAL) # Morphs self.ListScroll3.grid( row=2, column=0,sticky=N+S+E) self.List3 = Listbox(self.morFrame, height=18, width=25, selectmode=EXTENDED,exportselection=0, yscrollcommand=self.ListScroll3.set) self.List3.grid( row=2, column=1) self.ListScroll3["command"] = self.List3.yview self.listLabel4 = Label(self.pathFrame, text="Select .vmf file" , anchor=N, justify=LEFT) self.listLabel4.grid(row=1, column=1) self.ListScroll4 = Scrollbar(self.pathFrame, orient=VERTICAL) # .vmf self.ListScroll4.grid( row=2, column=0,sticky=N+S+E) self.List4 = Listbox(self.pathFrame, height=14, width=25, selectmode=SINGLE,exportselection=0, yscrollcommand=self.ListScroll4.set) self.List4.grid( row=2, column=1) self.ListScroll4["command"] = self.List4.yview self.List5 = Listbox(self.displayFrame, height=5, width=117, selectmode=SINGLE,exportselection=0) # Status bar self.List5.grid( row=3, column=0) self.listLabel6 = Label(self.browseFrame, text="Select actor for new .vmf path" , anchor=N, justify=LEFT) self.ListScroll6 = Scrollbar(self.browseFrame, orient=VERTICAL) # .vmf actor self.List6 = Listbox(self.browseFrame, height=10, width=25, selectmode=SINGLE,exportselection=0, yscrollcommand=self.ListScroll6.set) self.ListScroll6["command"] = self.List6.yview self.pathEntry = Entry(self.displayFrame, width=117) self.pathEntry.insert(0,"%s%s" %(self.basepath,self.corrfolder)) self.pathEntry.grid(row=1,column=0) # --- Buttons --- self.buttonRun = Button(self.quitFrame, text="Transfer Morphs", command=self.handleRun) self.buttonRun.grid(row=0, column=0) self.buttonQuit = Button(self.quitFrame, text="Quit Script", command=self.die) self.buttonQuit.grid(row=1, column=1) self.buttonShape = Button(self.quitFrame, text="Transfer Shape", command=self.handleShape) self.buttonShape.grid(row=0, column=1) self.buttonAll = Button(self.morbuttonFrame, text="All", command=self.allmorphs) self.buttonAll.grid(row=0, column=0) self.buttonNone = Button(self.morbuttonFrame, text="None", command=self.nomorphs) self.buttonNone.grid(row=0, column=1) self.buttonBrowse = Button(self.pathFrame, text="Browse for datafile folder", command=self.grid_browse) self.buttonBrowse.grid(row=3, column=1) self.buttonSBrowse = Button(self.browseFrame, text="Select Folder", command=self.browse) self.buttonBrowseCancel = Button(self.browseFrame, text="Cancel Browse", command=self.ungrid_browse) # ---- Mouse-button binding ---- self.List.bind('',lambda e, s=self: s.handleTarget(e.y)) self.List2.bind('',lambda e, s=self: s.handleSources(e.y)) self.List6.bind('',lambda e, s=self: s.handleBrowse(e.y)) self.fill_boxes(self.List) self.pyd_update() self.status_update("Ready") def grid_browse(self): """Show the .vwt browse actors listbox and buttons for hide-show""" if len(self.List2.curselection()) > 1: # User must specify actor self.browseFrame.grid(row=1,column=4) self.browseLabel.grid(row=0,column=1) self.listLabel6.grid(row=1,column=1) self.ListScroll6.grid(row=2,column=0,sticky=N+S+E) self.List6.grid(row=2,column=1) self.buttonSBrowse.grid(row=3,column=1) self.buttonBrowseCancel.grid(row=4,column=1) if len(self.List2.curselection()) == 1: # Automatically select the only actor s1 = self.List2.get(int(self.List2.curselection()[0])) name,fig = s1.split(" <") fig = fig.replace(">","") self.browse_act = ("(%s,%s)" %(name,fig)) self.browse() # Don't activate the secondary browse button if len(self.List2.curselection()) == 0: self.status_update("No source actor(s) selected. Specify actor(s) before using Browse.") def ungrid_browse(self): """Hide the .vwt browse actors listbox and buttons for hide-show""" self.browseFrame.grid_forget() self.browseLabel.grid_forget() self.listLabel6.grid_forget() self.ListScroll6.grid_forget() self.List6.grid_forget() self.buttonSBrowse.grid_forget() self.buttonBrowseCancel.grid_forget() self.browse_act = "" self.browsePath = "" self.List6.selection_clear(0,END) def handleBrowse(self,event): clicked = self.List6.nearest(event) self.browse_act = self.List6.get(clicked) if self.browsePath: name,fig = self.browse_act.replace("(","").replace(")","").split(",") self.actsS[(name,fig)][1] = [self.browsePath] self.path_update(self.browsePath) vfiles = os.listdir(self.browsePath) for vf in vfiles: self.List4.insert(END,"%s <%s,%s>" %(vf,name,fig)) self.ungrid_browse() def status_update(self,line): self.List5.insert(0,line) self.List5.update() def path_update(self,path): path = path.replace(os.sep,":") path = "Runtime:%s" %(path.split("Runtime:")[1]) self.pathEntry.delete(0,END) self.pathEntry.insert(0,path) self.pathEntry.index(len(self.basepath)-1) # self.pathEntry.update() def pyd_update(self): if not no_pyd: self.status_update("Running using Spanki's tdmt.pyd for greater speed.") else: self.status_update("Not running using Spanki's tdmt.pyd") if poser.Version() < 7.0: self.status_update("Reason: Poser version is less than 7.0.") if os.name == "mac": self.status_update("Reason: OS is Mac.") if poser.Version() >= 7.0 and os.name != "mac": self.status_update("Reason: tdmt.pyd not found.") def handleTarget(self,event): self.figT = None self.List2.delete(0,END) self.List3.delete(0,END) self.List4.delete(0,END) clicked = self.List.nearest(event) s1 = self.List.get(clicked) name,fig = s1.split(" <") fig = fig.replace(">","") if fig == "None": self.actT = scene.Actor(name) else: self.figT = scene.Figure(fig) self.actT = self.figT.Actor(name) self.fill_boxes(self.List2,self.actT.InternalName()) def handleSources(self,event): global FILE_VERSION self.actsS = {} clicked = self.List2.nearest(event) s1 = self.List2.get(clicked) name,fig = s1.split(" <") fig = fig.replace(">","") if fig == "None": actS = scene.Actor(name) else: figS = scene.Figure(fig) actS = figS.Actor(name) self.fill_morphbox(actS,name,fig) self.List6.insert(END,"(%s,%s)" %(name,fig)) self.List4.delete(0,END) path = geomPath(actS,self.actT,"full",overwrite=1) if path: self.dataPath = path self.path_update(path) vfiles = os.listdir(os.path.dirname(path)) if vfiles: for vf in vfiles: self.List4.insert(END,"%s <%s,%s>" %(vf,name,fig)) else: msg = "No .vwt files found for this actor set. Browse or run TDMT_Compare." self.status_update(msg) else: msg = "The .vwt path was not found. Browse or run TDMT_Compare." self.status_update(msg) self.actsS[(name,fig)] = [[],[os.path.dirname(path)],["full.vwt"]] def fill_morphbox(self,act,name,fig): for parm in act.Parameters(): if parm.IsMorphTarget(): self.List3.insert(END,"%s <%s,%s>" %(parm.Name(),name,fig)) def allmorphs(self): self.List3.selection_set(0,END) def nomorphs(self): self.List3.selection_clear(0,END) def fill_boxes(self,theList,notme=""): """ Adds the figures and props to the first set of listboxes """ for act in scene.Actors(): if act.IsLight() or act.IsCamera() or act.IsDeformer() or act.IsBase() or\ act.IsZone() or (not act.Geometry()) or act.Name() == 'GROUND' or\ act.Name() == 'FocusDistanceControl' or 'CenterOfMass' in act.Name(): continue if not act.OnOff(): continue if act.InternalName() == notme: continue line = [act.Name()] if act.ItsFigure(): line.append(act.ItsFigure().Name()) else: line.append(act.ItsFigure()) theList.insert(END,"%s <%s>" %(line[0],line[1])) def browse(self): pdir = os.path.dirname(poser.AppLocation()) pdir = self.checkScriptFolder(pdir) p = tkFileDialog.askdirectory(title="browse for data folder",initialdir=pdir) if p: self.browsePath = os.path.normpath(p) self.dataPath = os.path.normpath(p) self.path_update(os.path.normpath(p)) if self.browse_act: name,fig = self.browse_act.replace("(","").replace(")","").split(",") self.actsS[(name,fig)][1] = [self.browsePath] self.path_update(self.browsePath) vfiles = os.listdir(self.browsePath) self.List4.delete(0,END) for vf in vfiles: if vf.find("vmf") != -1 or vf.find("vmz") != -1: self.List4.insert(END,"%s <%s,%s>" %(vf,name,fig)) self.ungrid_browse() def checkScriptFolder(self,pdir): """Check to see if TDMT script folder exists""" pyfolder = os.path.join("Runtime","Python") pyfolder = os.path.join(pyfolder,"poserScripts") base = os.path.join(os.path.dirname(poser.AppLocation()),pyfolder) if os.path.exists(base): pdir = base scriptfolder = os.path.join(base,"TDMTfiles") if os.path.exists(scriptfolder): pdir = scriptfolder scriptfolder = os.path.join(scriptfolder,self.corrfolder.replace(":","")) if os.path.exists(scriptfolder): pdir = scriptfolder return pdir def die(self): """End the script""" root.destroy() root.quit() def handleShape(self): self.transfer = 1 self.handleRun() def handleRun(self): if not self.actT: # No target actor selected self.status_update("No Target actor selected.") return StartTime = time.time() s = self.List2.curselection() if s != (): all_acts = [self.List2.get(int(c)) for c in s] wnames = [] for t in all_acts: name,fig = t.split(" <") fig = fig.replace(">","") wnames.append((name,fig)) else: # No source actor(s) selected self.status_update("No Source actor(s) selected.") return if self.List3.curselection() == () and self.transfer == 0: self.status_update("No morph(s) selected.") return morphs = [self.List3.get(int(c)) for c in self.List3.curselection()] filenames = [self.List4.get(int(c)) for c in self.List4.curselection()] for mt in morphs: mname,stuff = mt.split(" <") name,fig = stuff.replace(">","").split(",") self.actsS[(name,fig)][0].append(mname) for f in filenames: fname,stuff = f.split(" <") name,fig = stuff.replace(">","").split(",") self.actsS[(name,fig)][2][0] = fname # Last filename for any given actor will be favored. for wname in wnames: path = self.actsS[wname][1][0] fname = self.actsS[wname][2][0] dataPath = os.path.normpath(os.path.join(path,fname)) name,fig = wname if fig == "None": actS = scene.Actor(name) else: actS = scene.Figure(fig).Actor(name) morphs = [] for mname in self.actsS[wname][0]: mt = actS.Parameter(mname) morphs.append([mt.Name(),mt.InternalName()]) if not os.path.exists(dataPath): # This should only happen when user hasn't selected a .vwt and "full.vwt" default is passed. swap = {"vmf":"vmz","vmz":"vmf"} ext = dataPath.split(".")[1] ext2 = swap[ext] altPath = "%s.%s" %(ext[0],ext2) if os.path.exists(altPath): dataPath = altPath else: self.path_update(dataPath) self.status_update("Unable to open file path. Try again, selecting a path.") self.status_update("Transferring morphs for %s to %s" %(actS.Name(),self.actT.Name())) self.path_update(dataPath) run2(dataPath,actS,self.actT,morphs,transfer=self.transfer) EndTime = (time.time() - StartTime)/60 minutes = int(EndTime) seconds = int((EndTime - float(minutes))*60) self.status_update("Done in %s minutes, %s seconds."%(minutes,seconds)) self.transfer = 0 app = App(root) root.mainloop()