# # File:: %RS_TOOLSLIB%/util/data_mk_texture_dictionary.rb # Description:: Script to create a generic RAGE RPF file from a set of # files or directory contents. # # Author:: David Muir # Date:: 12 July 2011 (AP2) # Date:: 20 January 2013 (AP3) # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'RSG.Base.dll' require 'RSG.Base.Configuration.dll' require 'RSG.Base.Windows.dll' require 'RSG.Pipeline.Core.dll' require 'RSG.Pipeline.Services.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::Services 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( 'output', LongOption::ArgType.Required, 'o', 'Output texture dictionary filename (required).' ), LongOption::new( 'metadata', LongOption::ArgType.Required, 'm', 'Texture metadata directory (TCS output files, required).' ), LongOption::new( 'template', LongOption::ArgType.Required, 't', 'Metadata Template (TCP) to default to (required).' ), LongOption::new( 'filter', LongOption::ArgType.Required, 'f', 'Wildcard filter (default: *.dds).' ), LongOption::new( 'recursive', LongOption::ArgType.Required, 'r', 'Recursive directory search (default: false).' ), LongOption::new( 'regentcs', LongOption::ArgType.Required, 'z', 'Re-generate the TCS files again.' ), ] TRAILING_DESC = { 'files' => 'list of files/directories to include/search for files to include (can include wildcards, e.g. x:/assets/*.dds).' } DEFAULT_FILTER = '*.*' CL_DESCRIPTION = 'Automatic TCS creation for texture dictionary' #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- def show_help( options ) puts "#{__FILE__}" puts "Usage:" puts options.usage() end # Regenerate texture metadata method; re-creates TCL and TCS data. Returns an # array of TCL files that need packed into the texture dictionary. def GenerateTextureMetadata( options, textures, rebuild, metadata_directory, metadata_template ) tcl_files = [] tcl_directory = Path::Combine( options.command_options.Config.ToolsTemp, 'texture_metadata' ) begin p4 = options.command_options.Project.SCMConnect() System::IO::Directory::CreateDirectory( metadata_directory ) \ unless ( System::IO::Directory::Exists( metadata_directory ) ) System::IO::Directory::CreateDirectory( tcl_directory ) \ unless ( System::IO::Directory::Exists( tcl_directory ) ) # Loop through all our textures; creating a TCL and optionally creating a TCS. textures.each do |texture| texture_basename = Path::GetFileNameWithoutExtension( texture ) tcl_filename = Path::Combine( tcl_directory, texture_basename + '.tcl' ) tcs_filename = Path::Combine( metadata_directory, texture_basename + '.tcs' ) # Create TCS (if required, or forced). if ( rebuild or ( not ::File::exists?( tcs_filename ) ) ) then RSG::Pipeline::Services::Platform::Texture::SpecificationFactory::Create( tcs_filename, metadata_template, [].to_clr( System::String ), texture, false ) end # Create TCL. tcl_files << tcl_filename RSG::Pipeline::Services::Platform::Texture::SpecificationFactory::CreateLink( tcl_filename, tcs_filename ) end ensure p4.Disconnect() end tcl_files end #----------------------------------------------------------------------------- # Entry #----------------------------------------------------------------------------- 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' ) ) show_help( g_Options ) exit( 1 ) end g_Config = g_Options.command_options.Config g_Project = g_Options.command_options.Project g_Branch = g_Options.command_options.Branch # Get output texture directory filename. g_OutputFilename = g_Options.get( 'output' ) if ( g_OutputFilename.nil? ) then g_Log.Error( "No output filename specified." ) show_help( g_Options ) exit( 1 ) end # Get TCS metadata directory. g_MetadataDirectory = g_Options.get( 'metadata' ) if ( g_MetadataDirectory.nil? ) then g_Log.Error( "No metadata directory specified." ) show_help( g_Options ) exit( 1 ) end # Get TCP template. g_MetadataTemplate = g_Options.get( 'template' ) if ( g_MetadataTemplate.nil? ) then g_Log.Error( "No metadata template specified." ) show_help( g_Options ) exit( 1 ) end # Determine whether we're regenerating the TCS files. g_RecenerateTCS = g_Options.has_option?( 'regentcs' ) ? true : false # Determine wildcard filter. g_WildcardFilter = g_Options.has_option?( 'filter' ) ? g_Options.get( 'filter' ) : '*.dds' # Recursive option. g_RecursiveOption = g_Options.has_option?( 'recursive' ) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly # Process our trailing arguments to get a collection of files # that will get packed; adhering to our filter and recursive options. g_Paths = [].to_clr g_Options.trailing.each do |trailing| pathname = Path::GetFullPath( trailing ) # Expand relative paths. if ( System::IO::File::Exists( pathname ) ) then g_Paths << pathname # regular files elsif ( System::IO::Directory::Exists( pathname ) ) then path_files = Directory.GetFiles( pathname, g_WildcardFilter, g_RecursiveOption ) g_Paths += path_files end end # Verify input paths. g_Paths = g_Paths.to_clr( System::String ) if ( 0 == g_Paths.Length ) then g_Log.Error( "No input paths specified." ) show_help( g_Options ) exit( 1 ) end # Verify output path is writable. if ( System::IO::File::Exists( g_OutputFilename ) and ( not ::File::writable?( g_OutputFilename ) ) ) then g_Log.Error( "Output file: #{g_OutputFilename} is not writable. Aborting." ) exit( 1 ) end # Ensure our TCL and TCS files exist; TCL files are always generated # and packed into the dictionary. TCS files are created if they don't # exist. g_TclPaths = GenerateTextureMetadata( g_Options, g_Paths, g_RecenerateTCS, g_MetadataDirectory, g_MetadataTemplate ) g_Log.Message( "Creating: #{g_OutputFilename} from #{g_Paths.Length} textures." ) # Texture dictionaries are flat file zips of textures. There is no # herarchy information so we can just pack using the Zip pipeline service. System::IO::File::Delete( g_OutputFilename ) if ( File::exists?( g_OutputFilename ) ) if ( not Zip::Create( g_Branch, g_OutputFilename, (g_Paths + g_TclPaths).to_clr( System::String ) ) ) then g_Log.Error( "Failed to create output zip: #{g_OutputFilename}. File locked?" ) exit( 1 ) end rescue SystemExit => ex exit( ex.status ) rescue Exception => ex g_Log.Exception( ex, 'Unhandled exception' ) puts "\n#{__FILE__} unhandled exception: #{ex.message}" puts ex.backtrace.join("\n\t") exit( 1 ) end end # %RS_TOOLSLIB%/util/data_mk_generic_itd_zip.rb