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

236 lines
10 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/util/data_convert_file.rb
# Description:: Entry-point into our asset build pipeline.
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# Date:: 19 March 2012
#
#-----------------------------------------------------------------------------
# Uses
#-----------------------------------------------------------------------------
require 'RSG.Base.dll'
require 'RSG.Base.Configuration.dll'
require 'RSG.Base.Windows.dll'
require 'RSG.Pipeline.Core.dll'
require 'RSG.Pipeline.Content.dll'
require 'RSG.Pipeline.Engine.dll'
include RSG::Base::Configuration
include RSG::Base::Logging
include RSG::Base::Logging::Universal
include RSG::Base::OS
include RSG::Base::Windows
include RSG::Pipeline::Core
include RSG::Pipeline::Content
include RSG::Pipeline::Engine
require 'mscorlib'
require 'System.Core'
include System::Collections::Generic
include System::IO
using_clr_extensions System::Linq
require 'pipeline/os/options'
include Pipeline
#-----------------------------------------------------------------------------
# Constants
#-----------------------------------------------------------------------------
AUTHOR = 'RSGEDI Tools'
EMAIL = 'RSGEDI Tools <*tools@rockstarnorth.com>'
OPTIONS = [
LongOption::new( 'input', LongOption::ArgType.Required, 'i',
'Specify input filename.' ),
LongOption::new( 'output', LongOption::ArgType.Required, 'o',
'Specify output filename.' ),
LongOption::new( 'recursive', LongOption::ArgType.None, 'r',
'Recurse through input data (for directories).' ),
LongOption::new( 'rebuild', LongOption::ArgType.None, 'f',
'Rebuild data; ignoring timestamp information.' ),
LongOption::new( 'preview', LongOption::ArgType.None, 'p',
'Preview data; output resources to preview folder.' ),
LongOption::new( 'proc', LongOption::ArgType.Required, 'c',
'Define processor to use; defaults to RAGE platform conversion.' ),
LongOption::new( 'no-sync', LongOption::ArgType.Required, 's',
'Disable engine Perforce dependency sync.' ),
LongOption::new( 'no-xge', LongOption::ArgType.None, 'x',
'Disable Xoreax XGE parallel processing engine.' ),
LongOption::new( 'no-content', LongOption::ArgType.None, 'y',
'Disable Content-Tree loading (required for most builds).' ),
LongOption::new( 'no-content-cache', LongOption::ArgType.None, 'z',
'Disable Content-Tree cache loading.' )
]
DEFAULT_PROCESSOR = 'RSG.Pipeline.Processor.Platform.Rage'
ULOG_VIEWER = '$(toolsbin)/UniversalLogViewer/UniversalLogViewer.exe'
ULOG_PATH = '$(toolsroot)/logs'
#-----------------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------------
# None
#-----------------------------------------------------------------------------
# Entry-Point
#-----------------------------------------------------------------------------
if ( __FILE__ == $0 ) then
# Initialise log and console output.
LogFactory.Initialize()
LogFactory.CreateApplicationConsoleLogTarget( )
g_Log = LogFactory.ApplicationLog
g_Options = OS::Options::new( OPTIONS )
begin
if ( g_Options.is_enabled?( 'help' ) )
puts "#{__FILE__}"
puts "Usage:"
puts g_Options.usage()
exit( 1 )
end
g_Config = g_Options.command_options.Config
g_Project = g_Options.command_options.Project
g_BranchName = g_Options.has_option?( 'branch' ) ? g_Options.get( 'branch' ) : g_Project.DefaultBranchName
g_Branch = g_Project.Branches[g_BranchName] if ( g_Project.Branches.ContainsKey( g_BranchName ) )
if ( g_Branch.nil? ) then
g_Log.Error( "Invalid branch '#{g_BranchName}' for project '#{g_Project.FriendlyName}'." )
exit( 1 )
end
# Engine initialisation.
g_EngineFlags = EngineFlags.Default
g_EngineFlags |= EngineFlags.Rebuild if ( g_Options.is_enabled?( 'rebuild' ) )
g_EngineFlags |= EngineFlags.Preview if ( g_Options.is_enabled?( 'preview' ) )
g_EngineFlags &= ~EngineFlags.SyncDependencies if ( g_Options.is_enabled?( 'no-sync' ) )
g_EngineFlags &= ~EngineFlags.XGE if ( g_Options.is_enabled?( 'no-xge' ) )
g_EngineFlags &= ~EngineFlags.LoadContent if ( g_Options.is_enabled?( 'no-content' ) )
g_EngineFlags &= ~EngineFlags.CacheContent if ( g_Options.is_enabled?( 'no-content-cache' ) )
g_EngineFlags &= ~EngineFlags.Popups unless ( g_Options.show_popups? )
g_Input = g_Options.get( 'input' )
g_Output = g_Options.get( 'output' )
g_Proc = g_Options.get( 'proc' )
g_Proc = DEFAULT_PROCESSOR if ( g_Proc.nil? )
if ( not (g_EngineFlags.HasFlag(EngineFlags.XGE)) ) then
g_Log.Warning( "Xoreax XGE parallel processing engine disabled." )
end
g_Log.Message( "Engine Flags from user options: #{g_EngineFlags}" )
g_Engine = nil
g_BuildTime = nil
g_Outputs = nil
# Set console title.
g_ConsoleTitle = System::Console.Title
System::Console.Title = "#{g_Project.FriendlyName}: Asset Build Pipeline, converting: #{g_Options.trailing.join(' ')}"
# If we have input and output arguments then that defines the process
# to execute; otherwise we fallback to the global convert system to
# load the content-tree from disk cache and execute the build.
if ( ( not g_Input.nil? ) and ( not g_Output.nil? ) )
g_Engine = Engine::new( g_Options.command_options, g_EngineFlags )
build_input = BuildInput::new( g_Branch )
tree = nil
if( not (g_EngineFlags.HasFlag(EngineFlags.LoadContent)))
#no-content flag has been passed in
tree = Factory::CreateEmptyTree(g_Branch)
else
tree = Factory::CreateTree(g_Branch, g_Engine.Processors)
end
input = tree.CreateFile( g_Input, false )
output = tree.CreateFile( g_Output, false )
pb = ProcessBuilder::new( g_Proc, g_Engine.Processors, tree )
pb.Inputs.Add( input )
pb.Outputs.Add( output )
process = pb.ToProcess( )
build_input.RawProcesses.Add( process )
g_Outputs = g_Engine.Build( build_input )
else
# If we're not explcitly set up for DLC; then we can override the project
# and branch we initialise the Engine with if the filenames passed in are
# DLC-related. This is set up here; and allows the convienience of
# right-click DLC asset builds.
g_Branches = []
g_Filenames = []
g_Options.trailing.each do |filename|
g_Filenames << System::IO::Path.GetFullPath( filename )
end
g_Filenames = g_Filenames.to_clr( System::String )
if ( not g_Project.IsDLC ) then
g_Config.DLCProjects.each do |kvp|
g_Filenames.each do |filename|
project = kvp.Value
project.Branches.each do |kvp2|
branch = kvp2.Value
if ( branch.IsRootedPath( branch.Export, filename ) or
branch.IsRootedPath( branch.Processed, filename ) ) then
g_Branches << branch
break
end
end
end
end
end
g_Branches = g_Branches.to_clr( RSG::Base::Configuration::IBranch ).Distinct( )
if ( 1 == g_Branches.Count() ) then
g_Branch = g_Branches.First()
g_Options.command_options.Project = g_Branch.Project
g_Options.command_options.Branch = g_Branch
g_Log.Message( "Switching project and branch context to: #{g_Branch.Project.FriendlyName} (#{g_Branch.Name})." )
elsif ( g_Branches.Count() > 1 ) then
g_Log.Error( "Multiple branch/project files detected. Aborting." )
exit( 1 )
else
# Leave our command options as they are.
end
g_Engine = Engine::new( g_Options.command_options, g_EngineFlags )
g_Outputs = g_Engine.Build( g_Filenames )
end
g_BuildTime = g_Outputs[2]
g_Log.Message( "Build Took: #{g_BuildTime}" )
exit( g_Outputs[0] ? 0 : 1 )
rescue SystemExit => ex
# Show Universal Log output on errors.
if ( g_Options.show_popups? and 0 != ex.status ) then
command = "#{g_Branch.Environment.Subst(ULOG_VIEWER)} #{LogFactory.ProcessLogDirectory}"
g_Log.Message( "Displaying Universal Logs: #{command}" )
system( command )
elsif ( g_Options.show_popups? ) then
## DHM; not sure this is neccessary?
## RSG::Pipeline::Services::MessageBox::Show( "Asset build completed successfully." )
end
LogFactory.ApplicationShutdown()
exit( ex.status )
rescue Exception => ex
g_Log.Exception( ex, "Exception during #{__FILE__}." )
puts "Exception during #{__FILE__}: #{ex.message}"
puts ex.backtrace.join("\n")
if ( g_Options.show_popups? ) then
dlg = RSG::Base::Windows::ExceptionStackTraceDlg::new( ex,
g_Config.EmailAddress, AUTHOR, EMAIL )
dlg.ShowDialog( )
end
exit( 1 )
end
end
# %RS_TOOLSLIB%/util/data_convert_file.rb