diff utils/frminfo/make_xml.py @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/frminfo/make_xml.py	Sun Jun 29 18:44:17 2008 +0000
@@ -0,0 +1,192 @@
+#! /usr/bin/env python
+import os,sys,string
+SUFFIX_LIST = [ "aa","ab","at","ae","ak","al","an","ao","ap","ar","as","aq" ]
+IDLE,WALK,RUN,CLIMB,PICKUP,USE,DODGE,HITFRONT,HITBACK,KICK,THROW,PUNCH =  range(len(SUFFIX_LIST))
+ACTION_IDS = range(len(SUFFIX_LIST))
+ACTION_NAMES = [
+"IDLE","WALK","RUN","CLIMB","PICKUP","USE","DODGE","HITFRONT","HITBACK","KICK","THROW","PUNCH"
+]
+SUFFIX_DICT = dict(zip(SUFFIX_LIST,ACTION_IDS))
+
+USAGE="""
+*** make_xml.py ***
+Generates XML Critter information from frm info in critter.dat
+--list			List all critters
+--to-xml CRITTER	Output XML generated for a critter CRITTER
+			into a file in the current directory
+--all-xml DIRECTORY	Output XML files for all critters in the list
+			into the directory DIRECTORY
+"""
+
+CRITTER_XML = string.Template("""\
+<!--
+	This is an auto-generated XML file
+	defining the animation actions a
+	critter can perform.
+	
+	Generator: make_xml.py
+-->
+<complex-animation name="$name" geometry="1">
+$actions
+</complex-animation>""")
+
+ACTION_XML = string.Template("""\
+	<!-- ACTION: $name FRAMES: $numFrames FPS: $fps -->
+	<action id="$id" direction="255">
+		<animation src="$filename"/>
+$partialActions
+	</action>
+""")
+
+PARTIAL_ACTION_XML=string.Template("""\
+		<partial-action number="$number">
+			<frames start="$startFrame" number="$endFrame"/>
+			<step number="$stepNumber"/>
+			<partial-action action="$nextActionId" number="$nextNumber" direction="255"/>
+		</partial-action>
+""")
+
+MOTION_XML = string.Template("""\
+		<motion distance="$distance"/>
+""")
+
+class Action(object):
+	def __init__(self,critter,suffix):
+		self.critter = critter
+		self.suffix = suffix
+		self.id = SUFFIX_DICT[ suffix ]
+		self.filename = "art/critters/" + self.critter.basename + self.suffix +".frm"
+		self.frminfo_parsed = False
+		
+	def __str__(self):
+		if self.frminfo_parsed:
+			return self.suffix + "[nframes="+str(self.numframes)+",fps="+str(self.fps)+"]"
+		return self.suffix + "[id="+str(self.id)+"]"
+	
+	def parseFrmInfo(self):
+		if self.frminfo_parsed: 
+			return
+		frminfo = os.popen("./frminfo -t " + self.filename).read()
+		print >> sys.stderr, "Parsing FRMINFO: ",self.filename
+		frminfo = [tuple(line.replace(" ","").split("=")) for line in frminfo.split("\n")[:-1]]
+		values = dict(frminfo)
+		self.numframes = int(values['num_frames'])
+		self.fps = int(values['frames_per_second'])
+		self.shiftx = int(values["shift_xy"].split(',')[0])
+		self.frminfo_parsed = True
+	def measureDistance(self):
+		cmd ="./frminfo -t " +self.filename + " -i " + str(self.numframes-1)+ " -d 1"
+		frminfo = os.popen(cmd).read()
+		frminfo = [tuple(line.replace(" ","").split("=")) for line in frminfo.split("\n")[:-1]]
+		values = dict(frminfo)
+		x,y = map(int,values["shift_xy"].split(","))
+		distance = (x - self.shiftx+ 16) / 32
+		print >> sys.stderr, ACTION_NAMES[self.id],"distance:",distance
+		return distance
+		
+	def generatePartialActions(self,actionId):
+		partialActions = ""
+		npas=1
+		if actionId in  [WALK,RUN]:
+			npas = self.measureDistance()
+			partialActions += MOTION_XML.substitute(distance=npas)
+			
+		if npas==0:
+			npas=1
+			
+		delta = (self.numframes/npas)
+		startFrame=0
+		endFrame = delta 
+		nextActionId = actionId	
+		for number in range(npas):
+			nextNumber = (number+1) % npas
+			stepNumber=number
+			partialActions += PARTIAL_ACTION_XML.safe_substitute(locals())
+			startFrame += delta
+		return partialActions
+		
+	def buildXML(self):
+		#if self.id not in [RUN,WALK]: return ""
+		self.parseFrmInfo()
+		id = self.id
+		name = ACTION_NAMES[id]
+		fps = self.fps
+		numFrames = self.numframes
+		filename = self.filename
+		partialActions = self.generatePartialActions(id)
+		return ACTION_XML.safe_substitute(locals())
+		
+class Critter(object):
+	def __init__(self,basename):
+		self.basename = basename
+		self.actions = {}
+		self.xml=""
+	def __str__(self):
+		return self.basename +"("+",".join(map(str,self.actions.values()))+")"
+	
+	def addAction(self,suffix):
+		action = Action(self,suffix)
+		self.actions[ action.id ] = action
+		
+	def buildXML(self):
+		if self.xml: return self.xml
+		name = self.basename
+		actions = ""
+		for action in self.actions.values():
+			actions += action.buildXML()
+		
+		return CRITTER_XML.safe_substitute(locals())
+		
+def readCritters():
+	critters = os.popen("./frminfo -l 14").read().split("\n")[1:]
+	critter_types = {}
+	for critter in critters:
+		basename = os.path.basename(critter).split('.')[0][:6]
+		if not basename:
+			continue
+		
+		action = os.path.basename(critter).split('.')[0][6:]
+		if not critter_types.has_key(basename):
+			critter_types[ basename ] = Critter(basename)
+		critter = critter_types[ basename ]
+		critter.addAction( action )
+		
+	return critter_types
+		
+
+def exportToXML(critter_name,critters,directory="./"):
+	if not critters.has_key(critter_name):
+		print >> sys.stderr, "Critter ",critter_name," not found."
+		sys.exit(1)
+		
+	critter = critters[critter_name]
+	
+	xml= critter.buildXML()
+	fname = os.path.join(directory,critter.basename + ".xml")
+	file =open(fname,"w")
+	file.write(xml)
+	print >> sys.stderr, "Wrote to ",fname
+	
+def main():
+	if len(sys.argv) == 1:
+		print USAGE
+		sys.exit(1)
+	print >> sys.stderr, "Reading Critter List"
+	critters = readCritters()
+	if sys.argv[1] == '--list':
+		for name,critter in critters.items():
+			name_getter = lambda x: ACTION_NAMES[x]
+			print name," actions  = ",map(name_getter,critter.actions.keys())
+		sys.exit(0)
+			
+	if len(sys.argv) == 2:
+		print USAGE
+		sys.exit(1)
+		
+	if sys.argv[1] == '--to-xml':
+		exportToXML( sys.argv[2], critters)
+	if sys.argv[1]=='--all-xml':
+		for critter_name in critters.keys():
+			exportToXML(critter_name,critters,sys.argv[2])
+	
+if __name__=="__main__": main();
\ No newline at end of file