592 lines
16 KiB
Ruby
Executable File
592 lines
16 KiB
Ruby
Executable File
#
|
|
#
|
|
# Author:: Mark Harrison-Ball <Mark.Harrison-Ball@rockstargames.com>
|
|
# Date:: 15 September 2013 (AP3)
|
|
# Purpose:
|
|
# ~ Inital analyis scene and generate a inital report
|
|
# - Upload inof to Database
|
|
# - Run external tool to generate acurate datafrom render
|
|
# - Generate Bugs from reports
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Uses
|
|
#-----------------------------------------------------------------------------
|
|
#$LOAD_PATH.unshift File.expand_path('../../Global/perforce/', __FILE__)
|
|
|
|
#NOTES
|
|
#
|
|
# Concat names are mission names
|
|
# Get list of concats
|
|
# Check name is not a concat name
|
|
# get clip name from anim name
|
|
|
|
|
|
require 'RSG.Base.dll'
|
|
require 'RSG.Base.Configuration.dll'
|
|
require 'RSG.Base.Windows.dll'
|
|
require 'RSG.SourceControl.Perforce'
|
|
require 'RSG.Metadata'
|
|
|
|
|
|
# Core
|
|
include RSG::Base::Configuration
|
|
include RSG::Base::Logging
|
|
include RSG::Base::Logging::Universal
|
|
include RSG::Base::OS
|
|
include RSG::SourceControl::Perforce
|
|
include RSG::Metadata
|
|
|
|
|
|
require 'mscorlib'
|
|
require 'System.Core'
|
|
require 'System.Xml'
|
|
|
|
|
|
include System::Collections::Generic
|
|
include System::IO
|
|
include System::Diagnostics
|
|
include System::Xml
|
|
include System::Runtime::InteropServices
|
|
include System::Net
|
|
include System::Net::Sockets
|
|
include System::Net::Mail
|
|
|
|
|
|
|
|
path = File.expand_path $0
|
|
path = File.dirname(path)
|
|
# Tool Specific classes
|
|
require "#{path}/../../Utils/CutsceneGrader/GradingReader.rb"
|
|
|
|
|
|
# global Core classes
|
|
require "#{path}/../../Global/project/project"
|
|
require "#{path}/../../Global/perforce/p4utils"
|
|
require "#{path}/../../Global/email/email.rb"
|
|
require "/GradingInfo.rb"
|
|
# To Depreciate as now lives in metautils
|
|
require "#{path}/../../Global/pargen/pscparser"
|
|
require "#{path}/../../Global/pargen/pscxmlparser"
|
|
#
|
|
require "#{path}/../../Global/metadata/metautils"
|
|
|
|
# Grading Stats
|
|
require "#{path}/../../Utils/CutsceneGrader/GradingStats"
|
|
|
|
# Cutfile object
|
|
require "#{path}/../../Global/cutscene/cutInfo"
|
|
|
|
# Clip Parser
|
|
require "#{path}/../../Global/anim/clip"
|
|
|
|
# Cutscene COntainer
|
|
require "#{path}/../../Utils/CutsceneGrader/CutsceneDef"
|
|
|
|
# EDL Parser
|
|
require "#{path}/../../Utils/ESTConversion/ESTconvert"
|
|
|
|
# EXCEL Parser
|
|
require "#{path}/../../Utils/ESTConversion/TrackingConvert"
|
|
|
|
# Debug Utils
|
|
require "#{path}/../../Global/debug/debugUtils.rb"
|
|
|
|
# Environment Coords Monitoring
|
|
require "#{path}/../../Utils/ReadFBX/readFBX.rb"
|
|
|
|
|
|
|
|
|
|
require 'pipeline/os/options'
|
|
include Pipeline
|
|
|
|
DEBUG = true
|
|
REPEAT = true
|
|
# Constants
|
|
CUTXML = 'data.cutxml'
|
|
CONCAT = '*.concatlist'
|
|
|
|
# time
|
|
sleepTime = 60 * 5
|
|
|
|
def logerror(e = 'unknown')
|
|
msg = "Exception occured: #{e.message} in #{e.backtrace}"
|
|
@g_Log.error(msg)
|
|
#send_email( AUTHOR, EXCEPTION_EMAIL, 'Cutscene Report Tool Crash', msg, @server)
|
|
end
|
|
|
|
|
|
# OLD METHOD
|
|
def updateStats( cutInfoList )
|
|
@g_Log.message('Updating Database Stats')
|
|
|
|
# Get our project we are working with
|
|
ProjectName = @g_Config.project.name.upcase
|
|
# Generate our Stats.
|
|
|
|
@cutStats.generateStats( cutInfoList, ProjectName )
|
|
end
|
|
|
|
def updateCutStats( objectList )
|
|
@g_Log.message('Updating Database Stats')
|
|
# Get our project we are working with
|
|
#ProjectName = @g_Config.project.name.upcase
|
|
# Generate our Stats.
|
|
#puts objectList
|
|
@cutStats.generateCutStats( objectList )
|
|
|
|
end
|
|
|
|
|
|
|
|
def syncPrequistes()
|
|
# Sync the definiations files
|
|
syncPaths = [@g_Config.project.DefaultBranch.Assets + "/metadata/definitions/...",
|
|
@g_Config.project.DefaultBranch.Assets + "/cuts/...cutxml",
|
|
@g_Config.project.DefaultBranch.Assets + "/non_final/cutscene/EDL/...edl",
|
|
@g_Config.project.root + "/docs/Production/*Camera_tracking.xlsm",
|
|
@g_Config.project.DefaultBranch.Assets + "/cuts/!!Cutlists/...concatlist",
|
|
@enviromentSets,
|
|
@g_Config.project.DefaultBranch.Assets + "/cuts/...clip",] # lets see how long this takes (Take 148 seconds from no assets)
|
|
|
|
# Batch up sync commands
|
|
@p4.sync(syncPaths,'')
|
|
end
|
|
|
|
|
|
def extractMissionName(clip)
|
|
fbx_property = @clip.getProperty("FBXFile_DO_NOT_RESOURCE",clip)
|
|
missionName = nil
|
|
if (fbx_property != nil) then
|
|
fbx_file = (fbx_property.GetPropertyAttributes()[0]).GetString()
|
|
fbx_file = fbx_file.Replace('\\','/')
|
|
assetSplit = fbx_file.Split('/')
|
|
# get name after "!!scenes"
|
|
sceneIndex = assetSplit.index("!!scenes")
|
|
if sceneIndex!=nil
|
|
missionName = assetSplit[sceneIndex+1]
|
|
end
|
|
end
|
|
missionName
|
|
|
|
end
|
|
|
|
# REFACTOR
|
|
def getMissionNameFromClips(dir)
|
|
clip_list = Directory.GetFiles(dir, "*.clip")
|
|
#puts clip_list
|
|
# Skip empty folders
|
|
if(clip_list.Length == 0) then
|
|
next
|
|
end
|
|
|
|
puts "==missionName=="
|
|
missionName = nil
|
|
#clip_list.each do | clip |
|
|
for i in (0..clip_list.Length-1)
|
|
puts "i=#{i.to_s} for clip #{clip_list[i]}"
|
|
missionName = extractMissionName(clip_list[i])
|
|
if missionName != nil then
|
|
break
|
|
end
|
|
end
|
|
missionName
|
|
end
|
|
|
|
|
|
|
|
def getCutInfo(cutFolder)
|
|
puts "Cutfolder = #{cutFolder}"
|
|
# To get our mission name we need a fucking clip file
|
|
clip_list = Directory.GetFiles(cutFolder, "*.clip")
|
|
# Skip empty folders
|
|
cutFile = nil
|
|
if clip_list.Length > 0
|
|
puts "==missionName=="
|
|
missionName = nil
|
|
#clip_list.each do | clip |
|
|
for i in (0..clip_list.Length-1)
|
|
puts "i=#{i.to_s} for clip #{clip_list[i]}"
|
|
missionName = extractMissionName(clip_list[i])
|
|
if missionName != nil then
|
|
break
|
|
end
|
|
end
|
|
puts 'prcessing cutxml'
|
|
cutxml = File.join(cutFolder, CUTXML)
|
|
|
|
if File.exist?(cutxml) # Make sure our File Exists
|
|
cutFile = CutFile.new(cutxml, @metadataUtils)
|
|
cutFile.missionStrand = missionName
|
|
debugPrint(cutFile)
|
|
#debugPrint(cutFile.shots)
|
|
#puts cutFile.shots[0].models[0].name
|
|
end
|
|
end
|
|
cutFile
|
|
|
|
end
|
|
|
|
# OBSOLETE - REMOVE
|
|
def processCuts()
|
|
@g_Log.message("Prcessing Cuts")
|
|
|
|
localList = []
|
|
|
|
# Process the rest of the cut files
|
|
projectPath = @g_Config.project.DefaultBranch.Assets + "/cuts/"
|
|
directory = projectPath
|
|
|
|
|
|
DirectoryList = Dir.entries(directory).select { |f| File.directory? File.join(directory, f)}
|
|
DirectoryList.each do |cutFolder|
|
|
puts "Procssing #{cutFolder}"
|
|
if not cutFolder=~/^\.\.?$/
|
|
if not cutFolder.start_with?('!!') or not @excludeList.include?(cutFolder.upcase)
|
|
_cutFile = getCutInfo(File.join(directory,cutFolder))
|
|
if _cutFile
|
|
cutDef = CutsceneDef.new(_cutFile, @ProjectID, P4fileinfo.new())
|
|
@CutInfoList.push(cutDef)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
localList
|
|
|
|
end
|
|
|
|
|
|
# OBSOLETE - REMOVE
|
|
def processConcuts()
|
|
# PROCESS OUR CONCATS
|
|
@g_Log.message("Prcessing Concats")
|
|
|
|
|
|
projectPath = @g_Config.project.DefaultBranch.Assets + "/cuts/!!Cutlists/"
|
|
localList= []
|
|
# Get our list of concat files
|
|
Dir["#{projectPath}*.concatlist"].each do |file|
|
|
@g_Log.message("Processing #{file}")
|
|
concatFile = ConcatFile.new(file, @metadataUtils, @g_Log)
|
|
puts "concatFile = #{concatFile} "
|
|
#if concatFile.isValid
|
|
# we need to get the mission name form the first shot
|
|
if concatFile.shots.count > 0
|
|
dirPath = File.dirname(concatFile.shots[0].shotPath)
|
|
clip_list = Directory.GetFiles(File.join(dirPath), "*.clip")
|
|
missionName = nil
|
|
#clip_list.each do | clip |
|
|
for i in (0..clip_list.Length-1)
|
|
#puts "i=#{i.to_s} for clip #{clip_list[i]}"
|
|
missionName = extractMissionName(clip_list[i])
|
|
if missionName != nil then
|
|
break
|
|
end
|
|
end
|
|
|
|
concatFile.missionStrand = missionName #File.basename(file,".*")
|
|
cutDef = CutsceneDef.new(concatFile, @ProjectID, P4fileinfo.new())
|
|
@CutInfoList.push(cutDef)
|
|
@excludeList.push(concatFile.name)
|
|
debugPrint(concatFile)
|
|
end
|
|
end
|
|
localList
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make sure email is valid...
|
|
def validateemail(email)
|
|
validEmail = email
|
|
emailTokens = email.split("@")
|
|
if emailTokens[1] == "take2games.com" then
|
|
validEmail = emailTokens[0] + "@rockstargames.com"
|
|
end
|
|
validEmail
|
|
end
|
|
|
|
def _getP4HeaderInfo(change, filename)
|
|
revIndex = @p4.get_file_info(filename, 'headRev')
|
|
headerinfo = P4fileinfo.new(change)
|
|
# Update additional p4 Info
|
|
headerinfo.email = validateemail(@p4.get_user_email(change.username))
|
|
headerinfo.filename = filename
|
|
headerinfo.revision = revIndex.to_i
|
|
|
|
return headerinfo
|
|
end
|
|
|
|
def fileDepotPath(filename)
|
|
localPath = nil
|
|
if filename != nil
|
|
# FIX FOR GTA in DEPOT PATH :(
|
|
filename = filename.sub('depot/','')
|
|
# Switch to X drive
|
|
localPath = "x:/"+filename.split("//")[1]
|
|
localPath
|
|
end
|
|
end
|
|
|
|
# Check if the data cutxml is in the root of the cutscene
|
|
# Pass in of a perforce file Path
|
|
def isRootDataCut(filePath)
|
|
isValid = false
|
|
pathSplit = filePath.downcase.split("/")
|
|
index = pathSplit.index('cuts')
|
|
if index != nil
|
|
if pathSplit[index+2] == CUTXML then
|
|
isValid = true
|
|
end
|
|
end
|
|
return isValid
|
|
end
|
|
|
|
|
|
# MOve to own syncs
|
|
|
|
def parseConcats()
|
|
# Check for any new Concats
|
|
@lastCL, changes = @p4.parse_p4_review(@concatsPath, @currentCL, @head)
|
|
|
|
changes.each do | change |
|
|
validfiles = @p4.findFilesinChange( change, CONCAT )
|
|
validfiles.each do | filename |
|
|
localPath = fileDepotPath(filename)
|
|
headerinfo = _getP4HeaderInfo(change, filename)
|
|
|
|
_concatFile = ConcatFile.new(localPath, @metadataUtils, @g_Log)
|
|
puts _concatFile.name
|
|
if _concatFile.shots.count > 0
|
|
dirPath = File.dirname(_concatFile.shots[0].shotPath)
|
|
clip_list = Directory.GetFiles(File.join(dirPath), "*.clip")
|
|
missionName = nil
|
|
#clip_list.each do | clip |
|
|
for i in (0..clip_list.Length-1)
|
|
missionName = extractMissionName(clip_list[i])
|
|
if missionName != nil then
|
|
break
|
|
end
|
|
end
|
|
_concatFile.missionStrand = missionName
|
|
|
|
cutDef = CutsceneDef.new(_concatFile, @ProjectID, headerinfo)
|
|
|
|
@CutInfoList.push(cutDef)
|
|
@excludeList.push(_concatFile.name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def processTracking()
|
|
# Check for Tracking DOc Changes
|
|
@lastCL, changes = @p4.parse_p4_review(@trackingDoc, @currentCL, @head)
|
|
changes.each do | change |
|
|
validfiles = nil
|
|
if @ProjectName == "RDR3" then
|
|
validfiles = @p4.findFilesinChange( change, 'RDR3_CAMERA_TRACKING.xlsm' ) # Hardcoded xls file
|
|
elsif @ProjectName == "GTA5" then
|
|
validfiles = @p4.findFilesinChange( change, 'GTAV_CAMERA_TRACKING.xlsm' ) # Hardcoded xls file
|
|
end
|
|
if validfiles.count > 0 then
|
|
localPath = fileDepotPath(validfiles[0])
|
|
if localPath != nil and File.exist?(localPath) then
|
|
headerinfo = _getP4HeaderInfo(change, validfiles[0])
|
|
@ExcelTracking.parseExcelDoc(localPath, headerinfo, @ProjectID )
|
|
end
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
|
|
def processEDLs()
|
|
# Check for EST submits an
|
|
@lastCL, changes = @p4.parse_p4_review(@edlPath, @currentCL, @head)
|
|
changes.each do | change |
|
|
validfiles = @p4.findFilesinChange( change, '*.edl' )
|
|
validfiles.each do | filename |
|
|
localPath = fileDepotPath(filename)
|
|
|
|
if localPath != nil and File.exist?(localPath) then
|
|
headerinfo = _getP4HeaderInfo(change, filename)
|
|
@avidUpdate.parseEDL(localPath, headerinfo, @ProjectID )
|
|
debugPrint(headerinfo)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# Check for Environment submits
|
|
def processSets()
|
|
@lastCL, changes = @p4.parse_p4_review(@enviromentSets, @currentCL, @head)
|
|
changes.each do | change |
|
|
validfiles = @p4.findFilesinChange( change, '*.fbx' )
|
|
validfiles.each do | filename |
|
|
localPath = fileDepotPath(filename)
|
|
if localPath != nil and File.exist?(localPath) then
|
|
@readFBX.parseFBX(localPath)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
def processCuts()
|
|
@lastCL, changes = @p4.parse_p4_review(@cutsPath, @currentCL, @head)
|
|
puts @lastCL
|
|
changes.each do | change |
|
|
# Check each change, see if there has been a cutxml file submitted
|
|
validfiles = @p4.findFilesinChange( change, CUTXML )
|
|
validfiles.each do | filename |
|
|
# ignore cutxml files in sub directories. Best to use strict Path
|
|
if isRootDataCut(filename) then
|
|
# Set to local Path... prop better way of doign this.
|
|
# CAn use the rsg source contril file state method but might be a laod on teh p4 server unless its a local command?
|
|
localPath = fileDepotPath(filename)
|
|
if localPath != nil and File.exist?(localPath) then
|
|
if not @excludeList.include?(localPath.upcase)
|
|
# Get P4 header for CL
|
|
headerinfo = _getP4HeaderInfo(change, filename)
|
|
# Get out Cutscene Data
|
|
_cutFile = getCutInfo(File.dirname(localPath))
|
|
if _cutFile
|
|
cutDef = CutsceneDef.new(_cutFile, @ProjectID, headerinfo)
|
|
@CutInfoList.push(cutDef)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def parse_p4_review()
|
|
# List of Cutscene Chnage Inforamtion
|
|
@excludeList = []
|
|
@CutInfoList = []
|
|
|
|
syncPrequistes()
|
|
@head = '#head'
|
|
parseConcats()
|
|
processCuts()
|
|
|
|
# Upload to Database
|
|
if @CutInfoList.count > 0
|
|
puts @CutInfoList[0]
|
|
updateCutStats(@CutInfoList)
|
|
end
|
|
|
|
processEDLs()
|
|
processTracking()
|
|
processSets()
|
|
|
|
|
|
end
|
|
|
|
|
|
#
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Entry-Point
|
|
#-----------------------------------------------------------------------------
|
|
if ( __FILE__ == $0 ) then
|
|
#g_Options = OS::Options::new( OPTIONS )
|
|
#Need to enable the initlaize on the TOOLS NG Branch
|
|
LogFactory.Initialize()
|
|
LogFactory.CreateApplicationConsoleLogTarget( )
|
|
@g_Log = LogFactory.ApplicationLog
|
|
|
|
# Config initialisation.
|
|
@g_Config = RSG::Base::Configuration::ConfigFactory::CreateConfig( )
|
|
@email = @g_Config.EmailAddress
|
|
@server= @g_Config.studios.this_studio.exchange_server
|
|
@g_Log.message("Using Server: #{@g_Config.studios.this_studio}")
|
|
|
|
|
|
|
|
# Database/Stat Init
|
|
@cutStats = GradingStats.new(@g_Log)
|
|
@avidUpdate = AvidUpdate.new(@g_Log)
|
|
@ExcelTracking = TrackingDocUpdate.new(@g_Log)
|
|
@readFBX = ReadFBX.new(@g_Log, @g_Config)
|
|
|
|
|
|
|
|
branch = @g_Config.Project.DefaultBranch
|
|
|
|
|
|
@p4 = P4Utils.new(@g_Log)
|
|
|
|
@clip = Clip.new(@g_Log)
|
|
# Reference our PSC parser
|
|
@metadataUtils = MetaData.new( branch )
|
|
@gradingreader = GradingReader.new(@g_Log)
|
|
|
|
@ProjectName = @g_Config.project.name.upcase
|
|
@ProjectID = getProjectID(@ProjectName)
|
|
|
|
|
|
# Perforce Monitor PATHS
|
|
@cutsPath = @g_Config.project.DefaultBranch.Assets + "/cuts/...cutxml"
|
|
@concatsPath = @g_Config.project.DefaultBranch.Assets + "/cuts/!!Cutlists/...concatlist"
|
|
@edlPath = @g_Config.project.DefaultBranch.Assets + "/non_final/cutscene/EDL/...edl"
|
|
@enviromentSets = @g_Config.project.DefaultBranch.Art + "/animation/resources/Sets/...FBX"
|
|
@trackingDoc = @g_Config.project.root + "/docs/Production/...xlsm"
|
|
|
|
# Get current CL number
|
|
@currentCL = @p4.get_current_changelistnumber()
|
|
@currentCL = 5213222 #TEST
|
|
|
|
|
|
begin
|
|
loop do
|
|
unless not REPEAT
|
|
begin
|
|
@g_Log.message('Working in Automation mode')
|
|
# CHeck the DataBase to see if there is a full grading request
|
|
#queryGradingRequest()
|
|
# Check if any new data has been submitted to p4
|
|
parse_p4_review()
|
|
@currentCL = @lastCL
|
|
|
|
@g_Log.message("Current CL: #{@currentCL}")
|
|
@g_Log.message("Waiting for...#{sleepTime.to_s} seconds.......")
|
|
sleep(sleepTime)
|
|
|
|
rescue => e
|
|
logerror(e)
|
|
end
|
|
else
|
|
begin
|
|
@g_Log.message('Working in Single mode')
|
|
# Check if we have a grading request
|
|
|
|
#test()
|
|
@g_Log.message('Complete')
|
|
|
|
rescue => e
|
|
logerror(e)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|
|
|