# # File:: content_ped.rb # Description:: Content system ped content tree node class implementation for a given ped. # # Author:: Luke Openshaw # Author:: David Muir # Date:: 5 August 2008 # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'pipeline/content/content_core' require 'rexml/document' include REXML module Pipeline module Content # # == Description # Base class for all ped content nodes. # class PedComponent < Group attr_reader :p attr_reader :ped_name attr_reader :geo_list attr_reader :tex_list attr_reader :stream_src attr_reader :hasBlendshapes attr_reader :blend_list attr_reader :createFragment attr_reader :streamed # # # def initialize( srcfile, project, ped_name, stream_src, hasBlendshapes, createFragment, streamed = false ) super(ped_name) @p = project @ped_name = ped_name @geo_list = [] @tex_list = [] @frag_list = [] @stream_src = stream_src @hasBlendshapes = hasBlendshapes @blend_list = [] @createFragment = createFragment @streamed = streamed # Only used by props currently @stream_path = OS::Path::combine( @stream_src, @ped_name ) @ped_zip_dir = OS::Path::combine( @p.export, 'models', 'cdimages' ) @cutsped_zip_dir = OS::Path::combine( @p.export, 'levels', @p.name, 'generic' ) if ::File.exist?(srcfile) then ::File.open( srcfile ) do |sourcefile| sourcedoc = Document.new( sourcefile ) populate_lists( sourcedoc ) end else @@log.error("Could not open #{srcfile}. It doesn't exist on disk") end end # # # def populate_lists( sourcedoc ) sourcedoc.root.each_element do | elem | case elem.name when 'geo' elem.each_element do | geo_elem | @geo_list << geo_elem.name end when 'txd' elem.each_element do | txd_elem | @tex_list << txd_elem.name end when 'frag' elem.each_element do |frag_elem| @frag_list << frag_elem.name end when 'blend' elem.each_element do | blend_elem | @blend_list << blend_elem.name end end end end # # # def build() build_geo() build_cloth() if ( @streamed ) then build_txds() else build_txd() end build_blendshapes() if @hasBlendshapes == true #build_blendshape_dictionary() if @hasBlendshapes == true end # # # def build_geo() if ( @streamed ) then @geo_list.each do | geo | pack_content = Zip::new( geo, @stream_path, "idd.zip", @p.ind_target, false ) # Drawable Information. has_packed_textures = false geo_geo_dir = OS::Path::combine( @stream_path, geo ) file_list = OS::FindEx.find_files( OS::Path::combine( geo_geo_dir, '*.*' ), false ) file_list.each do |file| next unless ::File::exists?( file ) # We now create drawable dictionaries for streamedpeds drawable_dict_group = Group.new( geo, geo ) drawable_dict_group.add_input( File::from_filename( file ) ) pack_content.add_input( drawable_dict_group ) end # Pack all none-diffuse textures and tcls in too texName = geo.slice(/[p|P]_[a-zA-Z]+_/) meshNum = geo.slice(/_[0-9]+/) texFiles = OS::FindEx.find_files(@stream_path + "/#{texName}*#{meshNum}*.dds", false) # Diffuse textures go in their own texture dictionary in build_txds() texFiles.delete_if { |f| f.include? "diff" } has_packed_textures = true if texFiles.count > 0 texFiles.each do | tex | texFilename = OS::Path::get_corebasename( tex ) drawable_dict_group = Group.new( geo, geo ) drawable_dict_group.add_input( File.new( texFilename, @stream_path, "dds" ) ) drawable_dict_group.add_input( File.new( texFilename, @stream_path, "tcl" ) ) \ if ::File::exists?( OS::Path.combine( @stream_path, texFilename + ".tcl" ) ) pack_content.add_input( drawable_dict_group ) end # Custom RBS scripts to include textures. if ( has_packed_textures ) then file_list = OS::FindEx.find_files( OS::Path::combine( @stream_path, '*.rbs' ), false ) file_list.each do |file| next unless ::File::exists?( file ) pack_content.add_input( File::from_filename( file ) ) end file_list = OS::FindEx.find_files( OS::Path::combine( @stream_path, geo, '*.textures' ), false ) file_list.each do |file| drawable_dict_group = Group.new( geo, geo ) drawable_dict_group.add_input( File::from_filename( file ) ) pack_content.add_input( drawable_dict_group ) end end add_child(pack_content) end else pack_content = Zip::new( @ped_name, @stream_src, "idd.zip", @p.ind_target, false ) @geo_list.each do | geo_name | geo_dir = OS::Path.combine( @stream_src, @ped_name, geo_name ) filelist = OS::FindEx.find_files(geo_dir + "/*.*", false) geo_group = Group.new( geo_name, geo_name ) filelist.each do | file | geo_group.add_input( File::from_filename( file ) ) \ if ::File.exist?( file ) end pack_content.add_input( geo_group ) end add_child(pack_content) end end # # Build cloth components. # def build_cloth() ild_dir = stream_src pack_cloth = Zip::new( @ped_name, ild_dir, "ild.zip", @p.ind_target, false ) @geo_list.each do | geo_name | geo_dir = OS::Path.combine( @stream_src, @ped_name, geo_name ) # find sub directories with cloth simulation meshes dir_list = OS::FindEx.find_dirs( geo_dir ) dir_list.each do |geo_cloth_dir| # Drawable Information. file_list = OS::FindEx.find_files( OS::Path::combine( geo_cloth_dir, '*.*' ), false ) file_list.each do |file| next unless ::File::exists?( file ) # We now create drawable dictionaries for streamedpeds drawable_dict_group = Group.new( geo_name, geo_name ) drawable_dict_group.add_input( File::from_filename( file ) ) pack_cloth.add_input( drawable_dict_group ) end puts pack_cloth end end add_child( pack_cloth ) if ( pack_cloth.inputs.size() > 0 ) end # # Build TXD components. # def build_txd() pack_content = Zip::new( @ped_name, @stream_src, "itd.zip", @p.ind_target, false ) tex_dir = OS::Path.combine( @stream_src, @ped_name ) filelist = OS::FindEx.find_files(tex_dir + "/*.tcl", false) filelist.each do | file | pack_content.add_input( File::from_filename( file ) ) \ if ::File.exist?( file ) end add_child(pack_content) end # # Build TXDs (If streamed) # def build_txds() # Uses geo_list as there are no txds in the character xml file @geo_list.each do | tex | tex_dir = @stream_path # Get the diffuse texture names to put in its own txd, taking off the prop name # There will probably be only one, but this is done rather than assuming _a will appear # after the mesh number diffTexName = tex.slice(/[p|P]_[a-zA-Z]+_/) + "diff" + tex.slice(/_[0-9]+/) diffFiles = OS::FindEx.find_files(tex_dir + "/#{diffTexName}*.tcl", false) diffFiles.each do | diffTex | diffFilename = OS::Path::get_corebasename( diffTex ) pack_content = Zip::new( diffFilename, tex_dir, "itd.zip", @p.ind_target, false ) pack_content.add_input( File.new( diffFilename, tex_dir, "tcl" ) ) \ if ::File::exists?( OS::Path.combine( tex_dir, diffFilename + ".tcl" ) ) add_child(pack_content) end end end # # Build fragment components. # def build_fragment() pack_content = Zip::new( @ped_name, @stream_src, "ift.zip", @p.ind_target, false ) frag_dir = OS::Path.combine( @stream_src, @ped_name ) file_list = OS::FindEx.find_files(frag_dir + "/*.*", false) frag_files = [] file_list.each do | file | frag_files << file if ( OS::Path.get_extension( file ) != "dds" and OS::Path.get_extension( file ) != "tcl" ) end frag_files.each do | frag_file | pack_content.add_input( File::from_filename( frag_file ) ) \ if ::File.exist?( frag_file ) end add_child(pack_content) end # # Build blendshapes # def build_blendshapes() pack_content = Zip::new( @ped_name, @stream_src, "ibs.zip", @p.ind_target, false ) @blend_list.each do | blend | blend_dir = OS::Path.combine( @stream_src, @ped_name, blend ) file_list = OS::FindEx.find_files(blend_dir + "/*.*", false) file_list.each do | file | pack_content.add_input( File::from_filename( file ) ) \ if ::File.exist?( file ) end end add_child(pack_content) end def build_blendshape_dictionary() pack_content = Zip::new( @ped_name, @stream_src, "isd.zip", @p.ind_target, false ) @blend_list.each do | blend | blend_dir = OS::Path.combine( @stream_src, @ped_name, blend ) filelist = OS::FindEx.find_files(blend_dir + "/*.*", false) blend_group = Group.new( blend, blend ) filelist.each do | file | blend_group.add_child( File::from_filename( file ) ) \ if ::File.exist?( file ) end pack_content.add_input( blend_group ) end add_child(pack_content) end # # Build individual ped zip # def build_zip() component_ped_zip = OS::Path::combine(@ped_zip_dir, 'componentpeds', "#{@ped_name}.ped.zip" ) files = [] file_list = OS::FindEx.find_files(@stream_src + "/#{@ped_name}*.zip", false) # Adds the fragment and meta files file_list.each do |ped_file| entry = {} entry[:src] = ped_file entry[:dst] = OS::Path::get_filename(ped_file) files << entry end ProjectUtil::data_zip_create( component_ped_zip, files ) end end # # == Description # Player ped component content node. # class PedPlayer < PedComponent # Class constructor. # +srcfile+ : player.xml file in users export stream. # +project+ : Pipeline::Project object # +ped_name+ : name of ped (i.e. 'player') def initialize( srcfile, project, ped_name, hasBlendShapes, createFragment, exportFolder = "streamedpeds" ) super( srcfile, project, ped_name, OS::Path::combine( project.netstream, exportFolder ), hasBlendShapes, createFragment) @blend_list = [] @stream_player = OS::Path::combine( @stream_src, @ped_name ) puts "SRCFILE: #{srcfile}" puts "STREAM: #{@stream_src}" puts "PLAYER: #{@stream_player}" end # # Build. # def build() build_txds() build_geo() build_cloth() if createFragment then build_fragment() build_frag_components() end #build_blendshapes() if @hasBlendshapes == true #build_blendshape_dictionary() if @hasBlendshapes == true end # # Return ContentGroup to build the correct content for previewing # this PedPlayer. # def preview_content( preview_directory ) project = Pipeline::Config::instance().project # Non-fragments go to a special directory. output_directory = OS::Path::combine( preview_directory, @ped_name ) content_group = Content::Group::new( "PedPlayer_#{@ped_name}_Preview" ) @children.each do |child| case child.extension when 'ift.zip' project.targets.each_value do |target| next unless ( target.enabled ) ext = Resourcing::convert_independent_extension_to_platform( child.filename, child.extension, target ) pack = Content::RPF::new( child.name, preview_directory, ext, target ) pack.add_input( child ) content_group.add_child( pack ) end else project.targets.each_value do |target| next unless ( target.enabled ) ext = Resourcing::convert_independent_extension_to_platform( child.filename, child.extension, target ) pack = Content::RPF::new( child.name, output_directory, ext, target ) pack.add_input( child ) content_group.add_child( pack ) end end end content_group end # # Build individual ped zip # def build_zip() @ped_name.downcase! streamed_ped_zip = OS::Path::combine(@ped_zip_dir, 'streamedpeds', "#{@ped_name}.ped.zip" ) files = [] # Gets the fragment file_list = OS::FindEx.find_files(@stream_src + "/#{@ped_name}*.zip", false) # Picks up all the zip files and rbs files for streamed ped file_list += OS::FindEx.find_files(@stream_src + "/#{@ped_name}/*.*", false) file_list.each do |ped_file| entry = {} entry[:src] = ped_file if @ped_name.eql?(OS::Path::get_trailing_directory(ped_file).downcase) then entry[:dst] = OS::Path::combine( @ped_name , OS::Path::get_filename(ped_file) ) else entry[:dst] = OS::Path::get_filename(ped_file) end files << entry end ProjectUtil::data_zip_create( streamed_ped_zip, files ) end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private # # Build TXD components. # def build_txds() @tex_list.each do | tex | pack_content = Zip::new( tex, @stream_player, "itd.zip", @p.ind_target, false ) tex_dir = OS::Path.combine( @stream_player, @ped_name ) pack_content.add_input( File.new( tex, tex_dir, "tcl" ) ) \ if ::File::exists?( OS::Path.combine( tex_dir, tex + ".tcl" ) ) add_child(pack_content) end end # # Build geometry components. # def build_geo() @geo_list.each do | geo | pack_content = Zip::new( geo, @stream_player, "idd.zip", @p.ind_target, false ) # Drawable Information. has_packed_textures = false geo_geo_dir = OS::Path::combine( @stream_player, geo ) file_list = OS::FindEx.find_files( OS::Path::combine( geo_geo_dir, '*.*' ), false ) file_list.each do |file| next unless ::File::exists?( file ) has_packed_textures = true if ( file.ends_with( ".dds" ) ) # We now create drawable dictionaries for streamedpeds drawable_dict_group = Group.new( geo, geo ) drawable_dict_group.add_input( File::from_filename( file ) ) pack_content.add_input( drawable_dict_group ) end # Custom RBS scripts to include textures. if ( has_packed_textures ) then file_list = OS::FindEx.find_files( OS::Path::combine( @stream_player, '*.rbs' ), false ) file_list.each do |file| next unless ::File::exists?( file ) pack_content.add_input( File::from_filename( file ) ) end end add_child(pack_content) end end # # Build cloth components. # def build_cloth() # override: the cloth ild goes into the peds folder, not in the stream # hence contains only one geom per ild ild_dir = OS::Path.combine( @stream_src, @ped_name ) @geo_list.each do | geo_name | # override: the cloth ild name must match geom, not ped pack_cloth = Zip::new( geo_name, ild_dir, "ild.zip", @p.ind_target, false ) geo_dir = OS::Path.combine( @stream_src, @ped_name, geo_name ) # find sub directories with cloth simulation meshes dir_list = OS::FindEx.find_dirs( geo_dir ) dir_list.each do |geo_cloth_dir| # Drawable Information. file_list = OS::FindEx.find_files( OS::Path::combine( geo_cloth_dir, '*.*' ), false ) file_list.each do |file| next unless ::File::exists?( file ) # We now create drawable dictionaries for streamedpeds drawable_dict_group = Group.new( geo_name, geo_name ) drawable_dict_group.add_input( File::from_filename( file ) ) pack_cloth.add_input( drawable_dict_group ) end puts pack_cloth end add_child(pack_cloth) if ( pack_cloth.inputs.size() > 0 ) end end # # Build fragment components. # def build_fragment() pack_content = Zip::new( @ped_name, @stream_src, "ift.zip", @p.ind_target, false ) frag_dir = OS::Path.combine( @stream_player, @ped_name ) file_list = OS::FindEx.find_files(frag_dir + "/*.*", false) frag_files = Array.new() file_list.each do | file | frag_files << file if ( OS::Path.get_extension( file ) != "dds" and OS::Path.get_extension( file ) != "tcl" ) end frag_files.each do | frag_file | pack_content.add_input( File::from_filename( frag_file ) ) \ if ::File.exist?( frag_file ) end add_child(pack_content) end # Build fragment components (/ped/frag/*) def build_frag_components() @frag_list.each do |frag| pack_content = Zip::new( frag, @stream_src, 'ift.zip', @p.ind_target, false ) frag_dir = OS::Path::combine( @stream_src, frag ) file_list = OS::FindEx::find_files( OS::Path::combine( frag_dir, '*.*' ), false ) file_list.each do |file| next unless ::File::exists?( file ) file_content = File::from_filename( file ) pack_content.add_input( file_content ) end add_child(pack_content) end end # # Build blendshape components. # def build_blendshapes() @blend_list.each do | blend | pack_content = Zip::new( @ped_name, @stream_player, "ibs.zip", @p.ind_target, false ) blend_dir = OS::Path.combine( @stream_src, blend ) file_list = OS::FindEx.find_files(blend_dir + "/*.*", false) file_list.each do | file | next unless ::File::exists?( file ) file_content = File::from_filename( file ) pack_content.add_input( file_content ) end add_child(pack_content) end end # # Build blendshape dictionary components. # def build_blendshape_dictionary() pack_content = Zip::new( @ped_name, @stream_src, "isd.zip", @p.ind_target, false ) @blend_list.each do | blend | blend_dir = OS::Path.combine( @stream_src, @ped_name, blend ) filelist = OS::FindEx.find_files(blend_dir + "/*.*", false) blend_group = Group.new( blend, blend ) filelist.each do | file | blend_group.add_child( File::from_filename( file ) ) \ if ::File.exist?( file ) end pack_content.add_input( blend_group ) end add_child(pack_content) end end # # == Description # class PedCutscene < PedPlayer # # # def initialize( srcfile, project, ped_name, hasBlendShapes, createFragment ) @blend_list = [] super( srcfile, project, ped_name, hasBlendShapes, createFragment, "cutspeds" ) end # # # def build() super() #TODO: This needs to be added as an option for cs characters #attr = pedXml.createattribute "setConfigOverride" #attr.value = "dirBin + /info.rbs/" #pedXmlRoot.Attributes.append(attr) # info.rbs contains # format "set_mipmapcount_max(1)\n" to:infoFile # format "set_mipmap_interleaving(0)\n" to:infoFile end # # Build individual ped zip # def build_zip() @ped_name.downcase! cutscene_ped_zip = OS::Path::combine(@cutsped_zip_dir, 'cutspeds', "#{@ped_name}.ped.zip" ) files = [] # Gets the fragment file_list = OS::FindEx.find_files(@stream_src + "/#{@ped_name}*.zip", false) # Picks up all the zip files and rbs files for streamed ped file_list += OS::FindEx.find_files(@stream_src + "/#{@ped_name}/*.*", false) file_list.each do |ped_file| entry = {} entry[:src] = ped_file if @ped_name.eql?(OS::Path::get_trailing_directory(ped_file).downcase) then entry[:dst] = OS::Path::combine( @ped_name , OS::Path::get_filename(ped_file) ) else entry[:dst] = OS::Path::get_filename(ped_file) end files << entry end ProjectUtil::data_zip_create( cutscene_ped_zip, files ) end end # # == Description # class PedOther < PedComponent # # # def initialize( srcfile, project, ped_name, hasBlendShapes, createFragment ) super( srcfile, project, ped_name, OS::Path::combine( project.netstream, "componentpeds" ), hasBlendShapes, createFragment ) end def build() super() if createFragment then build_fragment() end end end # # == Description # class PedProp < PedComponent XML_CONTENT_TYPE = 'pedprop' def initialize( srcfile, project, ped_name, streamed ) prop_path = if streamed then OS::Path::combine( project.netstream, "streamedpedprops" ) else OS::Path::combine( project.netstream, "pedprops" ) end # false for hasBlendShapes, true for createFragment (though not used for props!) super( srcfile, project, ped_name, prop_path, false, true, streamed ) end # # Empty TXDs are still desired for the ped txd hierarchy to work in game # So we create a TXD for ped props no matter if it has textures or not. # def build_txd() pack_content = Zip::new( @ped_name, @stream_src, "itd.zip", @p.ind_target, false ) tex_dir = OS::Path.combine( @stream_src, @ped_name ) file_list = OS::FindEx.find_files(tex_dir + "/*.tcl", false) zip_filename = OS::Path::combine( @stream_src, "#{@ped_name}.itd.zip" ) ProjectUtil::data_zip_create( zip_filename, file_list ) end end end # Content module end # Pipeline module