Files
2025-09-29 00:52:08 +02:00

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
#----------------------------------------------------------------------