Files
gtav-src/tools_ng/ironlib/util/data_mk_texture_dictionary.rb
2025-09-29 00:52:08 +02:00

224 lines
8.7 KiB
Ruby
Executable File

#
# 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 <david.muir@rockstarnorth.com>
# 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