# cutscene_cam_parser.rb # # Luke Openshaw # # Convert anim using anim2text and parse output to find FOV problem # There is an instatiation of an AnimationParserManager at the foot # of this script which passes true to the initialize fucntion to convert # all camera anims in the cuts root # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'find' require 'pipeline/os/path' require 'fileutils' module Animation # == Description # # Manager for the converting anims and parsing for FOV issues # class AnimationParserManager #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- CUTSCENE_ROOT = 'x:/gta/gta_assets/cuts/' OUTPUT_ROOT = 'x:/streamgta/cutscene_cams/' KEYNAME = 'camera' TRACK_FOV = 136 TRACK_JUMPCUT = 144 FOV_TOLERANCE = 3.0 attr_reader :animtextlist attr_reader :animtestlistfailed attr_reader :tracks attr_reader :animlist attr_reader :bustedscenes attr_reader :bustedscenesinfo def initialize(convertanims) @animlist = Array.new() @animtextlist = Array.new() @animtestlistfailed = Array.new() @bustedscenes = Array.new() @bustedscenesinfo = Array.new() trackids = Array[TRACK_FOV, TRACK_JUMPCUT] if convertanims build_anim_list(@animlist, CUTSCENE_ROOT) batch_anim_to_text() else build_anim_list(@animtextlist, OUTPUT_ROOT) end for animtext in @animtextlist do tracks = AnimationParser.parse(animtext, trackids) fovtrack = tracks[0] jumptrack = tracks[1] for j in 0..jumptrack.keys.length if jumptrack.keys[j].to_s == '1.0' if j + 2 < jumptrack.keys.length curr = fovtrack.keys[j].to_f currplus1 = fovtrack.keys[j+1].to_f currplus2 = fovtrack.keys[j+2].to_f diff = currplus2 - currplus1 if curr == currplus1 and currplus1 != currplus2 and diff.abs > FOV_TOLERANCE @bustedscenesinfo.push(animtext + ": " + jumptrack.owner + ": " + j.to_s) #if @bustedscenes.rindex(jumptrack.owner) == nil @bustedscenes.push(jumptrack.owner) if @bustedscenes.rindex(jumptrack.owner) == nil end end end end end print("SCENES\n") @bustedscenes.each { |scenename| print(scenename + "\n") } print("\n\n") print("DETAILS\n") @bustedscenesinfo.each { |info| print(info + "\n") } end def build_anim_list(animlist, rootpath) Find.find( rootpath ) do |subpath| if FileTest.file?( subpath ) subfile = Pipeline::OS::Path.get_basename(subpath) if subfile[0,6] == KEYNAME animlist.push(subpath) end end end end def batch_anim_to_text() @animlist.each { |animfile| anim_to_text(animfile) } end def anim_to_text( file ) scenename = Pipeline::OS::Path.get_trailing_directory(file) outputpath = OUTPUT_ROOT + scenename + "/" FileUtils.mkdir_p outputpath if File.directory?(outputpath) == false outputfile = outputpath + "/" + Pipeline::OS::Path.get_basename(file) + ".txt" cmd = "x:/tools_release/gta_bin/anim2text.exe " + file + " " + outputfile retval = system(cmd) if retval @animtextlist.push(outputfile) else @animtestlistfailed.push(outputfile) end end end # # == Description # # Parser for output from anim2text # class AnimationParser attr_reader :tracks def AnimationParser.parse(filename, trackids) @tracks = Array.new() File.open( filename, 'r' ) { |animfile| while animfile.eof == false do currentline = animfile.readline segs = currentline.split(':') if segs.length == 2 if segs[0] == 'track type' subsegs = segs[1].split(' ') if subsegs.length == 2 trackid = subsegs[1].tr('()', '').to_i for targettrackid in trackids do if trackid == targettrackid track = Track.new() track.tracktype = trackid track.owner = Pipeline::OS::Path.get_trailing_directory(filename) @tracks.push(AnimationParser.build_track(animfile, track)) end end end end end end } @tracks end def AnimationParser.build_track(animfile, track) track.keys = Array.new() finished = false currentline = animfile.readline currentline = animfile.readline while animfile.eof == false and finished == false do segs = currentline.split(':') if segs.length == 2 if segs[0].slice(0..2) == 'key' track.keys.push(segs[1].to_f) else finished = true end else finished = true end currentline = animfile.readline end track end end # # == Description # # Track class. Could really be a struct # class Track attr_reader :owner attr_reader :boneid attr_reader :tracktype attr_reader :keys def owner=( value ) @owner = value end def boneid=( value ) @boneid = value end def tracktype=( value ) @tracktype = value end def keys=( value ) @keys = value end end end animparser = Animation::AnimationParserManager.new(true)