# # File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_rage_manifest.rb # Description:: Class to construct PackFileMetadata files. # # Author:: David Muir # 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