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

299 lines
14 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/pipeline/resourcing/converters/converter_map_scenexml.rb
# Description:: Map data merge converter.
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# 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