############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Script Name: AnimFile.py ## Written And Maintained By: Ross George ## Contributors: David Bailey ## Description: Allows the parsing and enumeration of any data ## contained in an .anim file. Most of this script was adapted from ## scripts written by David Bailey. This allows us to fetch any data from ## an an .anim file. Including camera data which is the initial purpose ## of the classes contained within. ## ## Rules: Definitions: Prefixed with "rs_" ## Global Variables: Prefixed with "g" ## Local Variables: Prefixed with "l" ## Iteration Variables: Prefixed with "i" ## Arguments: Prefixed with "p" ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### #Debug #import wingdbstub import os import subprocess import tempfile #function from D.B script - need to integrate def partition(alist, indices): return [alist[i:j] for i, j in zip([0]+indices, indices+[None])] ######################################################################## class rs_Track: """Represents a track within an .anim file""" #---------------------------------------------------------------------- def __init__(self, pTrackData): """ Initializor which takes input data in the form of a string chunk direct from a .anim file. """ #---------------------------------------------------------------------- #Instance Variables #---------------------------------------------------------------------- self.mTrackNumber = -1 self.mTrackID = -1 self.mTrackTypeNumber = -1 self.mTrackTypeString = "" self.mTrackValues = [] #---------------------------------------------------------------------- #Pop the first line of the data string which should contain the header #info for the track lTrackHeaderData = pTrackData.pop(0) #Partition on the tab character (should only be one) #then split the result of that on the space character lTrackHeaderDataParsed = lTrackHeaderData.partition("\t")[2].split(" ") #Read in the various track descriptors self.mTrackNumber = lTrackHeaderDataParsed[1] self.mTrackID = lTrackHeaderDataParsed[3] self.mTrackTypeNumber = lTrackHeaderDataParsed[5] self.mTrackTypeString = lTrackHeaderDataParsed[6] #Strip out newline character from end of TrackTypeString self.mTrackTypeString = self.mTrackTypeString.strip('\n') #Then read in the track values while len( pTrackData ) > 0: #Pop off the next line which should be a track value lTrackValueData = pTrackData.pop(0) #Check if we have a new line character then break as #we have finished the track if( lTrackValueData == "\n" ): break #Partition on the tab character (should only be one) #then split the result of that on the space character lTrackValueDataParsed = lTrackValueData.partition("\t")[2].split(" ") lTrackValueSet = [] #Read in each of the track set values. #Sometimes there are three (x,y,z) sometimes less (camera fov). while len( lTrackValueDataParsed ) > 0: #Read the current value and add it to the current track value set try: lTrackValueSetSub = float( lTrackValueDataParsed.pop(0) ) lTrackValueSet.append( lTrackValueSetSub ) except: lTrackValueSetSub = 0.0 lTrackValueSet.append( lTrackValueSetSub ) #Add this track value set self.mTrackValues.append( lTrackValueSet ) #---------------------------------------------------------------------- ######################################################################## class rs_AnimFile: """For reading .anim files and working with the data contained within""" kEuler = 0 kQuaterion = 1 #---------------------------------------------------------------------- def __init__( self, pFileName, pRotationFormat = kEuler ): """Initializor which takes the path of the .anim file to be parsed""" #---------------------------------------------------------------------- #Instance Variables #---------------------------------------------------------------------- self.mTracks = [] #---------------------------------------------------------------------- lCmdString = "" lInputFile = pFileName lOutputFile = os.path.splitext(pFileName)[0] + ".txt" if pRotationFormat == self.kEuler : lCmdString = "{ToolsRoot}\\bin\\anim\\animdump.exe -anim \"{InputFile}\" -values -output -eulers > \"{OutputFile}\" -skel \{ToolsRoot}\\etc\\config\\anim\\skeletons\\player.skel\"".format( ToolsRoot = RS.Config.Tool.Path.Root, InputFile = lInputFile, OutputFile = lOutputFile) elif pRotationFormat == self.kQuaterion : lCmdString = "{ToolsRoot}\\bin\\anim\\animdump.exe -anim \"{InputFile}\" -values -output > \"{OutputFile}\" -skel \{ToolsRoot}\\etc\\config\\anim\\skeletons\\player.skel\"".format( ToolsRoot = RS.Config.Tool.Path.Root, InputFile = lInputFile, OutputFile = lOutputFile) else: #Passed an invalid pRotationFormat raise ValueError subprocess.call(lCmdString, stdin=None, stdout=None, stderr=None, shell=True) #Open and read in file data lFile = open(lOutputFile, "r") lFileData = lFile.readlines() lTrackIndexArray = [] #Get each index of the tracks so we can spilt the #file data at the next phase for iLine in lFileData: if iLine.startswith("Track"): lTrackIndexArray.append(lFileData.index(iLine)) #Partition the file data with the track indexes lAnimData = partition(lFileData, lTrackIndexArray) #ToDo - Parse header info lAnimHeaderData = lAnimData.pop(0) #Now parse the remaining data which should all be tracks while len( lAnimData ) > 0: #Pop off the next chunk of data and create a new Track #object using it lTrackData = lAnimData.pop(0) lTrack = rs_Track( lTrackData ) #Add it to our list of tracks self.mTracks.append( lTrack ) #---------------------------------------------------------------------- #---------------------------------------------------------------------- def GetTrack_TypeString(self, pTrackTypeString): """Returns a track by the passed TrackTypeString. Or None if it doesn't exist.""" try: lTrack = filter( lambda iTrack: iTrack.mTrackTypeString == pTrackTypeString, self.mTracks ) return lTrack[0] except: return None #---------------------------------------------------------------------- #---------------------------------------------------------------------- def TrackExists_TypeString (self, pTrackTypeString): """Returns true if the track with the passed pTrackTypeString exists. Else returns false.""" if( self.GetTrack_TypeString(pTrackTypeString) == None ): return False else: return True #----------------------------------------------------------------------