# # # Author:: Mark Harrison-Ball # Date:: 15 September 2013 (AP3) # Purpose: # ~ Generic object to store Shot Info # path = File.expand_path $0 path = File.dirname(path) require 'pathname' require "#{path}/../../Global/cutscene/modelInfo" require "#{path}/../../Global/cutscene/eventInfo" PROP_TYPE = 'cutfPropModelObject' PED_TYPE = 'cutfPedModelObject' VEHICLE_TYPE = 'cutfVehicleModelObject' WEAPON_TYPE = 'cutfWeaponModelObject' HIDDENPROP_TYPE = 'cutfHiddenModelObject' BLOCKINGBOUNDS_TYPE = 'cutfBlockingBoundsObject' AUDIO_TYPE = 'cutfAudioObject' PARTICLE_TYPE = 'cutfParticleEffectObject' OVERLAY_TYPE = 'cutfOverlayObject' ANIMATEDPARTICLE = 'cutfAnimatedParticleEffectObject' SUBTITLE_TYPE = 'cutfSubtitleObject' LIGHT_TYPE = 'cutfLightObject' ANIMATEDLIGHT_TYPE = 'cutfAnimatedLightObject' EVENTOBJECTID_TYPE = 'cutfObjectIdEvent' class ShotInfo attr_reader :shotName attr_reader :relativePath attr_reader :shotPath attr_reader :duration attr_reader :frames attr_reader :flags attr_reader :iRangeStart attr_reader :iRangeEnd attr_reader :errorMsg attr_reader :models attr_reader :offset attr_reader :rotation attr_reader :pCutsceneEventList attr_writer :shotName attr_writer :shotPath attr_writer :duration attr_writer :frames attr_writer :flags attr_writer :iRangeStart attr_writer :iRangeEnd attr_writer :errorMsg attr_writer :models attr_writer :offset attr_writer :rotation def initialize() @shotName = nil @shotPath = nil @relativePath = nil @duration = 0 #fTotalDuration @frames = 0 @flags = 0 #iCutsceneFlags @iRangeStart = 0 @iRangeEnd = 0 @errorMsg = '' @models = [] #Hold a list of Model Objects @bBlockingBounds = false @offset = [0,0,0] @rotation = 0 @decalsList = [] @vfxList = [] @pCutsceneEventList = [] end def parse(metadataUtils, log=nil) if @shotPath != nil begin setRelativePath() # Relative Path (this is to support different different branches) readMetafile(metadataUtils) rescue => e puts e if log log.error(e) end @errorMsg = e.to_s.gsub("'"," ") end end end private def setRelativePath() safe_path = Pathname.new(File.expand_path(@shotPath)).to_s pathSplit = safe_path.split('/') sceneIndex = pathSplit.index("cuts") filePath = '' (sceneIndex..pathSplit.length-1).each do |n| filePath+='/'+pathSplit[n] end @relativePath = filePath end # Read our Shot Info def readMetafile(metadataUtils) #BASIC DATA shotDef = metadataUtils.ParseMetaFile( @shotPath ) @duration = metadataUtils.FindFirstStructureNamed( shotDef, "fTotalDuration" ).value.to_f @iRangeStart = metadataUtils.FindFirstStructureNamed( shotDef, "iRangeStart" ).value.to_i @iRangeEnd = metadataUtils.FindFirstStructureNamed( shotDef, "iRangeEnd" ).value.to_i @frames = @iRangeEnd-@iRangeStart+1 # (@duration * 30).to_i @flags = metadataUtils.FindFirstStructureNamed(shotDef, "iCutsceneFlags")[0].value.to_i offset = metadataUtils.FindFirstStructureNamed(shotDef, "vOffset") @offset = [offset.x, offset.y, offset.z] @rotation = metadataUtils.FindFirstStructureNamed(shotDef, "fRotation").value.to_f #hasBlocking = metadataUtils.FindFirstStructureNamed(shotDef, "fRotation") # GET OUR MODEL OBJECTS readModels(metadataUtils, shotDef) # GET OUR SHOT EVENTS readEvents(metadataUtils, shotDef) end def readModels(metadataUtils, shotDef) cutscneObjs = metadataUtils.FindFirstStructureNamed( shotDef, "pCutsceneObjects" ) if cutscneObjs cutscneObjs.each do |object| if object.value.name == PED_TYPE modelInfo = ModelInfo.new( metadataUtils, object.value, PED_TYPE ) models.push(modelInfo) elsif object.value.name == VEHICLE_TYPE modelInfo = ModelInfo.new( metadataUtils, object.value, VEHICLE_TYPE ) models.push(modelInfo) elsif object.value.name == PROP_TYPE modelInfo = ModelInfo.new( metadataUtils, object.value, PROP_TYPE ) models.push(modelInfo) elsif object.value.name == WEAPON_TYPE modelInfo = ModelInfo.new( metadataUtils, object.value, WEAPON_TYPE ) models.push(modelInfo) #elsif object.value.name == HIDDENPROP_TYPE # modelInfo = ModelInfo.new( metadataUtils, object.value, HIDDENPROP_TYPE ) # models.push(modelInfo) #elsif object.value.name == BLOCKINGBOUNDS_TYPE # blockingInfo = BlockingInfo.new( metadataUtils, object.value, BLOCKINGBOUNDS_TYPE ) # models.push(blockingInfo) elsif object.value.name == AUDIO_TYPE #puts '/n##############################################/n' audioInfo = AudioInfo.new( metadataUtils, object.value, AUDIO_TYPE ) models.push(audioInfo) # DEBUG INFO #audioInfo.instance_variables.map do |var| # puts [var, audioInfo.instance_variable_get(var)].join(":") #end #puts '\n##############################################\n' end end end end def readEvents(metadataUtils, shotDef) cutsceneEventList = metadataUtils.FindFirstStructureNamed( shotDef, "pCutsceneEventList" ) if cutsceneEventList cutsceneEventList.each do |object| if object.value.name == EVENTOBJECTID_TYPE eventInfo = CutfObjectIdEvent.new( metadataUtils, object.value ) @pCutsceneEventList.push(eventInfo) end end end end end