182 lines
8.2 KiB
Python
Executable File
182 lines
8.2 KiB
Python
Executable File
###############################################################################################################
|
|
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
##
|
|
## 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
|
|
#----------------------------------------------------------------------
|
|
|