# # File:: %RS_TOOLSLIB%/pipeline/util/rage.rb # Description:: Rage gem and Rage project config XML interface. # # Author:: Greg Smith # Author:: David Muir # Date:: 22 February 2008 # # To avoid problems with incompatible Rage and XCompress libraries we are now # storing the gem version as well as the Ragebuilder executable configuration # in each project's config XML file. # # This means we cannot just require the Rage gem anymore, but must require a # particular version of it. # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'rexml/document' #----------------------------------------------------------------------------- # Implementation #----------------------------------------------------------------------------- module Pipeline # # == Description # The description of a command line to convert rage assets. This can parse # the project XML files to determine the correct versions of Ragebuilder # to use for a branch and platform combination. # class RageConvertTool class XMLParseError < Exception; end #--------------------------------------------------------------------- # Attributes #--------------------------------------------------------------------- attr_reader :name attr_reader :path attr_reader :gem_version attr_reader :split_packs attr_reader :options #--------------------------------------------------------------------- # Instance Methods #--------------------------------------------------------------------- def initialize( name, path, gem_version, split_packs, options ) @name = name @path = path @gem_version = gem_version @split_packs = split_packs @options = options end #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- # # Fill a hash with the tool used to convert to Rage for each platform # for a specific project and branch. If branch is not specified then # the project's default branch is used. # def RageConvertTool.parse( proj, branch = nil ) proj.load_config( ) branch = proj.default_branch if ( branch.nil? ) tools = {} File.open( proj.config ) do |file| doc = Document.new( file ) doc.elements.each( 'project/branches/branch' ) do |branch_elem| branch_name = branch_elem.attributes['name'] throw XMLParseError.new( 'XML Parse Error, no branch name specified. Fix project XML configuration.' ) \ if ( branch_name.nil? ) # Skip branches we ain't interested in. next unless ( branch_name == branch ) # Parse Rage Gem Version gem_version = branch_elem.elements['rage'].attributes['gem'] split_packs = ( 'false' == branch_elem.elements['rage'].attributes['split_packs'] ) ? false : true # Parse Rage XML branch_elem.elements.each( 'rage/ragebuilders/ragebuilder' ) do |target| platform = target.attributes['platform'] exe = target.attributes['exe'] options = " -options #{target.attributes['options']}" proj.in_env do |e| exe = e.subst( exe ) end tools[platform] = RageConvertTool.new( platform, exe, gem_version, split_packs, options ) end end end tools end end # # == Description # RageUtils class provides access into Ragebuilder functionality for # RPF/Pack, Image files and some misc. utilities. # class RageUtils #--------------------------------------------------------------------- # Attributes #--------------------------------------------------------------------- attr_reader :project # Project object attr_reader :branch # Branch object attr_reader :tools # RageConvertTool Hash (platform key) # Function Interfaces attr_reader :util # Utility functions attr_reader :rage # Low-level RAGE functions (e.g. hashing) #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- # Method that maps between our Ruby pipeline friendly platform key # names to Ragebuilder platform names. def RageUtils.rage_platform( platform ) rage_platform = platform case platform when 'xbox360' rage_platform = 'xenon' end rage_platform end #--------------------------------------------------------------------- # Instance Methods #--------------------------------------------------------------------- # Class constructor. def initialize( project, branch = nil ) @project = project @branch = branch.nil? ? branch : project.default_branch @tools = RageConvertTool::parse( @project, @branch ) first_key = tools.keys[0] throw RuntimeError.new( "No tools information or gem version for project branch." ) \ unless ( tools.is_a?( Hash ) ) unless ( @@gem_initialized ) then begin # Always use xenon gem. Saves large refactor to pass the # platform for every convert. This currently means all # platforms must share the same Rage gem. $rage_gem_version = tools[first_key].gem_version if ( ( not defined? $rage_gem_version ) or $rage_gem_version.nil? ) if ( $rage_gem_version != tools[first_key].gem_version ) throw RuntimeError.new( "Attempting to load different RAGE Gem versions in same script (#{$rage_gem_version}, #{tools[first_key].gem_version})." ) end gem 'rage', "= #{tools[first_key].gem_version}" require 'rage' LogSystem::instance().rootlog.info( "RAGE Gem version: #{$rage_gem_version}" ) rescue LoadError => ex throw RuntimeError.new( "Invalid Rage gem version: #{tools[first_key].gem_version}. Is it installed?" ) end end # Create our interfaces. @util = Rage::Util.instance( ) @rage = Rage::Rage::instance( ) # Initialise our RAGE Gem only once, as if we attempt to do it again # RAGE Param::Init assets and we fail badly. @util.init() unless ( @@gem_initialized ) @@gem_initialized = true unless ( @@gem_initialized ) end # Zip compatibility catch. def zip throw RuntimeError::new( "zip feature removed; script update required. Contact tools." ) end # RPF compatibility catch def pack throw RuntimeError::new( "pack feature removed; script update required. Contact tools." ) end # # Find files wrapper to take care of some housekeeping. This handles # the Ragebuilder function returning a single string with files # separated by ',' characters. # # Returns an Array of filename strings. # def find_files( search ) @util.find_files( search, true, true ).split( "," ) end # # Find dirs wrapper to take care of some housekeeping. This handles # the Ragebuilder function returning a single string with directories # separated by ',' characters. # # Returns an Array of directory strings. # def find_dirs( search ) @util.find_dirs( search ).split( "," ) end private # # Class (static) variable to store our initialised RAGE Gem state. # Initially false so we init the RAGE Gem once. # @@gem_initialized = false end end # Pipeline module # %RS_TOOLSLIB%/pipeline/util/rage.rb