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

358 lines
13 KiB
Ruby
Executable File

#
# File:: data_remove.rb
# Description:: Functions for removing unused data.
#
# Author:: Marissa Warner-Wu <marissa.warner-wu@rockstarnorth.com>
# Date:: 19 June 2009
#
#-----------------------------------------------------------------------------
# Uses
#-----------------------------------------------------------------------------
require 'pipeline/os/file'
require 'pipeline/util/rage_image'
require 'pipeline/projectutil/data_extract'
require 'pipeline/resourcing/path'
require 'pipeline/config/targets'
#-----------------------------------------------------------------------------
# Implementation
#-----------------------------------------------------------------------------
module Pipeline
module ProjectUtil
#-------------------------------------------------------------------------
# Functions
#-------------------------------------------------------------------------
#
# == Description
# A function which takes two image files and creates a new version of the
# first image without any items which overlap with the second image.
#
# If file is only in image1 - adds this file to new image
# If file is in both images - doesn't add
# i.e. image1 - image2 = resulting image
#
# Compares based on file name. Also appends some log information to an
# optional output file.
#
# === Example Usage
# The code below would print the name of the new image.
#
# ProjectUtil::data_cull_image( ep_branch.project, ep_branch, target, r, root_independent_filename, ep_independent_filename, output_dir, map_log ) do |new_filename|
# puts new_filename
# end
#
def ProjectUtil::data_cull_image(proj, branch, target, r, image1, image2, output_dir, output_file = "", &block)
# Start the builder
builder = Util::RagebuilderImage.new( proj, branch, branch.targets[target] )
# Open the output file and write the name of the file
log = nil
count = 0
unless output_file == ""
log = File.new(output_file, 'a')
log.write "#{image1}\n"
end
# Extract the contents of the two images ready for comparison.
image1_dest = OS::Path::combine( output_dir, 'image1' )
image2_dest = OS::Path::combine( output_dir, 'image2' )
image1_fullpath = []
image2_fullpath = []
image2_files = []
ProjectUtil::data_extract_image( r, image1, image1_dest ) do |extracted_filename|
image1_fullpath << extracted_filename
end
ProjectUtil::data_extract_image( r, image2, image2_dest ) do |extracted_filename|
image2_fullpath << extracted_filename
image2_files << OS::Path::get_filename( extracted_filename )
end
image_filename = OS::Path::combine( output_dir, OS::Path::get_trailing_directory( image1 ), OS::Path::get_filename( image1 ) )
builder.start
# Iterate over the file lists comparing filenames that match. Images
# have a flat directory structure so we don't need to worry about
# sub-directories. If the output file is specified then use this as well.
image1_fullpath.each do |image1_filename|
image1_file = OS::Path::get_filename( image1_filename )
unless ( image2_files.include?( OS::Path::get_filename( image1_file ) ) )
# Only add this file if it is not present in image2
builder.add( image1_filename )
next
end
#If we're not adding this to the image then log it
if log then
log.write "\t\t\t#{image1_file}\n"
count += 1
end
end #image1_fullpath.each
builder.save( image_filename )
builder.close
if log then
log.write "\tTOTAL: #{count}\n"
log.close
end
yield( image_filename ) if ( block_given? )
# Clean up extracted files
::FileUtils::rm_r( image1_dest ) if ( ::File::directory?( image1_dest ) )
::FileUtils::rm_r( image2_dest ) if ( ::File::directory?( image2_dest ) )
end #data_cull_image
#
# == Description
# A function which takes a cutsprops.img file from one project and
# compares it to cuts.img and cutsprops.img files from another project,
# removing the items not used in the cutscenes. Logs output to a file,
# cutsprops_compare_output.txt, in the output directory.
#
# Compares based on file name.
#
# === Example Usage
# The code below would print the name of the new image.
#
# ProjectUtil::data_cull_cutsprops( root_branch.project, root_branch, target, r, root_cutsprops, ep_cuts1, ep_cutsprops1, ep_cuts2, ep_cutsprops2, output_dir ) do |new_filename|
# puts new_filename
# end
#
def ProjectUtil::data_cull_cutsprops(proj, branch, target, r, cutsprops1, cuts1, cutsprops2, cuts2, cutsprops3, output_dir, &block)
puts "Output being written to cutsprops_compare_output.txt"
# Start the builder
builder = Util::RagebuilderImage.new( proj, branch, branch.targets[target] )
# Set up output file
log_filename = OS::Path::combine( output_dir, 'cutsprops_compare_output.txt' )
log = File.new( log_filename, 'w')
log.write("CUTSPROPS1: #{cutsprops1}\n")
log.write("CUTSPROPS2: #{cutsprops2}\n\n")
log.write("CUTSPROPS3: #{cutsprops3}\n\n")
# Keep track of cutscenes which have had duplicate files removed
duplicates = []
# Extract the contents of the two images for comparison and get lists of relevant files
cutsprops1_dest = OS::Path::combine( output_dir, 'cutsprops1' )
cutsprops2_dest = OS::Path::combine( output_dir, 'cutsprops2' )
cuts_dest = OS::Path::combine( output_dir, 'cuts' )
cuts_files = []
ProjectUtil::data_extract_image( r, cutsprops1, cutsprops1_dest )
ProjectUtil::data_extract_image( r, cutsprops2, cutsprops2_dest )
ProjectUtil::data_extract_image( r, cutsprops3, cutsprops2_dest, true )
ProjectUtil::data_extract_image( r, cuts1, cuts_dest )
ProjectUtil::data_extract_image( r, cuts2, cuts_dest )
cuts_files = OS::FindEx::find_files_recurse( OS::Path::combine( cuts_dest, '*.cut*' ) )
image_filename = OS::Path::combine( output_dir, 'cutsprops.img' )
builder.start( )
# Iterate over the .cut files and add required assets to image
used_assets = []
cuts_files.each do |cutscene|
log.write("Parsing cutscene: #{cutscene}\n")
text = []
assets = []
start = 0
finish = 0
# Parse for asset list
File.open(cutscene, 'r') do
text = IO.readlines( cutscene )
start = text.index( "[MODELS]\n" ) + 1
finish = text.index( "[/MODELS]\n" ) - 1
assets = text[start..finish]
end
# If this asset is used, add to the builder
assets.each do |line|
# Parse each line in the list for the item
item = ""
l = line.split[1]
if l then
item = l.downcase
log.write("\t\t\t#{item} - ")
else
log.write("\t\t\tNIL - ")
end
# Check to see if we should skip this item
if item == "" then
log.write("skipped because nil\n")
next
end
if item == "player" then
log.write("skipped because player\n")
next
end
if used_assets.include?( item ) then
log.write("skipped because already added\n")
next
end
cutsprops2_files = []
cutsprops2_files = OS::FindEx::find_files_recurse( OS::Path::combine( cutsprops2_dest, item + ".*" ) )
unless cutsprops2_files == [] then
log.write("skipped because in cutsprops2 or 3\n")
duplicates << cutscene
next
end
# Otherwise, find all the related files and add to the image
log.write("Searching for '" + OS::Path::combine( cutsprops1_dest, item + ".*" ) + "' " )
asset_files = OS::FindEx::find_files_recurse( OS::Path::combine( cutsprops1_dest, item + ".*" ) )
if asset_files == [] then
log.write("[[ERROR: no asset files found for this item]]\n")
next
end
used_assets << item
log.write("adding to image:\n")
asset_files.each do |file|
log.write("\t\t\t\t\t#{file}\n")
builder.add( file )
end
end #assets.each
end #cuts_files.each
if duplicates == [] then
log.write("==NO DUPLICATES FOUND\n")
else
log.write("==DUPLICATE FILES REMOVED FROM: #{duplicates}\n")
end
log.close
builder.save( image_filename )
builder.close( )
yield( image_filename ) if ( block_given? )
# Clean up extracted files
::FileUtils::rm_r( cutsprops1_dest ) if ( ::File::directory?( cutsprops1_dest ) )
::FileUtils::rm_r( cutsprops2_dest ) if ( ::File::directory?( cutsprops2_dest ) )
::FileUtils::rm_r( cuts_dest ) if ( ::File::directory?( cuts_dest ) )
end #data_cull_cutsprops
#
# == Description
# A function which replaces a given cuts image with a dummy file. The .cut
# files are replaced with empty files and the .iad files are replaced with a
# given template. The resulting image is passed to an optional given block.
#
# === Example Usage
# The code below would print the name of the new image.
#
# ProjectUtil::data_dummy_cuts( root_branch.project, root_branch, target, r, root_cuts, template_filename, output_dir ) do |new_filename|
# puts new_filename
# end
#
def ProjectUtil::data_dummy_cuts(proj, branch, target, r, image, template_file, output_dir, &block)
throw ArgumentError.new( "Invalid target object (#{target.class})." ) \
unless ( target.is_a?( Pipeline::Target ) )
throw ArgumentError.new( "Template file does not exist (#{template_file})." ) \
unless ( File.exist?(template_file) )
# Start the builder
builder = Util::RagebuilderImage.new( proj, branch, target )
# Read the template file
template = IO.read(template_file)
# Extract the contents of the image to a temporary folder
image_dest = OS::Path::combine( output_dir, 'dummy_cuts' )
image_fullpath = []
ProjectUtil::data_extract_image( r, image, image_dest ) do |extracted_filename|
image_fullpath << extracted_filename
end
new_image_filename = OS::Path::combine( output_dir, OS::Path::get_filename( image ) )
builder.start( )
# Iterate over the list of extracted files and replaces them
image_fullpath.each do |image_filename|
#target_filename = Resourcing::convert_independent_filename_to_platform( image_filename, target )
if OS::Path::get_extension( image_filename ) == "cut" then
f = File.new( image_filename, 'w' )
f.write( "[CUTSCENE_HEADER]\n1 1 1 1\n[/CUTSCENE_HEADER]\n" )
f.close
elsif OS::Path::get_extension( image_filename ) == "iad" then
f = File.new( image_filename, 'w' )
f.write( template )
f.close
else
puts "ERROR: #{image_filename} is not a .cut or a .iad file, skipping"
next
end
builder.add( image_filename )
end #image_fullpath.each
builder.save( new_image_filename )
builder.close( )
yield( new_image_filename ) if ( block_given? )
# Clean up extracted files
::FileUtils::rm_r( image_dest ) if ( ::File::directory?( image_dest ) )
end #data_dummy_cuts
#
# == Description
# A function which replaces a given image with a dummy image. All the
# files inside the image are extracted, replaced with dummies, and then
# repacked. The resulting image is passed to an optional given block.
#
# === Example Usage
# The code below would print the name of the new image.
#
# ProjectUtil::data_dummy_image( root_branch.project, root_branch, target, r, root_cuts, output_dir ) do |new_filename|
# puts new_filename
# end
#
def ProjectUtil::data_dummy_image(proj, branch, target, r, image, output_dir, &block)
throw ArgumentError.new( "Invalid target object (#{target.class})." ) \
unless ( target.is_a?( Pipeline::Target ) )
# Start the builder
builder = Util::RagebuilderImage.new( proj, branch, target )
# Extract the contents of the image to a temporary folder
image_dest = OS::Path::combine( output_dir, 'dummy_image' )
image_fullpath = []
ProjectUtil::data_extract_image( r, image, image_dest ) do |extracted_filename|
image_fullpath << extracted_filename
end
new_image_filename = OS::Path::combine( output_dir, OS::Path::get_filename( image ) )
builder.start( )
# Iterate over the list of extracted files and replaces with with empty target files
image_fullpath.each do |image_filename|
target_filename = Resourcing::convert_independent_filename_to_platform( image_filename, target )
puts target_filename
f = File.new( target_filename, 'w')
f.write('x')
builder.add( target_filename )
f.close
end #image_fullpath.each
builder.save( new_image_filename )
builder.close( )
yield( new_image_filename ) if ( block_given? )
# Clean up extracted files
::FileUtils::rm_r( image_dest ) if ( ::File::directory?( image_dest ) )
end #data_dummy_image
end # ProjectUtil module
end # Pipeline module
# data_remove.rb