# Tile Art XML Editor
# Edits Tile Art XML Files.
#
# Created 2009-04-01
# Last Modified 2009-04-05
#
# Created by Ruben Garza
import Tkinter
import ImageTk
import os
from elementtree import ElementTree as et
from elementtree.ElementTree import Element, SubElement
import sys
import tkMessageBox
import tkFileDialog
pathImages = "C:/perforce/UO/UOSA/Mainline/Runtime/Data/TileArtLegacy"
pathXML = "C:/perforce/UO/UOSA/Mainline/Runtime/Data/Definitions/TileArt"
tgaList = [""]
changeList = ""
# Create Checkbox List
chkBoxList = ["animation","hover_over","background","noshoot","bridge","partialhue","container"
,"roof","door","stair_back","stair_right","generic","equipment","surface","foliage","wall","impassable"
,"wet","lightsource","wearable","window","mongen","map","usenewart"]
chkBoxList.sort()
entryList =[["quality", "value"],["quantity", "value"],["weight", "value"],
["height", "value"],["Value", "value"],["ACWC", "value"],["slot", "value"],["hue", "value"],
["appearance", "value"],["gender", "value"],["race", "value"],["sittingData", "x"],
["sittingData", "y"],["legacy","offsetX"],["legacy","offsetY"],["sittingData","backSplitPosition"]]
entryList.sort(lambda x, y: cmp(x[0].lower(),y[0].lower()))
whereToLook = ["defaultInstanceProperties","defaultInstancePropertiesLegacy"]
root = Tkinter.Tk()
root.title('Tile Art XML Editor')
# Lets you set root's size
#w = 550
#h = 640
#x = 0
#y = 0
#root.geometry("%dx%d+%d+%d" % (w, h, x, y))
# XML Formatter
def indent(elem, level=0):
i = "\n" + level*" "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
# Function: Create a new changelist in p4
def CreateNewChangeList(description):
"Create a new changelist and returns the changelist number as a string"
p4in, p4out = os.popen2("p4 changelist -i")
p4in.write("change: new\n")
p4in.write("description: " + description)
p4in.close()
changelist = p4out.readline().split()[1]
return changelist
# Function: Open File for edit
def OpenFileForEdit(file, changelist = ""):
"Open a file for edit, if a changelist is passed in then open it in that list"
cmd = "p4 edit "
if changelist:
cmd += " -c " + changelist + " "
ret = os.popen(cmd + file).readline().strip()
if not ret.endswith("opened for edit"):
print "Couldn't open", file, "for edit:"
print ret
raise ValueError
# Function: Find Character in String
def findCharInString(inString,findString):
foundIt = False
for findMe in range(0,len(findString)) :
if inString == findString[findMe]: foundIt = True
return foundIt
# Function: Remove 0's
def removeZero(inString):
for findMe in range(0,(len(inString)-1)) :
if inString[0] == "0" : inString = inString [1:]
return inString
# Function to sort listbox items case insensitive
def sort_list(listbox1):
temp_list = list(listbox1.get(0, Tkinter.END))
temp_list.sort(key=str.lower)
# delete contents of present listbox
listbox1.delete(0, Tkinter.END)
# load listbox with sorted data
for item in temp_list:
listbox1.insert(Tkinter.END, item)
return
# Function: Open selected files for edit.
def openForEdit():
global changeList
if changeList == "" : changeList = CreateNewChangeList("Changing Tileart NO QA")
for listItem in range (0, len(listbx.curselection())) :
assetName = listbx.get(listbx.curselection()[listItem])
doIadd = True
try:
saveList = cklistbx.get(0,Tkinter.END)
for checkItem in range (0, len(saveList)):
if assetName == saveList[checkItem] : doIadd = False
except:
pass
if doIadd == True :
try:
OpenFileForEdit ((pathXML + "/" + assetName + ".tileart"),changeList)
except:
pass
cklistbx.insert(Tkinter.END, assetName)
sort_list(cklistbx)
return
# Function: Remove nonnumerical characters - not very bullet proof.
def trimFileName(inName):
outName = ((inName.split()[0]).split("_")[0]).split(".")[0]
outName = int(outName)
return outName
# Function: Find Entry Items XML
def entryItem(tree,elem, attr):
name = tree.getiterator(elem)
if len(name) > 0 : nameValue = name[0].get(attr)
else : nameValue = ""
return nameValue
# Function: Find checkbox Items XML
def checkBoxSet(tree,buttonSet,attr):
name = tree.getiterator(attr)
if len(name) > 0 : buttonSet.select()
else : buttonSet.deselect()
# Function: Turn All Batch Checkboxes On
def batchAllOn ():
saName.select()
for chkBx in range (0,len(chkBoxList)) :
UIsaveButton[chkBx].select()
for chkBx in range (0,len(entryList)) :
UIsaveEntry[chkBx].select()
# Function: Turn Off Batch Checkboxes On
def batchAllOff ():
saName.deselect()
for chkBx in range (0,len(chkBoxList)) :
UIsaveButton[chkBx].deselect()
for chkBx in range (0,len(entryList)) :
UIsaveEntry[chkBx].deselect()
# Function: Update XML and image when listbox clicked on.
def listUpdate(listToUse,entryChanged):
if entryChanged == True :
try:
typedVal = int(eListBx.get())
newVal = typedVal
bigList = listToUse.get(0,Tkinter.END)
bigInt = []
for testInt in bigList:
newInt = int(testInt)
bigInt.append(newInt)
try:
newVal = bigInt.index(typedVal)
except:
pass
listToUse.see(newVal)
except:
listVal = eListBx.get()
evListBx.set(listVal[:-1])
else:
try:
assetName = listToUse.get(listToUse.curselection()[0])
# Update Image
tgaPathAndName = os.path.join(pathImages, removeZero(assetName))
tgaList[0]=ImageTk.PhotoImage(file=(tgaPathAndName+".tga"))
imgLabel.config(image=tgaList[0])
# Parse XML
tree = et.parse(pathXML + "/" + assetName + ".tileart")
# Checkboxes
for chkBx in range (0,len(chkBoxList)) :
checkBoxSet(tree,UIchkBx[chkBx],chkBoxList[chkBx])
# Entry Items
evName.set((entryItem(tree,"art", "typeName")))
for entList in range (0,len(entryList)) :
varEntry[entList].set((entryItem(tree,entryList[entList][0],entryList[entList][1])))
except:
pass
# Function: Write XML values to selected files.
def writeVals():
if len(cklistbx.curselection()) > 0 :
print "Process " + str(len(cklistbx.curselection())) + " files"
for listItem in range (0, len(cklistbx.curselection())) :
assetName = cklistbx.get(cklistbx.curselection()[listItem])
print assetName
tree = et.parse(pathXML + "/" + assetName + ".tileart")
# Write / Delete Checkboxes
for checkBoxSet in range(0,len(chkBoxList)):
# Only change value if batch is checked
if saveChkBoxToggle[checkBoxSet].get() == 1 :
findElem = tree.getiterator(chkBoxList[checkBoxSet])
# Add Element
if varChkBox[checkBoxSet].get() == 1 :
if len(findElem) == 0 :
for addElem in range(0,len(whereToLook)):
subElem = tree.getiterator(whereToLook[addElem])
subElem[0].append(Element(chkBoxList[checkBoxSet]))
# Remove Element
else:
if len(findElem) > 0 :
for remElem in range(0,len(whereToLook)):
subElem = tree.getiterator(whereToLook[remElem])
delElem = subElem[0].find(chkBoxList[checkBoxSet])
subElem[0].remove(delElem)
# Write / Delete Entry Items
for entrySet in range(0,len(entryList)):
# Only change value if batch is checked
if saveEntryToggle[entrySet].get() == 1 :
findElem = tree.getiterator(entryList[entrySet][0])
# Add or Modify Element
if varEntry[entrySet].get() != "" :
if len(findElem) == 0 :
#Add Element Name
for addElem in range(0,len(whereToLook)):
subElem = tree.getiterator(whereToLook[addElem])
subElem[0].append(Element(entryList[entrySet][0]))
#Modify Element (Value)
for elt in tree.getiterator(entryList[entrySet][0]):
if elt.attrib.has_key (entryList[entrySet][1]):
elt.set(entryList[entrySet][1],varEntry[entrySet].get())
#Add Element
else:
elt.set(entryList[entrySet][1],varEntry[entrySet].get())
# Remove Element
else:
if len(findElem) > 0 :
for remElem in range(0,len(whereToLook)):
subElem = tree.getiterator(whereToLook[remElem])
delElem = subElem[0].find(entryList[entrySet][0])
subElem[0].remove(delElem)
# Write XML
root = tree.getroot()
indent(root)
tree.write(pathXML + "/" + assetName + ".tileart")
else:tkMessageBox.showwarning("Save - Please select from Lower list","Please select some files from the lower list then click on save.")
return
# Build Frames
frameButtons = Tkinter.Frame(root)
frameButtons.grid(row=0, column=0, columnspan=3, padx=5, pady=5,sticky=Tkinter.W)
frameLstBx = Tkinter.Frame(root)
frameLstBx.grid(row=1, column=0, rowspan=2, padx=5, pady=5,sticky=Tkinter.N)
frameChkBx = Tkinter.Frame(root)
frameChkBx.grid(row=1, column=1, padx=5, pady=5,sticky=Tkinter.N)
frameChkPic = Tkinter.Frame(root)
frameChkPic.grid(row=1, column=2, padx=5, pady=5,sticky=Tkinter.N)
frameEntry = Tkinter.Frame(frameChkPic)
frameEntry.grid(row=0, column=0, padx=5, pady=5, sticky=Tkinter.N+Tkinter.W)
frameImage = Tkinter.Frame(frameChkPic,borderwidth=5,relief=Tkinter.GROOVE)
frameImage.grid(row=1, column=0, sticky=Tkinter.N)
# Find Drectory
# testDir = tkFileDialog.askdirectory()
# pathXML = testDir
# Get list of assets
assetList = []
for assetName in os.listdir(pathXML):
assetName = assetName[:-8]
if findCharInString (assetName[0],"0123456789") : assetList.append(assetName)
assetList.sort(lambda a,b: cmp(trimFileName(a), trimFileName(b)))
# Build Listbox and Scrollbar
listAtitle = Tkinter.Label(frameLstBx, text="Tile Browser")
listAtitle.grid(row=0, column=0)
listscroll = Tkinter.Scrollbar(frameLstBx)
listbx = Tkinter.Listbox(frameLstBx, selectmode=Tkinter.EXTENDED,yscrollcommand=listscroll.set,height=30)
listbx.grid(row=1, column=0)
listscroll.grid(row=1, column=1,padx=0, pady=5,sticky=Tkinter.N+Tkinter.S+Tkinter.W)
listscroll.config(command=listbx.yview)
evListBx = Tkinter.StringVar()
eListBx = Tkinter.Entry(frameLstBx, textvariable=evListBx)
eListBx.grid(row=2, column=0)
listBtitle = Tkinter.Label(frameLstBx, text="Save checked out files:")
listBtitle.grid(row=3, column=0)
cklistscroll = Tkinter.Scrollbar(frameLstBx)
cklistbx = Tkinter.Listbox(frameLstBx, selectmode=Tkinter.EXTENDED,yscrollcommand=cklistscroll.set,height=10)
cklistbx.grid(row=4, column=0)
cklistscroll.grid(row=4, column=1,padx=0, pady=5,sticky=Tkinter.N+Tkinter.S+Tkinter.W)
cklistscroll.config(command=cklistbx.yview)
# Assign all files to listbox
for assetName in assetList :
listbx.insert(Tkinter.END, assetName)
listbx.select_set(0)
# Build Buttons
changeVals = Tkinter.Button(frameButtons, text="Check Out", command=openForEdit).grid(row=0, column=0,padx=1)
saveFile = Tkinter.Button(frameButtons, text="Save", command=writeVals).grid(row=0, column=1,padx=1)
#bExit = Tkinter.Button(frameButtons, text="QUIT", fg="red", command=root.quit).grid(row=0, column=2)
bBatchAllOn = Tkinter.Button(frameButtons, text="BatchAll", command=batchAllOn).grid(row=0, column=2,padx=1)
bBatchAllOn = Tkinter.Button(frameButtons, text="BatchNone", command=batchAllOff).grid(row=0, column=3,padx=1)
spacer = Tkinter.Label(frameButtons, text = " Batch:").grid(row=0, column=4)
# Build Label
#v = Tkinter.StringVar()
#lbStat = Tkinter.Label(frameButtons, textvariable=v)
#lbStat.grid(row=0, column=1)
#v.set("Status:")
# Build Label used to hold tile image
imgLabel = Tkinter.Label(frameImage)
imgLabel.grid(row=0, column=0)
# Bind Click and up and down arrows to list
listbx.bind('', lambda test : listUpdate(listbx, False))
listbx.bind('', lambda test : listUpdate(listbx, False))
listbx.bind('', lambda test : listUpdate(listbx, False))
#cklistbx.bind('',lambda test : listUpdate(cklistbx, False))
#cklistbx.bind('', lambda test : listUpdate(cklistbx, False))
#cklistbx.bind('', lambda test : listUpdate(cklistbx, False))
eListBx.bind('', lambda test : listUpdate(listbx, True))
# Check Box Widgets
lbStat = Tkinter.Label(frameChkBx, text="Batch | Enabled | Property")
lbStat.grid(row=4, column=0, padx=1, pady=1, sticky=Tkinter.W, columnspan=2)
saveChkBoxToggle = [] #Batch Save Variable
UIsaveButton = [] #UI Batch Save Check button
varChkBox = [] #Check Box Variable
UIchkBx = [] #UI Checkbox
for chkBx in range (0,len(chkBoxList)) :
saveChkBoxToggle.append(Tkinter.IntVar())
UIsaveButton.append(Tkinter.Checkbutton(frameChkBx, text="", variable=saveChkBoxToggle[chkBx]))
UIsaveButton[chkBx].grid(row=(5+chkBx), column=0, padx=1, pady=1, sticky=Tkinter.W)
varChkBox.append(Tkinter.IntVar())
UIchkBx.append((Tkinter.Checkbutton(frameChkBx, text=chkBoxList[chkBx], variable=varChkBox[chkBx])))
UIchkBx[chkBx].grid(row=(5+chkBx), column=1, padx=1, pady=1, sticky=Tkinter.W)
# Entry Widgets
EvStat = Tkinter.Label(frameEntry, text="Batch | Property | Value")
EvStat.grid(row=2, column=1, padx=1, pady=1, sticky=Tkinter.W, columnspan=3)
#Name
savName = Tkinter.IntVar()
saName = Tkinter.Checkbutton(frameButtons, text="", variable=savName)
saName.grid(row=0, column=6, sticky=Tkinter.E)
lName = Tkinter.Label(frameButtons, text="Name").grid(row=0, column=7, sticky=Tkinter.W)
evName = Tkinter.StringVar()
eName = Tkinter.Entry(frameButtons,width=25, textvariable=evName)
eName.grid(row=0, column=8, sticky=Tkinter.W)
saveEntryToggle = [] #Batch Save Variable
UIsaveEntry = [] #UI Batch Save Check button
UIentryLabel = [] #UI Entry Label
varEntry = [] #Entry Variable
UIEntry = [] #UI Checkbox
for chkBx in range (0,len(entryList)) :
saveEntryToggle.append(Tkinter.IntVar())
UIsaveEntry.append(Tkinter.Checkbutton(frameEntry, text="", variable=saveEntryToggle[chkBx]))
UIsaveEntry[chkBx].grid(row=(3+chkBx), column=1, padx=1, pady=1, sticky=Tkinter.W)
if entryList[chkBx][1] == "value" : tempText = entryList[chkBx][0]
else: tempText = entryList[chkBx][0] + " " + entryList[chkBx][1]
UIentryLabel.append(Tkinter.Label(frameEntry, text=tempText).grid(row=(3+chkBx), column=2,padx=5, pady=1, sticky=Tkinter.W))
varEntry.append(Tkinter.StringVar())
UIEntry.append(Tkinter.Entry(frameEntry,width=5, textvariable=varEntry[chkBx]))
UIEntry[chkBx].grid(row=(3+chkBx), column=3,padx=5, pady=1, sticky=Tkinter.W)
root.mainloop()
|