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

707 lines
24 KiB
Ruby
Executable File

#
# File:: content_ped.rb
# Description:: Content system ped content tree node class implementation for a given ped.
#
# Author:: Luke Openshaw <luke.openshaw@rockstarnorth.com>
# Author:: David Muir <david.muir@rockstarnorth.com>
# 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 <ped_name> 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