# # File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_map.rb # Description:: Map data converter definition. # # Author:: David Muir # Date:: 10 January 2010 # # Content convert specifics for map assets. This class should not be # used directly - use the ConvertSystem class instead. # #---------------------------------------------------------------------------- # Uses #---------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/content/content_core' require 'pipeline/content/content_maps' require 'pipeline/resourcing/converter' require 'pipeline/resourcing/converters/converter_map_assetcombine' require 'pipeline/resourcing/converters/converter_map_collision' require 'pipeline/resourcing/converters/converter_map_scenexml' require 'pipeline/util/incredibuild' #---------------------------------------------------------------------------- # Implementation #---------------------------------------------------------------------------- module Pipeline module Resourcing module Converters # # == Description # Map data root processor. # class MapConverter < ConverterBase include HasConverterChildren attr_reader :maps_output # Map child-converter output; Hash, by MapZip. def initialize( project, branch ) super( project, branch ) initialize_children( ) @maps = [] @file_list = {} # Add our child converters in the order they should be run. add_child_converter( MapConverterAssetCombine::new( project, branch ) ) add_child_converter( MapConverterCollision::new( project, branch ) ) add_child_converter( MapConverterSceneXml::new( project, branch ) ) end # Return whether this converter can convert the specified content node. def can_convert?( content ) ( content.is_a?( Content::ProcessedMapZip ) ) end # Converter prebuild step. def prebuild( ) end # Build the map processed zip(s). # # This runs build for each child converter; each child returns a Hash # optionally containing two keys, :output and :exclude. # # Files in the :output Array are included in the resultant zip; files # in the :exclude Array are in the source zip but not taken across. # Files listed in the :conversion Array are sent to the RageConverter # (this is a way of injecting new assets into the 2nd->3rd pipeline step). # def build( &block ) MapConverter::log().info( "Map converter building #{@maps.size} processed map zips." ) @maps_output = {} exclude_list = {} conversion_list = [] maps_result = true # Unpack map data. @maps.each do |map| prebuild_internal( map ) end # Push map through all of the child converters; this allows the # child converters to parallelise their processing. @children.each do |child| cres = child.build( @maps ) if ( cres.nil? ) then maps_result = false else cres.each_pair do |map, result| # Maps output has :exclude and :output keys @maps_output[map] = {} unless ( @maps_output.has_key?( map ) ) @maps_output[map].merge!( result ) do |k, v1, v2| [] + v1 + v2 end conversion_list += result[:conversion] if ( result.has_key?( :conversion ) ) end end end # Package up result after building up our data. maps_result = true @maps.each do |map| additional_outputs = @maps_output[map][:output] exclude_outputs = @maps_output[map][:exclude] maps_result &= postbuild_internal( map, additional_outputs, exclude_outputs ) end result = {} result[:conversion] = conversion_list result[:success] = maps_result result end # Clear the content from the build list. def clear( ) @maps.clear( ) @maps_output.clear( ) end # Add the content to the build list (if valid). def add_content( content ) if ( content.is_a?( Content::ProcessedMapZip ) ) then @maps << content @maps.uniq! true else MapConverter::log().error( "Could not convert: #{content}." ) false end end # Return raw map converter cache directory. def MapConverter::cache_dir_raw( branch ) c = ConvertSystem::instance( ) maps = OS::Path::combine( c.cache_root, 'maps' ) FileUtils::mkdir_p(maps) \ unless ( File::directory?( maps ) ) maps end # Return map converter cache directory. def MapConverter::cache_dir( branch, map ) throw ArgumentError::new( "Invalid Content::MapZip or Content::ProcessedMapZip object (#{map.class})." ) \ unless ( map.is_a?( Content::MapZip ) or map.is_a?( Content::ProcessedMapZip ) ) OS::Path::combine( MapConverter::cache_dir_raw( branch ), map.name ) end # Return MapConverter log object. def MapConverter::log() @@log = Log.new( 'convert_map' ) if ( @@log.nil? ) @@log end # Return whether we should use XGE for processing; we only utilise it # when its installed and there are more than one map section being processed. def MapConverter::use_xge( maps ) config = Pipeline::Config::instance() ( config.use_xge and Incredibuild::is_installed?() and ( maps.size() > 1 ) ) end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private @@log = nil # Prebuild step; extracts the input zip files as required. def prebuild_internal( map ) MapConverter::log().info( "Extracting processed map input files #{map.name}." ) @file_list[map] = [] cache_dir = MapConverter::cache_dir( @branch, map ) mapzip_files = map.inputs.collect do |mapzipinput| mapzipinput.filename end mapzip_files.each do |zip| if ( File::exists?( zip ) ) then @file_list[map] += ProjectUtil::data_zip_extract3( zip, cache_dir, true ) else MapConverter::log().error( "Dependency file does not exist: #{zip}." ) end end end # Postbuild step; repackages the output zip files as required picking # up the addition output and exclusion lists as required. def postbuild_internal( map, output_list, exclude_list ) throw ArgumentError::new( "Invalid additional file output list (#{output_list.class})." ) \ unless ( output_list.is_a?( Array ) ) throw ArgumentError::new( "Invalid exclude file list (#{exclude_list.class})." ) \ unless ( exclude_list.is_a?( Array ) ) MapConverter::log().info( "Repackaging processed map: #{map.filename}." ) MapConverter::log().info( "\tExcluding: #{exclude_list.join(',')}" ) cache_dir = MapConverter::cache_dir( @branch, map ) mapzip_files = map.inputs.collect do |mapzipinput| mapzipinput.filename end output_filename = map.filename output_dir = OS::Path::get_directory( output_filename ) FileUtils::mkdir_p( output_dir ) \ unless ( File::directory?( output_dir ) ) # Determine the actual file list to create the Zip from. actual_file_list = [] @file_list[map].each do |filename| assetname = OS::Path::get_filename( filename ) actual_file_list << filename unless ( exclude_list.include?( assetname ) ) end output_list.each do |filename| actual_file_list << filename end ProjectUtil::data_zip_create( output_filename, actual_file_list, true ) end end end # Converters module end # Resourcing module end # Pipeline module # %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_map.rb