254 lines
11 KiB
Ruby
Executable File
254 lines
11 KiB
Ruby
Executable File
#
|
|
# File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_rage_manifest.rb
|
|
# Description:: Class to construct PackFileMetadata files.
|
|
#
|
|
# Author:: David Muir <david.muir@rockstarnorth.com>
|
|
# Date:: 26 May 2011
|
|
#
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Uses
|
|
#----------------------------------------------------------------------------
|
|
require 'rexml/document'
|
|
include REXML
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Implementation
|
|
#----------------------------------------------------------------------------
|
|
module Pipeline
|
|
module Resourcing
|
|
module Converters
|
|
|
|
#
|
|
# == Description
|
|
# The PackfileMetadata class represents the metadata file packed into
|
|
# the platform RPF files used to describe dependencies and other metainfo
|
|
# about the data in the RPF.
|
|
#
|
|
# In the future this may not be produced in Ruby script.
|
|
#
|
|
class PackfileMetadata
|
|
def initialize( )
|
|
@asset_bindings = []
|
|
@imap_group_properties = {}
|
|
@imap_group_property_types = {}
|
|
@imap_dependencies = {}
|
|
@imap_dependencies_2 = {}
|
|
@imap_dependencies_2_is_interior = []
|
|
@ityp_dependencies_2 = {}
|
|
@ityp_dependencies_2_is_interior = []
|
|
@interior_dependencies = {}
|
|
end
|
|
|
|
def has_data?()
|
|
result = ( @asset_bindings.count > 0 or
|
|
@imap_group_properties.count > 0 or
|
|
@imap_dependencies.size > 0 or
|
|
@imap_dependencies_2.size > 0 or
|
|
@ityp_dependencies_2.size > 0 or
|
|
@interior_dependencies.size > 0 )
|
|
result
|
|
end
|
|
|
|
def save( filename )
|
|
|
|
begin
|
|
FileUtils::mkdir_p( OS::Path::get_directory( filename ) )
|
|
File::open( filename, 'w' ) do |fp|
|
|
document = Document::new
|
|
document << XMLDecl::new
|
|
|
|
root_element = Element::new( 'CPackFileMetaData' )
|
|
if @asset_bindings.count > 0 then
|
|
bindings_array = root_element.add_element( 'HDTxdBindingArray' )
|
|
@asset_bindings.each do |binding|
|
|
binding_element = bindings_array.add_element( 'CHDTxdAssetBinding' )
|
|
|
|
type_element = binding_element.add_element( 'assetType' )
|
|
type_element.text = binding[:type]
|
|
|
|
target_element = binding_element.add_element( 'targetAsset' )
|
|
target_element.text = binding[:targetAsset]
|
|
|
|
dependency_element = binding_element.add_element( 'HDTxd' )
|
|
dependency_element.text = binding[:HDTxd]
|
|
end
|
|
end
|
|
if @imap_group_properties.count > 0 then
|
|
ipl_groups_element = root_element.add_element( 'MapDataGroups' )
|
|
@imap_group_properties.keys.each do |ipl_group_key|
|
|
|
|
# Create a new IMAP Group
|
|
ipl_group_item_element = ipl_groups_element.add_element( 'Item' )
|
|
ipl_group_item_name_element = ipl_group_item_element.add_element( 'Name' )
|
|
ipl_group_item_name_element.text = ipl_group_key
|
|
|
|
@imap_group_properties[ipl_group_key].each do |prop_key, prop_value|
|
|
# test for whether it's an array
|
|
property_element = ipl_group_item_element.add_element( prop_key )
|
|
case @imap_group_property_types[prop_key]
|
|
when RageConverter::ParcodegenNodeTypes::ArrayType then
|
|
prop_value.each do |propArrayItem|
|
|
property_array_element = property_element.add_element( 'Item' )
|
|
property_array_element.text = propArrayItem
|
|
end
|
|
when RageConverter::ParcodegenNodeTypes::TextType then
|
|
property_element.text = prop_value
|
|
when RageConverter::ParcodegenNodeTypes::AttributeType then
|
|
property_element.add_attribute("value", prop_value)
|
|
else
|
|
RageConverter::log().error( "Error during manifest data creation: property #{prop_key} has invalid type #{@imap_group_property_types[prop_key]}" )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
# Old IMAP dependency system; implemented for interiors initially.
|
|
if ( @imap_dependencies.size > 0 ) then
|
|
imap_dependency_element = root_element.add_element( 'imapDependencies' )
|
|
@imap_dependencies.each_pair do |imap_name, ityp_name|
|
|
imap_dependency = imap_dependency_element.add_element( 'Item' )
|
|
imap_name_elem = imap_dependency.add_element( 'imapName' )
|
|
imap_name_elem.text = imap_name
|
|
ityp_name_elem = imap_dependency.add_element( 'itypName' )
|
|
ityp_name_elem.text = ityp_name
|
|
end
|
|
end
|
|
# New IMAP dependency system; implemented for all ITYPs required
|
|
# by an IMAP.
|
|
if ( @imap_dependencies_2.size > 0 ) then
|
|
imap_dependency_element = root_element.add_element( 'imapDependencies_2' )
|
|
@imap_dependencies_2.each_pair do |imap_name, ityp_names|
|
|
imap_depends = imap_dependency_element.add_element( 'Item' )
|
|
imap_name_elem = imap_depends.add_element( 'imapName' )
|
|
imap_name_elem.text = imap_name
|
|
if( @imap_dependencies_2_is_interior.find_index( imap_name ) != nil ) then
|
|
manifest_flags_elem = imap_depends.add_element( 'manifestFlags' )
|
|
manifest_flags_elem.text = 'INTERIOR_DATA'
|
|
end
|
|
required_ityps = imap_depends.add_element( 'itypDepArray' )
|
|
ityp_names.each do |ityp_name|
|
|
ityp_name_elem = required_ityps.add_element( 'Item' )
|
|
ityp_name_elem.text = ityp_name
|
|
end
|
|
end
|
|
end
|
|
# ITYP dependency system.
|
|
if ( @ityp_dependencies_2.size > 0 ) then
|
|
ityp_dependency_element = root_element.add_element( 'itypDependencies_2' )
|
|
@ityp_dependencies_2.each_pair do |ityp_name, ityp_names|
|
|
ityp_depends = ityp_dependency_element.add_element( 'Item' )
|
|
ityp_depends_elem = ityp_depends.add_element( 'itypName' )
|
|
ityp_depends_elem.text = ityp_name
|
|
if( @ityp_dependencies_2_is_interior.find_index( ityp_name ) != nil ) then
|
|
manifest_flags_elem = ityp_depends.add_element( 'manifestFlags' )
|
|
manifest_flags_elem.text = 'INTERIOR_DATA'
|
|
end
|
|
required_ityps = ityp_depends.add_element( 'itypDepArray' )
|
|
ityp_names.each do |ityp_name|
|
|
ityp_name_elem = required_ityps.add_element( 'Item' )
|
|
ityp_name_elem.text = ityp_name
|
|
end
|
|
end
|
|
end
|
|
|
|
# Interior dependency system.
|
|
# B* 892520 - static interior bounds
|
|
if ( @interior_dependencies.size > 0 ) then
|
|
interiors_element = root_element.add_element( 'Interiors' )
|
|
@interior_dependencies.each_pair do |interior_name, bounds_names|
|
|
item_element = interiors_element.add_element( 'Item' )
|
|
name_element = item_element.add_element( 'Name' )
|
|
name_element.text = interior_name
|
|
bounds_element = item_element.add_element( 'Bounds' )
|
|
bounds_names.each do |bounds_name|
|
|
bounds_item_element = bounds_element.add_element( 'Item' )
|
|
bounds_item_element.text = bounds_name
|
|
end
|
|
end
|
|
end
|
|
|
|
document << root_element
|
|
|
|
fmt = REXML::Formatters::Pretty.new()
|
|
fmt.compact = true
|
|
fmt.write( document, fp )
|
|
end
|
|
rescue Exception => ex
|
|
RageConverter::log( ).exception( ex, "Error generating manifest." )
|
|
end
|
|
end
|
|
|
|
# Add a drawable asset binding.
|
|
def add_drawable_asset_binding( target, dependency )
|
|
@asset_bindings << {
|
|
:type => 'AT_DRB',
|
|
:targetAsset => OS::Path::get_basename( target ),
|
|
:HDTxd => OS::Path::get_basename( dependency )
|
|
}
|
|
end
|
|
|
|
# Add a fragment asset binding.
|
|
def add_fragment_asset_binding( target, dependency )
|
|
@asset_bindings << {
|
|
:type => 'AT_FRG',
|
|
:targetAsset => OS::Path::get_basename( target ),
|
|
:HDTxd => OS::Path::get_basename( dependency )
|
|
}
|
|
end
|
|
|
|
# Add a texture dictionary asset binding.
|
|
def add_texture_dictionary_asset_binding( target, dependency )
|
|
@asset_bindings << {
|
|
:type => 'AT_TXD',
|
|
:targetAsset => OS::Path::get_basename( target ),
|
|
:HDTxd => OS::Path::get_basename( dependency )
|
|
}
|
|
end
|
|
|
|
# Add a binding of IPL group name to bounds filenames.
|
|
def add_imap_group_property( imap_group_name, property_name, property_value, type )
|
|
if nil==@imap_group_properties[imap_group_name] then
|
|
@imap_group_properties[imap_group_name] = Hash.new()
|
|
end
|
|
@imap_group_properties[imap_group_name][property_name] = property_value
|
|
@imap_group_property_types[property_name] = type
|
|
end
|
|
|
|
# OLD: Add an Interior IMAP dependency.
|
|
def add_imap_dependency( imap_name, ityp_name )
|
|
@imap_dependencies[imap_name] = ityp_name
|
|
end
|
|
|
|
# Add an IMAP to multiple-ITYP dependencies.
|
|
def add_imap_dependencies( imap_name, ityp_names, is_interior )
|
|
throw ArgumentError::new( "Invalid ITYP names argument (#{ityp_names.class})." ) \
|
|
unless ( ityp_names.is_a?( Array ) )
|
|
|
|
@imap_dependencies_2[imap_name] = ityp_names
|
|
@imap_dependencies_2_is_interior << imap_name if( is_interior )
|
|
end
|
|
|
|
# Add an ITYP to multiple-ITYP dependencies.
|
|
def add_ityp_dependencies( ityp_name, ityp_names, is_interior )
|
|
throw ArgumentError::new( "Invalid ITYP names argument (#{ityp_names.class})." ) \
|
|
unless ( ityp_names.is_a?( Array ) )
|
|
|
|
@ityp_dependencies_2[ityp_name] = ityp_names
|
|
@ityp_dependencies_2_is_interior << ityp_name if( is_interior )
|
|
end
|
|
|
|
# Add an ITYP to multiple-ITYP dependencies.
|
|
def add_interior_dependencies( interior_name, bounds_items )
|
|
throw ArgumentError::new( "Invalid bounds_items argument (#{bounds_items.class})." ) \
|
|
unless ( bounds_items.is_a?( Array ) )
|
|
|
|
@interior_dependencies[interior_name] = bounds_items
|
|
end
|
|
end
|
|
|
|
end # Converters module
|
|
end # Resourcing module
|
|
end # Pipeline module
|
|
|
|
# %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_rage_manifest.rb
|