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

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