import gzip, os from Tkinter import * import tkFileDialog try: import poser poser_found = 1 except: poser_found = 0 """ """ class figure(object): def __init__(self): self.actors = [] self.fignum = None self.actnames = [] def check_fignum(self,actline): checknum = actline.replace("\n","").split(":")[1] if not checknum: return 0 if not self.fignum: self.fignum = int(checknum) return 1 if int(checknum) != self.fignum: return 0 else: return 1 class actor(object): def __init__(self): """ Container class for actors. """ self.intname = "" # internal name self.weights = {} # weightMap listings as dict, with internal number (string) as key, full data block as value self.weights_order = [] # list of weight keys in order from cr2 self.joints = [] # container for joint class instances self.hasweights = 0 # flag for whether an actor uses weight mapping; probably redundant self.jointnames = [] # cross-indexing list for quick access to joint listings self.newnames = {} # dict of old weightmap numbers to new names class zoneclass(object): def __init__(self): self.sphere = 0 self.weight = 0 self.number = "" self.write = 1 self.active = 1 self.math = 0 self.others = [] self.block = "" self.newname = "" self.smooth = 0 old_number = "" class jointclass(object): def __init__(self): self.joint = 0 self.affect = 0 self.zones = [] self.others = [] def reader(pathDonor,pathTarget): path,ext = os.path.splitext(pathDonor) if ext == ".crz" or ext == ".CRZ": f = gzip.GzipFile(pathDonor) else: f = open(pathDonor,"r") g = f.readlines() f.close() fig = figure() depth = 0 prevline = "" newact = None actdepth = 2 channeldepth = 3 parmdepth = 4 isweights = 0 ischannels = 0 isjoints = 0 newzone = None weight_num = None iszone = 0 newjoint = None for num,line in enumerate(g): numtabs = line.count("\t") ls = line.strip() lt = ls.split() if not lt: continue # Handle opening brackets if lt[0] == "{": depth += 1 prev_lt = prevline.strip().split() if not prev_lt: continue if prev_lt[0] == "actor": good = fig.check_fignum(prevline) # Limit processing to only the first figure in the .cr2 if not good: continue checkline = g[num+1].strip().split() if checkline and (not checkline[0] == "storageOffset"): # Separate handling for actor geom listings and parm listings newact = actor() newact.intname = prevline.strip().replace("actor ","") fig.actnames.append(newact.intname) if (depth > actdepth) and (newact != None): # An actor's parameter block has been found. if prev_lt[0] == "weightMap": isweights = 1 """ Strangely, what looks like a standard space, between "weightMap" and the following identifier, behaves more like a tab. Use of line.replace("weightMap ","") fails to find the "weightMap " prefix. """ weight_num = prevline.strip().replace("weightMap","").strip() newact.weights[weight_num] = [prevline] newact.hasweights = 1 newact.weights_order.append(weight_num) elif prev_lt[0] == "channels": ischannels = 1 if ischannels: if ((prev_lt[0][:-1] == "twist") or (prev_lt[0][:-1] == "joint")): isjoints = 1 newjoint = jointclass() newact.jointnames.append(prevline.strip()) if (prev_lt[1][:-1] == "twist") or (prev_lt[1][:-1] == "joint"): newjoint.joint = 1 else: newjoint.affect = 1 if (prev_lt[0][:-1] == "smoothScale"): #ADDED isjoints = 1 newjoint = jointclass() newact.jointnames.append(prevline.strip()) newjoint.smooth = 1 if isjoints: if prev_lt[0] == "otherActor": newjoint.others.append(prevline.strip().split()[1]) elif prev_lt[0] == "spherezone": iszone = 1 elif prev_lt[0] == "weightmapzone": iszone = 2 if iszone: newzone = zoneclass() if iszone == 1: newzone.sphere = 1 else: newzone.weight = 1 newzone.number = g[num+3].strip().split()[1] newzone.block += prevline newzone.active = int(g[num+1].strip().split()[1]) newzone.math = int(g[num+2].strip().split()[1]) if not newzone.active: newzone.write = 0 # Handle closing brackets elif lt[0] == "}": depth -= 1 if (depth < actdepth) and (newact != None): fig.actors.append(newact) newact = None if isweights: newact.weights[weight_num].append(line) isweights = 0 weight_num = None if ischannels and (depth < channeldepth): ischannels = 0 if isjoints and (depth < parmdepth): newact.joints.append(newjoint) newjoint = None isjoints = 0 after_zones = 0 if iszone and (depth < (parmdepth + 2)): iszone = 0 newzone.block += line newjoint.zones.append(newzone) newzone = None # Handle actor block variables if (depth == actdepth) and (newact != None): if lt[0] == "name": newact.name = line prevline = line # Store the previous line for reference when an opening bracket is found. if isjoints: if isjoints: if iszone: newzone.block += line if isweights: newact.weights[weight_num].append(line) for act in fig.actors: #print "*********************************************" #print act.intname #for j in act.jointnames: # print j #for w in act.weights_order: #print w for i in range(len(act.jointnames)): j = act.joints[i] prefix = "" if not j.affect: if act.intname.find(":") != -1: prefix = "%s_" %(act.intname.split(":")[0]) else: prefix = "%s_" %(act.intname) z = j.zones zone_count = -1 for zone in z: if zone.weight: zone_count += 1 #print "%s %s = %s" %(act.intname,act.jointnames[i],zone.number) jointname = act.jointnames[i].split(" ")[1] zone.newname = "%s%s" %(prefix,jointname) if zone_count: zone.newname = "%s_%s" %(zone.newname,zone_count) if not act.newnames.has_key(zone.number): act.newnames[zone.number] = zone.newname zone.old_number = "%s" %(zone.number) #print "Old Number: %s" %(zone.number) if zone.newname != "": zone.number = zone.newname #print "New Number: %s" %(zone.number) zone.block = zone.block.replace(zone.old_number,zone.number) #print "**** New Names: ****" #for k in act.newnames.keys(): #print "%s = %s" %(k,act.newnames[k]) #if act.intname.find("phallo") != -1: #for w in act.weights_order: #print w #for k in act.newnames.keys(): #act.weights_order.replace(k,act.newnames[k]) #print act.weights.keys() new_weights_order = [] for number in act.weights_order: if act.newnames.has_key(number): new_weights_order.append(act.newnames[number]) act.weights[act.newnames[number]] = [i for i in act.weights[number]] del act.weights[number] mapname = act.weights[act.newnames[number]][0] mapname = mapname.replace(number,act.newnames[number]) act.weights[act.newnames[number]][0] = "%s" %(mapname) else: new_weights_order.append(number) act.weights_order = [i for i in new_weights_order] #print "**** New Weight Order: ****:" #for w in act.weights_order: # print w #print act.weights.keys() # Write the file """ Process is driven by looping over the full .cr2 content initially read in by script, but weights and zones are written in blocks. To prevent blocks from being written repeatedly, the stopweights and stopzones variables are used. Clever, or a tacky kludge? You be the judge. But, yeah. Probably the latter. """ isweights = 0 iszone = 0 actname = "" jointname = "" f = open("%s.cr2" %(os.path.splitext(pathTarget)[0]),"w") for num,line in enumerate(g): numtabs = line.count("\t") ls = line.strip() lt = ls.split() if not lt: f.write(line) continue if isweights == 2: isweights = 0 if iszone == 2: iszone = 0 if lt[0] == "actor": checkline = g[num+2].strip().split() if checkline and (not checkline[0] == "storageOffset"): actname = line.strip().replace("actor ","") stopweights = 0 elif lt[0] == "weightMap": isweights = 1 elif ((lt[0][:-1] == "twist") or (lt[0][:-1] == "joint") or (lt[0][:-1] == "smoothScale")): jointname = line.strip() stopzones = 0 elif lt[0] == "weightmapzone" or lt[0] == "spherezone": iszone = 1 elif lt[0] == "}": if isweights: isweights = 2 if iszone: iszone = 2 if isweights: if not stopweights: act = fig.actors[fig.actnames.index(actname)] for number in act.weights_order: if not act.weights.has_key(number): #print "Skipping weight zone %s..." %(number) continue weight = act.weights[number] #print weight[0] for weightline in weight: f.write(weightline) stopweights = 1 elif iszone: if not stopzones: act = fig.actors[fig.actnames.index(actname)] joint = act.joints[act.jointnames.index(jointname)] for zone in joint.zones: if zone.write: f.write(zone.block) #print zone.block stopzones = 1 else: f.write(line) f.close() # Cleanup step, may not be necessary g = [] for act in fig.actors: act.weights = {} if act.joints: for j in act.joints: for z in j.zones: z = None j.zones = [] act.joints = [] act = None fig = None class App(object): def __init__(self,master): self.master = master self.master.title("CR2 Joint Cleaner") if poser_found: topDir = os.path.dirname(poser.AppLocation()) runDir = os.path.join(topDir,"Runtime") self.libDir = os.path.normpath(os.path.join(runDir,"Libraries")) if not os.path.exists(self.libDir): self.libDir = "." else: self.libDir = "." self.pathDonor = "" self.pathTarget = "" self.masterFrame = Frame(self.master) self.masterFrame.grid(row=0, column=0) self.listFrame = Frame(self.masterFrame) self.listFrame.grid(row=0, column=0, padx=10) self.buttonFrame = Frame(self.masterFrame) self.buttonFrame.grid(row=1, column=0) self.labelDonor = Label(self.listFrame, text=".cr2 file to be cleaned", anchor=N, justify=LEFT) self.labelDonor.grid(row=0, column=1) self.listDonor = Listbox(self.listFrame, height=1, width=116, selectmode=SINGLE, exportselection=0) self.listDonor.grid(row=1, column=1) self.labelTarget = Label(self.listFrame, text="Save path for cleaned file", anchor=N, justify=LEFT) self.labelTarget.grid(row=2,column=1) self.listTarget = Listbox(self.listFrame, height=1, width=116, selectmode=SINGLE, exportselection=0) self.listTarget.grid(row=3, column=1) self.buttonDonor = Button(self.listFrame, text="...", command=self.browseDonor, padx=15) self.buttonDonor.grid(row=1, column=0, padx=5) self.buttonTarget = Button(self.listFrame, text="...", command=self.browseTarget, padx=15) self.buttonTarget.grid(row=3, column=0, padx=5) self.buttonRun = Button(self.buttonFrame, text="Run script", command=self.runScript, padx=25) self.buttonRun.grid(row=0, column=1, padx=5, pady=10) self.buttonQuit = Button(self.buttonFrame, text="Quit Script", command=self.quitScript, padx=25) self.buttonQuit.grid(row=0, column=2, padx=5, pady=10) self.listDonor.insert(END,"") # Tk throws an error when deleting an empty listbox (?!?); add a dummy entry, to avoid this. self.listTarget.insert(END,"") def quitScript(self): root.destroy() root.quit() def runScript(self): if (not self.pathDonor) or (not self.pathTarget): return if self.pathDonor == self.pathTarget: return #self.pathDonor = "C:\\MyPrograms\\Poser\\extra_runtimes\\My_figures\\Runtime\\Libraries\\Character\\temp3.crz" #self.pathTarget = "C:\\MyPrograms\\Poser\\extra_runtimes\\My_figures\\Runtime\\Libraries\\Character\\temp3_renamed_weights.crz" reader(self.pathDonor,self.pathTarget) root.destroy() root.quit() def relative_path(self,path): path = os.path.normpath(path) path = path.replace(os.sep,":") path = path.split("Runtime")[1] path = ":Runtime%s" %(path) return path def browseDonor(self): p = tkFileDialog.askopenfilename(initialdir=self.libDir, title="Locate Donor .cr2", filetypes=[("Poser Character File", "*.cr2 *.crz *.CR2 *.CRZ")]) if not p: return if p.find("Runtime") == -1: self.listDonor.insert(0,"A Poser library path is required.") return path = self.relative_path(p) self.listDonor.insert(0, path) self.pathDonor = p def browseTarget(self): p = tkFileDialog.asksaveasfilename(initialdir=self.libDir, title="Locate Target .cr2", filetypes=[("Poser Character File", "*.cr2 *.crz *.CR2 *.CRZ")]) if not p: return if p.find("Runtime") == -1: self.listTarget.insert(0,"A Poser library path is required.") return path = self.relative_path(p) self.listTarget.insert(0, path) self.pathTarget = p root = Tk() app = App(root) root.mainloop()