# # File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_map_scenexml.rb # Description:: Map data merge converter. # # Author:: David Muir # Date:: 22 March 2011 # #---------------------------------------------------------------------------- # Uses #---------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/content/content_core' require 'pipeline/os/path' require 'pipeline/os/start' require 'pipeline/resourcing/converter' require 'pipeline/scm/perforce' require 'pipeline/util/incredibuild_xge' include Pipeline include Pipeline::Resourcing #---------------------------------------------------------------------------- # Implementation #---------------------------------------------------------------------------- module Pipeline module Resourcing module Converters # # == Description # Map SceneXml converter; inputs are the raw exported SceneXml files and # we output the ITYP/IMAP data which is then put into the processed map # zip file. # # This child converter does its work in the 'prebuild'; this means we # have the ITYP and IMAP files available for when the merge child # converter repacks up the processed zip. # class MapConverterSceneXml < ChildConverterBase def initialize( project, branch ) super( project, branch ) end # Use SceneXml content to generate map metadata. def build( maps, &block ) MapConverter::log().info( "MapConverterSceneXml::build()" ) @maps_output = {} # Sync dependent data from P4 Dir::chdir( @project.root ) do p4 = SCM::Perforce::new( ) begin p4.connect( ) sync_pathname = OS::Path::combine( @project.assets, 'maps/scene_overrides', '...' ) MapConverter::log().info( "Syncing Scene override data from #{sync_pathname}" ) p4.run_sync( sync_pathname ) rescue Exception => ex MapConverter::log().exception( ex, 'Scene override data sync exception.' ) ensure p4.disconnect( ) end end # Prepare each map ready for the serialisation. maps.each do |map| @maps_output[map] = {} @maps_output[map][:output] = [] @maps_output[map][:exclude] = [] cache_dir = MapConverter::cache_dir( @branch, map ) # Clear cache of old metafiles. This is require in case there are # fewer streamed IMAP files produced because of map data characteristics # or the split algorithm changes. meta_files = OS::FindEx::find_files( OS::Path::combine( cache_dir, '*.imap' ) ) meta_files += OS::FindEx::find_files( OS::Path::combine( cache_dir, '*.ityp' ) ) FileUtils::rm( meta_files ) if ( meta_files.size > 0 ) # Exclude meta files; these will be re-added later if serialiser # outputs them. meta_files.each do |meta_file| @maps_output[map][:exclude] << OS::Path::get_filename( meta_file ) end # Temporarily delete any IPL files. ipl_files = OS::FindEx::find_files( OS::Path::combine( cache_dir, '*.ipl' ) ) FileUtils::rm( ipl_files ) if ( ipl_files.size > 0 ) # Exclude these from the final output. ipl_files.each do |ipl_file| @maps_output[map][:exclude] << OS::Path::get_filename( ipl_file ) end # Temporarily delete any IPL files END. # Exclude the occlusion data; this needs to match the MapOcclusion # content node processing. @maps_output[map][:exclude] << "#{map.name}.occl.zip" @maps_output[map][:ityp] = OS::Path::combine( cache_dir, "#{map.name}.ityp" ) @maps_output[map][:imap] = OS::Path::combine( cache_dir, "#{map.name}.imap" ) # Re-generate the map metadata. @maps_output[map][:scenexml_files] = [] export_definitions = false export_instances = false map.inputs.each do |input| next unless ( input.children.size > 0 ) @maps_output[map][:instances] = true if ( map.exportinstances ) @maps_output[map][:definitions] = true if ( map.exportdefinitions ) input.children.each do |child| next unless ( child.is_a?( Content::MapSceneXml ) ) @maps_output[map][:scenexml_files] << child.filename end end end # Execute the serialiser. if ( MapConverter::use_xge( maps ) ) then build_xge( maps ) else build_local( maps ) end # Post-serialise; prepare file lists etc for packaging. maps.each do |map| process = ( ( @maps_output[map].has_key?( :scenexml_files ) ) and ( @maps_output[map][:scenexml_files].size > 0 ) ) MapConverter::log().error( "Map #{map.name} has no input SceneXml files." ) unless ( process ) @maps_output[map][:success] = false unless ( process ) next unless ( process ) cache_dir = MapConverter::cache_dir( @branch, map ) ityp_filenames = OS::FindEx::find_files( OS::Path::combine( cache_dir, '*.ityp' ) ) imap_filenames = OS::FindEx::find_files( OS::Path::combine( cache_dir, '*.imap' ) ) @maps_output[map][:output] += ityp_filenames if ( @maps_output[map][:definitions] ) @maps_output[map][:output] += imap_filenames if ( @maps_output[map][:instances] ) # Ensure we don't exclude newly created files. ityp_filenames.each do |ityp_file| @maps_output[map][:exclude].delete( OS::Path::get_filename( ityp_file ) ) end imap_filenames.each do |imap_file| @maps_output[map][:exclude].delete( OS::Path::get_filename( imap_file ) ) end end @maps_output end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private SERIALISER = '$(toolsbin)/MapExport/MapExportIDEIPL.exe' ARGS_DEFS_AND_INSTS = '--nopopups --build $(export) --iplstream $(stream) --ityp $(ityp) --imap $(imap) --unilog $(toolslog)/converter_map_scenexml_$(mapname).ulog' ARGS_DEFS_ONLY = '--nopopups --build $(export) --iplstream $(stream) --ityp $(ityp) --unilog $(toolslog)/converter_map_scenexml_$(mapname).ulog' ARGS_INSTS_ONLY = '--nopopups --build $(export) --iplstream $(stream) --imap $(imap) --unilog $(toolslog)/converter_map_scenexml_$(mapname).ulog' STATUS_SUCCESS = 0 XGE_TOOL_NAME = 'Map_Metadata_Serialiser' XGE_TOOL_CAPTION = 'Generating Map Metadata...' XGE_TOOL_MASK = '*.ityp,*.imap,*.xml' # Build using local processes only (if XGE isn't installed for example). def build_local( maps ) maps.each do |map| next unless ( @maps_output[map].has_key?( :scenexml_files ) ) next unless ( @maps_output[map][:scenexml_files].size > 0 ) @branch.in_env do |e| cache_dir = MapConverter::cache_dir( @branch, map ) has_asset_combine = ( @parent.maps_output.has_key?( map ) and ( @parent.maps_output[map].has_key?( :asset_combine ) ) ) MapConverter::log().info( "Asset Combine XML: #{@parent.maps_output[map][:asset_combine]}." ) e.add( 'ityp', @maps_output[map][:ityp] ) e.add( 'imap', @maps_output[map][:imap] ) e.add( 'stream', cache_dir ) e.add( 'mapname', map.name ) e.add( 'toolslog', OS::Path::combine( Globals::instance().toolsroot, 'logs' ) ) e.add( 'assetcombine', @parent.maps_output[map][:asset_combine] ) if ( has_asset_combine ) command = '' if ( @maps_output[map][:instances] and @maps_output[map][:definitions] ) then command = e.subst( "#{SERIALISER} #{ARGS_DEFS_AND_INSTS} " ) elsif ( @maps_output[map][:definitions] ) then command = e.subst( "#{SERIALISER} #{ARGS_DEFS_ONLY} " ) elsif ( @maps_output[map][:instances] ) then command = e.subst( "#{SERIALISER} #{ARGS_INSTS_ONLY} " ) else MapConverter::log().error( "Map has no definitions or instances?!" ) next end command += e.subst( ' --asset_combine $(assetcombine) ' ) if ( has_asset_combine ) command += @maps_output[map][:scenexml_files].join(' ') MapConverter::log().info( "Serialiser command: #{command}" ) status, out, err = OS::start( command ) case ( status.exitstatus.to_i ) when STATUS_SUCCESS MapConverter::log().info( "Map SceneXml processing succeeded." ) else MapConverter::log().error( "Map SceneXml processing failed (#{status.exitstatus})." ) end end end end # Build using XGE processes. def build_xge( maps ) MapConverter::log().info( "Creating XGE SceneXml packets." ) config = Pipeline::Config::instance() xge_folder = XGE::get_temp_dir( @project, @branch.name ) xge_packet_folder = OS::Path::combine( xge_folder, 'maps' ) filename = OS::Path::combine( xge_packet_folder, 'maps.xml' ) log_filename = OS::Path::combine( xge_packet_folder, 'maps.log' ) MapConverter::log().info( "Creating XGE SceneXml project and tasks." ) # Construct XGE Project xge_project = XGE::Project::new( "#{@project.uiname} #{@branch.name} Map Metadata Serialisation" ) xge_taskgroups = {} # Construct XGE Environment and Tools xge_env = XGE::Environment::new( 'Environment' ) xge_env.add_variable( 'BinVar', config.toolsbin ) xge_env.add_tool( get_xge_tool() ) # Create a single task group for all serialiser tasks. xge_taskgroup = XGE::TaskGroup::new( 'Map Metadata Serialisation', [], xge_env, xge_env.tools.first, '$(BinVar)' ) # Add Tasks for each map. maps.each do |map| next unless ( @maps_output[map].has_key?( :scenexml_files ) ) next unless ( @maps_output[map][:scenexml_files].size > 0 ) cache_dir = MapConverter::cache_dir( @branch, map ) has_asset_combine = ( @parent.maps_output.has_key?( map ) and ( @parent.maps_output[map].has_key?( :asset_combine ) ) ) MapConverter::log().info( "Asset Combine XML: #{@parent.maps_output[map][:asset_combine]}." ) task_name = "Map #{map.name}" task = XGE::Task::new( task_name, '' ) task.caption = task_name task.inherit_params = false @branch.in_env do |e| e.add( 'ityp', @maps_output[map][:ityp] ) e.add( 'imap', @maps_output[map][:imap] ) e.add( 'stream', cache_dir ) e.add( 'mapname', map.name ) e.add( 'toolslog', OS::Path::combine( Globals::instance().toolsroot, 'logs' ) ) e.add( 'assetcombine', @parent.maps_output[map][:asset_combine] ) if ( has_asset_combine ) if ( @maps_output[map][:instances] and @maps_output[map][:definitions] ) then task.parameters = e.subst( "#{ARGS_DEFS_AND_INSTS} " ) elsif ( @maps_output[map][:definitions] ) then task.parameters = e.subst( "#{ARGS_DEFS_ONLY} " ) elsif ( @maps_output[map][:instances] ) then task.parameters = e.subst( "#{ARGS_INSTS_ONLY} " ) end task.parameters += e.subst( ' --asset_combine $(assetcombine) ' ) if ( has_asset_combine ) task.parameters += @maps_output[map][:scenexml_files].join(' ') end xge_taskgroup.tasks << task end xge_project.add_task( xge_taskgroup ) xge_project.write( filename ) result = true MapConverter::log().info( "Starting XGE serialisation process." ) if ( not XGE::start( filename, log_filename ) ) then MapConverter::log().error( "Map metadata serialisation failed. Check Build Monitor for errors." ) result = false if ( not config.user.username.downcase.include?( User::ASSETBUILDER_USER) ) error_msg = "XGE Map Metadata Serialisation failed. Check Build Monitor or #{log_filename} for errors." GUI::MessageBox::error( "XGE Error Notification", error_msg ) end end result end # Return an XGE::Tool object for the map metadata serialiser command # line utility. def get_xge_tool( ) @branch.in_env do |env| path = env.subst( SERIALISER ) XGE::Tool::new( XGE_TOOL_NAME, XGE_TOOL_CAPTION, 'Serialising remotely...', XGE_TOOL_MASK, true, path, '', true ) end end end end # Converters module end # Resourcing module end # Pipeline module # %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_map_scenexml.rb