111 lines
4.8 KiB
Ruby
111 lines
4.8 KiB
Ruby
![]() |
# The Natural Motion API is defined by a set of strings in NmRsMessageDefinitions.h which
|
||
|
# are accessed via enums in game code. The enum <--> string mapping is in CNmDefines and
|
||
|
# needs to be kept up to date with the NmRsMessageDefinitions.h which is where this little
|
||
|
# script comes in.
|
||
|
#
|
||
|
# Strip out everything but the API strings from NmRsMessageDefinitions and compare with
|
||
|
# the strings in NmDefines.cpp.
|
||
|
#
|
||
|
# Started on : 18/2/10
|
||
|
# Author : Richard Archibald
|
||
|
|
||
|
|
||
|
# Some defines to allow this script to work from any location and under different projects
|
||
|
# more easily.
|
||
|
PROJECT_BASE = "x:/gta5/src/dev_nm"
|
||
|
RAGE_DIR = "#{PROJECT_BASE}/rage"
|
||
|
|
||
|
|
||
|
# EXECUTION START:
|
||
|
if __FILE__ == $0
|
||
|
|
||
|
# Open the files to compare.
|
||
|
puts "Opening \"#{RAGE_DIR}/naturalmotion/src/rockstar/NmRsMessageDefinitions.h\""
|
||
|
nmApiFile = File.open("#{RAGE_DIR}/naturalmotion/src/rockstar/NmRsMessageDefinitions.h", "r")
|
||
|
puts "Opening \"#{PROJECT_BASE}/game/task/Physics/NmDefines.cpp\""
|
||
|
gameDefinesFile = File.open("#{PROJECT_BASE}/game/task/Physics/NmDefines.cpp", "r")
|
||
|
|
||
|
# Create two temporary files to store the stripped down versions of the two files
|
||
|
# above. These are the files we will actually run a diff on.
|
||
|
puts "Creating temporary files..."
|
||
|
nmApiCmpFile = File.new("NmApiStrings.txt", "w")
|
||
|
puts "done 1 ok."
|
||
|
gameCmpFile = File.new("GameSideApiStrings.txt", "w")
|
||
|
puts "done 2 ok."
|
||
|
|
||
|
# Iterate over each line of NmRsMessageDefinitions.h and spit out the strings into a
|
||
|
# temporary file.
|
||
|
nmApiFile.each_line do |line|
|
||
|
line.chomp!().strip!() # Get rid of the trailing '\n' character and any leading or trailing whitespace.
|
||
|
if line.match('BEHAVIOUR\(.*\)') && !line.match('BEHAVIOUR\(stopAllBehaviours\)')
|
||
|
apiString = line
|
||
|
#apiString = apiString.sub("BEHAVIOUR\(", "") # Delete "BEHAVIOUR(".
|
||
|
#apiString.chomp!("\)") # Delete the trailing right parenthesis.
|
||
|
nmApiCmpFile.puts("============================== #{apiString} ==============================")
|
||
|
elsif line.match('PARAMETER\(.*\)')
|
||
|
apiString = line
|
||
|
apiString = apiString.sub("PARAMETER\(", "")
|
||
|
apiString = apiString.slice(0..apiString.index(',')-1) # Delete from the first comma onwards.
|
||
|
nmApiCmpFile.puts("\"#{apiString}\"")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Iterate over each line of NmDefines.cpp and spit out the API strings into a temporary file to
|
||
|
# compare with the one we just made above. This file is complicated by the fact that there are other
|
||
|
# bits of code and definitions in there that have nothing to do with the API. Use a flag to keep track of
|
||
|
# whether we've reached the start of the static string definitions of the API.
|
||
|
bApiSentinelFound = false
|
||
|
bThisLineIsBlank = false
|
||
|
gameDefinesFile.each_line do |line|
|
||
|
line.chomp!().strip!() # Get rid of the trailing '\n' character and any leading or trailing whitespace.
|
||
|
|
||
|
# Only parse those lines which are in the API string block. When the final "}" is found, set the
|
||
|
# sentinel flag back to false to skip over any remaining code in the file.
|
||
|
if bApiSentinelFound && line != "{" && !line.match("\"stopAllBehaviours\"") && !line.match("\"start\"")
|
||
|
|
||
|
# Have we reached the end of the API string block?
|
||
|
if line == "};"
|
||
|
bApiSentinelFound = false
|
||
|
else
|
||
|
# ***** PARSE THE API STRING BLOCK *****
|
||
|
apiString = line
|
||
|
# If a line is blank, the next valid string should be a behaviour name. Flag this so that we
|
||
|
# can insert a marker in the txt file to aid comparison.
|
||
|
bLastLineWasBlank = bThisLineIsBlank
|
||
|
bThisLineIsBlank = false
|
||
|
if apiString == ""
|
||
|
bThisLineIsBlank = true
|
||
|
end
|
||
|
# Skip blank lines, feedback messages, any C++ comment lines which might be in there and the
|
||
|
# final "nmstring_end" string.
|
||
|
if apiString != "" && apiString.match(/^\".+\" *,/) && !apiString.match(/_FB,$/)
|
||
|
apiString = apiString.slice(0..apiString.index(',')-1) # Delete from the first comma onwards.
|
||
|
if bLastLineWasBlank
|
||
|
2.times do apiString.sub!("\"", "") end # Lose the quotes.
|
||
|
gameCmpFile.puts("============================== BEHAVIOUR(#{apiString}) ==============================")
|
||
|
else
|
||
|
gameCmpFile.puts("#{apiString}")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Check for API string block. This goes at the end of the loop so that we don't parse the sentinel
|
||
|
# itself.
|
||
|
if line.match('CNmDefines::ms_aNMStrings')
|
||
|
bApiSentinelFound = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Close all files.
|
||
|
nmApiFile.close()
|
||
|
gameDefinesFile.close()
|
||
|
nmApiCmpFile.close()
|
||
|
gameCmpFile.close()
|
||
|
puts "All files closed, comparing files..."
|
||
|
|
||
|
# Visualise the differences using an external merge program with GUI.
|
||
|
system('"C:\Program Files\Perforce\p4merge.exe" NmApiStrings.txt GameSideApiStrings.txt')
|
||
|
puts "Finished."
|
||
|
end
|